-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2086 from terraform-providers/devspace
New resource: DevSpace Controller for AKS cluster
- Loading branch information
Showing
14 changed files
with
2,204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package validate | ||
|
||
import ( | ||
"regexp" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/hashicorp/terraform/helper/validation" | ||
) | ||
|
||
func DevSpaceName() schema.SchemaValidateFunc { | ||
return func(i interface{}, k string) (s []string, es []error) { | ||
// Length should be between 3 and 31. | ||
if s, es = validation.StringLenBetween(3, 31)(i, k); len(es) > 0 { | ||
return s, es | ||
} | ||
|
||
// Naming rule. | ||
regexStr := "^[a-zA-Z0-9](-?[a-zA-Z0-9])*$" | ||
errMsg := "DevSpace name can only include alphanumeric characters, hyphens." | ||
if s, es = validation.StringMatch(regexp.MustCompile(regexStr), errMsg)(i, k); len(es) > 0 { | ||
return s, es | ||
} | ||
|
||
return s, es | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package validate | ||
|
||
import "testing" | ||
|
||
func TestValidateDevSpaceName(t *testing.T) { | ||
validNames := []string{ | ||
"valid-name", | ||
"valid02-name", | ||
"validName1", | ||
} | ||
for _, v := range validNames { | ||
_, errors := DevSpaceName()(v, "valid") | ||
if len(errors) != 0 { | ||
t.Fatalf("%q should be a valid DevSpace Name: %q", v, errors) | ||
} | ||
} | ||
|
||
invalidNames := []string{ | ||
"invalid!", | ||
"!@£", | ||
"-invalid", | ||
"double-hyphen--invalid", | ||
"invalid_name", | ||
} | ||
for _, v := range invalidNames { | ||
_, errors := DevSpaceName()(v, "invalid") | ||
if len(errors) == 0 { | ||
t.Fatalf("%q should be an invalid DevSpace Name", v) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
package azurerm | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/preview/devspaces/mgmt/2018-06-01-preview/devspaces" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/hashicorp/terraform/helper/validation" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||
) | ||
|
||
func resourceArmDevSpaceController() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceArmDevSpaceControllerCreate, | ||
Read: resourceArmDevSpaceControllerRead, | ||
Update: resourceArmDevSpaceControllerUpdate, | ||
Delete: resourceArmDevSpaceControllerDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validate.DevSpaceName(), | ||
}, | ||
|
||
"location": locationSchema(), | ||
|
||
"resource_group_name": resourceGroupNameSchema(), | ||
|
||
"sku": { | ||
Type: schema.TypeList, | ||
Required: true, | ||
ForceNew: true, | ||
MaxItems: 1, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.StringInSlice([]string{ | ||
"S1", | ||
}, false), | ||
}, | ||
"tier": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.StringInSlice([]string{ | ||
string(devspaces.Standard), | ||
}, false), | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"host_suffix": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
|
||
"target_container_host_resource_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: azure.ValidateResourceID, | ||
}, | ||
|
||
"target_container_host_credentials_base64": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
Sensitive: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
|
||
"tags": tagsSchema(), | ||
|
||
"data_plane_fqdn": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceArmDevSpaceControllerCreate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).devSpaceControllerClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
log.Printf("[INFO] preparing arguments for DevSpace Controller creation") | ||
|
||
name := d.Get("name").(string) | ||
location := azureRMNormalizeLocation(d.Get("location").(string)) | ||
resGroupName := d.Get("resource_group_name").(string) | ||
tags := d.Get("tags").(map[string]interface{}) | ||
|
||
sku := expandDevSpaceControllerSku(d) | ||
|
||
hostSuffix := d.Get("host_suffix").(string) | ||
tarCHResId := d.Get("target_container_host_resource_id").(string) | ||
tarCHCredBase64 := d.Get("target_container_host_credentials_base64").(string) | ||
|
||
controller := devspaces.Controller{ | ||
Location: &location, | ||
Tags: expandTags(tags), | ||
Sku: sku, | ||
ControllerProperties: &devspaces.ControllerProperties{ | ||
HostSuffix: &hostSuffix, | ||
TargetContainerHostResourceID: &tarCHResId, | ||
TargetContainerHostCredentialsBase64: &tarCHCredBase64, | ||
}, | ||
} | ||
|
||
future, err := client.Create(ctx, resGroupName, name, controller) | ||
if err != nil { | ||
return fmt.Errorf("Error creating DevSpace Controller %q (Resource Group %q): %+v", name, resGroupName, err) | ||
} | ||
|
||
if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { | ||
return fmt.Errorf("Error waiting for creation of DevSpace Controller %q (Resource Group %q): %+v", name, resGroupName, err) | ||
} | ||
|
||
result, err := client.Get(ctx, resGroupName, name) | ||
if err != nil { | ||
return fmt.Errorf("Error retrieving DevSpace %q (Resource Group %q): %+v", name, resGroupName, err) | ||
} | ||
|
||
if result.ID == nil { | ||
return fmt.Errorf("Cannot read DevSpace Controller %q (Resource Group %q) ID", name, resGroupName) | ||
} | ||
d.SetId(*result.ID) | ||
|
||
return resourceArmDevSpaceControllerRead(d, meta) | ||
} | ||
|
||
func resourceArmDevSpaceControllerRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).devSpaceControllerClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
id, err := parseAzureResourceID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
resGroupName := id.ResourceGroup | ||
name := id.Path["controllers"] | ||
|
||
result, err := client.Get(ctx, resGroupName, name) | ||
if err != nil { | ||
if utils.ResponseWasNotFound(result.Response) { | ||
log.Printf("[DEBUG] DevSpace Controller %q was not found in Resource Group %q - removing from state!", name, resGroupName) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
return fmt.Errorf("Error making Read request on DevSpace Controller Lab %q (Resource Group %q): %+v", name, resGroupName, err) | ||
} | ||
|
||
d.Set("name", result.Name) | ||
d.Set("resource_group_name", resGroupName) | ||
if location := result.Location; location != nil { | ||
d.Set("location", azureRMNormalizeLocation(*location)) | ||
} | ||
|
||
d.Set("sku", flattenDevSpaceControllerSku(result.Sku)) | ||
|
||
if props := result.ControllerProperties; props != nil { | ||
if props.HostSuffix != nil { | ||
d.Set("host_suffix", props.HostSuffix) | ||
} | ||
|
||
if props.DataPlaneFqdn != nil { | ||
d.Set("data_plane_fqdn", props.DataPlaneFqdn) | ||
} | ||
|
||
if props.TargetContainerHostResourceID != nil { | ||
d.Set("target_container_host_resource_id", props.TargetContainerHostResourceID) | ||
} | ||
} | ||
|
||
flattenAndSetTags(d, result.Tags) | ||
|
||
return nil | ||
} | ||
|
||
func resourceArmDevSpaceControllerUpdate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).devSpaceControllerClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
log.Printf("[INFO] preparing arguments for DevSpace Controller updating") | ||
|
||
name := d.Get("name").(string) | ||
resGroupName := d.Get("resource_group_name").(string) | ||
tags := d.Get("tags").(map[string]interface{}) | ||
|
||
params := devspaces.ControllerUpdateParameters{ | ||
Tags: expandTags(tags), | ||
} | ||
|
||
result, err := client.Update(ctx, resGroupName, name, params) | ||
if err != nil { | ||
return fmt.Errorf("Error updating DevSpace Controller %q (Resource Group %q): %+v", name, resGroupName, err) | ||
} | ||
|
||
if result.ID == nil { | ||
return fmt.Errorf("Cannot read DevSpace Controller %q (Resource Group %q) ID", name, resGroupName) | ||
} | ||
d.SetId(*result.ID) | ||
|
||
return resourceArmDevSpaceControllerRead(d, meta) | ||
} | ||
|
||
func resourceArmDevSpaceControllerDelete(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).devSpaceControllerClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
id, err := parseAzureResourceID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
resGroupName := id.ResourceGroup | ||
name := id.Path["controllers"] | ||
|
||
future, err := client.Delete(ctx, resGroupName, name) | ||
if err != nil { | ||
return fmt.Errorf("Error deleting DevSpace Controller %q (Resource Group %q): %+v", name, resGroupName, err) | ||
} | ||
|
||
if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { | ||
return fmt.Errorf("Error waiting for the deletion of DevSpace Controller %q (Resource Group %q): %+v", name, resGroupName, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func expandDevSpaceControllerSku(d *schema.ResourceData) *devspaces.Sku { | ||
if _, ok := d.GetOk("sku"); !ok { | ||
return nil | ||
} | ||
|
||
skuConfigs := d.Get("sku").([]interface{}) | ||
skuConfig := skuConfigs[0].(map[string]interface{}) | ||
skuName := skuConfig["name"].(string) | ||
skuTier := devspaces.SkuTier(skuConfig["tier"].(string)) | ||
|
||
return &devspaces.Sku{ | ||
Name: &skuName, | ||
Tier: skuTier, | ||
} | ||
} | ||
|
||
func flattenDevSpaceControllerSku(skuObj *devspaces.Sku) []interface{} { | ||
if skuObj == nil { | ||
return []interface{}{} | ||
} | ||
|
||
skuConfig := make(map[string]interface{}, 0) | ||
skuConfig["name"] = *skuObj.Name | ||
skuConfig["tier"] = skuObj.Tier | ||
|
||
return []interface{}{skuConfig} | ||
} |
Oops, something went wrong.