github.com/aldelo/common@v1.5.1/wrapper/sns/sns.go (about)

     1  package sns
     2  
     3  /*
     4   * Copyright 2020-2023 Aldelo, LP
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   *     http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  // =================================================================================================================
    20  // AWS CREDENTIAL:
    21  //		use $> aws configure (to set aws access key and secret to target machine)
    22  //		Store AWS Access ID and Secret Key into Default Profile Using '$ aws configure' cli
    23  //
    24  // To Install & Setup AWS CLI on Host:
    25  //		1) https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html
    26  //				On Ubuntu, if host does not have zip and unzip:
    27  //					$> sudo apt install zip
    28  //					$> sudo apt install unzip
    29  //				On Ubuntu, to install AWS CLI v2:
    30  //					$> curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    31  //					$> unzip awscliv2.zip
    32  //					$> sudo ./aws/install
    33  //		2) $> aws configure set region awsRegionName --profile default
    34  // 		3) $> aws configure
    35  //				follow prompts to enter Access ID and Secret Key
    36  //
    37  // AWS Region Name Reference:
    38  //		us-west-2, us-east-1, ap-northeast-1, etc
    39  //		See: https://docs.aws.amazon.com/general/latest/gr/rande.html
    40  // =================================================================================================================
    41  
    42  import (
    43  	"context"
    44  	"errors"
    45  	util "github.com/aldelo/common"
    46  	awshttp2 "github.com/aldelo/common/wrapper/aws"
    47  	awsregion "github.com/aldelo/common/wrapper/aws/awsregion"
    48  	"github.com/aldelo/common/wrapper/sns/snsapplicationplatform"
    49  	"github.com/aldelo/common/wrapper/sns/snscreatetopicattribute"
    50  	"github.com/aldelo/common/wrapper/sns/snsendpointattribute"
    51  	"github.com/aldelo/common/wrapper/sns/snsgetsubscriptionattribute"
    52  	"github.com/aldelo/common/wrapper/sns/snsgettopicattribute"
    53  	"github.com/aldelo/common/wrapper/sns/snsplatformapplicationattribute"
    54  	"github.com/aldelo/common/wrapper/sns/snsprotocol"
    55  	"github.com/aldelo/common/wrapper/sns/snssubscribeattribute"
    56  	"github.com/aldelo/common/wrapper/xray"
    57  	"github.com/aws/aws-sdk-go/aws"
    58  	"github.com/aws/aws-sdk-go/aws/session"
    59  	"github.com/aws/aws-sdk-go/service/sns"
    60  	awsxray "github.com/aws/aws-xray-sdk-go/xray"
    61  	"net/http"
    62  	"time"
    63  )
    64  
    65  // ================================================================================================================
    66  // STRUCTS
    67  // ================================================================================================================
    68  
    69  // SNS struct encapsulates the AWS SNS access functionality
    70  type SNS struct {
    71  	// define the AWS region that SNS is located at
    72  	AwsRegion awsregion.AWSRegion
    73  
    74  	// custom http2 client options
    75  	HttpOptions *awshttp2.HttpClientSettings
    76  
    77  	// optional, sms sender name info
    78  	SMSSenderName string
    79  
    80  	// optional, indicates if sms message sent is transaction or promotional
    81  	SMSTransactional bool
    82  
    83  	// store sns client object
    84  	snsClient *sns.SNS
    85  
    86  	_parentSegment *xray.XRayParentSegment
    87  }
    88  
    89  // SubscribedTopic struct encapsulates the AWS SNS subscribed topic data
    90  type SubscribedTopic struct {
    91  	SubscriptionArn string
    92  	TopicArn        string
    93  	Protocol        snsprotocol.SNSProtocol
    94  	Endpoint        string
    95  	Owner           string
    96  }
    97  
    98  // ================================================================================================================
    99  // STRUCTS FUNCTIONS
   100  // ================================================================================================================
   101  
   102  // ----------------------------------------------------------------------------------------------------------------
   103  // utility functions
   104  // ----------------------------------------------------------------------------------------------------------------
   105  
   106  // Connect will establish a connection to the SNS service
   107  func (s *SNS) Connect(parentSegment ...*xray.XRayParentSegment) (err error) {
   108  	if xray.XRayServiceOn() {
   109  		if len(parentSegment) > 0 {
   110  			s._parentSegment = parentSegment[0]
   111  		}
   112  
   113  		seg := xray.NewSegment("SNS-Connect", s._parentSegment)
   114  		defer seg.Close()
   115  		defer func() {
   116  			_ = seg.Seg.AddMetadata("SNS-AWS-Region", s.AwsRegion)
   117  			_ = seg.Seg.AddMetadata("SNS-SMS-Sender-Name", s.SMSSenderName)
   118  			_ = seg.Seg.AddMetadata("SNS-SMS-Transactional", s.SMSTransactional)
   119  
   120  			if err != nil {
   121  				_ = seg.Seg.AddError(err)
   122  			}
   123  		}()
   124  
   125  		err = s.connectInternal()
   126  
   127  		if err == nil {
   128  			awsxray.AWS(s.snsClient.Client)
   129  		}
   130  
   131  		return err
   132  	} else {
   133  		return s.connectInternal()
   134  	}
   135  }
   136  
   137  // Connect will establish a connection to the SNS service
   138  func (s *SNS) connectInternal() error {
   139  	// clean up prior object
   140  	s.snsClient = nil
   141  
   142  	if !s.AwsRegion.Valid() || s.AwsRegion == awsregion.UNKNOWN {
   143  		return errors.New("Connect To SNS Failed: (AWS Session Error) " + "Region is Required")
   144  	}
   145  
   146  	// create custom http2 client if needed
   147  	var httpCli *http.Client
   148  	var httpErr error
   149  
   150  	if s.HttpOptions == nil {
   151  		s.HttpOptions = new(awshttp2.HttpClientSettings)
   152  	}
   153  
   154  	// use custom http2 client
   155  	h2 := &awshttp2.AwsHttp2Client{
   156  		Options: s.HttpOptions,
   157  	}
   158  
   159  	if httpCli, httpErr = h2.NewHttp2Client(); httpErr != nil {
   160  		return errors.New("Connect to SNS Failed: (AWS Session Error) " + "Create Custom Http2 Client Errored = " + httpErr.Error())
   161  	}
   162  
   163  	// establish aws session connection and keep session object in struct
   164  	if sess, err := session.NewSession(
   165  		&aws.Config{
   166  			Region:     aws.String(s.AwsRegion.Key()),
   167  			HTTPClient: httpCli,
   168  		}); err != nil {
   169  		// aws session error
   170  		return errors.New("Connect To SNS Failed: (AWS Session Error) " + err.Error())
   171  	} else {
   172  		// create cached objects for shared use
   173  		s.snsClient = sns.New(sess)
   174  
   175  		if s.snsClient == nil {
   176  			return errors.New("Connect To SNS Client Failed: (New SNS Client Connection) " + "Connection Object Nil")
   177  		}
   178  
   179  		// session stored to struct
   180  		return nil
   181  	}
   182  }
   183  
   184  // Disconnect will disjoin from aws session by clearing it
   185  func (s *SNS) Disconnect() {
   186  	s.snsClient = nil
   187  }
   188  
   189  // UpdateParentSegment updates this struct's xray parent segment, if no parent segment, set nil
   190  func (s *SNS) UpdateParentSegment(parentSegment *xray.XRayParentSegment) {
   191  	s._parentSegment = parentSegment
   192  }
   193  
   194  // ----------------------------------------------------------------------------------------------------------------
   195  // internal helper methods
   196  // ----------------------------------------------------------------------------------------------------------------
   197  
   198  // toAwsCreateTopicAttributes will convert from strongly typed to aws accepted map
   199  func (s *SNS) toAwsCreateTopicAttributes(attributes map[snscreatetopicattribute.SNSCreateTopicAttribute]string) (newMap map[string]*string) {
   200  	// validate
   201  	if attributes == nil {
   202  		return nil
   203  	}
   204  
   205  	// make map
   206  	newMap = make(map[string]*string)
   207  
   208  	for k, v := range attributes {
   209  		if k.Valid() && k != snscreatetopicattribute.UNKNOWN {
   210  			newMap[k.Key()] = aws.String(v)
   211  		}
   212  	}
   213  
   214  	return newMap
   215  }
   216  
   217  // fromAwsCreateTopicAttributes will convert from aws map to strongly typed map
   218  func (s *SNS) fromAwsCreateTopicAttributes(attributes map[string]*string) (newMap map[snscreatetopicattribute.SNSCreateTopicAttribute]string) {
   219  	// validate
   220  	if attributes == nil {
   221  		return nil
   222  	}
   223  
   224  	// make map
   225  	newMap = make(map[snscreatetopicattribute.SNSCreateTopicAttribute]string)
   226  	var conv snscreatetopicattribute.SNSCreateTopicAttribute
   227  
   228  	for k, v := range attributes {
   229  		if util.LenTrim(k) > 0 {
   230  			v1 := aws.StringValue(v)
   231  
   232  			if k1, err := conv.ParseByKey(k); err == nil {
   233  				newMap[k1] = v1
   234  			}
   235  		}
   236  	}
   237  
   238  	return newMap
   239  }
   240  
   241  // toAwsGetTopicAttributes will convert from strongly typed to aws accepted map
   242  func (s *SNS) toAwsGetTopicAttributes(attributes map[snsgettopicattribute.SNSGetTopicAttribute]string) (newMap map[string]*string) {
   243  	// validate
   244  	if attributes == nil {
   245  		return nil
   246  	}
   247  
   248  	// make map
   249  	newMap = make(map[string]*string)
   250  
   251  	for k, v := range attributes {
   252  		if k.Valid() && k != snsgettopicattribute.UNKNOWN {
   253  			newMap[k.Key()] = aws.String(v)
   254  		}
   255  	}
   256  
   257  	return newMap
   258  }
   259  
   260  // fromAwsGetTopicAttributes will convert from aws map to strongly typed map
   261  func (s *SNS) fromAwsGetTopicAttributes(attributes map[string]*string) (newMap map[snsgettopicattribute.SNSGetTopicAttribute]string) {
   262  	// validate
   263  	if attributes == nil {
   264  		return nil
   265  	}
   266  
   267  	// make map
   268  	newMap = make(map[snsgettopicattribute.SNSGetTopicAttribute]string)
   269  	var conv snsgettopicattribute.SNSGetTopicAttribute
   270  
   271  	for k, v := range attributes {
   272  		if util.LenTrim(k) > 0 {
   273  			v1 := aws.StringValue(v)
   274  
   275  			if k1, err := conv.ParseByKey(k); err == nil {
   276  				newMap[k1] = v1
   277  			}
   278  		}
   279  	}
   280  
   281  	return newMap
   282  }
   283  
   284  // toAwsSubscribeAttributes will convert from strongly typed to aws accepted map
   285  func (s *SNS) toAwsSubscribeAttributes(attributes map[snssubscribeattribute.SNSSubscribeAttribute]string) (newMap map[string]*string) {
   286  	// validate
   287  	if attributes == nil {
   288  		return nil
   289  	}
   290  
   291  	// make map
   292  	newMap = make(map[string]*string)
   293  
   294  	for k, v := range attributes {
   295  		if k.Valid() && k != snssubscribeattribute.UNKNOWN {
   296  			newMap[k.Key()] = aws.String(v)
   297  		}
   298  	}
   299  
   300  	return newMap
   301  }
   302  
   303  // fromAwsSubscribeAttributes will convert from aws map to strongly typed map
   304  func (s *SNS) fromAwsSubscribeAttributes(attributes map[string]*string) (newMap map[snssubscribeattribute.SNSSubscribeAttribute]string) {
   305  	// validate
   306  	if attributes == nil {
   307  		return nil
   308  	}
   309  
   310  	// make map
   311  	newMap = make(map[snssubscribeattribute.SNSSubscribeAttribute]string)
   312  	var conv snssubscribeattribute.SNSSubscribeAttribute
   313  
   314  	for k, v := range attributes {
   315  		if util.LenTrim(k) > 0 {
   316  			v1 := aws.StringValue(v)
   317  
   318  			if k1, err := conv.ParseByKey(k); err == nil {
   319  				newMap[k1] = v1
   320  			}
   321  		}
   322  	}
   323  
   324  	return newMap
   325  }
   326  
   327  // toAwsGetSubscriptionAttributes will convert from strongly typed to aws accepted map
   328  func (s *SNS) toAwsGetSubscriptionAttributes(attributes map[snsgetsubscriptionattribute.SNSGetSubscriptionAttribute]string) (newMap map[string]*string) {
   329  	// validate
   330  	if attributes == nil {
   331  		return nil
   332  	}
   333  
   334  	// make map
   335  	newMap = make(map[string]*string)
   336  
   337  	for k, v := range attributes {
   338  		if k.Valid() && k != snsgetsubscriptionattribute.UNKNOWN {
   339  			newMap[k.Key()] = aws.String(v)
   340  		}
   341  	}
   342  
   343  	return newMap
   344  }
   345  
   346  // fromAwsGetSubscriptionAttributes will convert from aws map to strongly typed map
   347  func (s *SNS) fromAwsGetSubscriptionAttributes(attributes map[string]*string) (newMap map[snsgetsubscriptionattribute.SNSGetSubscriptionAttribute]string) {
   348  	// validate
   349  	if attributes == nil {
   350  		return nil
   351  	}
   352  
   353  	// make map
   354  	newMap = make(map[snsgetsubscriptionattribute.SNSGetSubscriptionAttribute]string)
   355  	var conv snsgetsubscriptionattribute.SNSGetSubscriptionAttribute
   356  
   357  	for k, v := range attributes {
   358  		if util.LenTrim(k) > 0 {
   359  			v1 := aws.StringValue(v)
   360  
   361  			if k1, err := conv.ParseByKey(k); err == nil {
   362  				newMap[k1] = v1
   363  			}
   364  		}
   365  	}
   366  
   367  	return newMap
   368  }
   369  
   370  // toAwsPlatformApplicationAttributes will convert from strongly typed to aws accepted map
   371  func (s *SNS) toAwsPlatformApplicationAttributes(attributes map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string) (newMap map[string]*string) {
   372  	// validate
   373  	if attributes == nil {
   374  		return nil
   375  	}
   376  
   377  	// make map
   378  	newMap = make(map[string]*string)
   379  
   380  	for k, v := range attributes {
   381  		if k.Valid() && k != snsplatformapplicationattribute.UNKNOWN {
   382  			newMap[k.Key()] = aws.String(v)
   383  		}
   384  	}
   385  
   386  	return newMap
   387  }
   388  
   389  // fromAwsPlatformApplicationAttributes will convert from aws map to strongly typed map
   390  func (s *SNS) fromAwsPlatformApplicationAttributes(attributes map[string]*string) (newMap map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string) {
   391  	// validate
   392  	if attributes == nil {
   393  		return nil
   394  	}
   395  
   396  	// make map
   397  	newMap = make(map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string)
   398  	var conv snsplatformapplicationattribute.SNSPlatformApplicationAttribute
   399  
   400  	for k, v := range attributes {
   401  		if util.LenTrim(k) > 0 {
   402  			v1 := aws.StringValue(v)
   403  
   404  			if k1, err := conv.ParseByKey(k); err == nil {
   405  				newMap[k1] = v1
   406  			}
   407  		}
   408  	}
   409  
   410  	return newMap
   411  }
   412  
   413  // toAwsEndpointAttributes will convert from strongly typed to aws accepted map
   414  func (s *SNS) toAwsEndpointAttributes(attributes map[snsendpointattribute.SNSEndpointAttribute]string) (newMap map[string]*string) {
   415  	// validate
   416  	if attributes == nil {
   417  		return nil
   418  	}
   419  
   420  	// make map
   421  	newMap = make(map[string]*string)
   422  
   423  	for k, v := range attributes {
   424  		if k.Valid() && k != snsendpointattribute.UNKNOWN {
   425  			newMap[k.Key()] = aws.String(v)
   426  		}
   427  	}
   428  
   429  	return newMap
   430  }
   431  
   432  // fromAwsEndpointAttributes will convert from aws map to strongly typed map
   433  func (s *SNS) fromAwsEndpointAttributes(attributes map[string]*string) (newMap map[snsendpointattribute.SNSEndpointAttribute]string) {
   434  	// validate
   435  	if attributes == nil {
   436  		return nil
   437  	}
   438  
   439  	// make map
   440  	newMap = make(map[snsendpointattribute.SNSEndpointAttribute]string)
   441  	var conv snsendpointattribute.SNSEndpointAttribute
   442  
   443  	for k, v := range attributes {
   444  		if util.LenTrim(k) > 0 {
   445  			v1 := aws.StringValue(v)
   446  
   447  			if k1, err := conv.ParseByKey(k); err == nil {
   448  				newMap[k1] = v1
   449  			}
   450  		}
   451  	}
   452  
   453  	return newMap
   454  }
   455  
   456  // ----------------------------------------------------------------------------------------------------------------
   457  // topic methods
   458  // ----------------------------------------------------------------------------------------------------------------
   459  
   460  // CreateTopic will create a new topic in SNS for clients to subscribe,
   461  // once topic is created, the topicArn is returned for subsequent uses
   462  //
   463  // Parameters:
   464  //  1. topicName = required, the name of the topic to create in SNS
   465  //  2. attributes = optional, topic attributes to further customize the topic
   466  //  3. timeOutDuration = optional, indicates timeout value for context
   467  //
   468  // Topic Attributes: (Key = Expected Value)
   469  //  1. DeliveryPolicy = The JSON serialization of the topic's delivery policy
   470  //  2. DisplayName = The human-readable name used in the From field for notifications to email and email-json endpoints
   471  //  3. Policy = The JSON serialization of the topic's access control policy
   472  //
   473  // The following attribute applies only to server-side-encryption (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html):
   474  //
   475  //	   	a) KmsMasterKeyId = The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK.
   476  //							For more information, see Key Terms (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html#sse-key-terms)
   477  //	   						For more examples, see KeyId (https://docs.aws.amazon.com/kms/latest/APIReference/API_DescribeKey.html#API_DescribeKey_RequestParameters) in the AWS Key Management Service API Reference
   478  func (s *SNS) CreateTopic(topicName string, attributes map[snscreatetopicattribute.SNSCreateTopicAttribute]string, timeOutDuration ...time.Duration) (topicArn string, err error) {
   479  	segCtx := context.Background()
   480  	segCtxSet := false
   481  
   482  	seg := xray.NewSegmentNullable("SNS-CreateTopic", s._parentSegment)
   483  
   484  	if seg != nil {
   485  		segCtx = seg.Ctx
   486  		segCtxSet = true
   487  
   488  		defer seg.Close()
   489  		defer func() {
   490  			_ = seg.Seg.AddMetadata("SNS-CreateTopic-TopicName", topicName)
   491  			_ = seg.Seg.AddMetadata("SNS-CreateTopic-Attributes", attributes)
   492  			_ = seg.Seg.AddMetadata("SNS-CreateTopic-Result-TopicArn", topicArn)
   493  
   494  			if err != nil {
   495  				_ = seg.Seg.AddError(err)
   496  			}
   497  		}()
   498  	}
   499  
   500  	// validation
   501  	if s.snsClient == nil {
   502  		err = errors.New("CreateTopic Failed: " + "SNS Client is Required")
   503  		return "", err
   504  	}
   505  
   506  	if util.LenTrim(topicName) <= 0 {
   507  		err = errors.New("CreateTopic Failed: " + "Topic Name is Required")
   508  		return "", err
   509  	}
   510  
   511  	// create input object
   512  	input := &sns.CreateTopicInput{
   513  		Name: aws.String(topicName),
   514  	}
   515  
   516  	if attributes != nil {
   517  		input.Attributes = s.toAwsCreateTopicAttributes(attributes)
   518  	}
   519  
   520  	// perform action
   521  	var output *sns.CreateTopicOutput
   522  
   523  	if len(timeOutDuration) > 0 {
   524  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
   525  		defer cancel()
   526  
   527  		output, err = s.snsClient.CreateTopicWithContext(ctx, input)
   528  	} else {
   529  		if segCtxSet {
   530  			output, err = s.snsClient.CreateTopicWithContext(segCtx, input)
   531  		} else {
   532  			output, err = s.snsClient.CreateTopic(input)
   533  		}
   534  	}
   535  
   536  	// evaluate result
   537  	if err != nil {
   538  		err = errors.New("CreateTopic Failed: (Create Action) " + err.Error())
   539  		return "", err
   540  	}
   541  
   542  	topicArn = *output.TopicArn
   543  	return topicArn, nil
   544  }
   545  
   546  // DeleteTopic will delete an existing SNS topic by topicArn,
   547  // returns nil if successful
   548  func (s *SNS) DeleteTopic(topicArn string, timeOutDuration ...time.Duration) (err error) {
   549  	segCtx := context.Background()
   550  	segCtxSet := false
   551  
   552  	seg := xray.NewSegmentNullable("SNS-DeleteTopic", s._parentSegment)
   553  
   554  	if seg != nil {
   555  		segCtx = seg.Ctx
   556  		segCtxSet = true
   557  
   558  		defer seg.Close()
   559  		defer func() {
   560  			_ = seg.Seg.AddMetadata("SNS-DeleteTopic-TopicArn", topicArn)
   561  
   562  			if err != nil {
   563  				_ = seg.Seg.AddError(err)
   564  			}
   565  		}()
   566  	}
   567  
   568  	// validation
   569  	if s.snsClient == nil {
   570  		err = errors.New("DeleteTopic Failed: " + "SNS Client is Required")
   571  		return err
   572  	}
   573  
   574  	if util.LenTrim(topicArn) <= 0 {
   575  		err = errors.New("DeleteTopic Failed: " + "Topic ARN is Required")
   576  		return err
   577  	}
   578  
   579  	// create input object
   580  	input := &sns.DeleteTopicInput{
   581  		TopicArn: aws.String(topicArn),
   582  	}
   583  
   584  	// perform action
   585  	if len(timeOutDuration) > 0 {
   586  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
   587  		defer cancel()
   588  
   589  		_, err = s.snsClient.DeleteTopicWithContext(ctx, input)
   590  	} else {
   591  		if segCtxSet {
   592  			_, err = s.snsClient.DeleteTopicWithContext(segCtx, input)
   593  		} else {
   594  			_, err = s.snsClient.DeleteTopic(input)
   595  		}
   596  	}
   597  
   598  	// evaluate result
   599  	if err != nil {
   600  		err = errors.New("DeleteTopic Failed: (Delete Action) " + err.Error())
   601  		return err
   602  	} else {
   603  		return nil
   604  	}
   605  }
   606  
   607  // ListTopics will list SNS topics, with optional nextToken for retrieving more list from a prior call
   608  //
   609  // Parameters:
   610  //  1. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list
   611  //  2. timeOutDuration = optional, indicates timeout value for context
   612  //
   613  // Return Values:
   614  //  1. topicArnsList = string slice of topic ARNs, nil if not set
   615  //  2. moreTopicArnsNextToken = if there are more topics, this token is filled, to query more, use the token as input parameter, blank if no more
   616  //  3. err = error info if any
   617  func (s *SNS) ListTopics(nextToken string, timeOutDuration ...time.Duration) (topicArnsList []string, moreTopicArnsNextToken string, err error) {
   618  	segCtx := context.Background()
   619  	segCtxSet := false
   620  
   621  	seg := xray.NewSegmentNullable("SNS-ListTopics", s._parentSegment)
   622  
   623  	if seg != nil {
   624  		segCtx = seg.Ctx
   625  		segCtxSet = true
   626  
   627  		defer seg.Close()
   628  		defer func() {
   629  			_ = seg.Seg.AddMetadata("SNS-ListTopics-NextToken", nextToken)
   630  			_ = seg.Seg.AddMetadata("SNS-ListTopics-Result-TopicArnsList", topicArnsList)
   631  			_ = seg.Seg.AddMetadata("SNS-ListTopics-Result-NextToken", moreTopicArnsNextToken)
   632  
   633  			if err != nil {
   634  				_ = seg.Seg.AddError(err)
   635  			}
   636  		}()
   637  	}
   638  
   639  	// validation
   640  	if s.snsClient == nil {
   641  		err = errors.New("ListTopics Failed: " + "SNS Client is Required")
   642  		return nil, "", err
   643  	}
   644  
   645  	// create input object
   646  	input := &sns.ListTopicsInput{}
   647  
   648  	if util.LenTrim(nextToken) > 0 {
   649  		input.NextToken = aws.String(nextToken)
   650  	}
   651  
   652  	// perform action
   653  	var output *sns.ListTopicsOutput
   654  
   655  	if len(timeOutDuration) > 0 {
   656  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
   657  		defer cancel()
   658  
   659  		output, err = s.snsClient.ListTopicsWithContext(ctx, input)
   660  	} else {
   661  		if segCtxSet {
   662  			output, err = s.snsClient.ListTopicsWithContext(segCtx, input)
   663  		} else {
   664  			output, err = s.snsClient.ListTopics(input)
   665  		}
   666  	}
   667  
   668  	// evaluate result
   669  	if err != nil {
   670  		err = errors.New("ListTopics Failed: (List Action) " + err.Error())
   671  		return nil, "", err
   672  	}
   673  
   674  	moreTopicArnsNextToken = aws.StringValue(output.NextToken)
   675  
   676  	for _, v := range output.Topics {
   677  		buf := aws.StringValue(v.TopicArn)
   678  
   679  		if util.LenTrim(buf) > 0 {
   680  			topicArnsList = append(topicArnsList, buf)
   681  		}
   682  	}
   683  
   684  	return topicArnsList, moreTopicArnsNextToken, nil
   685  }
   686  
   687  // GetTopicAttributes will retrieve a map of topic attributes based on topicArn
   688  //
   689  // Parameters:
   690  //  1. topicArn = required, specify the topicArn to retrieve related topic attributes
   691  //  2. timeOutDuration = optional, indicates timeout value for context
   692  //
   693  // Return Values:
   694  //  1. attributes = map of sns get topic attributes key value pairs related to teh topic ARN being queried
   695  //  2. err = error info if any
   696  //
   697  // Topic Attributes: (Key = Expected Value)
   698  //  1. DeliveryPolicy = The JSON serialization of the topic's delivery policy (See Subscribe DeliveryPolicy Json Format)
   699  //  2. DisplayName = The human-readable name used in the From field for notifications to email and email-json endpoints
   700  //  3. Owner = The AWS account ID of the topic's owner
   701  //  4. Policy = The JSON serialization of the topic's access control policy
   702  //  5. SubscriptionsConfirmed = The number of confirmed subscriptions for the topic
   703  //  6. SubscriptionsDeleted = The number of deleted subscriptions for the topic
   704  //  7. SubscriptionsPending = The number of subscriptions pending confirmation for the topic
   705  //  8. TopicArn = The topic's ARN
   706  //  9. EffectiveDeliveryPolicy = Yhe JSON serialization of the effective delivery policy, taking system defaults into account
   707  //
   708  // The following attribute applies only to server-side-encryption (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html):
   709  //
   710  //	   	a) KmsMasterKeyId = The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK.
   711  //							For more information, see Key Terms (https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html#sse-key-terms)
   712  //	   						For more examples, see KeyId (https://docs.aws.amazon.com/kms/latest/APIReference/API_DescribeKey.html#API_DescribeKey_RequestParameters) in the AWS Key Management Service API Reference
   713  func (s *SNS) GetTopicAttributes(topicArn string, timeOutDuration ...time.Duration) (attributes map[snsgettopicattribute.SNSGetTopicAttribute]string, err error) {
   714  	segCtx := context.Background()
   715  	segCtxSet := false
   716  
   717  	seg := xray.NewSegmentNullable("SNS-GetTopicAttributes", s._parentSegment)
   718  
   719  	if seg != nil {
   720  		segCtx = seg.Ctx
   721  		segCtxSet = true
   722  
   723  		defer seg.Close()
   724  		defer func() {
   725  			_ = seg.Seg.AddMetadata("SNS-GetTopicAttributes-TopicArn", topicArn)
   726  			_ = seg.Seg.AddMetadata("SNS-GetTopicAttributes-Result-Attributes", attributes)
   727  
   728  			if err != nil {
   729  				_ = seg.Seg.AddError(err)
   730  			}
   731  		}()
   732  	}
   733  
   734  	// validation
   735  	if s.snsClient == nil {
   736  		err = errors.New("GetTopicAttributes Failed: " + "SNS Client is Required")
   737  		return nil, err
   738  	}
   739  
   740  	if util.LenTrim(topicArn) <= 0 {
   741  		err = errors.New("GetTopicAttributes Failed: " + "Topic ARN is Required")
   742  		return nil, err
   743  	}
   744  
   745  	// create input object
   746  	input := &sns.GetTopicAttributesInput{
   747  		TopicArn: aws.String(topicArn),
   748  	}
   749  
   750  	// perform action
   751  	var output *sns.GetTopicAttributesOutput
   752  
   753  	if len(timeOutDuration) > 0 {
   754  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
   755  		defer cancel()
   756  
   757  		output, err = s.snsClient.GetTopicAttributesWithContext(ctx, input)
   758  	} else {
   759  		if segCtxSet {
   760  			output, err = s.snsClient.GetTopicAttributesWithContext(segCtx, input)
   761  		} else {
   762  			output, err = s.snsClient.GetTopicAttributes(input)
   763  		}
   764  	}
   765  
   766  	// evaluate result
   767  	if err != nil {
   768  		err = errors.New("GetTopicAttributes Failed: (Get Action) " + err.Error())
   769  		return nil, err
   770  	}
   771  
   772  	attributes = s.fromAwsGetTopicAttributes(output.Attributes)
   773  	return attributes, nil
   774  }
   775  
   776  // SetTopicAttribute will set or update a topic attribute,
   777  // For attribute value or Json format, see corresponding notes in CreateTopic where applicable
   778  func (s *SNS) SetTopicAttribute(topicArn string,
   779  	attributeName snscreatetopicattribute.SNSCreateTopicAttribute,
   780  	attributeValue string,
   781  	timeOutDuration ...time.Duration) (err error) {
   782  	segCtx := context.Background()
   783  	segCtxSet := false
   784  
   785  	seg := xray.NewSegmentNullable("SNS-SetTopicAttribute", s._parentSegment)
   786  
   787  	if seg != nil {
   788  		segCtx = seg.Ctx
   789  		segCtxSet = true
   790  
   791  		defer seg.Close()
   792  		defer func() {
   793  			_ = seg.Seg.AddMetadata("SNS-SetTopicAttribute-TopicArn", topicArn)
   794  			_ = seg.Seg.AddMetadata("SNS-SetTopicAttribute-AttributeName", attributeName)
   795  			_ = seg.Seg.AddMetadata("SNS-SetTopicAttribute-AttributeValue", attributeValue)
   796  
   797  			if err != nil {
   798  				_ = seg.Seg.AddError(err)
   799  			}
   800  		}()
   801  	}
   802  
   803  	// validation
   804  	if s.snsClient == nil {
   805  		err = errors.New("SetTopicAttribute Failed: " + "SNS Client is Required")
   806  		return err
   807  	}
   808  
   809  	if util.LenTrim(topicArn) <= 0 {
   810  		err = errors.New("SetTopicAttribute Failed: " + "Topic ARN is Required")
   811  		return err
   812  	}
   813  
   814  	if !attributeName.Valid() || attributeName == snscreatetopicattribute.UNKNOWN {
   815  		err = errors.New("SetTopicAttribute Failed: " + "Attribute Name is Required")
   816  		return err
   817  	}
   818  
   819  	// create input object
   820  	input := &sns.SetTopicAttributesInput{
   821  		TopicArn:       aws.String(topicArn),
   822  		AttributeName:  aws.String(attributeName.Key()),
   823  		AttributeValue: aws.String(attributeValue),
   824  	}
   825  
   826  	// perform action
   827  	if len(timeOutDuration) > 0 {
   828  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
   829  		defer cancel()
   830  
   831  		_, err = s.snsClient.SetTopicAttributesWithContext(ctx, input)
   832  	} else {
   833  		if segCtxSet {
   834  			_, err = s.snsClient.SetTopicAttributesWithContext(segCtx, input)
   835  		} else {
   836  			_, err = s.snsClient.SetTopicAttributes(input)
   837  		}
   838  	}
   839  
   840  	// evaluate result
   841  	if err != nil {
   842  		err = errors.New("SetTopicAttribute Failed: (Set Action) " + err.Error())
   843  		return err
   844  	} else {
   845  		return nil
   846  	}
   847  }
   848  
   849  // ----------------------------------------------------------------------------------------------------------------
   850  // subscriber methods
   851  // ----------------------------------------------------------------------------------------------------------------
   852  
   853  // Subscribe will allow client to subscribe to a SNS topic (previously created with CreateTopic method),
   854  // the subscriptionArn is returned upon success,
   855  //
   856  //	if subscription needs client confirmation, then the string 'pending confirmation' is returned instead
   857  //
   858  // Parameters:
   859  //  1. topicArn = required, subscribe to this topic ARN
   860  //  2. protocol = required, SNS callback protocol, so that when publish to the topic occurs, this protocol is used as callback
   861  //  3. endPoint = required, SNS callback endpoint, so that when publish to the topic occurs, this endpoint is triggered by the callback
   862  //  4. attributes = optional, map of sns subscribe attribute key value pairs
   863  //  5. timeOutDuration = optional, indicates timeout value for context
   864  //
   865  // Protocols: (Key = Expected Value)
   866  //  1. http = delivery of JSON-encoded message via HTTP POST
   867  //  2. https = delivery of JSON-encoded message via HTTPS POST
   868  //  3. email = delivery of message via SMTP
   869  //  4. email-json = delivery of JSON-encoded message via SMTP
   870  //  5. sms = delivery of message via SMS
   871  //  6. sqs = delivery of JSON-encoded message to an Amazon SQS queue
   872  //  7. application = delivery of JSON-encoded message to an EndpointArn for a mobile app and device
   873  //  8. lambda = delivery of JSON-encoded message to an Amazon Lambda function
   874  //
   875  // Endpoint To Receive Notifications: (Based on Protocol)
   876  //  1. http protocol = the endpoint is an URL beginning with http://
   877  //  2. https protocol = the endpoint is a URL beginning with https://
   878  //  3. email protocol = the endpoint is an email address
   879  //  4. email-json protocol = the endpoint is an email address
   880  //  5. sms protocol = the endpoint is a phone number of an SMS-enabled device
   881  //  6. sqs protocol = the endpoint is the ARN of an Amazon SQS queue
   882  //  7. application protocol = the endpoint is the EndpointArn of a mobile app and device
   883  //  8. lambda protocol = the endpoint is the ARN of an Amazon Lambda function
   884  //
   885  // Subscribe Attributes: (Key = Expected Value)
   886  //  1. DeliveryPolicy = The policy that defines how Amazon SNS retries failed deliveries to HTTP/S endpoints
   887  //     *) example to set delivery policy to 5 retries:
   888  //     {
   889  //     "healthyRetryPolicy": {
   890  //     "minDelayTarget": <intValue>,
   891  //     "maxDelayTarget": <intValue>,
   892  //     "numRetries": <intValue>,
   893  //     "numMaxDelayRetries": <intValue>,
   894  //     "backoffFunction": "<linear|arithmetic|geometric|exponential>"
   895  //     },
   896  //     "throttlePolicy": {
   897  //     "maxReceivesPerSecond": <intValue>
   898  //     }
   899  //     }
   900  //     *) Not All Json Elements Need To Be Filled in Policy, Use What is Needed, such as:
   901  //     { "healthyRetryPolicy": { "numRetries": 5 } }
   902  //  2. FilterPolicy = The simple JSON object that lets your subscriber receive only a subset of messages,
   903  //     rather than receiving every message published to the topic:
   904  //     *) subscriber attribute controls filter allowance,
   905  //     publish attribute indicates attributes contained in message
   906  //     *) if any single attribute in this policy doesn't match an attribute assigned to message, this policy rejects the message:
   907  //     {
   908  //     "store": ["example_corp"],
   909  //     "event": [{"anything-but": "order_cancelled"}],
   910  //     "customer_interests": ["rugby", "football", "baseball"],
   911  //     "price_usd": [{"numeric": [">=", 100]}]
   912  //     }
   913  //     *) "xyz": [{"anything-but": ...}] keyword indicates to match anything but the defined value ... Json element (... may be string or numeric)
   914  //     *) "xyz": [{"prefix": ...}] keyword indicates to match value prefixed from the defined value ... in Json element
   915  //     *) "xyz": [{"numeric": ["=", ...]}] keyword indicates numeric equal matching as indicated by numeric and =
   916  //     *) "xyz": [{"numeric": [">", ...]}] keyword indicates numeric compare matching as indicated by numeric and >, <, >=, <=
   917  //     *) "xyz": [{"numeric": [">", 0, "<", 100]}] keyword indicates numeric ranged compare matching as indicated by numeric and >, <, in parts
   918  //     *) "xyz": [{"exists": true}] keyword indicates attribute xyz exists matching
   919  //  3. RawMessageDelivery = When set to true, enables raw message delivery to Amazon SQS or HTTP/S endpoints.
   920  //     This eliminates the need for the endpoints to process JSON formatting, which is otherwise created for Amazon SNS metadata
   921  //  4. RedrivePolicy = When specified, sends undeliverable messages to the specified Amazon SQS dead-letter queue.
   922  //     Messages that can't be delivered due to client errors (for example, when the subscribed endpoint is unreachable),
   923  //     or server errors (for example, when the service that powers the subscribed endpoint becomes unavailable),
   924  //     are held in the dead-letter queue for further analysis or reprocessing
   925  //     *) example of RedrivePolicy to route failed messages to Dead Letter Queue (DLQ):
   926  //     {
   927  //     "deadLetterTargetArn": "dead letter sns queue arn such as arn:aws:sqs:us-east-2:12345678021:MyDeadLetterQueue"
   928  //     }
   929  //
   930  // Subscription Confirmation Support:
   931  //  1. Http / Https Endpoints Requires Subscription Confirmation Support, See Details in URL Below:
   932  //     a) https://docs.aws.amazon.com/sns/latest/dg/sns-http-https-endpoint-as-subscriber.html
   933  //  2. Once Subscribe action is performed, SNS sends confirmation notification to the HTTP/s Endpoint:
   934  //     b) Client Upon Receipt of the SNS Notification, Retrieve Token and Respond via ConfirmSubscription method
   935  func (s *SNS) Subscribe(topicArn string,
   936  	protocol snsprotocol.SNSProtocol,
   937  	endPoint string,
   938  	attributes map[snssubscribeattribute.SNSSubscribeAttribute]string,
   939  	timeOutDuration ...time.Duration) (subscriptionArn string, err error) {
   940  	segCtx := context.Background()
   941  	segCtxSet := false
   942  
   943  	seg := xray.NewSegmentNullable("SNS-Subscribe", s._parentSegment)
   944  
   945  	if seg != nil {
   946  		segCtx = seg.Ctx
   947  		segCtxSet = true
   948  
   949  		defer seg.Close()
   950  		defer func() {
   951  			_ = seg.Seg.AddMetadata("SNS-Subscribe-TopicArn", topicArn)
   952  			_ = seg.Seg.AddMetadata("SNS-Subscribe-Protocol", protocol)
   953  			_ = seg.Seg.AddMetadata("SNS-Subscribe-Endpoint", endPoint)
   954  			_ = seg.Seg.AddMetadata("SNS-Subscribe-Attributes", attributes)
   955  			_ = seg.Seg.AddMetadata("SNS-Subscribe-Result-SubscriptionArn", subscriptionArn)
   956  
   957  			if err != nil {
   958  				_ = seg.Seg.AddError(err)
   959  			}
   960  		}()
   961  	}
   962  
   963  	// validation
   964  	if s.snsClient == nil {
   965  		err = errors.New("Subscribe Failed: " + "SNS Client is Required")
   966  		return "", err
   967  	}
   968  
   969  	if util.LenTrim(topicArn) <= 0 {
   970  		err = errors.New("Subscribe Failed: " + "Topic ARN is Required")
   971  		return "", err
   972  	}
   973  
   974  	if !protocol.Valid() || protocol == snsprotocol.UNKNOWN {
   975  		err = errors.New("Subscribe Failed: " + "Protocol is Required")
   976  		return "", err
   977  	}
   978  
   979  	if util.LenTrim(endPoint) <= 0 {
   980  		err = errors.New("Subscribe Failed: " + "Endpoint is Required")
   981  		return "", err
   982  	}
   983  
   984  	// create input object
   985  	input := &sns.SubscribeInput{
   986  		TopicArn: aws.String(topicArn),
   987  		Protocol: aws.String(protocol.Key()),
   988  		Endpoint: aws.String(endPoint),
   989  	}
   990  
   991  	if attributes != nil {
   992  		input.Attributes = s.toAwsSubscribeAttributes(attributes)
   993  	}
   994  
   995  	// perform action
   996  	var output *sns.SubscribeOutput
   997  
   998  	if len(timeOutDuration) > 0 {
   999  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1000  		defer cancel()
  1001  
  1002  		output, err = s.snsClient.SubscribeWithContext(ctx, input)
  1003  	} else {
  1004  		if segCtxSet {
  1005  			output, err = s.snsClient.SubscribeWithContext(segCtx, input)
  1006  		} else {
  1007  			output, err = s.snsClient.Subscribe(input)
  1008  		}
  1009  	}
  1010  
  1011  	// evaluate result
  1012  	if err != nil {
  1013  		err = errors.New("Subscribe Failed: (Subscribe Action) " + err.Error())
  1014  		return "", err
  1015  	}
  1016  
  1017  	subscriptionArn = *output.SubscriptionArn
  1018  	return subscriptionArn, nil
  1019  }
  1020  
  1021  // Unsubscribe will remove a subscription in SNS via subscriptionArn,
  1022  // nil is returned if successful, otherwise err is filled with error info
  1023  //
  1024  // Parameters:
  1025  //  1. subscriptionArn = required, the subscription ARN to remove from SNS
  1026  //  2. timeOutDuration = optional, indicates timeout value for context
  1027  func (s *SNS) Unsubscribe(subscriptionArn string, timeOutDuration ...time.Duration) (err error) {
  1028  	segCtx := context.Background()
  1029  	segCtxSet := false
  1030  
  1031  	seg := xray.NewSegmentNullable("SNS-Unsubscribe", s._parentSegment)
  1032  
  1033  	if seg != nil {
  1034  		segCtx = seg.Ctx
  1035  		segCtxSet = true
  1036  
  1037  		defer seg.Close()
  1038  		defer func() {
  1039  			_ = seg.Seg.AddMetadata("SNS-Unsubscribe-SubscriptionArn", subscriptionArn)
  1040  
  1041  			if err != nil {
  1042  				_ = seg.Seg.AddError(err)
  1043  			}
  1044  		}()
  1045  	}
  1046  
  1047  	// validation
  1048  	if s.snsClient == nil {
  1049  		err = errors.New("Unsubscribe Failed: " + "SNS Client is Required")
  1050  		return err
  1051  	}
  1052  
  1053  	if util.LenTrim(subscriptionArn) <= 0 {
  1054  		err = errors.New("Unsubscribe Failed: " + "Subscription ARN is Required")
  1055  		return err
  1056  	}
  1057  
  1058  	// create input object
  1059  	input := &sns.UnsubscribeInput{
  1060  		SubscriptionArn: aws.String(subscriptionArn),
  1061  	}
  1062  
  1063  	// perform action
  1064  	if len(timeOutDuration) > 0 {
  1065  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1066  		defer cancel()
  1067  
  1068  		_, err = s.snsClient.UnsubscribeWithContext(ctx, input)
  1069  	} else {
  1070  		if segCtxSet {
  1071  			_, err = s.snsClient.UnsubscribeWithContext(segCtx, input)
  1072  		} else {
  1073  			_, err = s.snsClient.Unsubscribe(input)
  1074  		}
  1075  	}
  1076  
  1077  	// evaluate result
  1078  	if err != nil {
  1079  		err = errors.New("Unsubscribe Failed: (Unsubscribe Action) " + err.Error())
  1080  		return err
  1081  	} else {
  1082  		return nil
  1083  	}
  1084  }
  1085  
  1086  // ConfirmSubscription will confirm a pending subscription upon receive of SNS notification for subscription confirmation,
  1087  // the SNS subscription confirmation will contain a Token which is needed by ConfirmSubscription as input parameter in order to confirm,
  1088  //
  1089  // Parameters:
  1090  //  1. topicArn = required, the topic in SNS to confirm subscription for
  1091  //  2. token = required, the token from SNS confirmation notification receive upon call to Subscribe
  1092  //  3. timeOutDuration = optional, indicates timeout value for context
  1093  //
  1094  // Return Values:
  1095  //  1. subscriptionArn = upon confirmation, the subscription ARN attained
  1096  //  2. err = the error info if any
  1097  //
  1098  // Subscription Confirmation Support:
  1099  //  1. Http / Https / Email Endpoints Requires Subscription Confirmation Support, See Details in URL Below:
  1100  //     a) https://docs.aws.amazon.com/sns/latest/dg/sns-http-https-endpoint-as-subscriber.html
  1101  //  2. Once Subscribe action is performed, SNS sends confirmation notification to the HTTP/s Endpoint:
  1102  //     b) Client Upon Receipt of the SNS Notification, Retrieve Token and Respond via ConfirmSubscription method
  1103  func (s *SNS) ConfirmSubscription(topicArn string, token string, timeOutDuration ...time.Duration) (subscriptionArn string, err error) {
  1104  	segCtx := context.Background()
  1105  	segCtxSet := false
  1106  
  1107  	seg := xray.NewSegmentNullable("SNS-ConfirmSubscription", s._parentSegment)
  1108  
  1109  	if seg != nil {
  1110  		segCtx = seg.Ctx
  1111  		segCtxSet = true
  1112  
  1113  		defer seg.Close()
  1114  		defer func() {
  1115  			_ = seg.Seg.AddMetadata("SNS-ConfirmSubscription-TopicArn", topicArn)
  1116  			_ = seg.Seg.AddMetadata("SNS-ConfirmSubscription-Token", token)
  1117  			_ = seg.Seg.AddMetadata("SNS-ConfirmSubscription-Result-SubscriptionArn", subscriptionArn)
  1118  
  1119  			if err != nil {
  1120  				_ = seg.Seg.AddError(err)
  1121  			}
  1122  		}()
  1123  	}
  1124  
  1125  	// validation
  1126  	if s.snsClient == nil {
  1127  		err = errors.New("ConfirmSubscription Failed: " + "SNS Client is Required")
  1128  		return "", err
  1129  	}
  1130  
  1131  	if util.LenTrim(topicArn) <= 0 {
  1132  		err = errors.New("ConfirmSubscription Failed: " + "Topic ARN is Required")
  1133  		return "", err
  1134  	}
  1135  
  1136  	if util.LenTrim(token) <= 0 {
  1137  		err = errors.New("ConfirmSubscription Failed: " + "Token is Required (From Subscribe Action's SNS Confirmation Notification)")
  1138  		return "", err
  1139  	}
  1140  
  1141  	// create input object
  1142  	input := &sns.ConfirmSubscriptionInput{
  1143  		TopicArn: aws.String(topicArn),
  1144  		Token:    aws.String(token),
  1145  	}
  1146  
  1147  	// perform action
  1148  	var output *sns.ConfirmSubscriptionOutput
  1149  
  1150  	if len(timeOutDuration) > 0 {
  1151  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1152  		defer cancel()
  1153  
  1154  		output, err = s.snsClient.ConfirmSubscriptionWithContext(ctx, input)
  1155  	} else {
  1156  		if segCtxSet {
  1157  			output, err = s.snsClient.ConfirmSubscriptionWithContext(segCtx, input)
  1158  		} else {
  1159  			output, err = s.snsClient.ConfirmSubscription(input)
  1160  		}
  1161  	}
  1162  
  1163  	// evaluate result
  1164  	if err != nil {
  1165  		err = errors.New("ConfirmSubscription Failed: (ConfirmSubscription Action) " + err.Error())
  1166  		return "", err
  1167  	}
  1168  
  1169  	subscriptionArn = *output.SubscriptionArn
  1170  	return subscriptionArn, nil
  1171  }
  1172  
  1173  // ListSubscriptions will list SNS subscriptions, with optional nextToken for retrieving more list from a prior call
  1174  //
  1175  // Parameters:
  1176  //  1. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list
  1177  //  2. timeOutDuration = optional, indicates timeout value for context
  1178  //
  1179  // Return Values:
  1180  //  1. subscriptionsList = *SubscribedTopic slice containing subscriptions along with its related topic, nil if not set
  1181  //  2. moreSubscriptionsNextToken = if there are more subscriptions, this token is filled, to query more, use the token as input parameter, blank if no more
  1182  //  3. err = error info if any
  1183  func (s *SNS) ListSubscriptions(nextToken string, timeOutDuration ...time.Duration) (subscriptionsList []*SubscribedTopic, moreSubscriptionsNextToken string, err error) {
  1184  	segCtx := context.Background()
  1185  	segCtxSet := false
  1186  
  1187  	seg := xray.NewSegmentNullable("SNS-ListSubscriptions", s._parentSegment)
  1188  
  1189  	if seg != nil {
  1190  		segCtx = seg.Ctx
  1191  		segCtxSet = true
  1192  
  1193  		defer seg.Close()
  1194  		defer func() {
  1195  			_ = seg.Seg.AddMetadata("SNS-ListSubscriptions-NextToken", nextToken)
  1196  			_ = seg.Seg.AddMetadata("SNS-ListSubscriptions-Result-SubscriptionsList", subscriptionsList)
  1197  			_ = seg.Seg.AddMetadata("SNS-ListSubscriptions-Result-NextToken", moreSubscriptionsNextToken)
  1198  
  1199  			if err != nil {
  1200  				_ = seg.Seg.AddError(err)
  1201  			}
  1202  		}()
  1203  	}
  1204  
  1205  	// validation
  1206  	if s.snsClient == nil {
  1207  		err = errors.New("ListSubscriptions Failed: " + "SNS Client is Required")
  1208  		return nil, "", err
  1209  	}
  1210  
  1211  	// create input object
  1212  	input := &sns.ListSubscriptionsInput{}
  1213  
  1214  	if util.LenTrim(nextToken) > 0 {
  1215  		input.NextToken = aws.String(nextToken)
  1216  	}
  1217  
  1218  	// perform action
  1219  	var output *sns.ListSubscriptionsOutput
  1220  
  1221  	if len(timeOutDuration) > 0 {
  1222  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1223  		defer cancel()
  1224  
  1225  		output, err = s.snsClient.ListSubscriptionsWithContext(ctx, input)
  1226  	} else {
  1227  		if segCtxSet {
  1228  			output, err = s.snsClient.ListSubscriptionsWithContext(segCtx, input)
  1229  		} else {
  1230  			output, err = s.snsClient.ListSubscriptions(input)
  1231  		}
  1232  	}
  1233  
  1234  	// evaluate result
  1235  	if err != nil {
  1236  		err = errors.New("ListSubscriptions Failed: (List Action) " + err.Error())
  1237  		return nil, "", err
  1238  	}
  1239  
  1240  	moreSubscriptionsNextToken = aws.StringValue(output.NextToken)
  1241  
  1242  	if len(output.Subscriptions) > 0 {
  1243  		var conv snsprotocol.SNSProtocol
  1244  
  1245  		for _, v := range output.Subscriptions {
  1246  			if p, e := conv.ParseByKey(aws.StringValue(v.Protocol)); e == nil {
  1247  				subscriptionsList = append(subscriptionsList, &SubscribedTopic{
  1248  					SubscriptionArn: aws.StringValue(v.SubscriptionArn),
  1249  					TopicArn:        aws.StringValue(v.TopicArn),
  1250  					Endpoint:        aws.StringValue(v.Endpoint),
  1251  					Owner:           aws.StringValue(v.Owner),
  1252  					Protocol:        p,
  1253  				})
  1254  			}
  1255  		}
  1256  	}
  1257  
  1258  	return subscriptionsList, moreSubscriptionsNextToken, nil
  1259  }
  1260  
  1261  // ListSubscriptionsByTopic will list SNS subscriptions by a specific topic via topicArn,
  1262  // with optional nextToken for retrieving more list from a prior call
  1263  //
  1264  // Parameters:
  1265  //  1. topicArn = required, list subscriptions based on this topic ARN
  1266  //  2. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list
  1267  //  3. timeOutDuration = optional, indicates timeout value for context
  1268  //
  1269  // Return Values:
  1270  //  1. subscriptionsList = *SubscribedTopic slice containing subscriptions along with its related topic, nil if not set
  1271  //  2. moreSubscriptionsNextToken = if there are more subscriptions, this token is filled, to query more, use the token as input parameter, blank if no more
  1272  //  3. err = error info if any
  1273  func (s *SNS) ListSubscriptionsByTopic(topicArn string, nextToken string, timeOutDuration ...time.Duration) (subscriptionsList []*SubscribedTopic, moreSubscriptionsNextToken string, err error) {
  1274  	segCtx := context.Background()
  1275  	segCtxSet := false
  1276  
  1277  	seg := xray.NewSegmentNullable("SNS-ListSubscriptionsByTopic", s._parentSegment)
  1278  
  1279  	if seg != nil {
  1280  		segCtx = seg.Ctx
  1281  		segCtxSet = true
  1282  
  1283  		defer seg.Close()
  1284  		defer func() {
  1285  			_ = seg.Seg.AddMetadata("SNS-ListSubscriptionsByTopic-TopicArn", topicArn)
  1286  			_ = seg.Seg.AddMetadata("SNS-ListSubscriptionsByTopic-NextToken", nextToken)
  1287  			_ = seg.Seg.AddMetadata("SNS-ListSubscriptionsByTopic-Result-SubscriptionsList", subscriptionsList)
  1288  			_ = seg.Seg.AddMetadata("SNS-ListSubscriptionsByTopic-Result-NextToken", moreSubscriptionsNextToken)
  1289  
  1290  			if err != nil {
  1291  				_ = seg.Seg.AddError(err)
  1292  			}
  1293  		}()
  1294  	}
  1295  
  1296  	// validation
  1297  	if s.snsClient == nil {
  1298  		err = errors.New("ListSubscriptionsByTopic Failed: " + "SNS Client is Required")
  1299  		return nil, "", err
  1300  	}
  1301  
  1302  	if util.LenTrim(topicArn) <= 0 {
  1303  		err = errors.New("ListSubscriptionsByTopic Failed: " + "Topic ARN is Required")
  1304  		return nil, "", err
  1305  	}
  1306  
  1307  	// create input object
  1308  	input := &sns.ListSubscriptionsByTopicInput{
  1309  		TopicArn: aws.String(topicArn),
  1310  	}
  1311  
  1312  	if util.LenTrim(nextToken) > 0 {
  1313  		input.NextToken = aws.String(nextToken)
  1314  	}
  1315  
  1316  	// perform action
  1317  	var output *sns.ListSubscriptionsByTopicOutput
  1318  
  1319  	if len(timeOutDuration) > 0 {
  1320  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1321  		defer cancel()
  1322  
  1323  		output, err = s.snsClient.ListSubscriptionsByTopicWithContext(ctx, input)
  1324  	} else {
  1325  		if segCtxSet {
  1326  			output, err = s.snsClient.ListSubscriptionsByTopicWithContext(segCtx, input)
  1327  		} else {
  1328  			output, err = s.snsClient.ListSubscriptionsByTopic(input)
  1329  		}
  1330  	}
  1331  
  1332  	// evaluate result
  1333  	if err != nil {
  1334  		err = errors.New("ListSubscriptionsByTopic Failed: (List Action) " + err.Error())
  1335  		return nil, "", err
  1336  	}
  1337  
  1338  	moreSubscriptionsNextToken = aws.StringValue(output.NextToken)
  1339  
  1340  	if len(output.Subscriptions) > 0 {
  1341  		var conv snsprotocol.SNSProtocol
  1342  
  1343  		for _, v := range output.Subscriptions {
  1344  			if p, e := conv.ParseByKey(aws.StringValue(v.Protocol)); e == nil {
  1345  				subscriptionsList = append(subscriptionsList, &SubscribedTopic{
  1346  					SubscriptionArn: aws.StringValue(v.SubscriptionArn),
  1347  					TopicArn:        aws.StringValue(v.TopicArn),
  1348  					Endpoint:        aws.StringValue(v.Endpoint),
  1349  					Owner:           aws.StringValue(v.Owner),
  1350  					Protocol:        p,
  1351  				})
  1352  			}
  1353  		}
  1354  	}
  1355  
  1356  	return subscriptionsList, moreSubscriptionsNextToken, nil
  1357  }
  1358  
  1359  // GetSubscriptionAttributes will retrieve all subscription attributes for a specific subscription based on subscriptionArn
  1360  //
  1361  // Parameters:
  1362  //  1. subscriptionArn = required, the subscriptionArn for which attributes are retrieved from
  1363  //  2. timeOutDuration = optional, indicates timeout value for context
  1364  //
  1365  // Return Values:
  1366  //  1. attributes = map of sns get subscription attributes in key value pairs
  1367  //  2. err = error info if any
  1368  //
  1369  // Subscription Attributes: (Key = Expected Value)
  1370  //  1. ConfirmationWasAuthenticated = true if the subscription confirmation request was authenticated
  1371  //  2. DeliveryPolicy = The JSON serialization of the subscription's delivery policy (See Subscribe Notes)
  1372  //  3. EffectiveDeliveryPolicy = The JSON serialization of the effective delivery policy that takes into account the topic delivery policy,
  1373  //     and account system defaults (See Subscribe Notes for DeliveryPolicy Json format)
  1374  //  4. FilterPolicy = The filter policy JSON that is assigned to the subscription (See Subscribe Notes)
  1375  //  5. Owner = The AWS account ID of the subscription's owner
  1376  //  6. PendingConfirmation = true if the subscription hasn't been confirmed,
  1377  //     To confirm a pending subscription, call the ConfirmSubscription action with a confirmation token
  1378  //  7. RawMessageDelivery = true if raw message delivery is enabled for the subscription.
  1379  //     Raw messages are free of JSON formatting and can be sent to HTTP/S and Amazon SQS endpoints
  1380  //  8. RedrivePolicy = When specified, sends undeliverable messages to the specified Amazon SQS dead-letter queue.
  1381  //     Messages that can't be delivered due to client errors (for example, when the subscribed endpoint is unreachable),
  1382  //     or server errors (for example, when the service that powers the subscribed endpoint becomes unavailable)
  1383  //     are held in the dead-letter queue for further analysis or reprocessing (See Subscribe Notes)
  1384  //  9. SubscriptionArn = The subscription's ARN
  1385  //  10. TopicArn = The topic ARN that the subscription is associated with
  1386  func (s *SNS) GetSubscriptionAttributes(subscriptionArn string, timeOutDuration ...time.Duration) (attributes map[snsgetsubscriptionattribute.SNSGetSubscriptionAttribute]string, err error) {
  1387  	segCtx := context.Background()
  1388  	segCtxSet := false
  1389  
  1390  	seg := xray.NewSegmentNullable("SNS-GetSubscriptionAttributes", s._parentSegment)
  1391  
  1392  	if seg != nil {
  1393  		segCtx = seg.Ctx
  1394  		segCtxSet = true
  1395  
  1396  		defer seg.Close()
  1397  		defer func() {
  1398  			_ = seg.Seg.AddMetadata("SNS-GetSubscriptionAttributes-SubscriptionArn", subscriptionArn)
  1399  			_ = seg.Seg.AddMetadata("SNS-GetSubscriptionAttributes-Result-Attributes", attributes)
  1400  
  1401  			if err != nil {
  1402  				_ = seg.Seg.AddError(err)
  1403  			}
  1404  		}()
  1405  	}
  1406  
  1407  	// validation
  1408  	if s.snsClient == nil {
  1409  		err = errors.New("GetSubscriptionAttributes Failed: " + "SNS Client is Required")
  1410  		return nil, err
  1411  	}
  1412  
  1413  	if util.LenTrim(subscriptionArn) <= 0 {
  1414  		err = errors.New("GetSubscriptionAttributes Failed: " + "Subscription ARN is Required")
  1415  		return nil, err
  1416  	}
  1417  
  1418  	// create input object
  1419  	input := &sns.GetSubscriptionAttributesInput{
  1420  		SubscriptionArn: aws.String(subscriptionArn),
  1421  	}
  1422  
  1423  	// perform action
  1424  	var output *sns.GetSubscriptionAttributesOutput
  1425  
  1426  	if len(timeOutDuration) > 0 {
  1427  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1428  		defer cancel()
  1429  
  1430  		output, err = s.snsClient.GetSubscriptionAttributesWithContext(ctx, input)
  1431  	} else {
  1432  		if segCtxSet {
  1433  			output, err = s.snsClient.GetSubscriptionAttributesWithContext(segCtx, input)
  1434  		} else {
  1435  			output, err = s.snsClient.GetSubscriptionAttributes(input)
  1436  		}
  1437  	}
  1438  
  1439  	// evaluate result
  1440  	if err != nil {
  1441  		err = errors.New("GetSubscriptionAttributes Failed: (Get Action) " + err.Error())
  1442  		return nil, err
  1443  	}
  1444  
  1445  	attributes = s.fromAwsGetSubscriptionAttributes(output.Attributes)
  1446  	return attributes, nil
  1447  }
  1448  
  1449  // SetSubscriptionAttribute will set or update a subscription attribute,
  1450  // For attribute value or Json format, see corresponding notes in Subscribe where applicable
  1451  func (s *SNS) SetSubscriptionAttribute(subscriptionArn string,
  1452  	attributeName snssubscribeattribute.SNSSubscribeAttribute,
  1453  	attributeValue string,
  1454  	timeOutDuration ...time.Duration) (err error) {
  1455  	segCtx := context.Background()
  1456  	segCtxSet := false
  1457  
  1458  	seg := xray.NewSegmentNullable("SNS-SetSubscriptionAttribute", s._parentSegment)
  1459  
  1460  	if seg != nil {
  1461  		segCtx = seg.Ctx
  1462  		segCtxSet = true
  1463  
  1464  		defer seg.Close()
  1465  		defer func() {
  1466  			_ = seg.Seg.AddMetadata("SNS-SetSubscriptionAttribute-SubscriptionArn", subscriptionArn)
  1467  			_ = seg.Seg.AddMetadata("SNS-SetSubscriptionAttribute-AttributeName", attributeName)
  1468  			_ = seg.Seg.AddMetadata("SNS-SetSubscriptionAttribute-AttributeValue", attributeValue)
  1469  
  1470  			if err != nil {
  1471  				_ = seg.Seg.AddError(err)
  1472  			}
  1473  		}()
  1474  	}
  1475  
  1476  	// validation
  1477  	if s.snsClient == nil {
  1478  		err = errors.New("SetSubscriptionAttribute Failed: " + "SNS Client is Required")
  1479  		return err
  1480  	}
  1481  
  1482  	if util.LenTrim(subscriptionArn) <= 0 {
  1483  		err = errors.New("SetSubscriptionAttribute Failed: " + "Subscription ARN is Required")
  1484  		return err
  1485  	}
  1486  
  1487  	if !attributeName.Valid() || attributeName == snssubscribeattribute.UNKNOWN {
  1488  		err = errors.New("SetSubscriptionAttribute Failed: " + "Attribute Name is Required")
  1489  		return err
  1490  	}
  1491  
  1492  	// create input object
  1493  	input := &sns.SetSubscriptionAttributesInput{
  1494  		SubscriptionArn: aws.String(subscriptionArn),
  1495  		AttributeName:   aws.String(attributeName.Key()),
  1496  		AttributeValue:  aws.String(attributeValue),
  1497  	}
  1498  
  1499  	// perform action
  1500  	if len(timeOutDuration) > 0 {
  1501  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1502  		defer cancel()
  1503  
  1504  		_, err = s.snsClient.SetSubscriptionAttributesWithContext(ctx, input)
  1505  	} else {
  1506  		if segCtxSet {
  1507  			_, err = s.snsClient.SetSubscriptionAttributesWithContext(segCtx, input)
  1508  		} else {
  1509  			_, err = s.snsClient.SetSubscriptionAttributes(input)
  1510  		}
  1511  	}
  1512  
  1513  	// evaluate result
  1514  	if err != nil {
  1515  		err = errors.New("SetSubscriptionAttribute Failed: (Set Action) " + err.Error())
  1516  		return err
  1517  	} else {
  1518  		return nil
  1519  	}
  1520  }
  1521  
  1522  // ----------------------------------------------------------------------------------------------------------------
  1523  // publisher methods
  1524  // ----------------------------------------------------------------------------------------------------------------
  1525  
  1526  // Publish will publish a message to a topic or target via topicArn or targetArn respectively,
  1527  // upon publish completed, the messageId is returned
  1528  //
  1529  // Parameters:
  1530  //  1. topicArn = required but mutually exclusive, either topicArn or targetArn must be set (but NOT BOTH)
  1531  //  2. targetArn = required but mutually exclusive, either topicArn or targetArn must be set (but NOT BOTH)
  1532  //  3. message = required, the message to publish, up to 256KB
  1533  //  4. subject = optional, only for email endpoints, up to 100 characters
  1534  //  5. attributes = optional, message attributes
  1535  //     a) Other than defining Endpoint attributes as indicated in note below,
  1536  //     b) attributes can also contain Message specific attributes for use for Subscriber Filter Policy and etc,
  1537  //     *) For example, custom attribute name and value for the message can be defined in this map as metadata,
  1538  //     so that when Subscriber receives it can apply filter policy etc (See Subscribe method Filter Policy for more info)
  1539  //     i.e attributes["customer_interests"] = "rugby"
  1540  //     i.e attributes["price_usd"] = 100
  1541  //  6. timeOutDuration = optional, indicates timeout value for context
  1542  //
  1543  // Message Attribute Keys:
  1544  //  1. ADM
  1545  //     a) AWS.SNS.MOBILE.ADM.TTL
  1546  //  2. APNs
  1547  //     a) AWS.SNS.MOBILE.APNS_MDM.TTL
  1548  //     b) AWS.SNS.MOBILE.APNS_MDM_SANDBOX.TTL
  1549  //     c) AWS.SNS.MOBILE.APNS_PASSBOOK.TTL
  1550  //     d) AWS.SNS.MOBILE.APNS_PASSBOOK_SANDBOX.TTL
  1551  //     e) AWS.SNS.MOBILE.APNS_SANDBOX.TTL
  1552  //     f) AWS.SNS.MOBILE.APNS_VOIP.TTL
  1553  //     g) AWS.SNS.MOBILE.APNS_VOIP_SANDBOX.TTL
  1554  //     h) AWS.SNS.MOBILE.APNS.COLLAPSE_ID
  1555  //     i) AWS.SNS.MOBILE.APNS.PRIORITY
  1556  //     j) AWS.SNS.MOBILE.APNS.PUSH_TYPE
  1557  //     k) AWS.SNS.MOBILE.APNS.TOPIC
  1558  //     l) AWS.SNS.MOBILE.APNS.TTL
  1559  //     m) AWS.SNS.MOBILE.PREFERRED_AUTHENTICATION_METHOD
  1560  //  3. Custom Message Attribute Key Value Pairs
  1561  //     a) For Use Against Subscriber Filter Policy Matching
  1562  func (s *SNS) Publish(topicArn string,
  1563  	targetArn string,
  1564  	message string,
  1565  	subject string,
  1566  	attributes map[string]*sns.MessageAttributeValue,
  1567  	timeOutDuration ...time.Duration) (messageId string, err error) {
  1568  	segCtx := context.Background()
  1569  	segCtxSet := false
  1570  
  1571  	seg := xray.NewSegmentNullable("SNS-Publish", s._parentSegment)
  1572  
  1573  	if seg != nil {
  1574  		segCtx = seg.Ctx
  1575  		segCtxSet = true
  1576  
  1577  		defer seg.Close()
  1578  		defer func() {
  1579  			_ = seg.Seg.AddMetadata("SNS-Publish-TopicArn", topicArn)
  1580  			_ = seg.Seg.AddMetadata("SNS-Publish-TargetArn", targetArn)
  1581  			_ = seg.Seg.AddMetadata("SNS-Publish-Message", message)
  1582  			_ = seg.Seg.AddMetadata("SNS-Publish-Subject", subject)
  1583  			_ = seg.Seg.AddMetadata("SNS-Publish-Attributes", attributes)
  1584  			_ = seg.Seg.AddMetadata("SNS-Publish-Result-MessageID", messageId)
  1585  
  1586  			if err != nil {
  1587  				_ = seg.Seg.AddError(err)
  1588  			}
  1589  		}()
  1590  	}
  1591  
  1592  	// validation
  1593  	if s.snsClient == nil {
  1594  		err = errors.New("Publish Failed: " + "SNS Client is Required")
  1595  		return "", err
  1596  	}
  1597  
  1598  	if util.LenTrim(topicArn) <= 0 && util.LenTrim(targetArn) <= 0 {
  1599  		err = errors.New("Publish Failed: " + "Either Topic ARN or Target ARN is Required")
  1600  		return "", err
  1601  	}
  1602  
  1603  	if util.LenTrim(message) <= 0 {
  1604  		err = errors.New("Publish Failed: " + "Message is Required")
  1605  		return "", err
  1606  	}
  1607  
  1608  	if len(subject) > 0 {
  1609  		if util.LenTrim(subject) > 100 {
  1610  			err = errors.New("Publish Failed: " + "Subject Maximum Characters is 100")
  1611  			return "", err
  1612  		}
  1613  	}
  1614  
  1615  	// create input object
  1616  	input := &sns.PublishInput{
  1617  		Message: aws.String(message),
  1618  	}
  1619  
  1620  	if util.LenTrim(topicArn) > 0 {
  1621  		input.TopicArn = aws.String(topicArn)
  1622  	}
  1623  
  1624  	if util.LenTrim(targetArn) > 0 {
  1625  		input.TargetArn = aws.String(targetArn)
  1626  	}
  1627  
  1628  	if util.LenTrim(subject) > 0 {
  1629  		input.Subject = aws.String(subject)
  1630  	}
  1631  
  1632  	if attributes != nil {
  1633  		input.MessageAttributes = attributes
  1634  	}
  1635  
  1636  	// perform action
  1637  	var output *sns.PublishOutput
  1638  
  1639  	if len(timeOutDuration) > 0 {
  1640  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1641  		defer cancel()
  1642  
  1643  		output, err = s.snsClient.PublishWithContext(ctx, input)
  1644  	} else {
  1645  		if segCtxSet {
  1646  			output, err = s.snsClient.PublishWithContext(segCtx, input)
  1647  		} else {
  1648  			output, err = s.snsClient.Publish(input)
  1649  		}
  1650  	}
  1651  
  1652  	// evaluate result
  1653  	if err != nil {
  1654  		err = errors.New("Publish Failed: (Publish Action) " + err.Error())
  1655  		return "", err
  1656  	} else {
  1657  		messageId = *output.MessageId
  1658  		return messageId, nil
  1659  	}
  1660  }
  1661  
  1662  // ----------------------------------------------------------------------------------------------------------------
  1663  // sms methods
  1664  // ----------------------------------------------------------------------------------------------------------------
  1665  
  1666  // SendSMS will send a message to a specific SMS phone number, where phone number is in E.164 format (+12095551212 for example where +1 is country code),
  1667  // upon sms successfully sent, the messageId is returned
  1668  //
  1669  // Parameters:
  1670  //  1. phoneNumber = required, phone number to deliver an SMS message. Use E.164 format (+12095551212 where +1 is country code)
  1671  //  2. message = required, the message to publish; max is 140 ascii characters (70 characters when in UCS-2 encoding)
  1672  //  3. timeOutDuration = optional, indicates timeout value for context
  1673  //
  1674  // Fixed Message Attributes Explained:
  1675  //  1. AWS.SNS.SMS.SenderID = A custom ID that contains 3-11 alphanumeric characters, including at least one letter and no spaces.
  1676  //     The sender ID is displayed as the message sender on the receiving device.
  1677  //     For example, you can use your business brand to make the message source easier to recognize.
  1678  //     Support for sender IDs varies by country and/or region.
  1679  //     For example, messages delivered to U.S. phone numbers will not display the sender ID.
  1680  //     For the countries and regions that support sender IDs, see Supported Regions and countries.
  1681  //     If you do not specify a sender ID, the message will display a long code as the sender ID in supported countries and regions.
  1682  //     For countries or regions that require an alphabetic sender ID, the message displays NOTICE as the sender ID.
  1683  //     This message-level attribute overrides the account-level attribute DefaultSenderID, which you set using the SetSMSAttributes request.
  1684  //  2. AWS.SNS.SMS.SMSType = The type of message that you are sending:
  1685  //     a) Promotional = (default) – Noncritical messages, such as marketing messages.
  1686  //     Amazon SNS optimizes the message delivery to incur the lowest cost.
  1687  //     b) Transactional = Critical messages that support customer transactions,
  1688  //     such as one-time passcodes for multi-factor authentication.
  1689  //     Amazon SNS optimizes the message delivery to achieve the highest reliability.
  1690  //     This message-level attribute overrides the account-level attribute DefaultSMSType,
  1691  //     which you set using the SetSMSAttributes request.
  1692  func (s *SNS) SendSMS(phoneNumber string,
  1693  	message string,
  1694  	timeOutDuration ...time.Duration) (messageId string, err error) {
  1695  	segCtx := context.Background()
  1696  	segCtxSet := false
  1697  
  1698  	seg := xray.NewSegmentNullable("SNS-SendSMS", s._parentSegment)
  1699  
  1700  	if seg != nil {
  1701  		segCtx = seg.Ctx
  1702  		segCtxSet = true
  1703  
  1704  		defer seg.Close()
  1705  		defer func() {
  1706  			_ = seg.Seg.AddMetadata("SNS-SendSMS-Phone", phoneNumber)
  1707  			_ = seg.Seg.AddMetadata("SNS-SendSMS-Message", message)
  1708  			_ = seg.Seg.AddMetadata("SNS-SendSMS-Result-MessageID", messageId)
  1709  
  1710  			if err != nil {
  1711  				_ = seg.Seg.AddError(err)
  1712  			}
  1713  		}()
  1714  	}
  1715  
  1716  	// validation
  1717  	if s.snsClient == nil {
  1718  		err = errors.New("SendSMS Failed: " + "SNS Client is Required")
  1719  		return "", err
  1720  	}
  1721  
  1722  	if util.LenTrim(phoneNumber) <= 0 {
  1723  		err = errors.New("SendSMS Failed: " + "SMS Phone Number is Required")
  1724  		return "", err
  1725  	}
  1726  
  1727  	if util.LenTrim(message) <= 0 {
  1728  		err = errors.New("SendSMS Failed: " + "Message is Required")
  1729  		return "", err
  1730  	}
  1731  
  1732  	if len(message) > 140 {
  1733  		err = errors.New("SendSMS Failed: " + "SMS Text Message Maximum Characters Limited to 140")
  1734  		return "", err
  1735  	}
  1736  
  1737  	// fixed attributes
  1738  	m := make(map[string]*sns.MessageAttributeValue)
  1739  
  1740  	if util.LenTrim(s.SMSSenderName) > 0 {
  1741  		m["AWS.SNS.SMS.SenderID"] = &sns.MessageAttributeValue{StringValue: aws.String(s.SMSSenderName), DataType: aws.String("String")}
  1742  	}
  1743  
  1744  	smsTypeName := "Promotional"
  1745  
  1746  	if s.SMSTransactional {
  1747  		smsTypeName = "Transactional"
  1748  	}
  1749  
  1750  	m["AWS.SNS.SMS.SMSType"] = &sns.MessageAttributeValue{StringValue: aws.String(smsTypeName), DataType: aws.String("String")}
  1751  
  1752  	// create input object
  1753  	input := &sns.PublishInput{
  1754  		PhoneNumber:       aws.String(phoneNumber),
  1755  		Message:           aws.String(message),
  1756  		MessageAttributes: m,
  1757  	}
  1758  
  1759  	// perform action
  1760  	var output *sns.PublishOutput
  1761  
  1762  	if len(timeOutDuration) > 0 {
  1763  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1764  		defer cancel()
  1765  
  1766  		output, err = s.snsClient.PublishWithContext(ctx, input)
  1767  	} else {
  1768  		if segCtxSet {
  1769  			output, err = s.snsClient.PublishWithContext(segCtx, input)
  1770  		} else {
  1771  			output, err = s.snsClient.Publish(input)
  1772  		}
  1773  	}
  1774  
  1775  	// evaluate result
  1776  	if err != nil {
  1777  		err = errors.New("SendSMS Failed: (SMS Send Action) " + err.Error())
  1778  		return "", err
  1779  	} else {
  1780  		messageId = *output.MessageId
  1781  		return messageId, nil
  1782  	}
  1783  }
  1784  
  1785  // OptInPhoneNumber will opt in a SMS phone number to SNS for receiving messages (explict allow),
  1786  // returns nil if successful, otherwise error info is returned
  1787  //
  1788  // Parameters:
  1789  //  1. phoneNumber = required, phone number to opt in. Use E.164 format (+12095551212 where +1 is country code)
  1790  //  2. timeOutDuration = optional, indicates timeout value for context
  1791  func (s *SNS) OptInPhoneNumber(phoneNumber string, timeOutDuration ...time.Duration) (err error) {
  1792  	segCtx := context.Background()
  1793  	segCtxSet := false
  1794  
  1795  	seg := xray.NewSegmentNullable("SNS-OptInPhoneNumber", s._parentSegment)
  1796  
  1797  	if seg != nil {
  1798  		segCtx = seg.Ctx
  1799  		segCtxSet = true
  1800  
  1801  		defer seg.Close()
  1802  		defer func() {
  1803  			_ = seg.Seg.AddMetadata("SNS-OptInPhoneNumber-Phone", phoneNumber)
  1804  
  1805  			if err != nil {
  1806  				_ = seg.Seg.AddError(err)
  1807  			}
  1808  		}()
  1809  	}
  1810  
  1811  	// validation
  1812  	if s.snsClient == nil {
  1813  		err = errors.New("OptInPhoneNumber Failed: " + "SNS Client is Required")
  1814  		return err
  1815  	}
  1816  
  1817  	if util.LenTrim(phoneNumber) <= 0 {
  1818  		err = errors.New("OptInPhoneNumber Failed: " + "Phone Number is Required, in E.164 Format (i.e. +12095551212)")
  1819  		return err
  1820  	}
  1821  
  1822  	// create input object
  1823  	input := &sns.OptInPhoneNumberInput{
  1824  		PhoneNumber: aws.String(phoneNumber),
  1825  	}
  1826  
  1827  	// perform action
  1828  	if len(timeOutDuration) > 0 {
  1829  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1830  		defer cancel()
  1831  
  1832  		_, err = s.snsClient.OptInPhoneNumberWithContext(ctx, input)
  1833  	} else {
  1834  		if segCtxSet {
  1835  			_, err = s.snsClient.OptInPhoneNumberWithContext(segCtx, input)
  1836  		} else {
  1837  			_, err = s.snsClient.OptInPhoneNumber(input)
  1838  		}
  1839  	}
  1840  
  1841  	// evaluate result
  1842  	if err != nil {
  1843  		err = errors.New("OptInPhoneNumber Failed: (Action) " + err.Error())
  1844  		return err
  1845  	} else {
  1846  		return nil
  1847  	}
  1848  }
  1849  
  1850  // CheckIfPhoneNumberIsOptedOut will verify if a phone number is opted out of message reception
  1851  //
  1852  // Parameters:
  1853  //  1. phoneNumber = required, phone number to check if opted out. Use E.164 format (+12095551212 where +1 is country code)
  1854  //  2. timeOutDuration = optional, indicates timeout value for context
  1855  //
  1856  // Return Values:
  1857  //  1. optedOut = bool indicating if the given phone via input parameter was opted out (true), or not (false)
  1858  //  2. err = error info if any
  1859  func (s *SNS) CheckIfPhoneNumberIsOptedOut(phoneNumber string, timeOutDuration ...time.Duration) (optedOut bool, err error) {
  1860  	segCtx := context.Background()
  1861  	segCtxSet := false
  1862  
  1863  	seg := xray.NewSegmentNullable("SNS-CheckIfPhoneNumberIsOptedOutParentSegment", s._parentSegment)
  1864  
  1865  	if seg != nil {
  1866  		segCtx = seg.Ctx
  1867  		segCtxSet = true
  1868  
  1869  		defer seg.Close()
  1870  		defer func() {
  1871  			_ = seg.Seg.AddMetadata("SNS-CheckIfPhoneNumberIsOptedOut-Phone", phoneNumber)
  1872  			_ = seg.Seg.AddMetadata("SNS-CheckIfPhoneNumberIsOptedOut-Result-OptedOut", optedOut)
  1873  
  1874  			if err != nil {
  1875  				_ = seg.Seg.AddError(err)
  1876  			}
  1877  		}()
  1878  	}
  1879  
  1880  	// validation
  1881  	if s.snsClient == nil {
  1882  		err = errors.New("CheckIfPhoneNumberIsOptedOut Failed: " + "SNS Client is Required")
  1883  		return false, err
  1884  	}
  1885  
  1886  	if util.LenTrim(phoneNumber) <= 0 {
  1887  		err = errors.New("CheckIfPhoneNumberIsOptedOut Failed: " + "Phone Number is Required, in E.164 Format (i.e. +12095551212)")
  1888  		return false, err
  1889  	}
  1890  
  1891  	// create input object
  1892  	input := &sns.CheckIfPhoneNumberIsOptedOutInput{
  1893  		PhoneNumber: aws.String(phoneNumber),
  1894  	}
  1895  
  1896  	// perform action
  1897  	var output *sns.CheckIfPhoneNumberIsOptedOutOutput
  1898  
  1899  	if len(timeOutDuration) > 0 {
  1900  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1901  		defer cancel()
  1902  
  1903  		output, err = s.snsClient.CheckIfPhoneNumberIsOptedOutWithContext(ctx, input)
  1904  	} else {
  1905  		if segCtxSet {
  1906  			output, err = s.snsClient.CheckIfPhoneNumberIsOptedOutWithContext(segCtx, input)
  1907  		} else {
  1908  			output, err = s.snsClient.CheckIfPhoneNumberIsOptedOut(input)
  1909  		}
  1910  	}
  1911  
  1912  	// evaluate result
  1913  	if err != nil {
  1914  		err = errors.New("CheckIfPhoneNumberIsOptedOut Failed: (Action) " + err.Error())
  1915  		return false, err
  1916  	} else {
  1917  		optedOut = *output.IsOptedOut
  1918  		return optedOut, nil
  1919  	}
  1920  }
  1921  
  1922  // ListPhoneNumbersOptedOut will list opted out phone numbers, with optional nextToken for retrieving more list from a prior call
  1923  //
  1924  // Parameters:
  1925  //  1. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list
  1926  //  2. timeOutDuration = optional, indicates timeout value for context
  1927  //
  1928  // Return Values:
  1929  //  1. phonesList = string slice of opted out phone numbers, nil if not set
  1930  //  2. morePhonesNextToken = if there are more opted out phone numbers, this token is filled, to query more, use the token as input parameter, blank if no more
  1931  //  3. err = error info if any
  1932  func (s *SNS) ListPhoneNumbersOptedOut(nextToken string, timeOutDuration ...time.Duration) (phonesList []string, morePhonesNextToken string, err error) {
  1933  	segCtx := context.Background()
  1934  	segCtxSet := false
  1935  
  1936  	seg := xray.NewSegmentNullable("SNS-ListPhoneNumbersOptedOut", s._parentSegment)
  1937  
  1938  	if seg != nil {
  1939  		segCtx = seg.Ctx
  1940  		segCtxSet = true
  1941  
  1942  		defer seg.Close()
  1943  		defer func() {
  1944  			_ = seg.Seg.AddMetadata("SNS-ListPhoneNumbersOptedOut-NextToken", nextToken)
  1945  			_ = seg.Seg.AddMetadata("SNS-ListPhoneNumbersOptedOut-Result-PhonesList", phonesList)
  1946  			_ = seg.Seg.AddMetadata("SNS-ListPhoneNumbersOptedOut-Result-NextToken", morePhonesNextToken)
  1947  
  1948  			if err != nil {
  1949  				_ = seg.Seg.AddError(err)
  1950  			}
  1951  		}()
  1952  	}
  1953  
  1954  	// validation
  1955  	if s.snsClient == nil {
  1956  		err = errors.New("ListPhoneNumbersOptedOut Failed: " + "SNS Client is Required")
  1957  		return nil, "", err
  1958  	}
  1959  
  1960  	// create input object
  1961  	input := &sns.ListPhoneNumbersOptedOutInput{}
  1962  
  1963  	if util.LenTrim(nextToken) > 0 {
  1964  		input.NextToken = aws.String(nextToken)
  1965  	}
  1966  
  1967  	// perform action
  1968  	var output *sns.ListPhoneNumbersOptedOutOutput
  1969  
  1970  	if len(timeOutDuration) > 0 {
  1971  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  1972  		defer cancel()
  1973  
  1974  		output, err = s.snsClient.ListPhoneNumbersOptedOutWithContext(ctx, input)
  1975  	} else {
  1976  		if segCtxSet {
  1977  			output, err = s.snsClient.ListPhoneNumbersOptedOutWithContext(segCtx, input)
  1978  		} else {
  1979  			output, err = s.snsClient.ListPhoneNumbersOptedOut(input)
  1980  		}
  1981  	}
  1982  
  1983  	// evaluate result
  1984  	if err != nil {
  1985  		err = errors.New("ListPhoneNumbersOptedOut Failed: (Action) " + err.Error())
  1986  		return nil, "", err
  1987  	}
  1988  
  1989  	morePhonesNextToken = aws.StringValue(output.NextToken)
  1990  
  1991  	phonesList = aws.StringValueSlice(output.PhoneNumbers)
  1992  	return phonesList, morePhonesNextToken, nil
  1993  }
  1994  
  1995  // ----------------------------------------------------------------------------------------------------------------
  1996  // application endpoint APNS (Apple Push Notification Service) / FCM (Firebase Cloud Messaging) methods
  1997  // ----------------------------------------------------------------------------------------------------------------
  1998  
  1999  // CreatePlatformApplication will create a SNS platform application used for app notification via APNS, FCM, ADM etc.
  2000  // this method creates the application so that then Endpoint (devices that receives) for this application may be created to complete the setup.
  2001  //
  2002  // Once the application and endpoint is created, then for a device to Subscribe to a topic and receive SNS notifications
  2003  // via APNS, FCM, etc, the device will use the Subscribe's protocol as Application, and specify the Endpoint ARN accordingly.
  2004  //
  2005  // For the device to receive SNS notifications when provider Publish, the appropriate protocol specific setup is needed during
  2006  // Endpoint creation, for example, APNS requires to set private key and SSL certificate in Application Attributes' PlatformCredential and PlatformPrincipal (See notes below)
  2007  //
  2008  // In general, first create the Application via CreatePlatformApplication,
  2009  // Once application exists, then for each device that needs to receive SNS notification, create the appropriate Endpoint via CreatePlatformEndpoint
  2010  //
  2011  // Parameters:
  2012  //  1. name = required, platform application name
  2013  //  2. platform = required, the sns platform association with this application, such as APNS, FCM etc.
  2014  //  3. attributes = required, map of platform application attributes that defines specific values related to the chosen platform (see notes below)
  2015  //  4. timeOutDuration = optional, indicates timeout value for context
  2016  //
  2017  // Return Values:
  2018  //  1. platformApplicationArn = the created platform application's ARN
  2019  //  2. err = error info if any
  2020  //
  2021  // Platform Application Attributes: (Key = Expected Value)
  2022  //  1. PlatformCredential = The credential received from the notification service,
  2023  //     For APNS and APNS_SANDBOX, PlatformCredential is the private key
  2024  //     For GCM (Firebase Cloud Messaging), PlatformCredential is API key
  2025  //     For ADM, PlatformCredential is client secret
  2026  //  2. PlatformPrincipal = The principal received from the notification service,
  2027  //     For APNS and APNS_SANDBOX, PlatformPrincipal is SSL certificate
  2028  //     For GCM (Firebase Cloud Messaging), there is no PlatformPrincipal
  2029  //     For ADM, PlatformPrincipal is client id
  2030  //  3. EventEndpointCreated = Topic ARN to which EndpointCreated event notifications are sent
  2031  //  4. EventEndpointDeleted = Topic ARN to which EndpointDeleted event notifications are sent
  2032  //  5. EventEndpointUpdated = Topic ARN to which EndpointUpdate event notifications are sent
  2033  //  6. EventDeliveryFailure = Topic ARN to which DeliveryFailure event notifications are sent upon Direct Publish delivery failure (permanent) to one of the application's endpoints
  2034  //  7. SuccessFeedbackRoleArn = IAM role ARN used to give Amazon SNS write access to use CloudWatch Logs on your behalf
  2035  //  8. FailureFeedbackRoleArn = IAM role ARN used to give Amazon SNS write access to use CloudWatch Logs on your behalf
  2036  //  9. SuccessFeedbackSampleRate = Sample rate percentage (0-100) of successfully delivered messages
  2037  func (s *SNS) CreatePlatformApplication(name string,
  2038  	platform snsapplicationplatform.SNSApplicationPlatform,
  2039  	attributes map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string,
  2040  	timeOutDuration ...time.Duration) (platformApplicationArn string, err error) {
  2041  	segCtx := context.Background()
  2042  	segCtxSet := false
  2043  
  2044  	seg := xray.NewSegmentNullable("SNS-CreatePlatformApplication", s._parentSegment)
  2045  
  2046  	if seg != nil {
  2047  		segCtx = seg.Ctx
  2048  		segCtxSet = true
  2049  
  2050  		defer seg.Close()
  2051  		defer func() {
  2052  			_ = seg.Seg.AddMetadata("SNS-CreatePlatformApplication-Name", name)
  2053  			_ = seg.Seg.AddMetadata("SNS-CreatePlatformApplication-Platform", platform)
  2054  			_ = seg.Seg.AddMetadata("SNS-CreatePlatformApplication-Attributes", attributes)
  2055  			_ = seg.Seg.AddMetadata("SNS-CreatePlatformApplication-Result-PlatformApplicationArn", platformApplicationArn)
  2056  
  2057  			if err != nil {
  2058  				_ = seg.Seg.AddError(err)
  2059  			}
  2060  		}()
  2061  	}
  2062  
  2063  	// validation
  2064  	if s.snsClient == nil {
  2065  		err = errors.New("CreatePlatformApplication Failed: " + "SNS Client is Required")
  2066  		return "", err
  2067  	}
  2068  
  2069  	if util.LenTrim(name) <= 0 {
  2070  		err = errors.New("CreatePlatformApplication Failed: " + "Name is Required")
  2071  		return "", err
  2072  	}
  2073  
  2074  	if !platform.Valid() || platform == snsapplicationplatform.UNKNOWN {
  2075  		err = errors.New("CreatePlatformApplication Failed: " + "Platform is Required")
  2076  		return "", err
  2077  	}
  2078  
  2079  	if attributes == nil {
  2080  		err = errors.New("CreatePlatformApplication Failed: " + "Attributes Map is Required")
  2081  		return "", err
  2082  	}
  2083  
  2084  	// create input object
  2085  	input := &sns.CreatePlatformApplicationInput{
  2086  		Name:       aws.String(name),
  2087  		Platform:   aws.String(platform.Key()),
  2088  		Attributes: s.toAwsPlatformApplicationAttributes(attributes),
  2089  	}
  2090  
  2091  	// perform action
  2092  	var output *sns.CreatePlatformApplicationOutput
  2093  
  2094  	if len(timeOutDuration) > 0 {
  2095  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2096  		defer cancel()
  2097  
  2098  		output, err = s.snsClient.CreatePlatformApplicationWithContext(ctx, input)
  2099  	} else {
  2100  		if segCtxSet {
  2101  			output, err = s.snsClient.CreatePlatformApplicationWithContext(segCtx, input)
  2102  		} else {
  2103  			output, err = s.snsClient.CreatePlatformApplication(input)
  2104  		}
  2105  	}
  2106  
  2107  	// evaluate result
  2108  	if err != nil {
  2109  		err = errors.New("CreatePlatformApplication Failed: (Create Action) " + err.Error())
  2110  		return "", err
  2111  	} else {
  2112  		platformApplicationArn = *output.PlatformApplicationArn
  2113  		return platformApplicationArn, nil
  2114  	}
  2115  }
  2116  
  2117  // DeletePlatformApplication will delete a platform application by platformApplicationArn,
  2118  // returns nil if successful, otherwise error info is returned
  2119  //
  2120  // Parameters:
  2121  //  1. platformApplicationArn = the platform application to delete via platform application ARN specified
  2122  //  2. timeOutDuration = optional, indicates timeout value for context
  2123  func (s *SNS) DeletePlatformApplication(platformApplicationArn string, timeOutDuration ...time.Duration) (err error) {
  2124  	segCtx := context.Background()
  2125  	segCtxSet := false
  2126  
  2127  	seg := xray.NewSegmentNullable("SNS-DeletePlatformApplication", s._parentSegment)
  2128  
  2129  	if seg != nil {
  2130  		segCtx = seg.Ctx
  2131  		segCtxSet = true
  2132  
  2133  		defer seg.Close()
  2134  		defer func() {
  2135  			_ = seg.Seg.AddMetadata("SNS-DeletePlatformApplication-PlatformApplicationArn", platformApplicationArn)
  2136  
  2137  			if err != nil {
  2138  				_ = seg.Seg.AddError(err)
  2139  			}
  2140  		}()
  2141  	}
  2142  
  2143  	// validation
  2144  	if s.snsClient == nil {
  2145  		err = errors.New("DeletePlatformApplication Failed: " + "SNS Client is Required")
  2146  		return err
  2147  	}
  2148  
  2149  	if util.LenTrim(platformApplicationArn) <= 0 {
  2150  		err = errors.New("DeletePlatformApplication Failed: " + "Platform Application ARN is Required")
  2151  		return err
  2152  	}
  2153  
  2154  	// create input object
  2155  	input := &sns.DeletePlatformApplicationInput{
  2156  		PlatformApplicationArn: aws.String(platformApplicationArn),
  2157  	}
  2158  
  2159  	// perform action
  2160  	if len(timeOutDuration) > 0 {
  2161  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2162  		defer cancel()
  2163  
  2164  		_, err = s.snsClient.DeletePlatformApplicationWithContext(ctx, input)
  2165  	} else {
  2166  		if segCtxSet {
  2167  			_, err = s.snsClient.DeletePlatformApplicationWithContext(segCtx, input)
  2168  		} else {
  2169  			_, err = s.snsClient.DeletePlatformApplication(input)
  2170  		}
  2171  	}
  2172  
  2173  	// evaluate result
  2174  	if err != nil {
  2175  		err = errors.New("DeletePlatformApplication Failed: (Delete Action) " + err.Error())
  2176  		return err
  2177  	} else {
  2178  		return nil
  2179  	}
  2180  }
  2181  
  2182  // ListPlatformApplications will list platform application ARNs, with optional nextToken for retrieving more list from a prior call
  2183  //
  2184  // Parameters:
  2185  //  1. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list
  2186  //  2. timeOutDuration = optional, indicates timeout value for context
  2187  //
  2188  // Return Values:
  2189  //  1. platformApplicationArnsList = string slice of platform application ARNs, nil if not set
  2190  //  2. moreAppArnsNextToken = if there are more platform application ARNs, this token is filled, to query more, use the token as input parameter, blank if no more
  2191  //  3. err = error info if any
  2192  func (s *SNS) ListPlatformApplications(nextToken string, timeOutDuration ...time.Duration) (platformApplicationArnsList []string, moreAppArnsNextToken string, err error) {
  2193  	segCtx := context.Background()
  2194  	segCtxSet := false
  2195  
  2196  	seg := xray.NewSegmentNullable("SNS-ListPlatformApplications", s._parentSegment)
  2197  
  2198  	if seg != nil {
  2199  		segCtx = seg.Ctx
  2200  		segCtxSet = true
  2201  
  2202  		defer seg.Close()
  2203  		defer func() {
  2204  			_ = seg.Seg.AddMetadata("SNS-ListPlatformApplications-NextToken", nextToken)
  2205  			_ = seg.Seg.AddMetadata("SNS-ListPlatformApplications-Result-PlatformApplicationArnsList", platformApplicationArnsList)
  2206  			_ = seg.Seg.AddMetadata("SNS-ListPlatformApplications-Result-NextToken", moreAppArnsNextToken)
  2207  
  2208  			if err != nil {
  2209  				_ = seg.Seg.AddError(err)
  2210  			}
  2211  		}()
  2212  	}
  2213  
  2214  	// validation
  2215  	if s.snsClient == nil {
  2216  		err = errors.New("ListPlatformApplications Failed: " + "SNS Client is Required")
  2217  		return nil, "", err
  2218  	}
  2219  
  2220  	// create input object
  2221  	input := &sns.ListPlatformApplicationsInput{}
  2222  
  2223  	if util.LenTrim(nextToken) > 0 {
  2224  		input.NextToken = aws.String(nextToken)
  2225  	}
  2226  
  2227  	// perform action
  2228  	var output *sns.ListPlatformApplicationsOutput
  2229  
  2230  	if len(timeOutDuration) > 0 {
  2231  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2232  		defer cancel()
  2233  
  2234  		output, err = s.snsClient.ListPlatformApplicationsWithContext(ctx, input)
  2235  	} else {
  2236  		if segCtxSet {
  2237  			output, err = s.snsClient.ListPlatformApplicationsWithContext(segCtx, input)
  2238  		} else {
  2239  			output, err = s.snsClient.ListPlatformApplications(input)
  2240  		}
  2241  	}
  2242  
  2243  	// evaluate result
  2244  	if err != nil {
  2245  		err = errors.New("ListPlatformApplications Failed: (List Action) " + err.Error())
  2246  		return nil, "", err
  2247  	}
  2248  
  2249  	moreAppArnsNextToken = aws.StringValue(output.NextToken)
  2250  
  2251  	for _, v := range output.PlatformApplications {
  2252  		if v != nil {
  2253  			if v1 := aws.StringValue(v.PlatformApplicationArn); util.LenTrim(v1) > 0 {
  2254  				platformApplicationArnsList = append(platformApplicationArnsList, v1)
  2255  			}
  2256  		}
  2257  	}
  2258  
  2259  	return platformApplicationArnsList, moreAppArnsNextToken, nil
  2260  }
  2261  
  2262  // GetPlatformApplicationAttributes will retrieve application attributes based on a specific platform application ARN
  2263  //
  2264  // Parameters:
  2265  //  1. platformApplicationArn = required, the platform application ARN used to retrieve related application attributes
  2266  //  2. timeOutDuration = optional, indicates timeout value for context
  2267  //
  2268  // Return Values:
  2269  //  1. attributes = map of sns platform application attributes related to the given platform application ARN
  2270  //  2. err = error info if any
  2271  func (s *SNS) GetPlatformApplicationAttributes(platformApplicationArn string, timeOutDuration ...time.Duration) (attributes map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string, err error) {
  2272  	segCtx := context.Background()
  2273  	segCtxSet := false
  2274  
  2275  	seg := xray.NewSegmentNullable("SNS-GetPlatformApplicationAttributes", s._parentSegment)
  2276  
  2277  	if seg != nil {
  2278  		segCtx = seg.Ctx
  2279  		segCtxSet = true
  2280  
  2281  		defer seg.Close()
  2282  		defer func() {
  2283  			_ = seg.Seg.AddMetadata("SNS-GetPlatformApplicationAttributes-PlatformApplicationArn", platformApplicationArn)
  2284  			_ = seg.Seg.AddMetadata("SNS-GetPlatformApplicationAttributes-Result-Attributes", attributes)
  2285  
  2286  			if err != nil {
  2287  				_ = seg.Seg.AddError(err)
  2288  			}
  2289  		}()
  2290  	}
  2291  
  2292  	// validation
  2293  	if s.snsClient == nil {
  2294  		err = errors.New("GetPlatformApplicationAttributes Failed: " + "SNS Client is Required")
  2295  		return nil, err
  2296  	}
  2297  
  2298  	if util.LenTrim(platformApplicationArn) <= 0 {
  2299  		err = errors.New("GetPlatformApplicationAttributes Failed: " + "Platform Application ARN is Required")
  2300  		return nil, err
  2301  	}
  2302  
  2303  	// create input object
  2304  	input := &sns.GetPlatformApplicationAttributesInput{
  2305  		PlatformApplicationArn: aws.String(platformApplicationArn),
  2306  	}
  2307  
  2308  	// perform action
  2309  	var output *sns.GetPlatformApplicationAttributesOutput
  2310  
  2311  	if len(timeOutDuration) > 0 {
  2312  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2313  		defer cancel()
  2314  
  2315  		output, err = s.snsClient.GetPlatformApplicationAttributesWithContext(ctx, input)
  2316  	} else {
  2317  		if segCtxSet {
  2318  			output, err = s.snsClient.GetPlatformApplicationAttributesWithContext(segCtx, input)
  2319  		} else {
  2320  			output, err = s.snsClient.GetPlatformApplicationAttributes(input)
  2321  		}
  2322  	}
  2323  
  2324  	// evaluate result
  2325  	if err != nil {
  2326  		err = errors.New("GetPlatformApplicationAttributes Failed: (Get Action) " + err.Error())
  2327  		return nil, err
  2328  	}
  2329  
  2330  	attributes = s.fromAwsPlatformApplicationAttributes(output.Attributes)
  2331  	return attributes, nil
  2332  }
  2333  
  2334  // SetPlatformApplicationAttributes will set or update platform application attributes,
  2335  // For attribute value or Json format, see corresponding notes in CreatePlatformApplication where applicable
  2336  func (s *SNS) SetPlatformApplicationAttributes(platformApplicationArn string,
  2337  	attributes map[snsplatformapplicationattribute.SNSPlatformApplicationAttribute]string,
  2338  	timeOutDuration ...time.Duration) (err error) {
  2339  	segCtx := context.Background()
  2340  	segCtxSet := false
  2341  
  2342  	seg := xray.NewSegmentNullable("SNS-SetPlatformApplicationAttributes", s._parentSegment)
  2343  
  2344  	if seg != nil {
  2345  		segCtx = seg.Ctx
  2346  		segCtxSet = true
  2347  
  2348  		defer seg.Close()
  2349  		defer func() {
  2350  			_ = seg.Seg.AddMetadata("SNS-SetPlatformApplicationAttributes-PlatformApplicationArn", platformApplicationArn)
  2351  			_ = seg.Seg.AddMetadata("SNS-SetPlatformApplicationAttributes-Attributes", attributes)
  2352  
  2353  			if err != nil {
  2354  				_ = seg.Seg.AddError(err)
  2355  			}
  2356  		}()
  2357  	}
  2358  
  2359  	if s.snsClient == nil {
  2360  		err = errors.New("SetPlatformApplicationAttributes Failed: " + "SNS Client is Required")
  2361  		return err
  2362  	}
  2363  
  2364  	if util.LenTrim(platformApplicationArn) <= 0 {
  2365  		err = errors.New("SetPlatformApplicationAttributes Failed: " + "Platform Application ARN is Required")
  2366  		return err
  2367  	}
  2368  
  2369  	if attributes == nil {
  2370  		err = errors.New("SetPlatformApplicationAttributes Failed: " + "Attributes Map is Required")
  2371  		return err
  2372  	}
  2373  
  2374  	// create input
  2375  	input := &sns.SetPlatformApplicationAttributesInput{
  2376  		PlatformApplicationArn: aws.String(platformApplicationArn),
  2377  		Attributes:             s.toAwsPlatformApplicationAttributes(attributes),
  2378  	}
  2379  
  2380  	// perform action
  2381  	if len(timeOutDuration) > 0 {
  2382  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2383  		defer cancel()
  2384  
  2385  		_, err = s.snsClient.SetPlatformApplicationAttributesWithContext(ctx, input)
  2386  	} else {
  2387  		if segCtxSet {
  2388  			_, err = s.snsClient.SetPlatformApplicationAttributesWithContext(segCtx, input)
  2389  		} else {
  2390  			_, err = s.snsClient.SetPlatformApplicationAttributes(input)
  2391  		}
  2392  	}
  2393  
  2394  	// evaluate result
  2395  	if err != nil {
  2396  		err = errors.New("SetPlatformApplicationAttributes Failed: (Set Action) " + err.Error())
  2397  		return err
  2398  	} else {
  2399  		return nil
  2400  	}
  2401  }
  2402  
  2403  // CreatePlatformEndpoint will create a device endpoint for a specific platform application,
  2404  // this is the endpoint that will receive SNS notifications via defined protocol such as APNS or FCM
  2405  //
  2406  // Parameters:
  2407  //  1. platformApplicationArn = required, Plaform application ARN that was created, endpoint is added to this platform application
  2408  //  2. token = Unique identifier created by the notification service for an app on a device,
  2409  //     The specific name for Token will vary, depending on which notification service is being used,
  2410  //     For example, when using APNS as the notification service, you need the device token,
  2411  //     Alternatively, when using FCM or ADM, the device token equivalent is called the registration ID
  2412  //  3. customUserData = optional, Arbitrary user data to associate with the endpoint,
  2413  //     Amazon SNS does not use this data. The data must be in UTF-8 format and less than 2KB
  2414  //  4. timeOutDuration = optional, indicates timeout value for context
  2415  //
  2416  // Return Values:
  2417  //  1. endpointArn = the created endpoint ARN
  2418  //  2. err = the error info if any
  2419  func (s *SNS) CreatePlatformEndpoint(platformApplicationArn string,
  2420  	token string,
  2421  	customUserData string,
  2422  	timeOutDuration ...time.Duration) (endpointArn string, err error) {
  2423  	segCtx := context.Background()
  2424  	segCtxSet := false
  2425  
  2426  	seg := xray.NewSegmentNullable("SNS-CreatePlatformEndpoint", s._parentSegment)
  2427  
  2428  	if seg != nil {
  2429  		segCtx = seg.Ctx
  2430  		segCtxSet = true
  2431  
  2432  		defer seg.Close()
  2433  		defer func() {
  2434  			_ = seg.Seg.AddMetadata("SNS-CreatePlatformEndpoint-PlatformApplicationArn", platformApplicationArn)
  2435  			_ = seg.Seg.AddMetadata("SNS-CreatePlatformEndpoint-Token", token)
  2436  			_ = seg.Seg.AddMetadata("SNS-CreatePlatformEndpoint-CustomUserData", customUserData)
  2437  			_ = seg.Seg.AddMetadata("SNS-CreatePlatformEndpoint-Result-EndpointArn", endpointArn)
  2438  
  2439  			if err != nil {
  2440  				_ = seg.Seg.AddError(err)
  2441  			}
  2442  		}()
  2443  	}
  2444  
  2445  	// validation
  2446  	if s.snsClient == nil {
  2447  		err = errors.New("CreatePlatformEndpoint Failed: " + "SNS Client is Required")
  2448  		return "", err
  2449  	}
  2450  
  2451  	if util.LenTrim(platformApplicationArn) <= 0 {
  2452  		err = errors.New("CreatePlatformEndpoint Failed: " + "Platform Application ARN is Required")
  2453  		return "", err
  2454  	}
  2455  
  2456  	if util.LenTrim(token) <= 0 {
  2457  		err = errors.New("CreatePlatformEndpoint Failed: " + "Token is Required")
  2458  		return "", err
  2459  	}
  2460  
  2461  	// create input object
  2462  	input := &sns.CreatePlatformEndpointInput{
  2463  		PlatformApplicationArn: aws.String(platformApplicationArn),
  2464  		Token:                  aws.String(token),
  2465  	}
  2466  
  2467  	if util.LenTrim(customUserData) > 0 {
  2468  		input.CustomUserData = aws.String(customUserData)
  2469  	}
  2470  
  2471  	// perform action
  2472  	var output *sns.CreatePlatformEndpointOutput
  2473  
  2474  	if len(timeOutDuration) > 0 {
  2475  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2476  		defer cancel()
  2477  
  2478  		output, err = s.snsClient.CreatePlatformEndpointWithContext(ctx, input)
  2479  	} else {
  2480  		if segCtxSet {
  2481  			output, err = s.snsClient.CreatePlatformEndpointWithContext(segCtx, input)
  2482  		} else {
  2483  			output, err = s.snsClient.CreatePlatformEndpoint(input)
  2484  		}
  2485  	}
  2486  
  2487  	// evaluate result
  2488  	if err != nil {
  2489  		err = errors.New("CreatePlatformEndpoint Failed: (Create Action) " + err.Error())
  2490  		return "", err
  2491  	} else {
  2492  		endpointArn = aws.StringValue(output.EndpointArn)
  2493  		return endpointArn, nil
  2494  	}
  2495  }
  2496  
  2497  // DeletePlatformEndpoint will delete an endpoint based on endpointArn,
  2498  // returns nil if successful, otherwise error info is returned
  2499  //
  2500  // Parameters:
  2501  //  1. endpointArn = required, the endpoint to delete
  2502  //  2. timeOutDuration = optional, indicates timeout value for context
  2503  func (s *SNS) DeletePlatformEndpoint(endpointArn string, timeOutDuration ...time.Duration) (err error) {
  2504  	segCtx := context.Background()
  2505  	segCtxSet := false
  2506  
  2507  	seg := xray.NewSegmentNullable("SNS-DeletePlatformEndpoint", s._parentSegment)
  2508  
  2509  	if seg != nil {
  2510  		segCtx = seg.Ctx
  2511  		segCtxSet = true
  2512  
  2513  		defer seg.Close()
  2514  		defer func() {
  2515  			_ = seg.Seg.AddMetadata("SNS-DeletePlatformEndpoint-EndpointArn", endpointArn)
  2516  
  2517  			if err != nil {
  2518  				_ = seg.Seg.AddError(err)
  2519  			}
  2520  		}()
  2521  	}
  2522  
  2523  	// validation
  2524  	if s.snsClient == nil {
  2525  		err = errors.New("DeletePlatformEndpoint Failed: " + "SNS Client is Required")
  2526  		return err
  2527  	}
  2528  
  2529  	if util.LenTrim(endpointArn) <= 0 {
  2530  		err = errors.New("DeletePlatformEndpoint Failed: " + "Endpoint ARN is Required")
  2531  		return err
  2532  	}
  2533  
  2534  	// create input object
  2535  	input := &sns.DeleteEndpointInput{
  2536  		EndpointArn: aws.String(endpointArn),
  2537  	}
  2538  
  2539  	// perform action
  2540  	if len(timeOutDuration) > 0 {
  2541  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2542  		defer cancel()
  2543  
  2544  		_, err = s.snsClient.DeleteEndpointWithContext(ctx, input)
  2545  	} else {
  2546  		if segCtxSet {
  2547  			_, err = s.snsClient.DeleteEndpointWithContext(segCtx, input)
  2548  		} else {
  2549  			_, err = s.snsClient.DeleteEndpoint(input)
  2550  		}
  2551  	}
  2552  
  2553  	// evaluate result
  2554  	if err != nil {
  2555  		err = errors.New("DeletePlatformEndpoint Failed: (Delete Action) " + err.Error())
  2556  		return err
  2557  	} else {
  2558  		return nil
  2559  	}
  2560  }
  2561  
  2562  // ListEndpointsByPlatformApplication will list endpoints by platform application, with optional nextToken for retrieving more list from a prior call
  2563  //
  2564  // Parameters:
  2565  //  1. platformApplicationArn = required, the platform application to filter for its related endpoints to retrieve
  2566  //  2. nextToken = optional, if prior call returned more...token, pass in here to retrieve the related list
  2567  //  3. timeOutDuration = optional, indicates timeout value for context
  2568  //
  2569  // Return Values:
  2570  //  1. endpointArnsList = string slice of endpoint ARNs under the given platform application ARN, nil if not set
  2571  //  2. moreEndpointArnsNextToken = if there are more endpoints to load, this token is filled, to query more, use the token as input parameter, blank if no more
  2572  //  3. err = error info if any
  2573  func (s *SNS) ListEndpointsByPlatformApplication(platformApplicationArn string,
  2574  	nextToken string,
  2575  	timeOutDuration ...time.Duration) (endpointArnsList []string, moreEndpointArnsNextToken string, err error) {
  2576  	segCtx := context.Background()
  2577  	segCtxSet := false
  2578  
  2579  	seg := xray.NewSegmentNullable("SNS-ListEndpointsByPlatformApplication", s._parentSegment)
  2580  
  2581  	if seg != nil {
  2582  		segCtx = seg.Ctx
  2583  		segCtxSet = true
  2584  
  2585  		defer seg.Close()
  2586  		defer func() {
  2587  			_ = seg.Seg.AddMetadata("SNS-ListEndpointsByPlatformApplication-PlatformApplicationArn", platformApplicationArn)
  2588  			_ = seg.Seg.AddMetadata("SNS-ListEndpointsByPlatformApplication-NextToken", nextToken)
  2589  			_ = seg.Seg.AddMetadata("SNS-ListEndpointsByPlatformApplication-Result-EndpointArnsList", endpointArnsList)
  2590  			_ = seg.Seg.AddMetadata("SNS-ListEndpointsByPlatformApplication-Result-NextToken", moreEndpointArnsNextToken)
  2591  
  2592  			if err != nil {
  2593  				_ = seg.Seg.AddError(err)
  2594  			}
  2595  		}()
  2596  	}
  2597  
  2598  	// validation
  2599  	if s.snsClient == nil {
  2600  		err = errors.New("ListEndpointsByPlatformApplication Failed: " + "SNS Client is Required")
  2601  		return nil, "", err
  2602  	}
  2603  
  2604  	if util.LenTrim(platformApplicationArn) <= 0 {
  2605  		err = errors.New("ListEndpointsByPlatformApplication Failed: " + "Platform Application ARN is Required")
  2606  		return nil, "", err
  2607  	}
  2608  
  2609  	// create input object
  2610  	input := &sns.ListEndpointsByPlatformApplicationInput{
  2611  		PlatformApplicationArn: aws.String(platformApplicationArn),
  2612  	}
  2613  
  2614  	if util.LenTrim(nextToken) > 0 {
  2615  		input.NextToken = aws.String(nextToken)
  2616  	}
  2617  
  2618  	// perform action
  2619  	var output *sns.ListEndpointsByPlatformApplicationOutput
  2620  
  2621  	if len(timeOutDuration) > 0 {
  2622  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2623  		defer cancel()
  2624  
  2625  		output, err = s.snsClient.ListEndpointsByPlatformApplicationWithContext(ctx, input)
  2626  	} else {
  2627  		if segCtxSet {
  2628  			output, err = s.snsClient.ListEndpointsByPlatformApplicationWithContext(segCtx, input)
  2629  		} else {
  2630  			output, err = s.snsClient.ListEndpointsByPlatformApplication(input)
  2631  		}
  2632  	}
  2633  
  2634  	// evaluate result
  2635  	if err != nil {
  2636  		err = errors.New("ListEndpointsByPlatformApplication Failed: (List Action) " + err.Error())
  2637  		return nil, "", err
  2638  	}
  2639  
  2640  	moreEndpointArnsNextToken = aws.StringValue(output.NextToken)
  2641  
  2642  	for _, v := range output.Endpoints {
  2643  		if v != nil {
  2644  			if v1 := aws.StringValue(v.EndpointArn); util.LenTrim(v1) > 0 {
  2645  				endpointArnsList = append(endpointArnsList, v1)
  2646  			}
  2647  		}
  2648  	}
  2649  
  2650  	return endpointArnsList, moreEndpointArnsNextToken, nil
  2651  }
  2652  
  2653  // GetPlatformEndpointAttributes will retrieve endpoint attributes based on a specific endpoint ARN
  2654  //
  2655  // Parameters:
  2656  //  1. endpointArn = required, the endpoint ARN used to retrieve related endpoint attributes
  2657  //  2. timeOutDuration = optional, indicates timeout value for context
  2658  //
  2659  // Return Values:
  2660  //  1. attributes = map of sns endpoint attributes related to the given endpoint ARN
  2661  //  2. err = error info if any
  2662  //
  2663  // Endpoint Attributes: (Key = Expected Value)
  2664  //  1. CustomUserData = arbitrary user data to associate with the endpoint.
  2665  //     Amazon SNS does not use this data.
  2666  //     The data must be in UTF-8 format and less than 2KB.
  2667  //  2. Enabled = flag that enables/disables delivery to the endpoint. Amazon
  2668  //     SNS will set this to false when a notification service indicates to Amazon SNS that the endpoint is invalid.
  2669  //     Users can set it back to true, typically after updating Token.
  2670  //  3. Token = device token, also referred to as a registration id, for an app and mobile device.
  2671  //     This is returned from the notification service when an app and mobile device are registered with the notification service.
  2672  //     The device token for the iOS platform is returned in lowercase.
  2673  func (s *SNS) GetPlatformEndpointAttributes(endpointArn string, timeOutDuration ...time.Duration) (attributes map[snsendpointattribute.SNSEndpointAttribute]string, err error) {
  2674  	segCtx := context.Background()
  2675  	segCtxSet := false
  2676  
  2677  	seg := xray.NewSegmentNullable("SNS-GetPlatformEndpointAttributes", s._parentSegment)
  2678  
  2679  	if seg != nil {
  2680  		segCtx = seg.Ctx
  2681  		segCtxSet = true
  2682  
  2683  		defer seg.Close()
  2684  		defer func() {
  2685  			_ = seg.Seg.AddMetadata("SNS-GetPlatformEndpointAttributes-EndpointArn", endpointArn)
  2686  			_ = seg.Seg.AddMetadata("SNS-GetPlatformEndpointAttributes-Result-Attributes", attributes)
  2687  
  2688  			if err != nil {
  2689  				_ = seg.Seg.AddError(err)
  2690  			}
  2691  		}()
  2692  	}
  2693  
  2694  	// validation
  2695  	if s.snsClient == nil {
  2696  		err = errors.New("GetPlatformEndpointAttributes Failed: " + "SNS Client is Required")
  2697  		return nil, err
  2698  	}
  2699  
  2700  	if util.LenTrim(endpointArn) <= 0 {
  2701  		err = errors.New("GetPlatformEndpointAttributes Failed: " + "Endpoint ARN is Required")
  2702  		return nil, err
  2703  	}
  2704  
  2705  	// create input object
  2706  	input := &sns.GetEndpointAttributesInput{
  2707  		EndpointArn: aws.String(endpointArn),
  2708  	}
  2709  
  2710  	// perform action
  2711  	var output *sns.GetEndpointAttributesOutput
  2712  
  2713  	if len(timeOutDuration) > 0 {
  2714  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2715  		defer cancel()
  2716  
  2717  		output, err = s.snsClient.GetEndpointAttributesWithContext(ctx, input)
  2718  	} else {
  2719  		if segCtxSet {
  2720  			output, err = s.snsClient.GetEndpointAttributesWithContext(segCtx, input)
  2721  		} else {
  2722  			output, err = s.snsClient.GetEndpointAttributes(input)
  2723  		}
  2724  	}
  2725  
  2726  	// evaluate result
  2727  	if err != nil {
  2728  		err = errors.New("GetPlatformEndpointAttributes Failed: (Get Action) " + err.Error())
  2729  		return nil, err
  2730  	} else {
  2731  		attributes = s.fromAwsEndpointAttributes(output.Attributes)
  2732  		return attributes, nil
  2733  	}
  2734  }
  2735  
  2736  // SetPlatformEndpointAttributes will set or update platform endpoint attributes,
  2737  // For attribute value or Json format, see corresponding notes in CreatePlatformEndpoint where applicable
  2738  func (s *SNS) SetPlatformEndpointAttributes(endpointArn string,
  2739  	attributes map[snsendpointattribute.SNSEndpointAttribute]string,
  2740  	timeOutDuration ...time.Duration) (err error) {
  2741  	segCtx := context.Background()
  2742  	segCtxSet := false
  2743  
  2744  	seg := xray.NewSegmentNullable("SNS-SetPlatformEndpointAttributes", s._parentSegment)
  2745  
  2746  	if seg != nil {
  2747  		segCtx = seg.Ctx
  2748  		segCtxSet = true
  2749  
  2750  		defer seg.Close()
  2751  		defer func() {
  2752  			_ = seg.Seg.AddMetadata("SNS-SetPlatformEndpointAttributes-EndpointArn", endpointArn)
  2753  			_ = seg.Seg.AddMetadata("SNS-SetPlatformEndpointAttributes-Attributes", attributes)
  2754  
  2755  			if err != nil {
  2756  				_ = seg.Seg.AddError(err)
  2757  			}
  2758  		}()
  2759  	}
  2760  
  2761  	// validation
  2762  	if s.snsClient == nil {
  2763  		err = errors.New("SetPlatformEndpointAttributes Failed: " + "SNS Client is Required")
  2764  		return err
  2765  	}
  2766  
  2767  	if util.LenTrim(endpointArn) <= 0 {
  2768  		err = errors.New("SetPlatformEndpointAttributes Failed: " + "Endpoint ARN is Required")
  2769  		return err
  2770  	}
  2771  
  2772  	if attributes == nil {
  2773  		err = errors.New("SetPlatformEndpointAttributes Failed: " + "Attributes Map is Required")
  2774  		return err
  2775  	}
  2776  
  2777  	// create input
  2778  	input := &sns.SetEndpointAttributesInput{
  2779  		EndpointArn: aws.String(endpointArn),
  2780  		Attributes:  s.toAwsEndpointAttributes(attributes),
  2781  	}
  2782  
  2783  	// perform action
  2784  	if len(timeOutDuration) > 0 {
  2785  		ctx, cancel := context.WithTimeout(segCtx, timeOutDuration[0])
  2786  		defer cancel()
  2787  
  2788  		_, err = s.snsClient.SetEndpointAttributesWithContext(ctx, input)
  2789  	} else {
  2790  		if segCtxSet {
  2791  			_, err = s.snsClient.SetEndpointAttributesWithContext(segCtx, input)
  2792  		} else {
  2793  			_, err = s.snsClient.SetEndpointAttributes(input)
  2794  		}
  2795  	}
  2796  
  2797  	// evaluate result
  2798  	if err != nil {
  2799  		err = errors.New("SetPlatformEndpointAttributes Failed: (Set Action) " + err.Error())
  2800  		return err
  2801  	} else {
  2802  		return nil
  2803  	}
  2804  }