From 408a0edb172c73bdadd3caaefa90d529cab3a54c Mon Sep 17 00:00:00 2001 From: Jorge Marey Date: Sun, 27 Feb 2022 09:09:10 +0100 Subject: [PATCH] Add metadata to namespaces --- api/namespace.go | 1 + command/namespace_apply.go | 13 ++++++++++++ command/namespace_status.go | 13 ++++++++++++ nomad/structs/structs.go | 21 +++++++++++++++++++ .../content/docs/commands/namespace/apply.mdx | 5 +++++ 5 files changed, 53 insertions(+) diff --git a/api/namespace.go b/api/namespace.go index 409a62bdd..7e5352126 100644 --- a/api/namespace.go +++ b/api/namespace.go @@ -71,6 +71,7 @@ type Namespace struct { Description string Quota string Capabilities *NamespaceCapabilities `hcl:"capabilities,block"` + Meta map[string]string CreateIndex uint64 ModifyIndex uint64 } diff --git a/command/namespace_apply.go b/command/namespace_apply.go index 118645963..edab6bff2 100644 --- a/command/namespace_apply.go +++ b/command/namespace_apply.go @@ -216,6 +216,7 @@ func parseNamespaceSpecImpl(result *api.Namespace, list *ast.ObjectList) error { } delete(m, "capabilities") + delete(m, "meta") // Decode the rest if err := mapstructure.WeakDecode(m, result); err != nil { @@ -238,5 +239,17 @@ func parseNamespaceSpecImpl(result *api.Namespace, list *ast.ObjectList) error { } } + if metaO := list.Filter("meta"); len(metaO.Items) > 0 { + for _, o := range metaO.Elem().Items { + var m map[string]interface{} + if err := hcl.DecodeObject(&m, o.Val); err != nil { + return err + } + if err := mapstructure.WeakDecode(m, &result.Meta); err != nil { + return err + } + } + } + return nil } diff --git a/command/namespace_status.go b/command/namespace_status.go index 4f0f58b7f..654d1883d 100644 --- a/command/namespace_status.go +++ b/command/namespace_status.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "sort" "strings" "github.com/hashicorp/nomad/api" @@ -81,6 +82,18 @@ func (c *NamespaceStatusCommand) Run(args []string) int { c.Ui.Output(formatNamespaceBasics(ns)) + if len(ns.Meta) > 0 { + c.Ui.Output(c.Colorize().Color("\n[bold]Metadata[reset]")) + var keys []string + for k := range ns.Meta { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + c.Ui.Output(fmt.Sprintf("%s:\x1f%s", k, ns.Meta[k])) + } + } + if ns.Quota != "" { quotas := client.Quotas() spec, _, err := quotas.Info(ns.Quota, nil) diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 9a30381cf..78082eb44 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -4963,6 +4963,9 @@ type Namespace struct { // Capabilities is the set of capabilities allowed for this namespace Capabilities *NamespaceCapabilities + // Meta is the set of metadata key/value pairs that attached to the namespace + Meta map[string]string + // Hash is the hash of the namespace which is used to efficiently replicate // cross-regions. Hash []byte @@ -5016,6 +5019,18 @@ func (n *Namespace) SetHash() []byte { } } + // sort keys to ensure hash stability when meta is stored later + var keys []string + for k := range n.Meta { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + _, _ = hash.Write([]byte(k)) + _, _ = hash.Write([]byte(n.Meta[k])) + } + // Finalize the hash hashVal := hash.Sum(nil) @@ -5035,6 +5050,12 @@ func (n *Namespace) Copy() *Namespace { c.DisabledTaskDrivers = helper.CopySliceString(n.Capabilities.DisabledTaskDrivers) nc.Capabilities = c } + if n.Meta != nil { + nc.Meta = make(map[string]string, len(n.Meta)) + for k, v := range n.Meta { + nc.Meta[k] = v + } + } copy(nc.Hash, n.Hash) return nc } diff --git a/website/content/docs/commands/namespace/apply.mdx b/website/content/docs/commands/namespace/apply.mdx index d9f93453c..fa54517c2 100644 --- a/website/content/docs/commands/namespace/apply.mdx +++ b/website/content/docs/commands/namespace/apply.mdx @@ -64,5 +64,10 @@ capabilities { enabled_task_drivers = ["docker", "exec"] disabled_task_drivers = ["raw_exec"] } + +meta { + owner = "John Doe" + contact_mail = "john@mycompany.com +} $ nomad namespace apply namespace.json ```