Skip to content

Commit

Permalink
Merge pull request #5 from stevendborrelli/remove-tags
Browse files Browse the repository at this point in the history
Remove tags implementation
  • Loading branch information
stevendborrelli authored Oct 7, 2024
2 parents 45bb173 + c10bced commit 0600602
Show file tree
Hide file tree
Showing 8 changed files with 462 additions and 4 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# function-tags-manager
# function-tag-manager

`function-tag-manager` is a [Crossplane](https://crossplane.io) function that allows
Platform Operators to manage Cloud tags on managed resources.
Expand All @@ -10,6 +10,7 @@ There several use cases for this Function:
- Allowing external systems to set tags on Crossplane Managed Resources without conflict.
- Adding Common Tags to Resources without having to update every resource in a Composition.
- Allowing users the ability to add their own tags when Requesting new resources.
- Removing tags that have been set earlier in the pipeline by other functions.

## Installing the Function

Expand Down Expand Up @@ -128,6 +129,20 @@ Tag keys to ignore can be defined in `FromValue` or set in the Composite/Claim u

Another option for allowing external systems to manage tags is to use the [`initProvider`](https://docs.crossplane.io/latest/concepts/managed-resources/#initprovider) field of a Managed Resource.

### RemoveTags

The function can remove tags defined in the desired state by specifying
`removeTags` and providing an array of keys to delete.

```yaml
removeTags:
- type: FromValue
keys:
- fromValue2
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.removeTags
```

## Tag Policies

When Merging tags, a `Policy` can be set:
Expand Down
7 changes: 7 additions & 0 deletions examples/configuration-aws-network/composition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,13 @@ spec:
policy: Retain
keys:
- ignoreRetain1
removeTags:
- type: FromValue
keys:
- fromValue2 # delete tag defined earlier
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.removeTags

- step: automatically-detect-ready-composed-resources
functionRef:
name: crossplane-contrib-function-auto-ready
8 changes: 8 additions & 0 deletions fn.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1.RunFunctionRequest)
}
}
}
removeTags := f.ResolveRemoveTags(in.RemoveTags, oxr)
// Remove tags
if len(removeTags) > 0 {
err := RemoveTags(desired, removeTags)
if err != nil {
f.log.Debug("error removing tags", string(name), err.Error())
}
}
}

if err := response.SetDesiredComposedResources(rsp, desiredComposed); err != nil {
Expand Down
35 changes: 34 additions & 1 deletion input/v1beta1/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ type ManagedTags struct {
// +optional
AddTags []AddTag `json:"addTags,omitempty"`

// IgnoreTags is a map of tag keys to ignore if set on the
// IgnoreTags is a list of tag keys to ignore if set on the
// resource outside of Crossplane
// +optional
IgnoreTags IgnoreTags `json:"ignoreTags,omitempty"`

// IgnoreTags is a list of tag keys to remove from the resource
// +optional
RemoveTags RemoveTags `json:"removeTags,omitempty"`
}

type Tags map[string]string
Expand Down Expand Up @@ -78,6 +82,7 @@ type AddTag struct {
Policy TagManagerPolicy `json:"policy,omitempty"`
}

// IgnoreTag is a tag that is "ignored" by setting the desired value to the observed value.
type IgnoreTag struct {
// Type determines where tag keys are sourced from. FromValue are inline
// to the composition. FromCompositeFieldPath fetches keys from a field in
Expand All @@ -98,8 +103,29 @@ type IgnoreTag struct {
// +optional
Policy TagManagerPolicy `json:"policy,omitempty"`
}

type IgnoreTags []IgnoreTag

// RemoveTag is a tag that removed from the desired state.
type RemoveTag struct {
// Type determines where tag keys are sourced from. FromValue are inline
// to the composition. FromCompositeFieldPath fetches keys from a field in
// the composite resource
// +kubebuilder:validation:Enum=FromCompositeFieldPath;FromValue
Type TagManagerType `json:"type"`

// FromFieldPath if type is FromCompositeFieldPath, get keys to remove
// from the field in the Composite (like spec.parameters.removeTags)
// +optional
FromFieldPath *string `json:"fromFieldPath,omitempty"`

// Keys are tag keys to ignore for the FromValue type
// +optional
Keys []string `json:"keys,omitempty"`
}

type RemoveTags []RemoveTag

func (a *AddTag) GetType() TagManagerType {
if a == nil || a.Type == "" {
return FromValue
Expand Down Expand Up @@ -141,3 +167,10 @@ func GetKeys(i []IgnoreTag) []string {
}
return keys
}

func (a *RemoveTag) GetType() TagManagerType {
if a == nil || a.Type == "" {
return FromValue
}
return a.Type
}
53 changes: 53 additions & 0 deletions input/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 32 additions & 2 deletions package/input/tag-manager.fn.crossplane.io_managedtags.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@ spec:
type: string
ignoreTags:
description: |-
IgnoreTags is a map of tag keys to ignore if set on the
IgnoreTags is a list of tag keys to ignore if set on the
resource outside of Crossplane
items:
description: IgnoreTag is a tag that is "ignored" by setting the desired
value to the observed value.
properties:
fromFieldPath:
description: |-
Expand All @@ -88,7 +90,7 @@ spec:
type: string
type:
description: |-
Type determines where tag keysare sourced from. FromValue are inline
Type determines where tag keys are sourced from. FromValue are inline
to the composition. FromCompositeFieldPath fetches keys from a field in
the composite resource
enum:
Expand All @@ -109,6 +111,34 @@ spec:
type: string
metadata:
type: object
removeTags:
description: IgnoreTags is a list of tag keys to remove from the resource
items:
description: RemoveTag is a tag that removed from the desired state.
properties:
fromFieldPath:
description: |-
FromFieldPath if type is FromCompositeFieldPath, get keys to remove
from the field in the Composite (like spec.parameters.removeTags)
type: string
keys:
description: Keys are tag keys to ignore for the FromValue type
items:
type: string
type: array
type:
description: |-
Type determines where tag keys are sourced from. FromValue are inline
to the composition. FromCompositeFieldPath fetches keys from a field in
the composite resource
enum:
- FromCompositeFieldPath
- FromValue
type: string
required:
- type
type: object
type: array
type: object
served: true
storage: true
37 changes: 37 additions & 0 deletions tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,40 @@ func (f *Function) ResolveIgnoreTags(in []v1beta1.IgnoreTag, oxr *resource.Compo
}
return tu
}

// ResolveRemoveTag resolves the list of tag keys that will be removed
func (f *Function) ResolveRemoveTags(in []v1beta1.RemoveTag, oxr *resource.Composite) []string {
tagKeys := make([]string, 0)
for _, at := range in {
switch t := at.GetType(); t {
case v1beta1.FromValue:
tagKeys = append(tagKeys, at.Keys...)
case v1beta1.FromCompositeFieldPath: // resolve fields
tags := make([]string, 0)
err := fieldpath.Pave(oxr.Resource.Object).GetValueInto(*at.FromFieldPath, &tags)
if err != nil {
f.log.Debug("Unable to read tags from Composite field: ", *at.FromFieldPath, err)
}
tagKeys = append(tagKeys, tags...)
}
}
return tagKeys
}

// RemoveTags removes tags from a desired composed resource based
// on matching keys
func RemoveTags(desired *resource.DesiredComposed, keys []string) error {
if len(keys) == 0 {
return nil
}
var desiredTags v1beta1.Tags
_ = fieldpath.Pave(desired.Resource.Object).GetValueInto("spec.forProvider.tags", &desiredTags)
numTags := len(desiredTags)
for _, key := range keys {
delete(desiredTags, key)
}
if numTags > 0 {
return desired.Resource.SetValue("spec.forProvider.tags", desiredTags)
}
return nil
}
Loading

0 comments on commit 0600602

Please sign in to comment.