├── .github ├── dependabot.yaml ├── release.yaml └── workflows │ └── test.yaml ├── .gitignore ├── CHANGES.md ├── CONTRIBUTING.md ├── DCO ├── LICENSE ├── Makefile ├── README.md ├── docs ├── data-sources │ └── ct_config.md └── index.md ├── examples ├── .gitignore ├── content │ ├── fcos-snippet.yaml │ ├── fcos.yaml │ ├── flatcar-snippet.yaml │ └── flatcar.yaml ├── fedora-coreos.tf ├── flatcar-linux.tf └── versions.tf ├── go.mod ├── go.sum ├── internal ├── data_config.go ├── data_config_fcos_test.go ├── data_config_flatcar_test.go ├── hashcode.go ├── provider.go └── provider_test.go └── main.go /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: github-actions 8 | directory: "/" 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/release.yaml: -------------------------------------------------------------------------------- 1 | changelog: 2 | categories: 3 | - title: Contributions 4 | labels: 5 | - '*' 6 | exclude: 7 | labels: 8 | - dependencies 9 | - no-release-note 10 | - title: Dependencies 11 | labels: 12 | - dependencies 13 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | jobs: 10 | go: 11 | uses: poseidon/.github/.github/workflows/golang-library.yaml@main 12 | with: 13 | setup_terraform: true 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | _output/ 3 | *.test 4 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # terraform-provider-ct 2 | 3 | Notable changes between releases. 4 | 5 | ## Latest 6 | 7 | ## v0.13.0 8 | 9 | * Update the target stable Ignition spec version to v3.4.0 ([#156](https://github.com/poseidon/terraform-provider-ct/pull/156)) 10 | * Parse Butane Configs to Ignition v3.4.0 ([#159](https://github.com/poseidon/terraform-provider-ct/pull/159)) 11 | * Add support for `fcos` [v1.5.0](https://coreos.github.io/butane/config-fcos-v1_5/) Butane Configs 12 | * Add support for `flatcar` [v1.1.0](https://coreos.github.io/butane/config-flatcar-v1_1/) Butane Configs 13 | * Remove deprecated `platform` field 14 | * Move implementation to an `internal` package ([#157](https://github.com/poseidon/terraform-provider-ct/pull/157)) 15 | 16 | ## v0.12.0 17 | 18 | * Remove support for Container Linux Configs ([#132](https://github.com/poseidon/terraform-provider-ct/pull/132)) 19 | * Butane Configs support `fcos` and `flatcar` variants 20 | * Focus on converting Butane Configs (with different variants) to Ignition 21 | * Flatcar Linux now supports Ignition v3.3.0 22 | * Remove unused `github.com/coroes/ignition` (v1) dependencies 23 | * Deprecate the `platform` field, it's no longer used 24 | 25 | ## v0.11.0 26 | 27 | * Update coreos/butane from v0.14.0 to v0.15.0 ([#126](https://github.com/poseidon/terraform-provider-ct/pull/126)) 28 | * Add `flatcar` Butane Config variant with spec version 1.0.0 (generates Ignition v3.3.0) 29 | * Deprecate Container Linux Configs (please migrate to Butane Configs) 30 | * Update Go version to v1.18 31 | 32 | ## v0.10.0 33 | 34 | * Change how older (< 1.4) Butane Configs are parsed to Ignition ([#116](https://github.com/poseidon/terraform-provider-ct/pull/116)) 35 | * Parse Ignition bytes to the forward compatible Ignition version ([docs](https://github.com/poseidon/terraform-provider-ct#versions)) 36 | * Parse v1.3 Butane Configs to Ignition v3.3 37 | * Parse v1.2 Butane Configs to Ignition v3.3 38 | * Parse v1.1 Butane Configs to Ignition v3.3 39 | * Parse v1.0 Butane Configs to Ignition v3.3 40 | * Add support for verison skew among Butane Config snippets 41 | * Butane Config and snippets will always convert to the current Ignition version 42 | 43 | ## v0.9.2 44 | 45 | * Update butane, ignition, and Terraform SDK modules 46 | 47 | ## v0.9.1 48 | 49 | * Update Go version to v1.16+ 50 | * Add `darwin-arm64` release target 51 | 52 | ## v0.9.0 53 | 54 | * Add Butane Config v1.4.0 support ([#100](https://github.com/poseidon/terraform-provider-ct/pull/100)) 55 | * Accept Butane v1.4.0 config/snippets and render Ignition v3.3.0 56 | * Rename Fedora CoreOS Configs to Butane Configs 57 | * Remove Go module vendoring 58 | * Remove tarball release format 59 | 60 | ## v0.8.0 61 | 62 | * Migrate to Terraform Plugin SDK v2.3.0 ([#75](https://github.com/poseidon/terraform-provider-ct/pull/75)) 63 | * Add Fedora CoreOS Config v1.3.0 support ([#76](https://github.com/poseidon/terraform-provider-ct/pull/76)) 64 | 65 | ## v0.7.1 66 | 67 | * Fix possible empty rendered Ignition ([#72](https://github.com/poseidon/terraform-provider-ct/pull/72)) 68 | * Fix regression in rendering Fedora CoreOS v1.1.0 Configs with `snippets` and `pretty_print = false` 69 | * Remove Terraform v0.12.x instructions 70 | 71 | ## v0.7.0 72 | 73 | * Add Fedora CoreOS Config v1.2.0 support ([#71](https://github.com/poseidon/terraform-provider-ct/pull/71)) 74 | * Accept FCC v1.2.0 and output Ignition v3.2.0 75 | 76 | ## v0.6.1 77 | 78 | * Fix zip archive artifacts for Darwin and Windows ([#67](https://github.com/poseidon/terraform-provider-ct/pull/67)) 79 | * Add Linux ARM64 release artifacts ([#66](https://github.com/poseidon/terraform-provider-ct/pull/66)) 80 | 81 | ## v0.6.0 82 | 83 | * Add Fedora CoreOS Config v1.1.0 support ([#63](https://github.com/poseidon/terraform-provider-ct/pull/63)) 84 | * Accept FCC v1.1.0 and output Ignition v3.1.0 85 | * Continue to support FCC v1.0.0 and output Ignition v3.0.0 86 | * Support merging FCC snippets into v1.0.0 or v1.1.0 FCC content 87 | * Note: Version skew among snippets and content is not supported 88 | * Change Container Linux Config to render Ignition v2.3.0 ([#60](https://github.com/poseidon/terraform-provider-ct/pull/60)) 89 | * Add zip archive format with signed checksum 90 | 91 | ## v0.5.1 92 | 93 | * Allow empty string snippets ([#61](https://github.com/poseidon/terraform-provider-ct/pull/61)) 94 | 95 | ## v0.5.0 96 | 97 | * Add support for Fedora CoreOS `snippets` ([#58](https://github.com/poseidon/terraform-provider-ct/pull/58)) 98 | * Migrate to the Terraform Plugin SDK ([#56](https://github.com/poseidon/terraform-provider-ct/pull/56)) 99 | * Upgrade fcct from v0.1.0 to v0.4.0 ([#57](https://github.com/poseidon/terraform-provider-ct/pull/57)) 100 | 101 | ## v0.4.0 102 | 103 | * Support Fedora CoreOS Config `content` ([#52](https://github.com/poseidon/terraform-provider-ct/pull/52)) 104 | * Render Container Linux Config `content` in Ignition v2.2 format 105 | * Render Fedora CoreOS `content` in Ignition v3.x format (determined by their own [version](https://github.com/coreos/fcct/blob/master/docs/configuration-v1_0.md)) 106 | * Add `strict` field for strict validation (defaults to false) ([#53](https://github.com/poseidon/terraform-provider-ct/pull/53)) 107 | 108 | ## v0.3.2 109 | 110 | * Add compatibility with Terraform v0.12. Retain v0.11 compatibility ([#37](https://github.com/poseidon/terraform-provider-ct/pull/37)) 111 | 112 | ## v0.3.1 113 | 114 | * Document usage with the Terraform [3rd-party plugin](https://www.terraform.io/docs/configuration/providers.html#third-party-plugins) directory ([#35](https://github.com/poseidon/terraform-provider-ct/pull/35)) 115 | * Provide pre-compiled binaries from Go v1.11.5 116 | * Add windows release binaries 117 | 118 | ## v0.3.0 119 | 120 | * Render Ignition Configs at Ingition v2.2.0 121 | * Add `snippets` field for appending Container Linux Configs to `content` ([#22](https://github.com/poseidon/terraform-provider-ct/pull/22)) 122 | * Update `ct` to v0.8.0 123 | 124 | ## v0.2.1 125 | 126 | * Add `snippets` field for appending Container Linux Configs to `content` ([#22](https://github.com/poseidon/terraform-provider-ct/pull/22)) 127 | 128 | ## v0.2.0 129 | 130 | * Render Ignition Configs at Ignition v2.0.0 131 | * Add `platform` field to the `ct_config` data source 132 | * Add support for platform [dynamic templating](https://coreos.com/os/docs/latest/dynamic-data.html) 133 | * Update to support Terraform v0.9.2+ 134 | * Update Container Linux `ct` to v0.3.1 135 | 136 | ## v0.1.0 137 | 138 | Initial release as `tf-provider-fuze`. 139 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Developer Certificate of Origin 4 | 5 | By contributing, you agree to the Linux Foundation's Developer Certificate of Origin ([DCO](DCO)). The DCO is a statement that you, the contributor, have the legal right to make your contribution and understand the contribution will be distributed as part of this project. 6 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 660 York Street, Suite 102, 6 | San Francisco, CA 94110 USA 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | 12 | Developer's Certificate of Origin 1.1 13 | 14 | By making a contribution to this project, I certify that: 15 | 16 | (a) The contribution was created in whole or in part by me and I 17 | have the right to submit it under the open source license 18 | indicated in the file; or 19 | 20 | (b) The contribution is based upon previous work that, to the best 21 | of my knowledge, is covered under an appropriate open source 22 | license and I have the right under that license to submit that 23 | work with modifications, whether created in whole or in part 24 | by me, under the same open source license (unless I am 25 | permitted to submit under a different license), as indicated 26 | in the file; or 27 | 28 | (c) The contribution was provided directly to me by some other 29 | person who certified (a), (b) or (c) and I have not modified 30 | it. 31 | 32 | (d) I understand and agree that this project and the contribution 33 | are public and that a record of the contribution (including all 34 | personal information I submit with it, including my sign-off) is 35 | maintained indefinitely and may be redistributed consistent with 36 | this project or the open source license(s) involved. 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export CGO_ENABLED:=0 2 | 3 | VERSION=$(shell git describe --tags --match=v* --always) 4 | SEMVER=$(shell git describe --tags --match=v* --always | cut -c 2-) 5 | 6 | .PHONY: all 7 | all: build test vet fmt 8 | 9 | .PHONY: build 10 | build: 11 | @go build -o $@ github.com/poseidon/terraform-provider-ct 12 | 13 | .PHONY: test 14 | test: 15 | @go test ./... -cover 16 | 17 | .PHONY: vet 18 | vet: 19 | @go vet -all ./... 20 | 21 | .PHONY: fmt 22 | fmt: 23 | @test -z $$(go fmt ./...) 24 | 25 | .PHONY: lint 26 | lint: 27 | @golangci-lint run ./... 28 | 29 | .PHONY: clean 30 | clean: 31 | @rm -rf bin 32 | @rm -rf _output 33 | 34 | .PHONY: release 35 | release: \ 36 | clean \ 37 | _output/plugin-linux-amd64.zip \ 38 | _output/plugin-linux-arm64.zip \ 39 | _output/plugin-darwin-amd64.zip \ 40 | _output/plugin-darwin-arm64.zip \ 41 | _output/plugin-windows-amd64.zip 42 | 43 | _output/plugin-%.zip: NAME=terraform-provider-ct_$(SEMVER)_$(subst -,_,$*) 44 | _output/plugin-%.zip: DEST=_output/$(NAME) 45 | _output/plugin-%.zip: LOCAL=$(HOME)/.terraform.d/plugins/terraform.localhost/poseidon/ct/$(SEMVER) 46 | _output/plugin-%.zip: _output/%/terraform-provider-ct 47 | @mkdir -p $(DEST) 48 | @cp _output/$*/terraform-provider-ct $(DEST)/terraform-provider-ct_$(VERSION) 49 | @zip -j $(DEST).zip $(DEST)/terraform-provider-ct_$(VERSION) 50 | @mkdir -p $(LOCAL)/$(subst -,_,$*) 51 | @cp _output/$*/terraform-provider-ct $(LOCAL)/$(subst -,_,$*)/terraform-provider-ct_$(VERSION) 52 | 53 | _output/linux-amd64/terraform-provider-ct: GOARGS = GOOS=linux GOARCH=amd64 54 | _output/linux-arm64/terraform-provider-ct: GOARGS = GOOS=linux GOARCH=arm64 55 | _output/darwin-amd64/terraform-provider-ct: GOARGS = GOOS=darwin GOARCH=amd64 56 | _output/darwin-arm64/terraform-provider-ct: GOARGS = GOOS=darwin GOARCH=arm64 57 | _output/windows-amd64/terraform-provider-ct: GOARGS = GOOS=windows GOARCH=amd64 58 | _output/%/terraform-provider-ct: 59 | $(GOARGS) go build -o $@ github.com/poseidon/terraform-provider-ct 60 | 61 | release-sign: 62 | cd _output; sha256sum *.zip > terraform-provider-ct_$(SEMVER)_SHA256SUMS 63 | gpg --default-key 0x8F515AD1602065C8 --detach-sign _output/terraform-provider-ct_$(SEMVER)_SHA256SUMS 64 | 65 | release-verify: NAME=_output/terraform-provider-ct 66 | release-verify: 67 | gpg --verify $(NAME)_$(SEMVER)_SHA256SUMS.sig $(NAME)_$(SEMVER)_SHA256SUMS 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-provider-ct 2 | [![GoDoc](https://pkg.go.dev/badge/github.com/poseidon/terraform-provider-ct.svg)](https://pkg.go.dev/github.com/poseidon/terraform-provider-ct) 3 | [![Workflow](https://github.com/poseidon/terraform-provider-ct/actions/workflows/test.yaml/badge.svg)](https://github.com/poseidon/terraform-provider-ct/actions/workflows/test.yaml?query=branch%3Amain) 4 | ![Downloads](https://img.shields.io/github/downloads/poseidon/terraform-provider-ct/total) 5 | [![Sponsors](https://img.shields.io/github/sponsors/poseidon?logo=github)](https://github.com/sponsors/poseidon) 6 | [![Mastodon](https://img.shields.io/badge/follow-news-6364ff?logo=mastodon)](https://fosstodon.org/@poseidon) 7 | 8 | `terraform-provider-ct` allows Terraform to validate a [Butane config](https://coreos.github.io/butane/specs/) and transpile to an [Ignition config](https://coreos.github.io/ignition/) for machine consumption. 9 | 10 | ## Usage 11 | 12 | Configure the config transpiler provider (e.g. `providers.tf`). 13 | 14 | ```tf 15 | provider "ct" {} 16 | 17 | terraform { 18 | required_providers { 19 | ct = { 20 | source = "poseidon/ct" 21 | version = "0.13.0" 22 | } 23 | } 24 | } 25 | ``` 26 | 27 | Define a Butane config for Fedora CoreOS or Flatcar Linux: 28 | 29 | ```yaml 30 | variant: fcos 31 | version: 1.5.0 32 | passwd: 33 | users: 34 | - name: core 35 | ssh_authorized_keys: 36 | - ssh-key foo 37 | ``` 38 | 39 | ```yaml 40 | variant: flatcar 41 | version: 1.1.0 42 | passwd: 43 | users: 44 | - name: core 45 | ssh_authorized_keys: 46 | - ssh-key foo 47 | ``` 48 | 49 | Define a `ct_config` data source with strict validation. 50 | 51 | ```tf 52 | data "ct_config" "worker" { 53 | content = file("worker.yaml") 54 | strict = true 55 | pretty_print = false 56 | 57 | snippets = [ 58 | file("units.yaml"), 59 | file("storage.yaml"), 60 | ] 61 | } 62 | ``` 63 | 64 | Optionally, template the `content`. 65 | 66 | ```tf 67 | data "ct_config" "worker" { 68 | content = templatefile("worker.yaml", { 69 | ssh_authorized_key = "ssh-ed25519 AAAA...", 70 | }) 71 | strict = true 72 | } 73 | ``` 74 | 75 | Render the `ct_config` as Ignition for use by machine instances. 76 | 77 | ```tf 78 | resource "aws_instance" "worker" { 79 | user_data = data.ct_config.worker.rendered 80 | } 81 | ``` 82 | 83 | Run `terraform init` to ensure plugin version requirements are met. 84 | 85 | ``` 86 | $ terraform init 87 | ``` 88 | 89 | ## Requirements 90 | 91 | * Terraform v0.13+ [installed](https://www.terraform.io/downloads.html) 92 | 93 | ## Versions 94 | 95 | Butane configs are converted to the current (according to this provider) stable Ignition config and merged together. For example, `poseidon/ct` `v0.12.0` would convert a Butane Config with `variant: fcos` and `version: 1.2.0` to an Ignition config with version `v3.3.0`. This relies on Ignition's [forward compatibility](https://github.com/coreos/ignition/blob/main/config/v3_3/config.go#L61). 96 | 97 | | poseidon/ct | Butane variant | Butane version | Ignition verison | 98 | |-----------------------|----------------|----------------|------------------| 99 | | 0.13.x | fcos | 1.0.0, 1.1.0, 1.2.0, 1.3.0, 1.4.0, 1.5.0 | 3.4.0 | 100 | | 0.13.x | flatcar | 1.0.0, 1.1.0 | 3.4.0 | 101 | | 0.12.x | fcos | 1.0.0, 1.1.0, 1.2.0, 1.3.0, 1.4.0 | 3.3.0 | 102 | | 0.12.x | flatcar | 1.0.0 | 3.3.0 | 103 | 104 | Before `poseidon/ct` v0.12.0, `ct_config` content could be a Butane Config or a Container Linux Config (CLC). Before `poseidon/ct` v0.10.0, Butane configs contained a `version` that was associated with an Ignition format version. For example, a Butane config with `version: 1.0.0` would produce an Ignition config with version `3.0.0`. 105 | 106 | | terraform-provider-ct | CLC to Ignition | Butane to Ignition | 107 | |-----------------------|---------------------|--------------------| 108 | | 0.11.x | Renders 2.3.0 | Butane (1.0, 1.1, 1.2, 1.3, 1.4) -> Ignition 3.3 | 109 | | 0.10.x | Renders 2.3.0 | Butane (1.0, 1.1, 1.2, 1.3, 1.4) -> Ignition 3.3 | 110 | | 0.9.x | Renders 2.3.0 | Butane (1.0, 1.1, 1.2, 1.3, 1.4) -> Ignition (3.0, 3.1, 3.2, 3.2, 3.3) 111 | | 0.8.x | Renders 2.3.0 | Butane (1.0, 1.1, 1.2, 1.3) -> Ignition (3.0, 3.1, 3.2, 3.2) 112 | | 0.7.x | Renders 2.3.0 | Butane (1.0, 1.1, 1.2) -> Ignition (3.0, 3.1, 3.2) | 113 | | 0.6.x | Renders 2.3.0 | Butane (1.0, 1.1) -> Ignition (3.0, 3.1) | 114 | | 0.5.x | Renders 2.2.0 | Butane 1.0.0 -> Ignition 3.0.0 | 115 | | 0.4.x | Renders 2.2.0 | Butane 1.0.0 -> Ignition 3.0.0 | 116 | | 0.3.x | Renders 2.2.0 | NA | 117 | | 0.2.x | Renders 2.0.0 | NA | 118 | 119 | ## Development 120 | 121 | ### Binary 122 | 123 | To develop the provider plugin locally, build an executable with Go v1.18+. 124 | 125 | ``` 126 | make 127 | ``` 128 | -------------------------------------------------------------------------------- /docs/data-sources/ct_config.md: -------------------------------------------------------------------------------- 1 | # ct_config Data Source 2 | 3 | Validate a [Butane config](https://coreos.github.io/butane/specs/) and transpile it to an [Ignition config](https://coreos.github.io/ignition/) for machine consumption. 4 | 5 | ## Usage 6 | 7 | ```hcl 8 | data "ct_config" "worker" { 9 | content = file("worker.yaml") 10 | strict = true 11 | pretty_print = false 12 | 13 | snippets = [ 14 | file("units.yaml"), 15 | file("storage.yaml"), 16 | ] 17 | } 18 | 19 | resource "aws_instance" "worker" { 20 | user_data = data.ct_config.worker.rendered 21 | } 22 | ``` 23 | 24 | See the [Flatcar Container Linux](../../examples/flatcar-linux.tf) or [Fedora CoreOS](../../examples/fedora-coreos.tf) examples. 25 | 26 | ## Argument Reference 27 | 28 | * `content` - contents of a Butane Config that should be validated and transpiled to Ignition. 29 | * `strict` - strictly treat validation warnings as errors (default: false). 30 | * `pretty_print` - indent transpiled Ignition for visual prettiness (default: false) 31 | * `snippets` - list of Butane snippets to merge into the content. Content and snippet configs must have the same `version` and `variant`. 32 | 33 | ## Argument Attributes 34 | 35 | * `rendered` - transpiled Ignition configuration 36 | 37 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # config-transpiler Provider 2 | 3 | `terraform-provider-ct` allows Terraform to validate a [Butane config](https://coreos.github.io/butane/specs/) and transpile to an [Ignition config](https://coreos.github.io/ignition/) for machine consumption. 4 | 5 | ## Usage 6 | 7 | Configure the config transpiler provider (e.g. `providers.tf`). 8 | 9 | ```tf 10 | provider "ct" {} 11 | 12 | terraform { 13 | required_providers { 14 | ct = { 15 | source = "poseidon/ct" 16 | version = "0.13.0" 17 | } 18 | } 19 | } 20 | ``` 21 | 22 | Define a Butane config for Fedora CoreOS or Flatcar Linux: 23 | 24 | ```yaml 25 | variant: fcos 26 | version: 1.5.0 27 | passwd: 28 | users: 29 | - name: core 30 | ssh_authorized_keys: 31 | - ssh-key foo 32 | ``` 33 | 34 | ```yaml 35 | variant: flatcar 36 | version: 1.1.0 37 | passwd: 38 | users: 39 | - name: core 40 | ssh_authorized_keys: 41 | - ssh-key foo 42 | ``` 43 | 44 | Define a `ct_config` data source with strict validation. 45 | 46 | ```tf 47 | data "ct_config" "worker" { 48 | content = file("worker.yaml") 49 | strict = true 50 | pretty_print = false 51 | 52 | snippets = [ 53 | file("units.yaml"), 54 | file("storage.yaml"), 55 | ] 56 | } 57 | ``` 58 | 59 | Optionally, template the `content`. 60 | 61 | ```tf 62 | data "ct_config" "worker" { 63 | content = templatefile("worker.yaml", { 64 | ssh_authorized_key = "ssh-ed25519 AAAA...", 65 | }) 66 | strict = true 67 | } 68 | ``` 69 | 70 | Render the `ct_config` as Ignition for use by machine instances. 71 | 72 | ```tf 73 | resource "aws_instance" "worker" { 74 | user_data = data.ct_config.worker.rendered 75 | } 76 | ``` 77 | 78 | Run `terraform init` to ensure plugin version requirements are met. 79 | 80 | ``` 81 | $ terraform init 82 | ``` 83 | 84 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | .terraform 2 | *.tfstate* 3 | output 4 | -------------------------------------------------------------------------------- /examples/content/fcos-snippet.yaml: -------------------------------------------------------------------------------- 1 | variant: fcos 2 | version: 1.5.0 3 | storage: 4 | files: 5 | - path: /etc/zincati/config.d/90-disable-feature.toml 6 | contents: 7 | inline: | 8 | [updates] 9 | enabled = false 10 | 11 | -------------------------------------------------------------------------------- /examples/content/fcos.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | variant: fcos 3 | version: 1.5.0 4 | storage: 5 | filesystems: 6 | - path: / 7 | device: /dev/disk/by-label/ROOT 8 | format: ext4 9 | files: 10 | - path: /etc/motd 11 | mode: 0644 12 | contents: 13 | inline: | 14 | ${message} 15 | passwd: 16 | users: 17 | - name: core 18 | ssh_authorized_keys: 19 | - ssh-key foo 20 | -------------------------------------------------------------------------------- /examples/content/flatcar-snippet.yaml: -------------------------------------------------------------------------------- 1 | variant: flatcar 2 | version: 1.1.0 3 | storage: 4 | files: 5 | - path: "/etc/coreos/update.conf" 6 | mode: 0644 7 | contents: 8 | inline: | 9 | GROUP="alpha" 10 | SERVER="update.example.com/v1/update" 11 | -------------------------------------------------------------------------------- /examples/content/flatcar.yaml: -------------------------------------------------------------------------------- 1 | variant: flatcar 2 | version: 1.1.0 3 | storage: 4 | filesystems: 5 | - path: / 6 | device: "/dev/disk/by-label/ROOT" 7 | format: "ext4" 8 | files: 9 | - path: "/etc/motd" 10 | mode: 0644 11 | contents: 12 | inline: | 13 | ${message} 14 | passwd: 15 | users: 16 | - name: core 17 | ssh_authorized_keys: 18 | - ssh-key foo 19 | -------------------------------------------------------------------------------- /examples/fedora-coreos.tf: -------------------------------------------------------------------------------- 1 | # Butane Config for Fedora CoreOS 2 | data "ct_config" "fedora-coreos-config" { 3 | content = templatefile("${path.module}/content/fcos.yaml", { 4 | message = "Hello World!" 5 | }) 6 | strict = true 7 | pretty_print = true 8 | 9 | snippets = [ 10 | file("${path.module}/content/fcos-snippet.yaml"), 11 | ] 12 | } 13 | 14 | # Render as Ignition 15 | resource "local_file" "fedora-coreos" { 16 | content = data.ct_config.fedora-coreos-config.rendered 17 | filename = "${path.module}/output/fedora-coreos.ign" 18 | } 19 | -------------------------------------------------------------------------------- /examples/flatcar-linux.tf: -------------------------------------------------------------------------------- 1 | # Butane Config for Flatcar Linux 2 | data "ct_config" "flatcar-config" { 3 | content = templatefile("${path.module}/content/flatcar.yaml", { 4 | message = "Hello World!" 5 | }) 6 | strict = true 7 | pretty_print = true 8 | 9 | snippets = [ 10 | file("${path.module}/content/flatcar-snippet.yaml"), 11 | ] 12 | } 13 | 14 | # Render as Ignition 15 | resource "local_file" "flatcar" { 16 | content = data.ct_config.flatcar-config.rendered 17 | filename = "${path.module}/output/flatcar.ign" 18 | } 19 | -------------------------------------------------------------------------------- /examples/versions.tf: -------------------------------------------------------------------------------- 1 | 2 | terraform { 3 | required_version = ">= 0.13.0" 4 | required_providers { 5 | local = "~> 2.0" 6 | ct = { 7 | source = "poseidon/ct" 8 | version = "~> 0.13.0" 9 | #source = "terraform.localhost/poseidon/ct" 10 | #version = "0.12.0" 11 | } 12 | } 13 | } 14 | 15 | 16 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/poseidon/terraform-provider-ct 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.24.3 6 | 7 | require ( 8 | github.com/coreos/butane v0.24.0 9 | github.com/coreos/ignition/v2 v2.21.0 10 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 11 | ) 12 | 13 | require ( 14 | github.com/ProtonMail/go-crypto v1.1.6 // indirect 15 | github.com/agext/levenshtein v1.2.2 // indirect 16 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 17 | github.com/aws/aws-sdk-go v1.55.6 // indirect 18 | github.com/clarketm/json v1.17.1 // indirect 19 | github.com/cloudflare/circl v1.6.0 // indirect 20 | github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb // indirect 21 | github.com/coreos/go-semver v0.3.1 // indirect 22 | github.com/coreos/go-systemd/v22 v22.5.0 // indirect 23 | github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 // indirect 24 | github.com/davecgh/go-spew v1.1.1 // indirect 25 | github.com/fatih/color v1.16.0 // indirect 26 | github.com/golang/protobuf v1.5.4 // indirect 27 | github.com/google/go-cmp v0.7.0 // indirect 28 | github.com/hashicorp/errwrap v1.0.0 // indirect 29 | github.com/hashicorp/go-checkpoint v0.5.0 // indirect 30 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 31 | github.com/hashicorp/go-cty v1.5.0 // indirect 32 | github.com/hashicorp/go-hclog v1.6.3 // indirect 33 | github.com/hashicorp/go-multierror v1.1.1 // indirect 34 | github.com/hashicorp/go-plugin v1.6.3 // indirect 35 | github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 36 | github.com/hashicorp/go-uuid v1.0.3 // indirect 37 | github.com/hashicorp/go-version v1.7.0 // indirect 38 | github.com/hashicorp/hc-install v0.9.2 // indirect 39 | github.com/hashicorp/hcl/v2 v2.23.0 // indirect 40 | github.com/hashicorp/logutils v1.0.0 // indirect 41 | github.com/hashicorp/terraform-exec v0.23.0 // indirect 42 | github.com/hashicorp/terraform-json v0.25.0 // indirect 43 | github.com/hashicorp/terraform-plugin-go v0.27.0 // indirect 44 | github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect 45 | github.com/hashicorp/terraform-registry-address v0.2.5 // indirect 46 | github.com/hashicorp/terraform-svchost v0.1.1 // indirect 47 | github.com/hashicorp/yamux v0.1.1 // indirect 48 | github.com/mattn/go-colorable v0.1.13 // indirect 49 | github.com/mattn/go-isatty v0.0.20 // indirect 50 | github.com/mitchellh/copystructure v1.2.0 // indirect 51 | github.com/mitchellh/go-testing-interface v1.14.1 // indirect 52 | github.com/mitchellh/go-wordwrap v1.0.0 // indirect 53 | github.com/mitchellh/mapstructure v1.5.0 // indirect 54 | github.com/mitchellh/reflectwalk v1.0.2 // indirect 55 | github.com/oklog/run v1.0.0 // indirect 56 | github.com/pmezard/go-difflib v1.0.0 // indirect 57 | github.com/rogpeppe/go-internal v1.10.0 // indirect 58 | github.com/stretchr/testify v1.10.0 // indirect 59 | github.com/vincent-petithory/dataurl v1.0.0 // indirect 60 | github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect 61 | github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect 62 | github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect 63 | github.com/zclconf/go-cty v1.16.2 // indirect 64 | golang.org/x/crypto v0.38.0 // indirect 65 | golang.org/x/mod v0.24.0 // indirect 66 | golang.org/x/net v0.39.0 // indirect 67 | golang.org/x/sync v0.14.0 // indirect 68 | golang.org/x/sys v0.33.0 // indirect 69 | golang.org/x/text v0.25.0 // indirect 70 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect 71 | google.golang.org/appengine v1.6.8 // indirect 72 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e // indirect 73 | google.golang.org/grpc v1.72.1 // indirect 74 | google.golang.org/protobuf v1.36.6 // indirect 75 | gopkg.in/yaml.v3 v3.0.1 // indirect 76 | ) 77 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= 2 | dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 3 | github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= 4 | github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= 5 | github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= 6 | github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= 7 | github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= 8 | github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 9 | github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= 10 | github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= 11 | github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= 12 | github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= 13 | github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= 14 | github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= 15 | github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= 16 | github.com/clarketm/json v1.17.1 h1:U1IxjqJkJ7bRK4L6dyphmoO840P6bdhPdbbLySourqI= 17 | github.com/clarketm/json v1.17.1/go.mod h1:ynr2LRfb0fQU34l07csRNBTcivjySLLiY1YzQqKVfdo= 18 | github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= 19 | github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= 20 | github.com/coreos/butane v0.24.0 h1:sput//CnGz1ZUNT3TaSpbgjAjlefGC+/Ikiiwl5wO9Q= 21 | github.com/coreos/butane v0.24.0/go.mod h1:mLu58/AgW6lC116Rf/9N5b+ixj/zdhRtABBZjADHWFo= 22 | github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb h1:rmqyI19j3Z/74bIRhuC59RB442rXUazKNueVpfJPxg4= 23 | github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb/go.mod h1:rcFZM3uxVvdyNmsAV2jopgPD1cs5SPWJWU5dOz2LUnw= 24 | github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= 25 | github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= 26 | github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= 27 | github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 28 | github.com/coreos/ignition/v2 v2.21.0 h1:2q44zldXRuBXOJl/6Z6xBshZzi2muQuXRZBGGpvNbsk= 29 | github.com/coreos/ignition/v2 v2.21.0/go.mod h1:axhFZ3jEgXBjKtKp0rSMv2li0Rt43rasp5hS9uyYjco= 30 | github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 h1:uSmlDgJGbUB0bwQBcZomBTottKwEDF5fF8UjSwKSzWM= 31 | github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687/go.mod h1:Salmysdw7DAVuobBW/LwsKKgpyCPHUhjyJoMJD+ZJiI= 32 | github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= 33 | github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= 34 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 35 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 36 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 37 | github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 38 | github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 39 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 40 | github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= 41 | github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 42 | github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= 43 | github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= 44 | github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= 45 | github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= 46 | github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60= 47 | github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k= 48 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 49 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 50 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 51 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 52 | github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= 53 | github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 54 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 55 | github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= 56 | github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= 57 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 58 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 59 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 60 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 61 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 62 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 63 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 64 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 65 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 66 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 67 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 68 | github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= 69 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 70 | github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= 71 | github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= 72 | github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 73 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 74 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 75 | github.com/hashicorp/go-cty v1.5.0 h1:EkQ/v+dDNUqnuVpmS5fPqyY71NXVgT5gf32+57xY8g0= 76 | github.com/hashicorp/go-cty v1.5.0/go.mod h1:lFUCG5kd8exDobgSfyj4ONE/dc822kiYMguVKdHGMLM= 77 | github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= 78 | github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= 79 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= 80 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 81 | github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= 82 | github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= 83 | github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= 84 | github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= 85 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 86 | github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= 87 | github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 88 | github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= 89 | github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 90 | github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+OmtO24= 91 | github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I= 92 | github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos= 93 | github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= 94 | github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= 95 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 96 | github.com/hashicorp/terraform-exec v0.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEsiXmzATMW/I= 97 | github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY= 98 | github.com/hashicorp/terraform-json v0.25.0 h1:rmNqc/CIfcWawGiwXmRuiXJKEiJu1ntGoxseG1hLhoQ= 99 | github.com/hashicorp/terraform-json v0.25.0/go.mod h1:sMKS8fiRDX4rVlR6EJUMudg1WcanxCMoWwTLkgZP/vc= 100 | github.com/hashicorp/terraform-plugin-go v0.27.0 h1:ujykws/fWIdsi6oTUT5Or4ukvEan4aN9lY+LOxVP8EE= 101 | github.com/hashicorp/terraform-plugin-go v0.27.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o= 102 | github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= 103 | github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= 104 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 h1:NFPMacTrY/IdcIcnUB+7hsore1ZaRWU9cnB6jFoBnIM= 105 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0/go.mod h1:QYmYnLfsosrxjCnGY1p9c7Zj6n9thnEE+7RObeYs3fA= 106 | github.com/hashicorp/terraform-registry-address v0.2.5 h1:2GTftHqmUhVOeuu9CW3kwDkRe4pcBDq0uuK5VJngU1M= 107 | github.com/hashicorp/terraform-registry-address v0.2.5/go.mod h1:PpzXWINwB5kuVS5CA7m1+eO2f1jKb5ZDIxrOPfpnGkg= 108 | github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= 109 | github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= 110 | github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= 111 | github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= 112 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= 113 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= 114 | github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= 115 | github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= 116 | github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= 117 | github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 118 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 119 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 120 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 121 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 122 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 123 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 124 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 125 | github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 126 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 127 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 128 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 129 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 130 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 131 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 132 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 133 | github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= 134 | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= 135 | github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= 136 | github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= 137 | github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= 138 | github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 139 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 140 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 141 | github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= 142 | github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 143 | github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= 144 | github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 145 | github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= 146 | github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= 147 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 148 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 149 | github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= 150 | github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= 151 | github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= 152 | github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= 153 | github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= 154 | github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= 155 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 156 | github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 157 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 158 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 159 | github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= 160 | github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= 161 | github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 162 | github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= 163 | github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 164 | github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= 165 | github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= 166 | github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= 167 | github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= 168 | github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= 169 | github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= 170 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 171 | github.com/zclconf/go-cty v1.16.2 h1:LAJSwc3v81IRBZyUVQDUdZ7hs3SYs9jv0eZJDWHD/70= 172 | github.com/zclconf/go-cty v1.16.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= 173 | github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= 174 | github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= 175 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 176 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 177 | go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= 178 | go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= 179 | go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= 180 | go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= 181 | go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= 182 | go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= 183 | go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= 184 | go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= 185 | go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= 186 | go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= 187 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 188 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 189 | golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= 190 | golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= 191 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 192 | golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= 193 | golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= 194 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 195 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 196 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 197 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 198 | golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= 199 | golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= 200 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 201 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 202 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 203 | golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= 204 | golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 205 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 206 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 207 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 208 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 209 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 210 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 211 | golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 212 | golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 213 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 214 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 215 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 216 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 217 | golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= 218 | golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 219 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 220 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 221 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 222 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 223 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 224 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 225 | golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= 226 | golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= 227 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 228 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 229 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 230 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= 231 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 232 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 233 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 234 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 235 | google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= 236 | google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= 237 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e h1:YA5lmSs3zc/5w+xsRcHqpETkaYyK63ivEPzNTcUUlSA= 238 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= 239 | google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= 240 | google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= 241 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 242 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 243 | google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= 244 | google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 245 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 246 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 247 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 248 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 249 | gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= 250 | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 251 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 252 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 253 | -------------------------------------------------------------------------------- /internal/data_config.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | 8 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 9 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 10 | 11 | butane "github.com/coreos/butane/config" 12 | "github.com/coreos/butane/config/common" 13 | ignition "github.com/coreos/ignition/v2/config/v3_4" 14 | ) 15 | 16 | func DatasourceConfig() *schema.Resource { 17 | return &schema.Resource{ 18 | ReadContext: datasourceConfigRead, 19 | 20 | Schema: map[string]*schema.Schema{ 21 | "content": { 22 | Type: schema.TypeString, 23 | Required: true, 24 | }, 25 | "snippets": { 26 | Type: schema.TypeList, 27 | Elem: &schema.Schema{ 28 | Type: schema.TypeString, 29 | }, 30 | Optional: true, 31 | ForceNew: true, 32 | }, 33 | "files_dir": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | Default: nil, 37 | Description: "allow embedding local files relative to this directory", 38 | }, 39 | "pretty_print": { 40 | Type: schema.TypeBool, 41 | Optional: true, 42 | Default: false, 43 | }, 44 | "strict": { 45 | Type: schema.TypeBool, 46 | Optional: true, 47 | Default: false, 48 | }, 49 | "rendered": { 50 | Type: schema.TypeString, 51 | Computed: true, 52 | Description: "rendered ignition configuration", 53 | }, 54 | }, 55 | } 56 | } 57 | 58 | func datasourceConfigRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 59 | var diags diag.Diagnostics 60 | 61 | rendered, err := renderConfig(d) 62 | if err != nil { 63 | return diag.FromErr(err) 64 | } 65 | 66 | if err := d.Set("rendered", rendered); err != nil { 67 | return diag.FromErr(err) 68 | } 69 | d.SetId(hashcode(rendered)) 70 | return diags 71 | } 72 | 73 | // Render a Fedora CoreOS Config or Container Linux Config as Ignition JSON. 74 | func renderConfig(d *schema.ResourceData) (string, error) { 75 | // unchecked assertions seem to be the norm in Terraform :S 76 | content := d.Get("content").(string) 77 | pretty := d.Get("pretty_print").(bool) 78 | filesDir := d.Get("files_dir").(string) 79 | strict := d.Get("strict").(bool) 80 | snippetsIface := d.Get("snippets").([]interface{}) 81 | 82 | snippets := make([]string, len(snippetsIface)) 83 | for i, v := range snippetsIface { 84 | if v != nil { 85 | snippets[i] = v.(string) 86 | } 87 | } 88 | 89 | // Butane Config 90 | ign, err := butaneToIgnition([]byte(content), pretty, filesDir, strict, snippets) 91 | return string(ign), err 92 | } 93 | 94 | // Translate Fedora CoreOS config to Ignition v3.X.Y 95 | func butaneToIgnition(data []byte, pretty bool, filesDir string, strict bool, snippets []string) ([]byte, error) { 96 | ignBytes, report, err := butane.TranslateBytes(data, common.TranslateBytesOptions{ 97 | TranslateOptions: common.TranslateOptions{ 98 | FilesDir: filesDir, 99 | }, 100 | Pretty: pretty, 101 | }) 102 | // ErrNoVariant indicates data is a CLC, not an FCC 103 | if err != nil { 104 | return nil, err 105 | } 106 | if strict && len(report.Entries) > 0 { 107 | return nil, fmt.Errorf("strict parsing error: %v", report.String()) 108 | } 109 | 110 | // merge FCC snippets into main Ignition config 111 | return mergeFCCSnippets(ignBytes, pretty, filesDir, strict, snippets) 112 | } 113 | 114 | // Parse Fedora CoreOS Ignition and Butane snippets into Ignition Config. 115 | func mergeFCCSnippets(ignBytes []byte, pretty bool, filesDir string, strict bool, snippets []string) ([]byte, error) { 116 | ign, _, err := ignition.ParseCompatibleVersion(ignBytes) 117 | if err != nil { 118 | return nil, fmt.Errorf("%v", err) 119 | } 120 | 121 | for _, snippet := range snippets { 122 | ignextBytes, report, err := butane.TranslateBytes([]byte(snippet), common.TranslateBytesOptions{ 123 | TranslateOptions: common.TranslateOptions{ 124 | FilesDir: filesDir, 125 | }, 126 | Pretty: pretty, 127 | }) 128 | if err != nil { 129 | // For FCC, require snippets be FCCs (don't fall-through to CLC) 130 | if err == common.ErrNoVariant { 131 | return nil, fmt.Errorf("Butane snippets require `variant`: %v", err) 132 | } 133 | return nil, fmt.Errorf("Butane translate error: %v\n%s", err, report.String()) 134 | } 135 | if strict && len(report.Entries) > 0 { 136 | return nil, fmt.Errorf("strict parsing error: %v", report.String()) 137 | } 138 | 139 | ignext, _, err := ignition.ParseCompatibleVersion(ignextBytes) 140 | if err != nil { 141 | return nil, fmt.Errorf("snippet parse error: %v, expect v1.4.0", err) 142 | } 143 | ign = ignition.Merge(ign, ignext) 144 | } 145 | 146 | return marshalJSON(ign, pretty) 147 | } 148 | 149 | func marshalJSON(v interface{}, pretty bool) ([]byte, error) { 150 | if pretty { 151 | return json.MarshalIndent(v, "", " ") 152 | } 153 | return json.Marshal(v) 154 | } 155 | -------------------------------------------------------------------------------- /internal/data_config_fcos_test.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "regexp" 5 | "testing" 6 | 7 | r "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 8 | ) 9 | 10 | // Fedora CoreOS variant, v1.5.0 11 | 12 | const fedoraCoreOSV15Resource = ` 13 | data "ct_config" "fedora-coreos" { 14 | pretty_print = true 15 | strict = true 16 | content = <= 0 { 19 | return strconv.Itoa(v) 20 | } 21 | if -v >= 0 { 22 | return strconv.Itoa(-v) 23 | } 24 | // v == MinInt 25 | return "0" 26 | } 27 | -------------------------------------------------------------------------------- /internal/provider.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 5 | ) 6 | 7 | // Provider returns a config transpiler Provider. 8 | func Provider() *schema.Provider { 9 | return &schema.Provider{ 10 | DataSourcesMap: map[string]*schema.Resource{ 11 | "ct_config": DatasourceConfig(), 12 | }, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /internal/provider_test.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 7 | ) 8 | 9 | var testProviders = map[string]*schema.Provider{ 10 | "ct": Provider(), 11 | } 12 | 13 | func TestProvider(t *testing.T) { 14 | if err := Provider().InternalValidate(); err != nil { 15 | t.Fatalf("err: %s", err) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" 5 | 6 | "github.com/poseidon/terraform-provider-ct/internal" 7 | ) 8 | 9 | func main() { 10 | plugin.Serve(&plugin.ServeOpts{ 11 | ProviderFunc: internal.Provider, 12 | }) 13 | } 14 | --------------------------------------------------------------------------------