Skip to content

Commit 50de420

Browse files
authored
support multiple ACK resource tag formats (#88)
Issue #, if available: aws-controllers-k8s/community#1261 Description of changes: * support '%CONTROLLER_SERVICE%' , '%CONTROLLER_VERSION%', '%K8S_NAMESPACE%' and '%K8S_RESOURCE_NAME%' as the resource tag format * support tag format as substring, and not just complete tag value * As per the [comment](#87 (review)) , I did not add 'OWNER_ACCOUNT_ID' because any AWS related information will be known to customer when describing tags or viewing the resource in AWS console. * I also did not add 'K8S_CRD_VERSION' right now and waiting for multi version support , to find out the best place to find the k8s resource crd version. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 08a6708 commit 50de420

File tree

2 files changed

+138
-38
lines changed

2 files changed

+138
-38
lines changed

pkg/runtime/tags.go

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
package runtime
1515

1616
import (
17-
"fmt"
1817
"strings"
1918

2019
rtclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -23,19 +22,71 @@ import (
2322
acktypes "github.com/aws-controllers-k8s/runtime/pkg/types"
2423
)
2524

25+
// resolveTagFormat is a function which returns the resolved value for an
26+
// ACK resource tag format. Ex: %CONTROLLER_SERVICE% -> s3
27+
type resolveTagFormat func(rtclient.Object, acktypes.ServiceControllerMetadata) string
28+
2629
const (
2730
// MissingImageTagValue is the placeholder value when ACK controller
2831
// image tag(release semver) cannot be determined.
29-
MissingImageTagValue = "unknown"
32+
MissingImageTagValue = "unknown"
33+
ServiceAliasTagFormat = "%CONTROLLER_SERVICE%"
34+
ControllerVersionTagFormat = "%CONTROLLER_VERSION%"
35+
NamespaceTagFormat = "%K8S_NAMESPACE%"
36+
ResourceNameTagFormat = "%K8S_RESOURCE_NAME%"
3037
)
3138

39+
// ACKResourceTagFormats is map of ACK resource tag formats to it's
40+
// resolveTagFormat function.
41+
//
42+
// To add a new ACKResourceTag format, include it in this map, along with the
43+
// resolveTagFormat function and expandTagValue() method will start
44+
// expanding the new resource tag format.
45+
var ACKResourceTagFormats = map[string]resolveTagFormat{
46+
ServiceAliasTagFormat: func(
47+
obj rtclient.Object,
48+
md acktypes.ServiceControllerMetadata,
49+
) string {
50+
return md.ServiceAlias
51+
},
52+
53+
ControllerVersionTagFormat: func(
54+
obj rtclient.Object,
55+
md acktypes.ServiceControllerMetadata,
56+
) string {
57+
controllerImageTag := md.GitVersion
58+
// ACK controller released from the ACK CD pipeline will have the correct
59+
// GitVersion. But this value can be empty when manually building ACK
60+
// controller image locally and not passing the go ldflags.
61+
// Add a placeholder value when git tag is found missing.
62+
if controllerImageTag == "" {
63+
controllerImageTag = MissingImageTagValue
64+
}
65+
return controllerImageTag
66+
},
67+
68+
NamespaceTagFormat: func(
69+
obj rtclient.Object,
70+
md acktypes.ServiceControllerMetadata,
71+
) string {
72+
return obj.GetNamespace()
73+
},
74+
75+
ResourceNameTagFormat: func(
76+
obj rtclient.Object,
77+
md acktypes.ServiceControllerMetadata,
78+
) string {
79+
return obj.GetName()
80+
},
81+
}
82+
3283
// GetDefaultTags provides Default tags (key value pairs) for given resource
3384
func GetDefaultTags(
3485
config *ackconfig.Config,
35-
object rtclient.Object,
86+
obj rtclient.Object,
3687
md acktypes.ServiceControllerMetadata,
3788
) map[string]string {
38-
if object == nil || config == nil || len(config.ResourceTags) == 0 {
89+
if obj == nil || config == nil || len(config.ResourceTags) == 0 {
3990
return nil
4091
}
4192
var populatedTags = make(map[string]string)
@@ -49,46 +100,20 @@ func GetDefaultTags(
49100
if key == "" || val == "" {
50101
continue
51102
}
52-
populatedValue := expandTagValue(&val, object, md)
53-
populatedTags[key] = *populatedValue
54-
}
55-
if len(populatedTags) == 0 {
56-
return nil
103+
populatedTags[key] = expandTagValue(val, obj, md)
57104
}
58105
return populatedTags
59106
}
60107

108+
// expandTagValue returns the tag value after expanding all the ACKResourceTag
109+
// formats.
61110
func expandTagValue(
62-
value *string,
111+
value string,
63112
obj rtclient.Object,
64113
md acktypes.ServiceControllerMetadata,
65-
) *string {
66-
if value == nil || obj == nil {
67-
return nil
68-
}
69-
var expandedValue string = ""
70-
switch *value {
71-
case "%CONTROLLER_VERSION%":
72-
expandedValue = generateControllerVersion(md)
73-
case "%K8S_NAMESPACE%":
74-
expandedValue = obj.GetNamespace()
75-
default:
76-
expandedValue = *value
77-
}
78-
return &expandedValue
79-
}
80-
81-
// generateControllerVersion creates the tag value for key
82-
// "services.k8s.aws/controller-version". The value for this tag is in the
83-
// format "<service-name>-<controller-image-tag>". Ex: s3-v0.0.10
84-
func generateControllerVersion(md acktypes.ServiceControllerMetadata) string {
85-
controllerImageTag := md.GitVersion
86-
// ACK controller released from the ACK CD pipeline will have the correct
87-
// GitVersion. But this value can be empty when manually building ACK
88-
// controller image locally and not passing the go ldflags.
89-
// Add a placeholder value when git tag is found missing.
90-
if controllerImageTag == "" {
91-
controllerImageTag = MissingImageTagValue
114+
) string {
115+
for tagFormat, resolveTagFormat := range ACKResourceTagFormats {
116+
value = strings.ReplaceAll(value, tagFormat, resolveTagFormat(obj, md))
92117
}
93-
return fmt.Sprintf("%s-%s", md.ServiceAlias, controllerImageTag)
118+
return value
94119
}

pkg/runtime/tags_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package runtime_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/aws-controllers-k8s/runtime/pkg/config"
8+
9+
mocks "github.com/aws-controllers-k8s/runtime/mocks/controller-runtime/pkg/client"
10+
"github.com/aws-controllers-k8s/runtime/pkg/runtime"
11+
"github.com/aws-controllers-k8s/runtime/pkg/types"
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestGetDefaultTags(t *testing.T) {
16+
assert := assert.New(t)
17+
obj := mocks.Object{}
18+
obj.On("GetNamespace").Return("ns")
19+
obj.On("GetName").Return("res")
20+
21+
cfg := config.Config{}
22+
23+
md := types.ServiceControllerMetadata{
24+
ServiceAlias: "s3",
25+
VersionInfo: types.VersionInfo{
26+
GitVersion: "v0.0.10",
27+
},
28+
}
29+
30+
// nil config
31+
assert.Nil(runtime.GetDefaultTags(nil, &obj, md))
32+
33+
// nil object
34+
assert.Nil(runtime.GetDefaultTags(&cfg, nil, md))
35+
36+
// no resource tags
37+
assert.Nil(runtime.GetDefaultTags(&cfg, &obj, md))
38+
39+
// ill formed tags
40+
cfg.ResourceTags = []string{"foobar"}
41+
expandedTags := runtime.GetDefaultTags(&cfg, &obj, md)
42+
assert.Empty(expandedTags)
43+
44+
// ill formed tags
45+
cfg.ResourceTags = []string{"foo=bar=baz"}
46+
expandedTags = runtime.GetDefaultTags(&cfg, &obj, md)
47+
assert.Empty(expandedTags)
48+
49+
// tags without any ack resource tag format
50+
cfg.ResourceTags = []string{"foo=bar"}
51+
expandedTags = runtime.GetDefaultTags(&cfg, &obj, md)
52+
assert.Equal(1, len(expandedTags))
53+
assert.Equal("bar", expandedTags["foo"])
54+
55+
// expand ack resource tag formats
56+
cfg.ResourceTags = []string{
57+
"foo=bar",
58+
fmt.Sprintf("services.k8s.aws/controller-version=%s-%s",
59+
runtime.ServiceAliasTagFormat,
60+
runtime.ControllerVersionTagFormat,
61+
),
62+
fmt.Sprintf("services.k8s.aws/namespace=%s",
63+
runtime.NamespaceTagFormat,
64+
),
65+
fmt.Sprintf("services.k8s.aws/name=%s",
66+
runtime.ResourceNameTagFormat,
67+
),
68+
}
69+
expandedTags = runtime.GetDefaultTags(&cfg, &obj, md)
70+
assert.Equal(4, len(expandedTags))
71+
assert.Equal("bar", expandedTags["foo"])
72+
assert.Equal("s3-v0.0.10", expandedTags["services.k8s.aws/controller-version"])
73+
assert.Equal("ns", expandedTags["services.k8s.aws/namespace"])
74+
assert.Equal("res", expandedTags["services.k8s.aws/name"])
75+
}

0 commit comments

Comments
 (0)