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

Deprecations, Removals, and changes for 2.0.0 #49

Merged
merged 25 commits into from
Jun 21, 2018
Merged

Deprecations, Removals, and changes for 2.0.0 #49

merged 25 commits into from
Jun 21, 2018

Conversation

pearkes
Copy link
Contributor

@pearkes pearkes commented Jun 6, 2018

You may want to review #46 for more context on these changes, as they are part of a larger effort to simplify the user experience of the provider.

Motivation

This PR includes major backwards incompatible changes from the current version of the provider. This was required due to:

  • Upstream Consul API breaking changes (in 1.0 and otherwise)
  • Overlapping use cases between resources (some duplication in service registration, querying)
  • Allowing for unsupported / discouraged use cases, eg registering services against a local agent with Terraform

Changes

  • consul_agent_self has been deprecated. It does not work at all on Consul 1.0+ due to an upstream change. Because it had no required attributes, I've added one named deprecated which can be set to a boolean value, which then emits a warning stating it will be removed. This is the best UX I could come up with for deprecating an entire resource. Note that consul_agent_config was added in New data source: consul_agent_config #42 which provides some similar functionality.
  • consul_catalog_* renamed. The catalog datasources were renamed, removing the "catalog" part of the name. This is mostly for clarity as all service/node resources + datasources should use the catalog in the Terraform provider. Aliases were created, so the old naming should still work.
  • Deprecation warnings for consul_agent_service, consul_catalog_entry. Warnings have been added about upcoming deprecations for these resources due to the presence of consul_node and consul_service.
  • Upgrade guide. Added a comprehensive upgrade guide coming from the 1.x.x series.
  • consul_service changes. The consul_service resource now uses the catalog APIs and requires a node to be specified. Please see this comment for more detail.
  • Consul client upgrade. This upgrades the vendored version of the Consul API client to the 1.1.0 version, which is the latest Consul release.

Overall, I believe this is the least amount of change possible in this release in order to clarify several different problems reported by users of the provider to date, and to lay groundwork for future support of Consul features, covered in detail by #46. It was tough to propose these changes given it could possibly cause significant downstream work, but I believe the trade-off is worth it.

As a reminder, any users wishing to stay on the 1.x.x series of the provider can do so by pinning the version in the provider block:

provider "consul" {
  version = "1.0.0"
}

I'd definitely appreciate review and feedback on both implementation and upgrade strategies.

@pearkes pearkes requested a review from a team June 6, 2018 22:34
Type: schema.TypeBool,
Required: true,
Deprecated: "The consul_agent_self resource will be deprecated and removed in a future version. More information: https://github.com/terraform-providers/terraform-provider-consul/issues/46",
},
Copy link
Member

Choose a reason for hiding this comment

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

We have precedent for deprecating resource types from back when some of them were reworked as data sources, implemented via a transform function.

It could be reasonable to add another similar function that allows attaching a more free-form deprecation message via the same hook. The message added here, if non-empty, is returned as a warning during the validation step.

Your approach here is an interesting workaround, but it'll cause users to need to upgrade their configs to add this additional attribute, making this more of an "opt in to legacy behavior" flag. Certainly better than just removing it outright, of course!

Type: schema.TypeBool,
Required: true,
Deprecated: "The consul_agent_self resource will be deprecated and removed in a future version. More information: https://github.com/terraform-providers/terraform-provider-consul/issues/46",
},
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm curious about this resource deprecation strategy. Essentially, it's going to force all users to add a deprecated key to their configs, which is technically a backwards incompatible change itself, isn't it?

But I notice the resource has no other user-supplied fields on it, which makes it hard to mark as deprecated otherwise.

Is this solution the result of a previous discussion, or is a discussion about alternatives worthwhile?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Essentially, it's going to force all users to add a deprecated key to their configs, which is technically a backwards incompatible change itself, isn't it?

Yes, exactly. This is a solution based on a previous discussion about how there is no good solution. I'm super open to fixing it, but it sounds like we'd need an upstream change to support it that isn't near-term.

@@ -9,6 +9,8 @@ import (
)

func TestAccDataConsulAgentSelf_basic(t *testing.T) {
t.Skip("consul_agent_self is incompatible with Consul versions >= 1.0. It has been deprecated and will be removed in an upcoming version.")
Copy link
Contributor

Choose a reason for hiding this comment

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

Generally we continue to test things that are deprecated until they're actually removed, I believe, because we have a responsibility to make sure even deprecated things continue to work.

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 agree -- unfortunately the upstream API no longer supports this so the tests fail outright. Should I just leave them failing?

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's fine by me, just felt better to call Skip() like this.

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps we could make this opt-in with an environment variable, so we can still run tests against older versions of Consul if we want to?

In practice we're unlikely to actually bother to do this in any sort of automatic way, so I'd honestly be fine with leaving this t.Skip hardcoded under the expectation that we'll manually remove it temporarily for testing if we end up needing to do some further dev work for this against older versions of Consul. (which seems unlikely in itself)

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean, the ideal here would be to run tests against the last version of Consul to support this and the latest version of Consul, and use an environment variable to switch whether this was skipped or not.

But also, I don't think it's pressing enough to have a full test matrix built up before we review this PR, so I'm fine with skipping the tests that don't and can't pass, with the understanding that we'll be removing that functionality ASAP.

"github.com/hashicorp/terraform/helper/resource"
)

func TestAccDataConsulCatalogNodes_basic(t *testing.T) {
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 worth taking this opportunity to drop the Catalog from the test name, as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes -- this was me being lazy but I think now's the time. Will address.

"github.com/hashicorp/terraform/helper/resource"
)

func TestAccDataConsulCatalogService_basic(t *testing.T) {
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 worth taking this opportunity to drop the Catalog from the test name as well?

"github.com/hashicorp/terraform/helper/resource"
)

func TestAccDataConsulCatalogServices_basic(t *testing.T) {
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 worth taking this opportunity to drop the Catalog from the test name, too?

}

// Clear the ID
d.SetId("")
return nil
}

func retrieveService(client *consulapi.Client, name string, ident string, node string, dc string) (*consulapi.CatalogService, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see where node is used in this function. Am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Awesome catch. That was pretty vital due to the Consul data model, I hadn't actually done the appropriate check for matching a service. Also highlighted a gap in my tests.

testAccCheckConsulServiceValue("consul_service.app", "tags.0", "tag0"),
testAccCheckConsulServiceValue("consul_service.app", "tags.1", "tag1"),
resource.TestCheckResourceAttr("consul_service.google", "id", "google"),
resource.TestCheckResourceAttr("consul_service.google", "address", "www.google.com"),
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know how we feel about using google.com in our tests, but just calling out that hashicorptest.com exists if you ever need a test domain that doesn't serve content.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah sounds good. This was just in here but I like switching it out.

resource.TestCheckResourceAttr("consul_service.google", "address", "lb.google.com"),
),
},
},
Copy link
Contributor

Choose a reason for hiding this comment

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

My only real nitpick with this test is that it checks that the tests modified what they were supposed to, but doesn't check that the things they weren't supposed to modify are still what we can expect. If there's a bug that causes a field to get unset in state, or set to a wrong value in state, on update this won't catch it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, totally fair. Going to add some more checks.


## Attributes Reference

The following attributes are exported:

* `service_id` - The id of the service, defaults to the value of `name`.
* `id` - The ID of the service.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd highly recommend storing IDs that mean something to users in something other than id, because we often have to overload those for import, and it gets your users in the habit of treating id as opaque while still making the information accessible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're totally right, this change was not needed actually, we already expose service_id for this purpose. Fixed the docs and updated a test to check my assumption there.

page_title: "Consul: consul_catalog_nodes"
sidebar_current: "docs-consul-data-source-catalog-nodes"
page_title: "Consul: consul_nodes"
sidebar_current: "docs-consul-data-source-nodes"
Copy link
Contributor

Choose a reason for hiding this comment

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

You also need to update these in website/consul.erb or the sidebar highlighting won't work anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed, thanks!

@@ -81,7 +81,7 @@ func resourceConsulServiceCreate(d *schema.ResourceData, meta interface{}) error
// managed by the consul_node resource (or datasource)
nodeCheck, _, err := client.Catalog().Node(node, &consulapi.QueryOptions{Datacenter: dc})
if err != nil {
return fmt.Errorf("Cannot retrieve node: %v", err)
return fmt.Errorf("Cannot retrieve node '%s': %v", node, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip for future: %q will correctly quote and escape strings.

Not worth changing, just thought I'd call it out in case you weren't aware.

@@ -135,9 +135,11 @@ func resourceConsulServiceCreate(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("Failed to register service (dc: '%s'): %v", dc, err)
}

// Retrieve the service again to get the canonical service ID. We can't
// get this back from the register call or through
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like you dropped part of this comment?

@paddycarver paddycarver dismissed their stale review June 19, 2018 18:23

Changes made.

@paddycarver
Copy link
Contributor

All the changes made look good to me. I think the code of this looks fine, with the exception of that deprecated resource. I haven't run the tests yet, but I'll do that and make sure they still pass for me, too. I'd say we're good to go on this if we can't get a better solution to that deprecated resource in time.

I'm going to work on a PR today to make it possible to deprecate an entire resource. I'll link it from here. If we can get that reviewed and merged to Terraform core this week, I'd much rather we go down that road. And it seems like that's possible? So if we can do that, and you can just vendor Terraform at that commit, and update the resource in question to use the new Deprecated property, I think that's a better way forward, if we can make the timeline work.

If we get tight on time, I'm reluctantly OK with merging this as-is, because absent a Terraform core change, I don't see a better solution.

@paddycarver
Copy link
Contributor

hashicorp/terraform#18286 has been opened to make it so providers can deprecate resources. :)

@paddycarver
Copy link
Contributor

As of hashicorp/terraform@ec998a2, we have support for deprecating resources, not just fields. @pearkes, do you want to update your vendored copy and we can fix how the consul_agent_self data source is deprecated?

@pearkes
Copy link
Contributor Author

pearkes commented Jun 21, 2018

@paddycarver Awesome. Will work on an update and ping you for a final look!

@pearkes
Copy link
Contributor Author

pearkes commented Jun 21, 2018

@paddycarver updated to that version and utilizing it in 497123c! Here's the output in practice, looks great:

$ cat main.tf | grep agent_self
data "consul_agent_self" "read-agent" {}
$ terraform plan

Warning: data.consul_agent_self.read-agent: The consul_agent_self resource will be deprecated and removed in a future version. More information: https://github.com/terraform-providers/terraform-provider-consul/issues/46

Copy link
Contributor

@paddycarver paddycarver left a comment

Choose a reason for hiding this comment

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

Tests pass in CI, Travis is happy again, and our resource deprecations look great.

Amazing job @pearkes, this looks fantastic. Super excited for 2.0.0!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants