3

In a single Deployment Manager template, how do I create a new folder and a new project underneath it? The problem is that the reference to the folder includes a name in the format folders/123456, but the project requires a parent field in the format {'type': 'folder', 'id': 123456}. Using a $(ref.new-folder.name) won't work for the ID field in the parent record for the new project.

It feels like I need to do string manipulation on the $(ref.new-folder.name) like this:

# DOES NOT WORK
# but if it did, I could extract the numeric id from 'folders/123456'
parent_id = '$(ref.new-folder.name)'.replace('folders/', '')

But, of course, that won't work.

Here is my (non-working) attempt:

# Template for new folder & new project

folder_resource = {
  'name': 'new-folder',
  'type': 'gcp-types/cloudresourcemanager-v2:folders',
  'properties': {
     'parent': 'organizations/99999',
     'displayName': 'new-folder'
  }
}

project_resource = {
  'name': 'new-project',
  'type': 'clouresourcemanager.v1.project',
  'metadata': { 'dependsOn': ['new-folder'] },
  'properties': {
     'name': 'new-project',
     'parent': {
        'type': 'folder',
        # HERE it is -- the problem!
        'id': '$(ref.new-folder.name)'
     }
  }
}

return { 'resources': [folder_resource, project_resource] }

So, to reiterate, I'm getting hung-up on extracting the numeric folder id from the reference to the folder's name. The name is in the format folders/123456 but I just need the 123456 part to use in the parent field for the new project.

This question is specific to folder & project creation, but a more generalized question would be: is there a way to do string-manipulation on the value of references?

Thomas Ruble
  • 842
  • 6
  • 14
  • Howdy ... I get the feeling that Templates in Deployment Manager will give you the "scripting" that you want. This can either be in Jinja or Python ... see https://cloud.google.com/deployment-manager/docs/configuration/templates/create-basic-template – Kolban Dec 23 '19 at 21:41
  • 1
    Normally, they do! The problem is that I can't operate on $(ref.resource.value) -- the expansion of that variable at runtime prevents performing string operations on it. – Thomas Ruble Dec 24 '19 at 02:25
  • Like you mentioned, there is no clean reference to be made here. And since the python functions finish before the DM template is applied, you can't use python functions to fetch the folder name to pass to a python function. – Patrick W Dec 24 '19 at 16:00
  • This seems like a poor design choice. I'd recommend opening a feature request to have either the project API (for the `resourceID` field) or the folder API to be updated so that they can work more in line with what we'd expect for automation – Patrick W Dec 24 '19 at 16:01
  • same problem, opened an issue https://github.com/GoogleCloudPlatform/deploymentmanager-samples/issues/525 – koma Jan 23 '20 at 10:17

1 Answers1

1

For creating and managing folders document [a] might be helpful and folder name must meet the following requirements:

  1. The name may contain letters, digits, spaces, hyphens and underscores.
  2. The folder's display name must start and end with a letter or digit.
  3. The name must be 30 characters or less.
  4. The name must be distinct from all other folders that share its parent.

To create a folder:

Folders can be created with an API request.

The request JSON:

request_json= '{
display_name: "[DISPLAY_NAME]"
}'

The Create Folder curl request:

curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer ${bearer_token}" \
-d "$request_json" \
https://cloudresourcemanager.googleapis.com/v2/folders?parent=[ORGANIZATION_NAME]

Where:

-[DISPLAY_NAME] is the new folder's display name, for example "My Awesome Folder."

-[ORGANIZATION_NAME] is the name of the organization under which you're creating the folder, for example organizations/123.

The Create Folder response:

{
  "name": "operations/fc.123456789",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.resourcemanager.v2.FolderOperation",
    "displayName": "[DISPLAY_NAME]",
    "operationType": "CREATE"
  }
}

The Get Operation curl request:

curl -H "Authorization: Bearer ${bearer_token}" \
https://cloudresourcemanager.googleapis.com/v1/operations/fc.123456789

The Get Operation response:

{
      "name": "operations/fc.123456789",
      "metadata": {
        "@type": "type.googleapis.com/google.cloud.resourcemanager.v2.FolderOperation",
        "displayName": "[DISPLAY_NAME]",
        "operationType": "CREATE"
      },
      "done": true,
      "response": {
        "@type": "type.googleapis.com/google.cloud.resourcemanager.v2.Folder",
        "name": "folders/12345",
        "parent": "organizations/123",
        "displayName": "[DISPLAY_NAME]",
        "lifecycleState": "ACTIVE",
        "createTime": "2017-07-19T23:29:26.018Z",
        "updateTime": "2017-07-19T23:29:26.046Z"
      }
    }

Configuring access to folders

SetsIamPolicy sets the access control policy on a folder, replacing any existing policy. The resource field should be the folder's resource name, for example, folders/1234.

request_json= '{
   policy: {
     version: "1",
     bindings: [
       {
         role: "roles/resourcemanager.folderEditor",
         members: [
           "user:email1@example.com",
           "user:email2@example.com",
         ]
       }
     ]
   }
 }'

The curl request:

curl -X POST -H "Content-Type: application/json" \
   -H "Authorization: Bearer ${bearer_token}" \
   -d "$request_json" \
   https://cloudresourcemanager.googleapis.com/v2/[FOLDER_NAME]:setIamPolicy

Where:

-[FOLDER_NAME] is the name of the folder whose IAM policy is being set, for example folders/123.

Creating a project in a folder

 request_json= ‘{
      name: “[DISPLAY_NAME]”, projectId: “[PROJECT_ID]”, parent: {id: [PARENT_ID], type: [PARENT_TYPE] }
   }’

The curl request:

curl -X POST -H "Content-Type: application/json" \
   -H "Authorization: Bearer ${bearer_token}" \
   -d "$request_json" \
   https://cloudresourcemanager.googleapis.com/v1/projects

Where:

-[PROJECT_ID] is id of the project being created, for e.g., my-awesome-proj-123.

-[DISPLAY_NAME] is the display name of the project being created.

-[PARENT_ID] is the id of the parent being created under, for e.g. 123

-[PARENT_TYPE] is the type of the parent, like “folder” or “Organization”

When we create a reference to a resource, we also create a dependency between resources, document [b] might be helpful for this.

[a]-https://cloud.google.com/resource-manager/docs/creating-managing-folders [b]-https://cloud.google.com/deployment-manager/docs/configuration/use-references

Shanewaz
  • 191
  • 3
  • 1
    Thanks for that! However, I'm trying to solve this problem specifically for Deployment Manager -- without using gcloud scripts. – Thomas Ruble Dec 26 '19 at 13:58
  • I was looking for a workaround using deployment manager but unfortunately unable to get any. Seems it is better to create a feature request using: https://cloud.google.com/support/docs/issue-trackers – Shanewaz Dec 26 '19 at 18:43