Is there a way to use a stack transformation to ta...
# golang
b
Is there a way to use a stack transformation to tag all AWS (actually
aws-native
) resources in Golang? I have a real hard time to figure out how to do this (see all the
???
in below example). The main problem is that
aws-native
uses no common (shared) types for tags and sets of tags, instead it uses generated
interface
types specific to each taggable resource.
Copy code
package aws

import (
	"fmt"
	"reflect"
	"strings"

	"<http://github.com/pulumi/pulumi/sdk/v3/go/pulumi|github.com/pulumi/pulumi/sdk/v3/go/pulumi>"
)

type Tagger struct {
	tags map[string]string
}

func NewTagger() *Tagger {
	return &Tagger{}
}

func (*Tagger) isTaggable(ctx *pulumi.Context, typeName string, t reflect.Type) bool {
	if strings.HasPrefix(typeName, "aws-native:") {
		if field, found := t.FieldByName("Tags"); found {
			switch field.Type.Kind() {
			case reflect.Slice:
				return true
			}
		}
	}
	return false
}

func (t *Tagger) Apply(ctx *pulumi.Context) error {
	return ctx.RegisterStackTransformation(
		func(args *pulumi.ResourceTransformationArgs) *pulumi.ResourceTransformationResult {
			if t.isTaggable(ctx, args.Type, args.Props.ElementType()) {
				ptr := reflect.ValueOf(args.Props)
				val := ptr.Elem()
				tags := val.FieldByName("Tags")
				var tagList ???
				if !tags.IsZero() {
					tagList = tags.Interface().(???)
				} else {
					tagList = ???{}
				}
				for k, v := range t.tags {
					tagList = append(tagList, ???{ Key: pulumi.String(k), Value: pulumi.String(v)})
				}
				tags.Set(reflect.ValueOf(tagList))
				return &pulumi.ResourceTransformationResult{
					Props: args.Props,
					Opts:  args.Opts,
				}
			}
			ctx.Log.Warn(fmt.Sprintf("isTaggable(%s) -> false", args.Type), nil)
			return nil
		},
	)
}
t
b
@tall-librarian-49374 Yes, that is actually on what my code snipped above is based on. Unfortunately, that does not work for
aws-native
.
t
that does not work for
aws-native
.
Could you highlight the difference between two providers that makes it impossible for me?
b
Just check out all the occurrences of
???
in my example code snipped above.
Copy code
var tagList ???
				if !tags.IsZero() {
					tagList = tags.Interface().(???)
				} else {
					tagList = ???{}
				}
				for k, v := range t.tags {
					tagList = append(tagList, ???{ Key: pulumi.String(k), Value: pulumi.String(v)})
				}
There is no common (Go struct) type for Tags in the (generated)
aws-native
Go SDK. For each AWS Service (e.g.
ec2
, …), service specific (struct) types are created for Tags. For example: • for https://www.pulumi.com/registry/packages/aws-native/api-docs/kms/key/ there is
KeyTagArray
and
KeyTagArgs
• for https://www.pulumi.com/registry/packages/aws-native/api-docs/ecr/repository/there is
PublicRepositoryTagArray
and
PublicRepositoryTagArgs
Having no common type (struct or interface) for tagging resources for all AWS services and resource types, it is impossible to write generic code to tag them.
t
I see now - thank you. Sorry for being slow in parsing the question.