×

Creating type providers for Google Deployment Manager

Deployment Manager is an infrastructure deployment service that automates the creation and management of Google Cloud Platform resources. A lot of GCP resources can be created using the available GDM types. In essence a GDM type is an abstraction on top of the API of a GCP service. However some types are missing, so in this blog I want to show you how to add those yourself. GDM supports jinja2 and Python templates, for this blog we will use python.

Finding the discovery document

Before we can create our new type we need to find the discovery document associated with the API of the service we want to add. The information provided by the discovery document includes API-level properties such as an API description, resource schemas, authentication scopes, and methods. A link to the document is located in the rest documentation of the service, for example: https://cloud.google.com/scheduler/docs/reference/rest

Creating the type provider

Since we now have the discovery document, we can create our type resource. It’s important to add the “inputMappings” property, because this holds the credentials needed to authenticate with the API.

def _generateSchedulerTypeResource(context):
   properties = {
       'descriptorUrl': 'https://cloudscheduler.googleapis.com/$discovery/rest?version=v1beta1',
       'options': {
         'inputMappings': [
           {
             'fieldName': 'Authorization',
             'location': 'HEADER',
             'value': '$.concat("Bearer ", $.googleOauth2AccessToken())',
           },
         ],
       }
   }

   return {
       'name': 'cloudscheduler-v1beta1',
       'type': 'deploymentmanager.v2beta.typeProvider',
       'properties': properties,
   }

Creating the resource

Using our freshly created type provider we can define a service resource. The “action” property in the code below is a concatenation of the project id, type provider name and rest api endpoint id, which can be distilled from the discovery document. The “properties” dict holds the request properties you want to send to the API. The value of the “dependsOn” property must correspond with the name of the type provider.

def _generateSchedulerJobResource(context):
   project_id = 'myprojectid'
   region = 'europe-west2'
   parent = 'projects/' + project_id + '/locations/' + region
   name_short = 'myjob'
   name_full = parent + '/jobs/' + name_short
   topic = 'trigger-job'
  
   properties = {
       'name': name_full,
       'parent': parent,
       'description': name_short,
       'schedule': '0 6 */1 * *',
       'timeZone': 'Europe/Brussels',
       'pubsubTarget': {
           'topicName': 'projects/' + project_id + '/topics/' + topic,
           'attributes': {
               'source': 'cloudscheduler',
           },
       },
   }

   metadata = {
       'dependsOn': ['cloudscheduler-v1beta1'],
   }

   return {
       'name': 'cloudscheduler-job-' + name_short,
       'action': project_id + '/cloudscheduler-v1beta1:cloudscheduler.projects.locations.jobs.create',
       'properties': properties,
       'metadata': metadata,
   }

Putting it together

In our main function, which needs to be called “GenerateConfig”, we define a list holding the resources we want to create.

def GenerateConfig(context):
   resources = [
       _generateSchedulerTypeResource(context),
       _generateSchedulerJobResource(context),
   ]

   return {'resources': resources}
Picture of Maarten Baijs
Maarten Baijs
Cloud Consultant