github.com/mweagle/Sparta@v1.15.0/docs_source/content/reference/decorators/cloudmap.md (about)

     1  ---
     2  date: 2019-05-27 22:31:25
     3  title: CloudMap Service Discovery
     4  weight: 10
     5  alwaysopen: false
     6  ---
     7  
     8  The [CloudMapServiceDecorator](https://godoc.org/github.com/mweagle/Sparta/decorator#CloudMapServiceDecorator) allows your service to register a [service instance](https://docs.aws.amazon.com/cloud-map/latest/dg/working-with-instances.html) for your application.
     9  
    10  For example, an application that provisions a SQS queue and an AWS Lambda function that consumes messages from that queue may need a way for the Lambda function to discover the dynamically provisioned queue.
    11  
    12  Sparta supports an environment-based [discovery service](http://gosparta.io/reference/discovery/) but that discovery is limited to a single Service.
    13  
    14  The `CloudMapServiceDecorator` leverages the [CloudMap](https://aws.amazon.com/cloud-map/) service to support intra- and inter-service resource discovery. 
    15  
    16  ## Definition
    17  
    18  The first step is to create an instance of the `CloudMapServiceDecorator` type that can be used to register additional resources.
    19  
    20  ```go
    21  import (
    22    spartaDecorators "github.com/mweagle/Sparta/decorator"
    23  )
    24  
    25  func main() {
    26  
    27    ...
    28    cloudMapDecorator, cloudMapDecoratorErr := spartaDecorators.NewCloudMapServiceDecorator(gocf.String("SpartaServices"),
    29      gocf.String("SpartaSampleCloudMapService"))
    30  ...
    31  }
    32  ```
    33  
    34  The first argument is the [Cloud Map Namespace ID](https://docs.aws.amazon.com/cloud-map/latest/dg/working-with-namespaces.html) value to which the service (_MyService_) will publish.
    35  
    36  The decorator satisfies the [ServiceDecoratorHookHandler](https://godoc.org/github.com/mweagle/Sparta#ServiceDecoratorHookHandler). The instance should be provided as a `WorkflowHooks.ServiceDecorators` element to `MainEx` as in:
    37  
    38  ```go
    39  func main() {
    40    // ...
    41    cloudMapDecorator, cloudMapDecoratorErr := spartaDecorators.NewCloudMapServiceDecorator(gocf.String("SpartaServices"),
    42      gocf.String("SpartaSampleCloudMapService"))
    43      
    44    workflowHooks := &sparta.WorkflowHooks{
    45      ServiceDecorators: []sparta.ServiceDecoratorHookHandler{
    46        cloudMapDecorator,
    47      },
    48    }
    49  
    50    // ...
    51    err := sparta.MainEx(awsName,
    52      "Simple Sparta application that demonstrates core functionality",
    53      lambdaFunctions,
    54      nil,
    55      nil,
    56      workflowHooks,
    57      false)
    58  }
    59  ```
    60  
    61  ## Registering
    62  
    63  The returned `CloudMapServiceDecorator` instance satisfies the [ServiceDecoratorHookHandler](https://godoc.org/github.com/mweagle/Sparta#ServiceDecoratorHookHandler) interface. When invoked, it updates the content of you CloudFormation template with the resources and permissions as described below. `CloudMapServiceDecorator` implicitly creates a new [AWS::ServiceDiscovery::Service](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-servicediscovery-service.html) resource to which your resources will be published.
    64  
    65  ### Lambda Functions
    66  
    67  The `CloudMapServiceDecorator.PublishLambda` function publishes Lambda function information to the _(NamespaceID, ServiceID)_ pair.
    68  
    69  ```go
    70  lambdaFn, _ := sparta.NewAWSLambda("Hello World",
    71      helloWorld,
    72      sparta.IAMRoleDefinition{})
    73  cloudMapDecorator.PublishLambda("lambdaDiscoveryName", lambdaFn, nil)
    74  ```
    75  
    76  The default properties published include the [Lambda Outputs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html) and Type information:
    77  
    78  ```json
    79  {
    80      "Id": "CloudMapResbe2b7c536074312c-VuIPjfjuFaoc",
    81      "Attributes": {
    82          "Arn": "arn:aws:lambda:us-west-2:123412341234:function:MyHelloWorldStack-123412341234_Hello_World",
    83          "Name": "lambdaDiscoveryName",
    84          "Ref": "MyHelloWorldStack-123412341234_Hello_World",
    85          "Type": "AWS::Lambda::Function"
    86      }
    87  }
    88  ```
    89  
    90  ### Other Resources
    91  
    92  The `CloudMapServiceDecorator.PublishResource` function publishes arbitrary CloudFormation resource outputs information to the _(NamespaceID, ServiceID)_ pair.
    93  
    94  For instance, to publish SQS information in the context of a standard `ServiceDecorator`
    95  
    96  ```go
    97  func createSQSResourceDecorator(cloudMapDecorator *spartaDecorators.CloudMapServiceDecorator) sparta.ServiceDecoratorHookHandler {
    98    return sparta.ServiceDecoratorHookFunc(func(context map[string]interface{},
    99      serviceName string,
   100      template *gocf.Template,
   101      S3Bucket string,
   102      S3Key string,
   103      buildID string,
   104      awsSession *session.Session,
   105      noop bool,
   106      logger *logrus.Logger) error {
   107  
   108      sqsResource := &gocf.SQSQueue{}
   109      template.AddResource("SQSResource", sqsResource)
   110      return cloudMapDecorator.PublishResource("SQSResource",
   111        "SQSResource",
   112        sqsResource,
   113        nil)
   114    })
   115  }
   116  ```
   117  
   118  The default properties published include the [SQS Outputs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html) and Type information:
   119  
   120  ```json
   121  {
   122      "Id": "CloudMapRes21cf275e8bbbe136-CqWZ27gdLHf8",
   123      "Attributes": {
   124          "Arn": "arn:aws:sqs:us-west-2:123412341234:MyHelloWorldStack-123412341234-SQSResource-S9DWKIFKP14U",
   125          "Name": "SQSResource",
   126          "QueueName": "MyHelloWorldStack-123412341234-SQSResource-S9DWKIFKP14U",
   127          "Ref": "https://sqs.us-west-2.amazonaws.com/123412341234/MyHelloWorldStack-123412341234-SQSResource-S9DWKIFKP14U",
   128          "Type": "AWS::SQS::Queue"
   129      }
   130  }
   131  ```
   132  
   133  ## Enabling
   134  
   135  Publishing instances to CloudMap only makes them available for other services to discover them. Call the `EnableDiscoverySupport` with your `*sparta.LambdaAWSInfo` instance as the only argument. This function updates your Lambda function's environment to include the provisioned _ServiceInstance_ and also the IAM role privileges to authorize:
   136  
   137  * _servicediscovery:DiscoverInstances_
   138  * _servicediscovery:GetNamespace_
   139  * _servicediscovery:ListInstances_
   140  * _servicediscovery:GetService_
   141  
   142  For instance: 
   143  
   144  ```go
   145  func main() {
   146    // ...
   147  
   148    lambdaFn, _ := sparta.NewAWSLambda("Hello World",
   149        helloWorld,
   150        sparta.IAMRoleDefinition{})
   151  
   152    // ...
   153  
   154    cloudMapDecorator.EnableDiscoverySupport(lambdaFn)
   155    
   156    // ...
   157  }
   158  
   159  ```
   160  
   161  ## Invoking
   162  
   163  With the resources published and the lambda role properly updated, the last step is to dynamically discover the provisioned resources via CloudMap. Call `DiscoverInstancesWithContext` with the the set of key-value pairs to use for discovery as below:
   164  
   165  ```go
   166  
   167  func helloWorld(ctx context.Context) (string, error) {
   168      // ...
   169  
   170    props := map[string]string{
   171      "Type": "AWS::SQS::Queue",
   172    }
   173    results, resultsErr := spartaDecorators.DiscoverInstancesWithContext(ctx,
   174      props,
   175      logger)
   176    logger.WithFields(logrus.Fields{
   177      "Instances": results,
   178      "Error":     resultsErr,
   179      }).Info("Discovered instances!")
   180      // ...
   181  }
   182  ```
   183  
   184  Given the previous example of a single lambda function and an SQS-queue provisioning decorator, the `DiscoverInstancesWithContext` would return the matching instance with data similar to:
   185  
   186  ```json
   187  {
   188    "Instances": [
   189      {
   190        "Attributes": {
   191          "Arn": "arn:aws:sqs:us-west-2:123412341234:MyHelloWorldStack-123412341234-SQSResource-S9DWKIFKP14U",
   192          "Name": "SQSResource",
   193          "QueueName": "MyHelloWorldStack-123412341234-SQSResource-S9DWKIFKP14U",
   194          "Ref": "https://sqs.us-west-2.amazonaws.com/123412341234/MyHelloWorldStack-123412341234-SQSResource-S9DWKIFKP14U",
   195          "Type": "AWS::SQS::Queue"
   196        },
   197        "HealthStatus": "HEALTHY",
   198        "InstanceId": "CloudMapResd1a507076543ccd0-Fln1ITi5cf0y",
   199        "NamespaceName": "SpartaServices",
   200        "ServiceName": "SpartaSampleCloudMapService"
   201      }
   202    ]
   203  }
   204  ```