Skip to content

Commit

Permalink
AD Domain resource added (#3735)
Browse files Browse the repository at this point in the history
* AD Domain resource added

* fmt issue fixed

* validation regex and input flag added

* made domain_name field not updatable

* validationfunc added

* validationfunc error message modified
  • Loading branch information
venkykuberan authored Jul 28, 2020
1 parent aaed078 commit 8e10eec
Show file tree
Hide file tree
Showing 5 changed files with 244 additions and 0 deletions.
107 changes: 107 additions & 0 deletions products/activedirectory/api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Copyright 2020 Google Inc.
# 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
#
# http://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.

--- !ruby/object:Api::Product
name: ActiveDirectory
display_name: Managed Microsoft Active Directory
versions:
- !ruby/object:Api::Product::Version
name: ga
base_url: https://managedidentities.googleapis.com/v1/
scopes:
- https://www.googleapis.com/auth/cloud-platform
async: !ruby/object:Api::OpAsync
operation: !ruby/object:Api::OpAsync::Operation
path: 'name'
base_url: '{{op_id}}'
wait_ms: 1000
# It takes about 35-40 mins to get the resource created
timeouts: !ruby/object:Api::Timeouts
insert_minutes: 60
update_minutes: 60
delete_minutes: 60
result: !ruby/object:Api::OpAsync::Result
path: 'response'
resource_inside_response: true
status: !ruby/object:Api::OpAsync::Status
path: 'done'
complete: true
allowed:
- true
- false
error: !ruby/object:Api::OpAsync::Error
path: 'error'
message: 'message'
objects:
- !ruby/object:Api::Resource
name: 'Domain'
kind: 'activedirectory#domain'
base_url : projects/{{project}}/locations/global/domains?domainName={{domain_name}}
update_verb: :PATCH
update_mask: true
self_link: '{{name}}'
description: Creates a Microsoft AD domain
references: !ruby/object:Api::Resource::ReferenceLinks
guides:
'Managed Microsoft Active Directory Quickstart': 'https://cloud.google.com/managed-microsoft-ad/docs/quickstarts'
api: 'https://cloud.google.com/managed-microsoft-ad/reference/rest/v1/projects.locations.global.domains'
parameters:
- !ruby/object:Api::Type::String
name: domainName
required: true
url_param_only: true
input: true
description: |
The fully qualified domain name. e.g. mydomain.myorganization.com, with the restrictions,
https://cloud.google.com/managed-microsoft-ad/reference/rest/v1/projects.locations.global.domains.
properties:
- !ruby/object:Api::Type::String
name: 'name'
output: true
description: 'The unique name of the domain using the format: `projects/{project}/locations/global/domains/{domainName}`.'
- !ruby/object:Api::Type::KeyValuePairs
name: 'labels'
description: 'Resource labels that can contain user-provided metadata'
- !ruby/object:Api::Type::Array
name: 'authorizedNetworks'
item_type: Api::Type::String
description: |
The full names of the Google Compute Engine networks the domain instance is connected to. The domain is only available on networks listed in authorizedNetworks.
If CIDR subnets overlap between networks, domain creation will fail.
- !ruby/object:Api::Type::String
name: 'reservedIpRange'
required: true
input: true
description: |
The CIDR range of internal addresses that are reserved for this domain. Reserved networks must be /24 or larger.
Ranges must be unique and non-overlapping with existing subnets in authorizedNetworks
- !ruby/object:Api::Type::Array
name: 'locations'
required: true
item_type: Api::Type::String
description: |
Locations where domain needs to be provisioned. [regions][compute/docs/regions-zones/]
e.g. us-west1 or us-east4 Service supports up to 4 locations at once. Each location will use a /26 block.
- !ruby/object:Api::Type::String
name: 'admin'
default_value: 'setupadmin'
input: true
description: |
The name of delegated administrator account used to perform Active Directory operations.
If not specified, setupadmin will be used.
- !ruby/object:Api::Type::String
name: 'fqdn'
output: true
description: |
The fully-qualified domain name of the exposed domain used by clients to connect to the service.
Similar to what would be chosen for an Active Directory set up on an internal network.
39 changes: 39 additions & 0 deletions products/activedirectory/terraform.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2020 Google Inc.
# 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
#
# http://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.

--- !ruby/object:Provider::Terraform::Config
overrides: !ruby/object:Overrides::ResourceOverrides
Domain: !ruby/object:Overrides::Terraform::ResourceOverride
id_format: "{{name}}"
import_format: ["{{name}}"]
autogen_async: true
properties:
authorizedNetworks: !ruby/object:Overrides::Terraform::PropertyOverride
is_set: true
domainName: !ruby/object:Overrides::Terraform::PropertyOverride
required: true
validation: !ruby/object:Provider::Terraform::Validation
function: 'validateADDomainName()'
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_import: templates/terraform/custom_import/self_link_as_name.erb
examples:
- !ruby/object:Provider::Terraform::Examples
name: "active_directory_domain_basic"
primary_resource_id: "ad-domain"
vars:
name: "myorg"
files: !ruby/object:Provider::Config::Files
# These files have templating (ERB) code that will be run.
# This is usually to add licensing info, autogeneration notices, etc.
compile:
<%= lines(indent(compile('provider/terraform/product~compile.yaml'), 4)) -%>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "google_active_directory_domain" "ad-domain" {
domain_name = "mydomain.org.com"
locations = ["us-central1"]
reserved_ip_range = "192.168.255.0/24"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package google

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

func TestAccActiveDirectoryDomain_update(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"domain": "mydomain.org1.com",
"resource_name": "ad-domain",
}

resourceName := Nprintf("google_active_directory_domain.%{resource_name}", context)

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckActiveDirectoryDomainDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccADDomainBasic(context),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"domain_name"},
},
{
Config: testAccADDomainUpdate(context),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"domain_name"},
},
{
Config: testAccADDomainBasic(context),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"domain_name"},
},
},
})
}

func testAccADDomainBasic(context map[string]interface{}) string {

return Nprintf(`
resource "google_active_directory_domain" "%{resource_name}" {
domain_name = "%{domain}"
locations = ["us-central1"]
reserved_ip_range = "192.168.255.0/24"
}
`, context)
}

func testAccADDomainUpdate(context map[string]interface{}) string {
return Nprintf(`
resource "google_active_directory_domain" "%{resource_name}" {
domain_name = "%{domain}"
locations = ["us-central1", "us-west1"]
reserved_ip_range = "192.168.255.0/24"
labels = {
env = "test"
}
}
`, context)

}
15 changes: 15 additions & 0 deletions third_party/terraform/utils/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ const (

// https://cloud.google.com/iam/docs/understanding-custom-roles#naming_the_role
IAMCustomRoleIDRegex = "^[a-zA-Z0-9_\\.]{3,64}$"

// https://cloud.google.com/managed-microsoft-ad/reference/rest/v1/projects.locations.global.domains/create#query-parameters
ADDomainNameRegex = "^[a-z][a-z0-9-]{0,14}\\.[a-z0-9-\\.]*[a-z]+[a-z0-9]*$"
)

var (
Expand Down Expand Up @@ -311,3 +314,15 @@ func validateRFC3339Date(v interface{}, k string) (warnings []string, errors []e
}
return
}

func validateADDomainName() schema.SchemaValidateFunc {
return func(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)

if len(value) > 64 || !regexp.MustCompile(ADDomainNameRegex).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q (%q) doesn't match regexp %q, domain_name must be 2 to 64 with lowercase letters, digits, hyphens, dots and start with a letter", k, value, ADDomainNameRegex))
}
return
}
}

0 comments on commit 8e10eec

Please sign in to comment.