-
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
Fastly Plugin #3716
Comments
Concerning the purge part. How about a resource for a Fastly object similar to aws_s3_bucket_object where the necessary purge calls are made when the content of said object have changed? Even if the file data is not uploaded through terraform explicit dependencies could be used to signal new versions. |
👍 this would be epic |
Would really love to see this happen! Would the sub-resources, such as |
Not supporting counts is one down-side of representing the entire config as one resource, so you're right that this design would make it impossible to dynamically produce sets of child objects (like domains) based on variables. I think the only way around this would be to model versions explicitly, which is another alternative design I considered. In that case you'd end up with a structure like this: resource "fastly_service" "example" {
name = "example"
}
// This weird resource exists only to collect together the versioned resources.
// This resource has a computed attribute called "version" that updates on
// refresh so that it always matches the next unused version number,
// causing all of the downstream resources to update on every apply.
resource "fastly_config_version" "example" {
service_id = "${fastly_service.example.id}"
}
resource "fastly_domain" "example" {
service_id = "${fastly_service.example.id}"
// Since this references the version, it will always show a diff because
// there is always a new version to create.
version_id = "${fastly_config_version.example.id}"
hostname = "example.com"
description = "Main Site"
}
// This resource finally "sets live" the version we created earlier.
// At that point further updates are impossible and so a new version
// number must be assigned on the next refresh, which will cause
// this whole process to happen again.
resource "fastly_service_version_attachment" "example" {
service_id = "${fastly.service.example.id}"
version_id = "${fastly_config_version.example.id}"
} The huge downside of this design is that it can never converge: by splitting into distinct resources, the The alternative alternative I considered was to clone the config and edit it for each individual resource update. In this case, the version concept would not be modeled in the terraform config, and instead each Terraform apply would potentially increment the version number several times, with one config for each individual resource that changed. This would mean that partial configs would temporarily "go live" as the diff is applied, and it would necessarily make big updates slower due to the need to serialize all of the updates into a separate "clone config, change settings, set new config live" cycle. With all of that said, I'd love to hear alternative design suggestions that make a better compromise between these concerns. |
+1 |
Hi there, I'm going to chime in a bit here 😄. I wrote the Fastly golang API client (https://github.com/sethvargo/go-fastly), so I'm pretty familiar with Fastly's API process. Speaking totally outside of Terraform, the Fastly Flow ™️ is as follows:
I believe Terraform should transparently mask 1 and 2 for the user. Terraform should know if there are any changes to the resources from the last known state. If there exists any changes, clone a new version and update all resources on that version. Then validate and activate that version. I'm also not opposed to the "all-in-one" option originally proposed, but it seems to go against Terraform's design for other resources. |
I would love that, if it's possible. Can Terraform group resources together and do another action when the group is fully applied? |
@sethvargo I took another go at trying to make this work, by working through the steps you listed. (I'm not sure step 1 is always to clone the current configuration, but keeping that simplification for the sake of Terraform seems reasonable...) I think the main problem with mapping this to Terraform is that in Terraform every action must belong to either a resource or a provisioner, and each resource and provisioner has access only to its own state/diff. Thus it's not clear which resource(s)/provisioner(s) should own each step in a world where each Fastly concept maps to its own resource:
So with all of that said, I'd love to support separate Terraform resources for each Fastly object (in particular, I have a use-case for piecemeal adding of Domains which the above proposed design wouldn't support), but I don't see any way to model the Fastly API resources separately while preserving the correct order of operations and maintaining a reasonable Terraform user experience. Since I originally wrote this up I was working on a provider for Grafana in #3480 where there's a similar sort of issue where the whole dashboard deploys as a single unit but you'd like to build it from multiple separate resources. (No versioning in this case, but ends up causing similar design problems nonetheless.) In that case I found a different unusual solution by exploiting the fact that Grafana has its own first-class dashboard configuration format, and so I made the An advantage of this model is that it inverts the dependency tree: the So here's how that might look in the Fastly case: resource "fastly_service" "main" {
config = "${fastly_service_config.main.serialized_config}"
}
resource "fastly_service_config" "main" {
name = "example"
default_host = "example.com"
default_ttl = 600
domain_configs = [
"${fastly_domain_config.apex.serialized_config}",
"${fastly_domain_config.www.serialized_config}",
]
// etc, etc
}
resource "fastly_domain_config" "apex" {
hostname = "example.com"
description = "Main Site"
}
resource "fastly_domain_config" "www" {
hostname = "www.example.com"
description = "www Alias"
} In Grafana's case, this weird design can be further justified by using the same serialization format you get when you export a Dashboard from Grafana's UI, thus giving users a way to mix and match UI-authored configs with Terraform-generated configs. The issue with applying such a model to Fastly is that they don't have any sort of documented serialization of an entire service configuration, so any format used in those So this gets us a bit closer, but doesn't quite feel right yet. |
If #2275 was implemented it might help. |
+1 for this Thanks! |
Hey friends – I recently merged #5814 which implements @apparentlymart 's original idea for a Fastly provider. Big thanks to him for the initial thought work 😄 Let me know if you have any other questions! |
resource/lb_*: drop custom ValidateFuncs
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. |
It's very likely that I'll soon need (and thus write) a Fastly plugin. Fastly is a CDN service.
I'm opening this issue to collect the results of my initial research and to describe an interesting design challenge a Fastly plugin represents, in case others have feedback on the tradeoffs I'm thinking about.
"Service" resource
The main interesting resource type in Fastly is the "service", which is similar in principle to an AWS CloudFront "Web Distribution". However, Fastly implements its own concept of configuration versions for services, which requires an API workflow that isn't just simple CRUD.
Rather than modelling the the version concept explicitly in Terraform, I'm planning to hide it away behind the
Update
action, with every update always creating a new version and immediately setting it live. This makes the Terraform-based workflow quite different than the usual web UI workflow, but I feel that the versioning construct in the web UI is not really necessary when you're presumably putting the Terraform config under conventional version control, and you have Terraform's own plan/apply cycle to help you understand what is being changed.A further implication of treating versioning this way is that it's necessary to model the service and all of its descendant objects as a single resource. If they were all their own resources then each Terraform apply would generate potentially dozens of intermediate versions.
This leaves the service resource with quite a large schema:
Other resources
The only other resource that seems interesting to model in Terraform is User, allowing the use of Terraform to manage the set of users who have access to an account.
Purge Provisioner?
While not strictly related to a Fastly provider (unless something comes out of the idea in #2756), it could be useful to expose cache purging as a provisioner, e.g. so that Terraform can help ensure that a new app version is available shortly after it's been deployed.
The text was updated successfully, but these errors were encountered: