Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MS] provider/azurerm: New resource - Express Route Circuit #14265

Merged
merged 12 commits into from
May 14, 2017

Conversation

whiskeyjay
Copy link
Contributor

#14122 Adding basic support for Express Route Circuit.

Setting up an Express Route Circuit involves two major steps:

  • Creating an Express Route Circuit, then provide the "service key" to the connectivity provider for provisioning on their side.
  • Once the connection is provisioned by the provider, you can then continue to setup peering.

This change enables the first step, once the resource is created, the service key is returned as an attribute (see documentation).

Peering setup support is still underway, will be in another PR.

Tests:

$ make testacc TEST=./builtin/providers/azurerm TESTARGS='-run=TestAccAzureRMExpressRouteCircuit_importBasic'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/05/05 23:11:33 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/azurerm -v -run=TestAccAzureRMExpressRouteCircuit_importBasic -timeout 120m
=== RUN   TestAccAzureRMExpressRouteCircuit_importBasic
--- PASS: TestAccAzureRMExpressRouteCircuit_importBasic (97.99s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/azurerm	98.006s

$ make testacc TEST=./builtin/providers/azurerm TESTARGS='-run=TestAccAzureRMExpressRouteCircuit_basic'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/05/05 23:14:40 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/azurerm -v -run=TestAccAzureRMExpressRouteCircuit_basic -timeout 120m
=== RUN   TestAccAzureRMExpressRouteCircuit_basic
--- PASS: TestAccAzureRMExpressRouteCircuit_basic (125.20s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/azurerm	125.219s

Copy link
Contributor

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @whiskeyjay

Thanks for this PR - I've reviewed and left some comments in-line, but it generally looks good :)

Out of interest, is the list of Service Providers Name/Locations static, or can it change from time-to-time? (I'm wondering if it's worth some validation around this)

Thanks!

return err
}

if erc == nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to place this inside the error statement above - and explicitly check for a 404 here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That (check for 404) is done in the retrieveErcByResourceId function.

Required: true,
},

"sku_tier": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seeing as we need multiple properties here, would it be worth making this it's own object to make it clearer? i.e.

sku {
  family = "Metered"
  tier = "Standard"
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right!

"sku_tier": {
Type: schema.TypeString,
Optional: true,
Default: string(network.ExpressRouteCircuitSkuTierStandard),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we tend to make these explicit where possible, could we update this to remove the default and make this required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made "Required".

"sku_family": {
Type: schema.TypeString,
Optional: true,
Default: string(network.MeteredData),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same here)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made "Required".

"github.com/hashicorp/errwrap"
)

func extractResourceGroupAndErcName(resourceId string) (resourceGroup string, name string, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these methods going to be used outside of the Express Route resource? Otherwise would it make more sense for them to live in the resource until they're needed elsewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They will very likely be used by other types in the second part of Express Route work (peering). If not, I'll clean it up with peering support. Will that work? :)

The following attributes are exported:

* `id` - The Resource ID of the ExpressRoute circuit.
* `service_provider_provisioning_state` - The ServiceProviderProvisioningState state of the resource.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, I believe the only two states exposed for this field are going to be NotProvisioned and Provisioned - for when the resource doesn't exist, and does exist respectively. As such, is there much to be gained from exposing this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my bad - I copied the description from the REST API doc - this is actually the circuit provisioning state from the service provider, not the state of the resource representing the circuit. Only when the service provider has done their work, this attribute's value will be Provisioned and then further configuration of the ExpressRoute can be continued.

}

func testAccAzureRMExpressRouteCircuit_basic(rInt int) string {
return strings.Replace(`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to switch this out for a fmt.Sprintf to match the other acceptance tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to avoid future errors like adding/removing one or more %d in the config string but forgot to match the number of parameters supplied in Sprintf. That said, I also understand it would be nice to have a uniform coding style. Please let me know if this is indeed a style issue, I will be happy to change it to match existing ones.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@whiskeyjay so one option to avoid that issue when using a fmt.Sprintf is to use the substitute value of %[1]dto reference the first item rather than %d for this purpose (as you've seen we've started wrapping the test strings in a method, rather than formatting the string inside of each test to avoid the argument mismatch issue).

But yes, it'd be nice to make this consistent with the other acceptance tests if possible :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tombuildsstuff got it.

return errwrap.Wrapf("Error Deleting ExpressRouteCircuit {{err}}", err)
}

d.SetId("")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't needed in a Delete function - since the resource is removed from the state automatically :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

return errwrap.Wrapf("Error Parsing Azure Resource ID {{err}}", err)
}

_, err = ercClient.Delete(resGroup, name, make(chan struct{}))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just return the result of this error, rather than checking the result?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

Copy link
Contributor Author

@whiskeyjay whiskeyjay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed a few comments and made changes accordingly. Still working on the rest.

"github.com/hashicorp/errwrap"
)

func extractResourceGroupAndErcName(resourceId string) (resourceGroup string, name string, err error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They will very likely be used by other types in the second part of Express Route work (peering). If not, I'll clean it up with peering support. Will that work? :)

Required: true,
},

"sku_tier": {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right!

"sku_tier": {
Type: schema.TypeString,
Optional: true,
Default: string(network.ExpressRouteCircuitSkuTierStandard),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made "Required".

"sku_family": {
Type: schema.TypeString,
Optional: true,
Default: string(network.MeteredData),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made "Required".

The following attributes are exported:

* `id` - The Resource ID of the ExpressRoute circuit.
* `service_provider_provisioning_state` - The ServiceProviderProvisioningState state of the resource.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my bad - I copied the description from the REST API doc - this is actually the circuit provisioning state from the service provider, not the state of the resource representing the circuit. Only when the service provider has done their work, this attribute's value will be Provisioned and then further configuration of the ExpressRoute can be continued.

@whiskeyjay
Copy link
Contributor Author

@tombuildsstuff I made a few changes based on review comments; have one question regarding style in acc test file. Looking forward to your reply. Thanks!

Copy link
Contributor

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @whiskeyjay

Thanks for the ongoing effort here, I've taken another look and left a couple of minor comments in-line, but this otherwise LGTM :)

Thanks!

}
}

func resourceArmExpressRouteCircuitCreate(d *schema.ResourceData, meta interface{}) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: since this is both Creating and Updating, could we rename it resourceArmExpressRouteCircuitCreateOrUpdate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

serviceProviderName := d.Get("service_provider_name").(string)
peeringLocation := d.Get("peering_location").(string)
bandwidthInMbps := int32(d.Get("bandwidth_in_mbps").(int))
sku := expandExpressRouteCircuitSku(d.Get("sku").(*schema.Set))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we pass in d here and have the method take care of the casting, to be consistent with the other resources?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@tombuildsstuff tombuildsstuff added the waiting-response An issue/pull request is waiting for a response from the community label May 12, 2017
Copy link
Contributor Author

@whiskeyjay whiskeyjay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made changes in test (Replace -> Sprintf), and changed Create to CreateOrUpdate.

}
}

func resourceArmExpressRouteCircuitCreate(d *schema.ResourceData, meta interface{}) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

serviceProviderName := d.Get("service_provider_name").(string)
peeringLocation := d.Get("peering_location").(string)
bandwidthInMbps := int32(d.Get("bandwidth_in_mbps").(int))
sku := expandExpressRouteCircuitSku(d.Get("sku").(*schema.Set))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

func testAccAzureRMExpressRouteCircuit_basic(rInt int) string {
return strings.Replace(`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tombuildsstuff got it.

@tombuildsstuff tombuildsstuff removed the waiting-response An issue/pull request is waiting for a response from the community label May 14, 2017
@tombuildsstuff
Copy link
Contributor

tombuildsstuff commented May 14, 2017

Hi @whiskeyjay

Thanks for pushing the latest changes to this PR.

I've taken another look, pushed a minor tweak for consistency and run the tests and this LGTM :)

$ envchain azurerm make testacc TEST=./builtin/providers/azurerm TESTARGS='-run=TestAccAzureRMExpressRoute'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/05/14 13:26:45 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/azurerm -v -run=TestAccAzureRMExpressRoute -timeout 120m
=== RUN   TestAccAzureRMExpressRouteCircuit_importBasic
--- PASS: TestAccAzureRMExpressRouteCircuit_importBasic (124.33s)
=== RUN   TestAccAzureRMExpressRouteCircuit_basic
--- PASS: TestAccAzureRMExpressRouteCircuit_basic (143.59s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/azurerm	267.938s

Thanks!

@tombuildsstuff tombuildsstuff merged commit 6ca50dd into hashicorp:master May 14, 2017
tombuildsstuff added a commit that referenced this pull request May 14, 2017
@ghost
Copy link

ghost commented Apr 12, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Apr 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants