aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.68k stars 3.92k forks source link

aws-ecs: CloudMap service name is unexpectedly a token #22320

Open metametadata opened 2 years ago

metametadata commented 2 years ago

Describe the bug

CloudMap service name is unexpectedly a token in EC2Service.

Reproduction Steps

1) Build Ec2Service and provide cloudMapOptions name. 1) Later get name back from the built service via getCloudMapService -> getServiceName.

In Clojure:

(let [service (-> (Ec2Service$Builder/create ...)
                  (.cloudMapOptions (-> (CloudMapOptions$Builder.)
                                        (.cloudMapNamespace ...)
                                        (.name "foobar")
                                        .build))
                  ...
                  .build)]
  (println (.getServiceName (.getCloudMapService service))))

Expected Behavior

Prints foobar.

Current Behavior

Prints something like ${Token[TOKEN.14258]}.

Additional Information/Context

I need name to construct the service discovery endpoint URL for the service:

(defn sd-http-url
  [service port]
  (let [cloud-map-service (.getCloudMapService service)]
    (str "http://"
         (.getServiceName cloud-map-service)
         "."
         (.getNamespaceName (.getNamespace cloud-map-service))
         ":"
         port)))

Such URL is used outside of CDK deployment, so it should not contain any tokens.

Maybe there's some better way to achieve the same result?

At the moment I need to invent some workaround based on getting name via a CloudFormation output or just manually pass it around with the service value.

CDK CLI Version

2.42.1

Framework Version

2.42.1

Node.js Version

16.8.0

OS

macOS

Language

Java

pahud commented 1 year ago

Hi

If you try to get the service name attribute from the service resource before the cdk deployment, it would be the token instead of the resolved name attribute of the service. In your case if you already knows your service name i.e. "foobar" you can just directly use it to construct your cloudmap endpoint URL or reference it like:

const service = new Ec2Service(...);
new CfnOutput(stack, 'EndpointURL', { value: `http://${service.serviceName}${yourNameSpaceName}` }

You will not be able to see the full endpointURL until it is deployed. Please let me know if this answers your question.

metametadata commented 1 year ago

Thank you for the suggestions.

http://${service.serviceName}${yourNameSpaceName}

Unfortunately, it won't help because:

1) (.getServiceName service) can be different from (.getServiceName (.getCloudMapService service)). 1) (.getServiceName service) also returns a token, e.g. "${Token[TOKEN.939]}".

new CfnOutput

We use CFN outputs sometimes, but they are noticeably more inconvenient in comparison to passing real values around. For example, we combine deploying via CDK with custom code which runs Docker containers on local machine. Local-machine-related code has to be extra careful with deployment order and combining output-based values with real values.

We use outputs as en escape hatch only. E.g. to get EC2 instance ID which is generated only during deploy. But the service discovery name is not such a value.

if you already knows your service name i.e. "foobar" you can just directly use it to construct your cloudmap endpoint URL

Right, I had to apply this workaround. My current code:

(defn sd-host
  [service sd-name]
  (str sd-name
       "."
       (.getNamespaceName (.getNamespace (.getCloudMapService service)))))

(defn sd-http-url
  [service sd-name port]
  (str "http://" (sd-host service sd-name) ":" port))

This is poor design as I already pass service around which contains the needed value.

And this is the desired code:

(defn sd-host
  [service]
  (let [cloud-map-service (.getCloudMapService service)]
    (str (.getServiceName cloud-map-service)
         "."
         (.getNamespaceName (.getNamespace cloud-map-service)))))

(defn sd-http-url
  [service port]
  (str "http://" (sd-host service) ":" port))

In general, from the customer's POV, I don't see a good reason why the passed in cloudMapOptions name should be returned as a token when I ask for it again from service.