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 content, 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.

<span style="font-weight:bold">def</span> <span style="color:#900;font-weight:bold">_generateSchedulerTypeResource</span>(context):
   properties <span style="font-weight:bold">=</span> {
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">descriptorUrl</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">https://cloudscheduler.googleapis.com/$discovery/rest?version=v1beta1</span><span style="color:#b84">'</span>,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">options</span><span style="color:#b84">'</span>: {
         <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">inputMappings</span><span style="color:#b84">'</span>: [
           {
             <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">fieldName</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">Authorization</span><span style="color:#b84">'</span>,
             <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">location</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">HEADER</span><span style="color:#b84">'</span>,
             <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">value</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">$.concat(</span><span style="color:#b84">"</span><span style="color:#b84">Bearer </span><span style="color:#b84">"</span><span style="color:#b84">, $.googleOauth2AccessToken())</span><span style="color:#b84">'</span>,
           },
         ],
       }
   }

   <span style="font-weight:bold">return</span> {
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">name</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">cloudscheduler-v1beta1</span><span style="color:#b84">'</span>,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">type</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">deploymentmanager.v2beta.typeProvider</span><span style="color:#b84">'</span>,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">properties</span><span style="color:#b84">'</span>: 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.

<span style="font-weight:bold">def</span> <span style="color:#900;font-weight:bold">_generateSchedulerJobResource</span>(context):
   project_id <span style="font-weight:bold">=</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">myprojectid</span><span style="color:#b84">'</span>
   region <span style="font-weight:bold">=</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">europe-west2</span><span style="color:#b84">'</span>
   parent <span style="font-weight:bold">=</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">projects/</span><span style="color:#b84">'</span> <span style="font-weight:bold">+</span> project_id <span style="font-weight:bold">+</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">/locations/</span><span style="color:#b84">'</span> <span style="font-weight:bold">+</span> region
   name_short <span style="font-weight:bold">=</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">myjob</span><span style="color:#b84">'</span>
   name_full <span style="font-weight:bold">=</span> parent <span style="font-weight:bold">+</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">/jobs/</span><span style="color:#b84">'</span> <span style="font-weight:bold">+</span> name_short
   topic <span style="font-weight:bold">=</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">trigger-job</span><span style="color:#b84">'</span>
  
   properties <span style="font-weight:bold">=</span> {
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">name</span><span style="color:#b84">'</span>: name_full,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">parent</span><span style="color:#b84">'</span>: parent,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">content</span><span style="color:#b84">'</span>: name_short,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">schedule</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">0 6 */1 * *</span><span style="color:#b84">'</span>,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">timeZone</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">Europe/Brussels</span><span style="color:#b84">'</span>,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">pubsubTarget</span><span style="color:#b84">'</span>: {
           <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">topicName</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">projects/</span><span style="color:#b84">'</span> <span style="font-weight:bold">+</span> project_id <span style="font-weight:bold">+</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">/topics/</span><span style="color:#b84">'</span> <span style="font-weight:bold">+</span> topic,
           <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">attributes</span><span style="color:#b84">'</span>: {
               <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">source</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">cloudscheduler</span><span style="color:#b84">'</span>,
           },
       },
   }

   metadata <span style="font-weight:bold">=</span> {
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">dependsOn</span><span style="color:#b84">'</span>: [<span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">cloudscheduler-v1beta1</span><span style="color:#b84">'</span>],
   }

   <span style="font-weight:bold">return</span> {
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">name</span><span style="color:#b84">'</span>: <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">cloudscheduler-job-</span><span style="color:#b84">'</span> <span style="font-weight:bold">+</span> name_short,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">action</span><span style="color:#b84">'</span>: project_id <span style="font-weight:bold">+</span> <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">/cloudscheduler-v1beta1:cloudscheduler.projects.locations.jobs.create</span><span style="color:#b84">'</span>,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">properties</span><span style="color:#b84">'</span>: properties,
       <span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">metadata</span><span style="color:#b84">'</span>: 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.

<span style="font-weight:bold">def</span> <span style="color:#900;font-weight:bold">GenerateConfig</span>(context):
   resources <span style="font-weight:bold">=</span> [
       _generateSchedulerTypeResource(context),
       _generateSchedulerJobResource(context),
   ]

   <span style="font-weight:bold">return</span> {<span style="color:#b84"></span><span style="color:#b84">'</span><span style="color:#b84">resources</span><span style="color:#b84">'</span>: resources}
Share this article: Tweet this post / Post on LinkedIn