Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1084 from weaveworks/913-images-summary
Browse files Browse the repository at this point in the history
Add ListImages summary fields
  • Loading branch information
aaron7 authored May 21, 2018
2 parents 6689759 + 25d9aaf commit 883fcab
Show file tree
Hide file tree
Showing 27 changed files with 474 additions and 159 deletions.
23 changes: 18 additions & 5 deletions api/v6/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,19 @@ type ControllerStatus struct {
}

type Container struct {
Name string
Current image.Info
Available []image.Info
AvailableError string `json:",omitempty"`
Name string `json:",omitempty"`
Current image.Info `json:",omitempty"`
LatestFiltered image.Info `json:",omitempty"`

// All available images (ignoring tag filters)
Available []image.Info `json:",omitempty"`
AvailableError string `json:",omitempty"`
AvailableImagesCount int `json:",omitempty"`
NewAvailableImagesCount int `json:",omitempty"`

// Filtered available images (matching tag filters)
FilteredImagesCount int `json:",omitempty"`
NewFilteredImagesCount int `json:",omitempty"`
}

// --- config types
Expand All @@ -66,13 +75,17 @@ type Deprecated interface {
SyncNotify(context.Context) error
}

type ListImagesOptions struct {
OverrideContainerFields []string
}

type NotDeprecated interface {
// from v5
Export(context.Context) ([]byte, error)

// v6
ListServices(ctx context.Context, namespace string) ([]ControllerStatus, error)
ListImages(context.Context, update.ResourceSpec) ([]ImageStatus, error)
ListImages(ctx context.Context, spec update.ResourceSpec, opts ListImagesOptions) ([]ImageStatus, error)
UpdateManifests(context.Context, update.Spec) (job.ID, error)
SyncStatus(ctx context.Context, ref string) ([]string, error)
JobStatus(context.Context, job.ID) (job.Status, error)
Expand Down
2 changes: 1 addition & 1 deletion cmd/fluxctl/list_images_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (opts *controllerShowOpts) RunE(cmd *cobra.Command, args []string) error {

ctx := context.Background()

controllers, err := opts.API.ListImages(ctx, resourceSpec)
controllers, err := opts.API.ListImages(ctx, resourceSpec, v6.ListImagesOptions{})
if err != nil {
return err
}
Expand Down
136 changes: 106 additions & 30 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,35 +70,43 @@ func (d *Daemon) Export(ctx context.Context) ([]byte, error) {
return d.Cluster.Export()
}

func (d *Daemon) ListServices(ctx context.Context, namespace string) ([]v6.ControllerStatus, error) {
clusterServices, err := d.Cluster.AllControllers(namespace)
if err != nil {
return nil, errors.Wrap(err, "getting services from cluster")
}

func (d *Daemon) getPolicyResourceMap(ctx context.Context) (policy.ResourceMap, v6.ReadOnlyReason, error) {
var services policy.ResourceMap
var globalReadOnly v6.ReadOnlyReason
err = d.WithClone(ctx, func(checkout *git.Checkout) error {
err := d.WithClone(ctx, func(checkout *git.Checkout) error {
var err error
services, err = d.Manifests.ServicesWithPolicies(checkout.ManifestDir())
return err
})

// Capture errors related to read-only repositories
switch {
case err == git.ErrNotReady:
globalReadOnly = v6.ReadOnlyNotReady
case err == git.ErrNoConfig:
globalReadOnly = v6.ReadOnlyNoRepo
case err != nil:
return nil, errors.Wrap(err, "getting service policies")
return nil, globalReadOnly, errors.Wrap(err, "getting service policies")
}

return services, globalReadOnly, nil
}

func (d *Daemon) ListServices(ctx context.Context, namespace string) ([]v6.ControllerStatus, error) {
clusterServices, err := d.Cluster.AllControllers(namespace)
if err != nil {
return nil, errors.Wrap(err, "getting services from cluster")
}

policyResourceMap, readOnly, err := d.getPolicyResourceMap(ctx)
if err != nil {
return nil, err
}

var res []v6.ControllerStatus
for _, service := range clusterServices {
var readOnly v6.ReadOnlyReason
policies, ok := services[service.ID]
policies, ok := policyResourceMap[service.ID]
switch {
case globalReadOnly != "":
readOnly = globalReadOnly
case !ok:
readOnly = v6.ReadOnlyMissing
case service.IsSystem:
Expand Down Expand Up @@ -130,7 +138,7 @@ func (cs clusterContainers) Containers(i int) []resource.Container {
}

// List the images available for set of services
func (d *Daemon) ListImages(ctx context.Context, spec update.ResourceSpec) ([]v6.ImageStatus, error) {
func (d *Daemon) ListImages(ctx context.Context, spec update.ResourceSpec, opts v6.ListImagesOptions) ([]v6.ImageStatus, error) {
var services []cluster.Controller
var err error
if spec == update.ResourceSpecAll {
Expand All @@ -143,17 +151,25 @@ func (d *Daemon) ListImages(ctx context.Context, spec update.ResourceSpec) ([]v6
services, err = d.Cluster.SomeControllers([]flux.ResourceID{id})
}

images, err := update.CollectAvailableImages(d.Registry, clusterContainers(services), d.Logger)
imageRepos, err := update.FetchImageRepos(d.Registry, clusterContainers(services), d.Logger)
if err != nil {
return nil, errors.Wrap(err, "getting images for services")
}

policyResourceMap, _, err := d.getPolicyResourceMap(ctx)
if err != nil {
return nil, err
}

var res []v6.ImageStatus
for _, service := range services {
containers := containersWithAvailable(service, images)
serviceContainers, err := getServiceContainers(service, imageRepos, policyResourceMap, opts.OverrideContainerFields)
if err != nil {
return nil, err
}
res = append(res, v6.ImageStatus{
ID: service.ID,
Containers: containers,
Containers: serviceContainers,
})
}

Expand Down Expand Up @@ -544,23 +560,83 @@ func containers2containers(cs []resource.Container) []v6.Container {
return res
}

func containersWithAvailable(service cluster.Controller, images update.ImageMap) (res []v6.Container) {
func getServiceContainers(service cluster.Controller, imageRepos update.ImageRepos, policyResourceMap policy.ResourceMap, fields []string) (res []v6.Container, err error) {
if len(fields) == 0 {
fields = []string{
"Name",
"Current",
"LatestFiltered",
"Available",
"AvailableError",
"AvailableImagesCount",
"NewAvailableImagesCount",
"FilteredImagesCount",
"NewFilteredImagesCount",
}
}

for _, c := range service.ContainersOrNil() {
available := images.Available(c.Image.Name)
availableErr := ""
if available == nil {
availableErr = registry.ErrNoImageData.Error()
var container v6.Container

imageRepo := c.Image.Name
tagPattern := getTagPattern(policyResourceMap, service.ID, c.Name)

images := imageRepos.GetRepoImages(imageRepo)
currentImage := images.FindWithRef(c.Image)

// All images
imagesCount := len(images)
imagesErr := ""
if images == nil {
imagesErr = registry.ErrNoImageData.Error()
}
res = append(res, v6.Container{
Name: c.Name,
Current: image.Info{
ID: c.Image,
},
Available: available,
AvailableError: availableErr,
})
var newImages []image.Info
for _, img := range images {
if img.CreatedAt.After(currentImage.CreatedAt) {
newImages = append(newImages, img)
}
}
newImagesCount := len(newImages)

// Filtered images
filteredImages := images.Filter(tagPattern)
filteredImagesCount := len(filteredImages)
var newFilteredImages []image.Info
for _, img := range filteredImages {
if img.CreatedAt.After(currentImage.CreatedAt) {
newFilteredImages = append(newFilteredImages, img)
}
}
newFilteredImagesCount := len(newFilteredImages)

for _, field := range fields {
switch field {
case "Name":
container.Name = c.Name
case "Current":
container.Current = currentImage
case "LatestFiltered":
container.LatestFiltered, _ = filteredImages.Latest()
case "Available":
container.Available = images
case "AvailableError":
container.AvailableError = imagesErr
case "AvailableImagesCount":
container.AvailableImagesCount = imagesCount
case "NewAvailableImagesCount":
container.NewAvailableImagesCount = newImagesCount
case "FilteredImagesCount":
container.FilteredImagesCount = filteredImagesCount
case "NewFilteredImagesCount":
container.NewFilteredImagesCount = newFilteredImagesCount
default:
return nil, errors.Errorf("%s is an invalid field", field)
}
}
res = append(res, container)
}
return res

return res, nil
}

func policyCommitMessage(us policy.Updates, cause update.Cause) string {
Expand Down
Loading

0 comments on commit 883fcab

Please sign in to comment.