-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add command for listing container images (#117)
This commit adds the `homadctl containers list` command that will return a list of all container images in use in the nomad cluster. Specifically it looks for jobs using the docker driver and grabs the image from their configuration. This is a precursor to creating a command to check for available image upgrades. Signed-off-by: David Bond <davidsbond93@gmail.com>
- Loading branch information
1 parent
c052423
commit 353ffd7
Showing
6 changed files
with
168 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package cmd | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/davidsbond/homad/apps/homadctl/internal/nomad" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// Containers is the root command for tasks that manage container images within the homelab. | ||
func Containers() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "containers", | ||
Aliases: []string{"container"}, | ||
Args: cobra.NoArgs, | ||
Short: "Subcommands for managing containers running in the homelab", | ||
} | ||
|
||
cmd.AddCommand( | ||
containersList(), | ||
) | ||
|
||
return cmd | ||
} | ||
|
||
func containersList() *cobra.Command { | ||
var jsonOut bool | ||
|
||
cmd := &cobra.Command{ | ||
Use: "list", | ||
Aliases: []string{"ls"}, | ||
Args: cobra.NoArgs, | ||
Short: "List all containers running in the homelab", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
client, err := nomad.NewClient() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
images, err := nomad.Images(cmd.Context(), client) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if jsonOut { | ||
return json.NewEncoder(os.Stdout).Encode(images) | ||
} | ||
|
||
for _, image := range images { | ||
fmt.Println(image) | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
flags := cmd.PersistentFlags() | ||
flags.BoolVar(&jsonOut, "json", false, "Output containers in JSON format") | ||
|
||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,22 @@ | ||
package cmd | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/davidsbond/homad/apps/homadctl/internal/nomad" | ||
"github.com/hashicorp/nomad/api" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// GC returns a cobra command that triggers all periodic jobs in the maintenance namespace that have a suffix of | ||
// "gc". This is how garbage-collection tasks are typically named. | ||
// GC returns a cobra command that triggers all periodic garbage collection jobs. | ||
func GC() *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "gc", | ||
Short: "Trigger all garbage collection jobs available", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
const namespace = "maintenance" | ||
|
||
client, err := nomad.NewClient() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
client.SetNamespace(namespace) | ||
jobs, _, err := client.Jobs().List(&api.QueryOptions{}) | ||
switch { | ||
case err != nil: | ||
return err | ||
case len(jobs) == 0: | ||
return nil | ||
} | ||
|
||
jobIDs := make([]string, 0) | ||
for _, job := range jobs { | ||
if !strings.HasSuffix(job.Name, "gc") { | ||
continue | ||
} | ||
|
||
jobIDs = append(jobIDs, job.ID) | ||
} | ||
|
||
if len(jobIDs) == 0 { | ||
return nil | ||
} | ||
|
||
for _, jobID := range jobIDs { | ||
_, _, err = client.Jobs().PeriodicForce(jobID, &api.WriteOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
return nomad.GarbageCollect(cmd.Context(), client) | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,103 @@ | ||
// Package nomad provides functions for interacting with a nomad cluster. | ||
package nomad | ||
|
||
import "github.com/hashicorp/nomad/api" | ||
import ( | ||
"context" | ||
"net/http" | ||
"strings" | ||
"time" | ||
|
||
"github.com/hashicorp/nomad/api" | ||
"golang.org/x/exp/maps" | ||
) | ||
|
||
// NewClient returns a new nomad client configured to perform calls to the homelab. | ||
func NewClient() (*api.Client, error) { | ||
return api.NewClient(&api.Config{ | ||
Address: "https://homelab.dsb.dev", | ||
Address: "https://homelab.dsb.dev", | ||
Namespace: api.AllNamespacesNamespace, | ||
HttpClient: &http.Client{ | ||
Timeout: time.Minute, | ||
}, | ||
}) | ||
} | ||
|
||
// GarbageCollect triggers all periodic jobs within the nomad cluster that are suffixed with "gc". This is the typical | ||
// pattern for custom garbage collection jobs. | ||
func GarbageCollect(ctx context.Context, client *api.Client) error { | ||
jobs, _, err := client.Jobs().List(&api.QueryOptions{Namespace: api.AllNamespacesNamespace}) | ||
switch { | ||
case err != nil: | ||
return err | ||
case len(jobs) == 0: | ||
return nil | ||
} | ||
|
||
for _, job := range jobs { | ||
if ctx.Err() != nil { | ||
return ctx.Err() | ||
} | ||
|
||
if !strings.HasSuffix(job.Name, "gc") { | ||
continue | ||
} | ||
|
||
_, _, err = client.Jobs().PeriodicForce(job.ID, &api.WriteOptions{Namespace: job.Namespace}) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Images returns a slice of all container image tags used by tasks within the nomad cluster. | ||
func Images(ctx context.Context, client *api.Client) ([]string, error) { | ||
images := make(map[string]struct{}) | ||
|
||
jobs, _, err := client.Jobs().List(&api.QueryOptions{Namespace: api.AllNamespacesNamespace}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, job := range jobs { | ||
if ctx.Err() != nil { | ||
return nil, ctx.Err() | ||
} | ||
|
||
info, _, err := client.Jobs().Info(job.ID, &api.QueryOptions{Namespace: job.Namespace}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, taskGroup := range info.TaskGroups { | ||
if ctx.Err() != nil { | ||
return nil, ctx.Err() | ||
} | ||
|
||
for _, task := range taskGroup.Tasks { | ||
if ctx.Err() != nil { | ||
return nil, ctx.Err() | ||
} | ||
|
||
if task.Driver != "docker" { | ||
continue | ||
} | ||
|
||
imageInterface, ok := task.Config["image"] | ||
if !ok { | ||
continue | ||
} | ||
|
||
image, ok := imageInterface.(string) | ||
if !ok { | ||
continue | ||
} | ||
|
||
images[image] = struct{}{} | ||
} | ||
} | ||
} | ||
|
||
return maps.Keys(images), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters