-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
Support for multiple providers of the same type #1281
Conversation
It looks like the issue with user input I mentioned under "known issues" already existed on the current master, so I've opened issue #1282. |
I think it would be a good exercise to see what this would look like in the documentation. Currently, it says:
I'm not sure this is actually true, since providers map whole resource names: ResourcesMap: map[string]*schema.Resource{
"aws_autoscaling_group": resourceAwsAutoscalingGroup(),
"aws_db_instance": resourceAwsDbInstance(),
"aws_db_parameter_group": resourceAwsDbParameterGroup(),
"aws_db_security_group": resourceAwsDbSecurityGroup(),
// [...]
}, Anyhow, how does the documentation get amended to describe the proposed behavior?
I think it's difficult to describe. Especially the edge cases. For example, what's this do?
I'd also say there's already a syntax for naming things, the
so if we need a way to name providers, why not one of these:
There is a bit of inconsistency in option 1. Consider, an Option 2 is a bit weird since a Option 3 resolves this inconsistency by always using Option 4 resolves the ambiguity by always using |
Thanks for the feedback.
Yeah, as you said, that description doesn't seem to match what I'm seeing in the code. In terraform/util.go
Yes, I would actually prefer that syntax for consistency with the configuration for resource names. This was in fact the first format suggested by @phinze on IRC, but I haven't found a practical way to support it. The problem is that Terraform first parses the config into simple data-structures where these two formats are equivalent nested maps:
For resources, the name is required, so it always recurses one level to extract the name, but for providers it would be optional. Since those structures are equivalent, there's no straightforward way to distinguish when the key is intended as a name for the provider, or part of its config. I'll keep thinking about that one, since I agree it would be preferable. As for changing the resource type name to map it to a provider instance, that's an interesting suggestion, though the current use of the
This gives a validation error, since the "aws" provider doesn't support that type of resource:
|
You could probably make a pretty good heuristic guess. I'd wager that there are no providers where all their configuration keys are maps (if there are any maps at all), so if you are looking at the root object, inspect the keys. If all of them are maps, then guess that the keys are names of providers to instantiate, using the new proposed syntax. Or, if some of the values are not maps, then emit a deprecation warning and assume it's using the old syntax. Instantiate just one provider using the provider type as the name. You can make an even better guess if you know the schema of the provider, but I'm guessing that may not be easily accomplished.
I was sure it did something, and this was one of my guesses. The point is that the semantics are complicated and hard to describe, and while you could elaborate on them in the documentation, people probably won't read it. |
@bitglue yes, the built-in providers do not use nested maps at this time, but it's still valid for a provider's schema to do that. There might be third-party plugins that do, or this might be useful in the future, so I didn't want to make those assumptions about the schema. Using the schema validation to make a better guess does seem like a good idea, but I think would require some more complicated restructuring of the config processing, since the alias is needed a few steps before validation takes place. @phinze or @mitchellh I'd love to hear your thoughts on the "alias" field, or other ways to specify that in the configuration. |
I just came across another use case in my configurations that's probably relevant here. In a few places, I create IAM policies. IAM policies frequently need to contain the region and the account number in ARNs. Currently I just paste these values into the policy, but that makes my configuration quite unportable. I could also push them up to variables the user must provide, but it seems undesirable to burden the user with providing more information that could be calculate from information they've already provided. (The account number can be found, given an AWS API key). Each of these things has the same scope as an AWS connection, represented by an AWS provider. It would be very elegant if I could interpolate these values by referencing a provider instance, much as variables from resource instances can be interpolated now. Another reason, I think, to make provider syntax identical to resource syntax. |
5ae9795
to
2b7d68a
Compare
I just updated the PR with some unit tests and an AWS acceptance test. @bitglue do you have an example of what you're doing? It sounds like you're asking for the interpolation syntax to support referencing provider attributes, which sounds useful, but beyond the scope of this feature. |
@bitglue oh BTW, I talked with @phinze on IRC yesterday. He mentioned that they have some plans in mind to improve the config parser to be able to support the |
Here's what I'm doing specifically:
It would much better if I could have
and then later:
Agreed, interpolation like this is out of scope here, and by adopting a provider syntax that's consistent with resource syntax, it's immediately obvious how interpolation would work when it is implemented. I also still think you should just go ahead with implementing that syntax now. You don't need any changes to the parser because you can know that someone is using the new syntax because all of the keys will be maps, which I think is guaranteed to never happen with any existent provider because all providers have at least one attribute which is not a map. Deprecate the old syntax now and remove it in a few releases. |
We would really like to see this for 4.0. It blocks our move to Atlas for @ https://github.com/CiscoCloud/microservices-infrastructure |
@keithchambers This won't make it in 0.4 since it just isn't ready, and we're releasing 0.4 right now. But it is our priority for the next version which will have a much shorter release cycle. |
@bitglue well as I mentioned before, the method you suggested would seem to work for the built-in providers, but providers can be extended by plugins. Some plugins could use maps in their config, so I wouldn't want to introduce a change that would potentially break a third-party plugin due to a new interpretation of the config syntax. I still like the syntax, but at this point I don't see a way to do it without some possible breaking changes. I'll leave it to the Hashicorp developers to decide how or when they'd want to make that change. |
As I proposed, it would only be a problem if the provider was configured only by maps. I think it's extremely unlikely that someone implemented a provider which doesn't have a single scalar configuration value, or no configuration at all. This very tiny hypothetical breakage seems insignificant in comparison with the inherent instability of a 0.x software. I already have to patch bugs in Terraform almost every time I update it -- if I had to open up my manifests and change |
@bitglue I'll leave that judgement to the Hashicorp team, who knows a lot more about the plugin community than I do. I've found them quite helpful on the IRC channel, so I'm sure you could chat with them more about those ideas. One issue is that they seemed to want the alias to be an optional extra parameter in the Also, while I agree that it's unlikely that a provider's schema would only contain maps, consider this config:
Your proposed solution would correctly distinguish this config, however, the While the chances of this might be slim, I don't know the Terraform community well enough to determine the risk myself. So, I'd recommend talking it over with the Hashicorp team for more feedback. |
Talked to @phinze on IRC. Sounds like he's in agreement that
|
Is this going to make it into the next release? |
@progrium Yes |
Thanks @mitchellh, let me know if there some additional tests or anything you'd like to see. |
Hi @mgood Thanks for this! Also i agree with @bitglue that the format within resource types needs to flow better with the existing, top level naming decleration. Also, what is the expectation in the below scenario:
In my mind, Terraform should deploy the security group to ALL configured providers (of type AWS in this case) (with each provider then getting one instance each as configured with the provider: option). I guess in @bitglue 's naming format i'm saying resource This would allow multi-region deployments to share common resources without the need for duplication in the TF file (example, keys, security groups, image uploads (when supported)). Thoughts? |
@matjohn2 That's a use case I hadn't considered, though I think it would be better if the syntax to do it on all matching providers were explicit. Otherwise you forget to type something, and you get a big surprise. Having an explicit syntax would also allow richer syntax about what matches. Globs, regexes, etc. to apply to many, but not all the providers. |
@matjohn2 the issues I'd mentioned initially have since been addressed. The Hashicorp devs might notice something else while reviewing the change, but I think it's complete at this point. The provider syntax will eventually be changed to Any resources without an explicit Although, I believe that AWS security groups are "global" and not region-specific. So for security groups, you could define them just once, with any valid AWS provider and they would be usable by instances created in other regions. |
Thanks @mgood I aliased both provider sections (there is no provider in my configuration without an alias line). When each of the resources are assigned to the same 'provider:' everything is fine, but if I assign the security group (for example), to another aliased provider, i'd expect Instead, it succeeds, as if the planning/dependancy logic is aware only of the high level provider vs sub-region requirements. This then fails at the apply stage with an openstack error response, as we have attempted creation of an instance, using a security group that doesn't exist in that region.
I've also tested this on other resource types (ie, the Openstack Quantum network i'm creating) with a similar dependancy-related issue, resulting in an apply-time error. My configuration is below, minus credentials. In the example, you can see the security group is in a different provider region, tx1 vs int1. Shout if it's incorrect and i'm bringing this upon myself! Also, it's really easy to 'lose a resource' by changing the 'provider:' field, TF plan shows the resource needs creating in the new region, but forgets about your old instance. This seems to be another side affect of the same issue.
Matt |
This is interesting as I had a long term plan to add region to all google resources that did not already have a zone. This PR would make that unnecessary, although it seems like a bit of a hack to create a whole new provider config just to make it possible to deploy multi-region. |
@matjohn2 I think that's just a configuration issue, not a bug. When you use the syntax |
Adds an "alias" field to the provider which allows creating multiple instances of a provider under different names. This provides support for configurations such as multiple AWS providers for different regions. In each resource, the provider can be set with the "provider" field. (thanks to Cisco Cloud for their support)
Yes the resource model is not type-checked. Failures always come from the APIs behind the providers, so this is WAI. Lack of knowledge within Terraform of these kinds of constraints reminds me of #178 |
Pulling this down to do a full review now. Please don't make any more changes, or notify me if you need to! |
Great job. I finished the review, fixed the merge conflict, and I'm merging this in. There are some additional tests and bug fixes I need to make but I'll do so via another upcoming PR. |
Merged: 21b0a03 |
Thanks @mitchellh and @phinze |
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. |
This is incomplete, but I'm submitting to start getting feedback. This will enable support for #451.
Adds an "alias" field to the provider which allows creating multiple instances
of a provider under different names. This provides support for configurations
such as multiple AWS providers for different regions. In each resource, the
provider can be set with the "provider" field.
Known issues:
Tentatively, the config syntax looks like this:
(thanks to Cisco Cloud for sponsoring development)