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

Create new ListImagesWithOptions method in v10 #1129

Merged
merged 2 commits into from
Jun 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions api/api.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package api

import (
"github.com/weaveworks/flux/api/v9"
)
import "github.com/weaveworks/flux/api/v10"

// Server defines the minimal interface a Flux must satisfy to adequately serve a
// connecting fluxctl. This interface specifically does not facilitate connecting
// to Weave Cloud.
type Server interface {
v9.Server
v10.Server
}

// UpstreamServer is the interface a Flux must satisfy in order to communicate with
// Weave Cloud.
type UpstreamServer interface {
v9.Server
v9.Upstream
v10.Server
v10.Upstream
}
25 changes: 25 additions & 0 deletions api/v10/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This package defines the types for Flux API version 10.
package v10

import (
"context"

"github.com/weaveworks/flux/api/v6"
"github.com/weaveworks/flux/api/v9"
"github.com/weaveworks/flux/update"
)

type ListImagesOptions struct {
Spec update.ResourceSpec
OverrideContainerFields []string
}

type Server interface {
v6.NotDeprecated

ListImagesWithOptions(ctx context.Context, opts ListImagesOptions) ([]v6.ImageStatus, error)
}

type Upstream interface {
v9.Upstream
}
23 changes: 1 addition & 22 deletions api/v6/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/weaveworks/flux"
"github.com/weaveworks/flux/git"
"github.com/weaveworks/flux/image"
"github.com/weaveworks/flux/job"
"github.com/weaveworks/flux/ssh"
"github.com/weaveworks/flux/update"
Expand Down Expand Up @@ -42,22 +41,6 @@ type ControllerStatus struct {
Policies map[string]string
}

type Container struct {
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

type GitRemoteConfig struct {
Expand All @@ -76,17 +59,13 @@ 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(ctx context.Context, spec update.ResourceSpec, opts ListImagesOptions) ([]ImageStatus, error)
ListImages(ctx context.Context, spec update.ResourceSpec) ([]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
115 changes: 115 additions & 0 deletions api/v6/container.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package v6

import (
"github.com/pkg/errors"
"github.com/weaveworks/flux/image"
"github.com/weaveworks/flux/registry"
"github.com/weaveworks/flux/update"
)

// Container describes an individual container including current image info and
// available images.
type Container struct {
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"`
}

// NewContainer creates a Container given a list of images and the current image
func NewContainer(name string, images update.ImageInfos, currentImage image.Info, tagPattern string, fields []string) (Container, error) {
// All images
imagesCount := len(images)
imagesErr := ""
if images == nil {
imagesErr = registry.ErrNoImageData.Error()
}
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)
latestFiltered, _ := filteredImages.Latest()

container := Container{
Name: name,
Current: currentImage,
LatestFiltered: latestFiltered,

Available: images,
AvailableError: imagesErr,
AvailableImagesCount: imagesCount,
NewAvailableImagesCount: newImagesCount,
FilteredImagesCount: filteredImagesCount,
NewFilteredImagesCount: newFilteredImagesCount,
}
return filterContainerFields(container, fields)
}

// filterContainerFields returns a new container with only the fields specified. If not fields are specified,
// a list of default fields is used.
func filterContainerFields(container Container, fields []string) (Container, error) {
// Default fields
if len(fields) == 0 {
fields = []string{
"Name",
"Current",
"LatestFiltered",
"Available",
"AvailableError",
"AvailableImagesCount",
"NewAvailableImagesCount",
"FilteredImagesCount",
"NewFilteredImagesCount",
}
}

var c Container
for _, field := range fields {
switch field {
case "Name":
c.Name = container.Name
case "Current":
c.Current = container.Current
case "LatestFiltered":
c.LatestFiltered = container.LatestFiltered
case "Available":
c.Available = container.Available
case "AvailableError":
c.AvailableError = container.AvailableError
case "AvailableImagesCount":
c.AvailableImagesCount = container.AvailableImagesCount
case "NewAvailableImagesCount":
c.NewAvailableImagesCount = container.NewAvailableImagesCount
case "FilteredImagesCount":
c.FilteredImagesCount = container.FilteredImagesCount
case "NewFilteredImagesCount":
c.NewFilteredImagesCount = container.NewFilteredImagesCount
default:
return c, errors.Errorf("%s is an invalid field", field)
}
}
return c, nil
}
130 changes: 130 additions & 0 deletions api/v6/container_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package v6

import (
"reflect"
"testing"

"github.com/weaveworks/flux/image"
"github.com/weaveworks/flux/update"
)

func TestNewContainer(t *testing.T) {

testImage := image.Info{ImageID: "test"}

type args struct {
name string
images update.ImageInfos
currentImage image.Info
tagPattern string
fields []string
}
tests := []struct {
name string
args args
want Container
wantErr bool
}{
{
name: "Simple",
args: args{
name: "container1",
images: update.ImageInfos{testImage},
currentImage: testImage,
tagPattern: "*",
},
want: Container{
Name: "container1",
Current: testImage,
LatestFiltered: testImage,
Available: []image.Info{testImage},
AvailableImagesCount: 1,
NewAvailableImagesCount: 0,
FilteredImagesCount: 1,
NewFilteredImagesCount: 0,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewContainer(tt.args.name, tt.args.images, tt.args.currentImage, tt.args.tagPattern, tt.args.fields)
if (err != nil) != tt.wantErr {
t.Errorf("NewContainer() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewContainer() = %v, want %v", got, tt.want)
}
})
}
}

func TestFilterContainerFields(t *testing.T) {
testContainer := Container{
Name: "test",
Current: image.Info{ImageID: "123"},
LatestFiltered: image.Info{ImageID: "123"},
Available: []image.Info{{ImageID: "123"}},
AvailableError: "test",
AvailableImagesCount: 1,
NewAvailableImagesCount: 2,
FilteredImagesCount: 3,
NewFilteredImagesCount: 4,
}

type args struct {
container Container
fields []string
}
tests := []struct {
name string
args args
want Container
wantErr bool
}{
{
name: "Default fields",
args: args{
container: testContainer,
},
want: testContainer,
wantErr: false,
},
{
name: "Filter",
args: args{
container: testContainer,
fields: []string{"Name", "Available", "NewAvailableImagesCount", "NewFilteredImagesCount"},
},
want: Container{
Name: "test",
Available: []image.Info{{ImageID: "123"}},
NewAvailableImagesCount: 2,
NewFilteredImagesCount: 4,
},
wantErr: false,
},
{
name: "Invalid field",
args: args{
container: testContainer,
fields: []string{"Invalid"},
},
want: Container{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := filterContainerFields(tt.args.container, tt.args.fields)
if (err != nil) != tt.wantErr {
t.Errorf("FilterContainerFields() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("FilterContainerFields() = %v, want %v", got, tt.want)
}
})
}
}
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, v6.ListImagesOptions{})
controllers, err := opts.API.ListImages(ctx, resourceSpec)
if err != nil {
return err
}
Expand Down
Loading