Merge pull request #5204 from hashicorp/f-riviera-resource-groups
provider/azurerm: Use Riviera for Resource Groups
This commit is contained in:
commit
27d82a2397
|
@ -536,15 +536,15 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/jen20/riviera/azure",
|
"ImportPath": "github.com/jen20/riviera/azure",
|
||||||
"Rev": "5bae671a2903c37b4d580f24d9ab74ada633813f"
|
"Rev": "31f4644de1f4931e43271240069bf2b896f47005"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/jen20/riviera/dns",
|
"ImportPath": "github.com/jen20/riviera/dns",
|
||||||
"Rev": "5bae671a2903c37b4d580f24d9ab74ada633813f"
|
"Rev": "31f4644de1f4931e43271240069bf2b896f47005"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/jen20/riviera/sql",
|
"ImportPath": "github.com/jen20/riviera/sql",
|
||||||
"Rev": "5bae671a2903c37b4d580f24d9ab74ada633813f"
|
"Rev": "31f4644de1f4931e43271240069bf2b896f47005"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/jmespath/go-jmespath",
|
"ImportPath": "github.com/jmespath/go-jmespath",
|
||||||
|
|
|
@ -3,14 +3,11 @@ package azurerm
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
|
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/jen20/riviera/azure"
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceArmResourceGroup() *schema.Resource {
|
func resourceArmResourceGroup() *schema.Resource {
|
||||||
|
@ -60,20 +57,27 @@ func validateArmResourceGroupName(v interface{}, k string) (ws []string, es []er
|
||||||
|
|
||||||
func resourceArmResourceGroupUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourceArmResourceGroupUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*ArmClient)
|
client := meta.(*ArmClient)
|
||||||
resGroupClient := client.resourceGroupClient
|
rivieraClient := client.rivieraClient
|
||||||
|
|
||||||
if !d.HasChange("tags") {
|
if !d.HasChange("tags") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
name := d.Get("name").(string)
|
name := d.Get("name").(string)
|
||||||
|
|
||||||
newTags := d.Get("tags").(map[string]interface{})
|
newTags := d.Get("tags").(map[string]interface{})
|
||||||
_, err := resGroupClient.Patch(name, resources.ResourceGroup{
|
|
||||||
Tags: expandTags(newTags),
|
updateRequest := rivieraClient.NewRequestForURI(d.Id())
|
||||||
})
|
updateRequest.Command = &azure.UpdateResourceGroup{
|
||||||
|
Name: name,
|
||||||
|
Tags: *expandTags(newTags),
|
||||||
|
}
|
||||||
|
|
||||||
|
updateResponse, err := updateRequest.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error issuing Azure ARM create request to update resource group %q: %s", name, err)
|
return fmt.Errorf("Error updating resource group: %s", err)
|
||||||
|
}
|
||||||
|
if !updateResponse.IsSuccessful() {
|
||||||
|
return fmt.Errorf("Error updating resource group: %s", updateResponse.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourceArmResourceGroupRead(d, meta)
|
return resourceArmResourceGroupRead(d, meta)
|
||||||
|
@ -81,110 +85,100 @@ func resourceArmResourceGroupUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
func resourceArmResourceGroupCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceArmResourceGroupCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*ArmClient)
|
client := meta.(*ArmClient)
|
||||||
resGroupClient := client.resourceGroupClient
|
rivieraClient := client.rivieraClient
|
||||||
|
|
||||||
name := d.Get("name").(string)
|
createRequest := rivieraClient.NewRequest()
|
||||||
location := d.Get("location").(string)
|
createRequest.Command = &azure.CreateResourceGroup{
|
||||||
tags := d.Get("tags").(map[string]interface{})
|
Name: d.Get("name").(string),
|
||||||
|
Location: d.Get("location").(string),
|
||||||
rg := resources.ResourceGroup{
|
Tags: *expandTags(d.Get("tags").(map[string]interface{})),
|
||||||
Name: &name,
|
|
||||||
Location: &location,
|
|
||||||
Tags: expandTags(tags),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := resGroupClient.CreateOrUpdate(name, rg)
|
createResponse, err := createRequest.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error issuing Azure ARM create request for resource group '%s': %s", name, err)
|
return fmt.Errorf("Error creating resource group: %s", err)
|
||||||
|
}
|
||||||
|
if !createResponse.IsSuccessful() {
|
||||||
|
return fmt.Errorf("Error creating resource group: %s", createResponse.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp := createResponse.Parsed.(*azure.CreateResourceGroupResponse)
|
||||||
d.SetId(*resp.ID)
|
d.SetId(*resp.ID)
|
||||||
|
|
||||||
log.Printf("[DEBUG] Waiting for Resource Group (%s) to become available", name)
|
// TODO(jen20): Decide whether we need this or not and migrate to use @stack72's work if so
|
||||||
stateConf := &resource.StateChangeConf{
|
// log.Printf("[DEBUG] Waiting for Resource Group (%s) to become available", name)
|
||||||
Pending: []string{"Accepted"},
|
// stateConf := &resource.StateChangeConf{
|
||||||
Target: []string{"Succeeded"},
|
// Pending: []string{"Accepted"},
|
||||||
Refresh: resourceGroupStateRefreshFunc(client, name),
|
// Target: []string{"Succeeded"},
|
||||||
Timeout: 10 * time.Minute,
|
// Refresh: resourceGroupStateRefreshFunc(client, name),
|
||||||
}
|
// Timeout: 10 * time.Minute,
|
||||||
if _, err := stateConf.WaitForState(); err != nil {
|
// }
|
||||||
return fmt.Errorf("Error waiting for Resource Group (%s) to become available: %s", name, err)
|
// if _, err := stateConf.WaitForState(); err != nil {
|
||||||
}
|
// return fmt.Errorf("Error waiting for Resource Group (%s) to become available: %s", name, err)
|
||||||
|
// }
|
||||||
|
|
||||||
return resourceArmResourceGroupRead(d, meta)
|
return resourceArmResourceGroupRead(d, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceArmResourceGroupRead(d *schema.ResourceData, meta interface{}) error {
|
func resourceArmResourceGroupRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
resGroupClient := meta.(*ArmClient).resourceGroupClient
|
client := meta.(*ArmClient)
|
||||||
|
rivieraClient := client.rivieraClient
|
||||||
|
|
||||||
id, err := parseAzureResourceID(d.Id())
|
readRequest := rivieraClient.NewRequestForURI(d.Id())
|
||||||
|
readRequest.Command = &azure.GetResourceGroup{}
|
||||||
|
|
||||||
|
readResponse, err := readRequest.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("Error reading resource group: %s", err)
|
||||||
}
|
}
|
||||||
name := id.ResourceGroup
|
if !readResponse.IsSuccessful() {
|
||||||
|
log.Printf("[INFO] Error reading resource group %q - removing from state", d.Id())
|
||||||
res, err := resGroupClient.Get(name)
|
d.SetId("")
|
||||||
if err != nil {
|
return fmt.Errorf("Error reading resource group: %s", readResponse.Error)
|
||||||
if res.StatusCode == http.StatusNotFound {
|
|
||||||
d.SetId("")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("Error issuing read request to Azure ARM for resource group '%s': %s", name, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Set("name", res.Name)
|
resp := readResponse.Parsed.(*azure.GetResourceGroupResponse)
|
||||||
d.Set("location", res.Location)
|
|
||||||
|
|
||||||
flattenAndSetTags(d, res.Tags)
|
d.Set("name", resp.Name)
|
||||||
|
d.Set("location", resp.Location)
|
||||||
|
flattenAndSetTags(d, resp.Tags)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceArmResourceGroupExists(d *schema.ResourceData, meta interface{}) (bool, error) {
|
func resourceArmResourceGroupExists(d *schema.ResourceData, meta interface{}) (bool, error) {
|
||||||
resGroupClient := meta.(*ArmClient).resourceGroupClient
|
client := meta.(*ArmClient)
|
||||||
|
rivieraClient := client.rivieraClient
|
||||||
|
|
||||||
id, err := parseAzureResourceID(d.Id())
|
readRequest := rivieraClient.NewRequestForURI(d.Id())
|
||||||
|
readRequest.Command = &azure.GetResourceGroup{}
|
||||||
|
|
||||||
|
readResponse, err := readRequest.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, fmt.Errorf("Error reading resource group: %s", err)
|
||||||
}
|
}
|
||||||
name := id.ResourceGroup
|
if readResponse.IsSuccessful() {
|
||||||
|
|
||||||
resp, err := resGroupClient.CheckExistence(name)
|
|
||||||
if err != nil {
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceArmResourceGroupDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourceArmResourceGroupDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
resGroupClient := meta.(*ArmClient).resourceGroupClient
|
client := meta.(*ArmClient)
|
||||||
|
rivieraClient := client.rivieraClient
|
||||||
|
|
||||||
id, err := parseAzureResourceID(d.Id())
|
deleteRequest := rivieraClient.NewRequestForURI(d.Id())
|
||||||
|
deleteRequest.Command = &azure.DeleteResourceGroup{}
|
||||||
|
|
||||||
|
deleteResponse, err := deleteRequest.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("Error deleting resource group: %s", err)
|
||||||
}
|
}
|
||||||
name := id.ResourceGroup
|
if !deleteResponse.IsSuccessful() {
|
||||||
|
return fmt.Errorf("Error deleting resource group: %s", deleteResponse.Error)
|
||||||
_, err = resGroupClient.Delete(name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
|
||||||
|
|
||||||
func resourceGroupStateRefreshFunc(client *ArmClient, id string) resource.StateRefreshFunc {
|
|
||||||
return func() (interface{}, string, error) {
|
|
||||||
res, err := client.resourceGroupClient.Get(id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", fmt.Errorf("Error issuing read request in resourceGroupStateRefreshFunc to Azure ARM for resource group '%s': %s", id, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, *res.Properties.ProvisioningState, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,8 +128,8 @@ resource "azurerm_resource_group" "test" {
|
||||||
location = "West US"
|
location = "West US"
|
||||||
|
|
||||||
tags {
|
tags {
|
||||||
environment = "Production"
|
environment = "Production"
|
||||||
cost_center = "MSFT"
|
cost_center = "MSFT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package azure
|
||||||
|
|
||||||
|
type GetResourceGroupResponse struct {
|
||||||
|
ID *string `mapstructure:"id"`
|
||||||
|
Name *string `mapstructure:"name"`
|
||||||
|
Location *string `mapstructure:"location"`
|
||||||
|
ProvisioningState *string `mapstructure:"provisioningState"`
|
||||||
|
Tags *map[string]*string `mapstructure:"tags"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetResourceGroup struct {
|
||||||
|
Name string `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (command GetResourceGroup) APIInfo() APIInfo {
|
||||||
|
return APIInfo{
|
||||||
|
APIVersion: resourceGroupAPIVersion,
|
||||||
|
Method: "GET",
|
||||||
|
URLPathFunc: resourceGroupDefaultURLFunc(command.Name),
|
||||||
|
ResponseTypeFunc: func() interface{} {
|
||||||
|
return &GetResourceGroupResponse{}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,39 +26,24 @@ type Request struct {
|
||||||
client *Client
|
client *Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func readLocation(req interface{}) (string, bool) {
|
func readTaggedFields(command interface{}) map[string]interface{} {
|
||||||
var value reflect.Value
|
var value reflect.Value
|
||||||
if reflect.ValueOf(req).Kind() == reflect.Ptr {
|
if reflect.ValueOf(command).Kind() == reflect.Ptr {
|
||||||
value = reflect.ValueOf(req).Elem()
|
value = reflect.ValueOf(command).Elem()
|
||||||
} else {
|
} else {
|
||||||
value = reflect.ValueOf(req)
|
value = reflect.ValueOf(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
|
||||||
for i := 0; i < value.NumField(); i++ { // iterates through every struct type field
|
for i := 0; i < value.NumField(); i++ { // iterates through every struct type field
|
||||||
tag := value.Type().Field(i).Tag // returns the tag string
|
tag := value.Type().Field(i).Tag // returns the tag string
|
||||||
if tag.Get("riviera") == "location" {
|
tagValue := tag.Get("riviera")
|
||||||
return value.Field(i).String(), true
|
if tagValue != "" {
|
||||||
|
result[tagValue] = value.Field(i).Interface()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", false
|
return result
|
||||||
}
|
|
||||||
|
|
||||||
func readTags(req interface{}) (map[string]*string, bool) {
|
|
||||||
var value reflect.Value
|
|
||||||
if reflect.ValueOf(req).Kind() == reflect.Ptr {
|
|
||||||
value = reflect.ValueOf(req).Elem()
|
|
||||||
} else {
|
|
||||||
value = reflect.ValueOf(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < value.NumField(); i++ { // iterates through every struct type field
|
|
||||||
tag := value.Type().Field(i).Tag // returns the tag string
|
|
||||||
if tag.Get("riviera") == "tags" {
|
|
||||||
tags := value.Field(i)
|
|
||||||
return tags.Interface().(map[string]*string), true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return make(map[string]*string), false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (request *Request) pollForAsynchronousResponse(acceptedResponse *http.Response) (*http.Response, error) {
|
func (request *Request) pollForAsynchronousResponse(acceptedResponse *http.Response) (*http.Response, error) {
|
||||||
|
@ -108,24 +93,15 @@ func (request *Request) pollForAsynchronousResponse(acceptedResponse *http.Respo
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultARMRequestStruct(request *Request, properties interface{}) interface{} {
|
func defaultARMRequestStruct(request *Request, properties interface{}) interface{} {
|
||||||
bodyStruct := struct {
|
body := make(map[string]interface{})
|
||||||
Location *string `json:"location,omitempty"`
|
|
||||||
Tags *map[string]*string `json:"tags,omitempty"`
|
envelopeFields := readTaggedFields(properties)
|
||||||
Properties interface{} `json:"properties"`
|
for k, v := range envelopeFields {
|
||||||
}{
|
body[k] = v
|
||||||
Properties: properties,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if location, hasLocation := readLocation(request.Command); hasLocation {
|
body["properties"] = properties
|
||||||
bodyStruct.Location = &location
|
return body
|
||||||
}
|
|
||||||
if tags, hasTags := readTags(request.Command); hasTags {
|
|
||||||
if len(tags) > 0 {
|
|
||||||
bodyStruct.Tags = &tags
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bodyStruct
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultARMRequestSerialize(body interface{}) (io.ReadSeeker, error) {
|
func defaultARMRequestSerialize(body interface{}) (io.ReadSeeker, error) {
|
||||||
|
@ -162,6 +138,7 @@ func (request *Request) Execute() (*Response, error) {
|
||||||
} else {
|
} else {
|
||||||
bodyStruct = defaultARMRequestStruct(request, request.Command)
|
bodyStruct = defaultARMRequestStruct(request, request.Command)
|
||||||
}
|
}
|
||||||
|
|
||||||
serialized, err := defaultARMRequestSerialize(bodyStruct)
|
serialized, err := defaultARMRequestSerialize(bodyStruct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package azure
|
||||||
|
|
||||||
|
type UpdateResourceGroupResponse struct {
|
||||||
|
ID *string `mapstructure:"id"`
|
||||||
|
Name *string `mapstructure:"name"`
|
||||||
|
Location *string `mapstructure:"location"`
|
||||||
|
ProvisioningState *string `mapstructure:"provisioningState"`
|
||||||
|
Tags *map[string]*string `mapstructure:"tags"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateResourceGroup struct {
|
||||||
|
Name string `json:"-"`
|
||||||
|
Tags map[string]*string `json:"-" riviera:"tags"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (command UpdateResourceGroup) APIInfo() APIInfo {
|
||||||
|
return APIInfo{
|
||||||
|
APIVersion: resourceGroupAPIVersion,
|
||||||
|
Method: "PATCH",
|
||||||
|
URLPathFunc: resourceGroupDefaultURLFunc(command.Name),
|
||||||
|
ResponseTypeFunc: func() interface{} {
|
||||||
|
return &UpdateResourceGroupResponse{}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue