Luth
Luth

Reputation: 31

Create Cloud Run service with Deployment Manager

I'm trying to create a Cloud Run service using the Deployment Manager, as there's no native support for Cloud Run resource type, I created a type provider for the Cloud Run API by providing it's descriptor at https://run.googleapis.com/$discovery/rest?version=v1.

However, when I run this configuration to create the service using the Deployment Manager, I'm getting the error 404 - Requested entity was not found.

This is because when the Deployment Manager tries to perform the create operation, instead of calling the location specific service endpoint (e.g. https://us-central1-run.googleapis.com), it's using the global endpoint (https://run.googleapis.com) returned by the discovery url, and as stated in the API documentation, the global endpoint supports list method only.

To overcome this problem, I created a custom descriptior file and replaced the rootUrl by pointing it to the location specific service endpoint and I was able to create a Cloud Run service with DM.

I don't intend to keep a custom descriptor file because it may become outdated as the API evolves and I'd like to know if there's another recommended approach to get to correct API url from the Google's official API discovery document.

The following is my DM config:

resources:
- name: cloudrun-type-provider
  type: deploymentmanager.v2beta.typeProvider
  properties:
    descriptorUrl: https://us-central1-run.googleapis.com/$discovery/rest?version=v1
    options:
      inputMappings:
      - fieldName: Authorization
        location: HEADER
        value: >
          $.concat("Bearer ", $.googleOauth2AccessToken())
    collectionOverrides:
    - collection: namespaces.services
      options:
        virtualProperties: |
          schema: http://json-schema.org/draft-04/schema#
          type: object
          properties:
            metadata:
              type: object
              description: https://cloud.google.com/run/docs/reference/rest/v1/ObjectMeta
            spec:
              type: object
              description: https://cloud.google.com/run/docs/reference/rest/v1/namespaces.services#ServiceSpec
            status:
              type: object
              description: https://cloud.google.com/run/docs/reference/rest/v1/namespaces.services#ServiceStatus
        inputMappings:
        - methodMatch: ^create$
          location: PATH
          fieldName: parent
          value: $.concat("namespaces/", $.project)

        - methodMatch: ^(get|replaceService|delete)$
          location: PATH
          fieldName: name
          value: $.concat("namespaces/", $.project, "/services/", $.resource.name)

        - methodMatch: ^create$
          location: BODY
          fieldName: apiVersion
          value: $.concat("serving.knative.dev/v1")

        - methodMatch: ^create$
          location: BODY
          fieldName: kind
          value: $.concat("Service")

        - methodMatch: ^create$
          location: BODY
          fieldName: metadata.name
          value: $.resource.name

        - methodMatch: ^replaceService$
          location: BODY
          fieldName: metadata
          value: $.resource.self.metadata

        - methodMatch: ^(create|replaceService)$
          location: BODY
          fieldName: spec.template.spec
          value: $.resource.properties.spec

- name: dm-cloud-run
  type: MY-PROJECT/cloudrun-type-provider:namespaces.services
  metadata:
    dependsOn:
    - cloudrun-type-provider
  properties:
    spec:
      containerConcurrency: 50
      timeoutSeconds: 300
      containers:
      - image: marketplace.gcr.io/google/nginx1
        env:
        - name: ENV_VAR_1
          value: VALUE_1
        - name: ENV_VAR_1
          value: VALUE_2
        resources:
          limits:
            memory: 512Mi

Upvotes: 3

Views: 424

Answers (1)

MousyBusiness
MousyBusiness

Reputation: 308

I've managed to get a version of this working after hitting the same issues as you did.

My solution:

  1. create deployment-manager type
gcloud beta deployment-manager --project $PROJECT_ID type-providers create cloudrun --api-options-file=$DIR/../deployment/options.yaml --descriptor-url="https://run.googleapis.com/\$discovery/rest?version=v1"

options.yaml:

options:
  inputMappings:
    - fieldName: Authorization
      location: HEADER
      value: >
        $.concat("Bearer ", $.googleOauth2AccessToken())
  1. create cloudrun.py template
"""Creates the Cloud Run endpoint."""


def GenerateConfig(context):
    name: str = context.env['name']
    project = context.env['project']
    region = context.properties['region']

    resources = [{
        'name': name,
        'type': context.env['project'] + '/cloudrun:run.projects.locations.services.create',
        'properties': {
            'parent': 'projects/{}/locations/{}'.format(project, region),
            'apiVersion': 'serving.knative.dev/v1',
            'kind': 'Service',
            'metadata': {
                'name': '{}-blah'.format(name),  # TODO rename
                'namespace': 'YOUR_PROJECT_NAME_HERE',  # TODO change to your value
            },
            'spec': {
                'template': {
                    'spec': {
                        'containerConcurrency': 80,
                        'timeoutSeconds': 300,
                        'serviceAccountName': 'YOUR_SERVICE_ACCOUNT_HERE',  # TODO change to your value
                        'containers': [{'image': 'eu.gcr.io/YOUR_PROJECT_HERE/YOUR_IMAGE_HERE'}],  # TODO change to your value
                    },
                },
                'traffic': [
                    {'percent': 100, 'latestRevision': True}
                ],
            },
        }
    }]

    return {'resources': resources}

Workaround

Using type: context.env['project'] + '/cloudrun:run.namespaces.services.create' (and parent: namespaces/{namespace}) did not work for me, I also hit that 404. Please note this approach is how the docs describe how to use fully managed.
Instead use type: context.env['project'] + '/cloudrun:run.projects.locations.services.create' as show in the example snippet. The parent and a few fields will also have to change. A bit of trial and error got me to the final result.

API definition

https://run.googleapis.com//$discovery/rest?version=v1
This appears incomplete or inaccurate, trial and error and relying on the response errors to determine exactly what was required and what was not.

Upvotes: 0

Related Questions