├── .conform.yaml
├── .github
├── renovate.json
└── workflows
│ ├── acceptance-tests.yaml
│ ├── pull-request.yaml
│ ├── release.yml
│ └── slack-notify.yaml
├── .gitignore
├── .golangci.yml
├── .goreleaser.yml
├── .vscode
└── launch.json
├── CHANGELOG.md
├── LICENSE
├── Makefile
├── README.md
├── docs
├── data-sources
│ ├── client_configuration.md
│ ├── cluster_health.md
│ ├── cluster_kubeconfig.md
│ ├── image_factory_extensions_versions.md
│ ├── image_factory_overlays_versions.md
│ ├── image_factory_urls.md
│ ├── image_factory_versions.md
│ ├── machine_configuration.md
│ └── machine_disks.md
├── guides
│ └── version-0.2-upgrade.html.md
├── index.md
└── resources
│ ├── cluster_kubeconfig.md
│ ├── image_factory_schematic.md
│ ├── machine_bootstrap.md
│ ├── machine_configuration_apply.md
│ └── machine_secrets.md
├── examples
├── README.md
├── data-sources
│ ├── talos_client_configuration
│ │ └── data-source.tf
│ ├── talos_cluster_kubeconfig
│ │ └── data-source.tf
│ ├── talos_image_factory_extensions_versions
│ │ └── data-source.tf
│ ├── talos_image_factory_overlays_versions
│ │ └── data-source.tf
│ ├── talos_image_factory_urls
│ │ └── data-source.tf
│ ├── talos_image_factory_versions
│ │ └── data-source.tf
│ ├── talos_machine_configuration
│ │ └── data-source.tf
│ └── talos_machine_disks
│ │ └── data-source.tf
└── resources
│ ├── talos_cluster_kubeconfig
│ └── resource.tf
│ ├── talos_image_factory_schematic
│ └── resource.tf
│ ├── talos_machine_bootstrap
│ ├── import.sh
│ └── resource.tf
│ ├── talos_machine_configuration_apply
│ └── resource.tf
│ └── talos_machine_secrets
│ ├── import.sh
│ └── resource.tf
├── go.mod
├── go.sum
├── hack
├── release.sh
└── release.toml
├── main.go
├── pkg
└── talos
│ ├── internal
│ └── gen
│ │ └── diskspec.go
│ ├── provider.go
│ ├── provider_test.go
│ ├── talos_client_configuration_data_source.go
│ ├── talos_client_configuration_data_source_test.go
│ ├── talos_cluster_health_data_source.go
│ ├── talos_cluster_health_data_source_test.go
│ ├── talos_cluster_kubeconfig_data_source.go
│ ├── talos_cluster_kubeconfig_resource.go
│ ├── talos_cluster_kubeconfig_resource_test.go
│ ├── talos_image_factory_extensions_versions_data_source.go
│ ├── talos_image_factory_extensions_versions_data_source_test.go
│ ├── talos_image_factory_overlays_versions_data_source.go
│ ├── talos_image_factory_overlays_versions_data_source_test.go
│ ├── talos_image_factory_schematic_resource.go
│ ├── talos_image_factory_schematic_resource_test.go
│ ├── talos_image_factory_urls_data_source.go
│ ├── talos_image_factory_urls_data_source_test.go
│ ├── talos_image_factory_versions_data_source.go
│ ├── talos_image_factory_versions_data_source_test.go
│ ├── talos_machine_bootstrap_resource.go
│ ├── talos_machine_bootstrap_resource_test.go
│ ├── talos_machine_configuration_apply_resource.go
│ ├── talos_machine_configuration_apply_resource_test.go
│ ├── talos_machine_configuration_data_source.go
│ ├── talos_machine_configuration_data_source_test.go
│ ├── talos_machine_disks_data_source.go
│ ├── talos_machine_disks_data_source_test.go
│ ├── talos_machine_disks_data_source_types.go
│ ├── talos_machine_secrets_resource.go
│ ├── talos_machine_secrets_resource_test.go
│ ├── testdata
│ ├── patch-invalid.yaml
│ ├── patch-json6502.json
│ ├── patch-strategic.yaml
│ ├── secrets.yaml
│ └── secretsv1.2.yaml
│ └── util.go
├── templates
├── data-sources
│ ├── machine_configuration.md.tmpl
│ └── machine_disks.md.tmpl
├── guides
│ └── version-0.2-upgrade.html.md
├── index.md.tmpl
└── resources.md.tmpl
├── terraform-registry-manifest.json
└── tools
└── tools.go
/.conform.yaml:
--------------------------------------------------------------------------------
1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
2 | #
3 | # Generated on 2022-03-23T19:45:28Z by kres latest.
4 |
5 | ---
6 | policies:
7 | - type: commit
8 | spec:
9 | dco: true
10 | gpg:
11 | required: true
12 | identity:
13 | gitHubOrganization: siderolabs
14 | spellcheck:
15 | locale: US
16 | maximumOfOneCommit: true
17 | header:
18 | length: 89
19 | imperative: true
20 | case: lower
21 | invalidLastCharacters: .
22 | body:
23 | required: true
24 | conventional:
25 | types: ["chore","docs","perf","refactor","style","test","release"]
26 | scopes: [".*"]
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | ":semanticCommitScopeDisabled",
5 | "schedule:earlyMondays"
6 | ],
7 | "packageRules": [
8 | {
9 | "matchDatasources": [
10 | "go",
11 | "golang-version"
12 | ],
13 | "groupName": "go packages",
14 | "matchPackageNames": [
15 | "*"
16 | ]
17 | }
18 | ],
19 | "dependencyDashboard": true
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/acceptance-tests.yaml:
--------------------------------------------------------------------------------
1 | name: acceptance-tests
2 | concurrency:
3 | group: ${{ github.head_ref || github.run_id }}
4 | cancel-in-progress: true
5 | on:
6 | pull_request:
7 | paths:
8 | - 'go.mod'
9 | - 'go.sum'
10 | - '**.go'
11 | jobs:
12 | acc-tests:
13 | if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, 'dependabot/'))
14 | runs-on:
15 | - self-hosted
16 | - generic
17 | env:
18 | GOTOOLCHAIN: local
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v4
22 | - name: Set up Go
23 | uses: actions/setup-go@v5
24 | with:
25 | go-version-file: 'go.mod'
26 | cache: true
27 | - name: Set up Terraform
28 | uses: hashicorp/setup-terraform@v3
29 | with:
30 | terraform_wrapper: false
31 | - name: Set up libvirt
32 | env:
33 | LIBVIRT_DEFAULT_URI: qemu:///system
34 | run: |
35 | sudo apt-get update
36 | sudo apt-get install -y \
37 | bridge-utils \
38 | dnsmasq-base \
39 | libvirt-daemon-system \
40 | qemu-kvm \
41 | qemu-utils \
42 | qemu-block-extra \
43 | ovmf
44 |
45 | sudo ln -s OVMF_VARS_4M.fd /usr/share/OVMF/OVMF_VARS.fd
46 | sudo ln -s OVMF_CODE_4M.fd /usr/share/OVMF/OVMF_CODE.fd
47 |
48 | sudo virtlockd -d
49 | sudo virtlogd -d
50 | sudo libvirtd -d
51 | echo -e "\ndefault\n\n/pool-default\n\n" > pool.xml
52 | sudo mkdir /pool-default
53 | sudo chmod a+rwx /pool-default
54 | sudo virsh pool-define pool.xml
55 | sudo virsh pool-start default
56 | echo 'security_driver = "none"' | sudo tee --append /etc/libvirt/qemu.conf
57 | cat < net.xml
58 |
59 | default
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | EOF
70 | sudo virsh net-destroy default
71 | sudo virsh net-undefine default
72 | sudo virsh net-create net.xml
73 | - name: acceptance-test
74 | env:
75 | TERRAFORM_LIBVIRT_TEST_DOMAIN_TYPE: qemu
76 | LIBVIRT_DEFAULT_URI: qemu:///system
77 | CI: "true"
78 | run: |
79 | make testacc
80 |
--------------------------------------------------------------------------------
/.github/workflows/pull-request.yaml:
--------------------------------------------------------------------------------
1 | name: check-dirty
2 | on:
3 | pull_request:
4 | jobs:
5 | check-dirty:
6 | if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, 'dependabot/'))
7 | runs-on:
8 | - self-hosted
9 | - generic
10 | env:
11 | GOTOOLCHAIN: local
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v4
15 | - name: Set up Go
16 | uses: actions/setup-go@v5
17 | with:
18 | go-version-file: 'go.mod'
19 | cache: true
20 | - name: Set up Terraform
21 | uses: hashicorp/setup-terraform@v3
22 | with:
23 | terraform_wrapper: false
24 | - name: dirty-check
25 | run: |
26 | make check-dirty
27 | - name: golangci-lint
28 | uses: golangci/golangci-lint-action@v8
29 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | # This GitHub action can publish assets for release when a tag is created.
2 | # Currently its setup to run on any tag that matches the pattern "v*" (ie. v0.1.0).
3 | #
4 | # This uses an action (hashicorp/ghaction-import-gpg) that assumes you set your
5 | # private key in the `GPG_PRIVATE_KEY` secret and passphrase in the `PASSPHRASE`
6 | # secret. If you would rather own your own GPG handling, please fork this action
7 | # or use an alternative one for key handling.
8 | #
9 | # You will need to pass the `--batch` flag to `gpg` in your signing step
10 | # in `goreleaser` to indicate this is being used in a non-interactive mode.
11 | #
12 | name: release
13 | on:
14 | push:
15 | tags:
16 | - 'v*'
17 | permissions:
18 | contents: write
19 | jobs:
20 | goreleaser:
21 | runs-on:
22 | - self-hosted
23 | - generic
24 | steps:
25 | - name: Checkout
26 | uses: actions/checkout@v4
27 | - name: Unshallow
28 | run: git fetch --prune --unshallow
29 | - name: Set up Go
30 | uses: actions/setup-go@v5
31 | with:
32 | go-version-file: 'go.mod'
33 | cache: true
34 | - name: Import GPG key
35 | uses: crazy-max/ghaction-import-gpg@v6
36 | id: import_gpg
37 | with:
38 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
39 | passphrase: ${{ secrets.PASSPHRASE }}
40 | - name: release-notes
41 | run: make release-notes
42 | - name: Run GoReleaser
43 | uses: goreleaser/goreleaser-action@v6
44 | with:
45 | version: latest
46 | args: release --clean --release-notes=_out/RELEASE_NOTES.md
47 | env:
48 | GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
49 | # GitHub sets this automatically
50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51 |
--------------------------------------------------------------------------------
/.github/workflows/slack-notify.yaml:
--------------------------------------------------------------------------------
1 | name: slack-notify
2 | "on":
3 | workflow_run:
4 | workflows:
5 | - check-dirty
6 | - acceptance-tests
7 | - release
8 | types:
9 | - completed
10 | jobs:
11 | slack-notify:
12 | runs-on:
13 | - self-hosted
14 | - generic
15 | if: github.event.workflow_run.conclusion != 'skipped'
16 | steps:
17 | - name: Get PR number
18 | id: get-pr-number
19 | if: github.event.workflow_run.event == 'pull_request'
20 | env:
21 | GH_TOKEN: ${{ github.token }}
22 | run: |
23 | echo pull_request_number=$(gh pr view -R ${{ github.repository }} ${{ github.event.workflow_run.head_repository.owner.login }}:${{ github.event.workflow_run.head_branch }} --json number --jq .number) >> $GITHUB_OUTPUT
24 | - name: Slack Notify
25 | uses: slackapi/slack-github-action@v2
26 | with:
27 | method: chat.postMessage
28 | payload: |
29 | {
30 | "channel": "proj-talos-maintainers",
31 | "attachments": [
32 | {
33 | "color": "${{ github.event.workflow_run.conclusion == 'success' && '#2EB886' || github.event.workflow_run.conclusion == 'failure' && '#A30002' || '#FFCC00' }}",
34 | "fallback": "test",
35 | "blocks": [
36 | {
37 | "type": "section",
38 | "fields": [
39 | {
40 | "type": "mrkdwn",
41 | "text": "${{ github.event.workflow_run.event == 'pull_request' && format('*Pull Request:* {0} (`{1}`)\n<{2}/pull/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, steps.get-pr-number.outputs.pull_request_number, github.event.workflow_run.display_title) || format('*Build:* {0} (`{1}`)\n<{2}/commit/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, github.sha, github.event.workflow_run.display_title) }}"
42 | },
43 | {
44 | "type": "mrkdwn",
45 | "text": "*Status:*\n`${{ github.event.workflow_run.conclusion }}`"
46 | }
47 | ]
48 | },
49 | {
50 | "type": "section",
51 | "fields": [
52 | {
53 | "type": "mrkdwn",
54 | "text": "*Author:*\n`${{ github.actor }}`"
55 | },
56 | {
57 | "type": "mrkdwn",
58 | "text": "*Event:*\n`${{ github.event.workflow_run.event }}`"
59 | }
60 | ]
61 | },
62 | {
63 | "type": "divider"
64 | },
65 | {
66 | "type": "actions",
67 | "elements": [
68 | {
69 | "type": "button",
70 | "text": {
71 | "type": "plain_text",
72 | "text": "Logs"
73 | },
74 | "url": "${{ github.event.workflow_run.html_url }}"
75 | },
76 | {
77 | "type": "button",
78 | "text": {
79 | "type": "plain_text",
80 | "text": "Commit"
81 | },
82 | "url": "${{ github.event.repository.html_url }}/commit/${{ github.sha }}"
83 | }
84 | ]
85 | }
86 | ]
87 | }
88 | ]
89 | }
90 | token: ${{ secrets.SLACK_BOT_TOKEN }}
91 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | terraform-provider-talos
3 | _out
4 |
5 | ### Terraform ###
6 | # Local .terraform directories
7 | **/.terraform/*
8 |
9 | # .tfstate files
10 | *.tfstate
11 | *.tfstate.*
12 |
13 | # Crash log files
14 | crash.*.log
15 |
16 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as
17 | # password, private keys, and other secrets. These should not be part of version
18 | # control as they are data points which are potentially sensitive and subject
19 | # to change depending on the environment.
20 | #*.tfvars
21 | #*.tfvars.json
22 |
23 | # Ignore override files as they are usually used to override resources locally and so
24 | # are not checked in
25 | override.tf
26 | override.tf.json
27 | *_override.tf
28 | *_override.tf.json
29 |
30 | # Include override files you do wish to add to version control using negated pattern
31 | # !example_override.tf
32 |
33 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
34 | # example: *tfplan*
35 |
36 | # Ignore CLI configuration files
37 | .terraformrc
38 | terraform.rc
39 |
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
2 | #
3 | # Generated on 2025-05-05T10:34:00Z by kres be6d3a6a.
4 |
5 | version: "2"
6 |
7 | # options for analysis running
8 | run:
9 | modules-download-mode: readonly
10 | issues-exit-code: 1
11 | tests: true
12 |
13 | # output configuration options
14 | output:
15 | formats:
16 | text:
17 | path: stdout
18 | print-issued-lines: true
19 | print-linter-name: true
20 | path-prefix: ""
21 |
22 |
23 | linters:
24 | default: all
25 | disable:
26 | - exhaustruct
27 | - err113
28 | - forbidigo
29 | - funcorder
30 | - funlen
31 | - gochecknoglobals
32 | - gochecknoinits
33 | - godox
34 | - gomoddirectives
35 | - gosec
36 | - inamedparam
37 | - ireturn
38 | - mnd
39 | - nestif
40 | - nonamedreturns
41 | - paralleltest
42 | - tagalign
43 | - tagliatelle
44 | - thelper
45 | - varnamelen
46 | - wrapcheck
47 | - testifylint # complains about our assert recorder and has a number of false positives for assert.Greater(t, thing, 1)
48 | - protogetter # complains about us using Value field on typed spec, instead of GetValue which has a different signature
49 | - perfsprint # complains about us using fmt.Sprintf in non-performance critical code, updating just kres took too long
50 | - musttag # seems to be broken - goes into imported libraries and reports issues there
51 | - nolintlint # gives false positives - disable until https://github.com/golangci/golangci-lint/issues/3228 is resolved
52 | # all available settings of specific linters
53 | settings:
54 | cyclop:
55 | # the maximal code complexity to report
56 | max-complexity: 20
57 | dogsled:
58 | max-blank-identifiers: 2
59 | dupl:
60 | threshold: 150
61 | errcheck:
62 | check-type-assertions: true
63 | check-blank: true
64 | exhaustive:
65 | default-signifies-exhaustive: false
66 | gocognit:
67 | min-complexity: 30
68 | nestif:
69 | min-complexity: 5
70 | goconst:
71 | min-len: 3
72 | min-occurrences: 3
73 | gocritic:
74 | disabled-checks: [ ]
75 | gocyclo:
76 | min-complexity: 20
77 | godot:
78 | scope: declarations
79 | gomodguard: { }
80 | govet:
81 | enable-all: true
82 | lll:
83 | line-length: 200
84 | tab-width: 4
85 | misspell:
86 | locale: US
87 | nakedret:
88 | max-func-lines: 30
89 | prealloc:
90 | simple: true
91 | range-loops: true # Report preallocation suggestions on range loops, true by default
92 | for-loops: false # Report preallocation suggestions on for loops, false by default
93 | rowserrcheck: { }
94 | testpackage: { }
95 | unparam:
96 | check-exported: false
97 | unused:
98 | local-variables-are-used: false
99 | whitespace:
100 | multi-if: false # Enforces newlines (or comments) after every multi-line if statement
101 | multi-func: false # Enforces newlines (or comments) after every multi-line function signature
102 | wsl:
103 | strict-append: true
104 | allow-assign-and-call: true
105 | allow-multiline-assign: true
106 | allow-trailing-comment: false
107 | force-case-trailing-whitespace: 0
108 | allow-separated-leading-comment: false
109 | allow-cuddle-declarations: false
110 | force-err-cuddling: false
111 | depguard:
112 | rules:
113 | prevent_unmaintained_packages:
114 | list-mode: lax # allow unless explicitly denied
115 | files:
116 | - $all
117 | deny:
118 | - pkg: io/ioutil
119 | desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil"
120 | test_kres_depguard_extra_rule_1:
121 | deny:
122 | - desc: Test rule 1
123 | pkg: io/ioutil
124 | files:
125 | - test_1.go
126 | list-mode: lax
127 | test_kres_depguard_extra_rule_2:
128 | deny:
129 | - desc: Test rule 2
130 | pkg: io/ioutil
131 | files:
132 | - test_2.go
133 | list-mode: lax
134 |
135 | exclusions:
136 | generated: lax
137 | paths:
138 | - third_party$
139 | - builtin$
140 | - examples$
141 | issues:
142 | max-issues-per-linter: 10
143 | max-same-issues: 3
144 | uniq-by-line: true
145 | new: false
146 |
147 | severity:
148 | default: error
149 | formatters:
150 | enable:
151 | - gci
152 | - gofmt
153 | - gofumpt
154 | settings:
155 | gci:
156 | sections:
157 | - standard
158 | - default
159 | - localmodule
160 | gofmt:
161 | simplify: true
162 | gofumpt:
163 | extra-rules: false
164 | exclusions:
165 | generated: lax
166 | paths:
167 | - third_party$
168 | - builtin$
169 | - examples$
170 |
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | # Visit https://goreleaser.com for documentation on how to customize this
2 | # behavior.
3 | version: 2
4 | before:
5 | hooks:
6 | # this is just an example and not a requirement for provider building/publishing
7 | - go mod tidy
8 | builds:
9 | - env:
10 | # goreleaser does not work with CGO, it could also complicate
11 | # usage by users in CI/CD systems like Terraform Cloud where
12 | # they are unable to install libraries.
13 | - CGO_ENABLED=0
14 | mod_timestamp: '{{ .CommitTimestamp }}'
15 | flags:
16 | - -trimpath
17 | ldflags:
18 | - '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}}'
19 | goos:
20 | - freebsd
21 | - windows
22 | - linux
23 | - darwin
24 | goarch:
25 | - amd64
26 | - '386'
27 | - arm
28 | - arm64
29 | ignore:
30 | - goos: darwin
31 | goarch: '386'
32 | binary: '{{ .ProjectName }}_v{{ .Version }}'
33 | archives:
34 | - format: zip
35 | name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}'
36 | checksum:
37 | extra_files:
38 | - glob: 'terraform-registry-manifest.json'
39 | name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
40 | name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS'
41 | algorithm: sha256
42 | signs:
43 | - artifacts: checksum
44 | args:
45 | # if you are using this in a GitHub action or some other automated pipeline, you
46 | # need to pass the batch flag to indicate its not interactive.
47 | - "--batch"
48 | - "--local-user"
49 | - "{{ .Env.GPG_FINGERPRINT }}" # set this environment variable for your signing key
50 | - "--output"
51 | - "${signature}"
52 | - "--detach-sign"
53 | - "${artifact}"
54 | release:
55 | extra_files:
56 | - glob: 'terraform-registry-manifest.json'
57 | name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
58 | # If you want to manually examine the release before its live, uncomment this line:
59 | # draft: true
60 | changelog:
61 | disable: false
62 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Debug Talos Terraform Provider",
6 | "type": "go",
7 | "request": "launch",
8 | "mode": "debug",
9 | // this assumes your workspace is the root of the repo
10 | "program": "${workspaceFolder}",
11 | "env": {},
12 | "args": [
13 | "-debug",
14 | ]
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | TAG ?= $(shell git describe --tag --always --dirty)
2 | ARTIFACTS ?= _out
3 | TEST_TIMEOUT ?= 600s
4 |
5 | ifneq ($(origin TESTS), undefined)
6 | RUNARGS = -run='$(TESTS)'
7 | endif
8 |
9 | ifneq ($(origin CI), undefined)
10 | RUNARGS += -parallel=3
11 | RUNARGS += -timeout=25m
12 | RUNARGS += -exec="sudo -E"
13 | endif
14 |
15 | .PHONY: generate
16 | generate:
17 | go generate ./pkg/talos
18 | go generate
19 |
20 | .PHONY: testacc
21 | testacc:
22 | # TF_CLI_CONFIG_FILE is set here to avoid using the user's .terraformrc file. Ref: https://github.com/hashicorp/terraform-plugin-sdk/issues/1171
23 | TF_CLI_CONFIG_FILE="thisfiledoesnotexist" TF_ACC=1 go test -v -failfast -cover $(RUNARGS) ./...
24 |
25 | .PHONY: check-dirty
26 | check-dirty: generate ## Verifies that source tree is not dirty
27 | @if test -n "`git status --porcelain`"; then echo "Source tree is dirty"; git status; exit 1 ; fi
28 |
29 | build-debug:
30 | go build -gcflags='all=-N -l'
31 |
32 | install:
33 | go install .
34 |
35 | release-notes:
36 | mkdir -p $(ARTIFACTS)
37 | @ARTIFACTS=$(ARTIFACTS) ./hack/release.sh $@ $(ARTIFACTS)/RELEASE_NOTES.md $(TAG)
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # terraform-provider-talos
2 |
3 | ## Debugging
4 |
5 | In a bash shell, build a debug version of this provider binary:
6 |
7 | ```bash
8 | make build-debug
9 | ```
10 |
11 | In Visual Studio Code, [start the provider in a debug session](https://developer.hashicorp.com/terraform/plugin/debugging#starting-a-provider-in-debug-mode).
12 |
13 | In a new bash shell, go into your terraform project directory, and run
14 | terraform with `TF_REATTACH_PROVIDERS` set to the value printed in the VSCode debug windows.
15 |
--------------------------------------------------------------------------------
/docs/data-sources/client_configuration.md:
--------------------------------------------------------------------------------
1 | ---
2 | # generated by https://github.com/hashicorp/terraform-plugin-docs
3 | page_title: "talos_client_configuration Data Source - talos"
4 | subcategory: ""
5 | description: |-
6 | Generate client configuration for a Talos cluster
7 | ---
8 |
9 | # talos_client_configuration (Data Source)
10 |
11 | Generate client configuration for a Talos cluster
12 |
13 | ## Example Usage
14 |
15 | ```terraform
16 | resource "talos_machine_secrets" "this" {}
17 |
18 | data "talos_client_configuration" "this" {
19 | cluster_name = "example-cluster"
20 | client_configuration = talos_machine_secrets.this.client_configuration
21 | nodes = ["10.5.0.2"]
22 | }
23 | ```
24 |
25 |
26 | ## Schema
27 |
28 | ### Required
29 |
30 | - `client_configuration` (Attributes) The client configuration data (see [below for nested schema](#nestedatt--client_configuration))
31 | - `cluster_name` (String) The name of the cluster in the generated config
32 |
33 | ### Optional
34 |
35 | - `endpoints` (List of String) endpoints to set in the generated config
36 | - `nodes` (List of String) nodes to set in the generated config
37 |
38 | ### Read-Only
39 |
40 | - `id` (String) The ID of this resource
41 | - `talos_config` (String, Sensitive) The generated client configuration
42 |
43 |
44 | ### Nested Schema for `client_configuration`
45 |
46 | Required:
47 |
48 | - `ca_certificate` (String) The client CA certificate
49 | - `client_certificate` (String) The client certificate
50 | - `client_key` (String, Sensitive) The client key
51 |
--------------------------------------------------------------------------------
/docs/data-sources/cluster_health.md:
--------------------------------------------------------------------------------
1 | ---
2 | # generated by https://github.com/hashicorp/terraform-plugin-docs
3 | page_title: "talos_cluster_health Data Source - talos"
4 | subcategory: ""
5 | description: |-
6 | Waits for the Talos cluster to be healthy. Can be used as a dependency before running other operations on the cluster.
7 | ---
8 |
9 | # talos_cluster_health (Data Source)
10 |
11 | Waits for the Talos cluster to be healthy. Can be used as a dependency before running other operations on the cluster.
12 |
13 |
14 |
15 |
16 | ## Schema
17 |
18 | ### Required
19 |
20 | - `client_configuration` (Attributes) The client configuration data (see [below for nested schema](#nestedatt--client_configuration))
21 | - `control_plane_nodes` (List of String) List of control plane nodes to check for health.
22 | - `endpoints` (List of String) endpoints to use for the health check client. Use at least one control plane endpoint.
23 |
24 | ### Optional
25 |
26 | - `skip_kubernetes_checks` (Boolean) Skip Kubernetes component checks, this is useful to check if the nodes has finished booting up and kubelet is running. Default is false.
27 | - `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
28 | - `worker_nodes` (List of String) List of worker nodes to check for health.
29 |
30 | ### Read-Only
31 |
32 | - `id` (String) The ID of this resource.
33 |
34 |
35 | ### Nested Schema for `client_configuration`
36 |
37 | Required:
38 |
39 | - `ca_certificate` (String) The client CA certificate
40 | - `client_certificate` (String) The client certificate
41 | - `client_key` (String, Sensitive) The client key
42 |
43 |
44 |
45 | ### Nested Schema for `timeouts`
46 |
47 | Optional:
48 |
49 | - `read` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Read operations occur during any refresh or planning operation when refresh is enabled.
50 |
--------------------------------------------------------------------------------
/docs/data-sources/cluster_kubeconfig.md:
--------------------------------------------------------------------------------
1 | ---
2 | # generated by https://github.com/hashicorp/terraform-plugin-docs
3 | page_title: "talos_cluster_kubeconfig Data Source - talos"
4 | subcategory: ""
5 | description: |-
6 | Retrieves the kubeconfig for a Talos cluster
7 | ---
8 |
9 | # talos_cluster_kubeconfig (Data Source)
10 |
11 | Retrieves the kubeconfig for a Talos cluster
12 |
13 | ## Example Usage
14 |
15 | ```terraform
16 | resource "talos_machine_secrets" "this" {}
17 |
18 | data "talos_machine_configuration" "this" {
19 | cluster_name = "example-cluster"
20 | machine_type = "controlplane"
21 | cluster_endpoint = "https://cluster.local:6443"
22 | machine_secrets = talos_machine_secrets.this.machine_secrets
23 | }
24 |
25 | data "talos_client_configuration" "this" {
26 | cluster_name = "example-cluster"
27 | client_configuration = talos_machine_secrets.this.client_configuration
28 | nodes = ["10.5.0.2"]
29 | }
30 |
31 | resource "talos_machine_configuration_apply" "this" {
32 | client_configuration = talos_machine_secrets.this.client_configuration
33 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
34 | node = "10.5.0.2"
35 | config_patches = [
36 | yamlencode({
37 | machine = {
38 | install = {
39 | disk = "/dev/sdd"
40 | }
41 | }
42 | })
43 | ]
44 | }
45 |
46 | resource "talos_machine_bootstrap" "this" {
47 | depends_on = [
48 | talos_machine_configuration_apply.this
49 | ]
50 | node = "10.5.0.2"
51 | client_configuration = talos_machine_secrets.this.client_configuration
52 | }
53 |
54 |
55 | data "talos_cluster_kubeconfig" "this" {
56 | depends_on = [
57 | talos_machine_bootstrap.this
58 | ]
59 | client_configuration = talos_machine_secrets.this.client_configuration
60 | node = "10.5.0.2"
61 | }
62 | ```
63 |
64 |
65 | ## Schema
66 |
67 | ### Required
68 |
69 | - `client_configuration` (Attributes) The client configuration data (see [below for nested schema](#nestedatt--client_configuration))
70 | - `node` (String) controlplane node to retrieve the kubeconfig from
71 |
72 | ### Optional
73 |
74 | - `endpoint` (String) endpoint to use for the talosclient. If not set, the node value will be used
75 | - `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
76 | - `wait` (Boolean, Deprecated) Wait for the kubernetes api to be available
77 |
78 | ### Read-Only
79 |
80 | - `id` (String) The ID of this resource.
81 | - `kubeconfig_raw` (String, Sensitive) The raw kubeconfig
82 | - `kubernetes_client_configuration` (Attributes) The kubernetes client configuration (see [below for nested schema](#nestedatt--kubernetes_client_configuration))
83 |
84 |
85 | ### Nested Schema for `client_configuration`
86 |
87 | Required:
88 |
89 | - `ca_certificate` (String) The client CA certificate
90 | - `client_certificate` (String) The client certificate
91 | - `client_key` (String, Sensitive) The client key
92 |
93 |
94 |
95 | ### Nested Schema for `timeouts`
96 |
97 | Optional:
98 |
99 | - `read` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Read operations occur during any refresh or planning operation when refresh is enabled.
100 |
101 |
102 |
103 | ### Nested Schema for `kubernetes_client_configuration`
104 |
105 | Read-Only:
106 |
107 | - `ca_certificate` (String) The kubernetes CA certificate
108 | - `client_certificate` (String) The kubernetes client certificate
109 | - `client_key` (String, Sensitive) The kubernetes client key
110 | - `host` (String) The kubernetes host
111 |
--------------------------------------------------------------------------------
/docs/data-sources/image_factory_extensions_versions.md:
--------------------------------------------------------------------------------
1 | ---
2 | # generated by https://github.com/hashicorp/terraform-plugin-docs
3 | page_title: "talos_image_factory_extensions_versions Data Source - talos"
4 | subcategory: ""
5 | description: |-
6 | The image factory extensions versions data source provides a list of available extensions for a specific talos version from the image factory.
7 | ---
8 |
9 | # talos_image_factory_extensions_versions (Data Source)
10 |
11 | The image factory extensions versions data source provides a list of available extensions for a specific talos version from the image factory.
12 |
13 | ## Example Usage
14 |
15 | ```terraform
16 | provider "talos" {}
17 |
18 | data "talos_image_factory_extensions_versions" "this" {
19 | # get the latest talos version
20 | talos_version = "v1.7.5"
21 | filters = {
22 | names = [
23 | "amdgpu",
24 | "tailscale",
25 | ]
26 | }
27 | }
28 | ```
29 |
30 |
31 | ## Schema
32 |
33 | ### Required
34 |
35 | - `talos_version` (String) The talos version to get extensions for.
36 |
37 | ### Optional
38 |
39 | - `filters` (Attributes) The filter to apply to the extensions list. (see [below for nested schema](#nestedatt--filters))
40 |
41 | ### Read-Only
42 |
43 | - `extensions_info` (List of Object) The list of available extensions for the specified talos version. (see [below for nested schema](#nestedatt--extensions_info))
44 | - `id` (String) The ID of this resource.
45 |
46 |
47 | ### Nested Schema for `filters`
48 |
49 | Optional:
50 |
51 | - `names` (List of String) The name of the extension to filter by.
52 |
53 |
54 |
55 | ### Nested Schema for `extensions_info`
56 |
57 | Read-Only:
58 |
59 | - `author` (String)
60 | - `description` (String)
61 | - `digest` (String)
62 | - `name` (String)
63 | - `ref` (String)
64 |
--------------------------------------------------------------------------------
/docs/data-sources/image_factory_overlays_versions.md:
--------------------------------------------------------------------------------
1 | ---
2 | # generated by https://github.com/hashicorp/terraform-plugin-docs
3 | page_title: "talos_image_factory_overlays_versions Data Source - talos"
4 | subcategory: ""
5 | description: |-
6 | The image factory overlays versions data source provides a list of available overlays for a specific talos version from the image factory.
7 | ---
8 |
9 | # talos_image_factory_overlays_versions (Data Source)
10 |
11 | The image factory overlays versions data source provides a list of available overlays for a specific talos version from the image factory.
12 |
13 | ## Example Usage
14 |
15 | ```terraform
16 | provider "talos" {}
17 |
18 | data "talos_image_factory_overlays_versions" "this" {
19 | # get the latest talos version
20 | talos_version = "v1.7.5"
21 | filters = {
22 | name = "rock4cplus"
23 | }
24 | }
25 | ```
26 |
27 |
28 | ## Schema
29 |
30 | ### Required
31 |
32 | - `talos_version` (String) The talos version to get overlays for.
33 |
34 | ### Optional
35 |
36 | - `filters` (Attributes) The filter to apply to the overlays list. (see [below for nested schema](#nestedatt--filters))
37 |
38 | ### Read-Only
39 |
40 | - `id` (String) The ID of this resource.
41 | - `overlays_info` (List of Object) The list of available extensions for the specified talos version. (see [below for nested schema](#nestedatt--overlays_info))
42 |
43 |
44 | ### Nested Schema for `filters`
45 |
46 | Optional:
47 |
48 | - `name` (String) The name of the overlay to filter by.
49 |
50 |
51 |
52 | ### Nested Schema for `overlays_info`
53 |
54 | Read-Only:
55 |
56 | - `digest` (String)
57 | - `image` (String)
58 | - `name` (String)
59 | - `ref` (String)
60 |
--------------------------------------------------------------------------------
/docs/data-sources/image_factory_urls.md:
--------------------------------------------------------------------------------
1 | ---
2 | # generated by https://github.com/hashicorp/terraform-plugin-docs
3 | page_title: "talos_image_factory_urls Data Source - talos"
4 | subcategory: ""
5 | description: |-
6 | Generates URLs for different assets supported by the Talos image factory.
7 | ---
8 |
9 | # talos_image_factory_urls (Data Source)
10 |
11 | Generates URLs for different assets supported by the Talos image factory.
12 |
13 | ## Example Usage
14 |
15 | ```terraform
16 | data "talos_image_factory_urls" "this" {
17 | talos_version = "v1.7.5"
18 | schematic_id = "376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba"
19 | platform = "metal"
20 | }
21 |
22 | output "installer_image" {
23 | value = data.talos_image_factory_urls.this.urls.installer
24 | }
25 | ```
26 |
27 |
28 | ## Schema
29 |
30 | ### Required
31 |
32 | - `schematic_id` (String) The schematic ID for which the URLs are generated.
33 | - `talos_version` (String) The Talos version for which the URLs are generated.
34 |
35 | ### Optional
36 |
37 | - `architecture` (String) The platform architecture for which the URLs are generated. Defaults to amd64.
38 | - `platform` (String) The platform for which the URLs are generated.
39 |
40 | #### Metal
41 |
42 | - metal
43 |
44 | #### Cloud Platforms
45 | - aws
46 | - gcp
47 | - equinixMetal
48 | - azure
49 | - digital-ocean
50 | - nocloud
51 | - openstack
52 | - vmware
53 | - akamai
54 | - cloudstack
55 | - hcloud
56 | - oracle
57 | - upcloud
58 | - vultr
59 | - exoscale
60 | - opennebula
61 | - scaleway
62 | - `sbc` (String) The SBC's (Single Board Copmuters) for which the url are generated.
63 |
64 | #### Single Board Computers
65 | - rpi_generic
66 | - revpi_generic
67 | - bananapi_m64
68 | - nanopi_r4s
69 | - nanopi_r5s
70 | - jetson_nano
71 | - libretech_all_h3_cc_h5
72 | - orangepi_r1_plus_lts
73 | - pine64
74 | - rock64
75 | - rock4cplus
76 | - rock4se
77 | - rock5a
78 | - rock5b
79 | - rockpi_4
80 | - rockpi_4c
81 | - helios64
82 | - turingrk1
83 | - orangepi-5
84 | - orangepi-5-plus
85 | - rockpro64
86 |
87 | ### Read-Only
88 |
89 | - `id` (String) The ID of this resource.
90 | - `urls` (Attributes) The URLs for different assets supported by the Talos image factory. If the URL is not available for a specific asset, it will be an empty string. (see [below for nested schema](#nestedatt--urls))
91 |
92 |
93 | ### Nested Schema for `urls`
94 |
95 | Read-Only:
96 |
97 | - `disk_image` (String) The URL for the disk image.
98 | - `disk_image_secureboot` (String) The URL for the disk image with secure boot.
99 | - `initramfs` (String) The URL for the initramfs image.
100 | - `installer` (String) The URL for the installer image.
101 | - `installer_secureboot` (String) The URL for the installer image with secure boot.
102 | - `iso` (String) The URL for the ISO image.
103 | - `iso_secureboot` (String) The URL for the ISO image with secure boot.
104 | - `kernel` (String) The URL for the kernel image.
105 | - `kernel_command_line` (String) The URL for the kernel command line.
106 | - `pxe` (String) The URL for the PXE image.
107 | - `uki` (String) The URL for the UKI image.
108 |
--------------------------------------------------------------------------------
/docs/data-sources/image_factory_versions.md:
--------------------------------------------------------------------------------
1 | ---
2 | # generated by https://github.com/hashicorp/terraform-plugin-docs
3 | page_title: "talos_image_factory_versions Data Source - talos"
4 | subcategory: ""
5 | description: |-
6 | The image factory versions data source provides a list of available talos versions from the image factory.
7 | ---
8 |
9 | # talos_image_factory_versions (Data Source)
10 |
11 | The image factory versions data source provides a list of available talos versions from the image factory.
12 |
13 | ## Example Usage
14 |
15 | ```terraform
16 | provider "talos" {}
17 |
18 | data "talos_image_factory_versions" "this" {}
19 |
20 | output "latest" {
21 | value = element(data.talos_image_factory_versions.this.talos_versions, length(data.talos_image_factory_versions.this.talos_versions) - 1)
22 | }
23 | ```
24 |
25 |
26 | ## Schema
27 |
28 | ### Optional
29 |
30 | - `filters` (Attributes) The filter to apply to the overlays list. (see [below for nested schema](#nestedatt--filters))
31 |
32 | ### Read-Only
33 |
34 | - `id` (String) The ID of this resource.
35 | - `talos_versions` (List of String) The list of available talos versions.
36 |
37 |
38 | ### Nested Schema for `filters`
39 |
40 | Optional:
41 |
42 | - `stable_versions_only` (Boolean) If set to true, only stable versions will be returned. If set to false, all versions will be returned.
43 |
--------------------------------------------------------------------------------
/docs/data-sources/machine_configuration.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "talos_machine_configuration Data Source - talos"
3 | subcategory: ""
4 | description: |-
5 | Generate a machine configuration for a node type
6 | ---
7 |
8 | # talos_machine_configuration (Data Source)
9 |
10 | Generate a machine configuration for a node type
11 |
12 | -> **Note:** It is recommended to set the optional `talos_version` attribute. Otherwise when using a new version of the provider with a new major version of the Talos SDK, new machineconfig features will be enabled by default which could cause unexpected behavior.
13 |
14 | ## Example Usage
15 |
16 | ```terraform
17 | resource "talos_machine_secrets" "this" {}
18 |
19 | data "talos_machine_configuration" "this" {
20 | cluster_name = "example-cluster"
21 | machine_type = "controlplane"
22 | cluster_endpoint = "https://cluster.local:6443"
23 | machine_secrets = talos_machine_secrets.this.machine_secrets
24 | }
25 | ```
26 |
27 | ## Schema
28 |
29 | ### Required
30 |
31 | - `cluster_endpoint` (String) The endpoint of the talos kubernetes cluster
32 | - `cluster_name` (String) The name of the talos kubernetes cluster
33 | - `machine_secrets` (Attributes) The secrets for the talos cluster (see [below for nested schema](#nestedatt--machine_secrets))
34 | - `machine_type` (String) The type of machine to generate the configuration for
35 |
36 | ### Optional
37 |
38 | - `config_patches` (List of String) The list of config patches to apply to the generated configuration
39 | - `docs` (Boolean) Whether to generate documentation for the generated configuration. Defaults to false
40 | - `examples` (Boolean) Whether to generate examples for the generated configuration. Defaults to false
41 | - `kubernetes_version` (String) The version of kubernetes to use
42 | - `talos_version` (String) The version of talos features to use in generated machine configuration
43 |
44 | ### Read-Only
45 |
46 | - `id` (String) The ID of this resource.
47 | - `machine_configuration` (String, Sensitive) The generated machine configuration
48 |
49 |
50 | ### Nested Schema for `machine_secrets`
51 |
52 | Required:
53 |
54 | - `certs` (Attributes) The certs for the talos kubernetes cluster (see [below for nested schema](#nestedatt--machine_secrets--certs))
55 | - `cluster` (Attributes) The cluster secrets (see [below for nested schema](#nestedatt--machine_secrets--cluster))
56 | - `secrets` (Attributes) The secrets for the talos kubernetes cluster (see [below for nested schema](#nestedatt--machine_secrets--secrets))
57 | - `trustdinfo` (Attributes) The trustd info for the talos kubernetes cluster (see [below for nested schema](#nestedatt--machine_secrets--trustdinfo))
58 |
59 |
60 | ### Nested Schema for `machine_secrets.certs`
61 |
62 | Required:
63 |
64 | - `etcd` (Attributes) The certificate and key pair (see [below for nested schema](#nestedatt--machine_secrets--certs--etcd))
65 | - `k8s` (Attributes) The certificate and key pair (see [below for nested schema](#nestedatt--machine_secrets--certs--k8s))
66 | - `k8s_aggregator` (Attributes) The certificate and key pair (see [below for nested schema](#nestedatt--machine_secrets--certs--k8s_aggregator))
67 | - `k8s_serviceaccount` (Attributes) (see [below for nested schema](#nestedatt--machine_secrets--certs--k8s_serviceaccount))
68 | - `os` (Attributes) The certificate and key pair (see [below for nested schema](#nestedatt--machine_secrets--certs--os))
69 |
70 |
71 | ### Nested Schema for `machine_secrets.certs.etcd`
72 |
73 | Required:
74 |
75 | - `cert` (String) certificate data
76 | - `key` (String, Sensitive) key data
77 |
78 |
79 |
80 | ### Nested Schema for `machine_secrets.certs.k8s`
81 |
82 | Required:
83 |
84 | - `cert` (String) certificate data
85 | - `key` (String, Sensitive) key data
86 |
87 |
88 |
89 | ### Nested Schema for `machine_secrets.certs.k8s_aggregator`
90 |
91 | Required:
92 |
93 | - `cert` (String) certificate data
94 | - `key` (String, Sensitive) key data
95 |
96 |
97 |
98 | ### Nested Schema for `machine_secrets.certs.k8s_serviceaccount`
99 |
100 | Required:
101 |
102 | - `key` (String, Sensitive) The key for the k8s service account
103 |
104 |
105 |
106 | ### Nested Schema for `machine_secrets.certs.os`
107 |
108 | Required:
109 |
110 | - `cert` (String) certificate data
111 | - `key` (String, Sensitive) key data
112 |
113 |
114 |
115 |
116 | ### Nested Schema for `machine_secrets.cluster`
117 |
118 | Required:
119 |
120 | - `id` (String) The cluster id
121 | - `secret` (String, Sensitive) The cluster secret
122 |
123 |
124 |
125 | ### Nested Schema for `machine_secrets.secrets`
126 |
127 | Required:
128 |
129 | - `bootstrap_token` (String, Sensitive) The bootstrap token for the talos kubernetes cluster
130 | - `secretbox_encryption_secret` (String, Sensitive) The secretbox encryption secret for the talos kubernetes cluster
131 |
132 | Optional:
133 |
134 | - `aescbc_encryption_secret` (String, Sensitive) The aescbc encryption secret for the talos kubernetes cluster
135 |
136 |
137 |
138 | ### Nested Schema for `machine_secrets.trustdinfo`
139 |
140 | Required:
141 |
142 | - `token` (String, Sensitive) The trustd token for the talos kubernetes cluster
143 |
--------------------------------------------------------------------------------
/docs/data-sources/machine_disks.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "talos_machine_disks Data Source - talos"
3 | subcategory: ""
4 | description: |-
5 | Generate a machine configuration for a node type
6 | ---
7 |
8 | # talos_machine_disks (Data Source)
9 |
10 | Generate a machine configuration for a node type
11 |
12 | -> **Note:** Since Talos natively supports `.machine.install.diskSelector`, the `talos_machine_disks` data source maybe just used to query disk information that could be used elsewhere. It's recommended to use `machine.install.diskSelector` in Talos machine configuration.
13 |
14 | ## Example Usage
15 |
16 | ```terraform
17 | resource "talos_machine_secrets" "this" {}
18 |
19 | data "talos_machine_disks" "this" {
20 | client_configuration = talos_machine_secrets.this.client_configuration
21 | node = "10.5.0.2"
22 | selector = "disk.size > 6u * GB"
23 | }
24 |
25 | # for example, this could be used to pass in a list of disks to rook-ceph
26 | output "nvme_disks" {
27 | value = data.talos_machine_disks.this.disks.*.name
28 | }
29 | ```
30 |
31 | ## Schema
32 |
33 | ### Required
34 |
35 | - `client_configuration` (Attributes) The client configuration data (see [below for nested schema](#nestedatt--client_configuration))
36 | - `node` (String) controlplane node to retrieve the kubeconfig from
37 |
38 | ### Optional
39 |
40 | - `endpoint` (String) endpoint to use for the talosclient. If not set, the node value will be used
41 | - `selector` (String) The CEL expression to filter the disks.
42 | If not set, all disks will be returned.
43 | See [CEL documentation](https://www.talos.dev/latest/talos-guides/configuration/disk-management/#disk-selector).
44 | - `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
45 |
46 | ### Read-Only
47 |
48 | - `disks` (Attributes List) The disks that match the filters (see [below for nested schema](#nestedatt--disks))
49 | - `id` (String) The generated ID of this resource
50 |
51 |
52 | ### Nested Schema for `client_configuration`
53 |
54 | Required:
55 |
56 | - `ca_certificate` (String) The client CA certificate
57 | - `client_certificate` (String) The client certificate
58 | - `client_key` (String, Sensitive) The client key
59 |
60 |
61 |
62 | ### Nested Schema for `timeouts`
63 |
64 | Optional:
65 |
66 | - `read` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Read operations occur during any refresh or planning operation when refresh is enabled.
67 |
68 |
69 |
70 | ### Nested Schema for `disks`
71 |
72 | Read-Only:
73 |
74 | - `bus_path` (String)
75 | - `cdrom` (Boolean)
76 | - `dev_path` (String)
77 | - `io_size` (Number)
78 | - `modalias` (String)
79 | - `model` (String)
80 | - `pretty_size` (String)
81 | - `readonly` (Boolean)
82 | - `rotational` (Boolean)
83 | - `secondary_disks` (List of String)
84 | - `sector_size` (Number)
85 | - `serial` (String)
86 | - `size` (Number)
87 | - `sub_system` (String)
88 | - `symlinks` (List of String)
89 | - `transport` (String)
90 | - `uuid` (String)
91 | - `wwid` (String)
92 |
--------------------------------------------------------------------------------
/docs/guides/version-0.2-upgrade.html.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "Terraform Talos Provider Version 0.2 Upgrade Guide"
3 | description: |-
4 | Terraform Talos Provider Version 0.2 Upgrade Guide
5 | ---
6 |
7 | # Terraform Talos Provider Version 0.2 Upgrade Guide
8 |
9 | Version 0.2 of the Talos Terraform provider is a major release and include some breaking chages. This guide will walk you through the changes and how to upgrade your Terraform configuration.
10 |
11 | ~> **NOTE:** Version 0.2 of the Talos Terraform provider drops support for the following resources:
12 |
13 | > * `talos_client_configuration`
14 | > * `talos_cluster_kubeconfig`
15 | > * `talos_machine_configuration_controlplane`
16 | > * `talos_machine_configuration_worker`
17 |
18 | The following table lists the resources that have been removed and the new resources that replace them.
19 |
20 | | Removed Resource | Type | New Resource | Type |
21 | | ------------------------------------------ | -------- | ----------------------------- | ------------- |
22 | | `talos_client_configuration` | Resource | `talos_client_configuration` | Data Source |
23 | | `talos_cluster_kubeconfig` | Resource | `talos_cluster_kubeconfig` | Data Source |
24 | | `talos_machine_configuration_controlplane` | Resource | `talos_machine_configuration` | Data Resource |
25 | | `talos_machine_configuration_worker` | Resource | `talos_machine_configuration` | Data Resource |
26 |
27 | ## Upgrade topics:
28 |
29 | - [Upgrading `talos_client_configuration` resource](#upgrading-talos_client_configuration-resource)
30 | - [Upgrading `talos_cluster_kubeconfig` resource](#upgrading-talos_cluster_kubeconfig-resource)
31 | - [Upgrading `talos_machine_configuration_controlplane` resource](#upgrading-talos_machine_configuration_controlplane-resource)
32 | - [Upgrading `talos_machine_configuration_worker` resource](#upgrading-talos_machine_configuration_worker-resource)
33 |
34 | ### Upgrading `talos_client_configuration` resource
35 |
36 | The `talos_client_configuration` resource has been removed. The `talos_client_configuration` data source should be used instead.
37 |
38 | For example if the following resource was used:
39 |
40 | ```hcl
41 | resource "talos_machine_secrets" "this" {}
42 |
43 | resource "talos_client_configuration" "talosconfig" {
44 | cluster_name = "example-cluster"
45 | machine_secrets = talos_machine_secrets.this.machine_secrets
46 | }
47 | ```
48 |
49 | `talos_client_configuration` resource should be first removed from the state:
50 |
51 | ```bash
52 | terraform state rm talos_client_configuration.talosconfig
53 | ```
54 |
55 | and the code should be updated to:
56 |
57 | ```hcl
58 | resource "talos_machine_secrets" "machine_secrets" {}
59 |
60 | data "talos_client_configuration" "this" {
61 | cluster_name = "example-cluster"
62 | client_configuration = talos_machine_secrets.this.client_configuration
63 | }
64 | ```
65 |
66 | ### Upgrading `talos_cluster_kubeconfig` resource
67 |
68 | The `talos_cluster_kubeconfig` resource has been removed. The `talos_cluster_kubeconfig` data source should be used instead.
69 |
70 | For example if the following resource was used:
71 |
72 | ```hcl
73 | resource "talos_machine_secrets" "this" {}
74 |
75 | resource "talos_client_configuration" "this" {
76 | cluster_name = "example-cluster"
77 | machine_secrets = talos_machine_secrets.this.machine_secrets
78 | }
79 |
80 | resource "talos_cluster_kubeconfig" "kubeconfig" {
81 | talos_config = talos_client_configuration.this.talos_config
82 | endpoint = "10.5.0.2"
83 | node = "10.5.0.2"
84 | }
85 | ```
86 |
87 | `talos_cluster_kubeconfig` resource should be first removed from the state:
88 |
89 | ```bash
90 | terraform state rm talos_cluster_kubeconfig.kubeconfig
91 | ```
92 |
93 | and the code should be updated to:
94 |
95 | ```hcl
96 | resource "talos_machine_secrets" "machine_secrets" {}
97 |
98 | data "talos_cluster_kubeconfig" "this" {
99 | client_configuration = talos_machine_secrets.this.client_configuration
100 | node = "10.5.0.2"
101 | }
102 | ```
103 |
104 | ### Upgrading `talos_machine_configuration_controlplane` resource
105 |
106 | The `talos_machine_configuration_controlplane` resource has been removed. The `talos_machine_configuration` data source should be used instead.
107 |
108 | For example if the following resource was used:
109 |
110 | ```hcl
111 | resource "talos_machine_secrets" "this" {}
112 |
113 | resource "talos_client_configuration" "this" {
114 | cluster_name = "example-cluster"
115 | machine_secrets = talos_machine_secrets.this.machine_secrets
116 | }
117 |
118 | resource "talos_machine_configuration_controlplane" "this" {
119 | cluster_name = "example-cluster"
120 | cluster_endpoint = "https://10.5.0.2:6443"
121 | machine_secrets = talos_machine_secrets.this.machine_secrets
122 | }
123 |
124 | resource "talos_machine_configuration_apply" "this" {
125 | talos_config = talos_client_configuration.this.talos_config
126 | machine_configuration = talos_machine_configuration_controlplane.this.machine_config
127 | node = "10.5.0.2"
128 | endpoint = "10.5.0.2"
129 | }
130 | ```
131 |
132 | `talos_machine_configuration_controlplane` resource should be first removed from the state:
133 |
134 | ```bash
135 | terraform state rm talos_machine_configuration_controlplane.cp
136 | ```
137 |
138 | and the code should be updated to:
139 |
140 | ```hcl
141 | resource "talos_machine_secrets" "machine_secrets" {}
142 |
143 | data "talos_machine_configuration" "this" {
144 | cluster_name = "example-cluster"
145 | cluster_endpoint = "https://10.5.0.2:6443"
146 | machine_type = "controlplane"
147 | talos_version = talos_machine_secrets.this.talos_version
148 | machine_secrets = talos_machine_secrets.this.machine_secrets
149 | }
150 |
151 | resource "talos_machine_configuration_apply" "this" {
152 | client_configuration = talos_machine_secrets.this.client_configuration
153 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
154 | node = "10.5.0.2"
155 | }
156 | ```
157 |
158 | ### Upgrading `talos_machine_configuration_worker` resource
159 |
160 | The `talos_machine_configuration_worker` resource has been removed. The `talos_machine_configuration` data source should be used instead.
161 |
162 | For example if the following resource was used:
163 |
164 | ```hcl
165 | resource "talos_machine_secrets" "this" {}
166 |
167 | resource "talos_client_configuration" "this" {
168 | cluster_name = "example-cluster"
169 | machine_secrets = talos_machine_secrets.this.machine_secrets
170 | }
171 |
172 | resource "talos_machine_configuration_worker" "this" {
173 | cluster_name = "example-cluster"
174 | cluster_endpoint = "https://10.5.0.2:6443"
175 | machine_secrets = talos_machine_secrets.this.machine_secrets
176 | }
177 |
178 | resource "talos_machine_configuration_apply" "this" {
179 | talos_config = talos_client_configuration.this.talos_config
180 | machine_configuration = talos_machine_configuration_worker.this.machine_config
181 | node = "10.5.0.3"
182 | endpoint = "10.5.0.3"
183 | }
184 | ```
185 |
186 | `talos_machine_configuration_worker` resource should be first removed from the state:
187 |
188 | ```bash
189 | terraform state rm talos_machine_configuration_worker.worker
190 | ```
191 |
192 | and the code should be updated to:
193 |
194 | ```hcl
195 | resource "talos_machine_secrets" "machine_secrets" {}
196 |
197 | data "talos_machine_configuration" "this" {
198 | cluster_name = "example-cluster"
199 | cluster_endpoint = "https://10.5.0.2:6443"
200 | machine_type = "worker"
201 | talos_version = talos_machine_secrets.this.talos_version
202 | machine_secrets = talos_machine_secrets.this.machine_secrets
203 | }
204 |
205 | resource "talos_machine_configuration_apply" "this" {
206 | client_configuration = talos_machine_secrets.this.client_configuration
207 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
208 | node = "10.5.0.3"
209 | }
210 | ```
211 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "Provider: Talos"
3 | description: |-
4 | The Talos provider is used to manage a Talos cluster config generation and initial setup.
5 | ---
6 |
7 | # Talos Provider
8 |
9 | Talos provider allows to generate configs for a Talos cluster and apply them to the nodes, bootstrap nodes, check cluster health, and retrieve `kubeconfig` and `talosconfig`.
10 |
11 | Complete usages for this provider across a variety of environments can be found [here](https://github.com/siderolabs/contrib/tree/main/examples/terraform).
12 |
--------------------------------------------------------------------------------
/docs/resources/cluster_kubeconfig.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "talos_cluster_kubeconfig Resource - talos"
3 | subcategory: ""
4 | description: |-
5 | Retrieves the kubeconfig for a Talos cluster
6 | ---
7 |
8 | # talos_cluster_kubeconfig (Resource)
9 |
10 | Retrieves the kubeconfig for a Talos cluster
11 |
12 | ## Example Usage
13 |
14 | ```terraform
15 | resource "talos_machine_secrets" "this" {}
16 |
17 | data "talos_machine_configuration" "this" {
18 | cluster_name = "example-cluster"
19 | machine_type = "controlplane"
20 | cluster_endpoint = "https://cluster.local:6443"
21 | machine_secrets = talos_machine_secrets.this.machine_secrets
22 | }
23 |
24 | data "talos_client_configuration" "this" {
25 | cluster_name = "example-cluster"
26 | client_configuration = talos_machine_secrets.this.client_configuration
27 | nodes = ["10.5.0.2"]
28 | }
29 |
30 | resource "talos_machine_configuration_apply" "this" {
31 | client_configuration = talos_machine_secrets.this.client_configuration
32 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
33 | node = "10.5.0.2"
34 | config_patches = [
35 | yamlencode({
36 | machine = {
37 | install = {
38 | disk = "/dev/sdd"
39 | }
40 | }
41 | })
42 | ]
43 | }
44 |
45 | resource "talos_machine_bootstrap" "this" {
46 | depends_on = [
47 | talos_machine_configuration_apply.this
48 | ]
49 | node = "10.5.0.2"
50 | client_configuration = talos_machine_secrets.this.client_configuration
51 | }
52 |
53 |
54 | resource "talos_cluster_kubeconfig" "this" {
55 | depends_on = [
56 | talos_machine_bootstrap.this
57 | ]
58 | client_configuration = talos_machine_secrets.this.client_configuration
59 | node = "10.5.0.2"
60 | }
61 | ```
62 |
63 | ## Schema
64 |
65 | ### Required
66 |
67 | - `client_configuration` (Attributes) The client configuration data (see [below for nested schema](#nestedatt--client_configuration))
68 | - `node` (String) controlplane node to retrieve the kubeconfig from
69 |
70 | ### Optional
71 |
72 | - `certificate_renewal_duration` (String) The duration in hours before the certificate is renewed, defaults to 720h. Must be a valid duration string
73 | - `endpoint` (String) endpoint to use for the talosclient. If not set, the node value will be used
74 | - `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
75 |
76 | ### Read-Only
77 |
78 | - `id` (String) The ID of this resource.
79 | - `kubeconfig_raw` (String, Sensitive) The raw kubeconfig
80 | - `kubernetes_client_configuration` (Attributes) The kubernetes client configuration (see [below for nested schema](#nestedatt--kubernetes_client_configuration))
81 |
82 |
83 | ### Nested Schema for `client_configuration`
84 |
85 | Required:
86 |
87 | - `ca_certificate` (String) The client CA certificate
88 | - `client_certificate` (String) The client certificate
89 | - `client_key` (String, Sensitive) The client key
90 |
91 |
92 |
93 | ### Nested Schema for `timeouts`
94 |
95 | Optional:
96 |
97 | - `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
98 | - `update` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
99 |
100 |
101 |
102 | ### Nested Schema for `kubernetes_client_configuration`
103 |
104 | Read-Only:
105 |
106 | - `ca_certificate` (String) The kubernetes CA certificate
107 | - `client_certificate` (String) The kubernetes client certificate
108 | - `client_key` (String, Sensitive) The kubernetes client key
109 | - `host` (String) The kubernetes host
110 |
111 |
--------------------------------------------------------------------------------
/docs/resources/image_factory_schematic.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "talos_image_factory_schematic Resource - talos"
3 | subcategory: ""
4 | description: |-
5 | The image factory schematic resource allows you to create a schematic for a Talos image.
6 | ---
7 |
8 | # talos_image_factory_schematic (Resource)
9 |
10 | The image factory schematic resource allows you to create a schematic for a Talos image.
11 |
12 | ## Example Usage
13 |
14 | ```terraform
15 | provider "talos" {}
16 |
17 | data "talos_image_factory_extensions_versions" "this" {
18 | # get the latest talos version
19 | talos_version = "v1.7.5"
20 | filters = {
21 | names = [
22 | "amdgpu",
23 | "tailscale",
24 | ]
25 | }
26 | }
27 |
28 | resource "talos_image_factory_schematic" "this" {
29 | schematic = yamlencode(
30 | {
31 | customization = {
32 | systemExtensions = {
33 | officialExtensions = data.talos_image_factory_extensions_versions.this.extensions_info.*.name
34 | }
35 | }
36 | }
37 | )
38 | }
39 |
40 | output "schematic_id" {
41 | value = talos_image_factory_schematic.this.id
42 | }
43 | ```
44 |
45 | ## Schema
46 |
47 | ### Optional
48 |
49 | - `schematic` (String) The schematic yaml respresentation to generate the image.
50 |
51 | If not set, a vanilla Talos image schematic will be generated.
52 |
53 | > Refer to [image-factory](https://github.com/siderolabs/image-factory?tab=readme-ov-file#post-schematics) for the schema.
54 |
55 | ### Read-Only
56 |
57 | - `id` (String) The unique ID of the schematic, returned from Image Factory.
58 |
59 |
--------------------------------------------------------------------------------
/docs/resources/machine_bootstrap.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "talos_machine_bootstrap Resource - talos"
3 | subcategory: ""
4 | description: |-
5 | The machine bootstrap resource allows you to bootstrap a Talos node.
6 | ---
7 |
8 | # talos_machine_bootstrap (Resource)
9 |
10 | The machine bootstrap resource allows you to bootstrap a Talos node.
11 |
12 | ## Example Usage
13 |
14 | ```terraform
15 | resource "talos_machine_secrets" "this" {}
16 |
17 | data "talos_machine_configuration" "this" {
18 | cluster_name = "example-cluster"
19 | machine_type = "controlplane"
20 | cluster_endpoint = "https://cluster.local:6443"
21 | machine_secrets = talos_machine_secrets.this.machine_secrets
22 | }
23 |
24 | data "talos_client_configuration" "this" {
25 | cluster_name = "example-cluster"
26 | client_configuration = talos_machine_secrets.this.client_configuration
27 | nodes = ["10.5.0.2"]
28 | }
29 |
30 | resource "talos_machine_configuration_apply" "this" {
31 | client_configuration = talos_machine_secrets.this.client_configuration
32 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
33 | node = "10.5.0.2"
34 | config_patches = [
35 | yamlencode({
36 | machine = {
37 | install = {
38 | disk = "/dev/sdd"
39 | }
40 | }
41 | })
42 | ]
43 | }
44 |
45 | resource "talos_machine_bootstrap" "this" {
46 | depends_on = [
47 | talos_machine_configuration_apply.this
48 | ]
49 | node = "10.5.0.2"
50 | client_configuration = talos_machine_secrets.this.client_configuration
51 | }
52 | ```
53 |
54 | ## Schema
55 |
56 | ### Required
57 |
58 | - `client_configuration` (Attributes) The client configuration data (see [below for nested schema](#nestedatt--client_configuration))
59 | - `node` (String) The name of the node to bootstrap
60 |
61 | ### Optional
62 |
63 | - `endpoint` (String) The endpoint of the machine to bootstrap
64 | - `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
65 |
66 | ### Read-Only
67 |
68 | - `id` (String) This is a unique identifier for the machine
69 |
70 |
71 | ### Nested Schema for `client_configuration`
72 |
73 | Required:
74 |
75 | - `ca_certificate` (String) The client CA certificate
76 | - `client_certificate` (String) The client certificate
77 | - `client_key` (String, Sensitive) The client key
78 |
79 |
80 |
81 | ### Nested Schema for `timeouts`
82 |
83 | Optional:
84 |
85 | - `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
86 | ## Import
87 |
88 | Import is supported using the following syntax:
89 |
90 | ```terraform
91 | # machine bootstrap can be imported to let terraform know that the machine is already bootstrapped
92 | terraform import talos_machine_bootstrap.this
93 | ```
94 |
--------------------------------------------------------------------------------
/docs/resources/machine_configuration_apply.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "talos_machine_configuration_apply Resource - talos"
3 | subcategory: ""
4 | description: |-
5 | The machine configuration apply resource allows to apply machine configuration to a node
6 | ---
7 |
8 | # talos_machine_configuration_apply (Resource)
9 |
10 | The machine configuration apply resource allows to apply machine configuration to a node
11 |
12 | ## Example Usage
13 |
14 | ```terraform
15 | resource "talos_machine_secrets" "this" {}
16 |
17 | data "talos_machine_configuration" "this" {
18 | cluster_name = "example-cluster"
19 | machine_type = "controlplane"
20 | cluster_endpoint = "https://cluster.local:6443"
21 | machine_secrets = talos_machine_secrets.this.machine_secrets
22 | }
23 |
24 | data "talos_client_configuration" "this" {
25 | cluster_name = "example-cluster"
26 | client_configuration = talos_machine_secrets.this.client_configuration
27 | nodes = ["10.5.0.2"]
28 | }
29 |
30 | resource "talos_machine_configuration_apply" "this" {
31 | client_configuration = talos_machine_secrets.this.client_configuration
32 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
33 | node = "10.5.0.2"
34 | config_patches = [
35 | yamlencode({
36 | machine = {
37 | install = {
38 | disk = "/dev/sdd"
39 | }
40 | }
41 | })
42 | ]
43 | }
44 | ```
45 |
46 | ## Schema
47 |
48 | ### Required
49 |
50 | - `client_configuration` (Attributes) The client configuration data (see [below for nested schema](#nestedatt--client_configuration))
51 | - `machine_configuration_input` (String, Sensitive) The machine configuration to apply
52 | - `node` (String) The name of the node to bootstrap
53 |
54 | ### Optional
55 |
56 | - `apply_mode` (String) The mode of the apply operation
57 | - `config_patches` (List of String) The list of config patches to apply
58 | - `endpoint` (String) The endpoint of the machine to bootstrap
59 | - `on_destroy` (Attributes) Actions to be taken on destroy, if *reset* is not set this is a no-op.
60 |
61 | > Note: Any changes to *on_destroy* block has to be applied first by running *terraform apply* first,
62 | then a subsequent *terraform destroy* for the changes to take effect due to limitations in Terraform provider framework. (see [below for nested schema](#nestedatt--on_destroy))
63 | - `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
64 |
65 | ### Read-Only
66 |
67 | - `id` (String) This is a unique identifier for the machine
68 | - `machine_configuration` (String, Sensitive) The generated machine configuration after applying patches
69 |
70 |
71 | ### Nested Schema for `client_configuration`
72 |
73 | Required:
74 |
75 | - `ca_certificate` (String) The client CA certificate
76 | - `client_certificate` (String) The client certificate
77 | - `client_key` (String, Sensitive) The client key
78 |
79 |
80 |
81 | ### Nested Schema for `on_destroy`
82 |
83 | Optional:
84 |
85 | - `graceful` (Boolean) Graceful indicates whether node should leave etcd before the upgrade, it also enforces etcd checks before leaving. Default true
86 | - `reboot` (Boolean) Reboot indicates whether node should reboot or halt after resetting. Default false
87 | - `reset` (Boolean) Reset the machine to the initial state (STATE and EPHEMERAL will be wiped). Default false
88 |
89 |
90 |
91 | ### Nested Schema for `timeouts`
92 |
93 | Optional:
94 |
95 | - `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
96 | - `delete` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs.
97 | - `update` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
98 |
99 |
--------------------------------------------------------------------------------
/docs/resources/machine_secrets.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "talos_machine_secrets Resource - talos"
3 | subcategory: ""
4 | description: |-
5 | Generate machine secrets for Talos cluster.
6 | ---
7 |
8 | # talos_machine_secrets (Resource)
9 |
10 | Generate machine secrets for Talos cluster.
11 |
12 | ## Example Usage
13 |
14 | ```terraform
15 | resource "talos_machine_secrets" "machine_secrets" {}
16 | ```
17 |
18 | ## Schema
19 |
20 | ### Optional
21 |
22 | - `talos_version` (String) The version of talos features to use in generated machine configuration
23 |
24 | ### Read-Only
25 |
26 | - `client_configuration` (Attributes) The generated client configuration data (see [below for nested schema](#nestedatt--client_configuration))
27 | - `id` (String) The computed ID of the Talos cluster
28 | - `machine_secrets` (Attributes) The secrets for the talos cluster (see [below for nested schema](#nestedatt--machine_secrets))
29 |
30 |
31 | ### Nested Schema for `client_configuration`
32 |
33 | Read-Only:
34 |
35 | - `ca_certificate` (String) The client CA certificate
36 | - `client_certificate` (String) The client certificate
37 | - `client_key` (String, Sensitive) The client key
38 |
39 |
40 |
41 | ### Nested Schema for `machine_secrets`
42 |
43 | Read-Only:
44 |
45 | - `certs` (Attributes) (see [below for nested schema](#nestedatt--machine_secrets--certs))
46 | - `cluster` (Attributes) The cluster secrets (see [below for nested schema](#nestedatt--machine_secrets--cluster))
47 | - `secrets` (Attributes) kubernetes cluster secrets (see [below for nested schema](#nestedatt--machine_secrets--secrets))
48 | - `trustdinfo` (Attributes) trustd secrets (see [below for nested schema](#nestedatt--machine_secrets--trustdinfo))
49 |
50 |
51 | ### Nested Schema for `machine_secrets.certs`
52 |
53 | Read-Only:
54 |
55 | - `etcd` (Attributes) The certificate and key pair (see [below for nested schema](#nestedatt--machine_secrets--certs--etcd))
56 | - `k8s` (Attributes) The certificate and key pair (see [below for nested schema](#nestedatt--machine_secrets--certs--k8s))
57 | - `k8s_aggregator` (Attributes) The certificate and key pair (see [below for nested schema](#nestedatt--machine_secrets--certs--k8s_aggregator))
58 | - `k8s_serviceaccount` (Attributes) The service account secrets (see [below for nested schema](#nestedatt--machine_secrets--certs--k8s_serviceaccount))
59 | - `os` (Attributes) The certificate and key pair (see [below for nested schema](#nestedatt--machine_secrets--certs--os))
60 |
61 |
62 | ### Nested Schema for `machine_secrets.certs.etcd`
63 |
64 | Read-Only:
65 |
66 | - `cert` (String) certificate data
67 | - `key` (String, Sensitive) key data
68 |
69 |
70 |
71 | ### Nested Schema for `machine_secrets.certs.k8s`
72 |
73 | Read-Only:
74 |
75 | - `cert` (String) certificate data
76 | - `key` (String, Sensitive) key data
77 |
78 |
79 |
80 | ### Nested Schema for `machine_secrets.certs.k8s_aggregator`
81 |
82 | Read-Only:
83 |
84 | - `cert` (String) certificate data
85 | - `key` (String, Sensitive) key data
86 |
87 |
88 |
89 | ### Nested Schema for `machine_secrets.certs.k8s_serviceaccount`
90 |
91 | Read-Only:
92 |
93 | - `key` (String, Sensitive) The service account key
94 |
95 |
96 |
97 | ### Nested Schema for `machine_secrets.certs.os`
98 |
99 | Read-Only:
100 |
101 | - `cert` (String) certificate data
102 | - `key` (String, Sensitive) key data
103 |
104 |
105 |
106 |
107 | ### Nested Schema for `machine_secrets.cluster`
108 |
109 | Read-Only:
110 |
111 | - `id` (String) The cluster ID
112 | - `secret` (String, Sensitive) The cluster secret
113 |
114 |
115 |
116 | ### Nested Schema for `machine_secrets.secrets`
117 |
118 | Read-Only:
119 |
120 | - `aescbc_encryption_secret` (String, Sensitive) The AES-CBC encryption secret
121 | - `bootstrap_token` (String, Sensitive) The bootstrap token
122 | - `secretbox_encryption_secret` (String, Sensitive) The secretbox encryption secret
123 |
124 |
125 |
126 | ### Nested Schema for `machine_secrets.trustdinfo`
127 |
128 | Read-Only:
129 |
130 | - `token` (String, Sensitive) The trustd token
131 | ## Import
132 |
133 | Import is supported using the following syntax:
134 |
135 | ```terraform
136 | # machine secrets can be imported from an existing secrets file
137 | terraform import talos_machine_secrets.this
138 | ```
139 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Talos provider examples
2 |
3 | This directory contains a set of examples on using the Talos provider.
4 |
--------------------------------------------------------------------------------
/examples/data-sources/talos_client_configuration/data-source.tf:
--------------------------------------------------------------------------------
1 | resource "talos_machine_secrets" "this" {}
2 |
3 | data "talos_client_configuration" "this" {
4 | cluster_name = "example-cluster"
5 | client_configuration = talos_machine_secrets.this.client_configuration
6 | nodes = ["10.5.0.2"]
7 | }
8 |
--------------------------------------------------------------------------------
/examples/data-sources/talos_cluster_kubeconfig/data-source.tf:
--------------------------------------------------------------------------------
1 | resource "talos_machine_secrets" "this" {}
2 |
3 | data "talos_machine_configuration" "this" {
4 | cluster_name = "example-cluster"
5 | machine_type = "controlplane"
6 | cluster_endpoint = "https://cluster.local:6443"
7 | machine_secrets = talos_machine_secrets.this.machine_secrets
8 | }
9 |
10 | data "talos_client_configuration" "this" {
11 | cluster_name = "example-cluster"
12 | client_configuration = talos_machine_secrets.this.client_configuration
13 | nodes = ["10.5.0.2"]
14 | }
15 |
16 | resource "talos_machine_configuration_apply" "this" {
17 | client_configuration = talos_machine_secrets.this.client_configuration
18 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
19 | node = "10.5.0.2"
20 | config_patches = [
21 | yamlencode({
22 | machine = {
23 | install = {
24 | disk = "/dev/sdd"
25 | }
26 | }
27 | })
28 | ]
29 | }
30 |
31 | resource "talos_machine_bootstrap" "this" {
32 | depends_on = [
33 | talos_machine_configuration_apply.this
34 | ]
35 | node = "10.5.0.2"
36 | client_configuration = talos_machine_secrets.this.client_configuration
37 | }
38 |
39 |
40 | data "talos_cluster_kubeconfig" "this" {
41 | depends_on = [
42 | talos_machine_bootstrap.this
43 | ]
44 | client_configuration = talos_machine_secrets.this.client_configuration
45 | node = "10.5.0.2"
46 | }
47 |
--------------------------------------------------------------------------------
/examples/data-sources/talos_image_factory_extensions_versions/data-source.tf:
--------------------------------------------------------------------------------
1 | provider "talos" {}
2 |
3 | data "talos_image_factory_extensions_versions" "this" {
4 | # get the latest talos version
5 | talos_version = "v1.7.5"
6 | filters = {
7 | names = [
8 | "amdgpu",
9 | "tailscale",
10 | ]
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/examples/data-sources/talos_image_factory_overlays_versions/data-source.tf:
--------------------------------------------------------------------------------
1 | provider "talos" {}
2 |
3 | data "talos_image_factory_overlays_versions" "this" {
4 | # get the latest talos version
5 | talos_version = "v1.7.5"
6 | filters = {
7 | name = "rock4cplus"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/examples/data-sources/talos_image_factory_urls/data-source.tf:
--------------------------------------------------------------------------------
1 | data "talos_image_factory_urls" "this" {
2 | talos_version = "v1.7.5"
3 | schematic_id = "376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba"
4 | platform = "metal"
5 | }
6 |
7 | output "installer_image" {
8 | value = data.talos_image_factory_urls.this.urls.installer
9 | }
10 |
--------------------------------------------------------------------------------
/examples/data-sources/talos_image_factory_versions/data-source.tf:
--------------------------------------------------------------------------------
1 | provider "talos" {}
2 |
3 | data "talos_image_factory_versions" "this" {}
4 |
5 | output "latest" {
6 | value = element(data.talos_image_factory_versions.this.talos_versions, length(data.talos_image_factory_versions.this.talos_versions) - 1)
7 | }
8 |
--------------------------------------------------------------------------------
/examples/data-sources/talos_machine_configuration/data-source.tf:
--------------------------------------------------------------------------------
1 | resource "talos_machine_secrets" "this" {}
2 |
3 | data "talos_machine_configuration" "this" {
4 | cluster_name = "example-cluster"
5 | machine_type = "controlplane"
6 | cluster_endpoint = "https://cluster.local:6443"
7 | machine_secrets = talos_machine_secrets.this.machine_secrets
8 | }
9 |
--------------------------------------------------------------------------------
/examples/data-sources/talos_machine_disks/data-source.tf:
--------------------------------------------------------------------------------
1 | resource "talos_machine_secrets" "this" {}
2 |
3 | data "talos_machine_disks" "this" {
4 | client_configuration = talos_machine_secrets.this.client_configuration
5 | node = "10.5.0.2"
6 | selector = "disk.size > 6u * GB"
7 | }
8 |
9 | # for example, this could be used to pass in a list of disks to rook-ceph
10 | output "nvme_disks" {
11 | value = data.talos_machine_disks.this.disks.*.name
12 | }
13 |
--------------------------------------------------------------------------------
/examples/resources/talos_cluster_kubeconfig/resource.tf:
--------------------------------------------------------------------------------
1 | resource "talos_machine_secrets" "this" {}
2 |
3 | data "talos_machine_configuration" "this" {
4 | cluster_name = "example-cluster"
5 | machine_type = "controlplane"
6 | cluster_endpoint = "https://cluster.local:6443"
7 | machine_secrets = talos_machine_secrets.this.machine_secrets
8 | }
9 |
10 | data "talos_client_configuration" "this" {
11 | cluster_name = "example-cluster"
12 | client_configuration = talos_machine_secrets.this.client_configuration
13 | nodes = ["10.5.0.2"]
14 | }
15 |
16 | resource "talos_machine_configuration_apply" "this" {
17 | client_configuration = talos_machine_secrets.this.client_configuration
18 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
19 | node = "10.5.0.2"
20 | config_patches = [
21 | yamlencode({
22 | machine = {
23 | install = {
24 | disk = "/dev/sdd"
25 | }
26 | }
27 | })
28 | ]
29 | }
30 |
31 | resource "talos_machine_bootstrap" "this" {
32 | depends_on = [
33 | talos_machine_configuration_apply.this
34 | ]
35 | node = "10.5.0.2"
36 | client_configuration = talos_machine_secrets.this.client_configuration
37 | }
38 |
39 |
40 | resource "talos_cluster_kubeconfig" "this" {
41 | depends_on = [
42 | talos_machine_bootstrap.this
43 | ]
44 | client_configuration = talos_machine_secrets.this.client_configuration
45 | node = "10.5.0.2"
46 | }
47 |
--------------------------------------------------------------------------------
/examples/resources/talos_image_factory_schematic/resource.tf:
--------------------------------------------------------------------------------
1 | provider "talos" {}
2 |
3 | data "talos_image_factory_extensions_versions" "this" {
4 | # get the latest talos version
5 | talos_version = "v1.7.5"
6 | filters = {
7 | names = [
8 | "amdgpu",
9 | "tailscale",
10 | ]
11 | }
12 | }
13 |
14 | resource "talos_image_factory_schematic" "this" {
15 | schematic = yamlencode(
16 | {
17 | customization = {
18 | systemExtensions = {
19 | officialExtensions = data.talos_image_factory_extensions_versions.this.extensions_info.*.name
20 | }
21 | }
22 | }
23 | )
24 | }
25 |
26 | output "schematic_id" {
27 | value = talos_image_factory_schematic.this.id
28 | }
29 |
--------------------------------------------------------------------------------
/examples/resources/talos_machine_bootstrap/import.sh:
--------------------------------------------------------------------------------
1 | # machine bootstrap can be imported to let terraform know that the machine is already bootstrapped
2 | terraform import talos_machine_bootstrap.this
3 |
--------------------------------------------------------------------------------
/examples/resources/talos_machine_bootstrap/resource.tf:
--------------------------------------------------------------------------------
1 | resource "talos_machine_secrets" "this" {}
2 |
3 | data "talos_machine_configuration" "this" {
4 | cluster_name = "example-cluster"
5 | machine_type = "controlplane"
6 | cluster_endpoint = "https://cluster.local:6443"
7 | machine_secrets = talos_machine_secrets.this.machine_secrets
8 | }
9 |
10 | data "talos_client_configuration" "this" {
11 | cluster_name = "example-cluster"
12 | client_configuration = talos_machine_secrets.this.client_configuration
13 | nodes = ["10.5.0.2"]
14 | }
15 |
16 | resource "talos_machine_configuration_apply" "this" {
17 | client_configuration = talos_machine_secrets.this.client_configuration
18 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
19 | node = "10.5.0.2"
20 | config_patches = [
21 | yamlencode({
22 | machine = {
23 | install = {
24 | disk = "/dev/sdd"
25 | }
26 | }
27 | })
28 | ]
29 | }
30 |
31 | resource "talos_machine_bootstrap" "this" {
32 | depends_on = [
33 | talos_machine_configuration_apply.this
34 | ]
35 | node = "10.5.0.2"
36 | client_configuration = talos_machine_secrets.this.client_configuration
37 | }
38 |
--------------------------------------------------------------------------------
/examples/resources/talos_machine_configuration_apply/resource.tf:
--------------------------------------------------------------------------------
1 | resource "talos_machine_secrets" "this" {}
2 |
3 | data "talos_machine_configuration" "this" {
4 | cluster_name = "example-cluster"
5 | machine_type = "controlplane"
6 | cluster_endpoint = "https://cluster.local:6443"
7 | machine_secrets = talos_machine_secrets.this.machine_secrets
8 | }
9 |
10 | data "talos_client_configuration" "this" {
11 | cluster_name = "example-cluster"
12 | client_configuration = talos_machine_secrets.this.client_configuration
13 | nodes = ["10.5.0.2"]
14 | }
15 |
16 | resource "talos_machine_configuration_apply" "this" {
17 | client_configuration = talos_machine_secrets.this.client_configuration
18 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
19 | node = "10.5.0.2"
20 | config_patches = [
21 | yamlencode({
22 | machine = {
23 | install = {
24 | disk = "/dev/sdd"
25 | }
26 | }
27 | })
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/examples/resources/talos_machine_secrets/import.sh:
--------------------------------------------------------------------------------
1 | # machine secrets can be imported from an existing secrets file
2 | terraform import talos_machine_secrets.this
3 |
--------------------------------------------------------------------------------
/examples/resources/talos_machine_secrets/resource.tf:
--------------------------------------------------------------------------------
1 | resource "talos_machine_secrets" "machine_secrets" {}
2 |
--------------------------------------------------------------------------------
/hack/release.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
4 | #
5 | # Generated on 2024-08-29T12:20:48Z by kres b5ca957.
6 |
7 | set -e
8 |
9 | RELEASE_TOOL_IMAGE="ghcr.io/siderolabs/release-tool:latest"
10 |
11 | function release-tool {
12 | docker pull "${RELEASE_TOOL_IMAGE}" >/dev/null
13 | docker run --rm -w /src -v "${PWD}":/src:ro "${RELEASE_TOOL_IMAGE}" -l -d -n -t "${1}" ./hack/release.toml
14 | }
15 |
16 | function changelog {
17 | if [ "$#" -eq 1 ]; then
18 | (release-tool ${1}; echo; cat CHANGELOG.md) > CHANGELOG.md- && mv CHANGELOG.md- CHANGELOG.md
19 | else
20 | echo 1>&2 "Usage: $0 changelog [tag]"
21 | exit 1
22 | fi
23 | }
24 |
25 | function release-notes {
26 | release-tool "${2}" > "${1}"
27 | }
28 |
29 | function cherry-pick {
30 | if [ $# -ne 2 ]; then
31 | echo 1>&2 "Usage: $0 cherry-pick "
32 | exit 1
33 | fi
34 |
35 | git checkout $2
36 | git fetch
37 | git rebase upstream/$2
38 | git cherry-pick -x $1
39 | }
40 |
41 | function commit {
42 | if [ $# -ne 1 ]; then
43 | echo 1>&2 "Usage: $0 commit "
44 | exit 1
45 | fi
46 |
47 | if is_on_main_branch; then
48 | update_license_files
49 | fi
50 |
51 | git commit -s -m "release($1): prepare release" -m "This is the official $1 release."
52 | }
53 |
54 | function is_on_main_branch {
55 | main_remotes=("upstream" "origin")
56 | branch_names=("main" "master")
57 | current_branch=$(git rev-parse --abbrev-ref HEAD)
58 |
59 | echo "Check current branch: $current_branch"
60 |
61 | for remote in "${main_remotes[@]}"; do
62 | echo "Fetch remote $remote..."
63 |
64 | if ! git fetch --quiet "$remote" &>/dev/null; then
65 | echo "Failed to fetch $remote, skip..."
66 |
67 | continue
68 | fi
69 |
70 | for branch_name in "${branch_names[@]}"; do
71 | if ! git rev-parse --verify "$branch_name" &>/dev/null; then
72 | echo "Branch $branch_name does not exist, skip..."
73 |
74 | continue
75 | fi
76 |
77 | echo "Branch $remote/$branch_name exists, comparing..."
78 |
79 | merge_base=$(git merge-base "$current_branch" "$remote/$branch_name")
80 | latest_main=$(git rev-parse "$remote/$branch_name")
81 |
82 | if [ "$merge_base" = "$latest_main" ]; then
83 | echo "Current branch is up-to-date with $remote/$branch_name"
84 |
85 | return 0
86 | else
87 | echo "Current branch is not on $remote/$branch_name"
88 |
89 | return 1
90 | fi
91 | done
92 | done
93 |
94 | echo "No main or master branch found on any remote"
95 |
96 | return 1
97 | }
98 |
99 | function update_license_files {
100 | script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
101 | parent_dir="$(dirname "$script_dir")"
102 | current_year=$(date +"%Y")
103 | change_date=$(date -v+4y +"%Y-%m-%d" 2>/dev/null || date -d "+4 years" +"%Y-%m-%d" 2>/dev/null || date --date="+4 years" +"%Y-%m-%d")
104 |
105 | # Find LICENSE and .kres.yaml files recursively in the parent directory (project root)
106 | find "$parent_dir" \( -name "LICENSE" -o -name ".kres.yaml" \) -type f | while read -r file; do
107 | temp_file="${file}.tmp"
108 |
109 | if [[ $file == *"LICENSE" ]]; then
110 | if grep -q "^Business Source License" "$file"; then
111 | sed -e "s/The Licensed Work is (c) [0-9]\{4\}/The Licensed Work is (c) $current_year/" \
112 | -e "s/Change Date: [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/Change Date: $change_date/" \
113 | "$file" >"$temp_file"
114 | else
115 | continue # Not a Business Source License file
116 | fi
117 | elif [[ $file == *".kres.yaml" ]]; then
118 | sed -E 's/^([[:space:]]*)ChangeDate:.*$/\1ChangeDate: "'"$change_date"'"/' "$file" >"$temp_file"
119 | fi
120 |
121 | # Check if the file has changed
122 | if ! cmp -s "$file" "$temp_file"; then
123 | mv "$temp_file" "$file"
124 | echo "Updated: $file"
125 | git add "$file"
126 | else
127 | echo "No changes: $file"
128 | rm "$temp_file"
129 | fi
130 | done
131 | }
132 |
133 | if declare -f "$1" > /dev/null
134 | then
135 | cmd="$1"
136 | shift
137 | $cmd "$@"
138 | else
139 | cat < ", os.Args[0])
49 | }
50 |
51 | resourceType := os.Args[1]
52 | resourceName := strings.ToLower(strings.Split(resourceType, ".")[1])
53 |
54 | resource, ok := resourceMaps()[resourceType]
55 | if !ok {
56 | log.Fatalf("unknown type: %s", resourceType)
57 | }
58 |
59 | blockDiskSpecStruct := reflect.TypeOf(resource)
60 |
61 | g.Printf("type %s struct {\n", resourceName)
62 | for i := range blockDiskSpecStruct.NumField() {
63 | tfType, err := mapGoTypesToTFTypes(blockDiskSpecStruct.Field(i).Type)
64 | if err != nil {
65 | log.Fatalf("failed to map type %s: %v", blockDiskSpecStruct.Field(i).Type.Name(), err)
66 | }
67 |
68 | g.Printf("\t%s %s `tfsdk:\"%s\"`\n",
69 | blockDiskSpecStruct.Field(i).Name,
70 | tfType,
71 | strings.ReplaceAll(blockDiskSpecStruct.Field(i).Tag.Get("yaml"), ",omitempty", ""),
72 | )
73 |
74 | }
75 | g.Printf("}\n")
76 | g.Printf("\n")
77 |
78 | g.Printf("var %sAttributes = map[string]schema.Attribute{\n", resourceName)
79 | for i := 0; i < blockDiskSpecStruct.NumField(); i++ {
80 | attributeType, err := mapGoTypesToTFAttributeSpec(blockDiskSpecStruct.Field(i).Type)
81 | if err != nil {
82 | log.Fatalf("failed to map type %s: %v", blockDiskSpecStruct.Field(i).Type.Name(), err)
83 | }
84 |
85 | g.Printf("\t\"%s\": %s,\n",
86 | strings.ReplaceAll(blockDiskSpecStruct.Field(i).Tag.Get("yaml"), ",omitempty", ""),
87 | attributeType,
88 | )
89 | }
90 | g.Printf("}\n")
91 |
92 | g.Printf("func %sToTFTypes(%sSpec %s) %s {\n", resourceName, resourceName, resourceType, resourceName)
93 | g.Printf("\treturn %s{\n", resourceName)
94 |
95 | for i := 0; i < blockDiskSpecStruct.NumField(); i++ {
96 | tfType, err := mapStructTypeToTFType(blockDiskSpecStruct.Field(i), resourceName)
97 | if err != nil {
98 | log.Fatalf("failed to map type %s: %v", blockDiskSpecStruct.Field(i).Type.Name(), err)
99 | }
100 |
101 | g.Printf("\t\t%s: %s,\n",
102 | blockDiskSpecStruct.Field(i).Name,
103 | tfType,
104 | )
105 | }
106 |
107 | g.Printf("\t}\n")
108 | g.Printf("}\n")
109 |
110 | src := g.format()
111 |
112 | if err := os.WriteFile(fmt.Sprintf("%s_types.go", os.Args[2]), src, 0o644); err != nil {
113 | log.Fatalf("failed to write file: %v", err)
114 | }
115 | }
116 |
117 | type Generator struct {
118 | buf bytes.Buffer
119 | }
120 |
121 | func (g *Generator) Printf(format string, args ...interface{}) {
122 | fmt.Fprintf(&g.buf, format, args...)
123 | }
124 |
125 | // format returns the gofmt-ed contents of the Generator's buffer.
126 | func (g *Generator) format() []byte {
127 | src, err := format.Source(g.buf.Bytes())
128 | if err != nil {
129 | // Should never happen, but can arise when developing this code.
130 | // The user can compile the output to see the error.
131 | log.Printf("warning: internal error: invalid Go generated: %s", err)
132 | log.Printf("warning: compile the package to analyze the error")
133 | return g.buf.Bytes()
134 | }
135 |
136 | return src
137 | }
138 |
139 | func mapGoTypesToTFTypes(goType reflect.Type) (string, error) {
140 | // handle the case where the field is a slice
141 | if goType.Kind() == reflect.Slice {
142 | switch goType.Elem().Kind() {
143 | case reflect.String:
144 | return "types.List", nil
145 | default:
146 | return "", fmt.Errorf("unsupported slice type: %s", goType.Elem().Name())
147 | }
148 | }
149 |
150 | switch goType.Name() {
151 | case "string":
152 | return "types.String", nil
153 | case "uint", "uint64", "int", "int64":
154 | return "types.Int64", nil
155 | case "bool":
156 | return "types.Bool", nil
157 | default:
158 | return "", fmt.Errorf("unsupported type: %s", goType.Name())
159 | }
160 | }
161 |
162 | func mapGoTypesToTFAttributeSpec(goType reflect.Type) (string, error) {
163 | // handle the case where the field is a slice
164 | if goType.Kind() == reflect.Slice {
165 | switch goType.Elem().Kind() {
166 | case reflect.String:
167 | return `schema.ListAttribute{
168 | ElementType: types.StringType,
169 | Computed: true,
170 | }`, nil
171 | default:
172 | return "", fmt.Errorf("unsupported slice type: %s", goType.Elem().Name())
173 | }
174 | }
175 |
176 | switch goType.Name() {
177 | case "string":
178 | return `schema.StringAttribute{
179 | Computed: true,
180 | }`, nil
181 | case "uint", "uint64", "int", "int64":
182 | return `schema.Int64Attribute{
183 | Computed: true,
184 | }`, nil
185 | case "bool":
186 | return `schema.BoolAttribute{
187 | Computed: true,
188 | }`, nil
189 | default:
190 | return "", fmt.Errorf("unsupported type: %s", goType.Name())
191 | }
192 | }
193 |
194 | func mapStructTypeToTFType(structField reflect.StructField, resourceName string) (string, error) {
195 | // handle the case where the field is a slice
196 | if structField.Type.Kind() == reflect.Slice {
197 | switch structField.Type.Elem().Kind() {
198 | case reflect.String:
199 | return fmt.Sprintf(`types.ListValueMust(types.StringType, xslices.Map(%sSpec.%s, func(s string) attr.Value {
200 | return types.StringValue(s)
201 | }))`, resourceName, structField.Name), nil
202 | default:
203 | return "", fmt.Errorf("unsupported slice type: %s", structField.Type.Elem().Name())
204 | }
205 | }
206 |
207 | switch structField.Type.Name() {
208 | case "string":
209 | return fmt.Sprintf("types.StringValue(%sSpec.%s)", resourceName, structField.Name), nil
210 | case "uint", "uint64", "int", "int64":
211 | return fmt.Sprintf("types.Int64Value(int64(%sSpec.%s))", resourceName, structField.Name), nil
212 | case "bool":
213 | return fmt.Sprintf("types.BoolValue(%sSpec.%s)", resourceName, structField.Name), nil
214 | default:
215 | return "", fmt.Errorf("unsupported type: %s", structField.Type.Name())
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/pkg/talos/provider.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | // Package talos is a Terraform provider for Talos.
6 | package talos
7 |
8 | import (
9 | "context"
10 |
11 | "github.com/hashicorp/terraform-plugin-framework/datasource"
12 | "github.com/hashicorp/terraform-plugin-framework/provider"
13 | "github.com/hashicorp/terraform-plugin-framework/provider/schema"
14 | "github.com/hashicorp/terraform-plugin-framework/resource"
15 | "github.com/hashicorp/terraform-plugin-framework/types"
16 | "github.com/siderolabs/image-factory/pkg/client"
17 | )
18 |
19 | const (
20 | // ImageFactoryURL is the default URL of Image Factory.
21 | ImageFactoryURL = "https://factory.talos.dev"
22 | )
23 |
24 | // talosProvider is the provider implementation.
25 | type talosProvider struct{}
26 |
27 | type talosProviderModelV0 struct {
28 | ImageFactoryURL types.String `tfsdk:"image_factory_url"`
29 | }
30 |
31 | // New is a helper function to simplify provider server and testing implementation.
32 | func New() provider.Provider {
33 | return &talosProvider{}
34 | }
35 |
36 | // Metadata returns the provider type name.
37 | func (p *talosProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
38 | resp.TypeName = "talos"
39 | }
40 |
41 | // Schema defines the provider-level schema for configuration data.
42 | func (p *talosProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
43 | resp.Schema = schema.Schema{
44 | Attributes: map[string]schema.Attribute{
45 | "image_factory_url": schema.StringAttribute{
46 | Optional: true,
47 | Description: "The URL of Image Factory to generate schematics. If not set defaults to https://factory.talos.dev.",
48 | },
49 | },
50 | }
51 | }
52 |
53 | // Configure prepares a Talos client for data sources and resources.
54 | func (p *talosProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
55 | var config talosProviderModelV0
56 |
57 | resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
58 |
59 | if resp.Diagnostics.HasError() {
60 | return
61 | }
62 |
63 | imageFactoryURL := config.ImageFactoryURL.ValueString()
64 |
65 | if imageFactoryURL == "" && !config.ImageFactoryURL.IsUnknown() {
66 | imageFactoryURL = ImageFactoryURL
67 | }
68 |
69 | imageFactoryClient, err := client.New(imageFactoryURL)
70 | if err != nil {
71 | resp.Diagnostics.AddError("failed to create Image Factory client", err.Error())
72 |
73 | return
74 | }
75 |
76 | resp.DataSourceData = imageFactoryClient
77 | resp.ResourceData = imageFactoryClient
78 | }
79 |
80 | // DataSources defines the data sources implemented in the provider.
81 | func (p *talosProvider) DataSources(_ context.Context) []func() datasource.DataSource {
82 | return []func() datasource.DataSource{
83 | NewTalosMachineDisksDataSource,
84 | NewTalosMachineConfigurationDataSource,
85 | NewTalosClientConfigurationDataSource,
86 | NewTalosClusterHealthDataSource,
87 | NewTalosClusterKubeConfigDataSource,
88 | NewTalosImageFactoryVersionsDataSource,
89 | NewTalosImageFactoryExtensionsVersionsDataSource,
90 | NewTalosImageFactoryOverlaysVersionsDataSource,
91 | NewTalosImageFactoryURLSDataSource,
92 | }
93 | }
94 |
95 | // Resources defines the resources implemented in the provider.
96 | func (p *talosProvider) Resources(_ context.Context) []func() resource.Resource {
97 | return []func() resource.Resource{
98 | NewTalosMachineSecretsResource,
99 | NewTalosMachineConfigurationApplyResource,
100 | NewTalosMachineBootstrapResource,
101 | NewTalosClusterKubeConfigResource,
102 | NewTalosImageFactorySchematicResource,
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/pkg/talos/provider_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "fmt"
9 | "os"
10 | "strings"
11 | "text/template"
12 |
13 | "github.com/hashicorp/terraform-plugin-framework/providerserver"
14 | "github.com/hashicorp/terraform-plugin-go/tfprotov6"
15 | "github.com/siderolabs/talos/pkg/machinery/gendata"
16 |
17 | "github.com/siderolabs/terraform-provider-talos/pkg/talos"
18 | )
19 |
20 | // testAccProtoV6ProviderFactories are used to instantiate a provider during
21 | // acceptance testing. The factory function will be invoked for every Terraform
22 | // CLI command executed to create a provider server to which the CLI can
23 | // reattach.
24 | var testAccProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServer, error){
25 | "talos": providerserver.NewProtocol6WithError(talos.New()),
26 | }
27 |
28 | type dynamicConfig struct {
29 | Provider string
30 | ResourceName string
31 | IsoURL string
32 | CPUMode string
33 | WithApplyConfig bool
34 | WithBootstrap bool
35 | WithRetrieveKubeConfig bool
36 | WithClusterHealth bool
37 | }
38 |
39 | func (c *dynamicConfig) render() string {
40 | cpuMode := "host-passthrough"
41 | if os.Getenv("CI") != "" {
42 | cpuMode = "host-model"
43 | }
44 |
45 | c.CPUMode = cpuMode
46 |
47 | c.IsoURL = fmt.Sprintf("https://github.com/siderolabs/talos/releases/download/%s/metal-amd64.iso", gendata.VersionTag)
48 |
49 | configTemplate := `
50 | resource "talos_machine_secrets" "this" {}
51 |
52 | resource "libvirt_volume" "cp" {
53 | name = "{{ .ResourceName }}"
54 | size = 6442450944
55 | }
56 |
57 | resource "libvirt_domain" "cp" {
58 | name = "{{ .ResourceName }}"
59 | firmware = "/usr/share/OVMF/OVMF_CODE.fd"
60 | lifecycle {
61 | ignore_changes = [
62 | cpu,
63 | nvram,
64 | disk["url"],
65 | ]
66 | }
67 | cpu {
68 | mode = "{{ .CPUMode }}"
69 | }
70 | console {
71 | type = "pty"
72 | target_port = "0"
73 | }
74 | graphics {
75 | type = "vnc"
76 | listen_type = "address"
77 | }
78 | disk {
79 | url = "{{ .IsoURL }}"
80 | }
81 | disk {
82 | volume_id = libvirt_volume.cp.id
83 | }
84 | boot_device {
85 | dev = ["cdrom"]
86 | }
87 | network_interface {
88 | network_name = "default"
89 | wait_for_lease = true
90 | }
91 | vcpu = "2"
92 | memory = "4096"
93 | }
94 |
95 | {{ if eq .Provider "talosv1"}}
96 | resource "talos_client_configuration" "this" {
97 | cluster_name = "example-cluster"
98 | machine_secrets = talos_machine_secrets.this.machine_secrets
99 | }
100 |
101 | resource "talos_machine_configuration_controlplane" "this" {
102 | cluster_name = "example-cluster"
103 | cluster_endpoint = "https://${libvirt_domain.cp.network_interface[0].addresses[0]}:6443"
104 | machine_secrets = talos_machine_secrets.this.machine_secrets
105 | }
106 |
107 | {{ if .WithApplyConfig }}
108 | resource "talos_machine_configuration_apply" "this" {
109 | talos_config = talos_client_configuration.this.talos_config
110 | machine_configuration = talos_machine_configuration_controlplane.this.machine_config
111 | node = libvirt_domain.cp.network_interface[0].addresses[0]
112 | endpoint = libvirt_domain.cp.network_interface[0].addresses[0]
113 | config_patches = [
114 | yamlencode({
115 | machine = {
116 | install = {
117 | disk = "/dev/vda"
118 | }
119 | }
120 | }),
121 | ]
122 | }
123 | {{ end }}
124 |
125 | {{ if .WithBootstrap }}
126 | resource "talos_machine_bootstrap" "this" {
127 | depends_on = [
128 | talos_machine_configuration_apply.this
129 | ]
130 | node = libvirt_domain.cp.network_interface[0].addresses[0]
131 | endpoint = libvirt_domain.cp.network_interface[0].addresses[0]
132 | talos_config = talos_client_configuration.this.talos_config
133 | }
134 | {{ end }}
135 | {{ else }}
136 | data "talos_machine_configuration" "this" {
137 | cluster_name = "example-cluster"
138 | cluster_endpoint = "https://${libvirt_domain.cp.network_interface[0].addresses[0]}:6443"
139 | machine_type = "controlplane"
140 | machine_secrets = talos_machine_secrets.this.machine_secrets
141 | docs = false
142 | examples = false
143 | }
144 |
145 | data "talos_machine_disks" "this" {
146 | client_configuration = talos_machine_secrets.this.client_configuration
147 | node = libvirt_domain.cp.network_interface[0].addresses[0]
148 | selector = "disk.size > 6u * GB"
149 | }
150 |
151 | {{ if .WithApplyConfig }}
152 | resource "talos_machine_configuration_apply" "this" {
153 | client_configuration = talos_machine_secrets.this.client_configuration
154 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
155 | node = libvirt_domain.cp.network_interface[0].addresses[0]
156 | config_patches = [
157 | yamlencode({
158 | machine = {
159 | install = {
160 | disk = data.talos_machine_disks.this.disks[0].dev_path
161 | }
162 | }
163 | }),
164 | ]
165 | }
166 | {{ end }}
167 |
168 | {{ if .WithBootstrap }}
169 | resource "talos_machine_bootstrap" "this" {
170 | depends_on = [
171 | talos_machine_configuration_apply.this
172 | ]
173 | node = libvirt_domain.cp.network_interface[0].addresses[0]
174 | client_configuration = talos_machine_secrets.this.client_configuration
175 | }
176 | {{ end }}
177 |
178 | {{ if .WithRetrieveKubeConfig }}
179 | resource "talos_cluster_kubeconfig" "this" {
180 | depends_on = [
181 | talos_machine_bootstrap.this
182 | ]
183 | client_configuration = talos_machine_secrets.this.client_configuration
184 | node = libvirt_domain.cp.network_interface[0].addresses[0]
185 | }
186 | {{ end }}
187 |
188 | {{ if .WithClusterHealth }}
189 | data "talos_cluster_health" "this" {
190 | depends_on = [
191 | talos_cluster_kubeconfig.this
192 | ]
193 |
194 | timeouts = {
195 | read = "25m"
196 | }
197 |
198 | client_configuration = talos_machine_secrets.this.client_configuration
199 | endpoints = libvirt_domain.cp.network_interface[0].addresses
200 | control_plane_nodes = libvirt_domain.cp.network_interface[0].addresses
201 | }
202 | {{ end }}
203 | {{ end }}
204 | `
205 |
206 | var config strings.Builder
207 |
208 | template.Must(template.New("tf_config").Parse(configTemplate)).Execute(&config, c) //nolint:errcheck
209 |
210 | return config.String()
211 | }
212 |
--------------------------------------------------------------------------------
/pkg/talos/talos_client_configuration_data_source.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos
6 |
7 | import (
8 | "context"
9 |
10 | "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
11 | "github.com/hashicorp/terraform-plugin-framework/datasource"
12 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
13 | "github.com/hashicorp/terraform-plugin-framework/schema/validator"
14 | "github.com/hashicorp/terraform-plugin-framework/types"
15 | "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
16 | )
17 |
18 | type talosClientConfigurationDataSource struct{}
19 |
20 | type talosClientConfigurationDataSourceModelV0 struct {
21 | ID types.String `tfsdk:"id"`
22 | ClusterName types.String `tfsdk:"cluster_name"`
23 | ClientConfiguration clientConfiguration `tfsdk:"client_configuration"`
24 | Endpoints types.List `tfsdk:"endpoints"`
25 | Nodes types.List `tfsdk:"nodes"`
26 | TalosConfig types.String `tfsdk:"talos_config"`
27 | }
28 |
29 | var _ datasource.DataSource = &talosClientConfigurationDataSource{}
30 |
31 | // NewTalosClientConfigurationDataSource implements the datasource.DataSource interface.
32 | func NewTalosClientConfigurationDataSource() datasource.DataSource {
33 | return &talosClientConfigurationDataSource{}
34 | }
35 |
36 | func (d *talosClientConfigurationDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
37 | resp.TypeName = req.ProviderTypeName + "_client_configuration"
38 | }
39 |
40 | func (d *talosClientConfigurationDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
41 | resp.Schema = schema.Schema{
42 | Description: "Generate client configuration for a Talos cluster",
43 | Attributes: map[string]schema.Attribute{
44 | "id": schema.StringAttribute{
45 | Description: "The ID of this resource",
46 | Computed: true,
47 | },
48 | "cluster_name": schema.StringAttribute{
49 | Required: true,
50 | Description: "The name of the cluster in the generated config",
51 | Validators: []validator.String{
52 | stringvalidator.LengthAtLeast(1),
53 | },
54 | },
55 | "client_configuration": schema.SingleNestedAttribute{
56 | Attributes: map[string]schema.Attribute{
57 | "ca_certificate": schema.StringAttribute{
58 | Required: true,
59 | Description: "The client CA certificate",
60 | },
61 | "client_certificate": schema.StringAttribute{
62 | Required: true,
63 | Description: "The client certificate",
64 | },
65 | "client_key": schema.StringAttribute{
66 | Required: true,
67 | Sensitive: true,
68 | Description: "The client key",
69 | },
70 | },
71 | Required: true,
72 | Description: "The client configuration data",
73 | },
74 | "endpoints": schema.ListAttribute{
75 | ElementType: types.StringType,
76 | Optional: true,
77 | Description: "endpoints to set in the generated config",
78 | },
79 | "nodes": schema.ListAttribute{
80 | ElementType: types.StringType,
81 | Optional: true,
82 | Description: "nodes to set in the generated config",
83 | },
84 | "talos_config": schema.StringAttribute{
85 | Computed: true,
86 | Description: "The generated client configuration",
87 | Sensitive: true,
88 | },
89 | },
90 | }
91 | }
92 |
93 | func (d *talosClientConfigurationDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
94 | var state talosClientConfigurationDataSourceModelV0
95 |
96 | diags := req.Config.Get(ctx, &state)
97 | resp.Diagnostics.Append(diags...)
98 |
99 | if resp.Diagnostics.HasError() {
100 | return
101 | }
102 |
103 | var endpoints []string
104 |
105 | var nodes []string
106 |
107 | resp.Diagnostics.Append(state.Endpoints.ElementsAs(ctx, &endpoints, true)...)
108 |
109 | if resp.Diagnostics.HasError() {
110 | return
111 | }
112 |
113 | resp.Diagnostics.Append(state.Nodes.ElementsAs(ctx, &nodes, true)...)
114 |
115 | if resp.Diagnostics.HasError() {
116 | return
117 | }
118 |
119 | talosConfig, err := talosClientTFConfigToTalosClientConfig(
120 | state.ClusterName.ValueString(),
121 | state.ClientConfiguration.CA.ValueString(),
122 | state.ClientConfiguration.Cert.ValueString(),
123 | state.ClientConfiguration.Key.ValueString(),
124 | )
125 | if err != nil {
126 | resp.Diagnostics.AddError("failed to generate talos config", err.Error())
127 |
128 | return
129 | }
130 |
131 | if len(endpoints) > 0 {
132 | talosConfig.Contexts[state.ClusterName.ValueString()].Endpoints = endpoints
133 | }
134 |
135 | if len(nodes) > 0 {
136 | talosConfig.Contexts[state.ClusterName.ValueString()].Nodes = nodes
137 | }
138 |
139 | talosConfigStringBytes, err := talosConfig.Bytes()
140 | if err != nil {
141 | resp.Diagnostics.AddError("failed to generate talos config", err.Error())
142 |
143 | return
144 | }
145 |
146 | state.TalosConfig = basetypes.NewStringValue(string(talosConfigStringBytes))
147 | state.ID = state.ClusterName
148 |
149 | diags = resp.State.Set(ctx, &state)
150 | resp.Diagnostics.Append(diags...)
151 |
152 | if resp.Diagnostics.HasError() {
153 | return
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/pkg/talos/talos_client_configuration_data_source_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "strings"
9 | "testing"
10 | "text/template"
11 |
12 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
13 | "github.com/siderolabs/talos/pkg/machinery/client/config"
14 | "github.com/stretchr/testify/assert"
15 | "gopkg.in/yaml.v3"
16 | )
17 |
18 | func TestAccTalosClientConfigurationDataSource(t *testing.T) {
19 | resource.ParallelTest(t, resource.TestCase{
20 | IsUnitTest: true, // this is a local only resource, so can be unit tested
21 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
22 | Steps: []resource.TestStep{
23 | // test data source with default values
24 | {
25 | Config: testAccTalosClientConfigurationDataSourceConfig("test-cluster", nil, nil),
26 | Check: resource.ComposeAggregateTestCheckFunc(
27 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "id", "test-cluster"),
28 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "cluster_name", "test-cluster"),
29 | resource.TestCheckResourceAttrSet("data.talos_client_configuration.this", "client_configuration.%"),
30 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "endpoints.#", "0"),
31 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "nodes.#", "0"),
32 | resource.TestCheckResourceAttrSet("data.talos_client_configuration.this", "talos_config"),
33 | resource.TestCheckResourceAttrWith("data.talos_client_configuration.this", "talos_config", func(value string) error {
34 | return validateTalosClientConfigContext(t, value, "test-cluster", nil, nil)
35 | }),
36 | ),
37 | },
38 | // test data source with overrides
39 | {
40 | Config: testAccTalosClientConfigurationDataSourceConfig("test-cluster-1", []string{"10.5.0.2", "10.5.0.3"}, []string{"10.5.0.4"}),
41 | Check: resource.ComposeAggregateTestCheckFunc(
42 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "id", "test-cluster-1"),
43 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "cluster_name", "test-cluster-1"),
44 | resource.TestCheckResourceAttrSet("data.talos_client_configuration.this", "client_configuration.%"),
45 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "endpoints.0", "10.5.0.2"),
46 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "endpoints.1", "10.5.0.3"),
47 | resource.TestCheckResourceAttr("data.talos_client_configuration.this", "nodes.0", "10.5.0.4"),
48 | resource.TestCheckResourceAttrSet("data.talos_client_configuration.this", "talos_config"),
49 | resource.TestCheckResourceAttrWith("data.talos_client_configuration.this", "talos_config", func(value string) error {
50 | return validateTalosClientConfigContext(t, value, "test-cluster-1", []string{"10.5.0.2", "10.5.0.3"}, []string{"10.5.0.4"})
51 | }),
52 | ),
53 | },
54 | },
55 | })
56 | }
57 |
58 | func testAccTalosClientConfigurationDataSourceConfig(clusterName string, endpoints, nodes []string) string {
59 | configTemplate := `
60 | resource "talos_machine_secrets" "this" {}
61 |
62 | data "talos_client_configuration" "this" {
63 | cluster_name = "{{ .ClusterName }}"
64 | client_configuration = talos_machine_secrets.this.client_configuration
65 | {{if .Endpoints }}endpoints = [{{- range .Endpoints }}
66 | "{{ . }}",
67 | {{- end }}
68 | ]{{end }}
69 | {{if .Nodes }}nodes = [{{- range .Nodes }}
70 | "{{ . }}",
71 | {{- end }}
72 | ]{{end }}
73 | }
74 | `
75 |
76 | var config strings.Builder
77 |
78 | template.Must(template.New("tf_config").Parse(configTemplate)).Execute(&config, struct { //nolint:errcheck
79 | ClusterName string
80 | Endpoints []string
81 | Nodes []string
82 | }{
83 | ClusterName: clusterName,
84 | Endpoints: endpoints,
85 | Nodes: nodes,
86 | })
87 |
88 | return config.String()
89 | }
90 |
91 | func validateTalosClientConfigContext(t *testing.T, tc, contextName string, endpoints, nodes []string) error {
92 | var talosConfig config.Config
93 |
94 | if err := yaml.Unmarshal([]byte(tc), &talosConfig); err != nil {
95 | return err
96 | }
97 |
98 | assert.Equal(t, contextName, talosConfig.Context)
99 |
100 | if endpoints != nil {
101 | assert.Equal(t, endpoints, talosConfig.Contexts[contextName].Endpoints)
102 | }
103 |
104 | if nodes != nil {
105 | assert.Equal(t, nodes, talosConfig.Contexts[contextName].Nodes)
106 | }
107 |
108 | return nil
109 | }
110 |
--------------------------------------------------------------------------------
/pkg/talos/talos_cluster_health_data_source.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos
6 |
7 | import (
8 | "context"
9 | "fmt"
10 | "slices"
11 | "strings"
12 | "time"
13 |
14 | "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
15 | "github.com/hashicorp/terraform-plugin-framework/datasource"
16 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
17 | "github.com/hashicorp/terraform-plugin-framework/types"
18 | "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
19 | "github.com/siderolabs/talos/pkg/cluster"
20 | "github.com/siderolabs/talos/pkg/cluster/check"
21 | "github.com/siderolabs/talos/pkg/conditions"
22 | "github.com/siderolabs/talos/pkg/machinery/client"
23 | "github.com/siderolabs/talos/pkg/machinery/config/machine"
24 | )
25 |
26 | type talosClusterHealthDataSource struct{}
27 |
28 | var _ datasource.DataSource = &talosClusterHealthDataSource{}
29 |
30 | type talosClusterHealthDataSourceModelV0 struct {
31 | ID types.String `tfsdk:"id"`
32 | Endpoints types.List `tfsdk:"endpoints"`
33 | ControlPlaneNodes types.List `tfsdk:"control_plane_nodes"`
34 | WorkerNodes types.List `tfsdk:"worker_nodes"`
35 | ClientConfiguration clientConfiguration `tfsdk:"client_configuration"`
36 | Timeouts timeouts.Value `tfsdk:"timeouts"`
37 | SkipKubernetesChecks types.Bool `tfsdk:"skip_kubernetes_checks"`
38 | }
39 |
40 | type clusterNodes struct {
41 | nodesByType map[machine.Type][]cluster.NodeInfo
42 | nodes []cluster.NodeInfo
43 | }
44 |
45 | func newClusterNodes(controlPlaneNodes, workerNodes []string) (*clusterNodes, error) {
46 | controlPlaneNodeInfos, err := cluster.IPsToNodeInfos(controlPlaneNodes)
47 | if err != nil {
48 | return nil, err
49 | }
50 |
51 | workerNodeInfos, err := cluster.IPsToNodeInfos(workerNodes)
52 | if err != nil {
53 | return nil, err
54 | }
55 |
56 | nodesByType := make(map[machine.Type][]cluster.NodeInfo)
57 | nodesByType[machine.TypeControlPlane] = controlPlaneNodeInfos
58 | nodesByType[machine.TypeWorker] = workerNodeInfos
59 |
60 | return &clusterNodes{
61 | nodes: slices.Concat(controlPlaneNodeInfos, workerNodeInfos),
62 | nodesByType: nodesByType,
63 | }, nil
64 | }
65 |
66 | // Nodes returns cluster nodeinfos.
67 | func (c *clusterNodes) Nodes() []cluster.NodeInfo {
68 | return c.nodes
69 | }
70 |
71 | // NodesByType returns cluster nodeinfos by type.
72 | func (c *clusterNodes) NodesByType(t machine.Type) []cluster.NodeInfo {
73 | return c.nodesByType[t]
74 | }
75 |
76 | type reporter struct {
77 | lastLine string
78 | s strings.Builder
79 | }
80 |
81 | func newReporter() *reporter {
82 | return &reporter{}
83 | }
84 |
85 | // Update implements the conditions.Reporter interface.
86 | func (r *reporter) Update(condition conditions.Condition) {
87 | if condition.String() != r.lastLine {
88 | r.s.WriteString(fmt.Sprintf("waiting for %s\n", condition.String()))
89 | r.lastLine = condition.String()
90 | }
91 | }
92 |
93 | // String returns the string representation of the reporter.
94 | func (r *reporter) String() string {
95 | return r.s.String()
96 | }
97 |
98 | // NewTalosClusterHealthDataSource implements the datasource.DataSource interface.
99 | func NewTalosClusterHealthDataSource() datasource.DataSource {
100 | return &talosClusterHealthDataSource{}
101 | }
102 |
103 | func (d *talosClusterHealthDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
104 | resp.TypeName = req.ProviderTypeName + "_cluster_health"
105 | }
106 |
107 | func (d *talosClusterHealthDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
108 | resp.Schema = schema.Schema{
109 | Description: "Checks the health of a Talos cluster",
110 | MarkdownDescription: "Waits for the Talos cluster to be healthy. Can be used as a dependency before running other operations on the cluster.",
111 | Attributes: map[string]schema.Attribute{
112 | "id": schema.StringAttribute{
113 | Computed: true,
114 | },
115 | "endpoints": schema.ListAttribute{
116 | Required: true,
117 | ElementType: types.StringType,
118 | Description: "endpoints to use for the health check client. Use at least one control plane endpoint.",
119 | },
120 | "control_plane_nodes": schema.ListAttribute{
121 | Required: true,
122 | ElementType: types.StringType,
123 | Description: "List of control plane nodes to check for health.",
124 | },
125 | "worker_nodes": schema.ListAttribute{
126 | Optional: true,
127 | ElementType: types.StringType,
128 | Description: "List of worker nodes to check for health.",
129 | },
130 | "skip_kubernetes_checks": schema.BoolAttribute{
131 | Optional: true,
132 | Description: "Skip Kubernetes component checks, this is useful to check if the nodes has finished booting up and kubelet is running. Default is false.",
133 | },
134 | "client_configuration": schema.SingleNestedAttribute{
135 | Attributes: map[string]schema.Attribute{
136 | "ca_certificate": schema.StringAttribute{
137 | Required: true,
138 | Description: "The client CA certificate",
139 | },
140 | "client_certificate": schema.StringAttribute{
141 | Required: true,
142 | Description: "The client certificate",
143 | },
144 | "client_key": schema.StringAttribute{
145 | Required: true,
146 | Sensitive: true,
147 | Description: "The client key",
148 | },
149 | },
150 | Required: true,
151 | Description: "The client configuration data",
152 | },
153 | "timeouts": timeouts.Attributes(ctx, timeouts.Opts{
154 | Read: true,
155 | }),
156 | },
157 | }
158 | }
159 |
160 | func (d *talosClusterHealthDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
161 | var state talosClusterHealthDataSourceModelV0
162 |
163 | diags := req.Config.Get(ctx, &state)
164 | resp.Diagnostics.Append(diags...)
165 |
166 | if resp.Diagnostics.HasError() {
167 | return
168 | }
169 |
170 | var (
171 | endpoints []string
172 | controlPlaneNodes []string
173 | workerNodes []string
174 | )
175 |
176 | resp.Diagnostics.Append(state.Endpoints.ElementsAs(ctx, &endpoints, true)...)
177 |
178 | if resp.Diagnostics.HasError() {
179 | return
180 | }
181 |
182 | resp.Diagnostics.Append(state.ControlPlaneNodes.ElementsAs(ctx, &controlPlaneNodes, true)...)
183 |
184 | if resp.Diagnostics.HasError() {
185 | return
186 | }
187 |
188 | resp.Diagnostics.Append(state.WorkerNodes.ElementsAs(ctx, &workerNodes, true)...)
189 |
190 | if resp.Diagnostics.HasError() {
191 | return
192 | }
193 |
194 | readTimeout, diags := state.Timeouts.Read(ctx, 10*time.Minute)
195 | resp.Diagnostics.Append(diags...)
196 |
197 | if resp.Diagnostics.HasError() {
198 | return
199 | }
200 |
201 | talosConfig, err := talosClientTFConfigToTalosClientConfig(
202 | "dynamic",
203 | state.ClientConfiguration.CA.ValueString(),
204 | state.ClientConfiguration.Cert.ValueString(),
205 | state.ClientConfiguration.Key.ValueString(),
206 | )
207 | if err != nil {
208 | resp.Diagnostics.AddError("failed to generate talos config", err.Error())
209 |
210 | return
211 | }
212 |
213 | c, err := client.New(ctx, client.WithConfig(talosConfig), client.WithEndpoints(endpoints...))
214 | if err != nil {
215 | resp.Diagnostics.AddError("failed to create talos client", err.Error())
216 |
217 | return
218 | }
219 |
220 | defer c.Close() //nolint:errcheck
221 |
222 | clientProvider := &cluster.ConfigClientProvider{
223 | DefaultClient: c,
224 | }
225 | defer clientProvider.Close() //nolint:errcheck
226 |
227 | nodeInfos, err := newClusterNodes(controlPlaneNodes, workerNodes)
228 | if err != nil {
229 | resp.Diagnostics.AddError("failed to generate node infos", err.Error())
230 |
231 | return
232 | }
233 |
234 | clusterState := struct {
235 | cluster.ClientProvider
236 | cluster.K8sProvider
237 | cluster.Info
238 | }{
239 | ClientProvider: clientProvider,
240 | K8sProvider: &cluster.KubernetesClient{
241 | ClientProvider: clientProvider,
242 | },
243 | Info: nodeInfos,
244 | }
245 |
246 | // Run cluster readiness checks
247 | checkCtx, checkCtxCancel := context.WithTimeout(ctx, readTimeout)
248 | defer checkCtxCancel()
249 |
250 | reporter := newReporter()
251 |
252 | checks := slices.Concat(check.PreBootSequenceChecks(), check.K8sComponentsReadinessChecks())
253 |
254 | if !state.SkipKubernetesChecks.ValueBool() {
255 | checks = check.DefaultClusterChecks()
256 | }
257 |
258 | if err := check.Wait(checkCtx, &clusterState, checks, reporter); err != nil {
259 | resp.Diagnostics.AddWarning("failed checks", reporter.String())
260 | resp.Diagnostics.AddError("cluster health check failed", err.Error())
261 |
262 | return
263 | }
264 |
265 | state.ID = basetypes.NewStringValue("cluster_health")
266 |
267 | resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
268 |
269 | if resp.Diagnostics.HasError() {
270 | return
271 | }
272 | }
273 |
--------------------------------------------------------------------------------
/pkg/talos/talos_cluster_health_data_source_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "testing"
9 |
10 | "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
11 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
12 | )
13 |
14 | func TestAccTalosClusterHealthDataSource(t *testing.T) {
15 | rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
16 |
17 | resource.ParallelTest(t, resource.TestCase{
18 | ExternalProviders: map[string]resource.ExternalProvider{
19 | "libvirt": {
20 | Source: "dmacvicar/libvirt",
21 | },
22 | },
23 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
24 | Steps: []resource.TestStep{
25 | {
26 | Config: testAccTalosClusterHealthDataSourceConfig("talos", rName),
27 | Check: resource.ComposeAggregateTestCheckFunc(
28 | resource.TestCheckResourceAttr("data.talos_cluster_health.this", "id", "cluster_health"),
29 | ),
30 | },
31 | // make sure there are no changes
32 | {
33 | Config: testAccTalosClusterHealthDataSourceConfig("talos", rName),
34 | PlanOnly: true,
35 | },
36 | },
37 | })
38 | }
39 |
40 | func testAccTalosClusterHealthDataSourceConfig(providerName, rName string) string {
41 | config := dynamicConfig{
42 | Provider: providerName,
43 | ResourceName: rName,
44 | WithApplyConfig: true,
45 | WithBootstrap: true,
46 | WithRetrieveKubeConfig: true,
47 | WithClusterHealth: true,
48 | }
49 |
50 | return config.render()
51 | }
52 |
--------------------------------------------------------------------------------
/pkg/talos/talos_cluster_kubeconfig_data_source.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos
6 |
7 | import (
8 | "context"
9 | "time"
10 |
11 | "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
12 | "github.com/hashicorp/terraform-plugin-framework/datasource"
13 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
14 | "github.com/hashicorp/terraform-plugin-framework/types"
15 | "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
16 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
17 | "github.com/siderolabs/talos/pkg/machinery/client"
18 | "google.golang.org/grpc/codes"
19 | "google.golang.org/grpc/status"
20 | "k8s.io/client-go/tools/clientcmd"
21 | )
22 |
23 | type talosClusterKubeConfigDataSource struct{}
24 |
25 | type talosClusterKubeConfigDataSourceModelV0 struct { //nolint:govet
26 | ID types.String `tfsdk:"id"`
27 | Node types.String `tfsdk:"node"`
28 | Endpoint types.String `tfsdk:"endpoint"`
29 | ClientConfiguration clientConfiguration `tfsdk:"client_configuration"`
30 | KubeConfigRaw types.String `tfsdk:"kubeconfig_raw"`
31 | KubernetesClientConfiguration kubernetesClientConfiguration `tfsdk:"kubernetes_client_configuration"`
32 | Wait types.Bool `tfsdk:"wait"`
33 | Timeouts timeouts.Value `tfsdk:"timeouts"`
34 | }
35 |
36 | var _ datasource.DataSource = &talosClusterKubeConfigDataSource{}
37 |
38 | // NewTalosClusterKubeConfigDataSource implements the datasource.DataSource interface.
39 | func NewTalosClusterKubeConfigDataSource() datasource.DataSource {
40 | return &talosClusterKubeConfigDataSource{}
41 | }
42 |
43 | func (d *talosClusterKubeConfigDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
44 | resp.TypeName = req.ProviderTypeName + "_cluster_kubeconfig"
45 | }
46 |
47 | func (d *talosClusterKubeConfigDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
48 | resp.Schema = schema.Schema{
49 | DeprecationMessage: "Use `talos_cluster_kubeconfig` resource instead. This data source will be removed in the next minor version of the provider.",
50 | Description: "Retrieves the kubeconfig for a Talos cluster",
51 | Attributes: map[string]schema.Attribute{
52 | "id": schema.StringAttribute{
53 | Computed: true,
54 | },
55 | "node": schema.StringAttribute{
56 | Required: true,
57 | Description: "controlplane node to retrieve the kubeconfig from",
58 | },
59 | "endpoint": schema.StringAttribute{
60 | Optional: true,
61 | Computed: true,
62 | Description: "endpoint to use for the talosclient. If not set, the node value will be used",
63 | },
64 | "client_configuration": schema.SingleNestedAttribute{
65 | Attributes: map[string]schema.Attribute{
66 | "ca_certificate": schema.StringAttribute{
67 | Required: true,
68 | Description: "The client CA certificate",
69 | },
70 | "client_certificate": schema.StringAttribute{
71 | Required: true,
72 | Description: "The client certificate",
73 | },
74 | "client_key": schema.StringAttribute{
75 | Required: true,
76 | Sensitive: true,
77 | Description: "The client key",
78 | },
79 | },
80 | Required: true,
81 | Description: "The client configuration data",
82 | },
83 | "wait": schema.BoolAttribute{
84 | Optional: true,
85 | Description: "Wait for the kubernetes api to be available",
86 | DeprecationMessage: "This attribute is deprecated and no-op. Will be removed in a future version. Use talos_cluster_health instead.",
87 | },
88 | "kubeconfig_raw": schema.StringAttribute{
89 | Computed: true,
90 | Description: "The raw kubeconfig",
91 | Sensitive: true,
92 | },
93 | "kubernetes_client_configuration": schema.SingleNestedAttribute{
94 | Attributes: map[string]schema.Attribute{
95 | "host": schema.StringAttribute{
96 | Computed: true,
97 | Description: "The kubernetes host",
98 | },
99 | "ca_certificate": schema.StringAttribute{
100 | Computed: true,
101 | Description: "The kubernetes CA certificate",
102 | },
103 | "client_certificate": schema.StringAttribute{
104 | Computed: true,
105 | Description: "The kubernetes client certificate",
106 | },
107 | "client_key": schema.StringAttribute{
108 | Computed: true,
109 | Sensitive: true,
110 | Description: "The kubernetes client key",
111 | },
112 | },
113 | Computed: true,
114 | Description: "The kubernetes client configuration",
115 | },
116 | "timeouts": timeouts.Attributes(ctx, timeouts.Opts{
117 | Read: true,
118 | }),
119 | },
120 | }
121 | }
122 |
123 | // Read implements the datasource.DataSource interface.
124 | func (d *talosClusterKubeConfigDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
125 | var obj types.Object
126 |
127 | diags := req.Config.Get(ctx, &obj)
128 | resp.Diagnostics.Append(diags...)
129 |
130 | if resp.Diagnostics.HasError() {
131 | return
132 | }
133 |
134 | var state talosClusterKubeConfigDataSourceModelV0
135 | diags = obj.As(ctx, &state, basetypes.ObjectAsOptions{
136 | UnhandledNullAsEmpty: true,
137 | UnhandledUnknownAsEmpty: true,
138 | })
139 | resp.Diagnostics.Append(diags...)
140 |
141 | if resp.Diagnostics.HasError() {
142 | return
143 | }
144 |
145 | talosConfig, err := talosClientTFConfigToTalosClientConfig(
146 | "dynamic",
147 | state.ClientConfiguration.CA.ValueString(),
148 | state.ClientConfiguration.Cert.ValueString(),
149 | state.ClientConfiguration.Key.ValueString(),
150 | )
151 | if err != nil {
152 | resp.Diagnostics.AddError("failed to generate talos config", err.Error())
153 |
154 | return
155 | }
156 |
157 | if state.Endpoint.IsNull() {
158 | state.Endpoint = state.Node
159 | }
160 |
161 | readTimeout, diags := state.Timeouts.Read(ctx, 10*time.Minute)
162 | resp.Diagnostics.Append(diags...)
163 |
164 | if resp.Diagnostics.HasError() {
165 | return
166 | }
167 |
168 | ctxDeadline, cancel := context.WithTimeout(ctx, readTimeout)
169 | defer cancel()
170 |
171 | if retryErr := retry.RetryContext(ctxDeadline, readTimeout, func() *retry.RetryError {
172 | if clientOpErr := talosClientOp(ctx, state.Endpoint.ValueString(), state.Node.ValueString(), talosConfig, func(nodeCtx context.Context, c *client.Client) error {
173 | kubeConfigBytes, clientErr := c.Kubeconfig(nodeCtx)
174 | if clientErr != nil {
175 | return clientErr
176 | }
177 |
178 | state.KubeConfigRaw = basetypes.NewStringValue(string(kubeConfigBytes))
179 |
180 | return nil
181 | }); clientOpErr != nil {
182 | if s := status.Code(clientOpErr); s == codes.InvalidArgument {
183 | return retry.NonRetryableError(clientOpErr)
184 | }
185 |
186 | return retry.RetryableError(clientOpErr)
187 | }
188 |
189 | return nil
190 | }); retryErr != nil {
191 | resp.Diagnostics.AddError("failed to retrieve kubeconfig", retryErr.Error())
192 |
193 | return
194 | }
195 |
196 | kubeConfig, err := clientcmd.Load([]byte(state.KubeConfigRaw.ValueString()))
197 | if err != nil {
198 | resp.Diagnostics.AddError("failed to parse kubeconfig", err.Error())
199 |
200 | return
201 | }
202 |
203 | clusterName := kubeConfig.Contexts[kubeConfig.CurrentContext].Cluster
204 | authName := kubeConfig.Contexts[kubeConfig.CurrentContext].AuthInfo
205 |
206 | state.KubernetesClientConfiguration = kubernetesClientConfiguration{
207 | Host: basetypes.NewStringValue(kubeConfig.Clusters[clusterName].Server),
208 | CACertificate: basetypes.NewStringValue(bytesToBase64(kubeConfig.Clusters[clusterName].CertificateAuthorityData)),
209 | ClientCertificate: basetypes.NewStringValue(bytesToBase64(kubeConfig.AuthInfos[authName].ClientCertificateData)),
210 | ClientKey: basetypes.NewStringValue(bytesToBase64(kubeConfig.AuthInfos[authName].ClientKeyData)),
211 | }
212 |
213 | state.ID = basetypes.NewStringValue(clusterName)
214 |
215 | diags = resp.State.Set(ctx, &state)
216 | resp.Diagnostics.Append(diags...)
217 |
218 | if resp.Diagnostics.HasError() {
219 | return
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/pkg/talos/talos_cluster_kubeconfig_resource_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "testing"
9 | "time"
10 |
11 | "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
12 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
13 |
14 | "github.com/siderolabs/terraform-provider-talos/pkg/talos"
15 | )
16 |
17 | func TestAccTalosClusterKubeconfigResource(t *testing.T) {
18 | testTime := time.Now()
19 |
20 | rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
21 |
22 | resource.Test(t, resource.TestCase{
23 | ExternalProviders: map[string]resource.ExternalProvider{
24 | "libvirt": {
25 | Source: "dmacvicar/libvirt",
26 | },
27 | },
28 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
29 | Steps: []resource.TestStep{
30 | {
31 | Config: testAccTalosClusterKubeconfigResourceConfig(rName),
32 | Check: resource.ComposeAggregateTestCheckFunc(
33 | resource.TestCheckResourceAttr("talos_cluster_kubeconfig.this", "id", "example-cluster"),
34 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "node"),
35 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "endpoint"),
36 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "client_configuration.ca_certificate"),
37 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "client_configuration.client_certificate"),
38 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "client_configuration.client_key"),
39 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubeconfig_raw"),
40 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubernetes_client_configuration.host"),
41 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubernetes_client_configuration.ca_certificate"),
42 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubernetes_client_configuration.client_certificate"),
43 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubernetes_client_configuration.client_key"),
44 | ),
45 | },
46 | // test kubeconfig regeneration
47 | {
48 | PreConfig: func() {
49 | talos.OverridableTimeFunc = func() time.Time {
50 | return testTime.AddDate(0, 12, 5)
51 | }
52 | },
53 | Config: testAccTalosClusterKubeconfigResourceConfig(rName),
54 | PlanOnly: true,
55 | ExpectNonEmptyPlan: true,
56 | },
57 | },
58 | })
59 |
60 | talos.OverridableTimeFunc = func() time.Time {
61 | return testTime
62 | }
63 |
64 | resource.ParallelTest(t, resource.TestCase{
65 | ExternalProviders: map[string]resource.ExternalProvider{
66 | "libvirt": {
67 | Source: "dmacvicar/libvirt",
68 | },
69 | },
70 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
71 | Steps: []resource.TestStep{
72 | {
73 | Config: testAccTalosClusterKubeconfigResourceConfig(rName),
74 | Check: resource.ComposeAggregateTestCheckFunc(
75 | resource.TestCheckResourceAttr("talos_cluster_kubeconfig.this", "id", "example-cluster"),
76 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "node"),
77 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "endpoint"),
78 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "client_configuration.ca_certificate"),
79 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "client_configuration.client_certificate"),
80 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "client_configuration.client_key"),
81 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubeconfig_raw"),
82 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubernetes_client_configuration.host"),
83 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubernetes_client_configuration.ca_certificate"),
84 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubernetes_client_configuration.client_certificate"),
85 | resource.TestCheckResourceAttrSet("talos_cluster_kubeconfig.this", "kubernetes_client_configuration.client_key"),
86 | ),
87 | },
88 | // make sure there are no changes
89 | {
90 | Config: testAccTalosClusterKubeconfigResourceConfig(rName),
91 | PlanOnly: true,
92 | },
93 | },
94 | })
95 | }
96 |
97 | func testAccTalosClusterKubeconfigResourceConfig(rName string) string {
98 | config := dynamicConfig{
99 | Provider: "talos",
100 | ResourceName: rName,
101 | WithApplyConfig: true,
102 | WithBootstrap: true,
103 | WithRetrieveKubeConfig: true,
104 | }
105 |
106 | return config.render()
107 | }
108 |
--------------------------------------------------------------------------------
/pkg/talos/talos_image_factory_extensions_versions_data_source.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos
6 |
7 | import (
8 | "context"
9 | "fmt"
10 | "strings"
11 |
12 | "github.com/hashicorp/terraform-plugin-framework/attr"
13 | "github.com/hashicorp/terraform-plugin-framework/datasource"
14 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
15 | "github.com/hashicorp/terraform-plugin-framework/path"
16 | "github.com/hashicorp/terraform-plugin-framework/types"
17 | "github.com/siderolabs/gen/xslices"
18 | "github.com/siderolabs/image-factory/pkg/client"
19 | )
20 |
21 | type talosImageFactoryExtensionsVersionsDataSource struct {
22 | imageFactoryClient *client.Client
23 | }
24 |
25 | type talosImageFactoryExtensionsVersionsDataSourceModelV0 struct {
26 | ID types.String `tfsdk:"id"`
27 | TalosVersion types.String `tfsdk:"talos_version"`
28 | Filters *talosImageFactoryExtensionsVersionsFilter `tfsdk:"filters"`
29 | ExtensionsInfo []extensionInfo `tfsdk:"extensions_info"`
30 | }
31 |
32 | type talosImageFactoryExtensionsVersionsFilter struct {
33 | Names types.List `tfsdk:"names"`
34 | }
35 |
36 | type extensionInfo struct {
37 | Name types.String `tfsdk:"name"`
38 | Ref types.String `tfsdk:"ref"`
39 | Digest types.String `tfsdk:"digest"`
40 | Author types.String `tfsdk:"author"`
41 | Description types.String `tfsdk:"description"`
42 | }
43 |
44 | var _ datasource.DataSourceWithConfigure = &talosImageFactoryExtensionsVersionsDataSource{}
45 |
46 | // NewTalosImageFactoryExtensionsVersionsDataSource implements the datasource.DataSource interface.
47 | func NewTalosImageFactoryExtensionsVersionsDataSource() datasource.DataSource {
48 | return &talosImageFactoryExtensionsVersionsDataSource{}
49 | }
50 |
51 | func (d *talosImageFactoryExtensionsVersionsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
52 | resp.TypeName = req.ProviderTypeName + "_image_factory_extensions_versions"
53 | }
54 |
55 | func (d *talosImageFactoryExtensionsVersionsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
56 | resp.Schema = schema.Schema{
57 | Description: "The image factory extensions versions data source provides a list of available extensions for a specific talos version from the image factory.",
58 | Attributes: map[string]schema.Attribute{
59 | "id": schema.StringAttribute{
60 | Computed: true,
61 | },
62 | "talos_version": schema.StringAttribute{
63 | Required: true,
64 | Description: "The talos version to get extensions for.",
65 | },
66 | "filters": schema.SingleNestedAttribute{
67 | Optional: true,
68 | Description: "The filter to apply to the extensions list.",
69 | Attributes: map[string]schema.Attribute{
70 | "names": schema.ListAttribute{
71 | ElementType: types.StringType,
72 | Optional: true,
73 | Description: "The name of the extension to filter by.",
74 | },
75 | },
76 | },
77 | "extensions_info": schema.ListAttribute{
78 | ElementType: types.ObjectType{
79 | AttrTypes: map[string]attr.Type{
80 | "name": types.StringType,
81 | "ref": types.StringType,
82 | "digest": types.StringType,
83 | "author": types.StringType,
84 | "description": types.StringType,
85 | },
86 | },
87 | Computed: true,
88 | Description: "The list of available extensions for the specified talos version.",
89 | },
90 | },
91 | }
92 | }
93 |
94 | func (d *talosImageFactoryExtensionsVersionsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
95 | if req.ProviderData == nil {
96 | return
97 | }
98 |
99 | imageFactoryClient, ok := req.ProviderData.(*client.Client)
100 | if !ok {
101 | resp.Diagnostics.AddError(
102 | "failed to get image factory client",
103 | fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
104 | )
105 |
106 | return
107 | }
108 |
109 | d.imageFactoryClient = imageFactoryClient
110 | }
111 |
112 | func (d *talosImageFactoryExtensionsVersionsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
113 | if d.imageFactoryClient == nil {
114 | resp.Diagnostics.AddError("image factory client is not configured", "Please report this issue to the provider developers.")
115 |
116 | return
117 | }
118 |
119 | var config talosImageFactoryExtensionsVersionsDataSourceModelV0
120 |
121 | resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
122 |
123 | if resp.Diagnostics.HasError() {
124 | return
125 | }
126 |
127 | if config.TalosVersion.IsNull() || config.TalosVersion.IsUnknown() {
128 | return
129 | }
130 |
131 | extensionsInfo, err := d.imageFactoryClient.ExtensionsVersions(ctx, config.TalosVersion.ValueString())
132 | if err != nil {
133 | resp.Diagnostics.AddError("failed to get talos extensions versions", err.Error())
134 |
135 | return
136 | }
137 |
138 | if config.Filters != nil && !config.Filters.Names.IsNull() && !config.Filters.Names.IsUnknown() {
139 | var names []string
140 |
141 | resp.Diagnostics.Append(config.Filters.Names.ElementsAs(ctx, &names, true)...)
142 |
143 | if resp.Diagnostics.HasError() {
144 | return
145 | }
146 |
147 | extensionsInfo = xslices.Filter(extensionsInfo, func(e client.ExtensionInfo) bool {
148 | for _, n := range names {
149 | if strings.Contains(e.Name, n) {
150 | return true
151 | }
152 | }
153 |
154 | return false
155 | })
156 | }
157 |
158 | tfExtensionsInfo := xslices.Map(extensionsInfo, func(e client.ExtensionInfo) extensionInfo {
159 | return extensionInfo{
160 | Name: types.StringValue(e.Name),
161 | Ref: types.StringValue(e.Ref),
162 | Digest: types.StringValue(e.Digest),
163 | Author: types.StringValue(e.Author),
164 | Description: types.StringValue(e.Description),
165 | }
166 | })
167 |
168 | resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), "extensions_info")...)
169 |
170 | if resp.Diagnostics.HasError() {
171 | return
172 | }
173 |
174 | resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("extensions_info"), &tfExtensionsInfo)...)
175 |
176 | if resp.Diagnostics.HasError() {
177 | return
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/pkg/talos/talos_image_factory_extensions_versions_data_source_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "testing"
9 |
10 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
11 | )
12 |
13 | func TestAccTalosImageFactoryExtensionsVersionsDataSource(t *testing.T) {
14 | resource.ParallelTest(t, resource.TestCase{
15 | IsUnitTest: true, // this is a local only resource, so can be unit tested
16 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
17 | Steps: []resource.TestStep{
18 | {
19 | Config: testAccTalosImageFactoryExtensionsVersionsDataSourceConfig(),
20 | Check: resource.ComposeAggregateTestCheckFunc(
21 | resource.TestCheckResourceAttr("data.talos_image_factory_extensions_versions.this", "extensions_info.0.name", "siderolabs/amdgpu-firmware"),
22 | ),
23 | },
24 | {
25 | Config: testAccTalosImageFactoryExtensionsVersionsDataSourceConfigWithFilters(),
26 | Check: resource.ComposeAggregateTestCheckFunc(
27 | resource.TestCheckResourceAttr("data.talos_image_factory_extensions_versions.this", "extensions_info.#", "5"),
28 | resource.TestCheckResourceAttr("data.talos_image_factory_extensions_versions.this", "extensions_info.0.name", "siderolabs/nvidia-container-toolkit"),
29 | ),
30 | },
31 | },
32 | })
33 | }
34 |
35 | func testAccTalosImageFactoryExtensionsVersionsDataSourceConfig() string {
36 | return `
37 | provider "talos" {}
38 |
39 | data "talos_image_factory_extensions_versions" "this" {
40 | talos_version = "v1.7.0"
41 | }
42 | `
43 | }
44 |
45 | func testAccTalosImageFactoryExtensionsVersionsDataSourceConfigWithFilters() string {
46 | return `
47 | provider "talos" {}
48 |
49 | data "talos_image_factory_extensions_versions" "this" {
50 | talos_version = "v1.7.0"
51 | filters = {
52 | names = [
53 | "nvidia",
54 | "tailscale"
55 | ]
56 | }
57 | }
58 | `
59 | }
60 |
--------------------------------------------------------------------------------
/pkg/talos/talos_image_factory_overlays_versions_data_source.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos
6 |
7 | import (
8 | "context"
9 | "fmt"
10 | "strings"
11 |
12 | "github.com/hashicorp/terraform-plugin-framework/attr"
13 | "github.com/hashicorp/terraform-plugin-framework/datasource"
14 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
15 | "github.com/hashicorp/terraform-plugin-framework/path"
16 | "github.com/hashicorp/terraform-plugin-framework/types"
17 | "github.com/siderolabs/gen/xslices"
18 | "github.com/siderolabs/image-factory/pkg/client"
19 | )
20 |
21 | type talosImageFactoryOverlaysVersionsDataSource struct {
22 | imageFactoryClient *client.Client
23 | }
24 |
25 | type talosImageFactoryOverlaysVersionsDataSourceModelV0 struct {
26 | ID types.String `tfsdk:"id"`
27 | TalosVersion types.String `tfsdk:"talos_version"`
28 | Filters *talosImageFactoryOverlaysVersionsFilter `tfsdk:"filters"`
29 | OverlaysInfo []overlayInfo `tfsdk:"overlays_info"`
30 | }
31 |
32 | type talosImageFactoryOverlaysVersionsFilter struct {
33 | Name types.String `tfsdk:"name"`
34 | }
35 |
36 | type overlayInfo struct {
37 | Name types.String `tfsdk:"name"`
38 | Image types.String `tfsdk:"image"`
39 | Ref types.String `tfsdk:"ref"`
40 | Digest types.String `tfsdk:"digest"`
41 | }
42 |
43 | var _ datasource.DataSourceWithConfigure = &talosImageFactoryOverlaysVersionsDataSource{}
44 |
45 | // NewTalosImageFactoryOverlaysVersionsDataSource implements the datasource.DataSource interface.
46 | func NewTalosImageFactoryOverlaysVersionsDataSource() datasource.DataSource {
47 | return &talosImageFactoryOverlaysVersionsDataSource{}
48 | }
49 |
50 | func (d *talosImageFactoryOverlaysVersionsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
51 | resp.TypeName = req.ProviderTypeName + "_image_factory_overlays_versions"
52 | }
53 |
54 | func (d *talosImageFactoryOverlaysVersionsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
55 | resp.Schema = schema.Schema{
56 | Description: "The image factory overlays versions data source provides a list of available overlays for a specific talos version from the image factory.",
57 | Attributes: map[string]schema.Attribute{
58 | "id": schema.StringAttribute{
59 | Computed: true,
60 | },
61 | "talos_version": schema.StringAttribute{
62 | Required: true,
63 | Description: "The talos version to get overlays for.",
64 | },
65 | "filters": schema.SingleNestedAttribute{
66 | Optional: true,
67 | Description: "The filter to apply to the overlays list.",
68 | Attributes: map[string]schema.Attribute{
69 | "name": schema.StringAttribute{
70 | Optional: true,
71 | Description: "The name of the overlay to filter by.",
72 | },
73 | },
74 | },
75 | "overlays_info": schema.ListAttribute{
76 | ElementType: types.ObjectType{
77 | AttrTypes: map[string]attr.Type{
78 | "name": types.StringType,
79 | "image": types.StringType,
80 | "ref": types.StringType,
81 | "digest": types.StringType,
82 | },
83 | },
84 | Computed: true,
85 | Description: "The list of available extensions for the specified talos version.",
86 | },
87 | },
88 | }
89 | }
90 |
91 | func (d *talosImageFactoryOverlaysVersionsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
92 | if req.ProviderData == nil {
93 | return
94 | }
95 |
96 | imageFactoryClient, ok := req.ProviderData.(*client.Client)
97 | if !ok {
98 | resp.Diagnostics.AddError(
99 | "failed to get image factory client",
100 | fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
101 | )
102 |
103 | return
104 | }
105 |
106 | d.imageFactoryClient = imageFactoryClient
107 | }
108 |
109 | func (d *talosImageFactoryOverlaysVersionsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
110 | if d.imageFactoryClient == nil {
111 | resp.Diagnostics.AddError("image factory client is not configured", "Please report this issue to the provider developers.")
112 |
113 | return
114 | }
115 |
116 | var config talosImageFactoryOverlaysVersionsDataSourceModelV0
117 |
118 | resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
119 |
120 | if resp.Diagnostics.HasError() {
121 | return
122 | }
123 |
124 | if config.TalosVersion.IsNull() || config.TalosVersion.IsUnknown() {
125 | return
126 | }
127 |
128 | overlaysInfo, err := d.imageFactoryClient.OverlaysVersions(ctx, config.TalosVersion.ValueString())
129 | if err != nil {
130 | resp.Diagnostics.AddError("failed to get talos overlays versions", err.Error())
131 |
132 | return
133 | }
134 |
135 | if config.Filters != nil && !config.Filters.Name.IsNull() && !config.Filters.Name.IsUnknown() {
136 | overlaysInfo = xslices.Filter(overlaysInfo, func(e client.OverlayInfo) bool {
137 | return strings.Contains(e.Name, config.Filters.Name.ValueString())
138 | })
139 | }
140 |
141 | tfOverlaysInfo := xslices.Map(overlaysInfo, func(e client.OverlayInfo) overlayInfo {
142 | return overlayInfo{
143 | Name: types.StringValue(e.Name),
144 | Image: types.StringValue(e.Image),
145 | Ref: types.StringValue(e.Ref),
146 | Digest: types.StringValue(e.Digest),
147 | }
148 | })
149 |
150 | resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), "overlays_info")...)
151 |
152 | if resp.Diagnostics.HasError() {
153 | return
154 | }
155 |
156 | resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("overlays_info"), &tfOverlaysInfo)...)
157 |
158 | if resp.Diagnostics.HasError() {
159 | return
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/pkg/talos/talos_image_factory_overlays_versions_data_source_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "testing"
9 |
10 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
11 | )
12 |
13 | func TestAccTalosImageFactoryOverlaysVersionsDataSource(t *testing.T) {
14 | resource.ParallelTest(t, resource.TestCase{
15 | IsUnitTest: true, // this is a local only resource, so can be unit tested
16 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
17 | Steps: []resource.TestStep{
18 | {
19 | Config: testAccTalosImageFactoryOverlaysVersionsDataSourceConfig(),
20 | Check: resource.ComposeAggregateTestCheckFunc(
21 | resource.TestCheckResourceAttr("data.talos_image_factory_overlays_versions.this", "overlays_info.0.name", "rpi_generic"),
22 | ),
23 | },
24 | {
25 | Config: testAccTalosImageFactoryOverlaysVersionsDataSourceConfigWithFilters(),
26 | Check: resource.ComposeAggregateTestCheckFunc(
27 | resource.TestCheckResourceAttr("data.talos_image_factory_overlays_versions.this", "overlays_info.#", "1"),
28 | resource.TestCheckResourceAttr("data.talos_image_factory_overlays_versions.this", "overlays_info.0.name", "rock4cplus"),
29 | ),
30 | },
31 | },
32 | })
33 | }
34 |
35 | func testAccTalosImageFactoryOverlaysVersionsDataSourceConfig() string {
36 | return `
37 | provider "talos" {}
38 |
39 | data "talos_image_factory_overlays_versions" "this" {
40 | talos_version = "v1.7.0"
41 | }
42 | `
43 | }
44 |
45 | func testAccTalosImageFactoryOverlaysVersionsDataSourceConfigWithFilters() string {
46 | return `
47 | provider "talos" {}
48 |
49 | data "talos_image_factory_overlays_versions" "this" {
50 | talos_version = "v1.7.0"
51 | filters = {
52 | name = "rock4cplus"
53 | }
54 | }
55 | `
56 | }
57 |
--------------------------------------------------------------------------------
/pkg/talos/talos_image_factory_schematic_resource.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | // Package talos is a Terraform provider for Talos.
6 | package talos
7 |
8 | import (
9 | "context"
10 |
11 | "github.com/hashicorp/terraform-plugin-framework/resource"
12 | "github.com/hashicorp/terraform-plugin-framework/resource/schema"
13 | "github.com/hashicorp/terraform-plugin-framework/types"
14 | "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
15 | "github.com/siderolabs/image-factory/pkg/client"
16 | "github.com/siderolabs/image-factory/pkg/schematic"
17 | "gopkg.in/yaml.v3"
18 | )
19 |
20 | type talosImageFactorySchematicResource struct {
21 | imageFactoryClient *client.Client
22 | }
23 |
24 | var (
25 | _ resource.Resource = &talosImageFactorySchematicResource{}
26 | _ resource.ResourceWithConfigure = &talosImageFactorySchematicResource{}
27 | )
28 |
29 | var schematicAttributeMarkdownDescription = `
30 | The schematic yaml respresentation to generate the image.
31 |
32 | If not set, a vanilla Talos image schematic will be generated.
33 |
34 | > Refer to [image-factory](https://github.com/siderolabs/image-factory?tab=readme-ov-file#post-schematics) for the schema.
35 | `
36 |
37 | type talosImageFactorySchematicResourceModelV0 struct {
38 | ID types.String `tfsdk:"id"`
39 | Schematic types.String `tfsdk:"schematic"`
40 | }
41 |
42 | // NewTalosImageFactorySchematicResource implements the resource.Resource interface.
43 | func NewTalosImageFactorySchematicResource() resource.Resource {
44 | return &talosImageFactorySchematicResource{}
45 | }
46 |
47 | func (r *talosImageFactorySchematicResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
48 | resp.TypeName = req.ProviderTypeName + "_image_factory_schematic"
49 | }
50 |
51 | func (r *talosImageFactorySchematicResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
52 | resp.Schema = schema.Schema{
53 | Description: "The image factory schematic resource allows you to create a schematic for a Talos image.",
54 | Attributes: map[string]schema.Attribute{
55 | "id": schema.StringAttribute{
56 | Computed: true,
57 | Description: "The unique ID of the schematic, returned from Image Factory.",
58 | },
59 | "schematic": schema.StringAttribute{
60 | Optional: true,
61 | MarkdownDescription: schematicAttributeMarkdownDescription,
62 | },
63 | },
64 | }
65 | }
66 |
67 | func (r *talosImageFactorySchematicResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
68 | if req.ProviderData == nil {
69 | return
70 | }
71 |
72 | imageFactoryClient, ok := req.ProviderData.(*client.Client)
73 | if !ok {
74 | resp.Diagnostics.AddError(
75 | "failed to get image factory client",
76 | "Expected *client.Client, got: %T. Please report this issue to the provider developers.",
77 | )
78 |
79 | return
80 | }
81 |
82 | r.imageFactoryClient = imageFactoryClient
83 | }
84 |
85 | func (r *talosImageFactorySchematicResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
86 | var config talosImageFactorySchematicResourceModelV0
87 |
88 | resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
89 |
90 | if resp.Diagnostics.HasError() {
91 | return
92 | }
93 |
94 | var schematic schematic.Schematic
95 |
96 | if err := yaml.Unmarshal([]byte(config.Schematic.ValueString()), &schematic); err != nil {
97 | resp.Diagnostics.AddError("failed to unmarshal schematic", err.Error())
98 |
99 | return
100 | }
101 |
102 | schematicID, err := r.imageFactoryClient.SchematicCreate(ctx, schematic)
103 | if err != nil {
104 | resp.Diagnostics.AddError("failed to create schematic", err.Error())
105 |
106 | return
107 | }
108 |
109 | config.ID = basetypes.NewStringValue(schematicID)
110 |
111 | resp.Diagnostics.Append(resp.State.Set(ctx, &config)...)
112 |
113 | if resp.Diagnostics.HasError() {
114 | return
115 | }
116 | }
117 |
118 | func (r *talosImageFactorySchematicResource) Delete(_ context.Context, _ resource.DeleteRequest, _ *resource.DeleteResponse) {
119 | }
120 |
121 | func (r *talosImageFactorySchematicResource) Read(_ context.Context, _ resource.ReadRequest, _ *resource.ReadResponse) {
122 | }
123 |
124 | func (r *talosImageFactorySchematicResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
125 | var plan talosImageFactorySchematicResourceModelV0
126 |
127 | diags := req.Plan.Get(ctx, &plan)
128 | resp.Diagnostics.Append(diags...)
129 |
130 | if resp.Diagnostics.HasError() {
131 | return
132 | }
133 |
134 | var schematic schematic.Schematic
135 |
136 | if err := yaml.Unmarshal([]byte(plan.Schematic.ValueString()), &schematic); err != nil {
137 | resp.Diagnostics.AddError("failed to unmarshal schematic", err.Error())
138 |
139 | return
140 | }
141 |
142 | schematicID, err := r.imageFactoryClient.SchematicCreate(ctx, schematic)
143 | if err != nil {
144 | resp.Diagnostics.AddError("failed to update schematic", err.Error())
145 |
146 | return
147 | }
148 |
149 | plan.ID = basetypes.NewStringValue(schematicID)
150 |
151 | // Set state to fully populated data
152 | resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
153 |
154 | if resp.Diagnostics.HasError() {
155 | return
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/pkg/talos/talos_image_factory_schematic_resource_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "testing"
9 |
10 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
11 | )
12 |
13 | func TestAccTalosImageFactorySchematicResource(t *testing.T) {
14 | resource.ParallelTest(t, resource.TestCase{
15 | IsUnitTest: true, // this is a local only resource, so can be unit tested
16 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
17 | Steps: []resource.TestStep{
18 | // vanilla image
19 | {
20 | Config: testAccTalosTalosImageFactorySchematicConfig(),
21 | Check: resource.ComposeAggregateTestCheckFunc(
22 | resource.TestCheckResourceAttr("talos_image_factory_schematic.this", "id", "376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba"),
23 | ),
24 | },
25 | // empty schematic
26 | {
27 | Config: testAccTalosTalosImageFactorySchematicEmptySchematicConfig(),
28 | Check: resource.ComposeAggregateTestCheckFunc(
29 | resource.TestCheckResourceAttr("talos_image_factory_schematic.this", "id", "376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba"),
30 | ),
31 | },
32 | // empty customization
33 | {
34 | Config: testAccTalosTalosImageFactorySchematicEmptyCustomizationConfig(),
35 | Check: resource.ComposeAggregateTestCheckFunc(
36 | resource.TestCheckResourceAttr("talos_image_factory_schematic.this", "id", "376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba"),
37 | ),
38 | },
39 | // vanilla image
40 | {
41 | Config: testAccTalosTalosImageFactorySchematicConfig(),
42 | Check: resource.ComposeAggregateTestCheckFunc(
43 | resource.TestCheckResourceAttr("talos_image_factory_schematic.this", "id", "376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba"),
44 | ),
45 | },
46 | // known extension
47 | {
48 | Config: testAccTalosTalosImageFactorySchematicKnownExtensionConfig(),
49 | Check: resource.ComposeAggregateTestCheckFunc(
50 | resource.TestCheckResourceAttr("talos_image_factory_schematic.this", "id", "d01dbf04a51b44a41d62b7c9692da0a74889277651600da6b602582654e4b402"),
51 | ),
52 | },
53 | },
54 | })
55 | }
56 |
57 | func testAccTalosTalosImageFactorySchematicConfig() string {
58 | return `
59 | provider "talos" {}
60 |
61 | resource "talos_image_factory_schematic" "this" {}
62 | `
63 | }
64 |
65 | func testAccTalosTalosImageFactorySchematicEmptySchematicConfig() string {
66 | return `
67 | provider "talos" {}
68 |
69 | resource "talos_image_factory_schematic" "this" {
70 | schematic = yamlencode({})
71 | }
72 | `
73 | }
74 |
75 | func testAccTalosTalosImageFactorySchematicEmptyCustomizationConfig() string {
76 | return `
77 | provider "talos" {}
78 |
79 | resource "talos_image_factory_schematic" "this" {
80 | schematic = yamlencode(
81 | {
82 | customization = {}
83 | }
84 | )
85 | }
86 | `
87 | }
88 |
89 | func testAccTalosTalosImageFactorySchematicKnownExtensionConfig() string {
90 | return `
91 | provider "talos" {}
92 |
93 | resource "talos_image_factory_schematic" "this" {
94 | schematic = yamlencode(
95 | {
96 | customization = {
97 | systemExtensions = {
98 | officialExtensions = ["siderolabs/amdgpu-firmware"]
99 | }
100 | }
101 | }
102 | )
103 | }
104 | `
105 | }
106 |
--------------------------------------------------------------------------------
/pkg/talos/talos_image_factory_versions_data_source.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos
6 |
7 | import (
8 | "context"
9 | "fmt"
10 | "strings"
11 |
12 | "github.com/blang/semver/v4"
13 | "github.com/hashicorp/terraform-plugin-framework/datasource"
14 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
15 | "github.com/hashicorp/terraform-plugin-framework/types"
16 | "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
17 | "github.com/siderolabs/image-factory/pkg/client"
18 | )
19 |
20 | type talosImageFactoryVersionsDataSource struct {
21 | imageFactoryClient *client.Client
22 | }
23 |
24 | type talosImageFactoryVersionsDataSourceModelV0 struct {
25 | ID types.String `tfsdk:"id"`
26 | Filters *talosImageFactoryVersionsFilter `tfsdk:"filters"`
27 | TalosVersions []string `tfsdk:"talos_versions"`
28 | }
29 |
30 | type talosImageFactoryVersionsFilter struct {
31 | StableVersionOnly types.Bool `tfsdk:"stable_versions_only"`
32 | }
33 |
34 | var _ datasource.DataSourceWithConfigure = &talosImageFactoryVersionsDataSource{}
35 |
36 | // NewTalosImageFactoryVersionsDataSource implements the datasource.DataSource interface.
37 | func NewTalosImageFactoryVersionsDataSource() datasource.DataSource {
38 | return &talosImageFactoryVersionsDataSource{}
39 | }
40 |
41 | func (d *talosImageFactoryVersionsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
42 | resp.TypeName = req.ProviderTypeName + "_image_factory_versions"
43 | }
44 |
45 | func (d *talosImageFactoryVersionsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
46 | resp.Schema = schema.Schema{
47 | Description: "The image factory versions data source provides a list of available talos versions from the image factory.",
48 | Attributes: map[string]schema.Attribute{
49 | "id": schema.StringAttribute{
50 | Computed: true,
51 | },
52 | "talos_versions": schema.ListAttribute{
53 | ElementType: types.StringType,
54 | Computed: true,
55 | Description: "The list of available talos versions.",
56 | },
57 | "filters": schema.SingleNestedAttribute{
58 | Optional: true,
59 | Description: "The filter to apply to the overlays list.",
60 | Attributes: map[string]schema.Attribute{
61 | "stable_versions_only": schema.BoolAttribute{
62 | Optional: true,
63 | Description: "If set to true, only stable versions will be returned. If set to false, all versions will be returned.",
64 | },
65 | },
66 | },
67 | },
68 | }
69 | }
70 |
71 | func (d *talosImageFactoryVersionsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
72 | if req.ProviderData == nil {
73 | return
74 | }
75 |
76 | imageFactoryClient, ok := req.ProviderData.(*client.Client)
77 | if !ok {
78 | resp.Diagnostics.AddError(
79 | "failed to get image factory client",
80 | fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
81 | )
82 |
83 | return
84 | }
85 |
86 | d.imageFactoryClient = imageFactoryClient
87 | }
88 |
89 | func (d *talosImageFactoryVersionsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
90 | if d.imageFactoryClient == nil {
91 | resp.Diagnostics.AddError("image factory client is not configured", "Please report this issue to the provider developers.")
92 |
93 | return
94 | }
95 |
96 | versions, err := d.imageFactoryClient.Versions(ctx)
97 | if err != nil {
98 | resp.Diagnostics.AddError("failed to get talos versions", err.Error())
99 |
100 | return
101 | }
102 |
103 | var config talosImageFactoryVersionsDataSourceModelV0
104 |
105 | resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
106 |
107 | if resp.Diagnostics.HasError() {
108 | return
109 | }
110 |
111 | if config.Filters != nil && config.Filters.StableVersionOnly.ValueBool() {
112 | var filteredVersions []string
113 |
114 | for _, version := range versions {
115 | semVer, err := semver.Parse(strings.TrimPrefix(version, "v"))
116 | if err != nil {
117 | resp.Diagnostics.AddError("failed to parse talos version", err.Error())
118 |
119 | return
120 | }
121 |
122 | if len(semVer.Pre) > 0 {
123 | continue
124 | }
125 |
126 | filteredVersions = append(filteredVersions, version)
127 | }
128 |
129 | if resp.Diagnostics.HasError() {
130 | return
131 | }
132 |
133 | versions = filteredVersions
134 | }
135 |
136 | state := talosImageFactoryVersionsDataSourceModelV0{
137 | ID: basetypes.NewStringValue("talos_versions"),
138 | TalosVersions: versions,
139 | }
140 |
141 | resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
142 |
143 | if resp.Diagnostics.HasError() {
144 | return
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/pkg/talos/talos_image_factory_versions_data_source_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "testing"
9 |
10 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
11 | "github.com/hashicorp/terraform-plugin-testing/knownvalue"
12 | "github.com/hashicorp/terraform-plugin-testing/statecheck"
13 | )
14 |
15 | func TestAccTalosImageFactoryVersionsDataSource(t *testing.T) {
16 | resource.ParallelTest(t, resource.TestCase{
17 | IsUnitTest: true, // this is a local only resource, so can be unit tested
18 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
19 | Steps: []resource.TestStep{
20 | {
21 | Config: testAccTalosImageFactoryVersionsDataSourceConfig(),
22 | Check: resource.ComposeAggregateTestCheckFunc(
23 | resource.TestCheckResourceAttr("data.talos_image_factory_versions.this", "talos_versions.0", "v1.2.0"),
24 | ),
25 | },
26 | {
27 | Config: testAccTalosImageFactoryVersionsDataSourceWithFilterConfig(),
28 | ConfigStateChecks: []statecheck.StateCheck{
29 | statecheck.ExpectKnownOutputValue("talos_version", knownvalue.StringExact("v1.10.2")),
30 | },
31 | },
32 | },
33 | })
34 | }
35 |
36 | func testAccTalosImageFactoryVersionsDataSourceConfig() string {
37 | return `
38 | provider "talos" {}
39 |
40 | data "talos_image_factory_versions" "this" {}
41 | `
42 | }
43 |
44 | func testAccTalosImageFactoryVersionsDataSourceWithFilterConfig() string {
45 | return `
46 | provider "talos" {}
47 |
48 | data "talos_image_factory_versions" "this" {
49 | filters = {
50 | stable_versions_only = true
51 | }
52 | }
53 |
54 | output "talos_version" {
55 | value = data.talos_image_factory_versions.this.talos_versions[length(data.talos_image_factory_versions.this.talos_versions) - 1]
56 | }
57 | `
58 | }
59 |
--------------------------------------------------------------------------------
/pkg/talos/talos_machine_bootstrap_resource_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "fmt"
9 | "testing"
10 |
11 | "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
12 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
13 | )
14 |
15 | func TestAccTalosMachineBootstrapResource(t *testing.T) {
16 | resource.ParallelTest(t, resource.TestCase{
17 | IsUnitTest: true, // import can be unit tested
18 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
19 | Steps: []resource.TestStep{
20 | {
21 | // import the resource
22 | Config: testAccTalosMachineBootstrapResourceConfigImport("10.5.0.2"),
23 | ResourceName: "talos_machine_bootstrap.this",
24 | ImportStateId: "this",
25 | ImportState: true,
26 | ImportStatePersist: true,
27 | },
28 | // verify state is correct after import
29 | {
30 | Config: testAccTalosMachineBootstrapResourceConfigImport("10.5.0.2"),
31 | Check: resource.ComposeAggregateTestCheckFunc(
32 | resource.TestCheckResourceAttr("talos_machine_bootstrap.this", "id", "machine_bootstrap"),
33 | resource.TestCheckResourceAttr("talos_machine_bootstrap.this", "node", "10.5.0.2"),
34 | resource.TestCheckResourceAttr("talos_machine_bootstrap.this", "endpoint", "10.5.0.2"),
35 | resource.TestCheckResourceAttrSet("talos_machine_bootstrap.this", "client_configuration.ca_certificate"),
36 | resource.TestCheckResourceAttrSet("talos_machine_bootstrap.this", "client_configuration.client_certificate"),
37 | resource.TestCheckResourceAttrSet("talos_machine_bootstrap.this", "client_configuration.client_key"),
38 | ),
39 | },
40 | },
41 | })
42 | }
43 |
44 | func TestAccTalosMachineBootstrapResourceUpgrade(t *testing.T) {
45 | // ref: https://github.com/hashicorp/terraform-plugin-testing/pull/118
46 | t.Skip("skipping until TF test framework has a way to remove state resource")
47 |
48 | rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
49 |
50 | resource.ParallelTest(t, resource.TestCase{
51 | Steps: []resource.TestStep{
52 | // create TF config with v0.1.2 of the talos provider
53 | {
54 | ExternalProviders: map[string]resource.ExternalProvider{
55 | "talos": {
56 | VersionConstraint: "=0.1.2",
57 | Source: "siderolabs/talos",
58 | },
59 | "libvirt": {
60 | Source: "dmacvicar/libvirt",
61 | },
62 | },
63 | Config: testAccTalosMachineBootstrapResourceConfigV0("talosv1", rName),
64 | Check: resource.ComposeAggregateTestCheckFunc(
65 | resource.TestCheckNoResourceAttr("talos_client_configuration", "this"),
66 | resource.TestCheckNoResourceAttr("talos_machine_configuration_controlplane", "this"),
67 | resource.TestCheckResourceAttr("talos_machine_configuration_apply", "id", "this"),
68 | ),
69 | },
70 | // now test state migration with the latest version of the provider
71 | {
72 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
73 | ExternalProviders: map[string]resource.ExternalProvider{
74 | "libvirt": {
75 | Source: "dmacvicar/libvirt",
76 | },
77 | },
78 | Config: testAccTalosMachineBootstrapResourceConfigV1("talos", rName),
79 | Check: resource.ComposeAggregateTestCheckFunc(
80 | resource.TestCheckResourceAttr("talos_machine_bootstrap.this", "id", "machine_bootstrap"),
81 | resource.TestCheckResourceAttrSet("talos_machine_bootstrap.this", "node"),
82 | resource.TestCheckResourceAttrSet("talos_machine_bootstrap.this", "endpoint"),
83 | resource.TestCheckResourceAttrSet("talos_machine_bootstrap.this", "client_configuration.ca_certificate"),
84 | resource.TestCheckResourceAttrSet("talos_machine_bootstrap.this", "client_configuration.client_certificate"),
85 | resource.TestCheckResourceAttrSet("talos_machine_bootstrap.this", "client_configuration.client_key"),
86 | ),
87 | },
88 | // ensure there is no diff
89 | {
90 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
91 | ExternalProviders: map[string]resource.ExternalProvider{
92 | "libvirt": {
93 | Source: "dmacvicar/libvirt",
94 | },
95 | },
96 | Config: testAccTalosMachineBootstrapResourceConfigV1("talos", rName),
97 | PlanOnly: true,
98 | },
99 | },
100 | })
101 | }
102 |
103 | func testAccTalosMachineBootstrapResourceConfigV0(providerName, rName string) string {
104 | config := dynamicConfig{
105 | Provider: providerName,
106 | ResourceName: rName,
107 | WithApplyConfig: true,
108 | WithBootstrap: true,
109 | }
110 |
111 | return config.render()
112 | }
113 |
114 | func testAccTalosMachineBootstrapResourceConfigV1(providerName, rName string) string {
115 | config := dynamicConfig{
116 | Provider: providerName,
117 | ResourceName: rName,
118 | WithApplyConfig: true,
119 | WithBootstrap: true,
120 | }
121 |
122 | return config.render()
123 | }
124 |
125 | func testAccTalosMachineBootstrapResourceConfigImport(node string) string {
126 | return fmt.Sprintf(`
127 | resource "talos_machine_secrets" "this" {}
128 |
129 | resource "talos_machine_bootstrap" "this" {
130 | node = "%s"
131 | client_configuration = talos_machine_secrets.this.client_configuration
132 | }
133 | `, node)
134 | }
135 |
--------------------------------------------------------------------------------
/pkg/talos/talos_machine_configuration_apply_resource_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "testing"
9 |
10 | "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
11 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
12 | )
13 |
14 | func TestAccTalosMachineConfigurationApplyResource(t *testing.T) {
15 | rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
16 |
17 | resource.ParallelTest(t, resource.TestCase{
18 | ExternalProviders: map[string]resource.ExternalProvider{
19 | "libvirt": {
20 | Source: "dmacvicar/libvirt",
21 | },
22 | },
23 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
24 | Steps: []resource.TestStep{
25 | {
26 | Config: testAccTalosMachineConfigurationApplyResourceConfig("talos", rName),
27 | Check: resource.ComposeAggregateTestCheckFunc(
28 | resource.TestCheckResourceAttr("talos_machine_configuration_apply.this", "id", "machine_configuration_apply"),
29 | resource.TestCheckResourceAttr("talos_machine_configuration_apply.this", "apply_mode", "auto"),
30 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "node"),
31 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "endpoint"),
32 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "client_configuration.ca_certificate"),
33 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "client_configuration.client_certificate"),
34 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "client_configuration.client_key"),
35 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "machine_configuration_input"),
36 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "machine_configuration"),
37 | resource.TestCheckResourceAttr("talos_machine_configuration_apply.this", "config_patches.#", "1"),
38 | resource.TestCheckResourceAttr("talos_machine_configuration_apply.this", "config_patches.0", "\"machine\":\n \"install\":\n \"disk\": \"/dev/vda\"\n"),
39 | ),
40 | },
41 | // ensure there is no diff
42 | {
43 | Config: testAccTalosMachineConfigurationApplyResourceConfig("talos", rName),
44 | PlanOnly: true,
45 | },
46 | },
47 | })
48 | }
49 |
50 | func TestAccTalosMachineConfigurationApplyResourceUpgrade(t *testing.T) {
51 | // ref: https://github.com/hashicorp/terraform-plugin-testing/pull/118
52 | t.Skip("skipping until TF test framework has a way to remove state resource")
53 |
54 | rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
55 |
56 | resource.ParallelTest(t, resource.TestCase{
57 | Steps: []resource.TestStep{
58 | // create TF config with v0.1.2 of the talos provider
59 | {
60 | ExternalProviders: map[string]resource.ExternalProvider{
61 | "talos": {
62 | VersionConstraint: "=0.1.2",
63 | Source: "siderolabs/talos",
64 | },
65 | "libvirt": {
66 | Source: "dmacvicar/libvirt",
67 | },
68 | },
69 | Config: testAccTalosMachineConfigurationApplyResourceConfigV0("talosv1", rName),
70 | Check: resource.ComposeAggregateTestCheckFunc(
71 | resource.TestCheckNoResourceAttr("talos_client_configuration", "this"),
72 | resource.TestCheckNoResourceAttr("talos_machine_configuration_controlplane", "this"),
73 | ),
74 | },
75 | // now test state migration with the latest version of the provider
76 | {
77 | ExternalProviders: map[string]resource.ExternalProvider{
78 | "libvirt": {
79 | Source: "dmacvicar/libvirt",
80 | },
81 | },
82 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
83 | Config: testAccTalosMachineConfigurationApplyResourceConfigV1("talos", rName),
84 | Check: resource.ComposeAggregateTestCheckFunc(
85 | resource.TestCheckResourceAttr("talos_machine_configuration_apply.this", "id", "machine_configuration_apply"),
86 | resource.TestCheckResourceAttr("talos_machine_configuration_apply.this", "apply_mode", "auto"),
87 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "node"),
88 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "endpoint"),
89 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "client_configuration.ca_certificate"),
90 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "client_configuration.client_certificate"),
91 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "client_configuration.client_key"),
92 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "machine_configuration_input"),
93 | resource.TestCheckResourceAttrSet("talos_machine_configuration_apply.this", "machine_configuration"),
94 | resource.TestCheckResourceAttr("talos_machine_configuration_apply.this", "config_patches.#", "1"),
95 | resource.TestCheckResourceAttr("talos_machine_configuration_apply.this", "config_patches.0", "\"machine\":\n \"install\":\n \"disk\": \"/dev/vda\"\n"),
96 | ),
97 | },
98 | // ensure there is no diff
99 | {
100 | ExternalProviders: map[string]resource.ExternalProvider{
101 | "libvirt": {
102 | Source: "dmacvicar/libvirt",
103 | },
104 | },
105 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
106 | Config: testAccTalosMachineConfigurationApplyResourceConfigV1("talos", rName),
107 | PlanOnly: true,
108 | },
109 | },
110 | })
111 | }
112 |
113 | func testAccTalosMachineConfigurationApplyResourceConfig(providerName, rName string) string {
114 | config := dynamicConfig{
115 | Provider: providerName,
116 | ResourceName: rName,
117 | WithApplyConfig: true,
118 | WithBootstrap: false,
119 | }
120 |
121 | return config.render()
122 | }
123 |
124 | func testAccTalosMachineConfigurationApplyResourceConfigV0(providerName, rName string) string {
125 | config := dynamicConfig{
126 | Provider: providerName,
127 | ResourceName: rName,
128 | WithApplyConfig: true,
129 | WithBootstrap: false,
130 | }
131 |
132 | return config.render()
133 | }
134 |
135 | func testAccTalosMachineConfigurationApplyResourceConfigV1(providerName, rName string) string {
136 | config := dynamicConfig{
137 | Provider: providerName,
138 | ResourceName: rName,
139 | WithApplyConfig: true,
140 | WithBootstrap: false,
141 | }
142 |
143 | return config.render()
144 | }
145 |
--------------------------------------------------------------------------------
/pkg/talos/talos_machine_disks_data_source.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos
6 |
7 | import (
8 | "context"
9 | "errors"
10 | "time"
11 |
12 | "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
13 | "github.com/hashicorp/terraform-plugin-framework/datasource"
14 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
15 | "github.com/hashicorp/terraform-plugin-framework/types"
16 | "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
17 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
18 | "github.com/siderolabs/talos/pkg/machinery/cel"
19 | "github.com/siderolabs/talos/pkg/machinery/cel/celenv"
20 | "github.com/siderolabs/talos/pkg/machinery/client"
21 | "github.com/siderolabs/talos/pkg/machinery/config/types/block/blockhelpers"
22 | "google.golang.org/grpc/codes"
23 | "google.golang.org/grpc/status"
24 | )
25 |
26 | //go:generate go run internal/gen/diskspec.go block.DiskSpec talos_machine_disks_data_source
27 |
28 | func (e nodiskFoundError) Error() string {
29 | return "no disk matching the filter found"
30 | }
31 |
32 | type nodiskFoundError struct{}
33 |
34 | type talosMachineDisksDataSource struct{}
35 |
36 | type talosMachineDisksDataSourceModelV1 struct { //nolint:govet
37 | ID types.String `tfsdk:"id"`
38 | Node types.String `tfsdk:"node"`
39 | Endpoint types.String `tfsdk:"endpoint"`
40 | Selector types.String `tfsdk:"selector"`
41 | ClientConfiguration clientConfiguration `tfsdk:"client_configuration"`
42 | Disks []diskspec `tfsdk:"disks"`
43 | Timeouts timeouts.Value `tfsdk:"timeouts"`
44 | }
45 |
46 | var _ datasource.DataSource = &talosMachineDisksDataSource{}
47 |
48 | // NewTalosMachineDisksDataSource implements the datasource.DataSource interface.
49 | func NewTalosMachineDisksDataSource() datasource.DataSource {
50 | return &talosMachineDisksDataSource{}
51 | }
52 |
53 | func (d *talosMachineDisksDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
54 | resp.TypeName = req.ProviderTypeName + "_machine_disks"
55 | }
56 |
57 | func (d *talosMachineDisksDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
58 | resp.Schema = schema.Schema{
59 | Description: "Generate a machine configuration for a node type",
60 | Attributes: map[string]schema.Attribute{
61 | "id": schema.StringAttribute{
62 | Description: "The generated ID of this resource",
63 | Computed: true,
64 | },
65 | "node": schema.StringAttribute{
66 | Required: true,
67 | Description: "controlplane node to retrieve the kubeconfig from",
68 | },
69 | "endpoint": schema.StringAttribute{
70 | Optional: true,
71 | Computed: true,
72 | Description: "endpoint to use for the talosclient. If not set, the node value will be used",
73 | },
74 | "client_configuration": schema.SingleNestedAttribute{
75 | Attributes: map[string]schema.Attribute{
76 | "ca_certificate": schema.StringAttribute{
77 | Required: true,
78 | Description: "The client CA certificate",
79 | },
80 | "client_certificate": schema.StringAttribute{
81 | Required: true,
82 | Description: "The client certificate",
83 | },
84 | "client_key": schema.StringAttribute{
85 | Required: true,
86 | Sensitive: true,
87 | Description: "The client key",
88 | },
89 | },
90 | Required: true,
91 | Description: "The client configuration data",
92 | },
93 | "selector": schema.StringAttribute{
94 | Optional: true,
95 | MarkdownDescription: `The CEL expression to filter the disks.
96 | If not set, all disks will be returned.
97 | See [CEL documentation](https://www.talos.dev/latest/talos-guides/configuration/disk-management/#disk-selector).`,
98 | },
99 | "disks": schema.ListNestedAttribute{
100 | Description: "The disks that match the filters",
101 | NestedObject: schema.NestedAttributeObject{
102 | Attributes: diskspecAttributes,
103 | },
104 | Computed: true,
105 | },
106 | "timeouts": timeouts.Attributes(ctx, timeouts.Opts{
107 | Read: true,
108 | }),
109 | },
110 | }
111 | }
112 |
113 | func (d *talosMachineDisksDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { //nolint:gocognit,gocyclo,cyclop
114 | var obj types.Object
115 |
116 | diags := req.Config.Get(ctx, &obj)
117 | resp.Diagnostics.Append(diags...)
118 |
119 | if resp.Diagnostics.HasError() {
120 | return
121 | }
122 |
123 | var state talosMachineDisksDataSourceModelV1
124 | diags = obj.As(ctx, &state, basetypes.ObjectAsOptions{
125 | UnhandledNullAsEmpty: true,
126 | UnhandledUnknownAsEmpty: true,
127 | })
128 | resp.Diagnostics.Append(diags...)
129 |
130 | if resp.Diagnostics.HasError() {
131 | return
132 | }
133 |
134 | talosConfig, err := talosClientTFConfigToTalosClientConfig(
135 | "dynamic",
136 | state.ClientConfiguration.CA.ValueString(),
137 | state.ClientConfiguration.Cert.ValueString(),
138 | state.ClientConfiguration.Key.ValueString(),
139 | )
140 | if err != nil {
141 | resp.Diagnostics.AddError("failed to generate talos config", err.Error())
142 |
143 | return
144 | }
145 |
146 | if state.Endpoint.IsNull() {
147 | state.Endpoint = state.Node
148 | }
149 |
150 | readTimeout, diags := state.Timeouts.Read(ctx, 10*time.Minute)
151 | resp.Diagnostics.Append(diags...)
152 |
153 | if resp.Diagnostics.HasError() {
154 | return
155 | }
156 |
157 | ctxDeadline, cancel := context.WithTimeout(ctx, readTimeout)
158 | defer cancel()
159 |
160 | selector := state.Selector.ValueString()
161 |
162 | if selector == "" {
163 | // if there is no selector, we can return all disks
164 | selector = "true"
165 | }
166 |
167 | exp, err := cel.ParseBooleanExpression(selector, celenv.DiskLocator())
168 | if err != nil {
169 | resp.Diagnostics.AddError("failed to parse celenv selector", err.Error())
170 |
171 | return
172 | }
173 |
174 | if err := retry.RetryContext(ctxDeadline, readTimeout, func() *retry.RetryError {
175 | if err := talosClientOp(ctx, state.Endpoint.ValueString(), state.Node.ValueString(), talosConfig, func(nodeCtx context.Context, c *client.Client) error {
176 | disks, err := blockhelpers.MatchDisks(nodeCtx, c.COSI, &exp)
177 | if err != nil {
178 | return err
179 | }
180 |
181 | for _, disk := range disks {
182 | state.Disks = append(state.Disks, diskspecToTFTypes(*disk.TypedSpec()))
183 | }
184 |
185 | return nil
186 | }); err != nil {
187 | if s := status.Code(err); s == codes.InvalidArgument {
188 | return retry.NonRetryableError(err)
189 | }
190 |
191 | if errors.Is(err, nodiskFoundError{}) {
192 | return retry.NonRetryableError(err)
193 | }
194 |
195 | return retry.RetryableError(err)
196 | }
197 |
198 | return nil
199 | }); err != nil {
200 | resp.Diagnostics.AddError("failed to get list of disks", err.Error())
201 |
202 | return
203 | }
204 |
205 | state.ID = basetypes.NewStringValue("machine_disks")
206 |
207 | diags = resp.State.Set(ctx, &state)
208 | resp.Diagnostics.Append(diags...)
209 |
210 | if resp.Diagnostics.HasError() {
211 | return
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/pkg/talos/talos_machine_disks_data_source_test.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | package talos_test
6 |
7 | import (
8 | "testing"
9 |
10 | "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
11 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
12 | )
13 |
14 | func TestAccTalosMachineDisksDataSource(t *testing.T) {
15 | rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
16 |
17 | resource.ParallelTest(t, resource.TestCase{
18 | ExternalProviders: map[string]resource.ExternalProvider{
19 | "libvirt": {
20 | Source: "dmacvicar/libvirt",
21 | },
22 | },
23 | ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
24 | Steps: []resource.TestStep{
25 | // test default config
26 | {
27 | Config: testAccTalosMachineDisksDataSourceConfigV0("talos", rName),
28 | Check: resource.ComposeAggregateTestCheckFunc(
29 | resource.TestCheckResourceAttr("data.talos_machine_disks.this", "id", "machine_disks"),
30 | resource.TestCheckResourceAttrSet("data.talos_machine_disks.this", "node"),
31 | resource.TestCheckResourceAttrSet("data.talos_machine_disks.this", "endpoint"),
32 | resource.TestCheckResourceAttrSet("data.talos_machine_disks.this", "client_configuration.ca_certificate"),
33 | resource.TestCheckResourceAttrSet("data.talos_machine_disks.this", "client_configuration.client_certificate"),
34 | resource.TestCheckResourceAttrSet("data.talos_machine_disks.this", "client_configuration.client_key"),
35 | resource.TestCheckResourceAttr("data.talos_machine_disks.this", "selector", "disk.size > 6u * GB"),
36 | resource.TestCheckResourceAttr("data.talos_machine_disks.this", "disks.#", "1"),
37 | resource.TestCheckResourceAttr("data.talos_machine_disks.this", "disks.0.dev_path", "/dev/vda"),
38 | ),
39 | },
40 | },
41 | })
42 | }
43 |
44 | func testAccTalosMachineDisksDataSourceConfigV0(providerName, rName string) string {
45 | config := dynamicConfig{
46 | Provider: providerName,
47 | ResourceName: rName,
48 | WithApplyConfig: false,
49 | WithBootstrap: false,
50 | }
51 |
52 | return config.render()
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/talos/talos_machine_disks_data_source_types.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | // Code generated by "diskspec.go"; DO NOT EDIT.
6 |
7 | package talos
8 |
9 | import (
10 | "github.com/hashicorp/terraform-plugin-framework/attr"
11 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
12 | "github.com/hashicorp/terraform-plugin-framework/types"
13 | "github.com/siderolabs/gen/xslices"
14 | "github.com/siderolabs/talos/pkg/machinery/resources/block"
15 | )
16 |
17 | type diskspec struct {
18 | DevPath types.String `tfsdk:"dev_path"`
19 | Size types.Int64 `tfsdk:"size"`
20 | PrettySize types.String `tfsdk:"pretty_size"`
21 | IOSize types.Int64 `tfsdk:"io_size"`
22 | SectorSize types.Int64 `tfsdk:"sector_size"`
23 | Readonly types.Bool `tfsdk:"readonly"`
24 | CDROM types.Bool `tfsdk:"cdrom"`
25 | Model types.String `tfsdk:"model"`
26 | Serial types.String `tfsdk:"serial"`
27 | Modalias types.String `tfsdk:"modalias"`
28 | WWID types.String `tfsdk:"wwid"`
29 | UUID types.String `tfsdk:"uuid"`
30 | BusPath types.String `tfsdk:"bus_path"`
31 | SubSystem types.String `tfsdk:"sub_system"`
32 | Transport types.String `tfsdk:"transport"`
33 | Rotational types.Bool `tfsdk:"rotational"`
34 | SecondaryDisks types.List `tfsdk:"secondary_disks"`
35 | Symlinks types.List `tfsdk:"symlinks"`
36 | }
37 |
38 | var diskspecAttributes = map[string]schema.Attribute{
39 | "dev_path": schema.StringAttribute{
40 | Computed: true,
41 | },
42 | "size": schema.Int64Attribute{
43 | Computed: true,
44 | },
45 | "pretty_size": schema.StringAttribute{
46 | Computed: true,
47 | },
48 | "io_size": schema.Int64Attribute{
49 | Computed: true,
50 | },
51 | "sector_size": schema.Int64Attribute{
52 | Computed: true,
53 | },
54 | "readonly": schema.BoolAttribute{
55 | Computed: true,
56 | },
57 | "cdrom": schema.BoolAttribute{
58 | Computed: true,
59 | },
60 | "model": schema.StringAttribute{
61 | Computed: true,
62 | },
63 | "serial": schema.StringAttribute{
64 | Computed: true,
65 | },
66 | "modalias": schema.StringAttribute{
67 | Computed: true,
68 | },
69 | "wwid": schema.StringAttribute{
70 | Computed: true,
71 | },
72 | "uuid": schema.StringAttribute{
73 | Computed: true,
74 | },
75 | "bus_path": schema.StringAttribute{
76 | Computed: true,
77 | },
78 | "sub_system": schema.StringAttribute{
79 | Computed: true,
80 | },
81 | "transport": schema.StringAttribute{
82 | Computed: true,
83 | },
84 | "rotational": schema.BoolAttribute{
85 | Computed: true,
86 | },
87 | "secondary_disks": schema.ListAttribute{
88 | ElementType: types.StringType,
89 | Computed: true,
90 | },
91 | "symlinks": schema.ListAttribute{
92 | ElementType: types.StringType,
93 | Computed: true,
94 | },
95 | }
96 |
97 | func diskspecToTFTypes(diskspecSpec block.DiskSpec) diskspec {
98 | return diskspec{
99 | DevPath: types.StringValue(diskspecSpec.DevPath),
100 | Size: types.Int64Value(int64(diskspecSpec.Size)),
101 | PrettySize: types.StringValue(diskspecSpec.PrettySize),
102 | IOSize: types.Int64Value(int64(diskspecSpec.IOSize)),
103 | SectorSize: types.Int64Value(int64(diskspecSpec.SectorSize)),
104 | Readonly: types.BoolValue(diskspecSpec.Readonly),
105 | CDROM: types.BoolValue(diskspecSpec.CDROM),
106 | Model: types.StringValue(diskspecSpec.Model),
107 | Serial: types.StringValue(diskspecSpec.Serial),
108 | Modalias: types.StringValue(diskspecSpec.Modalias),
109 | WWID: types.StringValue(diskspecSpec.WWID),
110 | UUID: types.StringValue(diskspecSpec.UUID),
111 | BusPath: types.StringValue(diskspecSpec.BusPath),
112 | SubSystem: types.StringValue(diskspecSpec.SubSystem),
113 | Transport: types.StringValue(diskspecSpec.Transport),
114 | Rotational: types.BoolValue(diskspecSpec.Rotational),
115 | SecondaryDisks: types.ListValueMust(types.StringType, xslices.Map(diskspecSpec.SecondaryDisks, func(s string) attr.Value {
116 | return types.StringValue(s)
117 | })),
118 | Symlinks: types.ListValueMust(types.StringType, xslices.Map(diskspecSpec.Symlinks, func(s string) attr.Value {
119 | return types.StringValue(s)
120 | })),
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/pkg/talos/testdata/patch-invalid.yaml:
--------------------------------------------------------------------------------
1 | machine:
2 | sysctl:
3 | foo: bar
4 |
--------------------------------------------------------------------------------
/pkg/talos/testdata/patch-json6502.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "op": "add",
4 | "path": "/cluster/allowSchedulingOnControlPlanes",
5 | "value": true
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/pkg/talos/testdata/patch-strategic.yaml:
--------------------------------------------------------------------------------
1 | machine:
2 | sysfs:
3 | foo: bar
4 | cluster:
5 | apiServer:
6 | extraArgs:
7 | foo: bar
8 |
--------------------------------------------------------------------------------
/pkg/talos/testdata/secrets.yaml:
--------------------------------------------------------------------------------
1 | cluster:
2 | id: _u8NZvwQ9ObtEN7iTzc-OEpk20K-rnO3FNcjvVEQ84Q=
3 | secret: UnZE8oq6qPNI8tuw+WF3PGi2Zba0RQuit/aJTflOau8=
4 | secrets:
5 | bootstraptoken: m2wfba.pcyzhp6rf6pubqtk
6 | secretboxencryptionsecret: avDR6jwn4iYS6sTOH689P2UcNUlh3UsuO+FaOKI2hls=
7 | trustdinfo:
8 | token: s5lcto.f2ythdlx6avcsny9
9 | certs:
10 | etcd:
11 | crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmakNDQVNTZ0F3SUJBZ0lSQUt6KzNQbkZYWHNTdXNQb3RLTnVabG93Q2dZSUtvWkl6ajBFQXdJd0R6RU4KTUFzR0ExVUVDaE1FWlhSalpEQWVGdzB5TXpBME1ERXhORE01TURaYUZ3MHpNekF6TWpreE5ETTVNRFphTUE4eApEVEFMQmdOVkJBb1RCR1YwWTJRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTbGFaU0p1UnhMCit4NDdYelY5OWIwaEd1dmdybGZrUnFEdStVUWlrSFJlRCtFL3VZUXprc1ArZTFLMVBUcFJVTG45ZEJYY21jd1AKazY2UXRCN09mQ0pEbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSApBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRk5kVHVVdmduZXcwCkJSa0dZRnJueWNpWFZjUTdNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUURJZGVqQ3ppL25xb3h0eUp3QnROTEYKTDE3UWdqQjNzMFoySUV5ZDZPTE51UUlnY0lHcWRWemJKQ3dXSkZXSWxnWWVyUGZvZzdzUjFxMWdKV25ST3p4UApBakE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
12 | key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUoxWVI2ck9pd3N2TmRWZFErVnpiQ1hlRlBEbGJ1cDVUM1ZidnJrVDM2M1NvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFcFdtVWlia2NTL3NlTzE4MWZmVzlJUnJyNEs1WDVFYWc3dmxFSXBCMFhnL2hQN21FTTVMRAovbnRTdFQwNlVWQzUvWFFWM0puTUQ1T3VrTFFlem53aVF3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
13 | k8s:
14 | crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpakNDQVMrZ0F3SUJBZ0lRSE5COFFlVjRtazlUR3k4amtTUGtYVEFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXpNRFF3TVRFME16a3dObG9YRFRNek1ETXlPVEUwTXprdwpObG93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCQVBKQjEwL3RnVFlkdVhrS0h6SVFEZDNLbW54MithbmFXcGN3RUlhWlhMbnNsRHRycGU3ancwaXRVK1oKa2w2eEd5STk4M0FpRkxWc004cHhra3RoZ2tTallUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVU1K0hGd29PbTdURWhpcm1DTGt2SllyRmRQc293Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQU1WZFNVUEUKcGlNWkpkNHNYV1pvdzdLb0djWWhPb1NtcDJkaUZEdUEzMjcyQWlFQTRuamcwN2ZhVEFGck1SUGF4SmFIMVhsdQpKTHBPMTh0bHZhVlVFMW5XY2xnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
15 | key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUZJQ0crOUR1Wm9YU0xiVjRWK1VoZkdRUWV5OUJ3dWEwZUx6M0hTU1hyMmhvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFQThrSFhUKzJCTmgyNWVRb2ZNaEFOM2NxYWZIYjVxZHBhbHpBUWhwbGN1ZXlVTzJ1bDd1UApEU0sxVDVtU1hyRWJJajN6Y0NJVXRXd3p5bkdTUzJHQ1JBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
16 | k8saggregator:
17 | crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZVENDQVFhZ0F3SUJBZ0lSQUtDY3hEVUM4UG9GK3pSajJWVlJLWTR3Q2dZSUtvWkl6ajBFQXdJd0FEQWUKRncweU16QTBNREV4TkRNNU1EWmFGdzB6TXpBek1qa3hORE01TURaYU1BQXdXVEFUQmdjcWhrak9QUUlCQmdncQpoa2pPUFFNQkJ3TkNBQVFPUjZKcTl1ekp3RWNFZnowc1dKdERVejhwNUpseHRJZkJjTTMzRFJ5cDhCSDZGQTFCCjJiUkx5ZTBsU3p6TXFmdVpFblhxOE9qazdobklGSUdsNlVNaW8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4dwpIUVlEVlIwT0JCWUVGQUpPaUFGNTRhUXRPaUpzdFU2U2Z1QWpGOFJwTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCklRREdPOUhXVXNaZlozRUdJTEdGRjJwUDIwUGNjSDZMV2hZSjg1eHB2RDBOSGdJaEFOOHFpVElXYVF2dUs3M1cKVENwT2g5TU1PS2o1YmFNcEh6M2FJOGVMZHBiVAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
18 | key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU4rRDdGWGJoUTg4c1d6eEJPSXZtMVJVVVBtT25VeFBCRGlvR21mL1dnMjlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFRGtlaWF2YnN5Y0JIQkg4OUxGaWJRMU0vS2VTWmNiU0h3WEROOXcwY3FmQVIraFFOUWRtMApTOG50SlVzOHpLbjdtUkoxNnZEbzVPNFp5QlNCcGVsRElnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
19 | k8sserviceaccount:
20 | key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUVabmsrN2djSXBLdC8vM2lrQ1dLZm5SNnFjeWY5bHVyK1lGbzQyTlhVVVlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFeG9rOTBEbnI2MGRYQ3BhQmxUMnVJUnRjdUJPLytCVjZEajVPaWYvTGVwSS95NktlQ2lRTApwRGZxenNHQW5zQXkrVHI3SWNxSUlROGZGaXRtK0t5emJBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
21 | os:
22 | crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQekNCOHFBREFnRUNBaEVBM0E0TEZ3cDVTZG5wTXVmYlp3NHVpekFGQmdNclpYQXdFREVPTUF3R0ExVUUKQ2hNRmRHRnNiM013SGhjTk1qTXdOREF4TVRRek9UQTJXaGNOTXpNd016STVNVFF6T1RBMldqQVFNUTR3REFZRApWUVFLRXdWMFlXeHZjekFxTUFVR0F5dGxjQU1oQUZ2TWUyeHFzSk9WemkvY0xLNXVXVzU2VmZZK29nWlYvQVowCmxlTFdtTWl1bzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUcKQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkxqK3VablllVFFUdEdmUgpOeVVQYWh6dzNkdkhNQVVHQXl0bGNBTkJBQVg4cVhJNm4ydlk3ZGxnZGtxckUvN25ua2kwTzFtVERDL3dBamlwCmpaemY5QmhocEdRUXFYSkxHdlhJTnRDaXN5KzQrcTVtOUVjUUpMMXF4UWdOdndnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
23 | key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJSlVlQmxic3hhMW0vR1B0NTZCeVIvZ1Z3YWRzVmdkc3pXZEh4MWZiZ0c4VwotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K
24 |
--------------------------------------------------------------------------------
/pkg/talos/testdata/secretsv1.2.yaml:
--------------------------------------------------------------------------------
1 | cluster:
2 | id: q_I385nl7MWqU1UpW224rQyZW4TWd_WmnxsA2MQLsl8=
3 | secret: 1szT7qMuensSCcSVRtnFsG0pbXMLMSZ8r5wu/41aJBc=
4 | secrets:
5 | bootstraptoken: 5co9z6.qnnjtotc5ffntt62
6 | aescbcencryptionsecret: hLrjDIpZ8gSGwejFfnUnjOrn9PQ7Bj3yq/ggAgD9AHA=
7 | trustdinfo:
8 | token: o2q4ek.ofdeihu3li44x7lr
9 | certs:
10 | etcd:
11 | crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmakNDQVNTZ0F3SUJBZ0lSQU8rYmlXSlFJdHZXZUZ0UUNEVDhwRXd3Q2dZSUtvWkl6ajBFQXdJd0R6RU4KTUFzR0ExVUVDaE1FWlhSalpEQWVGdzB5TXpBME1ERXhOVFF4TURSYUZ3MHpNekF6TWpreE5UUXhNRFJhTUE4eApEVEFMQmdOVkJBb1RCR1YwWTJRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFReHRnaFlZV1AvCngzWGFBM1RPVXd4Y1AySlh2QVYzdllaS2I1SENKK0E2M2dieE50dW5Gcm03NW8rK0ZQQndYdUtZUmMrU09pTXEKdWY5bjdkZmY4cUJKbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSApBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkU2VUVneitoOSsvCnZYdnNod1d2bHJvQkh6SlFNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUUQ3YTFzMy91cmRybFlxaXJxTmN6aTIKTm5qNVFCdFVmczFNYkNqNTdkYXR3d0lnZlJYdEIyWVZMUy9OMFVQTDkxekhITCtLM09EaEZ2M1dsc0gwMlpmdgpMNHc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
12 | key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUJDNUpZQmgzWWQ2NnJwWkcvTHZEMWt4SFRvWTA4QnZsQkpMcy9aZXR4NldvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFTWJZSVdHRmovOGQxMmdOMHpsTU1YRDlpVjd3RmQ3MkdTbStSd2lmZ090NEc4VGJicHhhNQp1K2FQdmhUd2NGN2ltRVhQa2pvaktybi9aKzNYMy9LZ1NRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
13 | k8s:
14 | crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRVW9hWGkyZGxUWHk1alNBUVdvSUZOVEFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXpNRFF3TVRFMU5ERXdORm9YRFRNek1ETXlPVEUxTkRFdwpORm93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCRWJieTQreTdIWmZUcVNNaDRtMWx3a3E3THE5WUtWdVhmV3BJLzZ4K1orZC9uUFJFNFA0eGhNUklKL3oKZHl4TDJxTGNSOUcxV3pjVWJBRVYrMjliUWNDallUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVUzRG8xb2MzM054dWhYRTJ4M2NvbHM3a2dWWmN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQU9pb3RHR1MKNnJLdWFoT2twMlQ5NjRzSUhhdmx3bUJqZ0ljVkI1dTFPV2RsQWlBRXZKUUVTRGNBZWlmVm1seG1pdWVDMHl4SQowODBqY2FxUjdUVWNjaHhrSnc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
15 | key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUx5bm9FaURjeG1NL3ZlL1B1R0YwWFNjeEgydG10SGZSdVU0SkVvejBGRmtvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFUnR2TGo3THNkbDlPcEl5SGliV1hDU3JzdXIxZ3BXNWQ5YWtqL3JINW41MytjOUVUZy9qRwpFeEVnbi9OM0xFdmFvdHhIMGJWYk54UnNBUlg3YjF0QndBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
16 | k8saggregator:
17 | crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZRENDQVFhZ0F3SUJBZ0lSQUp5THJmLzk5aE00a1ZNWTJraFd4TjR3Q2dZSUtvWkl6ajBFQXdJd0FEQWUKRncweU16QTBNREV4TlRReE1EUmFGdzB6TXpBek1qa3hOVFF4TURSYU1BQXdXVEFUQmdjcWhrak9QUUlCQmdncQpoa2pPUFFNQkJ3TkNBQVFZTTBWWUVZWTVOaURlNHp6Z21mYlJSdDRNalRmOUlyeUVVcms1SjNPRFQzYkFpanVDCmd6eWpmTkZIbFlXbm9PcWZBeGpjVVVsQkU2L2xuRmdiMzNwUW8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4dwpIUVlEVlIwT0JCWUVGTHBKUEhhRGw1UjY4NjlDNEVyVXF5WHhBeUpWTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDCklFc0VlOElSNEwvK3phMC9CbzlUNGRKbERpQ3VDK1BSd1JueXE4OEE5dFUvQWlFQTBGUXNJcGk5V1ZiU2krODQKQkVCaGRWTkpmQUVUYTZVQ2UrTWFsNUJRUjlrPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
18 | key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUMxSDViQUY5RkJWQzVIQjZ2dzJwL1FRUFkvWEVjdzhaTUJ0ZDZFTmw3cXFvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFR0RORldCR0dPVFlnM3VNODRKbjIwVWJlREkwMy9TSzhoRks1T1NkemcwOTJ3SW83Z29NOApvM3pSUjVXRnA2RHFud01ZM0ZGSlFST3Y1WnhZRzk5NlVBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
19 | k8sserviceaccount:
20 | key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxHRjlhcmp4SEdyMExMbTdMTjg0Ympjbml2RWpGSkxlUFNvVGhZUS9maWdvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFNjRuQVlld3hqeVkrVkY4MDZ5WU5iU3pnNEl4cFh6TW1hMW93b3FjbDc5elZtMkRsbHcxUApYR3FTZ0hpWUxwcjZ1ZU5OeSswcXdOdklCU3RKSXZLVzNnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
21 | os:
22 | crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQakNCOGFBREFnRUNBaEIzcXY0bDNhTStSaGFsWmdHOGowdDNNQVVHQXl0bGNEQVFNUTR3REFZRFZRUUsKRXdWMFlXeHZjekFlRncweU16QTBNREV4TlRReE1EUmFGdzB6TXpBek1qa3hOVFF4TURSYU1CQXhEakFNQmdOVgpCQW9UQlhSaGJHOXpNQ293QlFZREsyVndBeUVBWk1TT1d4aHF4UThEbHdUVmszM2xRN09ydDAvOTE5b0JXTVpUCmRSU3Q4SGFqWVRCZk1BNEdBMVVkRHdFQi93UUVBd0lDaERBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFRWUkKS3dZQkJRVUhBd0l3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVYkhDeHcyOTd4RHc3Tjh0SQpDQTJTUDc2K3Q5OHdCUVlESzJWd0EwRUFrcnQ1UEVnZ2JZNFFlYnNIa2lDTmZlMFpZNlE1UmZhVm52TVRxOE1lCnRhSktTQ1NPYTljczh2dXVDMnl2QmNSU0hPWldocG9WaW05bXhEaVc3TDZTQXc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
23 | key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJRjdtNmJKWHNOd3F4ejFMaXRnVlFJSEx5WDJab1hadW85UTNEZjRGSThWaAotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K
24 |
--------------------------------------------------------------------------------
/templates/data-sources/machine_configuration.md.tmpl:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "{{.Name}} {{.Type}} - {{.RenderedProviderName}}"
3 | subcategory: ""
4 | description: |-
5 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }}
6 | ---
7 |
8 | # {{.Name}} ({{.Type}})
9 |
10 | {{ .Description | trimspace }}
11 |
12 | -> **Note:** It is recommended to set the optional `talos_version` attribute. Otherwise when using a new version of the provider with a new major version of the Talos SDK, new machineconfig features will be enabled by default which could cause unexpected behavior.
13 |
14 | {{ if .HasExample -}}
15 | ## Example Usage
16 |
17 | {{ tffile (printf .ExampleFile) }}
18 | {{- end }}
19 | {{ .SchemaMarkdown | trimspace }}
20 |
--------------------------------------------------------------------------------
/templates/data-sources/machine_disks.md.tmpl:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "{{.Name}} {{.Type}} - {{.RenderedProviderName}}"
3 | subcategory: ""
4 | description: |-
5 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }}
6 | ---
7 |
8 | # {{.Name}} ({{.Type}})
9 |
10 | {{ .Description | trimspace }}
11 |
12 | -> **Note:** Since Talos natively supports `.machine.install.diskSelector`, the `talos_machine_disks` data source maybe just used to query disk information that could be used elsewhere. It's recommended to use `machine.install.diskSelector` in Talos machine configuration.
13 |
14 | {{ if .HasExample -}}
15 | ## Example Usage
16 |
17 | {{ tffile (printf .ExampleFile) }}
18 | {{- end }}
19 | {{ .SchemaMarkdown | trimspace }}
20 |
--------------------------------------------------------------------------------
/templates/guides/version-0.2-upgrade.html.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "Terraform Talos Provider Version 0.2 Upgrade Guide"
3 | description: |-
4 | Terraform Talos Provider Version 0.2 Upgrade Guide
5 | ---
6 |
7 | # Terraform Talos Provider Version 0.2 Upgrade Guide
8 |
9 | Version 0.2 of the Talos Terraform provider is a major release and include some breaking chages. This guide will walk you through the changes and how to upgrade your Terraform configuration.
10 |
11 | ~> **NOTE:** Version 0.2 of the Talos Terraform provider drops support for the following resources:
12 |
13 | > * `talos_client_configuration`
14 | > * `talos_cluster_kubeconfig`
15 | > * `talos_machine_configuration_controlplane`
16 | > * `talos_machine_configuration_worker`
17 |
18 | The following table lists the resources that have been removed and the new resources that replace them.
19 |
20 | | Removed Resource | Type | New Resource | Type |
21 | | ------------------------------------------ | -------- | ----------------------------- | ------------- |
22 | | `talos_client_configuration` | Resource | `talos_client_configuration` | Data Source |
23 | | `talos_cluster_kubeconfig` | Resource | `talos_cluster_kubeconfig` | Data Source |
24 | | `talos_machine_configuration_controlplane` | Resource | `talos_machine_configuration` | Data Resource |
25 | | `talos_machine_configuration_worker` | Resource | `talos_machine_configuration` | Data Resource |
26 |
27 | ## Upgrade topics:
28 |
29 | - [Upgrading `talos_client_configuration` resource](#upgrading-talos_client_configuration-resource)
30 | - [Upgrading `talos_cluster_kubeconfig` resource](#upgrading-talos_cluster_kubeconfig-resource)
31 | - [Upgrading `talos_machine_configuration_controlplane` resource](#upgrading-talos_machine_configuration_controlplane-resource)
32 | - [Upgrading `talos_machine_configuration_worker` resource](#upgrading-talos_machine_configuration_worker-resource)
33 |
34 | ### Upgrading `talos_client_configuration` resource
35 |
36 | The `talos_client_configuration` resource has been removed. The `talos_client_configuration` data source should be used instead.
37 |
38 | For example if the following resource was used:
39 |
40 | ```hcl
41 | resource "talos_machine_secrets" "this" {}
42 |
43 | resource "talos_client_configuration" "talosconfig" {
44 | cluster_name = "example-cluster"
45 | machine_secrets = talos_machine_secrets.this.machine_secrets
46 | }
47 | ```
48 |
49 | `talos_client_configuration` resource should be first removed from the state:
50 |
51 | ```bash
52 | terraform state rm talos_client_configuration.talosconfig
53 | ```
54 |
55 | and the code should be updated to:
56 |
57 | ```hcl
58 | resource "talos_machine_secrets" "machine_secrets" {}
59 |
60 | data "talos_client_configuration" "this" {
61 | cluster_name = "example-cluster"
62 | client_configuration = talos_machine_secrets.this.client_configuration
63 | }
64 | ```
65 |
66 | ### Upgrading `talos_cluster_kubeconfig` resource
67 |
68 | The `talos_cluster_kubeconfig` resource has been removed. The `talos_cluster_kubeconfig` data source should be used instead.
69 |
70 | For example if the following resource was used:
71 |
72 | ```hcl
73 | resource "talos_machine_secrets" "this" {}
74 |
75 | resource "talos_client_configuration" "this" {
76 | cluster_name = "example-cluster"
77 | machine_secrets = talos_machine_secrets.this.machine_secrets
78 | }
79 |
80 | resource "talos_cluster_kubeconfig" "kubeconfig" {
81 | talos_config = talos_client_configuration.this.talos_config
82 | endpoint = "10.5.0.2"
83 | node = "10.5.0.2"
84 | }
85 | ```
86 |
87 | `talos_cluster_kubeconfig` resource should be first removed from the state:
88 |
89 | ```bash
90 | terraform state rm talos_cluster_kubeconfig.kubeconfig
91 | ```
92 |
93 | and the code should be updated to:
94 |
95 | ```hcl
96 | resource "talos_machine_secrets" "machine_secrets" {}
97 |
98 | data "talos_cluster_kubeconfig" "this" {
99 | client_configuration = talos_machine_secrets.this.client_configuration
100 | node = "10.5.0.2"
101 | }
102 | ```
103 |
104 | ### Upgrading `talos_machine_configuration_controlplane` resource
105 |
106 | The `talos_machine_configuration_controlplane` resource has been removed. The `talos_machine_configuration` data source should be used instead.
107 |
108 | For example if the following resource was used:
109 |
110 | ```hcl
111 | resource "talos_machine_secrets" "this" {}
112 |
113 | resource "talos_client_configuration" "this" {
114 | cluster_name = "example-cluster"
115 | machine_secrets = talos_machine_secrets.this.machine_secrets
116 | }
117 |
118 | resource "talos_machine_configuration_controlplane" "this" {
119 | cluster_name = "example-cluster"
120 | cluster_endpoint = "https://10.5.0.2:6443"
121 | machine_secrets = talos_machine_secrets.this.machine_secrets
122 | }
123 |
124 | resource "talos_machine_configuration_apply" "this" {
125 | talos_config = talos_client_configuration.this.talos_config
126 | machine_configuration = talos_machine_configuration_controlplane.this.machine_config
127 | node = "10.5.0.2"
128 | endpoint = "10.5.0.2"
129 | }
130 | ```
131 |
132 | `talos_machine_configuration_controlplane` resource should be first removed from the state:
133 |
134 | ```bash
135 | terraform state rm talos_machine_configuration_controlplane.cp
136 | ```
137 |
138 | and the code should be updated to:
139 |
140 | ```hcl
141 | resource "talos_machine_secrets" "machine_secrets" {}
142 |
143 | data "talos_machine_configuration" "this" {
144 | cluster_name = "example-cluster"
145 | cluster_endpoint = "https://10.5.0.2:6443"
146 | machine_type = "controlplane"
147 | talos_version = talos_machine_secrets.this.talos_version
148 | machine_secrets = talos_machine_secrets.this.machine_secrets
149 | }
150 |
151 | resource "talos_machine_configuration_apply" "this" {
152 | client_configuration = talos_machine_secrets.this.client_configuration
153 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
154 | node = "10.5.0.2"
155 | }
156 | ```
157 |
158 | ### Upgrading `talos_machine_configuration_worker` resource
159 |
160 | The `talos_machine_configuration_worker` resource has been removed. The `talos_machine_configuration` data source should be used instead.
161 |
162 | For example if the following resource was used:
163 |
164 | ```hcl
165 | resource "talos_machine_secrets" "this" {}
166 |
167 | resource "talos_client_configuration" "this" {
168 | cluster_name = "example-cluster"
169 | machine_secrets = talos_machine_secrets.this.machine_secrets
170 | }
171 |
172 | resource "talos_machine_configuration_worker" "this" {
173 | cluster_name = "example-cluster"
174 | cluster_endpoint = "https://10.5.0.2:6443"
175 | machine_secrets = talos_machine_secrets.this.machine_secrets
176 | }
177 |
178 | resource "talos_machine_configuration_apply" "this" {
179 | talos_config = talos_client_configuration.this.talos_config
180 | machine_configuration = talos_machine_configuration_worker.this.machine_config
181 | node = "10.5.0.3"
182 | endpoint = "10.5.0.3"
183 | }
184 | ```
185 |
186 | `talos_machine_configuration_worker` resource should be first removed from the state:
187 |
188 | ```bash
189 | terraform state rm talos_machine_configuration_worker.worker
190 | ```
191 |
192 | and the code should be updated to:
193 |
194 | ```hcl
195 | resource "talos_machine_secrets" "machine_secrets" {}
196 |
197 | data "talos_machine_configuration" "this" {
198 | cluster_name = "example-cluster"
199 | cluster_endpoint = "https://10.5.0.2:6443"
200 | machine_type = "worker"
201 | talos_version = talos_machine_secrets.this.talos_version
202 | machine_secrets = talos_machine_secrets.this.machine_secrets
203 | }
204 |
205 | resource "talos_machine_configuration_apply" "this" {
206 | client_configuration = talos_machine_secrets.this.client_configuration
207 | machine_configuration_input = data.talos_machine_configuration.this.machine_configuration
208 | node = "10.5.0.3"
209 | }
210 | ```
211 |
--------------------------------------------------------------------------------
/templates/index.md.tmpl:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "Provider: Talos"
3 | description: |-
4 | The Talos provider is used to manage a Talos cluster config generation and initial setup.
5 | ---
6 |
7 | # Talos Provider
8 |
9 | Talos provider allows to generate configs for a Talos cluster and apply them to the nodes, bootstrap nodes, check cluster health, and retrieve `kubeconfig` and `talosconfig`.
10 |
11 | Complete usages for this provider across a variety of environments can be found [here](https://github.com/siderolabs/contrib/tree/main/examples/terraform).
12 |
--------------------------------------------------------------------------------
/templates/resources.md.tmpl:
--------------------------------------------------------------------------------
1 | ---
2 | page_title: "{{.Name}} {{.Type}} - {{.RenderedProviderName}}"
3 | subcategory: ""
4 | description: |-
5 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }}
6 | ---
7 |
8 | # {{.Name}} ({{.Type}})
9 |
10 | {{ .Description | trimspace }}
11 |
12 | {{ if .HasExample -}}
13 | ## Example Usage
14 |
15 | {{ tffile (printf .ExampleFile) }}
16 | {{- end }}
17 | {{ .SchemaMarkdown | trimspace }}
18 | {{ if .HasImport -}}
19 | ## Import
20 |
21 | Import is supported using the following syntax:
22 |
23 | {{ tffile (printf .ImportFile) }}
24 | {{- end }}
25 |
--------------------------------------------------------------------------------
/terraform-registry-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "metadata": {
4 | "protocol_versions": [
5 | "5.0"
6 | ]
7 | }
8 | }
--------------------------------------------------------------------------------
/tools/tools.go:
--------------------------------------------------------------------------------
1 | // This Source Code Form is subject to the terms of the Mozilla Public
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 |
5 | //go:build tools
6 |
7 | package tools
8 |
9 | import (
10 | // document generation
11 | _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs"
12 | )
13 |
--------------------------------------------------------------------------------