Skip to content

Instantly share code, notes, and snippets.

@palladius
Last active April 19, 2023 14:34
Show Gist options
  • Save palladius/a99993feb7e6d78b7a2abea0a10c3242 to your computer and use it in GitHub Desktop.
Save palladius/a99993feb7e6d78b7a2abea0a10c3242 to your computer and use it in GitHub Desktop.
Some cool Migration Org bash scripts

Migrate GCP projects across Organizations

Article on Medium: https://medium.com/@palladiusbonton/how-to-migrate-projects-across-organizations-c7e254ab90af

This gist: https://gist.github.com/palladius/a99993feb7e6d78b7a2abea0a10c3242

Initial bash config

You could add this to a .envrc and use direnv for instance:

$ cat .envrc
# Your Org Admin account, and gcloud already working for it:
export POWER_ACCOUNT='my-power-account@gmail.com'
# SRC ORG: 12345678901 source.example.com 
export SRC_ORG_ID="12345678901"
export SRC_ORG_DOMAIN='source.example.com'
# DST ORG: 45678901234 destination.example.com
export DST_ORG_ID="45678901234"
export DST_ORG_DOMAIN='destination.example.com'

make sure to change it and source it every time you change it (or use direnv, again)

Find all folders under a folder_id

$ gcloud resource-manager folders list --folder '133363080569' 
DISPLAY_NAME          PARENT_NAME                      ID
palladius-eu          folders/133363080569  1038774614299
goliardia-mygbiz-com  folders/133363080569  1060878125337
ricc-rocks            folders/133363080569   232459007745
palladius-it          folders/133363080569   240430455062
carlessos-org         folders/133363080569   412566726466
palladi-us            folders/133363080569   681226422412
SPECIAL_ORPHANS       folders/133363080569   737267668168
sredemo-dev           folders/133363080569   883877833337

get Org-level IAM 'VIP' permissions

gcloud organizations get-iam-policy "$ORG_ID" \
  -flatten='bindings[].members' \
  -format='table(bindings.role,bindings.members)' | 
  tee "t.org-iam-policy.$ORG_DOMAIN.txt"

Find projects under an org

  1. Asset_inventory_command (complex, tree structure):
gcloud beta asset search-all-resources \
  --asset-types=cloudresourcemanager.googleapis.com/Project \
  --scope=organizations/$ORGID  | egrep '^name:' | cut -d/ -f 5
  1. Simplified_single_command:
gcloud projects list --filter "parent.id=$ORGID AND parent.type=organization" | \
   awk '{print $1 }' | grep -v PROJECT_ID
  1. Super duper graphical way:
git clone https://github.com/palladius/org-folder-projects-graph/
./recurse_folders.rb my.domain.com  # before move
make cache-clean                    # after move
./recurse_folders.rb my.domain.com  # after move

Change project name

gcloud projects update "$MY_PROJECT_ID" --name='My New Description max 30chars'

enable Org to Org permissions

gcloud resource-manager org-policies allow --organization "$SRC_ORG_ID" \
  resourcemanager.allowedExportDestinations \
  "under:organizations/$DST_ORG_ID"
  
  gcloud resource-manager org-policies allow --organization "$DST_ORG_ID" \
  resourcemanager.allowedImportSource \
  "under:organizations/$SRC_ORG_ID"
  
  # in case you need to add person@domain2.com to domain1.com
  # You might want to give person@destination.example.com access to Source Org
  # or viceversa to legacy-person@source.example.com access to Destination Org.
  # more info: https://cloud.google.com/resource-manager/docs/organization-policy/restricting-domains
  $ gcloud resource-manager org-policies allow \
  --organization "$SRC_ORG_ID" \
  iam.allowedPolicyMemberDomains 'C0abcdefg' # gives access to SrcOrg to Dest id
  
  # Set IAM for SrcOrg
$ gcloud organizations add-iam-policy-binding $ORG_ID \
  --member='user:$ACCOUNT' \
  --role='roles/resourcemanager.organizationAdmin' \
  --role='roles/resourcemanager.projectIamAdmin' \
  --role='roles/resourcemanager.projectMover'  \
  --role='roles/orgpolicy.policyAdmin'  \
  --condition=None
  

Find orphans

Orphans are account-dependent. To cacth them all, you might want to run a simple iteration like this:

for ACCOUNT in work@company.com private-account@gmail.com ; do 
    gcloud --account "$ACCOUNT" projects list --filter="parent.id.yesno(yes='Yes', no='No')=No" | tee "out/16listorphans-for-$ACCOUNT.txt"
done

It's important you dump this list to file so you can then re-use it and give it as source to another script.

For instance you can take this output above and recurse into a gcloud command:

cat out/16listorphans-for-blah@company.com.txt | \
   awk '{print $1}' | \
      while read PROJECT_ID ; do 
        # Note you need to do `--organization` if its a root folder.
        echo gcloud beta projects move "$PROJECT_ID" --folder "$DESTINATION_ID" ; 
      done | tee migrate.sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment