Skip to content

Commit

Permalink
support multiple ACK resource tag formats
Browse files Browse the repository at this point in the history
  • Loading branch information
vijtrip2 committed May 23, 2022
1 parent 08a6708 commit 849d6c8
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 38 deletions.
101 changes: 63 additions & 38 deletions pkg/runtime/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
package runtime

import (
"fmt"
"strings"

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

// resolveTagFormat is a function which returns the resolved value for an
// ACK resource tag format. Ex: %CONTROLLER_SERVICE% -> s3
type resolveTagFormat func(rtclient.Object, acktypes.ServiceControllerMetadata) string

const (
// MissingImageTagValue is the placeholder value when ACK controller
// image tag(release semver) cannot be determined.
MissingImageTagValue = "unknown"
MissingImageTagValue = "unknown"
ServiceAliasTagFormat = "%CONTROLLER_SERVICE%"
ControllerVersionTagFormat = "%CONTROLLER_VERSION%"
NamespaceTagFormat = "%K8S_NAMESPACE%"
ResourceNameTagFormat = "%K8S_RESOURCE_NAME%"
)

// ACKResourceTagFormats is map of ACK resource tag formats to it's
// resolveTagFormat function.
//
// To add a new ACKResourceTag format, include it in this map, along with the
// resolveTagFormat function and expandTagValue() method will start
// expanding the new resource tag format.
var ACKResourceTagFormats = map[string]resolveTagFormat{
ServiceAliasTagFormat: func(
obj rtclient.Object,
md acktypes.ServiceControllerMetadata,
) string {
return md.ServiceAlias
},

ControllerVersionTagFormat: func(
obj rtclient.Object,
md acktypes.ServiceControllerMetadata,
) string {
controllerImageTag := md.GitVersion
// ACK controller released from the ACK CD pipeline will have the correct
// GitVersion. But this value can be empty when manually building ACK
// controller image locally and not passing the go ldflags.
// Add a placeholder value when git tag is found missing.
if controllerImageTag == "" {
controllerImageTag = MissingImageTagValue
}
return controllerImageTag
},

NamespaceTagFormat: func(
obj rtclient.Object,
md acktypes.ServiceControllerMetadata,
) string {
return obj.GetNamespace()
},

ResourceNameTagFormat: func(
obj rtclient.Object,
md acktypes.ServiceControllerMetadata,
) string {
return obj.GetName()
},
}

// GetDefaultTags provides Default tags (key value pairs) for given resource
func GetDefaultTags(
config *ackconfig.Config,
object rtclient.Object,
obj rtclient.Object,
md acktypes.ServiceControllerMetadata,
) map[string]string {
if object == nil || config == nil || len(config.ResourceTags) == 0 {
if obj == nil || config == nil || len(config.ResourceTags) == 0 {
return nil
}
var populatedTags = make(map[string]string)
Expand All @@ -49,46 +100,20 @@ func GetDefaultTags(
if key == "" || val == "" {
continue
}
populatedValue := expandTagValue(&val, object, md)
populatedTags[key] = *populatedValue
}
if len(populatedTags) == 0 {
return nil
populatedTags[key] = expandTagValue(val, obj, md)
}
return populatedTags
}

// expandTagValue returns the tag value after expanding all the ACKResourceTag
// formats.
func expandTagValue(
value *string,
value string,
obj rtclient.Object,
md acktypes.ServiceControllerMetadata,
) *string {
if value == nil || obj == nil {
return nil
}
var expandedValue string = ""
switch *value {
case "%CONTROLLER_VERSION%":
expandedValue = generateControllerVersion(md)
case "%K8S_NAMESPACE%":
expandedValue = obj.GetNamespace()
default:
expandedValue = *value
}
return &expandedValue
}

// generateControllerVersion creates the tag value for key
// "services.k8s.aws/controller-version". The value for this tag is in the
// format "<service-name>-<controller-image-tag>". Ex: s3-v0.0.10
func generateControllerVersion(md acktypes.ServiceControllerMetadata) string {
controllerImageTag := md.GitVersion
// ACK controller released from the ACK CD pipeline will have the correct
// GitVersion. But this value can be empty when manually building ACK
// controller image locally and not passing the go ldflags.
// Add a placeholder value when git tag is found missing.
if controllerImageTag == "" {
controllerImageTag = MissingImageTagValue
) string {
for tagFormat, resolveTagFormat := range ACKResourceTagFormats {
value = strings.ReplaceAll(value, tagFormat, resolveTagFormat(obj, md))
}
return fmt.Sprintf("%s-%s", md.ServiceAlias, controllerImageTag)
return value
}
75 changes: 75 additions & 0 deletions pkg/runtime/tags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package runtime_test

import (
"fmt"
"testing"

"github.com/aws-controllers-k8s/runtime/pkg/config"

mocks "github.com/aws-controllers-k8s/runtime/mocks/controller-runtime/pkg/client"
"github.com/aws-controllers-k8s/runtime/pkg/runtime"
"github.com/aws-controllers-k8s/runtime/pkg/types"
"github.com/stretchr/testify/assert"
)

func TestGetDefaultTags(t *testing.T) {
assert := assert.New(t)
obj := mocks.Object{}
obj.On("GetNamespace").Return("ns")
obj.On("GetName").Return("res")

cfg := config.Config{}

md := types.ServiceControllerMetadata{
ServiceAlias: "s3",
VersionInfo: types.VersionInfo{
GitVersion: "v0.0.10",
},
}

// nil config
assert.Nil(runtime.GetDefaultTags(nil, &obj, md))

// nil object
assert.Nil(runtime.GetDefaultTags(&cfg, nil, md))

// no resource tags
assert.Nil(runtime.GetDefaultTags(&cfg, &obj, md))

// ill formed tags
cfg.ResourceTags = []string{"foobar"}
expandedTags := runtime.GetDefaultTags(&cfg, &obj, md)
assert.Empty(expandedTags)

// ill formed tags
cfg.ResourceTags = []string{"foo=bar=baz"}
expandedTags = runtime.GetDefaultTags(&cfg, &obj, md)
assert.Empty(expandedTags)

// tags without any ack resource tag format
cfg.ResourceTags = []string{"foo=bar"}
expandedTags = runtime.GetDefaultTags(&cfg, &obj, md)
assert.Equal(1, len(expandedTags))
assert.Equal("bar", expandedTags["foo"])

// expand ack resource tag formats
cfg.ResourceTags = []string{
"foo=bar",
fmt.Sprintf("services.k8s.aws/controller-version=%s-%s",
runtime.ServiceAliasTagFormat,
runtime.ControllerVersionTagFormat,
),
fmt.Sprintf("services.k8s.aws/namespace=%s",
runtime.NamespaceTagFormat,
),
fmt.Sprintf("services.k8s.aws/name=%s",
runtime.ResourceNameTagFormat,
),
}
expandedTags = runtime.GetDefaultTags(&cfg, &obj, md)
assert.Equal(4, len(expandedTags))
assert.Equal("bar", expandedTags["foo"])
assert.Equal("s3-v0.0.10", expandedTags["services.k8s.aws/controller-version"])
assert.Equal("ns", expandedTags["services.k8s.aws/namespace"])
assert.Equal("res", expandedTags["services.k8s.aws/name"])
}

0 comments on commit 849d6c8

Please sign in to comment.