Skip to content

Commit

Permalink
feat(k8s): Set default labels and annotations from spec.json
Browse files Browse the repository at this point in the history
  • Loading branch information
captncraig authored Sep 10, 2020
1 parent e8b3805 commit 073e616
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 4 deletions.
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.2-0.20200818193711-d2fcc899bdc2 h1:CZtx9gNen+kr3PuC/JQff3n1pJbgpy7Wr3hzjnupqdw=
github.com/google/go-cmp v0.5.2-0.20200818193711-d2fcc899bdc2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-jsonnet v0.15.1-0.20200331184325-4f4aa80dd785 h1:+dlQ7fPoeAqO0U9V+94golo/rW1/V2Pn+v8aPp3ljRM=
github.com/google/go-jsonnet v0.15.1-0.20200331184325-4f4aa80dd785/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw=
github.com/google/go-jsonnet v0.16.1-0.20200908152747-b70cbd441a39 h1:noLRnY1ESguFGDPxXvIcESe2rG63f+ZSbSGYfVa6iHo=
Expand Down
24 changes: 24 additions & 0 deletions pkg/process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ func Process(raw interface{}, cfg v1alpha1.Config, exprs Matchers) (manifest.Lis
// tanka.dev/** labels
out = Label(out, cfg)

// arbitrary labels and annotations from spec
out = ResourceDefaults(out, cfg)

// Perhaps filter for kind/name expressions
if len(exprs) > 0 {
out = Filter(out, exprs)
Expand All @@ -65,6 +68,27 @@ func Label(list manifest.List, cfg v1alpha1.Config) manifest.List {
return list
}

func ResourceDefaults(list manifest.List, cfg v1alpha1.Config) manifest.List {
for i, m := range list {
for k, v := range cfg.Spec.ResourceDefaults.Annotations {
annotations := m.Metadata().Annotations()
if _, ok := annotations[k]; !ok {
annotations[k] = v
}
}

for k, v := range cfg.Spec.ResourceDefaults.Labels {
labels := m.Metadata().Labels()
if _, ok := labels[k]; !ok {
labels[k] = v
}
}

list[i] = m
}
return list
}

// Unwrap returns all Kubernetes objects in the manifest. If m is not a List
// type, a one item List is returned
func Unwrap(manifests map[string]manifest.Manifest) error {
Expand Down
92 changes: 92 additions & 0 deletions pkg/process/resourceDefaults_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package process

import (
"testing"

"github.com/google/go-cmp/cmp"

"github.com/grafana/tanka/pkg/kubernetes/manifest"
"github.com/grafana/tanka/pkg/spec/v1alpha1"
)

func TestResourceDefaults(t *testing.T) {
cases := []struct {
name string
beforeAnnotations map[string]string
beforeLabels map[string]string
specAnnotations map[string]string
specLabels map[string]string
expectedAnnotations map[string]string
expectedLabels map[string]string
}{
// resource without a namespace: set it
{
name: "No change",
},
{
name: "Add annotation",
specAnnotations: map[string]string{"a": "b"},
expectedAnnotations: map[string]string{"a": "b"},
},
{
name: "Add Label",
specLabels: map[string]string{"a": "b"},
expectedLabels: map[string]string{"a": "b"},
},
{
name: "Add leaves existing",
beforeAnnotations: map[string]string{"1": "2"},
beforeLabels: map[string]string{"1": "2"},
specAnnotations: map[string]string{"a": "b"},
specLabels: map[string]string{"a": "b"},
expectedAnnotations: map[string]string{"a": "b", "1": "2"},
expectedLabels: map[string]string{"a": "b", "1": "2"},
},
{
name: "Existing overrides spec",
beforeAnnotations: map[string]string{"a": "c", "1": "2"},
beforeLabels: map[string]string{"a": "c", "1": "2"},
specAnnotations: map[string]string{"a": "b"},
specLabels: map[string]string{"a": "b"},
expectedAnnotations: map[string]string{"a": "c", "1": "2"},
expectedLabels: map[string]string{"a": "c", "1": "2"},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
cfg := v1alpha1.Config{
Spec: v1alpha1.Spec{
ResourceDefaults: v1alpha1.ResourceDefaults{
Annotations: c.specAnnotations,
Labels: c.specLabels,
},
},
}

before := manifest.Manifest{
"kind": "Deployment",
}
for k, v := range c.beforeAnnotations {
before.Metadata().Annotations()[k] = v
}
for k, v := range c.beforeLabels {
before.Metadata().Labels()[k] = v
}

expected := manifest.Metadata{}
for k, v := range c.expectedAnnotations {
expected.Annotations()[k] = v
}
for k, v := range c.expectedLabels {
expected.Labels()[k] = v
}

result := ResourceDefaults(manifest.List{before}, cfg)
actual := result[0]
if diff := cmp.Diff(expected, actual.Metadata()); diff != "" {
t.Error(diff)
}
})
}
}
15 changes: 11 additions & 4 deletions pkg/spec/v1alpha1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,15 @@ func (m Metadata) NameLabel() string {

// Spec defines Kubernetes properties
type Spec struct {
APIServer string `json:"apiServer"`
Namespace string `json:"namespace"`
DiffStrategy string `json:"diffStrategy,omitempty"`
InjectLabels bool `json:"injectLabels,omitempty"`
APIServer string `json:"apiServer"`
Namespace string `json:"namespace"`
DiffStrategy string `json:"diffStrategy,omitempty"`
InjectLabels bool `json:"injectLabels,omitempty"`
ResourceDefaults ResourceDefaults `json:"resourceDefaults,omitempty"`
}

// ResourceDefaults will be inserted in any manifests that tanka processes.
type ResourceDefaults struct {
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}

0 comments on commit 073e616

Please sign in to comment.