Skip to content
This repository has been archived by the owner on Oct 30, 2024. It is now read-only.

Commit

Permalink
s3-propagate-tags (#3177)
Browse files Browse the repository at this point in the history
  • Loading branch information
calvix authored Sep 29, 2021
1 parent 813e88c commit a131e50
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add cloud tags propagation to S3 buckets.

### Changed

- Update `aws-attach-etcd-dep` image version to `0.2.0` to include bugfixes.
Expand Down
3 changes: 2 additions & 1 deletion service/controller/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,8 @@ func newClusterResources(config ClusterConfig) ([]resource.Interface, error) {
var s3BucketResource resource.Interface
{
c := s3bucket.Config{
Logger: config.Logger,
CtrlClient: config.K8sClient.CtrlClient(),
Logger: config.Logger,

AccessLogsExpiration: config.AccessLogsExpiration,
DeleteLoggingBucket: config.DeleteLoggingBucket,
Expand Down
7 changes: 6 additions & 1 deletion service/controller/resource/s3bucket/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,15 @@ func (r *Resource) ApplyCreateChange(ctx context.Context, obj, createChange inte
}

if r.includeTags {
tagSet, err := r.getS3BucketTags(ctx, cr)
if err != nil {
return microerror.Mask(err)
}

i := &s3.PutBucketTaggingInput{
Bucket: aws.String(bucketInput.Name),
Tagging: &s3.Tagging{
TagSet: r.getS3BucketTags(cr),
TagSet: tagSet,
},
}

Expand Down
4 changes: 4 additions & 0 deletions service/controller/resource/s3bucket/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import (
"github.com/giantswarm/microerror"
)

var executionFailedError = &microerror.Error{
Kind: "executionFailedError",
}

var invalidConfigError = &microerror.Error{
Kind: "invalidConfigError",
}
Expand Down
56 changes: 51 additions & 5 deletions service/controller/resource/s3bucket/resource.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package s3bucket

import (
"context"
"strings"

"github.com/aws/aws-sdk-go/service/s3"
infrastructurev1alpha3 "github.com/giantswarm/apiextensions/v3/pkg/apis/infrastructure/v1alpha3"
"github.com/giantswarm/microerror"
"github.com/giantswarm/micrologger"
apiv1alpha3 "sigs.k8s.io/cluster-api/api/v1alpha3"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/giantswarm/aws-operator/pkg/awstags"
"github.com/giantswarm/aws-operator/pkg/label"
"github.com/giantswarm/aws-operator/service/controller/key"
)

Expand All @@ -20,7 +26,8 @@ const (
// Config represents the configuration used to create a new s3bucket resource.
type Config struct {
// Dependencies.
Logger micrologger.Logger
Logger micrologger.Logger
CtrlClient client.Client

// Settings.
AccessLogsExpiration int
Expand All @@ -32,7 +39,8 @@ type Config struct {
// Resource implements the s3bucket resource.
type Resource struct {
// Dependencies.
logger micrologger.Logger
ctrlClient client.Client
logger micrologger.Logger

// Settings.
accessLogsExpiration int
Expand All @@ -58,7 +66,8 @@ func New(config Config) (*Resource, error) {

r := &Resource{
// Dependencies.
logger: config.Logger,
ctrlClient: config.CtrlClient,
logger: config.Logger,

// Settings.
accessLogsExpiration: config.AccessLogsExpiration,
Expand Down Expand Up @@ -97,11 +106,48 @@ func containsBucketState(bucketStateName string, bucketStateList []BucketState)
return false
}

func (r *Resource) getS3BucketTags(customObject infrastructurev1alpha3.AWSCluster) []*s3.Tag {
func (r *Resource) getS3BucketTags(ctx context.Context, customObject infrastructurev1alpha3.AWSCluster) ([]*s3.Tag, error) {
tags := key.AWSTags(&customObject, r.installationName)
return awstags.NewS3(tags)

var list apiv1alpha3.ClusterList
err := r.ctrlClient.List(
ctx,
&list,
client.MatchingLabels{label.Cluster: key.ClusterID(&customObject)},
)
if err != nil {
return nil, microerror.Mask(err)
}
if len(list.Items) != 1 {
return nil, microerror.Maskf(executionFailedError, "expected 1 CR got %d", len(list.Items))
}

allTags := addCloudTags(tags, list.Items[0].GetLabels())

return awstags.NewS3(allTags), nil
}

func (r *Resource) canBeDeleted(bucket BucketState) bool {
return !bucket.IsLoggingBucket || bucket.IsLoggingBucket && r.deleteLoggingBucket
}

// add cloud tags from `labels` to `tags` map
func addCloudTags(tags map[string]string, labels map[string]string) map[string]string {
for k, v := range labels {
if isCloudTagKey(k) {
tags[trimCloudTagKey(k)] = v
}
}

return tags
}

// IsCloudTagKey checks if a tag has proper prefix
func isCloudTagKey(tagKey string) bool {
return strings.HasPrefix(tagKey, key.KeyCloudPrefix)
}

// TrimCloudTagKey trims key cloud prefix from a tag
func trimCloudTagKey(tagKey string) string {
return strings.TrimPrefix(tagKey, key.KeyCloudPrefix)
}
48 changes: 46 additions & 2 deletions service/controller/resource/s3bucket/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,53 @@ package s3bucket
import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/giantswarm/microerror"
"github.com/giantswarm/operatorkit/v5/pkg/resource/crud"

"github.com/giantswarm/aws-operator/service/controller/controllercontext"
"github.com/giantswarm/aws-operator/service/controller/key"
)

func (r *Resource) ApplyUpdateChange(ctx context.Context, obj, updateChange interface{}) error {
// update bucket tags
cr, err := key.ToCluster(ctx, obj)
if err != nil {
return microerror.Mask(err)
}
cc, err := controllercontext.FromContext(ctx)
if err != nil {
return microerror.Mask(err)
}

currentBuckets, err := toBucketState(updateChange)
if err != nil {
return microerror.Mask(err)
}

for _, bucket := range currentBuckets {
if r.includeTags {
tagSet, err := r.getS3BucketTags(ctx, cr)
if err != nil {
return microerror.Mask(err)
}

i := &s3.PutBucketTaggingInput{
Bucket: aws.String(bucket.Name),
Tagging: &s3.Tagging{
TagSet: tagSet,
},
}

_, err = cc.Client.TenantCluster.AWS.S3.PutBucketTagging(i)
if err != nil {
return microerror.Mask(err)
}
}
r.logger.Debugf(ctx, "S3 bucket %#q tags updated", bucket.Name)
}

return nil
}

Expand All @@ -29,7 +71,9 @@ func (r *Resource) NewUpdatePatch(ctx context.Context, obj, currentState, desire
return patch, nil
}

// newUpdateChange is a no-op because S3 buckets are not updated.
// newUpdateChange returns all buckets in order to update tags on all buckets
func (r *Resource) newUpdateChange(ctx context.Context, obj, currentState, desiredState interface{}) (interface{}, error) {
return nil, nil
currentBuckets, err := toBucketState(currentState)

return currentBuckets, err
}

0 comments on commit a131e50

Please sign in to comment.