diff --git a/Gopkg.lock b/Gopkg.lock index be55a51c54..ac561530b1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -26,10 +26,11 @@ revision = "de5bf2ad457846296e2031421a34e2568e304e35" [[projects]] - digest = "1:c13498cd03b22da5795048d7c64ac4ae8e24be6eea76684652635195f23fa36c" + digest = "1:5709ee3e36a5176373df316c5b8039283fde024caca12441aa9fed4d37e34e3b" name = "github.com/aws/aws-sdk-go" packages = [ "aws", + "aws/arn", "aws/awserr", "aws/awsutil", "aws/client", @@ -53,12 +54,15 @@ "internal/sdkuri", "internal/shareddefaults", "private/protocol", + "private/protocol/json/jsonutil", + "private/protocol/jsonrpc", "private/protocol/query", "private/protocol/query/queryutil", "private/protocol/rest", "private/protocol/restxml", "private/protocol/xml/xmlutil", "service/elb", + "service/resourcegroupstaggingapi", "service/route53", "service/sts", ] @@ -819,9 +823,12 @@ analyzer-version = 1 input-imports = [ "github.com/aws/aws-sdk-go/aws", + "github.com/aws/aws-sdk-go/aws/arn", "github.com/aws/aws-sdk-go/aws/credentials", + "github.com/aws/aws-sdk-go/aws/ec2metadata", "github.com/aws/aws-sdk-go/aws/session", "github.com/aws/aws-sdk-go/service/elb", + "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi", "github.com/aws/aws-sdk-go/service/route53", "github.com/ghodss/yaml", "github.com/kevinburke/go-bindata", diff --git a/pkg/dns/aws/dns.go b/pkg/dns/aws/dns.go index f63e806d34..55731773b0 100644 --- a/pkg/dns/aws/dns.go +++ b/pkg/dns/aws/dns.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "strings" "sync" "github.com/sirupsen/logrus" @@ -9,10 +10,12 @@ import ( "github.com/openshift/cluster-ingress-operator/pkg/dns" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/ec2metadata" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/elb" + "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" "github.com/aws/aws-sdk-go/service/route53" ) @@ -33,11 +36,16 @@ var _ dns.Manager = &Manager{} type Manager struct { elb *elb.ELB route53 *route53.Route53 + tags *resourcegroupstaggingapi.ResourceGroupsTaggingAPI config Config - lock sync.RWMutex - // zones is a cache of all known DNS zones and their associated tags. - zones []*zoneWithTags + + // lock protects access to everything below. + lock sync.RWMutex + // publicZoneID is the public zone shared by all clusters. + publicZoneID string + // privateZoneID is the private zone owned by the cluster. + privateZoneID string // updatedRecords is a cache of records which have been created during the // life of this manager. The key is zoneID+domain+target. This is a quick hack // to minimize AWS API calls for now. @@ -87,85 +95,74 @@ func NewManager(config Config) (*Manager, error) { return &Manager{ elb: elb.New(sess, aws.NewConfig().WithRegion(region)), route53: route53.New(sess), - + // TODO: This API will only return hostedzone resources (which are global) + // when the region is forced to us-east-1. We don't yet understand why. + tags: resourcegroupstaggingapi.New(sess, aws.NewConfig().WithRegion("us-east-1")), config: config, - zones: []*zoneWithTags{}, updatedRecords: map[string]struct{}{}, }, nil } -type zoneWithTags struct { - zone *route53.HostedZone - tags []*route53.Tag -} - -// updateZoneCache caches all zones and their tags. -func (m *Manager) updateZoneCache() error { +// discoverZones finds the public and private zones to manage, setting the +// privateZoneID and publicZoneID fields. An error is returned if either zone +// can't be found. +func (m *Manager) discoverZones() error { m.lock.Lock() defer m.lock.Unlock() - // There's no reason to update this more than once as we're only interested in - // the zones scoped to this cluster. - if len(m.zones) > 0 { - return nil - } - - // Find and cache all zones and their tags. - // TODO: probably only need to store the two zones we care about. - zones := []*zoneWithTags{} - listedAllTags := true - f := func(resp *route53.ListHostedZonesOutput, lastPage bool) (shouldContinue bool) { - for _, zone := range resp.HostedZones { - tagsList, err := m.route53.ListTagsForResource(&route53.ListTagsForResourceInput{ - ResourceType: aws.String("hostedzone"), - ResourceId: zone.Id, - }) - if err != nil { - logrus.Errorf("failed to list tags for hosted zone %s: %v", zone.Id, err) - listedAllTags = false - return false + // Find the public zone, which is the non-private zone whose domain matches + // the cluster base domain. + if len(m.publicZoneID) == 0 { + f := func(resp *route53.ListHostedZonesOutput, lastPage bool) (shouldContinue bool) { + for _, zone := range resp.HostedZones { + if aws.StringValue(zone.Name) == m.config.BaseDomain && !aws.BoolValue(zone.Config.PrivateZone) { + m.publicZoneID = aws.StringValue(zone.Id) + return false + } } - zones = append(zones, &zoneWithTags{zone: zone, tags: tagsList.ResourceTagSet.Tags}) + return true } - return true - } - err := m.route53.ListHostedZonesPages(&route53.ListHostedZonesInput{}, f) - if err != nil { - return fmt.Errorf("failed to list hosted zones: %v", err) - } - if !listedAllTags { - return fmt.Errorf("failed to list all hosted zone tags") - } - - m.zones = zones - return nil -} - -// findClusterPublicZone finds the public zone with the base domain from config. -func (m *Manager) findClusterPublicZone() *route53.HostedZone { - m.lock.Lock() - defer m.lock.Unlock() - for _, zwt := range m.zones { - if aws.StringValue(zwt.zone.Name) == m.config.BaseDomain && !aws.BoolValue(zwt.zone.Config.PrivateZone) { - return zwt.zone + err := m.route53.ListHostedZonesPages(&route53.ListHostedZonesInput{}, f) + if err != nil { + return fmt.Errorf("failed to list hosted zones: %v", err) } + if len(m.publicZoneID) == 0 { + return fmt.Errorf("couldn't find public hosted zone for %q", m.config.BaseDomain) + } + logrus.Infof("using public zone %s", m.publicZoneID) } - return nil -} -// findClusterPrivateZone finds the private zone with the base domain and -// cluster ID from config. -func (m *Manager) findClusterPrivateZone() *route53.HostedZone { - m.lock.Lock() - defer m.lock.Unlock() - for _, zwt := range m.zones { - if aws.StringValue(zwt.zone.Name) == m.config.BaseDomain && aws.BoolValue(zwt.zone.Config.PrivateZone) { - for _, tag := range zwt.tags { - if aws.StringValue(tag.Key) == "openshiftClusterID" && aws.StringValue(tag.Value) == m.config.ClusterID { - return zwt.zone - } + // Find the private zone, which is the private zone whose openshiftClusterID tag + // value matches the cluster ID. + if len(m.privateZoneID) == 0 { + zones, err := m.tags.GetResources(&resourcegroupstaggingapi.GetResourcesInput{ + ResourceTypeFilters: []*string{aws.String("route53:hostedzone")}, + TagFilters: []*resourcegroupstaggingapi.TagFilter{ + { + Key: aws.String("openshiftClusterID"), + Values: []*string{aws.String(m.config.ClusterID)}, + }, + }, + }) + if err != nil { + return fmt.Errorf("failed to get tagged resources: %v", err) + } + for _, zone := range zones.ResourceTagMappingList { + zoneARN, err := arn.Parse(aws.StringValue(zone.ResourceARN)) + if err != nil { + return fmt.Errorf("failed to parse hostedzone ARN %q: %v", aws.StringValue(zone.ResourceARN), err) } + elems := strings.Split(zoneARN.Resource, "/") + if len(elems) != 2 || elems[0] != "hostedzone" { + return fmt.Errorf("got unexpected resource ARN: %v", zoneARN) + } + m.privateZoneID = elems[1] + break } + if len(m.privateZoneID) == 0 { + return fmt.Errorf("couldn't find private hosted zone for cluster id %q", m.config.ClusterID) + } + logrus.Infof("using private zone %s", m.privateZoneID) } return nil } @@ -182,18 +179,9 @@ func (m *Manager) EnsureAlias(domain, target string) error { } // Ensure the zone cache is up to date. - err := m.updateZoneCache() + err := m.discoverZones() if err != nil { - return fmt.Errorf("failed to update hosted zone cache: %v", err) - } - - publicZone := m.findClusterPublicZone() - privateZone := m.findClusterPrivateZone() - if publicZone == nil { - return fmt.Errorf("failed to find public zone for cluster") - } - if privateZone == nil { - return fmt.Errorf("failed to find private zone for cluster") + return fmt.Errorf("failed to discover hosted zones: %v", err) } // Find the target hosted zone of the load balancer attached to the service. @@ -219,7 +207,7 @@ func (m *Manager) EnsureAlias(domain, target string) error { // TODO: handle the caching/diff detection in a better way. m.lock.Lock() defer m.lock.Unlock() - for _, zoneID := range []string{aws.StringValue(publicZone.Id), aws.StringValue(privateZone.Id)} { + for _, zoneID := range []string{m.publicZoneID, m.privateZoneID} { key := zoneID + domain + target // Only process these once, for now. if _, exists := m.updatedRecords[key]; exists { diff --git a/vendor/github.com/aws/aws-sdk-go/aws/arn/arn.go b/vendor/github.com/aws/aws-sdk-go/aws/arn/arn.go new file mode 100644 index 0000000000..44aa125a18 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/arn/arn.go @@ -0,0 +1,86 @@ +// Package arn provides a parser for interacting with Amazon Resource Names. +package arn + +import ( + "errors" + "strings" +) + +const ( + arnDelimiter = ":" + arnSections = 6 + arnPrefix = "arn:" + + // zero-indexed + sectionPartition = 1 + sectionService = 2 + sectionRegion = 3 + sectionAccountID = 4 + sectionResource = 5 + + // errors + invalidPrefix = "arn: invalid prefix" + invalidSections = "arn: not enough sections" +) + +// ARN captures the individual fields of an Amazon Resource Name. +// See http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html for more information. +type ARN struct { + // The partition that the resource is in. For standard AWS regions, the partition is "aws". If you have resources in + // other partitions, the partition is "aws-partitionname". For example, the partition for resources in the China + // (Beijing) region is "aws-cn". + Partition string + + // The service namespace that identifies the AWS product (for example, Amazon S3, IAM, or Amazon RDS). For a list of + // namespaces, see + // http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-aws-service-namespaces. + Service string + + // The region the resource resides in. Note that the ARNs for some resources do not require a region, so this + // component might be omitted. + Region string + + // The ID of the AWS account that owns the resource, without the hyphens. For example, 123456789012. Note that the + // ARNs for some resources don't require an account number, so this component might be omitted. + AccountID string + + // The content of this part of the ARN varies by service. It often includes an indicator of the type of resource — + // for example, an IAM user or Amazon RDS database - followed by a slash (/) or a colon (:), followed by the + // resource name itself. Some services allows paths for resource names, as described in + // http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-paths. + Resource string +} + +// Parse parses an ARN into its constituent parts. +// +// Some example ARNs: +// arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment +// arn:aws:iam::123456789012:user/David +// arn:aws:rds:eu-west-1:123456789012:db:mysql-db +// arn:aws:s3:::my_corporate_bucket/exampleobject.png +func Parse(arn string) (ARN, error) { + if !strings.HasPrefix(arn, arnPrefix) { + return ARN{}, errors.New(invalidPrefix) + } + sections := strings.SplitN(arn, arnDelimiter, arnSections) + if len(sections) != arnSections { + return ARN{}, errors.New(invalidSections) + } + return ARN{ + Partition: sections[sectionPartition], + Service: sections[sectionService], + Region: sections[sectionRegion], + AccountID: sections[sectionAccountID], + Resource: sections[sectionResource], + }, nil +} + +// String returns the canonical representation of the ARN +func (arn ARN) String() string { + return arnPrefix + + arn.Partition + arnDelimiter + + arn.Service + arnDelimiter + + arn.Region + arnDelimiter + + arn.AccountID + arnDelimiter + + arn.Resource +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go new file mode 100644 index 0000000000..864fb6704b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go @@ -0,0 +1,296 @@ +// Package jsonutil provides JSON serialization of AWS requests and responses. +package jsonutil + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/private/protocol" +) + +var timeType = reflect.ValueOf(time.Time{}).Type() +var byteSliceType = reflect.ValueOf([]byte{}).Type() + +// BuildJSON builds a JSON string for a given object v. +func BuildJSON(v interface{}) ([]byte, error) { + var buf bytes.Buffer + + err := buildAny(reflect.ValueOf(v), &buf, "") + return buf.Bytes(), err +} + +func buildAny(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + origVal := value + value = reflect.Indirect(value) + if !value.IsValid() { + return nil + } + + vtype := value.Type() + + t := tag.Get("type") + if t == "" { + switch vtype.Kind() { + case reflect.Struct: + // also it can't be a time object + if value.Type() != timeType { + t = "structure" + } + case reflect.Slice: + // also it can't be a byte slice + if _, ok := value.Interface().([]byte); !ok { + t = "list" + } + case reflect.Map: + // cannot be a JSONValue map + if _, ok := value.Interface().(aws.JSONValue); !ok { + t = "map" + } + } + } + + switch t { + case "structure": + if field, ok := vtype.FieldByName("_"); ok { + tag = field.Tag + } + return buildStruct(value, buf, tag) + case "list": + return buildList(value, buf, tag) + case "map": + return buildMap(value, buf, tag) + default: + return buildScalar(origVal, buf, tag) + } +} + +func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + if !value.IsValid() { + return nil + } + + // unwrap payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := value.Type().FieldByName(payload) + tag = field.Tag + value = elemOf(value.FieldByName(payload)) + + if !value.IsValid() { + return nil + } + } + + buf.WriteByte('{') + + t := value.Type() + first := true + for i := 0; i < t.NumField(); i++ { + member := value.Field(i) + + // This allocates the most memory. + // Additionally, we cannot skip nil fields due to + // idempotency auto filling. + field := t.Field(i) + + if field.PkgPath != "" { + continue // ignore unexported fields + } + if field.Tag.Get("json") == "-" { + continue + } + if field.Tag.Get("location") != "" { + continue // ignore non-body elements + } + if field.Tag.Get("ignore") != "" { + continue + } + + if protocol.CanSetIdempotencyToken(member, field) { + token := protocol.GetIdempotencyToken() + member = reflect.ValueOf(&token) + } + + if (member.Kind() == reflect.Ptr || member.Kind() == reflect.Slice || member.Kind() == reflect.Map) && member.IsNil() { + continue // ignore unset fields + } + + if first { + first = false + } else { + buf.WriteByte(',') + } + + // figure out what this field is called + name := field.Name + if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + writeString(name, buf) + buf.WriteString(`:`) + + err := buildAny(member, buf, field.Tag) + if err != nil { + return err + } + + } + + buf.WriteString("}") + + return nil +} + +func buildList(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + buf.WriteString("[") + + for i := 0; i < value.Len(); i++ { + buildAny(value.Index(i), buf, "") + + if i < value.Len()-1 { + buf.WriteString(",") + } + } + + buf.WriteString("]") + + return nil +} + +type sortedValues []reflect.Value + +func (sv sortedValues) Len() int { return len(sv) } +func (sv sortedValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } +func (sv sortedValues) Less(i, j int) bool { return sv[i].String() < sv[j].String() } + +func buildMap(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + buf.WriteString("{") + + sv := sortedValues(value.MapKeys()) + sort.Sort(sv) + + for i, k := range sv { + if i > 0 { + buf.WriteByte(',') + } + + writeString(k.String(), buf) + buf.WriteString(`:`) + + buildAny(value.MapIndex(k), buf, "") + } + + buf.WriteString("}") + + return nil +} + +func buildScalar(v reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + // prevents allocation on the heap. + scratch := [64]byte{} + switch value := reflect.Indirect(v); value.Kind() { + case reflect.String: + writeString(value.String(), buf) + case reflect.Bool: + if value.Bool() { + buf.WriteString("true") + } else { + buf.WriteString("false") + } + case reflect.Int64: + buf.Write(strconv.AppendInt(scratch[:0], value.Int(), 10)) + case reflect.Float64: + f := value.Float() + if math.IsInf(f, 0) || math.IsNaN(f) { + return &json.UnsupportedValueError{Value: v, Str: strconv.FormatFloat(f, 'f', -1, 64)} + } + buf.Write(strconv.AppendFloat(scratch[:0], f, 'f', -1, 64)) + default: + switch converted := value.Interface().(type) { + case time.Time: + format := tag.Get("timestampFormat") + if len(format) == 0 { + format = protocol.UnixTimeFormatName + } + + ts := protocol.FormatTime(format, converted) + if format != protocol.UnixTimeFormatName { + ts = `"` + ts + `"` + } + + buf.WriteString(ts) + case []byte: + if !value.IsNil() { + buf.WriteByte('"') + if len(converted) < 1024 { + // for small buffers, using Encode directly is much faster. + dst := make([]byte, base64.StdEncoding.EncodedLen(len(converted))) + base64.StdEncoding.Encode(dst, converted) + buf.Write(dst) + } else { + // for large buffers, avoid unnecessary extra temporary + // buffer space. + enc := base64.NewEncoder(base64.StdEncoding, buf) + enc.Write(converted) + enc.Close() + } + buf.WriteByte('"') + } + case aws.JSONValue: + str, err := protocol.EncodeJSONValue(converted, protocol.QuotedEscape) + if err != nil { + return fmt.Errorf("unable to encode JSONValue, %v", err) + } + buf.WriteString(str) + default: + return fmt.Errorf("unsupported JSON value %v (%s)", value.Interface(), value.Type()) + } + } + return nil +} + +var hex = "0123456789abcdef" + +func writeString(s string, buf *bytes.Buffer) { + buf.WriteByte('"') + for i := 0; i < len(s); i++ { + if s[i] == '"' { + buf.WriteString(`\"`) + } else if s[i] == '\\' { + buf.WriteString(`\\`) + } else if s[i] == '\b' { + buf.WriteString(`\b`) + } else if s[i] == '\f' { + buf.WriteString(`\f`) + } else if s[i] == '\r' { + buf.WriteString(`\r`) + } else if s[i] == '\t' { + buf.WriteString(`\t`) + } else if s[i] == '\n' { + buf.WriteString(`\n`) + } else if s[i] < 32 { + buf.WriteString("\\u00") + buf.WriteByte(hex[s[i]>>4]) + buf.WriteByte(hex[s[i]&0xF]) + } else { + buf.WriteByte(s[i]) + } + } + buf.WriteByte('"') +} + +// Returns the reflection element of a value, if it is a pointer. +func elemOf(value reflect.Value) reflect.Value { + for value.Kind() == reflect.Ptr { + value = value.Elem() + } + return value +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go new file mode 100644 index 0000000000..b11f3ee45b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go @@ -0,0 +1,228 @@ +package jsonutil + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io" + "reflect" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/private/protocol" +) + +// UnmarshalJSON reads a stream and unmarshals the results in object v. +func UnmarshalJSON(v interface{}, stream io.Reader) error { + var out interface{} + + err := json.NewDecoder(stream).Decode(&out) + if err == io.EOF { + return nil + } else if err != nil { + return err + } + + return unmarshalAny(reflect.ValueOf(v), out, "") +} + +func unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error { + vtype := value.Type() + if vtype.Kind() == reflect.Ptr { + vtype = vtype.Elem() // check kind of actual element type + } + + t := tag.Get("type") + if t == "" { + switch vtype.Kind() { + case reflect.Struct: + // also it can't be a time object + if _, ok := value.Interface().(*time.Time); !ok { + t = "structure" + } + case reflect.Slice: + // also it can't be a byte slice + if _, ok := value.Interface().([]byte); !ok { + t = "list" + } + case reflect.Map: + // cannot be a JSONValue map + if _, ok := value.Interface().(aws.JSONValue); !ok { + t = "map" + } + } + } + + switch t { + case "structure": + if field, ok := vtype.FieldByName("_"); ok { + tag = field.Tag + } + return unmarshalStruct(value, data, tag) + case "list": + return unmarshalList(value, data, tag) + case "map": + return unmarshalMap(value, data, tag) + default: + return unmarshalScalar(value, data, tag) + } +} + +func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + mapData, ok := data.(map[string]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a structure (%#v)", data) + } + + t := value.Type() + if value.Kind() == reflect.Ptr { + if value.IsNil() { // create the structure if it's nil + s := reflect.New(value.Type().Elem()) + value.Set(s) + value = s + } + + value = value.Elem() + t = t.Elem() + } + + // unwrap any payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := t.FieldByName(payload) + return unmarshalAny(value.FieldByName(payload), data, field.Tag) + } + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + if field.PkgPath != "" { + continue // ignore unexported fields + } + + // figure out what this field is called + name := field.Name + if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + member := value.FieldByIndex(field.Index) + err := unmarshalAny(member, mapData[name], field.Tag) + if err != nil { + return err + } + } + return nil +} + +func unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + listData, ok := data.([]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a list (%#v)", data) + } + + if value.IsNil() { + l := len(listData) + value.Set(reflect.MakeSlice(value.Type(), l, l)) + } + + for i, c := range listData { + err := unmarshalAny(value.Index(i), c, "") + if err != nil { + return err + } + } + + return nil +} + +func unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + mapData, ok := data.(map[string]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a map (%#v)", data) + } + + if value.IsNil() { + value.Set(reflect.MakeMap(value.Type())) + } + + for k, v := range mapData { + kvalue := reflect.ValueOf(k) + vvalue := reflect.New(value.Type().Elem()).Elem() + + unmarshalAny(vvalue, v, "") + value.SetMapIndex(kvalue, vvalue) + } + + return nil +} + +func unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error { + + switch d := data.(type) { + case nil: + return nil // nothing to do here + case string: + switch value.Interface().(type) { + case *string: + value.Set(reflect.ValueOf(&d)) + case []byte: + b, err := base64.StdEncoding.DecodeString(d) + if err != nil { + return err + } + value.Set(reflect.ValueOf(b)) + case *time.Time: + format := tag.Get("timestampFormat") + if len(format) == 0 { + format = protocol.ISO8601TimeFormatName + } + + t, err := protocol.ParseTime(format, d) + if err != nil { + return err + } + value.Set(reflect.ValueOf(&t)) + case aws.JSONValue: + // No need to use escaping as the value is a non-quoted string. + v, err := protocol.DecodeJSONValue(d, protocol.NoEscape) + if err != nil { + return err + } + value.Set(reflect.ValueOf(v)) + default: + return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type()) + } + case float64: + switch value.Interface().(type) { + case *int64: + di := int64(d) + value.Set(reflect.ValueOf(&di)) + case *float64: + value.Set(reflect.ValueOf(&d)) + case *time.Time: + // Time unmarshaled from a float64 can only be epoch seconds + t := time.Unix(int64(d), 0).UTC() + value.Set(reflect.ValueOf(&t)) + default: + return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type()) + } + case bool: + switch value.Interface().(type) { + case *bool: + value.Set(reflect.ValueOf(&d)) + default: + return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type()) + } + default: + return fmt.Errorf("unsupported JSON value (%v)", data) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go new file mode 100644 index 0000000000..9a7ba27ad5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go @@ -0,0 +1,115 @@ +// Package jsonrpc provides JSON RPC utilities for serialization of AWS +// requests and responses. +package jsonrpc + +//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/json.json build_test.go +//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/json.json unmarshal_test.go + +import ( + "encoding/json" + "io" + "strings" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil" + "github.com/aws/aws-sdk-go/private/protocol/rest" +) + +var emptyJSON = []byte("{}") + +// BuildHandler is a named request handler for building jsonrpc protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.jsonrpc.Build", Fn: Build} + +// UnmarshalHandler is a named request handler for unmarshaling jsonrpc protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.jsonrpc.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling jsonrpc protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.jsonrpc.UnmarshalMeta", Fn: UnmarshalMeta} + +// UnmarshalErrorHandler is a named request handler for unmarshaling jsonrpc protocol request errors +var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.jsonrpc.UnmarshalError", Fn: UnmarshalError} + +// Build builds a JSON payload for a JSON RPC request. +func Build(req *request.Request) { + var buf []byte + var err error + if req.ParamsFilled() { + buf, err = jsonutil.BuildJSON(req.Params) + if err != nil { + req.Error = awserr.New("SerializationError", "failed encoding JSON RPC request", err) + return + } + } else { + buf = emptyJSON + } + + if req.ClientInfo.TargetPrefix != "" || string(buf) != "{}" { + req.SetBufferBody(buf) + } + + if req.ClientInfo.TargetPrefix != "" { + target := req.ClientInfo.TargetPrefix + "." + req.Operation.Name + req.HTTPRequest.Header.Add("X-Amz-Target", target) + } + if req.ClientInfo.JSONVersion != "" { + jsonVersion := req.ClientInfo.JSONVersion + req.HTTPRequest.Header.Add("Content-Type", "application/x-amz-json-"+jsonVersion) + } +} + +// Unmarshal unmarshals a response for a JSON RPC service. +func Unmarshal(req *request.Request) { + defer req.HTTPResponse.Body.Close() + if req.DataFilled() { + err := jsonutil.UnmarshalJSON(req.Data, req.HTTPResponse.Body) + if err != nil { + req.Error = awserr.NewRequestFailure( + awserr.New("SerializationError", "failed decoding JSON RPC response", err), + req.HTTPResponse.StatusCode, + req.RequestID, + ) + } + } + return +} + +// UnmarshalMeta unmarshals headers from a response for a JSON RPC service. +func UnmarshalMeta(req *request.Request) { + rest.UnmarshalMeta(req) +} + +// UnmarshalError unmarshals an error response for a JSON RPC service. +func UnmarshalError(req *request.Request) { + defer req.HTTPResponse.Body.Close() + + var jsonErr jsonErrorResponse + err := json.NewDecoder(req.HTTPResponse.Body).Decode(&jsonErr) + if err == io.EOF { + req.Error = awserr.NewRequestFailure( + awserr.New("SerializationError", req.HTTPResponse.Status, nil), + req.HTTPResponse.StatusCode, + req.RequestID, + ) + return + } else if err != nil { + req.Error = awserr.NewRequestFailure( + awserr.New("SerializationError", "failed decoding JSON RPC error response", err), + req.HTTPResponse.StatusCode, + req.RequestID, + ) + return + } + + codes := strings.SplitN(jsonErr.Code, "#", 2) + req.Error = awserr.NewRequestFailure( + awserr.New(codes[len(codes)-1], jsonErr.Message, nil), + req.HTTPResponse.StatusCode, + req.RequestID, + ) +} + +type jsonErrorResponse struct { + Code string `json:"__type"` + Message string `json:"message"` +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/api.go b/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/api.go new file mode 100644 index 0000000000..351a636300 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/api.go @@ -0,0 +1,1311 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package resourcegroupstaggingapi + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/aws/request" +) + +const opGetResources = "GetResources" + +// GetResourcesRequest generates a "aws/request.Request" representing the +// client's request for the GetResources operation. The "output" return +// value will be populated with the request's response once the request completes +// successfully. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See GetResources for more information on using the GetResources +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the GetResourcesRequest method. +// req, resp := client.GetResourcesRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/GetResources +func (c *ResourceGroupsTaggingAPI) GetResourcesRequest(input *GetResourcesInput) (req *request.Request, output *GetResourcesOutput) { + op := &request.Operation{ + Name: opGetResources, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"PaginationToken"}, + OutputTokens: []string{"PaginationToken"}, + LimitToken: "ResourcesPerPage", + TruncationToken: "", + }, + } + + if input == nil { + input = &GetResourcesInput{} + } + + output = &GetResourcesOutput{} + req = c.newRequest(op, input, output) + return +} + +// GetResources API operation for AWS Resource Groups Tagging API. +// +// Returns all the tagged resources that are associated with the specified tags +// (keys and values) located in the specified region for the AWS account. The +// tags and the resource types that you specify in the request are known as +// filters. The response includes all tags that are associated with the requested +// resources. If no filter is provided, this action returns a paginated resource +// list with the associated tags. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Resource Groups Tagging API's +// API operation GetResources for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInvalidParameterException "InvalidParameterException" +// A parameter is missing or a malformed string or invalid or out-of-range value +// was supplied for the request parameter. +// +// * ErrCodeThrottledException "ThrottledException" +// The request was denied to limit the frequency of submitted requests. +// +// * ErrCodeInternalServiceException "InternalServiceException" +// The request processing failed because of an unknown error, exception, or +// failure. You can retry the request. +// +// * ErrCodePaginationTokenExpiredException "PaginationTokenExpiredException" +// A PaginationToken is valid for a maximum of 15 minutes. Your request was +// denied because the specified PaginationToken has expired. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/GetResources +func (c *ResourceGroupsTaggingAPI) GetResources(input *GetResourcesInput) (*GetResourcesOutput, error) { + req, out := c.GetResourcesRequest(input) + return out, req.Send() +} + +// GetResourcesWithContext is the same as GetResources with the addition of +// the ability to pass a context and additional request options. +// +// See GetResources for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *ResourceGroupsTaggingAPI) GetResourcesWithContext(ctx aws.Context, input *GetResourcesInput, opts ...request.Option) (*GetResourcesOutput, error) { + req, out := c.GetResourcesRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// GetResourcesPages iterates over the pages of a GetResources operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See GetResources method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a GetResources operation. +// pageNum := 0 +// err := client.GetResourcesPages(params, +// func(page *GetResourcesOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *ResourceGroupsTaggingAPI) GetResourcesPages(input *GetResourcesInput, fn func(*GetResourcesOutput, bool) bool) error { + return c.GetResourcesPagesWithContext(aws.BackgroundContext(), input, fn) +} + +// GetResourcesPagesWithContext same as GetResourcesPages except +// it takes a Context and allows setting request options on the pages. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *ResourceGroupsTaggingAPI) GetResourcesPagesWithContext(ctx aws.Context, input *GetResourcesInput, fn func(*GetResourcesOutput, bool) bool, opts ...request.Option) error { + p := request.Pagination{ + NewRequest: func() (*request.Request, error) { + var inCpy *GetResourcesInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.GetResourcesRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + + cont := true + for p.Next() && cont { + cont = fn(p.Page().(*GetResourcesOutput), !p.HasNextPage()) + } + return p.Err() +} + +const opGetTagKeys = "GetTagKeys" + +// GetTagKeysRequest generates a "aws/request.Request" representing the +// client's request for the GetTagKeys operation. The "output" return +// value will be populated with the request's response once the request completes +// successfully. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See GetTagKeys for more information on using the GetTagKeys +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the GetTagKeysRequest method. +// req, resp := client.GetTagKeysRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/GetTagKeys +func (c *ResourceGroupsTaggingAPI) GetTagKeysRequest(input *GetTagKeysInput) (req *request.Request, output *GetTagKeysOutput) { + op := &request.Operation{ + Name: opGetTagKeys, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"PaginationToken"}, + OutputTokens: []string{"PaginationToken"}, + LimitToken: "", + TruncationToken: "", + }, + } + + if input == nil { + input = &GetTagKeysInput{} + } + + output = &GetTagKeysOutput{} + req = c.newRequest(op, input, output) + return +} + +// GetTagKeys API operation for AWS Resource Groups Tagging API. +// +// Returns all tag keys in the specified region for the AWS account. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Resource Groups Tagging API's +// API operation GetTagKeys for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInvalidParameterException "InvalidParameterException" +// A parameter is missing or a malformed string or invalid or out-of-range value +// was supplied for the request parameter. +// +// * ErrCodeThrottledException "ThrottledException" +// The request was denied to limit the frequency of submitted requests. +// +// * ErrCodeInternalServiceException "InternalServiceException" +// The request processing failed because of an unknown error, exception, or +// failure. You can retry the request. +// +// * ErrCodePaginationTokenExpiredException "PaginationTokenExpiredException" +// A PaginationToken is valid for a maximum of 15 minutes. Your request was +// denied because the specified PaginationToken has expired. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/GetTagKeys +func (c *ResourceGroupsTaggingAPI) GetTagKeys(input *GetTagKeysInput) (*GetTagKeysOutput, error) { + req, out := c.GetTagKeysRequest(input) + return out, req.Send() +} + +// GetTagKeysWithContext is the same as GetTagKeys with the addition of +// the ability to pass a context and additional request options. +// +// See GetTagKeys for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *ResourceGroupsTaggingAPI) GetTagKeysWithContext(ctx aws.Context, input *GetTagKeysInput, opts ...request.Option) (*GetTagKeysOutput, error) { + req, out := c.GetTagKeysRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// GetTagKeysPages iterates over the pages of a GetTagKeys operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See GetTagKeys method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a GetTagKeys operation. +// pageNum := 0 +// err := client.GetTagKeysPages(params, +// func(page *GetTagKeysOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *ResourceGroupsTaggingAPI) GetTagKeysPages(input *GetTagKeysInput, fn func(*GetTagKeysOutput, bool) bool) error { + return c.GetTagKeysPagesWithContext(aws.BackgroundContext(), input, fn) +} + +// GetTagKeysPagesWithContext same as GetTagKeysPages except +// it takes a Context and allows setting request options on the pages. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *ResourceGroupsTaggingAPI) GetTagKeysPagesWithContext(ctx aws.Context, input *GetTagKeysInput, fn func(*GetTagKeysOutput, bool) bool, opts ...request.Option) error { + p := request.Pagination{ + NewRequest: func() (*request.Request, error) { + var inCpy *GetTagKeysInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.GetTagKeysRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + + cont := true + for p.Next() && cont { + cont = fn(p.Page().(*GetTagKeysOutput), !p.HasNextPage()) + } + return p.Err() +} + +const opGetTagValues = "GetTagValues" + +// GetTagValuesRequest generates a "aws/request.Request" representing the +// client's request for the GetTagValues operation. The "output" return +// value will be populated with the request's response once the request completes +// successfully. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See GetTagValues for more information on using the GetTagValues +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the GetTagValuesRequest method. +// req, resp := client.GetTagValuesRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/GetTagValues +func (c *ResourceGroupsTaggingAPI) GetTagValuesRequest(input *GetTagValuesInput) (req *request.Request, output *GetTagValuesOutput) { + op := &request.Operation{ + Name: opGetTagValues, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"PaginationToken"}, + OutputTokens: []string{"PaginationToken"}, + LimitToken: "", + TruncationToken: "", + }, + } + + if input == nil { + input = &GetTagValuesInput{} + } + + output = &GetTagValuesOutput{} + req = c.newRequest(op, input, output) + return +} + +// GetTagValues API operation for AWS Resource Groups Tagging API. +// +// Returns all tag values for the specified key in the specified region for +// the AWS account. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Resource Groups Tagging API's +// API operation GetTagValues for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInvalidParameterException "InvalidParameterException" +// A parameter is missing or a malformed string or invalid or out-of-range value +// was supplied for the request parameter. +// +// * ErrCodeThrottledException "ThrottledException" +// The request was denied to limit the frequency of submitted requests. +// +// * ErrCodeInternalServiceException "InternalServiceException" +// The request processing failed because of an unknown error, exception, or +// failure. You can retry the request. +// +// * ErrCodePaginationTokenExpiredException "PaginationTokenExpiredException" +// A PaginationToken is valid for a maximum of 15 minutes. Your request was +// denied because the specified PaginationToken has expired. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/GetTagValues +func (c *ResourceGroupsTaggingAPI) GetTagValues(input *GetTagValuesInput) (*GetTagValuesOutput, error) { + req, out := c.GetTagValuesRequest(input) + return out, req.Send() +} + +// GetTagValuesWithContext is the same as GetTagValues with the addition of +// the ability to pass a context and additional request options. +// +// See GetTagValues for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *ResourceGroupsTaggingAPI) GetTagValuesWithContext(ctx aws.Context, input *GetTagValuesInput, opts ...request.Option) (*GetTagValuesOutput, error) { + req, out := c.GetTagValuesRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// GetTagValuesPages iterates over the pages of a GetTagValues operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See GetTagValues method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a GetTagValues operation. +// pageNum := 0 +// err := client.GetTagValuesPages(params, +// func(page *GetTagValuesOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *ResourceGroupsTaggingAPI) GetTagValuesPages(input *GetTagValuesInput, fn func(*GetTagValuesOutput, bool) bool) error { + return c.GetTagValuesPagesWithContext(aws.BackgroundContext(), input, fn) +} + +// GetTagValuesPagesWithContext same as GetTagValuesPages except +// it takes a Context and allows setting request options on the pages. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *ResourceGroupsTaggingAPI) GetTagValuesPagesWithContext(ctx aws.Context, input *GetTagValuesInput, fn func(*GetTagValuesOutput, bool) bool, opts ...request.Option) error { + p := request.Pagination{ + NewRequest: func() (*request.Request, error) { + var inCpy *GetTagValuesInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.GetTagValuesRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + + cont := true + for p.Next() && cont { + cont = fn(p.Page().(*GetTagValuesOutput), !p.HasNextPage()) + } + return p.Err() +} + +const opTagResources = "TagResources" + +// TagResourcesRequest generates a "aws/request.Request" representing the +// client's request for the TagResources operation. The "output" return +// value will be populated with the request's response once the request completes +// successfully. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See TagResources for more information on using the TagResources +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the TagResourcesRequest method. +// req, resp := client.TagResourcesRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/TagResources +func (c *ResourceGroupsTaggingAPI) TagResourcesRequest(input *TagResourcesInput) (req *request.Request, output *TagResourcesOutput) { + op := &request.Operation{ + Name: opTagResources, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &TagResourcesInput{} + } + + output = &TagResourcesOutput{} + req = c.newRequest(op, input, output) + return +} + +// TagResources API operation for AWS Resource Groups Tagging API. +// +// Applies one or more tags to the specified resources. Note the following: +// +// * Not all resources can have tags. For a list of resources that support +// tagging, see Supported Resources (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/supported-resources.html) +// in the AWS Resource Groups and Tag Editor User Guide. +// +// * Each resource can have up to 50 tags. For other limits, see Tag Restrictions +// (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#tag-restrictions) +// in the Amazon EC2 User Guide for Linux Instances. +// +// * You can only tag resources that are located in the specified region +// for the AWS account. +// +// * To add tags to a resource, you need the necessary permissions for the +// service that the resource belongs to as well as permissions for adding +// tags. For more information, see Obtaining Permissions for Tagging (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/obtaining-permissions-for-tagging.html) +// in the AWS Resource Groups and Tag Editor User Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Resource Groups Tagging API's +// API operation TagResources for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInvalidParameterException "InvalidParameterException" +// A parameter is missing or a malformed string or invalid or out-of-range value +// was supplied for the request parameter. +// +// * ErrCodeThrottledException "ThrottledException" +// The request was denied to limit the frequency of submitted requests. +// +// * ErrCodeInternalServiceException "InternalServiceException" +// The request processing failed because of an unknown error, exception, or +// failure. You can retry the request. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/TagResources +func (c *ResourceGroupsTaggingAPI) TagResources(input *TagResourcesInput) (*TagResourcesOutput, error) { + req, out := c.TagResourcesRequest(input) + return out, req.Send() +} + +// TagResourcesWithContext is the same as TagResources with the addition of +// the ability to pass a context and additional request options. +// +// See TagResources for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *ResourceGroupsTaggingAPI) TagResourcesWithContext(ctx aws.Context, input *TagResourcesInput, opts ...request.Option) (*TagResourcesOutput, error) { + req, out := c.TagResourcesRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opUntagResources = "UntagResources" + +// UntagResourcesRequest generates a "aws/request.Request" representing the +// client's request for the UntagResources operation. The "output" return +// value will be populated with the request's response once the request completes +// successfully. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See UntagResources for more information on using the UntagResources +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the UntagResourcesRequest method. +// req, resp := client.UntagResourcesRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/UntagResources +func (c *ResourceGroupsTaggingAPI) UntagResourcesRequest(input *UntagResourcesInput) (req *request.Request, output *UntagResourcesOutput) { + op := &request.Operation{ + Name: opUntagResources, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &UntagResourcesInput{} + } + + output = &UntagResourcesOutput{} + req = c.newRequest(op, input, output) + return +} + +// UntagResources API operation for AWS Resource Groups Tagging API. +// +// Removes the specified tags from the specified resources. When you specify +// a tag key, the action removes both that key and its associated value. The +// operation succeeds even if you attempt to remove tags from a resource that +// were already removed. Note the following: +// +// * To remove tags from a resource, you need the necessary permissions for +// the service that the resource belongs to as well as permissions for removing +// tags. For more information, see Obtaining Permissions for Tagging (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/obtaining-permissions-for-tagging.html) +// in the AWS Resource Groups and Tag Editor User Guide. +// +// * You can only tag resources that are located in the specified region +// for the AWS account. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Resource Groups Tagging API's +// API operation UntagResources for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInvalidParameterException "InvalidParameterException" +// A parameter is missing or a malformed string or invalid or out-of-range value +// was supplied for the request parameter. +// +// * ErrCodeThrottledException "ThrottledException" +// The request was denied to limit the frequency of submitted requests. +// +// * ErrCodeInternalServiceException "InternalServiceException" +// The request processing failed because of an unknown error, exception, or +// failure. You can retry the request. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26/UntagResources +func (c *ResourceGroupsTaggingAPI) UntagResources(input *UntagResourcesInput) (*UntagResourcesOutput, error) { + req, out := c.UntagResourcesRequest(input) + return out, req.Send() +} + +// UntagResourcesWithContext is the same as UntagResources with the addition of +// the ability to pass a context and additional request options. +// +// See UntagResources for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *ResourceGroupsTaggingAPI) UntagResourcesWithContext(ctx aws.Context, input *UntagResourcesInput, opts ...request.Option) (*UntagResourcesOutput, error) { + req, out := c.UntagResourcesRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// Details of the common errors that all actions return. +type FailureInfo struct { + _ struct{} `type:"structure"` + + // The code of the common error. Valid values include InternalServiceException, + // InvalidParameterException, and any valid error code returned by the AWS service + // that hosts the resource that you want to tag. + ErrorCode *string `type:"string" enum:"ErrorCode"` + + // The message of the common error. + ErrorMessage *string `type:"string"` + + // The HTTP status code of the common error. + StatusCode *int64 `type:"integer"` +} + +// String returns the string representation +func (s FailureInfo) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s FailureInfo) GoString() string { + return s.String() +} + +// SetErrorCode sets the ErrorCode field's value. +func (s *FailureInfo) SetErrorCode(v string) *FailureInfo { + s.ErrorCode = &v + return s +} + +// SetErrorMessage sets the ErrorMessage field's value. +func (s *FailureInfo) SetErrorMessage(v string) *FailureInfo { + s.ErrorMessage = &v + return s +} + +// SetStatusCode sets the StatusCode field's value. +func (s *FailureInfo) SetStatusCode(v int64) *FailureInfo { + s.StatusCode = &v + return s +} + +type GetResourcesInput struct { + _ struct{} `type:"structure"` + + // A string that indicates that additional data is available. Leave this value + // empty for your initial request. If the response includes a PaginationToken, + // use that string for this value to request an additional page of data. + PaginationToken *string `type:"string"` + + // The constraints on the resources that you want returned. The format of each + // resource type is service[:resourceType]. For example, specifying a resource + // type of ec2 returns all tagged Amazon EC2 resources (which includes tagged + // EC2 instances). Specifying a resource type of ec2:instance returns only EC2 + // instances. + // + // The string for each service name and resource type is the same as that embedded + // in a resource's Amazon Resource Name (ARN). Consult the AWS General Reference + // for the following: + // + // * For a list of service name strings, see AWS Service Namespaces (http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-aws-service-namespaces). + // + // * For resource type strings, see Example ARNs (http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-syntax). + // + // * For more information about ARNs, see Amazon Resource Names (ARNs) and + // AWS Service Namespaces (http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). + ResourceTypeFilters []*string `type:"list"` + + // A limit that restricts the number of resources returned by GetResources in + // paginated output. You can set ResourcesPerPage to a minimum of 1 item and + // the maximum of 50 items. + ResourcesPerPage *int64 `type:"integer"` + + // A list of tags (keys and values). A request can include up to 50 keys, and + // each key can include up to 20 values. + // + // If you specify multiple filters connected by an AND operator in a single + // request, the response returns only those resources that are associated with + // every specified filter. + // + // If you specify multiple filters connected by an OR operator in a single request, + // the response returns all resources that are associated with at least one + // or possibly more of the specified filters. + TagFilters []*TagFilter `type:"list"` + + // A limit that restricts the number of tags (key and value pairs) returned + // by GetResources in paginated output. A resource with no tags is counted as + // having one tag (one key and value pair). + // + // GetResources does not split a resource and its associated tags across pages. + // If the specified TagsPerPage would cause such a break, a PaginationToken + // is returned in place of the affected resource and its tags. Use that token + // in another request to get the remaining data. For example, if you specify + // a TagsPerPage of 100 and the account has 22 resources with 10 tags each (meaning + // that each resource has 10 key and value pairs), the output will consist of + // 3 pages, with the first page displaying the first 10 resources, each with + // its 10 tags, the second page displaying the next 10 resources each with its + // 10 tags, and the third page displaying the remaining 2 resources, each with + // its 10 tags. + // + // You can set TagsPerPage + TagsPerPage *int64 `type:"integer"` +} + +// String returns the string representation +func (s GetResourcesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetResourcesInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetResourcesInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetResourcesInput"} + if s.TagFilters != nil { + for i, v := range s.TagFilters { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "TagFilters", i), err.(request.ErrInvalidParams)) + } + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetPaginationToken sets the PaginationToken field's value. +func (s *GetResourcesInput) SetPaginationToken(v string) *GetResourcesInput { + s.PaginationToken = &v + return s +} + +// SetResourceTypeFilters sets the ResourceTypeFilters field's value. +func (s *GetResourcesInput) SetResourceTypeFilters(v []*string) *GetResourcesInput { + s.ResourceTypeFilters = v + return s +} + +// SetResourcesPerPage sets the ResourcesPerPage field's value. +func (s *GetResourcesInput) SetResourcesPerPage(v int64) *GetResourcesInput { + s.ResourcesPerPage = &v + return s +} + +// SetTagFilters sets the TagFilters field's value. +func (s *GetResourcesInput) SetTagFilters(v []*TagFilter) *GetResourcesInput { + s.TagFilters = v + return s +} + +// SetTagsPerPage sets the TagsPerPage field's value. +func (s *GetResourcesInput) SetTagsPerPage(v int64) *GetResourcesInput { + s.TagsPerPage = &v + return s +} + +type GetResourcesOutput struct { + _ struct{} `type:"structure"` + + // A string that indicates that the response contains more data than can be + // returned in a single response. To receive additional data, specify this string + // for the PaginationToken value in a subsequent request. + PaginationToken *string `type:"string"` + + // A list of resource ARNs and the tags (keys and values) associated with each. + ResourceTagMappingList []*ResourceTagMapping `type:"list"` +} + +// String returns the string representation +func (s GetResourcesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetResourcesOutput) GoString() string { + return s.String() +} + +// SetPaginationToken sets the PaginationToken field's value. +func (s *GetResourcesOutput) SetPaginationToken(v string) *GetResourcesOutput { + s.PaginationToken = &v + return s +} + +// SetResourceTagMappingList sets the ResourceTagMappingList field's value. +func (s *GetResourcesOutput) SetResourceTagMappingList(v []*ResourceTagMapping) *GetResourcesOutput { + s.ResourceTagMappingList = v + return s +} + +type GetTagKeysInput struct { + _ struct{} `type:"structure"` + + // A string that indicates that additional data is available. Leave this value + // empty for your initial request. If the response includes a PaginationToken, + // use that string for this value to request an additional page of data. + PaginationToken *string `type:"string"` +} + +// String returns the string representation +func (s GetTagKeysInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetTagKeysInput) GoString() string { + return s.String() +} + +// SetPaginationToken sets the PaginationToken field's value. +func (s *GetTagKeysInput) SetPaginationToken(v string) *GetTagKeysInput { + s.PaginationToken = &v + return s +} + +type GetTagKeysOutput struct { + _ struct{} `type:"structure"` + + // A string that indicates that the response contains more data than can be + // returned in a single response. To receive additional data, specify this string + // for the PaginationToken value in a subsequent request. + PaginationToken *string `type:"string"` + + // A list of all tag keys in the AWS account. + TagKeys []*string `type:"list"` +} + +// String returns the string representation +func (s GetTagKeysOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetTagKeysOutput) GoString() string { + return s.String() +} + +// SetPaginationToken sets the PaginationToken field's value. +func (s *GetTagKeysOutput) SetPaginationToken(v string) *GetTagKeysOutput { + s.PaginationToken = &v + return s +} + +// SetTagKeys sets the TagKeys field's value. +func (s *GetTagKeysOutput) SetTagKeys(v []*string) *GetTagKeysOutput { + s.TagKeys = v + return s +} + +type GetTagValuesInput struct { + _ struct{} `type:"structure"` + + // The key for which you want to list all existing values in the specified region + // for the AWS account. + // + // Key is a required field + Key *string `min:"1" type:"string" required:"true"` + + // A string that indicates that additional data is available. Leave this value + // empty for your initial request. If the response includes a PaginationToken, + // use that string for this value to request an additional page of data. + PaginationToken *string `type:"string"` +} + +// String returns the string representation +func (s GetTagValuesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetTagValuesInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetTagValuesInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetTagValuesInput"} + if s.Key == nil { + invalidParams.Add(request.NewErrParamRequired("Key")) + } + if s.Key != nil && len(*s.Key) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Key", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetKey sets the Key field's value. +func (s *GetTagValuesInput) SetKey(v string) *GetTagValuesInput { + s.Key = &v + return s +} + +// SetPaginationToken sets the PaginationToken field's value. +func (s *GetTagValuesInput) SetPaginationToken(v string) *GetTagValuesInput { + s.PaginationToken = &v + return s +} + +type GetTagValuesOutput struct { + _ struct{} `type:"structure"` + + // A string that indicates that the response contains more data than can be + // returned in a single response. To receive additional data, specify this string + // for the PaginationToken value in a subsequent request. + PaginationToken *string `type:"string"` + + // A list of all tag values for the specified key in the AWS account. + TagValues []*string `type:"list"` +} + +// String returns the string representation +func (s GetTagValuesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetTagValuesOutput) GoString() string { + return s.String() +} + +// SetPaginationToken sets the PaginationToken field's value. +func (s *GetTagValuesOutput) SetPaginationToken(v string) *GetTagValuesOutput { + s.PaginationToken = &v + return s +} + +// SetTagValues sets the TagValues field's value. +func (s *GetTagValuesOutput) SetTagValues(v []*string) *GetTagValuesOutput { + s.TagValues = v + return s +} + +// A list of resource ARNs and the tags (keys and values) that are associated +// with each. +type ResourceTagMapping struct { + _ struct{} `type:"structure"` + + // An array of resource ARN(s). + ResourceARN *string `min:"1" type:"string"` + + // The tags that have been applied to one or more AWS resources. + Tags []*Tag `type:"list"` +} + +// String returns the string representation +func (s ResourceTagMapping) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ResourceTagMapping) GoString() string { + return s.String() +} + +// SetResourceARN sets the ResourceARN field's value. +func (s *ResourceTagMapping) SetResourceARN(v string) *ResourceTagMapping { + s.ResourceARN = &v + return s +} + +// SetTags sets the Tags field's value. +func (s *ResourceTagMapping) SetTags(v []*Tag) *ResourceTagMapping { + s.Tags = v + return s +} + +// The metadata that you apply to AWS resources to help you categorize and organize +// them. Each tag consists of a key and an optional value, both of which you +// define. For more information, see Tag Basics (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#tag-basics) +// in the Amazon EC2 User Guide for Linux Instances. +type Tag struct { + _ struct{} `type:"structure"` + + // One part of a key-value pair that make up a tag. A key is a general label + // that acts like a category for more specific tag values. + // + // Key is a required field + Key *string `min:"1" type:"string" required:"true"` + + // The optional part of a key-value pair that make up a tag. A value acts as + // a descriptor within a tag category (key). + // + // Value is a required field + Value *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s Tag) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Tag) GoString() string { + return s.String() +} + +// SetKey sets the Key field's value. +func (s *Tag) SetKey(v string) *Tag { + s.Key = &v + return s +} + +// SetValue sets the Value field's value. +func (s *Tag) SetValue(v string) *Tag { + s.Value = &v + return s +} + +// A list of tags (keys and values) that are used to specify the associated +// resources. +type TagFilter struct { + _ struct{} `type:"structure"` + + // One part of a key-value pair that make up a tag. A key is a general label + // that acts like a category for more specific tag values. + Key *string `min:"1" type:"string"` + + // The optional part of a key-value pair that make up a tag. A value acts as + // a descriptor within a tag category (key). + Values []*string `type:"list"` +} + +// String returns the string representation +func (s TagFilter) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TagFilter) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *TagFilter) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "TagFilter"} + if s.Key != nil && len(*s.Key) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Key", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetKey sets the Key field's value. +func (s *TagFilter) SetKey(v string) *TagFilter { + s.Key = &v + return s +} + +// SetValues sets the Values field's value. +func (s *TagFilter) SetValues(v []*string) *TagFilter { + s.Values = v + return s +} + +type TagResourcesInput struct { + _ struct{} `type:"structure"` + + // A list of ARNs. An ARN (Amazon Resource Name) uniquely identifies a resource. + // You can specify a minimum of 1 and a maximum of 20 ARNs (resources) to tag. + // An ARN can be set to a maximum of 1600 characters. For more information, + // see Amazon Resource Names (ARNs) and AWS Service Namespaces (http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) + // in the AWS General Reference. + // + // ResourceARNList is a required field + ResourceARNList []*string `min:"1" type:"list" required:"true"` + + // The tags that you want to add to the specified resources. A tag consists + // of a key and a value that you define. + // + // Tags is a required field + Tags map[string]*string `min:"1" type:"map" required:"true"` +} + +// String returns the string representation +func (s TagResourcesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TagResourcesInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *TagResourcesInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "TagResourcesInput"} + if s.ResourceARNList == nil { + invalidParams.Add(request.NewErrParamRequired("ResourceARNList")) + } + if s.ResourceARNList != nil && len(s.ResourceARNList) < 1 { + invalidParams.Add(request.NewErrParamMinLen("ResourceARNList", 1)) + } + if s.Tags == nil { + invalidParams.Add(request.NewErrParamRequired("Tags")) + } + if s.Tags != nil && len(s.Tags) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Tags", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetResourceARNList sets the ResourceARNList field's value. +func (s *TagResourcesInput) SetResourceARNList(v []*string) *TagResourcesInput { + s.ResourceARNList = v + return s +} + +// SetTags sets the Tags field's value. +func (s *TagResourcesInput) SetTags(v map[string]*string) *TagResourcesInput { + s.Tags = v + return s +} + +type TagResourcesOutput struct { + _ struct{} `type:"structure"` + + // Details of resources that could not be tagged. An error code, status code, + // and error message are returned for each failed item. + FailedResourcesMap map[string]*FailureInfo `type:"map"` +} + +// String returns the string representation +func (s TagResourcesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TagResourcesOutput) GoString() string { + return s.String() +} + +// SetFailedResourcesMap sets the FailedResourcesMap field's value. +func (s *TagResourcesOutput) SetFailedResourcesMap(v map[string]*FailureInfo) *TagResourcesOutput { + s.FailedResourcesMap = v + return s +} + +type UntagResourcesInput struct { + _ struct{} `type:"structure"` + + // A list of ARNs. An ARN (Amazon Resource Name) uniquely identifies a resource. + // You can specify a minimum of 1 and a maximum of 20 ARNs (resources) to untag. + // An ARN can be set to a maximum of 1600 characters. For more information, + // see Amazon Resource Names (ARNs) and AWS Service Namespaces (http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) + // in the AWS General Reference. + // + // ResourceARNList is a required field + ResourceARNList []*string `min:"1" type:"list" required:"true"` + + // A list of the tag keys that you want to remove from the specified resources. + // + // TagKeys is a required field + TagKeys []*string `min:"1" type:"list" required:"true"` +} + +// String returns the string representation +func (s UntagResourcesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UntagResourcesInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UntagResourcesInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UntagResourcesInput"} + if s.ResourceARNList == nil { + invalidParams.Add(request.NewErrParamRequired("ResourceARNList")) + } + if s.ResourceARNList != nil && len(s.ResourceARNList) < 1 { + invalidParams.Add(request.NewErrParamMinLen("ResourceARNList", 1)) + } + if s.TagKeys == nil { + invalidParams.Add(request.NewErrParamRequired("TagKeys")) + } + if s.TagKeys != nil && len(s.TagKeys) < 1 { + invalidParams.Add(request.NewErrParamMinLen("TagKeys", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetResourceARNList sets the ResourceARNList field's value. +func (s *UntagResourcesInput) SetResourceARNList(v []*string) *UntagResourcesInput { + s.ResourceARNList = v + return s +} + +// SetTagKeys sets the TagKeys field's value. +func (s *UntagResourcesInput) SetTagKeys(v []*string) *UntagResourcesInput { + s.TagKeys = v + return s +} + +type UntagResourcesOutput struct { + _ struct{} `type:"structure"` + + // Details of resources that could not be untagged. An error code, status code, + // and error message are returned for each failed item. + FailedResourcesMap map[string]*FailureInfo `type:"map"` +} + +// String returns the string representation +func (s UntagResourcesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UntagResourcesOutput) GoString() string { + return s.String() +} + +// SetFailedResourcesMap sets the FailedResourcesMap field's value. +func (s *UntagResourcesOutput) SetFailedResourcesMap(v map[string]*FailureInfo) *UntagResourcesOutput { + s.FailedResourcesMap = v + return s +} + +const ( + // ErrorCodeInternalServiceException is a ErrorCode enum value + ErrorCodeInternalServiceException = "InternalServiceException" + + // ErrorCodeInvalidParameterException is a ErrorCode enum value + ErrorCodeInvalidParameterException = "InvalidParameterException" +) diff --git a/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/doc.go b/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/doc.go new file mode 100644 index 0000000000..45896e0ec8 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/doc.go @@ -0,0 +1,64 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +// Package resourcegroupstaggingapi provides the client and types for making API +// requests to AWS Resource Groups Tagging API. +// +// This guide describes the API operations for the resource groups tagging. +// +// A tag is a label that you assign to an AWS resource. A tag consists of a +// key and a value, both of which you define. For example, if you have two Amazon +// EC2 instances, you might assign both a tag key of "Stack." But the value +// of "Stack" might be "Testing" for one and "Production" for the other. +// +// Tagging can help you organize your resources and enables you to simplify +// resource management, access management and cost allocation. For more information +// about tagging, see Working with Tag Editor (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/tag-editor.html) +// and Working with Resource Groups (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/resource-groups.html). +// For more information about permissions you need to use the resource groups +// tagging APIs, see Obtaining Permissions for Resource Groups (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/obtaining-permissions-for-resource-groups.html) +// and Obtaining Permissions for Tagging (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/obtaining-permissions-for-tagging.html). +// +// You can use the resource groups tagging APIs to complete the following tasks: +// +// * Tag and untag supported resources located in the specified region for +// the AWS account +// +// * Use tag-based filters to search for resources located in the specified +// region for the AWS account +// +// * List all existing tag keys in the specified region for the AWS account +// +// * List all existing values for the specified key in the specified region +// for the AWS account +// +// Not all resources can have tags. For a lists of resources that you can tag, +// see Supported Resources (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/supported-resources.html) +// in the AWS Resource Groups and Tag Editor User Guide. +// +// To make full use of the resource groups tagging APIs, you might need additional +// IAM permissions, including permission to access the resources of individual +// services as well as permission to view and apply tags to those resources. +// For more information, see Obtaining Permissions for Tagging (http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/obtaining-permissions-for-tagging.html) +// in the AWS Resource Groups and Tag Editor User Guide. +// +// See https://docs.aws.amazon.com/goto/WebAPI/resourcegroupstaggingapi-2017-01-26 for more information on this service. +// +// See resourcegroupstaggingapi package documentation for more information. +// https://docs.aws.amazon.com/sdk-for-go/api/service/resourcegroupstaggingapi/ +// +// Using the Client +// +// To contact AWS Resource Groups Tagging API with the SDK use the New function to create +// a new service client. With that client you can make API requests to the service. +// These clients are safe to use concurrently. +// +// See the SDK's documentation for more information on how to use the SDK. +// https://docs.aws.amazon.com/sdk-for-go/api/ +// +// See aws.Config documentation for more information on configuring SDK clients. +// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config +// +// See the AWS Resource Groups Tagging API client ResourceGroupsTaggingAPI for more +// information on creating client for this service. +// https://docs.aws.amazon.com/sdk-for-go/api/service/resourcegroupstaggingapi/#New +package resourcegroupstaggingapi diff --git a/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/errors.go b/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/errors.go new file mode 100644 index 0000000000..89e5a769db --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/errors.go @@ -0,0 +1,33 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package resourcegroupstaggingapi + +const ( + + // ErrCodeInternalServiceException for service response error code + // "InternalServiceException". + // + // The request processing failed because of an unknown error, exception, or + // failure. You can retry the request. + ErrCodeInternalServiceException = "InternalServiceException" + + // ErrCodeInvalidParameterException for service response error code + // "InvalidParameterException". + // + // A parameter is missing or a malformed string or invalid or out-of-range value + // was supplied for the request parameter. + ErrCodeInvalidParameterException = "InvalidParameterException" + + // ErrCodePaginationTokenExpiredException for service response error code + // "PaginationTokenExpiredException". + // + // A PaginationToken is valid for a maximum of 15 minutes. Your request was + // denied because the specified PaginationToken has expired. + ErrCodePaginationTokenExpiredException = "PaginationTokenExpiredException" + + // ErrCodeThrottledException for service response error code + // "ThrottledException". + // + // The request was denied to limit the frequency of submitted requests. + ErrCodeThrottledException = "ThrottledException" +) diff --git a/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/service.go b/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/service.go new file mode 100644 index 0000000000..705db6b0d7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/service.go @@ -0,0 +1,97 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package resourcegroupstaggingapi + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" +) + +// ResourceGroupsTaggingAPI provides the API operation methods for making requests to +// AWS Resource Groups Tagging API. See this package's package overview docs +// for details on the service. +// +// ResourceGroupsTaggingAPI methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type ResourceGroupsTaggingAPI struct { + *client.Client +} + +// Used for custom client initialization logic +var initClient func(*client.Client) + +// Used for custom request initialization logic +var initRequest func(*request.Request) + +// Service information constants +const ( + ServiceName = "tagging" // Name of service. + EndpointsID = ServiceName // ID to lookup a service endpoint with. + ServiceID = "Resource Groups Tagging API" // ServiceID is a unique identifer of a specific service. +) + +// New creates a new instance of the ResourceGroupsTaggingAPI client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a ResourceGroupsTaggingAPI client from just a session. +// svc := resourcegroupstaggingapi.New(mySession) +// +// // Create a ResourceGroupsTaggingAPI client with additional configuration +// svc := resourcegroupstaggingapi.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func New(p client.ConfigProvider, cfgs ...*aws.Config) *ResourceGroupsTaggingAPI { + c := p.ClientConfig(EndpointsID, cfgs...) + return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *ResourceGroupsTaggingAPI { + svc := &ResourceGroupsTaggingAPI{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: ServiceName, + ServiceID: ServiceID, + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2017-01-26", + JSONVersion: "1.1", + TargetPrefix: "ResourceGroupsTaggingAPI_20170126", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + // Run custom client initialization if present + if initClient != nil { + initClient(svc.Client) + } + + return svc +} + +// newRequest creates a new request for a ResourceGroupsTaggingAPI operation and runs any +// custom request initialization. +func (c *ResourceGroupsTaggingAPI) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + // Run custom request initialization if present + if initRequest != nil { + initRequest(req) + } + + return req +}