From 62753d5e2febf571ba7fed654d9aff982d2a2cdb Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Tue, 5 Sep 2017 14:36:40 +0100 Subject: [PATCH] Save locked user and message to annotations * add a policy for the user and message given when locking * set them in `fluxctl lock` and clear them in `fluxctl unlock` They will appear in the annotations of the object, and in the result of the list-services API call. (But not in the output of `fluxctl list-services`) --- cluster/kubernetes/resource/load.go | 2 +- cluster/kubernetes/resource/resource.go | 9 +++++++-- cmd/fluxctl/lock_cmd.go | 10 +++++++++- cmd/fluxctl/unlock_cmd.go | 7 +++++-- policy/policy.go | 10 ++++++---- policy/policy_test.go | 12 ++++++++---- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/cluster/kubernetes/resource/load.go b/cluster/kubernetes/resource/load.go index 433a29a22..d31d7e03f 100644 --- a/cluster/kubernetes/resource/load.go +++ b/cluster/kubernetes/resource/load.go @@ -46,7 +46,7 @@ func Load(roots ...string) (map[string]resource.Resource, error) { return objs, nil } -// ParseManifests takes a dump of config (a multidoc YAML) and +// ParseMultidoc takes a dump of config (a multidoc YAML) and // constructs an object set from the resources represented therein. func ParseMultidoc(multidoc []byte, source string) (map[string]resource.Resource, error) { objs := map[string]resource.Resource{} diff --git a/cluster/kubernetes/resource/resource.go b/cluster/kubernetes/resource/resource.go index d0203b548..3b69bf4cd 100644 --- a/cluster/kubernetes/resource/resource.go +++ b/cluster/kubernetes/resource/resource.go @@ -51,8 +51,13 @@ func (o baseObject) ServiceIDs(all map[string]resource.Resource) []flux.ServiceI func (o baseObject) Policy() policy.Set { set := policy.Set{} for k, v := range o.Meta.Annotations { - if strings.HasPrefix(k, PolicyPrefix) && v == "true" { - set = set.Add(policy.Policy(strings.TrimPrefix(k, PolicyPrefix))) + if strings.HasPrefix(k, PolicyPrefix) { + p := strings.TrimPrefix(k, PolicyPrefix) + if v == "true" { + set = set.Add(policy.Policy(p)) + } else { + set = set.Set(policy.Policy(p), v) + } } } return set diff --git a/cmd/fluxctl/lock_cmd.go b/cmd/fluxctl/lock_cmd.go index 694a41b19..0e3c36d01 100644 --- a/cmd/fluxctl/lock_cmd.go +++ b/cmd/fluxctl/lock_cmd.go @@ -47,8 +47,16 @@ func (opts *serviceLockOpts) RunE(cmd *cobra.Command, args []string) error { return err } + lockedPolicy := policy.Set{policy.Locked: "true"} + if opts.cause.User != "" { + lockedPolicy = lockedPolicy.Set(policy.LockedUser, opts.cause.User) + } + if opts.cause.Message != "" { + lockedPolicy = lockedPolicy.Set(policy.LockedMsg, opts.cause.Message) + } + jobID, err := opts.API.UpdatePolicies(noInstanceID, policy.Updates{ - serviceID: policy.Update{Add: policy.Set{policy.Locked: "true"}}, + serviceID: policy.Update{Add: lockedPolicy}, }, opts.cause) if err != nil { return err diff --git a/cmd/fluxctl/unlock_cmd.go b/cmd/fluxctl/unlock_cmd.go index 859a1ef8d..23e1da305 100644 --- a/cmd/fluxctl/unlock_cmd.go +++ b/cmd/fluxctl/unlock_cmd.go @@ -48,8 +48,11 @@ func (opts *serviceUnlockOpts) RunE(cmd *cobra.Command, args []string) error { } jobID, err := opts.API.UpdatePolicies(noInstanceID, policy.Updates{ - serviceID: policy.Update{Remove: policy.Set{policy.Locked: "true"}}, - }, opts.cause) + serviceID: policy.Update{Remove: policy.Set{ + policy.Locked: "true", + policy.LockedMsg: "", + policy.LockedUser: "", + }}}, opts.cause) if err != nil { return err } diff --git a/policy/policy.go b/policy/policy.go index 2ee3f3089..db16a7621 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -8,10 +8,12 @@ import ( ) const ( - Ignore = Policy("ignore") - Locked = Policy("locked") - Automated = Policy("automated") - TagAll = Policy("tag_all") + Ignore = Policy("ignore") + Locked = Policy("locked") + LockedUser = Policy("locked_user") + LockedMsg = Policy("locked_msg") + Automated = Policy("automated") + TagAll = Policy("tag_all") ) // Policy is an string, denoting the current deployment policy of a service, diff --git a/policy/policy_test.go b/policy/policy_test.go index b22b1d499..914cd6c95 100644 --- a/policy/policy_test.go +++ b/policy/policy_test.go @@ -7,13 +7,17 @@ import ( ) func TestJSON(t *testing.T) { - policy := Set{} - policy = policy.Add(Ignore) - policy = policy.Add(Locked) + boolPolicy := Set{} + boolPolicy = boolPolicy.Add(Ignore) + boolPolicy = boolPolicy.Add(Locked) + policy := boolPolicy.Set(LockedUser, "user@example.com") if !(policy.Contains(Ignore) && policy.Contains(Locked)) { t.Errorf("Policy did not include those added") } + if val, ok := policy.Get(LockedUser); !ok || val != "user@example.com" { + t.Errorf("Policy did not include policy that was set") + } bs, err := json.Marshal(policy) if err != nil { @@ -37,7 +41,7 @@ func TestJSON(t *testing.T) { if err = json.Unmarshal(bs, &policy2); err != nil { t.Fatal(err) } - if !reflect.DeepEqual(policy, policy2) { + if !reflect.DeepEqual(boolPolicy, policy2) { t.Errorf("Parsing equivalent list did not preserve policy. Expected:\n%#v\nGot:\n%#v\n", policy, policy2) } }