Search code examples
pythongoogle-cloud-platformgoogle-api-python-clientgoogle-deployment-manager

Labeling a Google Cloud Platform Deployment after it has been created


We have a batch tagger that processes the activity log for newly created resources that we then apply a label to for billing purposes. We are trying to auto-tag our deployments in this way since we discovered that failed deployments were accumulating and incurring a fair amount of cost. My issue is that I cannot tag the deployment.

I need to add a global label to a deployment and everything I try programmatically does not seem to work.

I try using the existing config like this:

manifests = self.deploymentManagerService.manifests().list(project=project, 

deployment=deployment_name).execute()
config = manifests['manifests'][0]['config']
...
content_dict = eval(json.dumps(json.loads(config['content'])))
output = StringIO.StringIO()
yaml.dump(content_dict, output, encoding=None)

body = {'labels': labels, 'fingerprint': fingerprint, 'name': deployment_name,  'target': {'config': { 'content': output.getvalue()}}}
print "BODY=", body
deploymentManagerService.deployments().patch(project=project,
                                             deployment=deployment_name,
                                             body=body).execute()

This correctly labels the deployment, but errors out on the update with path problems.

I tried an empty resources section:

 body = {'labels': labels, 'fingerprint': fingerprint, 'name': deployment_name,  'target': {'config': { 'content': 'resources:\n'}}}

This labels the deployment but blanks out the config (not good).

I try no config or target and get a 400. I am at a loss.


Solution

  • There's no need to get the manifest. Using patch is the right idea, but there's an extra header you need to add. Here's an example:

    dep = self.deploymentManagerService.deployments().get(
        deployment=deployment, project=project).execute()
    body = {'labels': [{'key': 'foo', 'value': 'bar'}],
            'fingerprint': dep['fingerprint']}
    
    req = self.deploymentManagerService.deployments().patch(
        project=project, deployment=deployment, body=body)
    # This header is required for patch requests to work correctly.
    req.headers['X-Cloud-DM-Patch'] = 'True'
    res = req.execute()
    

    Additionally, you would likely want to:

    1. Retry this whole block if there is a concurrent modification (HTTP 409 Conflict).
    2. Think about how you want to handle existing labels (if there can be existing labels in your use case).
    3. Have a loop to wait for the long running operation returned from execute to finish.