Skip to content

Commit 57f2e20

Browse files
committed
#5 Add tag command to tag object/versions.
1 parent be85c7e commit 57f2e20

1 file changed

Lines changed: 127 additions & 0 deletions

File tree

cmd/tags.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package cmd
2+
3+
import (
4+
"strings"
5+
6+
"github.com/aws/aws-sdk-go/aws"
7+
"github.com/aws/aws-sdk-go/service/s3"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
var tagRoot = &cobra.Command{
12+
Use: "tag",
13+
Short: "Tag S3 object(s)",
14+
}
15+
16+
func getTagMap(expectValue bool) map[string]string {
17+
tagSet := make(map[string]string)
18+
for _, t := range tagFlags.tags {
19+
i := strings.IndexRune(t, '=')
20+
switch {
21+
case expectValue && i > 0:
22+
tagSet[t[:i]] = t[i+1:]
23+
case !expectValue && i > 0:
24+
tagSet[t[:i]] = ""
25+
case !expectValue:
26+
tagSet[t] = ""
27+
}
28+
}
29+
return tagSet
30+
}
31+
32+
var tagAdd = &cobra.Command{
33+
Use: "add s3://bucket/folder/ s3://bucket/folder/prefix ...",
34+
Short: "Add tag(s) to S3 object(s)",
35+
SilenceUsage: true,
36+
RunE: func(_ *cobra.Command, urls []string) error {
37+
svc := getS3()
38+
return run(urls, accessFuncBuilder(func(bucket string, o *s3.ObjectVersion) error {
39+
tagResp, err := svc.GetObjectTagging(&s3.GetObjectTaggingInput{
40+
Bucket: &bucket,
41+
Key: o.Key,
42+
VersionId: o.VersionId,
43+
})
44+
if err != nil {
45+
return err
46+
}
47+
ts := tagResp.TagSet
48+
newTags := getTagMap(true)
49+
for i := range ts {
50+
if v, ok := newTags[*ts[i].Key]; ok {
51+
ts[i].Value = aws.String(v) // copy
52+
delete(newTags, *ts[i].Key)
53+
}
54+
}
55+
for k, v := range newTags {
56+
ts = append(ts, &s3.Tag{
57+
Key: aws.String(k),
58+
Value: aws.String(v),
59+
})
60+
}
61+
62+
_, err = svc.PutObjectTagging(&s3.PutObjectTaggingInput{
63+
Bucket: &bucket,
64+
Key: o.Key,
65+
VersionId: o.VersionId,
66+
Tagging: &s3.Tagging{
67+
TagSet: ts,
68+
},
69+
})
70+
return err
71+
}))
72+
},
73+
}
74+
75+
var tagRm = &cobra.Command{
76+
Use: "rm s3://bucket/folder/ s3://bucket/folder/prefix ...",
77+
Short: "remove tag(s) from S3 object(s)",
78+
SilenceUsage: true,
79+
RunE: func(_ *cobra.Command, urls []string) error {
80+
svc := getS3()
81+
return run(urls, accessFuncBuilder(func(bucket string, o *s3.ObjectVersion) error {
82+
tagResp, err := svc.GetObjectTagging(&s3.GetObjectTaggingInput{
83+
Bucket: &bucket,
84+
Key: o.Key,
85+
VersionId: o.VersionId,
86+
})
87+
if err != nil {
88+
return err
89+
}
90+
ts := tagResp.TagSet
91+
rmTags := getTagMap(false)
92+
i := 0
93+
for i < len(ts) {
94+
if _, ok := rmTags[*ts[i].Key]; ok {
95+
// remove an element in an array by swapping it with last element and reducing array size
96+
ts[len(ts)-1], ts[i] = ts[i], ts[len(ts)-1]
97+
ts = ts[:len(ts)-1]
98+
continue
99+
}
100+
i++
101+
}
102+
_, err = svc.PutObjectTagging(&s3.PutObjectTaggingInput{
103+
Bucket: &bucket,
104+
Key: o.Key,
105+
VersionId: o.VersionId,
106+
Tagging: &s3.Tagging{
107+
TagSet: ts,
108+
},
109+
})
110+
return err
111+
}))
112+
},
113+
}
114+
115+
func init() {
116+
tagAdd.Flags().StringSliceVar(&tagFlags.tags, "tags", nil, "tags as --tags 'tag1=value1,tag2=value2' or multiple --tags ... options")
117+
tagAdd.MarkFlagRequired("tags")
118+
tagRm.Flags().StringSliceVar(&tagFlags.tags, "tags", nil, "tags as --tags 'tag1,tag2' or multiple --tags ... options")
119+
tagRm.MarkFlagRequired("tags")
120+
initVersionsConfig(tagRoot.PersistentFlags())
121+
tagRoot.AddCommand(tagAdd, tagRm)
122+
rootCmd.AddCommand(tagRoot)
123+
}
124+
125+
var tagFlags struct {
126+
tags []string
127+
}

0 commit comments

Comments
 (0)