diff --git a/api/v11/api.go b/api/v11/api.go index 1e0034204..5b591b9a1 100644 --- a/api/v11/api.go +++ b/api/v11/api.go @@ -4,14 +4,14 @@ package v11 import ( "context" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/api/v10" "github.com/weaveworks/flux/api/v6" + "github.com/weaveworks/flux/resource" ) type ListServicesOptions struct { Namespace string - Services []flux.ResourceID + Services []resource.ID } type Server interface { diff --git a/api/v6/api.go b/api/v6/api.go index a95f2a4f3..4b8e341d5 100644 --- a/api/v6/api.go +++ b/api/v6/api.go @@ -3,16 +3,16 @@ package v6 import ( "context" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/git" "github.com/weaveworks/flux/job" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/ssh" "github.com/weaveworks/flux/update" ) type ImageStatus struct { - ID flux.ResourceID + ID resource.ID Containers []Container } @@ -31,13 +31,13 @@ const ( ) type ControllerStatus struct { - ID flux.ResourceID + ID resource.ID Containers []Container ReadOnly ReadOnlyReason Status string Rollout cluster.RolloutStatus SyncError string - Antecedent flux.ResourceID + Antecedent resource.ID Labels map[string]string Automated bool Locked bool diff --git a/cluster/cluster.go b/cluster/cluster.go index 5fedba272..e8d203a67 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -4,7 +4,6 @@ import ( "context" "errors" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/ssh" @@ -27,8 +26,8 @@ const ( type Cluster interface { // Get all of the services (optionally, from a specific namespace), excluding those AllWorkloads(ctx context.Context, maybeNamespace string) ([]Workload, error) - SomeWorkloads(ctx context.Context, ids []flux.ResourceID) ([]Workload, error) - IsAllowedResource(flux.ResourceID) bool + SomeWorkloads(ctx context.Context, ids []resource.ID) ([]Workload, error) + IsAllowedResource(resource.ID) bool Ping() error Export(ctx context.Context) ([]byte, error) Sync(SyncSet) error @@ -60,7 +59,7 @@ type RolloutStatus struct { // Workload describes a cluster resource that declares versioned images. type Workload struct { - ID flux.ResourceID + ID resource.ID Status string // A status summary for display // Is the controller considered read-only because it's under the // control of the platform. In the case of Kubernetes, we simply @@ -70,7 +69,7 @@ type Workload struct { // resource through some mechanism (like an operator, or custom // resource controller), we try to record the ID of that resource // in this field. - Antecedent flux.ResourceID + Antecedent resource.ID Labels map[string]string Policies policy.Set Rollout RolloutStatus diff --git a/cluster/kubernetes/images.go b/cluster/kubernetes/images.go index e4fdcc912..89196fe10 100644 --- a/cluster/kubernetes/images.go +++ b/cluster/kubernetes/images.go @@ -11,9 +11,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/registry" + "github.com/weaveworks/flux/resource" ) func mergeCredentials(log func(...interface{}) error, @@ -145,7 +145,7 @@ func (c *Cluster) ImagesToFetch() registry.ImageCreds { imageCreds := make(registry.ImageCreds) for _, workload := range workloads { - logger := log.With(c.logger, "resource", flux.MakeResourceID(ns.Name, kind, workload.GetName())) + logger := log.With(c.logger, "resource", resource.MakeID(ns.Name, kind, workload.GetName())) mergeCredentials(logger.Log, c.includeImage, c.client, ns.Name, workload.podTemplate, imageCreds, seenCreds) } diff --git a/cluster/kubernetes/kubernetes.go b/cluster/kubernetes/kubernetes.go index 188f6b0d2..6547f4b91 100644 --- a/cluster/kubernetes/kubernetes.go +++ b/cluster/kubernetes/kubernetes.go @@ -17,11 +17,11 @@ import ( k8sclientdynamic "k8s.io/client-go/dynamic" k8sclient "k8s.io/client-go/kubernetes" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" - "github.com/weaveworks/flux/cluster/kubernetes/resource" + kresource "github.com/weaveworks/flux/cluster/kubernetes/resource" fhrclient "github.com/weaveworks/flux/integrations/client/clientset/versioned" "github.com/weaveworks/flux/ssh" + "github.com/weaveworks/flux/resource" ) type coreClient k8sclient.Interface @@ -98,7 +98,7 @@ type Cluster struct { // syncErrors keeps a record of all per-resource errors during // the sync from Git repo to the cluster. - syncErrors map[flux.ResourceID]error + syncErrors map[resource.ID]error muSyncErrors sync.RWMutex allowedNamespaces []string @@ -128,7 +128,7 @@ func NewCluster(client ExtendedClient, applier Applier, sshKeyRing ssh.KeyRing, // SomeWorkloads returns the workloads named, missing out any that don't // exist in the cluster or aren't in an allowed namespace. // They do not necessarily have to be returned in the order requested. -func (c *Cluster) SomeWorkloads(ctx context.Context, ids []flux.ResourceID) (res []cluster.Workload, err error) { +func (c *Cluster) SomeWorkloads(ctx context.Context, ids []resource.ID) (res []cluster.Workload, err error) { var workloads []cluster.Workload for _, id := range ids { if !c.IsAllowedResource(id) { @@ -192,7 +192,7 @@ func (c *Cluster) AllWorkloads(ctx context.Context, namespace string) (res []clu for _, workload := range workloads { if !isAddon(workload) { - id := flux.MakeResourceID(ns.Name, kind, workload.GetName()) + id := resource.MakeID(ns.Name, kind, workload.GetName()) c.muSyncErrors.RLock() workload.syncError = c.syncErrors[id] c.muSyncErrors.RUnlock() @@ -208,7 +208,7 @@ func (c *Cluster) AllWorkloads(ctx context.Context, namespace string) (res []clu func (c *Cluster) setSyncErrors(errs cluster.SyncError) { c.muSyncErrors.Lock() defer c.muSyncErrors.Unlock() - c.syncErrors = make(map[flux.ResourceID]error) + c.syncErrors = make(map[resource.ID]error) for _, e := range errs { c.syncErrors[e.ResourceID] = e.Error } @@ -317,7 +317,7 @@ func (c *Cluster) getAllowedAndExistingNamespaces(ctx context.Context) ([]apiv1. return namespaces.Items, nil } -func (c *Cluster) IsAllowedResource(id flux.ResourceID) bool { +func (c *Cluster) IsAllowedResource(id resource.ID) bool { if len(c.allowedNamespaces) == 0 { // All resources are allowed when all namespaces are allowed return true @@ -326,7 +326,7 @@ func (c *Cluster) IsAllowedResource(id flux.ResourceID) bool { namespace, kind, name := id.Components() namespaceToCheck := namespace - if namespace == resource.ClusterScope { + if namespace == kresource.ClusterScope { // All cluster-scoped resources (not namespaced) are allowed ... if kind != "namespace" { return true diff --git a/cluster/kubernetes/manifests.go b/cluster/kubernetes/manifests.go index 0dcf28237..26abae33b 100644 --- a/cluster/kubernetes/manifests.go +++ b/cluster/kubernetes/manifests.go @@ -10,7 +10,6 @@ import ( "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apimachinery/pkg/runtime/schema" - "github.com/weaveworks/flux" kresource "github.com/weaveworks/flux/cluster/kubernetes/resource" "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/resource" @@ -133,7 +132,7 @@ func (m *manifests) ParseManifest(def []byte, source string) (map[string]resourc return result, nil } -func (m *manifests) SetWorkloadContainerImage(def []byte, id flux.ResourceID, container string, image image.Ref) ([]byte, error) { +func (m *manifests) SetWorkloadContainerImage(def []byte, id resource.ID, container string, image image.Ref) ([]byte, error) { return updateWorkload(def, id, container, image) } diff --git a/cluster/kubernetes/patch.go b/cluster/kubernetes/patch.go index 808f795f5..50307e665 100644 --- a/cluster/kubernetes/patch.go +++ b/cluster/kubernetes/patch.go @@ -15,17 +15,17 @@ import ( "k8s.io/apimachinery/pkg/util/strategicpatch" k8sscheme "k8s.io/client-go/kubernetes/scheme" - "github.com/weaveworks/flux" - "github.com/weaveworks/flux/cluster/kubernetes/resource" + kresource "github.com/weaveworks/flux/cluster/kubernetes/resource" + "github.com/weaveworks/flux/resource" ) func createManifestPatch(originalManifests, modifiedManifests []byte, originalSource, modifiedSource string) ([]byte, error) { - originalResources, err := resource.ParseMultidoc(originalManifests, originalSource) + originalResources, err := kresource.ParseMultidoc(originalManifests, originalSource) if err != nil { fmt.Errorf("cannot parse %s: %s", originalSource, err) } - modifiedResources, err := resource.ParseMultidoc(modifiedManifests, modifiedSource) + modifiedResources, err := kresource.ParseMultidoc(modifiedManifests, modifiedSource) if err != nil { fmt.Errorf("cannot parse %s: %s", modifiedSource, err) } @@ -61,12 +61,12 @@ func createManifestPatch(originalManifests, modifiedManifests []byte, originalSo } func applyManifestPatch(originalManifests, patchManifests []byte, originalSource, patchSource string) ([]byte, error) { - originalResources, err := resource.ParseMultidoc(originalManifests, originalSource) + originalResources, err := kresource.ParseMultidoc(originalManifests, originalSource) if err != nil { return nil, fmt.Errorf("cannot parse %s: %s", originalSource, err) } - patchResources, err := resource.ParseMultidoc(patchManifests, patchSource) + patchResources, err := kresource.ParseMultidoc(patchManifests, patchSource) if err != nil { return nil, fmt.Errorf("cannot parse %s: %s", patchSource, err) } @@ -120,7 +120,7 @@ func getFullScheme() *runtime.Scheme { return fullScheme } -func getPatch(originalManifest resource.KubeManifest, modifiedManifest resource.KubeManifest, scheme *runtime.Scheme) ([]byte, error) { +func getPatch(originalManifest kresource.KubeManifest, modifiedManifest kresource.KubeManifest, scheme *runtime.Scheme) ([]byte, error) { groupVersion, err := schema.ParseGroupVersion(originalManifest.GroupVersion()) if err != nil { return nil, fmt.Errorf("cannot parse groupVersion %q: %s", originalManifest.GroupVersion(), err) @@ -192,7 +192,7 @@ func addIdentifyingData(apiVersion string, kind string, name string, namespace s return obj, err } -func applyPatch(originalManifest, patchManifest resource.KubeManifest, scheme *runtime.Scheme) ([]byte, error) { +func applyPatch(originalManifest, patchManifest kresource.KubeManifest, scheme *runtime.Scheme) ([]byte, error) { groupVersion, err := schema.ParseGroupVersion(originalManifest.GroupVersion()) if err != nil { return nil, fmt.Errorf("cannot parse groupVersion %q: %s", originalManifest.GroupVersion(), err) @@ -227,8 +227,8 @@ func applyPatch(originalManifest, patchManifest resource.KubeManifest, scheme *r return patched, nil } -// resourceID works like Resource.ResourceID() but avoids namespaces, +// resourceID works like Resource.ID() but avoids namespaces, // since they may be incorrect -func resourceID(manifest resource.KubeManifest) flux.ResourceID { - return flux.MakeResourceID(manifest.GetNamespace(), manifest.GetKind(), manifest.GetKind()) +func resourceID(manifest kresource.KubeManifest) resource.ID { + return resource.MakeID(manifest.GetNamespace(), manifest.GetKind(), manifest.GetKind()) } diff --git a/cluster/kubernetes/policies.go b/cluster/kubernetes/policies.go index 0136ee072..5418035d2 100644 --- a/cluster/kubernetes/policies.go +++ b/cluster/kubernetes/policies.go @@ -5,13 +5,11 @@ import ( "github.com/pkg/errors" - "github.com/weaveworks/flux" kresource "github.com/weaveworks/flux/cluster/kubernetes/resource" - "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" ) -func (m *manifests) UpdateWorkloadPolicies(def []byte, id flux.ResourceID, update policy.Update) ([]byte, error) { +func (m *manifests) UpdateWorkloadPolicies(def []byte, id resource.ID, update resource.PolicyUpdate) ([]byte, error) { resources, err := m.ParseManifest(def, "stdin") if err != nil { return nil, err diff --git a/cluster/kubernetes/policies_test.go b/cluster/kubernetes/policies_test.go index 2438a21ec..edc33ebee 100644 --- a/cluster/kubernetes/policies_test.go +++ b/cluster/kubernetes/policies_test.go @@ -9,22 +9,22 @@ import ( "github.com/go-kit/kit/log" "github.com/stretchr/testify/assert" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/policy" + "github.com/weaveworks/flux/resource" ) func TestUpdatePolicies(t *testing.T) { for _, c := range []struct { name string in, out []string - update policy.Update + update resource.PolicyUpdate wantErr bool }{ { name: "adding annotation with others existing", in: []string{"prometheus.io.scrape", "'false'"}, out: []string{"prometheus.io.scrape", "'false'", "flux.weave.works/automated", "'true'"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.Automated: "true"}, }, }, @@ -32,7 +32,7 @@ func TestUpdatePolicies(t *testing.T) { name: "adding annotation when already has annotation", in: []string{"flux.weave.works/automated", "'true'"}, out: []string{"flux.weave.works/automated", "'true'"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.Automated: "true"}, }, }, @@ -40,7 +40,7 @@ func TestUpdatePolicies(t *testing.T) { name: "adding annotation when already has annotation and others", in: []string{"flux.weave.works/automated", "'true'", "prometheus.io.scrape", "'false'"}, out: []string{"flux.weave.works/automated", "'true'", "prometheus.io.scrape", "'false'"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.Automated: "true"}, }, }, @@ -48,7 +48,7 @@ func TestUpdatePolicies(t *testing.T) { name: "adding first annotation", in: nil, out: []string{"flux.weave.works/automated", "'true'"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.Automated: "true"}, }, }, @@ -56,7 +56,7 @@ func TestUpdatePolicies(t *testing.T) { name: "add and remove different annotations at the same time", in: []string{"flux.weave.works/automated", "'true'", "prometheus.io.scrape", "'false'"}, out: []string{"prometheus.io.scrape", "'false'", "flux.weave.works/locked", "'true'"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.Locked: "true"}, Remove: policy.Set{policy.Automated: "true"}, }, @@ -65,7 +65,7 @@ func TestUpdatePolicies(t *testing.T) { name: "remove overrides add for same key", in: nil, out: nil, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.Locked: "true"}, Remove: policy.Set{policy.Locked: "true"}, }, @@ -74,7 +74,7 @@ func TestUpdatePolicies(t *testing.T) { name: "remove annotation with others existing", in: []string{"flux.weave.works/automated", "true", "prometheus.io.scrape", "false"}, out: []string{"prometheus.io.scrape", "false"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Remove: policy.Set{policy.Automated: "true"}, }, }, @@ -82,7 +82,7 @@ func TestUpdatePolicies(t *testing.T) { name: "remove last annotation", in: []string{"flux.weave.works/automated", "true"}, out: nil, - update: policy.Update{ + update: resource.PolicyUpdate{ Remove: policy.Set{policy.Automated: "true"}, }, }, @@ -90,7 +90,7 @@ func TestUpdatePolicies(t *testing.T) { name: "remove annotation with no annotations", in: nil, out: nil, - update: policy.Update{ + update: resource.PolicyUpdate{ Remove: policy.Set{policy.Automated: "true"}, }, }, @@ -98,7 +98,7 @@ func TestUpdatePolicies(t *testing.T) { name: "remove annotation with only others", in: []string{"prometheus.io.scrape", "false"}, out: []string{"prometheus.io.scrape", "false"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Remove: policy.Set{policy.Automated: "true"}, }, }, @@ -106,7 +106,7 @@ func TestUpdatePolicies(t *testing.T) { name: "multiline", in: []string{"flux.weave.works/locked_msg", "|-\n first\n second"}, out: nil, - update: policy.Update{ + update: resource.PolicyUpdate{ Remove: policy.Set{policy.LockedMsg: "foo"}, }, }, @@ -114,7 +114,7 @@ func TestUpdatePolicies(t *testing.T) { name: "multiline with empty line", in: []string{"flux.weave.works/locked_msg", "|-\n first\n\n third"}, out: nil, - update: policy.Update{ + update: resource.PolicyUpdate{ Remove: policy.Set{policy.LockedMsg: "foo"}, }, }, @@ -122,7 +122,7 @@ func TestUpdatePolicies(t *testing.T) { name: "add tag policy", in: nil, out: []string{"flux.weave.works/tag.nginx", "glob:*"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("nginx"): "glob:*"}, }, }, @@ -130,7 +130,7 @@ func TestUpdatePolicies(t *testing.T) { name: "add non-glob tag policy", in: nil, out: []string{"flux.weave.works/tag.nginx", "foo"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("nginx"): "foo"}, }, }, @@ -138,7 +138,7 @@ func TestUpdatePolicies(t *testing.T) { name: "add semver tag policy", in: nil, out: []string{"flux.weave.works/tag.nginx", "semver:*"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("nginx"): "semver:*"}, }, }, @@ -146,7 +146,7 @@ func TestUpdatePolicies(t *testing.T) { name: "add invalid semver tag policy", in: nil, out: []string{"flux.weave.works/tag.nginx", "semver:*"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("nginx"): "semver:invalid"}, }, wantErr: true, @@ -155,7 +155,7 @@ func TestUpdatePolicies(t *testing.T) { name: "add regexp tag policy", in: nil, out: []string{"flux.weave.works/tag.nginx", "regexp:(.*?)"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("nginx"): "regexp:(.*?)"}, }, }, @@ -163,7 +163,7 @@ func TestUpdatePolicies(t *testing.T) { name: "add invalid regexp tag policy", in: nil, out: []string{"flux.weave.works/tag.nginx", "regexp:(.*?)"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("nginx"): "regexp:*"}, }, wantErr: true, @@ -172,7 +172,7 @@ func TestUpdatePolicies(t *testing.T) { name: "set tag to all containers", in: nil, out: []string{"flux.weave.works/tag.nginx", "semver:*"}, - update: policy.Update{ + update: resource.PolicyUpdate{ Add: policy.Set{policy.TagAll: "semver:*"}, }, }, @@ -180,7 +180,7 @@ func TestUpdatePolicies(t *testing.T) { t.Run(c.name, func(t *testing.T) { caseIn := templToString(t, annotationsTemplate, c.in) caseOut := templToString(t, annotationsTemplate, c.out) - resourceID := flux.MustParseResourceID("default:deployment/nginx") + resourceID := resource.MustParseID("default:deployment/nginx") manifests := NewManifests(ConstNamespacer("default"), log.NewLogfmtLogger(os.Stdout)) out, err := manifests.UpdateWorkloadPolicies([]byte(caseIn), resourceID, c.update) assert.Equal(t, c.wantErr, err != nil, "unexpected error value: %s", err) @@ -192,8 +192,8 @@ func TestUpdatePolicies(t *testing.T) { } func TestUpdatePolicies_invalidTagPattern(t *testing.T) { - resourceID := flux.MustParseResourceID("default:deployment/nginx") - update := policy.Update{ + resourceID := resource.MustParseID("default:deployment/nginx") + update := resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("nginx"): "semver:invalid"}, } _, err := (&manifests{}).UpdateWorkloadPolicies(nil, resourceID, update) diff --git a/cluster/kubernetes/resource/load_test.go b/cluster/kubernetes/resource/load_test.go index ffffbe79f..9d42dcdb3 100644 --- a/cluster/kubernetes/resource/load_test.go +++ b/cluster/kubernetes/resource/load_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/assert" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster/kubernetes/testfiles" "github.com/weaveworks/flux/resource" ) @@ -211,9 +210,9 @@ items: if len(list.Items) != 2 { t.Fatalf("expected two items, got %+v", list.Items) } - for i, id := range []flux.ResourceID{ - flux.MustParseResourceID("ns:deployment/foo"), - flux.MustParseResourceID("ns:service/bar")} { + for i, id := range []resource.ID{ + resource.MustParseID("ns:deployment/foo"), + resource.MustParseID("ns:service/bar")} { if list.Items[i].ResourceID() != id { t.Errorf("At %d, expected %q, got %q", i, id, list.Items[i].ResourceID()) } @@ -246,9 +245,9 @@ items: if len(list.Items) != 2 { t.Fatalf("expected two items, got %+v", list.Items) } - for i, id := range []flux.ResourceID{ - flux.MustParseResourceID("ns:deployment/foo"), - flux.MustParseResourceID("ns:deployment/bar")} { + for i, id := range []resource.ID{ + resource.MustParseID("ns:deployment/foo"), + resource.MustParseID("ns:deployment/bar")} { if list.Items[i].ResourceID() != id { t.Errorf("At %d, expected %q, got %q", i, id, list.Items[i].ResourceID()) } diff --git a/cluster/kubernetes/resource/resource.go b/cluster/kubernetes/resource/resource.go index 4599a9a1b..2a010dec7 100644 --- a/cluster/kubernetes/resource/resource.go +++ b/cluster/kubernetes/resource/resource.go @@ -3,9 +3,8 @@ package resource import ( "strings" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" - "github.com/weaveworks/flux" fluxerr "github.com/weaveworks/flux/errors" "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" @@ -65,12 +64,12 @@ func (o baseObject) GetName() string { return o.Meta.Name } -func (o baseObject) ResourceID() flux.ResourceID { +func (o baseObject) ResourceID() resource.ID { ns := o.Meta.Namespace if ns == "" { ns = ClusterScope } - return flux.MakeResourceID(ns, o.Kind, o.Meta.Name) + return resource.MakeID(ns, o.Kind, o.Meta.Name) } // SetNamespace implements KubeManifest.SetNamespace, so things with diff --git a/cluster/kubernetes/resourcekinds.go b/cluster/kubernetes/resourcekinds.go index a7416c64f..9905b7733 100644 --- a/cluster/kubernetes/resourcekinds.go +++ b/cluster/kubernetes/resourcekinds.go @@ -9,7 +9,6 @@ import ( apiv1 "k8s.io/api/core/v1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" kresource "github.com/weaveworks/flux/cluster/kubernetes/resource" "github.com/weaveworks/flux/image" @@ -24,7 +23,7 @@ import ( // FluxHelmRelease. We use this rather than the `OwnerReference` type // built into Kubernetes so that there are no garbage-collection // implications. The value is expected to be a serialised -// `flux.ResourceID`. +// `resource.ID`. const AntecedentAnnotation = "flux.weave.works/antecedent" ///////////////////////////////////////////////////////////////////////////// @@ -56,7 +55,7 @@ type workload struct { podTemplate apiv1.PodTemplateSpec } -func (w workload) toClusterWorkload(resourceID flux.ResourceID) cluster.Workload { +func (w workload) toClusterWorkload(resourceID resource.ID) cluster.Workload { var clusterContainers []resource.Container var excuse string for _, container := range w.podTemplate.Spec.Containers { @@ -78,9 +77,9 @@ func (w workload) toClusterWorkload(resourceID flux.ResourceID) cluster.Workload clusterContainers = append(clusterContainers, resource.Container{Name: container.Name, Image: ref}) } - var antecedent flux.ResourceID + var antecedent resource.ID if ante, ok := w.GetAnnotations()[AntecedentAnnotation]; ok { - id, err := flux.ParseResourceID(ante) + id, err := resource.ParseID(ante) if err == nil { antecedent = id } diff --git a/cluster/kubernetes/sync.go b/cluster/kubernetes/sync.go index 502de85fe..33a70e3f0 100644 --- a/cluster/kubernetes/sync.go +++ b/cluster/kubernetes/sync.go @@ -25,7 +25,6 @@ import ( "k8s.io/client-go/discovery" "k8s.io/client-go/rest" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" kresource "github.com/weaveworks/flux/cluster/kubernetes/resource" "github.com/weaveworks/flux/policy" @@ -169,14 +168,14 @@ type kuberesource struct { namespaced bool } -// ResourceID returns the ResourceID for this resource loaded from the +// ResourceID returns the ID for this resource loaded from the // cluster. -func (r *kuberesource) ResourceID() flux.ResourceID { +func (r *kuberesource) ResourceID() resource.ID { ns, kind, name := r.obj.GetNamespace(), r.obj.GetKind(), r.obj.GetName() if !r.namespaced { ns = kresource.ClusterScope } - return flux.MakeResourceID(ns, kind, name) + return resource.MakeID(ns, kind, name) } // Bytes returns a byte slice description, including enough info to @@ -368,7 +367,7 @@ func makeGCMark(syncSetName, resourceID string) string { // --- internal types for keeping track of syncing type applyObject struct { - ResourceID flux.ResourceID + ResourceID resource.ID Source string Payload []byte } @@ -381,13 +380,13 @@ func makeChangeSet() changeSet { return changeSet{objs: make(map[string][]applyObject)} } -func (c *changeSet) stage(cmd string, id flux.ResourceID, source string, bytes []byte) { +func (c *changeSet) stage(cmd string, id resource.ID, source string, bytes []byte) { c.objs[cmd] = append(c.objs[cmd], applyObject{id, source, bytes}) } // Applier is something that will apply a changeset to the cluster. type Applier interface { - apply(log.Logger, changeSet, map[flux.ResourceID]error) cluster.SyncError + apply(log.Logger, changeSet, map[resource.ID]error) cluster.SyncError } type Kubectl struct { @@ -472,7 +471,7 @@ func (objs applyOrder) Less(i, j int) bool { return ranki < rankj } -func (c *Kubectl) apply(logger log.Logger, cs changeSet, errored map[flux.ResourceID]error) (errs cluster.SyncError) { +func (c *Kubectl) apply(logger log.Logger, cs changeSet, errored map[resource.ID]error) (errs cluster.SyncError) { f := func(objs []applyObject, cmd string, args ...string) { if len(objs) == 0 { return diff --git a/cluster/kubernetes/sync_test.go b/cluster/kubernetes/sync_test.go index e83e297fd..349d019bc 100644 --- a/cluster/kubernetes/sync_test.go +++ b/cluster/kubernetes/sync_test.go @@ -9,26 +9,21 @@ import ( "github.com/ghodss/yaml" "github.com/go-kit/kit/log" + "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" + crdfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - // "k8s.io/apimachinery/pkg/runtime/serializer" - // "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/dynamic" - // dynamicfake "k8s.io/client-go/dynamic/fake" - // k8sclient "k8s.io/client-go/kubernetes" - "github.com/stretchr/testify/assert" - crdfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake" "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" dynamicfake "k8s.io/client-go/dynamic/fake" k8sclient "k8s.io/client-go/kubernetes" corefake "k8s.io/client-go/kubernetes/fake" k8s_testing "k8s.io/client-go/testing" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" kresource "github.com/weaveworks/flux/cluster/kubernetes/resource" fluxfake "github.com/weaveworks/flux/integrations/client/clientset/versioned/fake" @@ -116,7 +111,7 @@ func groupVersionResource(res *unstructured.Unstructured) schema.GroupVersionRes return schema.GroupVersionResource{Group: gvk.Group, Version: gvk.Version, Resource: strings.ToLower(gvk.Kind) + "s"} } -func (a fakeApplier) apply(_ log.Logger, cs changeSet, errored map[flux.ResourceID]error) cluster.SyncError { +func (a fakeApplier) apply(_ log.Logger, cs changeSet, errored map[resource.ID]error) cluster.SyncError { var errs []cluster.ResourceError operate := func(obj applyObject, cmd string) { @@ -730,9 +725,9 @@ spec: // TestApplyOrder checks that applyOrder works as expected. func TestApplyOrder(t *testing.T) { objs := []applyObject{ - {ResourceID: flux.MakeResourceID("test", "Deployment", "deploy")}, - {ResourceID: flux.MakeResourceID("test", "Secret", "secret")}, - {ResourceID: flux.MakeResourceID("", "Namespace", "namespace")}, + {ResourceID: resource.MakeID("test", "Deployment", "deploy")}, + {ResourceID: resource.MakeID("test", "Secret", "secret")}, + {ResourceID: resource.MakeID("", "Namespace", "namespace")}, } sort.Sort(applyOrder(objs)) for i, name := range []string{"namespace", "secret", "deploy"} { diff --git a/cluster/kubernetes/testfiles/data.go b/cluster/kubernetes/testfiles/data.go index b47ce105c..3504bd3f2 100644 --- a/cluster/kubernetes/testfiles/data.go +++ b/cluster/kubernetes/testfiles/data.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/resource" ) func TempDir(t *testing.T) (string, func()) { @@ -44,30 +44,30 @@ func WriteTestFiles(dir string) error { // ResourceMap is the map of resource names to relative paths, which // must correspond with `Files` below. -var ResourceMap = map[flux.ResourceID]string{ - flux.MustParseResourceID("default:deployment/helloworld"): "helloworld-deploy.yaml", - flux.MustParseResourceID("default:deployment/locked-service"): "locked-service-deploy.yaml", - flux.MustParseResourceID("default:deployment/test-service"): "test/test-service-deploy.yaml", - flux.MustParseResourceID("default:deployment/multi-deploy"): "multi.yaml", - flux.MustParseResourceID("default:service/multi-service"): "multi.yaml", - flux.MustParseResourceID("default:deployment/list-deploy"): "list.yaml", - flux.MustParseResourceID("default:service/list-service"): "list.yaml", - flux.MustParseResourceID("default:deployment/semver"): "semver-deploy.yaml", - flux.MustParseResourceID("default:daemonset/init"): "init.yaml", +var ResourceMap = map[resource.ID]string{ + resource.MustParseID("default:deployment/helloworld"): "helloworld-deploy.yaml", + resource.MustParseID("default:deployment/locked-service"): "locked-service-deploy.yaml", + resource.MustParseID("default:deployment/test-service"): "test/test-service-deploy.yaml", + resource.MustParseID("default:deployment/multi-deploy"): "multi.yaml", + resource.MustParseID("default:service/multi-service"): "multi.yaml", + resource.MustParseID("default:deployment/list-deploy"): "list.yaml", + resource.MustParseID("default:service/list-service"): "list.yaml", + resource.MustParseID("default:deployment/semver"): "semver-deploy.yaml", + resource.MustParseID("default:daemonset/init"): "init.yaml", } // WorkloadMap ... given a base path, construct the map representing // the services given in the test data. Must be kept in sync with // `Files` below. TODO(michael): derive from ResourceMap, or similar. -func WorkloadMap(dir string) map[flux.ResourceID][]string { - return map[flux.ResourceID][]string{ - flux.MustParseResourceID("default:deployment/helloworld"): []string{filepath.Join(dir, "helloworld-deploy.yaml")}, - flux.MustParseResourceID("default:deployment/locked-service"): []string{filepath.Join(dir, "locked-service-deploy.yaml")}, - flux.MustParseResourceID("default:deployment/test-service"): []string{filepath.Join(dir, "test/test-service-deploy.yaml")}, - flux.MustParseResourceID("default:deployment/multi-deploy"): []string{filepath.Join(dir, "multi.yaml")}, - flux.MustParseResourceID("default:deployment/list-deploy"): []string{filepath.Join(dir, "list.yaml")}, - flux.MustParseResourceID("default:deployment/semver"): []string{filepath.Join(dir, "semver-deploy.yaml")}, - flux.MustParseResourceID("default:daemonset/init"): []string{filepath.Join(dir, "init.yaml")}, +func WorkloadMap(dir string) map[resource.ID][]string { + return map[resource.ID][]string{ + resource.MustParseID("default:deployment/helloworld"): []string{filepath.Join(dir, "helloworld-deploy.yaml")}, + resource.MustParseID("default:deployment/locked-service"): []string{filepath.Join(dir, "locked-service-deploy.yaml")}, + resource.MustParseID("default:deployment/test-service"): []string{filepath.Join(dir, "test/test-service-deploy.yaml")}, + resource.MustParseID("default:deployment/multi-deploy"): []string{filepath.Join(dir, "multi.yaml")}, + resource.MustParseID("default:deployment/list-deploy"): []string{filepath.Join(dir, "list.yaml")}, + resource.MustParseID("default:deployment/semver"): []string{filepath.Join(dir, "semver-deploy.yaml")}, + resource.MustParseID("default:daemonset/init"): []string{filepath.Join(dir, "init.yaml")}, } } diff --git a/cluster/kubernetes/update.go b/cluster/kubernetes/update.go index d2ac4debf..eb9a1fdc8 100644 --- a/cluster/kubernetes/update.go +++ b/cluster/kubernetes/update.go @@ -3,8 +3,8 @@ package kubernetes import ( "strings" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" + "github.com/weaveworks/flux/resource" ) // updateWorkload takes a YAML document stream (one or more YAML @@ -12,7 +12,7 @@ import ( // container name, and the name of the new image that should be used // for the container. It returns a new YAML stream where the image for // the container has been replaced with the imageRef supplied. -func updateWorkload(in []byte, resource flux.ResourceID, container string, newImageID image.Ref) ([]byte, error) { +func updateWorkload(in []byte, resource resource.ID, container string, newImageID image.Ref) ([]byte, error) { namespace, kind, name := resource.Components() if _, ok := resourceKinds[strings.ToLower(kind)]; !ok { return nil, UpdateNotSupportedError(kind) diff --git a/cluster/kubernetes/update_test.go b/cluster/kubernetes/update_test.go index caacf09ea..ea2ed46e8 100644 --- a/cluster/kubernetes/update_test.go +++ b/cluster/kubernetes/update_test.go @@ -3,8 +3,8 @@ package kubernetes import ( "testing" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" + "github.com/weaveworks/flux/resource" ) type update struct { @@ -25,7 +25,7 @@ func testUpdate(t *testing.T, u update) { for _, container := range u.containers { var out []byte var err error - if out, err = updateWorkload([]byte(manifest), flux.MustParseResourceID(u.resourceID), container, id); err != nil { + if out, err = updateWorkload([]byte(manifest), resource.MustParseID(u.resourceID), container, id); err != nil { t.Errorf("Failed: %s", err.Error()) return } diff --git a/cluster/mock/mock.go b/cluster/mock/mock.go index a16633fd0..96aba0406 100644 --- a/cluster/mock/mock.go +++ b/cluster/mock/mock.go @@ -4,11 +4,9 @@ import ( "bytes" "context" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/manifests" - "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/ssh" ) @@ -16,16 +14,16 @@ import ( // Doubles as a cluster.Cluster and cluster.Manifests implementation type Mock struct { AllWorkloadsFunc func(ctx context.Context, maybeNamespace string) ([]cluster.Workload, error) - SomeWorkloadsFunc func(ctx context.Context, ids []flux.ResourceID) ([]cluster.Workload, error) - IsAllowedResourceFunc func(flux.ResourceID) bool + SomeWorkloadsFunc func(ctx context.Context, ids []resource.ID) ([]cluster.Workload, error) + IsAllowedResourceFunc func(resource.ID) bool PingFunc func() error ExportFunc func(ctx context.Context) ([]byte, error) SyncFunc func(cluster.SyncSet) error PublicSSHKeyFunc func(regenerate bool) (ssh.PublicKey, error) - SetWorkloadContainerImageFunc func(def []byte, id flux.ResourceID, container string, newImageID image.Ref) ([]byte, error) + SetWorkloadContainerImageFunc func(def []byte, id resource.ID, container string, newImageID image.Ref) ([]byte, error) LoadManifestsFunc func(base string, paths []string) (map[string]resource.Resource, error) ParseManifestFunc func(def []byte, source string) (map[string]resource.Resource, error) - UpdateWorkloadPoliciesFunc func([]byte, flux.ResourceID, policy.Update) ([]byte, error) + UpdateWorkloadPoliciesFunc func([]byte, resource.ID, resource.PolicyUpdate) ([]byte, error) CreateManifestPatchFunc func(originalManifests, modifiedManifests []byte, originalSource, modifiedSource string) ([]byte, error) ApplyManifestPatchFunc func(originalManifests, patch []byte, originalSource, patchSource string) ([]byte, error) AppendManifestToBufferFunc func([]byte, *bytes.Buffer) error @@ -38,11 +36,11 @@ func (m *Mock) AllWorkloads(ctx context.Context, maybeNamespace string) ([]clust return m.AllWorkloadsFunc(ctx, maybeNamespace) } -func (m *Mock) SomeWorkloads(ctx context.Context, ids []flux.ResourceID) ([]cluster.Workload, error) { +func (m *Mock) SomeWorkloads(ctx context.Context, ids []resource.ID) ([]cluster.Workload, error) { return m.SomeWorkloadsFunc(ctx, ids) } -func (m *Mock) IsAllowedResource(id flux.ResourceID) bool { +func (m *Mock) IsAllowedResource(id resource.ID) bool { return m.IsAllowedResourceFunc(id) } @@ -62,7 +60,7 @@ func (m *Mock) PublicSSHKey(regenerate bool) (ssh.PublicKey, error) { return m.PublicSSHKeyFunc(regenerate) } -func (m *Mock) SetWorkloadContainerImage(def []byte, id flux.ResourceID, container string, newImageID image.Ref) ([]byte, error) { +func (m *Mock) SetWorkloadContainerImage(def []byte, id resource.ID, container string, newImageID image.Ref) ([]byte, error) { return m.SetWorkloadContainerImageFunc(def, id, container, newImageID) } @@ -74,7 +72,7 @@ func (m *Mock) ParseManifest(def []byte, source string) (map[string]resource.Res return m.ParseManifestFunc(def, source) } -func (m *Mock) UpdateWorkloadPolicies(def []byte, id flux.ResourceID, p policy.Update) ([]byte, error) { +func (m *Mock) UpdateWorkloadPolicies(def []byte, id resource.ID, p resource.PolicyUpdate) ([]byte, error) { return m.UpdateWorkloadPoliciesFunc(def, id, p) } diff --git a/cluster/sync.go b/cluster/sync.go index ebe3aab9e..2638302d4 100644 --- a/cluster/sync.go +++ b/cluster/sync.go @@ -3,7 +3,6 @@ package cluster import ( "strings" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/resource" ) @@ -22,7 +21,7 @@ type SyncSet struct { } type ResourceError struct { - ResourceID flux.ResourceID + ResourceID resource.ID Source string Error error } diff --git a/cmd/fluxctl/args.go b/cmd/fluxctl/args.go index 2c864c523..b1fc7916b 100644 --- a/cmd/fluxctl/args.go +++ b/cmd/fluxctl/args.go @@ -3,9 +3,9 @@ package main import ( "bytes" "fmt" - "io/ioutil" + "io/ioutil" "os/exec" - "strings" + "strings" "github.com/spf13/cobra" @@ -35,6 +35,7 @@ func getCommitAuthor() string { } var execCommand = exec.Command + func getUserGitConfigValue(arg string) string { var out bytes.Buffer cmd := execCommand("git", "config", "--get", "--null", arg) diff --git a/cmd/fluxctl/args_test.go b/cmd/fluxctl/args_test.go index 1c634f964..9b6385daf 100644 --- a/cmd/fluxctl/args_test.go +++ b/cmd/fluxctl/args_test.go @@ -1,10 +1,10 @@ package main import ( - "fmt" - "testing" + "fmt" "os" "os/exec" + "testing" ) func helperCommand(command string, s ...string) (cmd *exec.Cmd) { @@ -21,7 +21,6 @@ func TestHelperProcess(t *testing.T) { } defer os.Exit(0) - args := os.Args for len(args) > 0 { if args[0] == "--" { @@ -35,18 +34,18 @@ func TestHelperProcess(t *testing.T) { } _, args = args[0], args[1:] - for _, a := range args { - if a == "user.name" { - fmt.Fprintf(os.Stdout, "Jane Doe") - } else if a == "user.email" { - fmt.Fprintf(os.Stdout, "jd@j.d") - } - } + for _, a := range args { + if a == "user.name" { + fmt.Fprintf(os.Stdout, "Jane Doe") + } else if a == "user.email" { + fmt.Fprintf(os.Stdout, "jd@j.d") + } + } } func checkAuthor(t *testing.T, input string, expected string) { - execCommand = helperCommand - defer func(){ execCommand = exec.Command }() + execCommand = helperCommand + defer func() { execCommand = exec.Command }() author := getUserGitConfigValue(input) if author != expected { t.Fatalf("author %q does not match expected value %q", author, expected) diff --git a/cmd/fluxctl/list_images_cmd.go b/cmd/fluxctl/list_images_cmd.go index 5fbbba7d6..07b5ed9d2 100644 --- a/cmd/fluxctl/list_images_cmd.go +++ b/cmd/fluxctl/list_images_cmd.go @@ -8,10 +8,10 @@ import ( "github.com/spf13/cobra" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/api/v10" "github.com/weaveworks/flux/api/v6" "github.com/weaveworks/flux/registry" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/update" ) @@ -64,7 +64,7 @@ func (opts *imageListOpts) RunE(cmd *cobra.Command, args []string) error { opts.workload = opts.controller } if len(opts.workload) > 0 { - id, err := flux.ParseResourceIDOptionalNamespace(opts.namespace, opts.workload) + id, err := resource.ParseIDOptionalNamespace(opts.namespace, opts.workload) if err != nil { return err } diff --git a/cmd/fluxctl/policy_cmd.go b/cmd/fluxctl/policy_cmd.go index ba871186b..64d6f5f6f 100644 --- a/cmd/fluxctl/policy_cmd.go +++ b/cmd/fluxctl/policy_cmd.go @@ -6,8 +6,9 @@ import ( "strings" "github.com/spf13/cobra" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/policy" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/update" ) @@ -97,7 +98,7 @@ func (opts *workloadPolicyOpts) RunE(cmd *cobra.Command, args []string) error { return newUsageError("lock and unlock both specified") } - resourceID, err := flux.ParseResourceIDOptionalNamespace(opts.namespace, opts.workload) + resourceID, err := resource.ParseIDOptionalNamespace(opts.namespace, opts.workload) if err != nil { return err } @@ -108,7 +109,7 @@ func (opts *workloadPolicyOpts) RunE(cmd *cobra.Command, args []string) error { } ctx := context.Background() - updates := policy.Updates{ + updates := resource.PolicyUpdates{ resourceID: changes, } jobID, err := opts.API.UpdateManifests(ctx, update.Spec{ @@ -122,7 +123,7 @@ func (opts *workloadPolicyOpts) RunE(cmd *cobra.Command, args []string) error { return await(ctx, cmd.OutOrStdout(), cmd.OutOrStderr(), opts.API, jobID, false, opts.verbosity) } -func calculatePolicyChanges(opts *workloadPolicyOpts) (policy.Update, error) { +func calculatePolicyChanges(opts *workloadPolicyOpts) (resource.PolicyUpdate, error) { add := policy.Set{} if opts.automate { add = add.Add(policy.Automated) @@ -153,7 +154,7 @@ func calculatePolicyChanges(opts *workloadPolicyOpts) (policy.Update, error) { for _, tagPair := range opts.tags { parts := strings.Split(tagPair, "=") if len(parts) != 2 { - return policy.Update{}, fmt.Errorf("invalid container/tag pair: %q. Expected format is 'container=filter'", tagPair) + return resource.PolicyUpdate{}, fmt.Errorf("invalid container/tag pair: %q. Expected format is 'container=filter'", tagPair) } container, tag := parts[0], parts[1] @@ -164,7 +165,7 @@ func calculatePolicyChanges(opts *workloadPolicyOpts) (policy.Update, error) { } } - return policy.Update{ + return resource.PolicyUpdate{ Add: add, Remove: remove, }, nil diff --git a/cmd/fluxctl/release_cmd.go b/cmd/fluxctl/release_cmd.go index 4be590747..93d8f8916 100644 --- a/cmd/fluxctl/release_cmd.go +++ b/cmd/fluxctl/release_cmd.go @@ -8,11 +8,11 @@ import ( "github.com/spf13/cobra" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/api/v11" "github.com/weaveworks/flux/api/v6" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/job" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/update" ) @@ -103,7 +103,7 @@ func (opts *workloadReleaseOpts) RunE(cmd *cobra.Command, args []string) error { workloads = []update.ResourceSpec{update.ResourceSpecAll} } else { for _, workload := range opts.workloads { - id, err := flux.ParseResourceIDOptionalNamespace(opts.namespace, workload) + id, err := resource.ParseIDOptionalNamespace(opts.namespace, workload) if err != nil { return err } @@ -130,9 +130,9 @@ func (opts *workloadReleaseOpts) RunE(cmd *cobra.Command, args []string) error { kind = update.ReleaseKindPlan } - var excludes []flux.ResourceID + var excludes []resource.ID for _, exclude := range opts.exclude { - s, err := flux.ParseResourceIDOptionalNamespace(opts.namespace, exclude) + s, err := resource.ParseIDOptionalNamespace(opts.namespace, exclude) if err != nil { return err } diff --git a/cmd/fluxctl/release_cmd_test.go b/cmd/fluxctl/release_cmd_test.go index 472320488..3eb72ff26 100644 --- a/cmd/fluxctl/release_cmd_test.go +++ b/cmd/fluxctl/release_cmd_test.go @@ -5,7 +5,7 @@ import ( "reflect" "testing" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/update" ) @@ -38,9 +38,9 @@ func TestReleaseCommand_CLIConversion(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{ - flux.MustParseResourceID("default:deployment/test"), - flux.MustParseResourceID("default:deployment/yeah"), + Excludes: []resource.ID{ + resource.MustParseID("default:deployment/test"), + resource.MustParseID("default:deployment/yeah"), }, }}, } { diff --git a/cmd/fluxd/main.go b/cmd/fluxd/main.go index a05a3b266..9ceadf202 100644 --- a/cmd/fluxd/main.go +++ b/cmd/fluxd/main.go @@ -293,7 +293,7 @@ func main() { } mandatoryRegistry := stringset(*registryRequire) - if *gitSecret && len(*gitImportGPG) == 0 { + if *gitSecret && len(*gitImportGPG) == 0 { logger.Log("warning", fmt.Sprintf("--git-secret is enabled but there is no GPG key(s) provided using --git-gpg-key-import, we assume you mounted the keyring directly and continue")) } diff --git a/daemon/daemon.go b/daemon/daemon.go index eee5991b4..e7189ea2a 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -11,7 +11,6 @@ import ( "github.com/go-kit/kit/log" "github.com/pkg/errors" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/api" "github.com/weaveworks/flux/api/v10" "github.com/weaveworks/flux/api/v11" @@ -199,7 +198,7 @@ func (d *Daemon) ListImagesWithOptions(ctx context.Context, opts v10.ListImagesO if err != nil { return nil, errors.Wrap(err, "treating workload spec as ID") } - workloads, err = d.Cluster.SomeWorkloads(ctx, []flux.ResourceID{id}) + workloads, err = d.Cluster.SomeWorkloads(ctx, []resource.ID{id}) if err != nil { return nil, errors.Wrap(err, "getting some workloads") } @@ -290,7 +289,7 @@ func (d *Daemon) makeLoggingJobFunc(f jobFunc) jobFunc { } logger.Log("revision", result.Revision) if result.Revision != "" { - var workloadIDs []flux.ResourceID + var workloadIDs []resource.ID for id, result := range result.Result { if result.Status == update.ReleaseStatusSuccess { workloadIDs = append(workloadIDs, id) @@ -350,7 +349,7 @@ func (d *Daemon) UpdateManifests(ctx context.Context, spec update.Spec) (job.ID, return id, err } return d.queueJob(d.makeLoggingJobFunc(d.makeJobFromUpdate(d.release(spec, s)))), nil - case policy.Updates: + case resource.PolicyUpdates: return d.queueJob(d.makeLoggingJobFunc(d.makeJobFromUpdate(d.updatePolicies(spec, s)))), nil case update.ManualSync: return d.queueJob(d.sync()), nil @@ -390,10 +389,10 @@ func (d *Daemon) sync() jobFunc { } } -func (d *Daemon) updatePolicies(spec update.Spec, updates policy.Updates) updateFunc { +func (d *Daemon) updatePolicies(spec update.Spec, updates resource.PolicyUpdates) updateFunc { return func(ctx context.Context, jobID job.ID, working *git.Checkout, logger log.Logger) (job.Result, error) { // For each update - var workloadIDs []flux.ResourceID + var workloadIDs []resource.ID result := job.Result{ Spec: &spec, Result: update.Result{}, @@ -704,7 +703,7 @@ func getWorkloadContainers(workload cluster.Workload, imageRepos update.ImageRep return res, nil } -func policyCommitMessage(us policy.Updates, cause update.Cause) string { +func policyCommitMessage(us resource.PolicyUpdates, cause update.Cause) string { // shortcut, since we want roughly the same information events := policyEvents(us, time.Now()) commitMsg := &bytes.Buffer{} @@ -727,14 +726,14 @@ func policyCommitMessage(us policy.Updates, cause update.Cause) string { // policyEvents builds a map of events (by type), for all the events in this set of // updates. There will be one event per type, containing all workload ids // affected by that event. e.g. all automated workload will share an event. -func policyEvents(us policy.Updates, now time.Time) map[string]event.Event { +func policyEvents(us resource.PolicyUpdates, now time.Time) map[string]event.Event { eventsByType := map[string]event.Event{} for workloadID, update := range us { for _, eventType := range policyEventTypes(update) { e, ok := eventsByType[eventType] if !ok { e = event.Event{ - ServiceIDs: []flux.ResourceID{}, + ServiceIDs: []resource.ID{}, Type: eventType, StartedAt: now, EndedAt: now, @@ -749,7 +748,7 @@ func policyEvents(us policy.Updates, now time.Time) map[string]event.Event { } // policyEventTypes is a deduped list of all event types this update contains -func policyEventTypes(u policy.Update) []string { +func policyEventTypes(u resource.PolicyUpdate) []string { types := map[string]struct{}{} for p := range u.Add { switch { diff --git a/daemon/daemon_test.go b/daemon/daemon_test.go index bf27c521d..3333b6938 100644 --- a/daemon/daemon_test.go +++ b/daemon/daemon_test.go @@ -14,7 +14,6 @@ import ( "github.com/go-kit/kit/log" "github.com/stretchr/testify/assert" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/api/v10" "github.com/weaveworks/flux/api/v11" "github.com/weaveworks/flux/api/v6" @@ -156,7 +155,7 @@ func TestDaemon_ListWorkloadsWithOptions(t *testing.T) { t.Run("filter id", func(t *testing.T) { s, err := d.ListServicesWithOptions(ctx, v11.ListServicesOptions{ Namespace: "", - Services: []flux.ResourceID{flux.MustParseResourceID(wl)}}) + Services: []resource.ID{resource.MustParseID(wl)}}) if err != nil { t.Fatalf("Error: %s", err.Error()) } @@ -168,7 +167,7 @@ func TestDaemon_ListWorkloadsWithOptions(t *testing.T) { t.Run("filter id and namespace", func(t *testing.T) { _, err := d.ListServicesWithOptions(ctx, v11.ListServicesOptions{ Namespace: "foo", - Services: []flux.ResourceID{flux.MustParseResourceID(wl)}}) + Services: []resource.ID{resource.MustParseID(wl)}}) if err == nil { t.Fatal("Expected error but got nil") } @@ -177,7 +176,7 @@ func TestDaemon_ListWorkloadsWithOptions(t *testing.T) { t.Run("filter unsupported id kind", func(t *testing.T) { _, err := d.ListServicesWithOptions(ctx, v11.ListServicesOptions{ Namespace: "foo", - Services: []flux.ResourceID{flux.MustParseResourceID("default:unsupportedkind/goodbyeworld")}}) + Services: []resource.ID{resource.MustParseID("default:unsupportedkind/goodbyeworld")}}) if err == nil { t.Fatal("Expected error but got nil") } @@ -195,7 +194,7 @@ func TestDaemon_ListImagesWithOptions(t *testing.T) { specAll := update.ResourceSpec(update.ResourceSpecAll) // Service 1 - svcID, err := flux.ParseResourceID(wl) + svcID, err := resource.ParseID(wl) assert.NoError(t, err) currentImageRef, err := image.ParseRef(currentHelloImage) assert.NoError(t, err) @@ -205,7 +204,7 @@ func TestDaemon_ListImagesWithOptions(t *testing.T) { assert.NoError(t, err) // Service 2 - anotherSvcID, err := flux.ParseResourceID(anotherWl) + anotherSvcID, err := resource.ParseID(anotherWl) assert.NoError(t, err) anotherImageRef, err := image.ParseRef(anotherImage) assert.NoError(t, err) @@ -577,7 +576,7 @@ func TestDaemon_Automated(t *testing.T) { w := newWait(t) workload := cluster.Workload{ - ID: flux.MakeResourceID(ns, "deployment", "helloworld"), + ID: resource.MakeID(ns, "deployment", "helloworld"), Containers: cluster.ContainersOrExcuse{ Containers: []resource.Container{ { @@ -587,7 +586,7 @@ func TestDaemon_Automated(t *testing.T) { }, }, } - k8s.SomeWorkloadsFunc = func(ctx context.Context, ids []flux.ResourceID) ([]cluster.Workload, error) { + k8s.SomeWorkloadsFunc = func(ctx context.Context, ids []resource.ID) ([]cluster.Workload, error) { return []cluster.Workload{workload}, nil } start() @@ -601,7 +600,7 @@ func TestDaemon_Automated_semver(t *testing.T) { defer clean() w := newWait(t) - resid := flux.MustParseResourceID("default:deployment/semver") + resid := resource.MustParseID("default:deployment/semver") workload := cluster.Workload{ ID: resid, Containers: cluster.ContainersOrExcuse{ @@ -613,7 +612,7 @@ func TestDaemon_Automated_semver(t *testing.T) { }, }, } - k8s.SomeWorkloadsFunc = func(ctx context.Context, ids []flux.ResourceID) ([]cluster.Workload, error) { + k8s.SomeWorkloadsFunc = func(ctx context.Context, ids []resource.ID) ([]cluster.Workload, error) { return []cluster.Workload{workload}, nil } start() @@ -638,7 +637,7 @@ func mockDaemon(t *testing.T) (*Daemon, func(), func(), *mock.Mock, *mockEventWr logger := log.NewNopLogger() singleService := cluster.Workload{ - ID: flux.MustParseResourceID(wl), + ID: resource.MustParseID(wl), Containers: cluster.ContainersOrExcuse{ Containers: []resource.Container{ { @@ -651,7 +650,7 @@ func mockDaemon(t *testing.T) (*Daemon, func(), func(), *mock.Mock, *mockEventWr multiService := []cluster.Workload{ singleService, { - ID: flux.MakeResourceID("another", "deployment", "service"), + ID: resource.MakeID("another", "deployment", "service"), Containers: cluster.ContainersOrExcuse{ Containers: []resource.Container{ { @@ -685,10 +684,10 @@ func mockDaemon(t *testing.T) (*Daemon, func(), func(), *mock.Mock, *mockEventWr } return []cluster.Workload{}, nil } - k8s.IsAllowedResourceFunc = func(flux.ResourceID) bool { return true } + k8s.IsAllowedResourceFunc = func(resource.ID) bool { return true } k8s.ExportFunc = func(ctx context.Context) ([]byte, error) { return testBytes, nil } k8s.PingFunc = func() error { return nil } - k8s.SomeWorkloadsFunc = func(ctx context.Context, ids []flux.ResourceID) ([]cluster.Workload, error) { + k8s.SomeWorkloadsFunc = func(ctx context.Context, ids []resource.ID) ([]cluster.Workload, error) { return []cluster.Workload{ singleService, }, nil @@ -887,8 +886,8 @@ func updateImage(ctx context.Context, d *Daemon, t *testing.T) job.ID { func updatePolicy(ctx context.Context, t *testing.T, d *Daemon) job.ID { return updateManifest(ctx, t, d, update.Spec{ Type: update.Policy, - Spec: policy.Updates{ - flux.MustParseResourceID("default:deployment/helloworld"): { + Spec: resource.PolicyUpdates{ + resource.MustParseID("default:deployment/helloworld"): { Add: policy.Set{ policy.Locked: "true", }, diff --git a/daemon/errors.go b/daemon/errors.go index 32e095d0e..45a36f2bf 100644 --- a/daemon/errors.go +++ b/daemon/errors.go @@ -4,13 +4,13 @@ import ( "fmt" "sync" - "github.com/weaveworks/flux" fluxerr "github.com/weaveworks/flux/errors" "github.com/weaveworks/flux/job" + "github.com/weaveworks/flux/resource" ) type SyncErrors struct { - errs map[flux.ResourceID]error + errs map[resource.ID]error mu sync.Mutex } diff --git a/daemon/images.go b/daemon/images.go index 6404b825b..4624472b9 100644 --- a/daemon/images.go +++ b/daemon/images.go @@ -7,7 +7,6 @@ import ( "github.com/go-kit/kit/log" "github.com/pkg/errors" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" @@ -48,9 +47,9 @@ func (d *Daemon) pollForNewImages(logger log.Logger) { } } -type resources map[flux.ResourceID]resource.Resource +type resources map[resource.ID]resource.Resource -func (r resources) IDs() (ids []flux.ResourceID) { +func (r resources) IDs() (ids []resource.ID) { for k, _ := range r { ids = append(ids, k) } @@ -66,7 +65,7 @@ func (d *Daemon) getAllowedAutomatedResources(ctx context.Context) (resources, e return nil, err } - result := map[flux.ResourceID]resource.Resource{} + result := map[resource.ID]resource.Resource{} for _, resource := range resources { policies := resource.Policies() if policies.Has(policy.Automated) && !policies.Has(policy.Locked) && !policies.Has(policy.Ignore) { diff --git a/daemon/images_test.go b/daemon/images_test.go index 2d2295f25..0e424fbdc 100644 --- a/daemon/images_test.go +++ b/daemon/images_test.go @@ -1,14 +1,14 @@ package daemon import ( - "github.com/weaveworks/flux/policy" "testing" "time" "github.com/go-kit/kit/log" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/image" + "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/registry" registryMock "github.com/weaveworks/flux/registry/mock" "github.com/weaveworks/flux/resource" @@ -28,11 +28,11 @@ const ( ) type candidate struct { - resourceID flux.ResourceID + resourceID resource.ID policies policy.Set } -func (c candidate) ResourceID() flux.ResourceID { +func (c candidate) ResourceID() resource.ID { return c.resourceID } @@ -50,7 +50,7 @@ func (candidate) Bytes() []byte { func TestCalculateChanges_Automated(t *testing.T) { logger := log.NewNopLogger() - resourceID := flux.MakeResourceID(ns, "deployment", "application") + resourceID := resource.MakeID(ns, "deployment", "application") candidateWorkloads := resources{ resourceID: candidate{ resourceID: resourceID, @@ -98,7 +98,7 @@ func TestCalculateChanges_Automated(t *testing.T) { } func TestCalculateChanges_UntaggedImage(t *testing.T) { logger := log.NewNopLogger() - resourceID := flux.MakeResourceID(ns, "deployment", "application") + resourceID := resource.MakeID(ns, "deployment", "application") candidateWorkloads := resources{ resourceID: candidate{ resourceID: resourceID, @@ -154,7 +154,7 @@ func TestCalculateChanges_UntaggedImage(t *testing.T) { } func TestCalculateChanges_ZeroTimestamp(t *testing.T) { logger := log.NewNopLogger() - resourceID := flux.MakeResourceID(ns, "deployment", "application") + resourceID := resource.MakeID(ns, "deployment", "application") candidateWorkloads := resources{ resourceID: candidate{ resourceID: resourceID, diff --git a/daemon/sync.go b/daemon/sync.go index 64a92681d..a306146f5 100644 --- a/daemon/sync.go +++ b/daemon/sync.go @@ -9,7 +9,6 @@ import ( "path/filepath" "time" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/event" "github.com/weaveworks/flux/git" @@ -69,9 +68,9 @@ func (d *Daemon) Sync(ctx context.Context, started time.Time, revision string, s // Determine what resources changed during the sync changedResources, err := getChangedResources(ctx, c, d.GitTimeout, working, resourceStore, resources) - serviceIDs := flux.ResourceIDSet{} + serviceIDs := resource.IDSet{} for _, r := range changedResources { - serviceIDs.Add([]flux.ResourceID{r.ResourceID()}) + serviceIDs.Add([]resource.ID{r.ResourceID()}) } // Retrieve git notes and collect events from them @@ -347,7 +346,7 @@ func collectNoteEvents(ctx context.Context, c changeSet, notes map[string]struct } // logCommitEvent reports all synced commits to the upstream. -func logCommitEvent(el eventLogger, c changeSet, serviceIDs flux.ResourceIDSet, started time.Time, +func logCommitEvent(el eventLogger, c changeSet, serviceIDs resource.IDSet, started time.Time, includesEvents map[string]bool, resourceErrors []event.ResourceError, logger log.Logger) error { if len(c.commits) == 0 { return nil diff --git a/daemon/sync_test.go b/daemon/sync_test.go index cfaa36733..01d65a8d2 100644 --- a/daemon/sync_test.go +++ b/daemon/sync_test.go @@ -14,7 +14,6 @@ import ( "github.com/go-kit/kit/log" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/cluster/kubernetes" "github.com/weaveworks/flux/cluster/kubernetes/testfiles" @@ -25,6 +24,7 @@ import ( "github.com/weaveworks/flux/job" "github.com/weaveworks/flux/manifests" registryMock "github.com/weaveworks/flux/registry/mock" + "github.com/weaveworks/flux/resource" ) const ( @@ -93,7 +93,7 @@ func TestPullAndSync_InitialSync(t *testing.T) { syncCalled := 0 var syncDef *cluster.SyncSet - expectedResourceIDs := flux.ResourceIDs{} + expectedResourceIDs := resource.IDs{} for id, _ := range testfiles.ResourceMap { expectedResourceIDs = append(expectedResourceIDs, id) } @@ -132,8 +132,8 @@ func TestPullAndSync_InitialSync(t *testing.T) { t.Errorf("Unexpected event type: %#v", es[0]) } else { gotResourceIDs := es[0].ServiceIDs - flux.ResourceIDs(gotResourceIDs).Sort() - if !reflect.DeepEqual(gotResourceIDs, []flux.ResourceID(expectedResourceIDs)) { + resource.IDs(gotResourceIDs).Sort() + if !reflect.DeepEqual(gotResourceIDs, []resource.ID(expectedResourceIDs)) { t.Errorf("Unexpected event workload ids: %#v, expected: %#v", gotResourceIDs, expectedResourceIDs) } } @@ -174,7 +174,7 @@ func TestDoSync_NoNewCommits(t *testing.T) { syncCalled := 0 var syncDef *cluster.SyncSet - expectedResourceIDs := flux.ResourceIDs{} + expectedResourceIDs := resource.IDs{} for id, _ := range testfiles.ResourceMap { expectedResourceIDs = append(expectedResourceIDs, id) } @@ -288,7 +288,7 @@ func TestDoSync_WithNewCommit(t *testing.T) { syncCalled := 0 var syncDef *cluster.SyncSet - expectedResourceIDs := flux.ResourceIDs{} + expectedResourceIDs := resource.IDs{} for id, _ := range testfiles.ResourceMap { expectedResourceIDs = append(expectedResourceIDs, id) } @@ -326,10 +326,10 @@ func TestDoSync_WithNewCommit(t *testing.T) { t.Errorf("Unexpected event type: %#v", es[0]) } else { gotResourceIDs := es[0].ServiceIDs - flux.ResourceIDs(gotResourceIDs).Sort() + resource.IDs(gotResourceIDs).Sort() // Event should only have changed workload ids - if !reflect.DeepEqual(gotResourceIDs, []flux.ResourceID{flux.MustParseResourceID("default:deployment/helloworld")}) { - t.Errorf("Unexpected event workload ids: %#v, expected: %#v", gotResourceIDs, []flux.ResourceID{flux.MustParseResourceID("default:deployment/helloworld")}) + if !reflect.DeepEqual(gotResourceIDs, []resource.ID{resource.MustParseID("default:deployment/helloworld")}) { + t.Errorf("Unexpected event workload ids: %#v, expected: %#v", gotResourceIDs, []resource.ID{resource.MustParseID("default:deployment/helloworld")}) } } // It moves the tag diff --git a/event/event.go b/event/event.go index dd44d11f3..09f8f3792 100644 --- a/event/event.go +++ b/event/event.go @@ -1,15 +1,14 @@ package event import ( + "encoding/json" "fmt" "sort" "strings" "time" - "encoding/json" - "github.com/pkg/errors" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/update" ) @@ -42,7 +41,7 @@ type Event struct { // Identifiers of workloads affected by this event. // TODO: rename to WorkloadIDs after adding versioning. - ServiceIDs []flux.ResourceID `json:"serviceIDs"` + ServiceIDs []resource.ID `json:"serviceIDs"` // Type is the type of event, usually "release" for now, but could be other // things later @@ -199,7 +198,7 @@ type Commit struct { } type ResourceError struct { - ID flux.ResourceID + ID resource.ID Path string Error string } diff --git a/flux.go b/flux.go deleted file mode 100644 index e27c5999e..000000000 --- a/flux.go +++ /dev/null @@ -1,240 +0,0 @@ -package flux - -import ( - "encoding/json" - "fmt" - "regexp" - "sort" - "strings" - - "github.com/pkg/errors" -) - -var ( - ErrInvalidServiceID = errors.New("invalid service ID") - - LegacyServiceIDRegexp = regexp.MustCompile("^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$") - // The namespace and name components are (apparently - // non-normatively) defined in - // https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md - // In practice, more punctuation is used than allowed there; - // specifically, people use underscores as well as dashes and dots, and in names, colons. - ResourceIDRegexp = regexp.MustCompile("^(|[a-zA-Z0-9_-]+):([a-zA-Z0-9_-]+)/([a-zA-Z0-9_.:-]+)$") - UnqualifiedResourceIDRegexp = regexp.MustCompile("^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_.:-]+)$") -) - -// ResourceID is an opaque type which uniquely identifies a resource in an -// orchestrator. -type ResourceID struct { - resourceIDImpl -} - -type resourceIDImpl interface { - String() string -} - -// Old-style / format -type legacyServiceID struct { - namespace, service string -} - -func (id legacyServiceID) String() string { - return fmt.Sprintf("%s/%s", id.namespace, id.service) -} - -// New :/ format -type resourceID struct { - namespace, kind, name string -} - -func (id resourceID) String() string { - return fmt.Sprintf("%s:%s/%s", id.namespace, id.kind, id.name) -} - -// ParseResourceID constructs a ResourceID from a string representation -// if possible, returning an error value otherwise. -func ParseResourceID(s string) (ResourceID, error) { - if m := ResourceIDRegexp.FindStringSubmatch(s); m != nil { - return ResourceID{resourceID{m[1], strings.ToLower(m[2]), m[3]}}, nil - } - if m := LegacyServiceIDRegexp.FindStringSubmatch(s); m != nil { - return ResourceID{legacyServiceID{m[1], m[2]}}, nil - } - return ResourceID{}, errors.Wrap(ErrInvalidServiceID, "parsing "+s) -} - -// MustParseResourceID constructs a ResourceID from a string representation, -// panicing if the format is invalid. -func MustParseResourceID(s string) ResourceID { - id, err := ParseResourceID(s) - if err != nil { - panic(err) - } - return id -} - -// ParseResourceIDOptionalNamespace constructs a ResourceID from either a fully -// qualified string representation, or an unqualified kind/name representation -// and the supplied namespace. -func ParseResourceIDOptionalNamespace(namespace, s string) (ResourceID, error) { - if m := ResourceIDRegexp.FindStringSubmatch(s); m != nil { - return ResourceID{resourceID{m[1], strings.ToLower(m[2]), m[3]}}, nil - } - if m := UnqualifiedResourceIDRegexp.FindStringSubmatch(s); m != nil { - return ResourceID{resourceID{namespace, strings.ToLower(m[1]), m[2]}}, nil - } - return ResourceID{}, errors.Wrap(ErrInvalidServiceID, "parsing "+s) -} - -// MakeResourceID constructs a ResourceID from constituent components. -func MakeResourceID(namespace, kind, name string) ResourceID { - return ResourceID{resourceID{namespace, strings.ToLower(kind), name}} -} - -// Components returns the constituent components of a ResourceID -func (id ResourceID) Components() (namespace, kind, name string) { - switch impl := id.resourceIDImpl.(type) { - case resourceID: - return impl.namespace, impl.kind, impl.name - case legacyServiceID: - return impl.namespace, "service", impl.service - default: - panic("wrong underlying type") - } -} - -// MarshalJSON encodes a ResourceID as a JSON string. This is -// done to maintain backwards compatibility with previous flux -// versions where the ResourceID is a plain string. -func (id ResourceID) MarshalJSON() ([]byte, error) { - if id.resourceIDImpl == nil { - // Sadly needed as it's possible to construct an empty ResourceID literal - return json.Marshal("") - } - return json.Marshal(id.String()) -} - -// UnmarshalJSON decodes a ResourceID from a JSON string. This is -// done to maintain backwards compatibility with previous flux -// versions where the ResourceID is a plain string. -func (id *ResourceID) UnmarshalJSON(data []byte) (err error) { - var str string - if err := json.Unmarshal(data, &str); err != nil { - return err - } - if string(str) == "" { - // Sadly needed as it's possible to construct an empty ResourceID literal - *id = ResourceID{} - return nil - } - *id, err = ParseResourceID(string(str)) - return err -} - -// MarshalText encodes a ResourceID as a flat string; this is -// required because ResourceIDs are sometimes used as map keys. -func (id ResourceID) MarshalText() (text []byte, err error) { - return []byte(id.String()), nil -} - -// MarshalText decodes a ResourceID from a flat string; this is -// required because ResourceIDs are sometimes used as map keys. -func (id *ResourceID) UnmarshalText(text []byte) error { - result, err := ParseResourceID(string(text)) - if err != nil { - return err - } - *id = result - return nil -} - -type ResourceIDSet map[ResourceID]struct{} - -func (s ResourceIDSet) String() string { - var ids []string - for id := range s { - ids = append(ids, id.String()) - } - return "{" + strings.Join(ids, ", ") + "}" -} - -func (s ResourceIDSet) Add(ids []ResourceID) { - for _, id := range ids { - s[id] = struct{}{} - } -} - -func (s ResourceIDSet) Without(others ResourceIDSet) ResourceIDSet { - if s == nil || len(s) == 0 || others == nil || len(others) == 0 { - return s - } - res := ResourceIDSet{} - for id := range s { - if !others.Contains(id) { - res[id] = struct{}{} - } - } - return res -} - -func (s ResourceIDSet) Contains(id ResourceID) bool { - if s == nil { - return false - } - _, ok := s[id] - return ok -} - -func (s ResourceIDSet) Intersection(others ResourceIDSet) ResourceIDSet { - if s == nil { - return others - } - if others == nil { - return s - } - result := ResourceIDSet{} - for id := range s { - if _, ok := others[id]; ok { - result[id] = struct{}{} - } - } - return result -} - -func (s ResourceIDSet) ToSlice() ResourceIDs { - i := 0 - keys := make(ResourceIDs, len(s)) - for k := range s { - keys[i] = k - i++ - } - return keys -} - -type ResourceIDs []ResourceID - -func (p ResourceIDs) Len() int { return len(p) } -func (p ResourceIDs) Less(i, j int) bool { return p[i].String() < p[j].String() } -func (p ResourceIDs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } -func (p ResourceIDs) Sort() { sort.Sort(p) } - -func (ids ResourceIDs) Without(others ResourceIDSet) (res ResourceIDs) { - for _, id := range ids { - if !others.Contains(id) { - res = append(res, id) - } - } - return res -} - -func (ids ResourceIDs) Contains(id ResourceID) bool { - set := ResourceIDSet{} - set.Add(ids) - return set.Contains(id) -} - -func (ids ResourceIDs) Intersection(others ResourceIDSet) ResourceIDSet { - set := ResourceIDSet{} - set.Add(ids) - return set.Intersection(others) -} diff --git a/git/gittest/repo.go b/git/gittest/repo.go index 5c4dd6ffb..061ff1803 100644 --- a/git/gittest/repo.go +++ b/git/gittest/repo.go @@ -7,9 +7,9 @@ import ( "path/filepath" "testing" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster/kubernetes/testfiles" "github.com/weaveworks/flux/git" + "github.com/weaveworks/flux/resource" ) // Repo creates a new clone-able git repo, pre-populated with some kubernetes @@ -65,7 +65,7 @@ func Repo(t *testing.T) (*git.Repo, func()) { // Workloads is a shortcut to getting the names of the workloads (NB // not all resources, just the workloads) represented in the test // files. -func Workloads() (res []flux.ResourceID) { +func Workloads() (res []resource.ID) { for k, _ := range testfiles.WorkloadMap("") { res = append(res, k) } diff --git a/http/daemon/server.go b/http/daemon/server.go index b27277342..a50933853 100644 --- a/http/daemon/server.go +++ b/http/daemon/server.go @@ -8,16 +8,15 @@ import ( "github.com/gorilla/mux" "github.com/pkg/errors" stdprometheus "github.com/prometheus/client_golang/prometheus" - "github.com/weaveworks/common/middleware" - "github.com/weaveworks/flux" + "github.com/weaveworks/common/middleware" "github.com/weaveworks/flux/api" "github.com/weaveworks/flux/api/v10" "github.com/weaveworks/flux/api/v11" transport "github.com/weaveworks/flux/http" "github.com/weaveworks/flux/job" fluxmetrics "github.com/weaveworks/flux/metrics" - "github.com/weaveworks/flux/policy" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/update" ) @@ -152,7 +151,7 @@ func (s HTTPServer) ListServicesWithOptions(w http.ResponseWriter, r *http.Reque services := r.URL.Query().Get("services") if services != "" { for _, svc := range strings.Split(services, ",") { - id, err := flux.ParseResourceID(svc) + id, err := resource.ParseID(svc) if err != nil { transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing service spec %q", svc)) return @@ -223,9 +222,9 @@ func (s HTTPServer) UpdateImages(w http.ResponseWriter, r *http.Request) { return } - var excludes []flux.ResourceID + var excludes []resource.ID for _, ex := range r.URL.Query()["exclude"] { - s, err := flux.ParseResourceID(ex) + s, err := resource.ParseID(ex) if err != nil { transport.WriteError(w, r, http.StatusBadRequest, errors.Wrapf(err, "parsing excluded service %q", ex)) return @@ -252,7 +251,7 @@ func (s HTTPServer) UpdateImages(w http.ResponseWriter, r *http.Request) { } func (s HTTPServer) UpdatePolicies(w http.ResponseWriter, r *http.Request) { - var updates policy.Updates + var updates resource.PolicyUpdates if err := json.NewDecoder(r.Body).Decode(&updates); err != nil { transport.WriteError(w, r, http.StatusBadRequest, err) return diff --git a/image/image.go b/image/image.go index d580c5ed5..e8e56b10e 100644 --- a/image/image.go +++ b/image/image.go @@ -242,7 +242,7 @@ type Labels struct { BuildDate time.Time `json:"org.label-schema.build-date,omitempty"` // Created holds the Open Container Image spec 'created' label // Ref: https://github.com/opencontainers/image-spec/blob/master/annotations.md#pre-defined-annotation-keys - Created time.Time `json:"org.opencontainers.image.created,omitempty"` + Created time.Time `json:"org.opencontainers.image.created,omitempty"` } // MarshalJSON returns the Labels value in JSON (as bytes). It is diff --git a/image/image_test.go b/image/image_test.go index 818ed124a..09044bd39 100644 --- a/image/image_test.go +++ b/image/image_test.go @@ -238,9 +238,9 @@ func TestImage_OrderByCreationDate(t *testing.T) { imA := mustMakeInfo("my/Image:2", testTime) imB := mustMakeInfo("my/Image:0", time.Time{}).setLabels(Labels{Created: time0}) imC := mustMakeInfo("my/Image:3", time.Time{}).setLabels(Labels{BuildDate: time2}) - imD := mustMakeInfo("my/Image:4", time.Time{}) // test nil + imD := mustMakeInfo("my/Image:4", time.Time{}) // test nil imE := mustMakeInfo("my/Image:1", time.Time{}).setLabels(Labels{Created: testTime}) // test equal - imF := mustMakeInfo("my/Image:5", time.Time{}) // test nil equal + imF := mustMakeInfo("my/Image:5", time.Time{}) // test nil equal imgs := []Info{imA, imB, imC, imD, imE, imF} Sort(imgs, NewerByCreated) checkSorted(t, imgs) diff --git a/integrations/apis/flux.weave.works/v1beta1/types.go b/integrations/apis/flux.weave.works/v1beta1/types.go index bc67b6923..7b3b0f63e 100644 --- a/integrations/apis/flux.weave.works/v1beta1/types.go +++ b/integrations/apis/flux.weave.works/v1beta1/types.go @@ -9,7 +9,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/helm/pkg/chartutil" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/resource" ) // +genclient @@ -27,8 +27,8 @@ type HelmRelease struct { // ResourceID returns an ID made from the identifying parts of the // resource, as a convenience for Flux, which uses them // everywhere. -func (fhr HelmRelease) ResourceID() flux.ResourceID { - return flux.MakeResourceID(fhr.Namespace, "HelmRelease", fhr.Name) +func (fhr HelmRelease) ResourceID() resource.ID { + return resource.MakeID(fhr.Namespace, "HelmRelease", fhr.Name) } // ReleaseName returns the configured release name, or constructs and diff --git a/integrations/helm/chartsync/chartsync.go b/integrations/helm/chartsync/chartsync.go index a26d0a912..16b0b3e27 100644 --- a/integrations/helm/chartsync/chartsync.go +++ b/integrations/helm/chartsync/chartsync.go @@ -385,7 +385,7 @@ func (chs *ChartChangeSync) reconcileReleaseDef(fhr fluxv1beta1.HelmRelease) { if !chs.release.OwnedByHelmRelease(rel, fhr) { msg := fmt.Sprintf("release '%s' does not belong to HelmRelease", releaseName) chs.setCondition(fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionFalse, ReasonUpgradeFailed, msg) - chs.logger.Log("warning", msg + ", this may be an indication that multiple HelmReleases with the same release name exist", "resource", fhr.ResourceID().String()) + chs.logger.Log("warning", msg+", this may be an indication that multiple HelmReleases with the same release name exist", "resource", fhr.ResourceID().String()) return } diff --git a/integrations/helm/release/release.go b/integrations/helm/release/release.go index 7f8dfef82..ca420b62e 100644 --- a/integrations/helm/release/release.go +++ b/integrations/helm/release/release.go @@ -25,11 +25,11 @@ import ( k8shelm "k8s.io/helm/pkg/helm" helmenv "k8s.io/helm/pkg/helm/environment" hapi_release "k8s.io/helm/pkg/proto/hapi/release" + helmutil "k8s.io/helm/pkg/releaseutil" - "github.com/weaveworks/flux" fluxk8s "github.com/weaveworks/flux/cluster/kubernetes" flux_v1beta1 "github.com/weaveworks/flux/integrations/apis/flux.weave.works/v1beta1" - helmutil "k8s.io/helm/pkg/releaseutil" + "github.com/weaveworks/flux/resource" ) type Action string @@ -89,8 +89,8 @@ func (r *Release) GetUpgradableRelease(name string) (*hapi_release.Release, erro case hapi_release.Status_FAILED: return nil, fmt.Errorf("release requires a rollback before it can be upgraded (%s)", status.GetCode().String()) case hapi_release.Status_PENDING_INSTALL, - hapi_release.Status_PENDING_UPGRADE, - hapi_release.Status_PENDING_ROLLBACK: + hapi_release.Status_PENDING_UPGRADE, + hapi_release.Status_PENDING_ROLLBACK: return nil, fmt.Errorf("operation pending for release (%s)", status.GetCode().String()) default: return nil, fmt.Errorf("current state prevents it from being upgraded (%s)", status.GetCode().String()) @@ -277,7 +277,7 @@ func (r *Release) OwnedByHelmRelease(release *hapi_release.Release, fhr flux_v1b objs := releaseManifestToUnstructured(release.Manifest, log.NewNopLogger()) escapedAnnotation := strings.ReplaceAll(fluxk8s.AntecedentAnnotation, ".", `\.`) - args := []string{"-o", "jsonpath={.metadata.annotations."+escapedAnnotation+"}", "get"} + args := []string{"-o", "jsonpath={.metadata.annotations." + escapedAnnotation + "}", "get"} for ns, res := range namespacedResourceMap(objs, release.Namespace) { for _, r := range res { @@ -326,9 +326,9 @@ func (r *Release) annotateResources(release *hapi_release.Release, fhr flux_v1be } } -// fhrResourceID constructs a flux.ResourceID for a HelmRelease resource. -func fhrResourceID(fhr flux_v1beta1.HelmRelease) flux.ResourceID { - return flux.MakeResourceID(fhr.Namespace, "HelmRelease", fhr.Name) +// fhrResourceID constructs a resource.ID for a HelmRelease resource. +func fhrResourceID(fhr flux_v1beta1.HelmRelease) resource.ID { + return resource.MakeID(fhr.Namespace, "HelmRelease", fhr.Name) } // values tries to resolve all given value file sources and merges diff --git a/manifests/configaware.go b/manifests/configaware.go index a740f3ccf..20429ef27 100644 --- a/manifests/configaware.go +++ b/manifests/configaware.go @@ -11,9 +11,7 @@ import ( "strings" "sync" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" - "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" ) @@ -131,7 +129,7 @@ func findConfigFilePaths(baseDir string, initialPath string) (string, string, er return "", "", configFileNotFoundErr } -func (ca *configAware) SetWorkloadContainerImage(ctx context.Context, resourceID flux.ResourceID, container string, +func (ca *configAware) SetWorkloadContainerImage(ctx context.Context, resourceID resource.ID, container string, newImageID image.Ref) error { resourcesByID, err := ca.getResourcesByID(ctx) if err != nil { @@ -268,8 +266,8 @@ func (ca *configAware) getGeneratedManifests(ctx context.Context, cf *ConfigFile return buf.Bytes(), nil } -func (ca *configAware) UpdateWorkloadPolicies(ctx context.Context, resourceID flux.ResourceID, - update policy.Update) (bool, error) { +func (ca *configAware) UpdateWorkloadPolicies(ctx context.Context, resourceID resource.ID, + update resource.PolicyUpdate) (bool, error) { resourcesByID, err := ca.getResourcesByID(ctx) if err != nil { return false, err @@ -293,7 +291,7 @@ func (ca *configAware) UpdateWorkloadPolicies(ctx context.Context, resourceID fl } func (ca *configAware) updateConfigFileWorkloadPolicies(ctx context.Context, cf *ConfigFile, r resource.Resource, - update policy.Update) (bool, error) { + update resource.PolicyUpdate) (bool, error) { if cf.PatchUpdated != nil { var changed bool err := ca.updatePatchFile(ctx, cf, func(previousManifests []byte) ([]byte, error) { diff --git a/manifests/configaware_test.go b/manifests/configaware_test.go index 6e4ee5edb..0c789b44f 100644 --- a/manifests/configaware_test.go +++ b/manifests/configaware_test.go @@ -10,7 +10,6 @@ import ( "github.com/go-kit/kit/log" "github.com/stretchr/testify/assert" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster/kubernetes" "github.com/weaveworks/flux/cluster/kubernetes/testfiles" "github.com/weaveworks/flux/image" @@ -143,13 +142,13 @@ func TestCommandUpdatedConfigFile(t *testing.T) { resources, err := frs.GetAllResourcesByID(ctx) assert.NoError(t, err) assert.Equal(t, 1, len(resources)) - deploymentID := flux.MustParseResourceID("default:deployment/helloworld") + deploymentID := resource.MustParseID("default:deployment/helloworld") assert.Contains(t, resources, deploymentID.String()) ref, err := image.ParseRef("repo/image:tag") assert.NoError(t, err) err = frs.SetWorkloadContainerImage(ctx, deploymentID, "greeter", ref) assert.NoError(t, err) - _, err = frs.UpdateWorkloadPolicies(ctx, deploymentID, policy.Update{ + _, err = frs.UpdateWorkloadPolicies(ctx, deploymentID, resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("greeter"): "glob:master-*"}, }) assert.NoError(t, err) @@ -189,7 +188,7 @@ func TestPatchUpdatedConfigFile(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 2, len(resources)) var deployment resource.Resource - deploymentID := flux.MustParseResourceID("default:deployment/helloworld") + deploymentID := resource.MustParseID("default:deployment/helloworld") for id, res := range resources { if id == deploymentID.String() { deployment = res @@ -200,7 +199,7 @@ func TestPatchUpdatedConfigFile(t *testing.T) { assert.NoError(t, err) err = frs.SetWorkloadContainerImage(ctx, deploymentID, "greeter", ref) assert.NoError(t, err) - _, err = frs.UpdateWorkloadPolicies(ctx, deploymentID, policy.Update{ + _, err = frs.UpdateWorkloadPolicies(ctx, deploymentID, resource.PolicyUpdate{ Add: policy.Set{policy.TagPrefix("greeter"): "glob:master-*"}, }) expectedPatch := `--- diff --git a/manifests/configfile.go b/manifests/configfile.go index 2fd896454..aa1a65b93 100644 --- a/manifests/configfile.go +++ b/manifests/configfile.go @@ -13,7 +13,7 @@ import ( "github.com/pkg/errors" "gopkg.in/yaml.v2" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/resource" ) const ( @@ -114,7 +114,7 @@ func (cf *ConfigFile) ExecGenerators(ctx context.Context, generators []Generator // ExecContainerImageUpdaters executes all the image updates in the configuration file. // It will stop at the first error, in which case the returned error will be non-nil func (cf *ConfigFile) ExecContainerImageUpdaters(ctx context.Context, - workload flux.ResourceID, container string, image, imageTag string) []ConfigFileCombinedExecResult { + workload resource.ID, container string, image, imageTag string) []ConfigFileCombinedExecResult { env := makeEnvFromResourceID(workload) env = append(env, "FLUX_CONTAINER="+container, @@ -137,7 +137,7 @@ func (cf *ConfigFile) ExecContainerImageUpdaters(ctx context.Context, // policy. It will stop at the first error, in which case the returned // error will be non-nil func (cf *ConfigFile) ExecPolicyUpdaters(ctx context.Context, - workload flux.ResourceID, policyName, policyValue string) []ConfigFileCombinedExecResult { + workload resource.ID, policyName, policyValue string) []ConfigFileCombinedExecResult { env := makeEnvFromResourceID(workload) env = append(env, "FLUX_POLICY="+policyName) if policyValue != "" { @@ -190,7 +190,7 @@ func (cf *ConfigFile) execCommand(ctx context.Context, env []string, stdOut, std return err } -func makeEnvFromResourceID(id flux.ResourceID) []string { +func makeEnvFromResourceID(id resource.ID) []string { ns, kind, name := id.Components() return []string{ "FLUX_WORKLOAD=" + id.String(), diff --git a/manifests/configfile_test.go b/manifests/configfile_test.go index fcef9e121..c7d300a61 100644 --- a/manifests/configfile_test.go +++ b/manifests/configfile_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "gopkg.in/yaml.v2" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/resource" ) const patchUpdatedConfigFile = `--- @@ -83,7 +83,7 @@ func TestExecContainerImageUpdaters(t *testing.T) { var cf ConfigFile err := yaml.Unmarshal([]byte(echoCmdUpdatedConfigFile), &cf) assert.NoError(t, err) - resourceID := flux.MustParseResourceID("default:deployment/foo") + resourceID := resource.MustParseID("default:deployment/foo") result := cf.ExecContainerImageUpdaters(context.Background(), resourceID, "bar", "repo/image", "latest") assert.Equal(t, 2, len(result), "result: %s", result) assert.Equal(t, @@ -98,7 +98,7 @@ func TestExecAnnotationUpdaters(t *testing.T) { var cf ConfigFile err := yaml.Unmarshal([]byte(echoCmdUpdatedConfigFile), &cf) assert.NoError(t, err) - resourceID := flux.MustParseResourceID("default:deployment/foo") + resourceID := resource.MustParseID("default:deployment/foo") // Test the update/addition of annotations annotationValue := "value" diff --git a/manifests/manifests.go b/manifests/manifests.go index 4c049e8fb..652e644e3 100644 --- a/manifests/manifests.go +++ b/manifests/manifests.go @@ -3,9 +3,7 @@ package manifests import ( "bytes" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" - "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" ) @@ -21,9 +19,9 @@ type Manifests interface { // ParseManifest parses the content of a collection of manifests, into resources ParseManifest(def []byte, source string) (map[string]resource.Resource, error) // Set the image of a container in a manifest's bytes to that given - SetWorkloadContainerImage(def []byte, resourceID flux.ResourceID, container string, newImageID image.Ref) ([]byte, error) + SetWorkloadContainerImage(def []byte, resourceID resource.ID, container string, newImageID image.Ref) ([]byte, error) // UpdateWorkloadPolicies modifies a manifest to apply the policy update specified - UpdateWorkloadPolicies(def []byte, id flux.ResourceID, update policy.Update) ([]byte, error) + UpdateWorkloadPolicies(def []byte, id resource.ID, update resource.PolicyUpdate) ([]byte, error) // CreateManifestPatch obtains a patch between the original and modified manifests CreateManifestPatch(originalManifests, modifiedManifests []byte, originalSource, modifiedSource string) ([]byte, error) // ApplyManifestPatch applies a manifest patch (obtained with CreateManifestDiff) returned the patched manifests diff --git a/manifests/rawfiles.go b/manifests/rawfiles.go index ac202d19e..382bbd610 100644 --- a/manifests/rawfiles.go +++ b/manifests/rawfiles.go @@ -7,9 +7,7 @@ import ( "os" "path/filepath" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" - "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" ) @@ -28,7 +26,7 @@ func NewRawFiles(baseDir string, paths []string, manifests Manifests) *rawFiles } // Set the container image of a resource in the store -func (f *rawFiles) SetWorkloadContainerImage(ctx context.Context, id flux.ResourceID, container string, newImageID image.Ref) error { +func (f *rawFiles) SetWorkloadContainerImage(ctx context.Context, id resource.ID, container string, newImageID image.Ref) error { resourcesByID, err := f.GetAllResourcesByID(ctx) if err != nil { return err @@ -59,7 +57,7 @@ func (f *rawFiles) setManifestWorkloadContainerImage(r resource.Resource, contai // UpdateWorkloadPolicies modifies a resource in the store to apply the policy-update specified. // It returns whether a change in the resource was actually made as a result of the change -func (f *rawFiles) UpdateWorkloadPolicies(ctx context.Context, id flux.ResourceID, update policy.Update) (bool, error) { +func (f *rawFiles) UpdateWorkloadPolicies(ctx context.Context, id resource.ID, update resource.PolicyUpdate) (bool, error) { resourcesByID, err := f.GetAllResourcesByID(ctx) if err != nil { return false, err @@ -71,7 +69,7 @@ func (f *rawFiles) UpdateWorkloadPolicies(ctx context.Context, id flux.ResourceI return f.updateManifestWorkloadPolicies(r, update) } -func (f *rawFiles) updateManifestWorkloadPolicies(r resource.Resource, update policy.Update) (bool, error) { +func (f *rawFiles) updateManifestWorkloadPolicies(r resource.Resource, update resource.PolicyUpdate) (bool, error) { fullFilePath := filepath.Join(f.baseDir, r.Source()) def, err := ioutil.ReadFile(fullFilePath) if err != nil { diff --git a/manifests/store.go b/manifests/store.go index 3c26576af..322fff6fb 100644 --- a/manifests/store.go +++ b/manifests/store.go @@ -4,9 +4,7 @@ import ( "context" "fmt" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" - "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/resource" ) @@ -22,10 +20,10 @@ func ErrResourceNotFound(name string) error { // in a file or not e.g., generated and updated by a .flux.yaml file, explicit Kubernetes .yaml manifests files ... type Store interface { // Set the container image of a resource in the store - SetWorkloadContainerImage(ctx context.Context, resourceID flux.ResourceID, container string, newImageID image.Ref) error + SetWorkloadContainerImage(ctx context.Context, resourceID resource.ID, container string, newImageID image.Ref) error // UpdateWorkloadPolicies modifies a resource in the store to apply the policy-update specified. // It returns whether a change in the resource was actually made as a result of the change - UpdateWorkloadPolicies(ctx context.Context, resourceID flux.ResourceID, update policy.Update) (bool, error) + UpdateWorkloadPolicies(ctx context.Context, resourceID resource.ID, update resource.PolicyUpdate) (bool, error) // Load all the resources in the store. The returned map is indexed by the resource IDs GetAllResourcesByID(ctx context.Context) (map[string]resource.Resource, error) } diff --git a/policy/policy.go b/policy/policy.go index ef846858a..c9ec95f34 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -3,8 +3,6 @@ package policy import ( "encoding/json" "strings" - - "github.com/weaveworks/flux" ) const ( @@ -47,13 +45,6 @@ func GetTagPattern(policies Set, container string) Pattern { return NewPattern(pattern) } -type Updates map[flux.ResourceID]Update - -type Update struct { - Add Set `json:"add"` - Remove Set `json:"remove"` -} - type Set map[Policy]string // We used to specify a set of policies as []Policy, and in some places diff --git a/registry/client.go b/registry/client.go index 4434a4ef4..b34de4635 100644 --- a/registry/client.go +++ b/registry/client.go @@ -158,9 +158,9 @@ interpret: } var config struct { - Arch string `json:"architecture"` - Created time.Time `json:"created"` - OS string `json:"os"` + Arch string `json:"architecture"` + Created time.Time `json:"created"` + OS string `json:"os"` ContainerConfig struct { Labels image.Labels `json:"labels"` } `json:"container_config"` diff --git a/registry/credentials.go b/registry/credentials.go index b8c49616c..9962b8903 100644 --- a/registry/credentials.go +++ b/registry/credentials.go @@ -145,11 +145,11 @@ func (cs Credentials) credsFor(host string) creds { } } - if hostIsAzureContainerRegistry(host) { - if cred, err := getAzureCloudConfigAADToken(host); err == nil { - return cred - } - } + if hostIsAzureContainerRegistry(host) { + if cred, err := getAzureCloudConfigAADToken(host); err == nil { + return cred + } + } return creds{} } diff --git a/release/context.go b/release/context.go index ac279ae4b..7008c6568 100644 --- a/release/context.go +++ b/release/context.go @@ -6,7 +6,6 @@ import ( "github.com/pkg/errors" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/manifests" "github.com/weaveworks/flux/registry" @@ -68,7 +67,7 @@ func (rc *ReleaseContext) SelectWorkloads(ctx context.Context, results update.Re // Apply prefilters to select the controllers that we'll ask the // cluster about. - var toAskClusterAbout []flux.ResourceID + var toAskClusterAbout []resource.ID for _, s := range allDefined { res := s.Filter(prefilters...) if res.Error == "" { @@ -118,13 +117,13 @@ func (rc *ReleaseContext) SelectWorkloads(ctx context.Context, results update.Re // WorkloadsForUpdate collects all workloads defined in manifests and prepares a list of // workload updates for each of them. It does not consider updatability. -func (rc *ReleaseContext) WorkloadsForUpdate(ctx context.Context) (map[flux.ResourceID]*update.WorkloadUpdate, error) { +func (rc *ReleaseContext) WorkloadsForUpdate(ctx context.Context) (map[resource.ID]*update.WorkloadUpdate, error) { resources, err := rc.GetAllResources(ctx) if err != nil { return nil, err } - var defined = map[flux.ResourceID]*update.WorkloadUpdate{} + var defined = map[resource.ID]*update.WorkloadUpdate{} for _, res := range resources { if wl, ok := res.(resource.Workload); ok { defined[res.ResourceID()] = &update.WorkloadUpdate{ diff --git a/release/releaser_test.go b/release/releaser_test.go index f4d733081..122619173 100644 --- a/release/releaser_test.go +++ b/release/releaser_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/assert" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/cluster/kubernetes" "github.com/weaveworks/flux/cluster/mock" @@ -37,7 +36,7 @@ var ( oldRef, _ = image.ParseRef(oldImage) sidecarImage = "weaveworks/sidecar:master-a000001" sidecarRef, _ = image.ParseRef(sidecarImage) - hwSvcID, _ = flux.ParseResourceID("default:deployment/helloworld") + hwSvcID, _ = resource.ParseID("default:deployment/helloworld") hwSvcSpec, _ = update.ParseResourceSpec(hwSvcID.String()) hwSvc = cluster.Workload{ ID: hwSvcID, @@ -62,7 +61,7 @@ var ( newLockedImg = "quay.io/weaveworks/locked-service:2" newLockedRef, _ = image.ParseRef(newLockedImg) - lockedSvcID, _ = flux.ParseResourceID("default:deployment/locked-service") + lockedSvcID, _ = resource.ParseID("default:deployment/locked-service") lockedSvcSpec, _ = update.ParseResourceSpec(lockedSvcID.String()) lockedSvc = cluster.Workload{ ID: lockedSvcID, @@ -78,7 +77,7 @@ var ( semverHwImg = "quay.io/weaveworks/helloworld:3.0.0" semverHwRef, _ = image.ParseRef(semverHwImg) - semverSvcID = flux.MustParseResourceID("default:deployment/semver") + semverSvcID = resource.MustParseID("default:deployment/semver") semverSvc = cluster.Workload{ ID: semverSvcID, Containers: cluster.ContainersOrExcuse{ @@ -92,7 +91,7 @@ var ( } semverSvcSpec, _ = update.ParseResourceSpec(semverSvc.ID.String()) - testSvcID = flux.MustParseResourceID("default:deployment/test-service") + testSvcID = resource.MustParseID("default:deployment/test-service") testSvc = cluster.Workload{ ID: testSvcID, Containers: cluster.ContainersOrExcuse{ @@ -148,7 +147,7 @@ func mockCluster(running ...cluster.Workload) *mock.Mock { AllWorkloadsFunc: func(ctx context.Context, maybeNamespace string) ([]cluster.Workload, error) { return running, nil }, - SomeWorkloadsFunc: func(ctx context.Context, ids []flux.ResourceID) ([]cluster.Workload, error) { + SomeWorkloadsFunc: func(ctx context.Context, ids []resource.ID) ([]cluster.Workload, error) { var res []cluster.Workload for _, id := range ids { for _, svc := range running { @@ -221,7 +220,7 @@ func (x expected) Result() update.Result { } func Test_InitContainer(t *testing.T) { - initWorkloadID := flux.MustParseResourceID("default:daemonset/init") + initWorkloadID := resource.MustParseID("default:daemonset/init") initSvc := cluster.Workload{ ID: initWorkloadID, Containers: cluster.ContainersOrExcuse{ @@ -287,11 +286,11 @@ func Test_FilterLogic(t *testing.T) { ServiceSpecs: []update.ResourceSpec{hwSvcSpec}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/helloworld"): update.WorkloadResult{ + resource.MustParseID("default:deployment/helloworld"): update.WorkloadResult{ Status: update.ReleaseStatusSuccess, PerContainer: []update.ContainerUpdate{ { @@ -315,11 +314,11 @@ func Test_FilterLogic(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{lockedSvcID}, + Excludes: []resource.ID{lockedSvcID}, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/helloworld"): update.WorkloadResult{ + resource.MustParseID("default:deployment/helloworld"): update.WorkloadResult{ Status: update.ReleaseStatusSuccess, PerContainer: []update.ContainerUpdate{ { @@ -334,7 +333,7 @@ func Test_FilterLogic(t *testing.T) { }, }, }, - flux.MustParseResourceID("default:deployment/locked-service"): update.WorkloadResult{ + resource.MustParseID("default:deployment/locked-service"): update.WorkloadResult{ Status: update.ReleaseStatusIgnored, Error: update.Excluded, }, @@ -347,11 +346,11 @@ func Test_FilterLogic(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecFromRef(newHwRef), Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/helloworld"): update.WorkloadResult{ + resource.MustParseID("default:deployment/helloworld"): update.WorkloadResult{ Status: update.ReleaseStatusSuccess, PerContainer: []update.ContainerUpdate{ { @@ -361,7 +360,7 @@ func Test_FilterLogic(t *testing.T) { }, }, }, - flux.MustParseResourceID("default:deployment/locked-service"): update.WorkloadResult{ + resource.MustParseID("default:deployment/locked-service"): update.WorkloadResult{ Status: update.ReleaseStatusIgnored, Error: update.DifferentImage, }, @@ -376,11 +375,11 @@ func Test_FilterLogic(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/helloworld"): update.WorkloadResult{ + resource.MustParseID("default:deployment/helloworld"): update.WorkloadResult{ Status: update.ReleaseStatusSuccess, PerContainer: []update.ContainerUpdate{ { @@ -395,7 +394,7 @@ func Test_FilterLogic(t *testing.T) { }, }, }, - flux.MustParseResourceID("default:deployment/locked-service"): update.WorkloadResult{ + resource.MustParseID("default:deployment/locked-service"): update.WorkloadResult{ Status: update.ReleaseStatusSkipped, Error: update.Locked, }, @@ -408,11 +407,11 @@ func Test_FilterLogic(t *testing.T) { ServiceSpecs: []update.ResourceSpec{hwSvcSpec, update.ResourceSpecAll}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/helloworld"): update.WorkloadResult{ + resource.MustParseID("default:deployment/helloworld"): update.WorkloadResult{ Status: update.ReleaseStatusSuccess, PerContainer: []update.ContainerUpdate{ { @@ -427,7 +426,7 @@ func Test_FilterLogic(t *testing.T) { }, }, }, - flux.MustParseResourceID("default:deployment/locked-service"): update.WorkloadResult{ + resource.MustParseID("default:deployment/locked-service"): update.WorkloadResult{ Status: update.ReleaseStatusSkipped, Error: update.Locked, }, @@ -440,11 +439,11 @@ func Test_FilterLogic(t *testing.T) { ServiceSpecs: []update.ResourceSpec{notInRepoSpec}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID(notInRepoService): skippedNotInRepo, + resource.MustParseID(notInRepoService): skippedNotInRepo, }, Else: ignoredNotIncluded, }, @@ -485,12 +484,12 @@ func Test_Force_lockedWorkload(t *testing.T) { ServiceSpecs: []update.ResourceSpec{lockedSvcSpec}, ImageSpec: update.ImageSpecFromRef(newLockedRef), Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, Force: true, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/locked-service"): success, + resource.MustParseID("default:deployment/locked-service"): success, }, Else: ignoredNotIncluded, }, @@ -500,12 +499,12 @@ func Test_Force_lockedWorkload(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecFromRef(newLockedRef), Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, Force: true, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/locked-service"): skippedLocked, + resource.MustParseID("default:deployment/locked-service"): skippedLocked, }, Else: skippedNotInCluster, }, @@ -516,12 +515,12 @@ func Test_Force_lockedWorkload(t *testing.T) { ServiceSpecs: []update.ResourceSpec{lockedSvcSpec}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, Force: true, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/locked-service"): success, + resource.MustParseID("default:deployment/locked-service"): success, }, Else: ignoredNotIncluded, }, @@ -531,12 +530,12 @@ func Test_Force_lockedWorkload(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, Force: true, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/locked-service"): skippedLocked, + resource.MustParseID("default:deployment/locked-service"): skippedLocked, }, Else: skippedNotInCluster, }, @@ -587,12 +586,12 @@ func Test_Force_filteredContainer(t *testing.T) { ServiceSpecs: []update.ResourceSpec{semverSvcSpec}, ImageSpec: update.ImageSpecFromRef(newHwRef), // does not match filter Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, Force: true, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/semver"): successNew, + resource.MustParseID("default:deployment/semver"): successNew, }, Else: ignoredNotIncluded, }, @@ -603,12 +602,12 @@ func Test_Force_filteredContainer(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecFromRef(newHwRef), // does not match filter Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, Force: true, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/semver"): successNew, + resource.MustParseID("default:deployment/semver"): successNew, }, Else: skippedNotInCluster, }, @@ -619,12 +618,12 @@ func Test_Force_filteredContainer(t *testing.T) { ServiceSpecs: []update.ResourceSpec{semverSvcSpec}, ImageSpec: update.ImageSpecLatest, // will filter images by semver and pick newest version Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, Force: true, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/semver"): successSemver, + resource.MustParseID("default:deployment/semver"): successSemver, }, Else: ignoredNotIncluded, }, @@ -635,12 +634,12 @@ func Test_Force_filteredContainer(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, Force: true, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/semver"): successSemver, + resource.MustParseID("default:deployment/semver"): successSemver, }, Else: skippedNotInCluster, }, @@ -685,11 +684,11 @@ func Test_ImageStatus(t *testing.T) { ServiceSpecs: []update.ResourceSpec{testSvcSpec}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/test-service"): update.WorkloadResult{ + resource.MustParseID("default:deployment/test-service"): update.WorkloadResult{ Status: update.ReleaseStatusIgnored, Error: update.DoesNotUseImage, }, @@ -702,11 +701,11 @@ func Test_ImageStatus(t *testing.T) { ServiceSpecs: []update.ResourceSpec{hwSvcSpec}, ImageSpec: update.ImageSpecLatest, Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, }, Expected: expected{ Specific: update.Result{ - flux.MustParseResourceID("default:deployment/helloworld"): update.WorkloadResult{ + resource.MustParseID("default:deployment/helloworld"): update.WorkloadResult{ Status: update.ReleaseStatusSkipped, Error: update.ImageUpToDate, }, @@ -729,7 +728,7 @@ func Test_ImageStatus(t *testing.T) { } func Test_UpdateMultidoc(t *testing.T) { - egID := flux.MustParseResourceID("default:deployment/multi-deploy") + egID := resource.MustParseID("default:deployment/multi-deploy") egSvc := cluster.Workload{ ID: egID, Containers: cluster.ContainersOrExcuse{ @@ -776,7 +775,7 @@ func Test_UpdateMultidoc(t *testing.T) { } func Test_UpdateList(t *testing.T) { - egID := flux.MustParseResourceID("default:deployment/list-deploy") + egID := resource.MustParseID("default:deployment/list-deploy") egSvc := cluster.Workload{ ID: egID, Containers: cluster.ContainersOrExcuse{ @@ -839,7 +838,7 @@ func Test_UpdateContainers(t *testing.T) { } for _, tst := range []struct { Name string - WorkloadID flux.ResourceID + WorkloadID resource.ID Spec []update.ContainerUpdate Force bool @@ -1018,7 +1017,7 @@ func Test_UpdateContainers(t *testing.T) { }, } { specs := update.ReleaseContainersSpec{ - ContainerSpecs: map[flux.ResourceID][]update.ContainerUpdate{tst.WorkloadID: tst.Spec}, + ContainerSpecs: map[resource.ID][]update.ContainerUpdate{tst.WorkloadID: tst.Spec}, Kind: update.ReleaseKindExecute, } @@ -1056,7 +1055,7 @@ type badManifests struct { manifests.Manifests } -func (m *badManifests) SetWorkloadContainerImage(def []byte, id flux.ResourceID, container string, image image.Ref) ([]byte, error) { +func (m *badManifests) SetWorkloadContainerImage(def []byte, id resource.ID, container string, image image.Ref) ([]byte, error) { return def, nil } @@ -1066,7 +1065,7 @@ func Test_BadRelease(t *testing.T) { ServiceSpecs: []update.ResourceSpec{update.ResourceSpecAll}, ImageSpec: update.ImageSpecFromRef(newHwRef), Kind: update.ReleaseKindExecute, - Excludes: []flux.ResourceID{}, + Excludes: []resource.ID{}, } checkout1, cleanup1 := setup(t) defer cleanup1() diff --git a/remote/mock.go b/remote/mock.go index 8f4e5a9bd..1d8891727 100644 --- a/remote/mock.go +++ b/remote/mock.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/api" "github.com/weaveworks/flux/api/v10" "github.com/weaveworks/flux/api/v11" @@ -17,6 +16,7 @@ import ( "github.com/weaveworks/flux/guid" "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/job" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/update" ) @@ -113,9 +113,9 @@ var _ api.UpstreamServer = &MockServer{} func ServerTestBattery(t *testing.T, wrap func(mock api.UpstreamServer) api.UpstreamServer) { // set up namespace := "the-space-of-names" - serviceID := flux.MustParseResourceID(namespace + "/service") - serviceList := []flux.ResourceID{serviceID} - services := flux.ResourceIDSet{} + serviceID := resource.MustParseID(namespace + "/service") + serviceList := []resource.ID{serviceID} + services := resource.IDSet{} services.Add(serviceList) now := time.Now().UTC() @@ -123,7 +123,7 @@ func ServerTestBattery(t *testing.T, wrap func(mock api.UpstreamServer) api.Upst imageID, _ := image.ParseRef("quay.io/example.com/frob:v0.4.5") serviceAnswer := []v6.ControllerStatus{ v6.ControllerStatus{ - ID: flux.MustParseResourceID("foobar/hello"), + ID: resource.MustParseID("foobar/hello"), Status: "ok", Containers: []v6.Container{ v6.Container{ @@ -140,7 +140,7 @@ func ServerTestBattery(t *testing.T, wrap func(mock api.UpstreamServer) api.Upst imagesAnswer := []v6.ImageStatus{ v6.ImageStatus{ - ID: flux.MustParseResourceID("barfoo/yello"), + ID: resource.MustParseID("barfoo/yello"), Containers: []v6.Container{ { Name: "flubnicator", diff --git a/remote/rpc/clientV11.go b/remote/rpc/clientV11.go index 5a38a7312..2f4d063c8 100644 --- a/remote/rpc/clientV11.go +++ b/remote/rpc/clientV11.go @@ -8,7 +8,7 @@ import ( "github.com/weaveworks/flux/api/v11" "github.com/weaveworks/flux/api/v6" "github.com/weaveworks/flux/remote" - ) +) // RPCClientV11 is the rpc-backed implementation of a server, for // talking to remote daemons. This version introduces methods which accept an diff --git a/remote/rpc/compat.go b/remote/rpc/compat.go index 5f8b9561d..35282bb27 100644 --- a/remote/rpc/compat.go +++ b/remote/rpc/compat.go @@ -5,13 +5,13 @@ import ( "errors" "fmt" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/api/v10" "github.com/weaveworks/flux/api/v11" "github.com/weaveworks/flux/api/v6" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/remote" + "github.com/weaveworks/flux/resource" "github.com/weaveworks/flux/update" ) @@ -29,7 +29,7 @@ func requireServiceSpecKinds(ss update.ResourceSpec, kinds []string) error { return nil } -func requireServiceIDKinds(id flux.ResourceID, kinds []string) error { +func requireServiceIDKinds(id resource.ID, kinds []string) error { _, kind, _ := id.Components() if !contains(kinds, kind) { return fmt.Errorf("Unsupported resource kind: %s", kind) @@ -40,7 +40,7 @@ func requireServiceIDKinds(id flux.ResourceID, kinds []string) error { func requireSpecKinds(s update.Spec, kinds []string) error { switch s := s.Spec.(type) { - case policy.Updates: + case resource.PolicyUpdates: for id, _ := range s { _, kind, _ := id.Components() if !contains(kinds, kind) { @@ -120,7 +120,7 @@ func listServicesWithOptions(ctx context.Context, p listServicesWithoutOptionsCl } // Polyfill the service IDs filter - want := map[flux.ResourceID]struct{}{} + want := map[resource.ID]struct{}{} for _, svc := range opts.Services { want[svc] = struct{}{} } @@ -160,7 +160,7 @@ func listImagesWithOptions(ctx context.Context, client listImagesWithoutOptionsC return statuses, err } - policyMap := map[flux.ResourceID]map[string]string{} + policyMap := map[resource.ID]map[string]string{} for _, service := range services { policyMap[service.ID] = service.Policies } diff --git a/remote/rpc/server.go b/remote/rpc/server.go index 256c8c7ba..2d9f850bf 100644 --- a/remote/rpc/server.go +++ b/remote/rpc/server.go @@ -21,7 +21,7 @@ import ( // Server takes an api.Server and makes it available over RPC. type Server struct { - server *rpc.Server + server *rpc.Server } // NewServer instantiates a new RPC server, handling requests on the diff --git a/resource/id.go b/resource/id.go new file mode 100644 index 000000000..280557f2e --- /dev/null +++ b/resource/id.go @@ -0,0 +1,240 @@ +package resource + +import ( + "encoding/json" + "fmt" + "regexp" + "sort" + "strings" + + "github.com/pkg/errors" +) + +var ( + ErrInvalidServiceID = errors.New("invalid service ID") + + LegacyServiceIDRegexp = regexp.MustCompile("^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$") + // The namespace and name components are (apparently + // non-normatively) defined in + // https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md + // In practice, more punctuation is used than allowed there; + // specifically, people use underscores as well as dashes and dots, and in names, colons. + IDRegexp = regexp.MustCompile("^(|[a-zA-Z0-9_-]+):([a-zA-Z0-9_-]+)/([a-zA-Z0-9_.:-]+)$") + UnqualifiedIDRegexp = regexp.MustCompile("^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_.:-]+)$") +) + +// ID is an opaque type which uniquely identifies a resource in an +// orchestrator. +type ID struct { + resourceIDImpl +} + +type resourceIDImpl interface { + String() string +} + +// Old-style / format +type legacyServiceID struct { + namespace, service string +} + +func (id legacyServiceID) String() string { + return fmt.Sprintf("%s/%s", id.namespace, id.service) +} + +// New :/ format +type resourceID struct { + namespace, kind, name string +} + +func (id resourceID) String() string { + return fmt.Sprintf("%s:%s/%s", id.namespace, id.kind, id.name) +} + +// ParseID constructs a ID from a string representation +// if possible, returning an error value otherwise. +func ParseID(s string) (ID, error) { + if m := IDRegexp.FindStringSubmatch(s); m != nil { + return ID{resourceID{m[1], strings.ToLower(m[2]), m[3]}}, nil + } + if m := LegacyServiceIDRegexp.FindStringSubmatch(s); m != nil { + return ID{legacyServiceID{m[1], m[2]}}, nil + } + return ID{}, errors.Wrap(ErrInvalidServiceID, "parsing "+s) +} + +// MustParseID constructs a ID from a string representation, +// panicing if the format is invalid. +func MustParseID(s string) ID { + id, err := ParseID(s) + if err != nil { + panic(err) + } + return id +} + +// ParseIDOptionalNamespace constructs a ID from either a fully +// qualified string representation, or an unqualified kind/name representation +// and the supplied namespace. +func ParseIDOptionalNamespace(namespace, s string) (ID, error) { + if m := IDRegexp.FindStringSubmatch(s); m != nil { + return ID{resourceID{m[1], strings.ToLower(m[2]), m[3]}}, nil + } + if m := UnqualifiedIDRegexp.FindStringSubmatch(s); m != nil { + return ID{resourceID{namespace, strings.ToLower(m[1]), m[2]}}, nil + } + return ID{}, errors.Wrap(ErrInvalidServiceID, "parsing "+s) +} + +// MakeID constructs a ID from constituent components. +func MakeID(namespace, kind, name string) ID { + return ID{resourceID{namespace, strings.ToLower(kind), name}} +} + +// Components returns the constituent components of a ID +func (id ID) Components() (namespace, kind, name string) { + switch impl := id.resourceIDImpl.(type) { + case resourceID: + return impl.namespace, impl.kind, impl.name + case legacyServiceID: + return impl.namespace, "service", impl.service + default: + panic("wrong underlying type") + } +} + +// MarshalJSON encodes a ID as a JSON string. This is +// done to maintain backwards compatibility with previous flux +// versions where the ID is a plain string. +func (id ID) MarshalJSON() ([]byte, error) { + if id.resourceIDImpl == nil { + // Sadly needed as it's possible to construct an empty ID literal + return json.Marshal("") + } + return json.Marshal(id.String()) +} + +// UnmarshalJSON decodes a ID from a JSON string. This is +// done to maintain backwards compatibility with previous flux +// versions where the ID is a plain string. +func (id *ID) UnmarshalJSON(data []byte) (err error) { + var str string + if err := json.Unmarshal(data, &str); err != nil { + return err + } + if string(str) == "" { + // Sadly needed as it's possible to construct an empty ID literal + *id = ID{} + return nil + } + *id, err = ParseID(string(str)) + return err +} + +// MarshalText encodes a ID as a flat string; this is +// required because ResourceIDs are sometimes used as map keys. +func (id ID) MarshalText() (text []byte, err error) { + return []byte(id.String()), nil +} + +// MarshalText decodes a ID from a flat string; this is +// required because ResourceIDs are sometimes used as map keys. +func (id *ID) UnmarshalText(text []byte) error { + result, err := ParseID(string(text)) + if err != nil { + return err + } + *id = result + return nil +} + +type IDSet map[ID]struct{} + +func (s IDSet) String() string { + var ids []string + for id := range s { + ids = append(ids, id.String()) + } + return "{" + strings.Join(ids, ", ") + "}" +} + +func (s IDSet) Add(ids []ID) { + for _, id := range ids { + s[id] = struct{}{} + } +} + +func (s IDSet) Without(others IDSet) IDSet { + if s == nil || len(s) == 0 || others == nil || len(others) == 0 { + return s + } + res := IDSet{} + for id := range s { + if !others.Contains(id) { + res[id] = struct{}{} + } + } + return res +} + +func (s IDSet) Contains(id ID) bool { + if s == nil { + return false + } + _, ok := s[id] + return ok +} + +func (s IDSet) Intersection(others IDSet) IDSet { + if s == nil { + return others + } + if others == nil { + return s + } + result := IDSet{} + for id := range s { + if _, ok := others[id]; ok { + result[id] = struct{}{} + } + } + return result +} + +func (s IDSet) ToSlice() IDs { + i := 0 + keys := make(IDs, len(s)) + for k := range s { + keys[i] = k + i++ + } + return keys +} + +type IDs []ID + +func (p IDs) Len() int { return len(p) } +func (p IDs) Less(i, j int) bool { return p[i].String() < p[j].String() } +func (p IDs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } +func (p IDs) Sort() { sort.Sort(p) } + +func (ids IDs) Without(others IDSet) (res IDs) { + for _, id := range ids { + if !others.Contains(id) { + res = append(res, id) + } + } + return res +} + +func (ids IDs) Contains(id ID) bool { + set := IDSet{} + set.Add(ids) + return set.Contains(id) +} + +func (ids IDs) Intersection(others IDSet) IDSet { + set := IDSet{} + set.Add(ids) + return set.Intersection(others) +} diff --git a/resourceid_test.go b/resource/id_test.go similarity index 87% rename from resourceid_test.go rename to resource/id_test.go index 786792cc3..32befd6fb 100644 --- a/resourceid_test.go +++ b/resource/id_test.go @@ -1,4 +1,4 @@ -package flux +package resource import ( "testing" @@ -24,14 +24,14 @@ func TestResourceIDParsing(t *testing.T) { for _, tc := range valid { t.Run(tc.name, func(t *testing.T) { - if _, err := ParseResourceID(tc.id); err != nil { + if _, err := ParseID(tc.id); err != nil { t.Error(err) } }) } for _, tc := range invalid { t.Run(tc.name, func(t *testing.T) { - if _, err := ParseResourceID(tc.id); err == nil { + if _, err := ParseID(tc.id); err == nil { t.Errorf("expected %q to be considered invalid", tc.id) } }) diff --git a/resource/policy.go b/resource/policy.go index b3910c337..fb3dbea52 100644 --- a/resource/policy.go +++ b/resource/policy.go @@ -17,7 +17,7 @@ import ( // variables. When represented in manifests, policies are expected to // have a non-empty value when present, even if it's `"true"`; so an // empty value can safely denote deletion. -func ChangesForPolicyUpdate(workload Workload, update policy.Update) (map[string]string, error) { +func ChangesForPolicyUpdate(workload Workload, update PolicyUpdate) (map[string]string, error) { add, del := update.Add, update.Remove // We may be sent the pseudo-policy `policy.TagAll`, which means // apply this filter to all containers. To do so, we need to know @@ -45,3 +45,11 @@ func ChangesForPolicyUpdate(workload Workload, update policy.Update) (map[string } return result, nil } + +type PolicyUpdates map[ID]PolicyUpdate + +type PolicyUpdate struct { + Add policy.Set `json:"add"` + Remove policy.Set `json:"remove"` +} + diff --git a/resource/resource.go b/resource/resource.go index a09a21bbf..8f0bf55db 100644 --- a/resource/resource.go +++ b/resource/resource.go @@ -1,17 +1,16 @@ package resource import ( - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/policy" ) // For the minute we just care about type Resource interface { - ResourceID() flux.ResourceID // name, to correlate with what's in the cluster - Policies() policy.Set // policy for this resource; e.g., whether it is locked, automated, ignored - Source() string // where did this come from (informational) - Bytes() []byte // the definition, for sending to cluster.Sync + ResourceID() ID // name, to correlate with what's in the cluster + Policies() policy.Set // policy for this resource; e.g., whether it is locked, automated, ignored + Source() string // where did this come from (informational) + Bytes() []byte // the definition, for sending to cluster.Sync } type Container struct { diff --git a/sync/mock.go b/sync/mock.go index cd9d5b466..814ef9604 100644 --- a/sync/mock.go +++ b/sync/mock.go @@ -1,8 +1,8 @@ package sync import ( - "github.com/weaveworks/flux" "github.com/weaveworks/flux/policy" + "github.com/weaveworks/flux/resource" ) type rsc struct { @@ -26,8 +26,8 @@ func (rs rsc) Bytes() []byte { return []byte{} } -func (rs rsc) ResourceID() flux.ResourceID { - return flux.MakeResourceID(rs.Meta.Namespace, rs.Kind, rs.Meta.Name) +func (rs rsc) ResourceID() resource.ID { + return resource.MakeID(rs.Meta.Namespace, rs.Kind, rs.Meta.Name) } func (rs rsc) Policy() policy.Set { diff --git a/update/automated.go b/update/automated.go index 0c32575ac..e2328c21d 100644 --- a/update/automated.go +++ b/update/automated.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/go-kit/kit/log" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/resource" ) @@ -16,12 +16,12 @@ type Automated struct { } type Change struct { - WorkloadID flux.ResourceID + WorkloadID resource.ID Container resource.Container ImageID image.Ref } -func (a *Automated) Add(service flux.ResourceID, container resource.Container, image image.Ref) { +func (a *Automated) Add(service resource.ID, container resource.Container, image image.Ref) { a.Changes = append(a.Changes, Change{service, container, image}) } @@ -139,18 +139,18 @@ func (a *Automated) calculateImageUpdates(rc ReleaseContext, candidates []*Workl } // workloadMap transposes the changes so they can be looked up by ID -func (a *Automated) workloadMap() map[flux.ResourceID][]Change { - set := map[flux.ResourceID][]Change{} +func (a *Automated) workloadMap() map[resource.ID][]Change { + set := map[resource.ID][]Change{} for _, change := range a.Changes { set[change.WorkloadID] = append(set[change.WorkloadID], change) } return set } -func (a *Automated) workloadIDs() []flux.ResourceID { - slice := []flux.ResourceID{} +func (a *Automated) workloadIDs() []resource.ID { + slice := []resource.ID{} for workload, _ := range a.workloadMap() { - slice = append(slice, flux.MustParseResourceID(workload.String())) + slice = append(slice, resource.MustParseID(workload.String())) } return slice } diff --git a/update/filter.go b/update/filter.go index 0482f90fe..0c6a2ba16 100644 --- a/update/filter.go +++ b/update/filter.go @@ -1,9 +1,9 @@ package update import ( - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/policy" + "github.com/weaveworks/flux/resource" ) const ( @@ -47,7 +47,7 @@ func (f *SpecificImageFilter) Filter(u WorkloadUpdate) WorkloadResult { } type ExcludeFilter struct { - IDs []flux.ResourceID + IDs []resource.ID } func (f *ExcludeFilter) Filter(u WorkloadUpdate) WorkloadResult { @@ -63,7 +63,7 @@ func (f *ExcludeFilter) Filter(u WorkloadUpdate) WorkloadResult { } type IncludeFilter struct { - IDs []flux.ResourceID + IDs []resource.ID } func (f *IncludeFilter) Filter(u WorkloadUpdate) WorkloadResult { diff --git a/update/menu.go b/update/menu.go index 2605b1530..129e3dbf7 100644 --- a/update/menu.go +++ b/update/menu.go @@ -7,7 +7,7 @@ import ( "io" "text/tabwriter" - "github.com/weaveworks/flux" + "github.com/weaveworks/flux/resource" ) const ( @@ -69,7 +69,7 @@ func (c *writer) flush() error { } type menuItem struct { - id flux.ResourceID + id resource.ID status WorkloadUpdateStatus error string update ContainerUpdate @@ -101,7 +101,7 @@ func NewMenu(out io.Writer, results Result, verbosity int) *Menu { func (m *Menu) fromResults(results Result, verbosity int) { for _, workloadID := range results.WorkloadIDs() { - resourceID := flux.MustParseResourceID(workloadID) + resourceID := resource.MustParseID(workloadID) result := results[resourceID] switch result.Status { case ReleaseStatusIgnored: @@ -147,8 +147,8 @@ func (m *Menu) AddItem(mi menuItem) { } // Run starts the interactive menu mode. -func (m *Menu) Run() (map[flux.ResourceID][]ContainerUpdate, error) { - specs := make(map[flux.ResourceID][]ContainerUpdate) +func (m *Menu) Run() (map[resource.ID][]ContainerUpdate, error) { + specs := make(map[resource.ID][]ContainerUpdate) if m.selectable == 0 { return specs, errors.New("No changes found.") } @@ -194,7 +194,7 @@ func (m *Menu) Run() (map[flux.ResourceID][]ContainerUpdate, error) { func (m *Menu) Print() { m.wr.writeln(tableHeading) - var previd flux.ResourceID + var previd resource.ID for _, item := range m.items { inline := previd == item.id m.wr.writeln(m.renderItem(item, inline)) @@ -207,7 +207,7 @@ func (m *Menu) printInteractive() { m.wr.clear() m.wr.writeln(" " + tableHeading) i := 0 - var previd flux.ResourceID + var previd resource.ID for _, item := range m.items { inline := previd == item.id m.wr.writeln(m.renderInteractiveItem(item, inline, i)) diff --git a/update/print_test.go b/update/print_test.go index ec76dd015..d56eb16f0 100644 --- a/update/print_test.go +++ b/update/print_test.go @@ -4,8 +4,8 @@ import ( "bytes" "testing" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" + "github.com/weaveworks/flux/resource" ) func mustParseRef(s string) image.Ref { @@ -26,7 +26,7 @@ func TestPrintResults(t *testing.T) { { name: "basic, just results", result: Result{ - flux.MustParseResourceID("default/helloworld"): WorkloadResult{ + resource.MustParseID("default/helloworld"): WorkloadResult{ Status: ReleaseStatusSuccess, Error: "", PerContainer: []ContainerUpdate{ @@ -47,7 +47,7 @@ default/helloworld success helloworld: quay.io/weaveworks/helloworld:master-a0 { name: "With an error, *and* results", result: Result{ - flux.MustParseResourceID("default/helloworld"): WorkloadResult{ + resource.MustParseID("default/helloworld"): WorkloadResult{ Status: ReleaseStatusSuccess, Error: "test error", PerContainer: []ContainerUpdate{ @@ -69,10 +69,10 @@ default/helloworld success test error { name: "Service results should be sorted", result: Result{ - flux.MustParseResourceID("default/d"): WorkloadResult{Status: ReleaseStatusSuccess}, - flux.MustParseResourceID("default/c"): WorkloadResult{Status: ReleaseStatusSuccess}, - flux.MustParseResourceID("default/b"): WorkloadResult{Status: ReleaseStatusSuccess}, - flux.MustParseResourceID("default/a"): WorkloadResult{Status: ReleaseStatusSuccess}, + resource.MustParseID("default/d"): WorkloadResult{Status: ReleaseStatusSuccess}, + resource.MustParseID("default/c"): WorkloadResult{Status: ReleaseStatusSuccess}, + resource.MustParseID("default/b"): WorkloadResult{Status: ReleaseStatusSuccess}, + resource.MustParseID("default/a"): WorkloadResult{Status: ReleaseStatusSuccess}, }, expected: ` WORKLOAD STATUS UPDATES diff --git a/update/release_containers.go b/update/release_containers.go index 7231ab5db..e225f9205 100644 --- a/update/release_containers.go +++ b/update/release_containers.go @@ -9,7 +9,6 @@ import ( "github.com/go-kit/kit/log" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/resource" ) @@ -19,7 +18,7 @@ var zeroImageRef = image.Ref{} // ReleaseContainersSpec defines the spec for a `containers` manifest update. type ReleaseContainersSpec struct { Kind ReleaseKind - ContainerSpecs map[flux.ResourceID][]ContainerUpdate + ContainerSpecs map[resource.ID][]ContainerUpdate SkipMismatches bool Force bool } @@ -59,7 +58,7 @@ func (s ReleaseContainersSpec) resultsError(results Result) error { } func (s ReleaseContainersSpec) filters() ([]WorkloadFilter, []WorkloadFilter) { - var rids []flux.ResourceID + var rids []resource.ID for rid := range s.ContainerSpecs { rids = append(rids, rid) } diff --git a/update/release_image.go b/update/release_image.go index 5a0add724..795a61769 100644 --- a/update/release_image.go +++ b/update/release_image.go @@ -8,10 +8,10 @@ import ( "github.com/pkg/errors" "github.com/go-kit/kit/log" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" "github.com/weaveworks/flux/policy" "github.com/weaveworks/flux/registry" + "github.com/weaveworks/flux/resource" ) const ( @@ -56,7 +56,7 @@ type ReleaseImageSpec struct { ServiceSpecs []ResourceSpec // TODO: rename to WorkloadSpecs after adding versioning ImageSpec ImageSpec Kind ReleaseKind - Excludes []flux.ResourceID + Excludes []resource.ID Force bool } @@ -119,14 +119,14 @@ func (s ReleaseImageSpec) selectWorkloads(ctx context.Context, rc ReleaseContext func (s ReleaseImageSpec) filters(rc ReleaseContext) ([]WorkloadFilter, []WorkloadFilter, error) { var prefilters, postfilters []WorkloadFilter - ids := []flux.ResourceID{} + ids := []resource.ID{} for _, ss := range s.ServiceSpecs { if ss == ResourceSpecAll { // "" Overrides any other filters - ids = []flux.ResourceID{} + ids = []resource.ID{} break } - id, err := flux.ParseResourceID(string(ss)) + id, err := resource.ParseID(string(ss)) if err != nil { return nil, nil, err } @@ -297,25 +297,25 @@ func (s ReleaseImageSpec) calculateImageUpdates(rc ReleaseContext, candidates [] return updates, nil } -type ResourceSpec string // ResourceID or "" +type ResourceSpec string // ID or "" func ParseResourceSpec(s string) (ResourceSpec, error) { if s == string(ResourceSpecAll) { return ResourceSpecAll, nil } - id, err := flux.ParseResourceID(s) + id, err := resource.ParseID(s) if err != nil { return "", errors.Wrap(err, "invalid workload spec") } return ResourceSpec(id.String()), nil } -func MakeResourceSpec(id flux.ResourceID) ResourceSpec { +func MakeResourceSpec(id resource.ID) ResourceSpec { return ResourceSpec(id.String()) } -func (s ResourceSpec) AsID() (flux.ResourceID, error) { - return flux.ParseResourceID(string(s)) +func (s ResourceSpec) AsID() (resource.ID, error) { + return resource.ParseID(string(s)) } func (s ResourceSpec) String() string { diff --git a/update/result.go b/update/result.go index 9f4c7c16e..ff057f048 100644 --- a/update/result.go +++ b/update/result.go @@ -5,8 +5,8 @@ import ( "sort" "strings" - "github.com/weaveworks/flux" "github.com/weaveworks/flux/image" + "github.com/weaveworks/flux/resource" ) type WorkloadUpdateStatus string @@ -19,7 +19,7 @@ const ( ReleaseStatusUnknown WorkloadUpdateStatus = "unknown" ) -type Result map[flux.ResourceID]WorkloadResult +type Result map[resource.ID]WorkloadResult func (r Result) WorkloadIDs() []string { var result []string @@ -30,8 +30,8 @@ func (r Result) WorkloadIDs() []string { return result } -func (r Result) AffectedResources() flux.ResourceIDs { - ids := flux.ResourceIDs{} +func (r Result) AffectedResources() resource.IDs { + ids := resource.IDs{} for id, result := range r { if result.Status == ReleaseStatusSuccess { ids = append(ids, id) diff --git a/update/spec.go b/update/spec.go index a84ef5f20..e285e72e0 100644 --- a/update/spec.go +++ b/update/spec.go @@ -4,7 +4,7 @@ import ( "encoding/json" "errors" - "github.com/weaveworks/flux/policy" + "github.com/weaveworks/flux/resource" ) const ( @@ -43,7 +43,7 @@ func (spec *Spec) UnmarshalJSON(in []byte) error { spec.Cause = wire.Cause switch wire.Type { case Policy: - var update policy.Updates + var update resource.PolicyUpdates if err := json.Unmarshal(wire.SpecBytes, &update); err != nil { return err } diff --git a/update/workload.go b/update/workload.go index 7eeacbc49..bb14fc044 100644 --- a/update/workload.go +++ b/update/workload.go @@ -1,13 +1,12 @@ package update import ( - "github.com/weaveworks/flux" "github.com/weaveworks/flux/cluster" "github.com/weaveworks/flux/resource" ) type WorkloadUpdate struct { - ResourceID flux.ResourceID + ResourceID resource.ID Workload cluster.Workload Resource resource.Workload Updates []ContainerUpdate