From 39505bcfd45c1b4283495825fe236a5dc636e706 Mon Sep 17 00:00:00 2001 From: Danny Seymour Date: Tue, 19 Feb 2019 11:33:46 -0800 Subject: [PATCH] Add unit test to check G Suite group is created Fixes https://github.com/terraform-google-modules/terraform-google-project-factory/issues/111 --- modules/core_project_factory/main.tf | 2 +- .../scripts/preconditions/preconditions.py | 5 +- test/fixtures/full/main.tf | 14 +++-- test/fixtures/shared/variables.tf | 3 +- test/helpers/test_migrate.py | 19 +++--- test/integration/full/controls/gsuite.rb | 6 ++ test/scripts/gsuite/gsuite_groups.py | 63 +++++++++++++++++++ 7 files changed, 92 insertions(+), 20 deletions(-) create mode 100755 test/scripts/gsuite/gsuite_groups.py diff --git a/modules/core_project_factory/main.tf b/modules/core_project_factory/main.tf index 5a1686c8a..db8d401c2 100644 --- a/modules/core_project_factory/main.tf +++ b/modules/core_project_factory/main.tf @@ -136,7 +136,7 @@ resource "google_compute_shared_vpc_service_project" "shared_vpc_attachment" { Default compute service account retrieval *****************************************/ data "google_compute_default_service_account" "default" { - project = "${google_project.main.id}" + project = "${google_project.main.project_id}" depends_on = ["google_project_service.project_services"] } diff --git a/modules/core_project_factory/scripts/preconditions/preconditions.py b/modules/core_project_factory/scripts/preconditions/preconditions.py index 6b60041ac..0ac0041b2 100755 --- a/modules/core_project_factory/scripts/preconditions/preconditions.py +++ b/modules/core_project_factory/scripts/preconditions/preconditions.py @@ -303,7 +303,9 @@ def validate(self, credentials): return req.asdict() @classmethod - def argument_type(cls, string, pat=re.compile(r"[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}")): + def argument_type(cls, + string, + pat=re.compile(r"[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}")): if not pat.match(string): msg = "%r is not a valid billing account ID format" % string raise argparse.ArgumentTypeError(msg) @@ -333,6 +335,7 @@ class EmptyStrAction(argparse.Action): """ Convert empty string values parsed by argparse into None. """ + def __call__(self, parser, namespace, values, option_string=None): values = None if values == '' else values setattr(namespace, self.dest, values) diff --git a/test/fixtures/full/main.tf b/test/fixtures/full/main.tf index f573be044..bb6caba5d 100644 --- a/test/fixtures/full/main.tf +++ b/test/fixtures/full/main.tf @@ -50,7 +50,8 @@ module "vpc" { source = "terraform-google-modules/network/google" version = "~> 0.4.0" network_name = "pf-test-int-full-${random_string.suffix.result}" - project_id = "${var.shared_vpc}" + + project_id = "${var.shared_vpc}" # The provided project must already be a Shared VPC host shared_vpc_host = "false" @@ -89,11 +90,12 @@ module "project-factory" { group_role = "${var.group_role}" group_name = "${var.group_name}" shared_vpc = "${var.shared_vpc}" - shared_vpc_subnets = "${local.shared_vpc_subnets}" - sa_role = "${var.sa_role}" - sa_group = "${var.sa_group}" - credentials_path = "${var.credentials_path}" - lien = "true" + + shared_vpc_subnets = "${local.shared_vpc_subnets}" + sa_role = "${var.sa_role}" + sa_group = "${var.sa_group}" + credentials_path = "${var.credentials_path}" + lien = "true" activate_apis = [ "compute.googleapis.com", diff --git a/test/fixtures/shared/variables.tf b/test/fixtures/shared/variables.tf index f3027de02..99413caf1 100644 --- a/test/fixtures/shared/variables.tf +++ b/test/fixtures/shared/variables.tf @@ -22,8 +22,7 @@ variable "folder_id" { default = "" } -variable "domain" { -} +variable "domain" {} variable "usage_bucket_name" { default = "" diff --git a/test/helpers/test_migrate.py b/test/helpers/test_migrate.py index 515b9a3ae..2eea3ce14 100755 --- a/test/helpers/test_migrate.py +++ b/test/helpers/test_migrate.py @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import copy import os import sys import unittest @@ -117,15 +116,15 @@ ), ( "module.project-factory.google_project_iam_member.gsuite_group_role", - "module.project-factory.module.project-factory.google_project_iam_member.gsuite_group_role", + "module.project-factory.module.project-factory.google_project_iam_member.gsuite_group_role", # noqa: E501 ), ( "module.project-factory.google_project_service.project_services", - "module.project-factory.module.project-factory.google_project_service.project_services", + "module.project-factory.module.project-factory.google_project_service.project_services", # noqa: E501 ), ( - "module.project-factory.google_service_account.default_service_account", - "module.project-factory.module.project-factory.google_service_account.default_service_account", + "module.project-factory.google_service_account.default_service_account", # noqa: E501 + "module.project-factory.module.project-factory.google_service_account.default_service_account", # noqa: E501 ), ( "module.project-factory.google_service_account_iam_member.service_account_grant_to_group", # noqa: E501 @@ -137,7 +136,7 @@ ), ( "module.project-factory.random_id.random_project_id_suffix", - "module.project-factory.module.project-factory.random_id.random_project_id_suffix", + "module.project-factory.module.project-factory.random_id.random_project_id_suffix", # noqa: E501 ), ] @@ -148,19 +147,19 @@ TERRAFORM_DROPPED_DATA_SOURCES = [ ( "module.project-factory.google_organization.org", - "module.project-factory.module.project-factory.google_organization.org", + "module.project-factory.module.project-factory.google_organization.org", # noqa: E501 ), ( "module.project-factory.null_data_source.data_final_group_email", - "module.project-factory.module.project-factory.null_data_source.data_final_group_email", + "module.project-factory.module.project-factory.null_data_source.data_final_group_email", # noqa: E501 ), ( "module.project-factory.null_data_source.data_given_group_email", - "module.project-factory.module.project-factory.null_data_source.data_given_group_email", + "module.project-factory.module.project-factory.null_data_source.data_given_group_email", # noqa: E501 ), ( "module.project-factory.null_data_source.data_group_email_format", - "module.project-factory.module.project-factory.null_data_source.data_group_email_format", + "module.project-factory.module.project-factory.null_data_source.data_group_email_format", # noqa: E501 ), ] diff --git a/test/integration/full/controls/gsuite.rb b/test/integration/full/controls/gsuite.rb index d8c537578..971e9dcc0 100644 --- a/test/integration/full/controls/gsuite.rb +++ b/test/integration/full/controls/gsuite.rb @@ -18,6 +18,7 @@ project_id = attribute('project_id') service_account_email = attribute('service_account_email') credentials_path = attribute('credentials_path') +gsuite_admin_account = attribute('gsuite_admin_account') ENV['CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE'] = File.absolute_path( credentials_path, @@ -74,4 +75,9 @@ ) end end + + describe command("./test/scripts/gsuite/gsuite_groups.py --sa-json-credentials='test/fixtures/shared/credentials.json' --group-email #{group_email} --impersonate-user #{gsuite_admin_account}") do + its('exit_status') { should eq 0 } + its('stderr') { should eq '' } + end end diff --git a/test/scripts/gsuite/gsuite_groups.py b/test/scripts/gsuite/gsuite_groups.py new file mode 100755 index 000000000..05bf21810 --- /dev/null +++ b/test/scripts/gsuite/gsuite_groups.py @@ -0,0 +1,63 @@ +#! /usr/bin/env python3 + +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +from googleapiclient.errors import HttpError +from googleapiclient.discovery import build +from google.oauth2 import service_account + +SCOPES = ['https://www.googleapis.com/auth/admin.directory.group'] + + +def authenticate(impersonated_user, sa_json_file_path, scopes): + print('Getting delegated credentials for %s' % impersonated_user) + + return service_account.Credentials.from_service_account_file( + sa_json_file_path, + scopes=scopes, + subject=impersonated_user + ) + + + +def group_exists(service, group_email): + try: + return service.groups().get(groupKey=group_email).execute() + except HttpError as e: + if e.resp.status == 404: + print('Group %s does not exist' % group_email) + exit(1) + else: + print('Error fetching groups %s %s' % e.content, e.error_details) + exit(2) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description='Test if the specified G Suite exists') + parser.add_argument('--sa-json-credentials', dest='sa_json_credentials') + parser.add_argument('--group-email', dest='group_email') + parser.add_argument('--impersonate-user', dest='impersonate_user') + args = parser.parse_args() + + service = build("admin", + "directory_v1", + credentials=authenticate( + args.impersonate_user, + args.sa_json_credentials, + SCOPES) + ) + group_exists(service, args.group_email)