From 77fae782cb0209466d4153fa67a63b724509f2d9 Mon Sep 17 00:00:00 2001 From: AleDecre Date: Wed, 21 Dec 2022 17:31:40 +0000 Subject: [PATCH] Added provider and resources implementations Co-authored-by: Erasmo <58850674+erasmonotaro@users.noreply.github.com> --- .github/workflows/lint.yml | 67 +++ .github/workflows/release.yml | 41 ++ .golangci.yml | 133 +++++ .goreleaser.yml | 60 +++ .markdownlint.yml | 3 + .markdownlintignore | 1 + README.md | 30 +- docs/index.md | 63 +++ docs/resources/generate.md | 29 + docs/resources/offload.md | 47 ++ docs/resources/peer.md | 29 + examples/provider/provider.tf | 6 + .../resources/generate_resource/resource.tf | 2 + .../resources/offload_resource/resource.tf | 19 + .../resources/peering_resource/resource.tf | 9 + go.mod | 101 ++++ go.sum | 505 ++++++++++++++++++ liqo/attribute_plan_modifier/default_value.go | 42 ++ liqo/generate_resource.go | 195 +++++++ liqo/offload_resource.go | 276 ++++++++++ liqo/peer_resource.go | 271 ++++++++++ liqo/provider.go | 407 ++++++++++++++ main.go | 20 + terraform-registry-manifest.json | 6 + tools/tools.go | 8 + 25 files changed, 2354 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/release.yml create mode 100644 .golangci.yml create mode 100644 .goreleaser.yml create mode 100644 .markdownlint.yml create mode 100644 .markdownlintignore create mode 100644 docs/index.md create mode 100644 docs/resources/generate.md create mode 100644 docs/resources/offload.md create mode 100644 docs/resources/peer.md create mode 100644 examples/provider/provider.tf create mode 100644 examples/resources/generate_resource/resource.tf create mode 100644 examples/resources/offload_resource/resource.tf create mode 100644 examples/resources/peering_resource/resource.tf create mode 100644 go.mod create mode 100644 go.sum create mode 100644 liqo/attribute_plan_modifier/default_value.go create mode 100644 liqo/generate_resource.go create mode 100644 liqo/offload_resource.go create mode 100644 liqo/peer_resource.go create mode 100644 liqo/provider.go create mode 100644 main.go create mode 100644 terraform-registry-manifest.json create mode 100644 tools/tools.go diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..de075be --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,67 @@ +name: Linting +on: + pull_request: + +jobs: + golangci: + name: Lint golang files + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + repository: ${{github.event.pull_request.head.repo.full_name}} + persist-credentials: false + + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: 1.19 + + - name: golangci-lint + uses: golangci/golangci-lint-action@v3.3.1 + with: + only-new-issues: true + version: v1.50.0 + + gomodtidy: + name: Enforce go.mod tidiness + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: "${{ github.event.pull_request.head.sha }}" + repository: ${{github.event.pull_request.head.repo.full_name}} + persist-credentials: false + + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: 1.19 + + - name: Execute go mod tidy and check the outcome + working-directory: ./ + run: | + go mod tidy + exit_code=$(git diff --exit-code) + exit ${exit_code} + + markdownlint: + name: Lint markdown files + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3 + with: + ref: "${{ github.event.pull_request.head.sha }}" + repository: ${{github.event.pull_request.head.repo.full_name}} + persist-credentials: false + + - name: Lint markdown files + uses: avto-dev/markdown-lint@v1 + with: + config: '.markdownlint.yml' + args: '**/*.md' \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..eaf72a9 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +# Terraform Provider release workflow. +name: Release + +# This GitHub action creates a release when a tag that matches the pattern +# "v*" (e.g. v0.1.0) is created. +on: + push: + tags: + - 'v*' + +# Releases need permissions to read and write the repository contents. +# GitHub considers creating releases and uploading assets as writing contents. +permissions: + contents: write + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + # Allow goreleaser to access older tag information. + fetch-depth: 0 + - uses: actions/setup-go@v3 + with: + go-version-file: 'go.mod' + cache: true + - name: Import GPG key + uses: crazy-max/ghaction-import-gpg@v5 + id: import_gpg + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.PASSPHRASE }} + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v4 + with: + args: release --rm-dist + env: + # GitHub sets the GITHUB_TOKEN secret automatically. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..8192fd5 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,133 @@ +run: + timeout: 10m + skip-files: + - "zz_generated.*.go" + +linters-settings: + exhaustive: + check-generated: false + default-signifies-exhaustive: true + + lll: + line-length: 150 + gomodguard: + blocked: + modules: + - github.com/go-logr/logr: + recommendations: + - k8s.io/klog/v2 + gci: + sections: + - standard # Captures all standard packages if they do not match another section. + - default # Contains all imports that could not be matched to another section type. + - prefix(github.com/liqotech) # Groups all imports with the specified Prefix. + goconst: + min-len: 2 + min-occurrences: 2 + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + disabled-checks: + # Conflicts with govet check-shadowing + - sloppyReassign + goimports: + local-prefixes: github.com/liqotech + govet: + check-shadowing: true + misspell: + locale: US + nolintlint: + allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space) + allow-unused: false # report any unused nolint directives + require-explanation: true # require an explanation for nolint directives + require-specific: true # require nolint directives to be specific about which linter is being skipped + dupl: + threshold: 300 + +linters: + disable-all: true + enable: + - asciicheck + - bodyclose + - depguard + - dogsled + - dupl + - errcheck + - errorlint + - exhaustive + - exportloopref + # - funlen + # - gochecknoglobals + # - gochecknoinits + # - gocognit + - gci + - goconst + - gocritic + - gocyclo + - godot + # - godox + # - goerr113 + - gofmt + - goheader + - goimports + - gomodguard + # - gomnd + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - lll + # - maligned + - misspell + - nakedret + # - nestif + - noctx + - nolintlint + # - prealloc + - revive + - rowserrcheck + - staticcheck + - stylecheck + # - testpackage + - typecheck + - unconvert + - unparam + - unused + - whitespace + # - wsl + +issues: + #fix: true + + max-issues-per-linter: 0 + max-same-issues: 0 + + # Disable the default exclude patterns (as they disable the mandatory comments) + exclude-use-default: false + exclude: + # errcheck: Almost all programs ignore errors on these functions and in most cases it's ok + - Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked + + exclude-rules: + - linters: + - govet + text: 'declaration of "(err|ctx)" shadows declaration at' + - linters: + - gosec + # Disable the check to test that HTTP clients are not using an insecure TLS connection. + # We need it to contact the remote authentication services exposing a self-signed certificate + text: TLS InsecureSkipVerify set true. + - linters: + - errorlint + # Disable the check to test errors type assertion on switches. + text: type switch on error will fail on wrapped errors. Use errors.As to check for specific errors + + # Exclude the following linters from running on tests files. + - path: _test\.go + linters: + - whitespace \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..9bb0aa7 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,60 @@ +# Visit https://goreleaser.com for documentation on how to customize this +# behavior. +before: + hooks: + # this is just an example and not a requirement for provider building/publishing + - go mod tidy +builds: +- env: + # goreleaser does not work with CGO, it could also complicate + # usage by users in CI/CD systems like Terraform Cloud where + # they are unable to install libraries. + - CGO_ENABLED=0 + mod_timestamp: '{{ .CommitTimestamp }}' + flags: + - -trimpath + ldflags: + - '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}}' + goos: + - freebsd + - windows + - linux + - darwin + goarch: + - amd64 + - '386' + - arm + - arm64 + ignore: + - goos: darwin + goarch: '386' + binary: '{{ .ProjectName }}_v{{ .Version }}' +archives: +- format: zip + name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}' +checksum: + extra_files: + - glob: 'terraform-registry-manifest.json' + name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json' + name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS' + algorithm: sha256 +signs: + - artifacts: checksum + args: + # if you are using this in a GitHub action or some other automated pipeline, you + # need to pass the batch flag to indicate its not interactive. + - "--batch" + - "--local-user" + - "{{ .Env.GPG_FINGERPRINT }}" # set this environment variable for your signing key + - "--output" + - "${signature}" + - "--detach-sign" + - "${artifact}" +release: + extra_files: + - glob: 'terraform-registry-manifest.json' + name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json' + # If you want to manually examine the release before its live, uncomment this line: + # draft: true +changelog: + skip: true diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 0000000..ffd4281 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,3 @@ +default: true +line-length: false +no-inline-html: false \ No newline at end of file diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000..5c457d7 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1 @@ +docs \ No newline at end of file diff --git a/README.md b/README.md index cf6aeba..8efa5b0 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,42 @@ # Liqo provider - Provider for Terraform to perform Liqo operations. +> Provider for Terraform to perform Liqo operations. ## Getting Started + Follow this example steps to test locally the implemented provider. ### Prerequisites + - [Terraform](https://developer.hashicorp.com/terraform/downloads) -- [Liqo CLI tool](https://docs.liqo.io/en/v0.6.1/installation/liqoctl.html) - [go](https://go.dev/doc/install) ### Installation -1. in ***.terraform.d*** folder (you should have it in home/\/) make directory with this command replacing _architecture_ with your architecture (example: linux_arm64 or linux_amd64): - ``` mkdir -p /plugins/liqo-provider/liqo/liqo/0.0.1// ``` +1. in ***.terraform.d*** folder (you should have it in home/\/) make directory with this command replacing *architecture* with your architecture (example: linux_arm64 or linux_amd64): + + `mkdir -p /plugins/liqo-provider/liqo/liqo/0.0.1//` my complete path is the following: - ```home//.terraform.d/plugins/liqo-provider/liqo/liqo/0.0.1/linux_arm64/``` + `home//.terraform.d/plugins/liqo-provider/liqo/liqo/0.0.1/linux_arm64/` -2. from root run command replacing _path_ with the one created in first step: +2. from root run command replacing *path* with the one created in first step: - ```go build -o /terraform-provider-liqo ``` + `go build -o /terraform-provider-liqo` -3. in your main.tf tell to Terraform to use provider implemented locally by yoursel with this directive in required_providers: +3. in your main.tf tell to Terraform to use provider implemented locally +by yourself with this directive in *required_providers*: ```source = "liqo-provider/liqo/liqo"``` for example: - ```hcl + + ```terraform terraform { required_providers { liqo = { - source = "liqo-provider/liqo/liqo" + source = "liqo-provider/liqo/liqo" } } } ``` - -4. run command: - - ```terraform init ``` - - ```terraform apply -auto-approve``` diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..8e1c902 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,63 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "liqo Provider" +subcategory: "" +description: |- + Interact with Liqo. +--- + +# liqo Provider + +Interact with Liqo. + +## Example Usage + +```terraform +# Initialization of kubernetes clients +provider "liqo" { + kubernetes = { + config_path = "path/to/kubeconfig" + } +} +``` + + +## Schema + +### Optional + +- `kubernetes` (Attributes) (see [below for nested schema](#nestedatt--kubernetes)) + + +### Nested Schema for `kubernetes` + +Optional: + +- `client_certificate` (String) PEM-encoded client certificate for TLS authentication. +- `client_key` (String) PEM-encoded client certificate key for TLS authentication. +- `cluster_ca_certificate` (String) PEM-encoded root certificates bundle for TLS authentication. +- `config_context` (String) +- `config_context_auth_info` (String) +- `config_context_cluster` (String) +- `config_path` (String) Path to the kube config file. Can be set with KubeConfigPath. +- `config_paths` (List of String) +- `exec` (Attributes) (see [below for nested schema](#nestedatt--kubernetes--exec)) +- `host` (String) The hostname (in form of URI) of Kubernetes master. +- `insecure` (Boolean) Whether server should be accessed without verifying the TLS certificate. +- `password` (String) The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint. +- `proxy_url` (String) URL to the proxy to be used for all API requests +- `token` (String) Token to authenticate an service account +- `username` (String) The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint. + + +### Nested Schema for `kubernetes.exec` + +Required: + +- `api_version` (String) +- `command` (String) + +Optional: + +- `args` (List of String) +- `env` (Map of String) diff --git a/docs/resources/generate.md b/docs/resources/generate.md new file mode 100644 index 0000000..5580030 --- /dev/null +++ b/docs/resources/generate.md @@ -0,0 +1,29 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "liqo_generate Resource - liqo" +subcategory: "" +description: |- + Generate peering parameters for remote clusters +--- + +# liqo_generate (Resource) + +Generate peering parameters for remote clusters + + + + +## Schema + +### Optional + +- `liqo_namespace` (String) Namespace where is Liqo installed in provider cluster. + +### Read-Only + +- `auth_ep` (String) Provider authentication endpoint. +- `cluster_id` (String) Provider cluster ID. +- `cluster_name` (String) Provider cluster name. +- `local_token` (String) Provider authentication token. + + diff --git a/docs/resources/offload.md b/docs/resources/offload.md new file mode 100644 index 0000000..4efde03 --- /dev/null +++ b/docs/resources/offload.md @@ -0,0 +1,47 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "liqo_offload Resource - liqo" +subcategory: "" +description: |- + Offload a namespace. +--- + +# liqo_offload (Resource) + +Offload a namespace. + + + + +## Schema + +### Required + +- `namespace` (String) Offload a namespace. + +### Optional + +- `cluster_selector_terms` (Attributes List) Selectors to restrict the set of remote clusters. (see [below for nested schema](#nestedatt--cluster_selector_terms)) +- `namespace_mapping_strategy` (String) Naming strategy used to create the remote namespace. +- `pod_offloading_strategy` (String) Namespace to offload. + + +### Nested Schema for `cluster_selector_terms` + +Optional: + +- `match_expressions` (Attributes List) A list of cluster selector. (see [below for nested schema](#nestedatt--cluster_selector_terms--match_expressions)) + + +### Nested Schema for `cluster_selector_terms.match_expressions` + +Required: + +- `key` (String) The label key that the selector applies to. +- `operator` (String) Represents a key's relationship to a set of values. + +Optional: + +- `values` (List of String) An array of string values. + + diff --git a/docs/resources/peer.md b/docs/resources/peer.md new file mode 100644 index 0000000..e4238f2 --- /dev/null +++ b/docs/resources/peer.md @@ -0,0 +1,29 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "liqo_peer Resource - liqo" +subcategory: "" +description: |- + Execute peering. +--- + +# liqo_peer (Resource) + +Execute peering. + + + + +## Schema + +### Required + +- `cluster_authurl` (String) Provider authentication url used for peering. +- `cluster_id` (String) Provider cluster ID used for peering. +- `cluster_name` (String) Provider cluster name used for peering. +- `cluster_token` (String) Provider authentication token used for peering. + +### Optional + +- `liqo_namespace` (String) Namespace where is Liqo installed in provider cluster. + + diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf new file mode 100644 index 0000000..ae896ab --- /dev/null +++ b/examples/provider/provider.tf @@ -0,0 +1,6 @@ +# Initialization of kubernetes clients +provider "liqo" { + kubernetes = { + config_path = "path/to/kubeconfig" + } +} \ No newline at end of file diff --git a/examples/resources/generate_resource/resource.tf b/examples/resources/generate_resource/resource.tf new file mode 100644 index 0000000..15a7696 --- /dev/null +++ b/examples/resources/generate_resource/resource.tf @@ -0,0 +1,2 @@ +# Generate peer parameters. +resource "liqo_generate" "generate" {} \ No newline at end of file diff --git a/examples/resources/offload_resource/resource.tf b/examples/resources/offload_resource/resource.tf new file mode 100644 index 0000000..59f4cb8 --- /dev/null +++ b/examples/resources/offload_resource/resource.tf @@ -0,0 +1,19 @@ +# +resource "liqo_offload" "offload" { + + namespace = "liqo-demo" + pod_offloading_strategy = "LocalAndRemote" + namespace_mapping_strategy = "DefaultName" + cluster_selector_terms = [ + { + match_expressions = [ + { + key = "region" + operator = "In" + values = ["europe", "us-west"] + }, + ] + } + ] + +} diff --git a/examples/resources/peering_resource/resource.tf b/examples/resources/peering_resource/resource.tf new file mode 100644 index 0000000..99227f9 --- /dev/null +++ b/examples/resources/peering_resource/resource.tf @@ -0,0 +1,9 @@ +# Peer two clusters. +resource "liqo_peer" "peer" { + + cluster_id = "" + cluster_name = "" + cluster_authurl = "" + cluster_token = "" + +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..11b0bb0 --- /dev/null +++ b/go.mod @@ -0,0 +1,101 @@ +module github.com/liqotech/terraform-provider-liqo + +go 1.19 + +require ( + github.com/hashicorp/terraform-plugin-framework v0.16.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.6.0 + github.com/liqotech/liqo v0.6.0 + github.com/mitchellh/go-homedir v1.1.0 + k8s.io/api v0.25.3 + k8s.io/apimachinery v0.25.3 + k8s.io/client-go v0.25.3 + k8s.io/kubectl v0.25.3 + k8s.io/utils v0.0.0-20220922133306-665eaaec4324 + sigs.k8s.io/controller-runtime v0.13.0 +) + +require ( + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.1.1 // indirect + github.com/Masterminds/sprig/v3 v3.2.2 // indirect + github.com/armon/go-radix v1.0.0 // indirect + github.com/aws/aws-sdk-go v1.44.92 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-checkpoint v0.5.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-hclog v1.2.1 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-plugin v1.4.6 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/hc-install v0.4.0 // indirect + github.com/hashicorp/terraform-exec v0.17.2 // indirect + github.com/hashicorp/terraform-json v0.14.0 // indirect + github.com/hashicorp/terraform-plugin-docs v0.13.0 + github.com/hashicorp/terraform-plugin-go v0.14.1 // indirect + github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect + github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c // indirect + github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect + github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect + github.com/huandu/xstrings v1.3.2 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mitchellh/cli v1.1.4 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oklog/run v1.0.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/posener/complete v1.2.3 // indirect + github.com/rogpeppe/go-internal v1.8.0 // indirect + github.com/russross/blackfriday v1.6.0 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect + github.com/vmihailenco/tagparser v0.1.2 // indirect + github.com/zclconf/go-cty v1.10.0 // indirect + golang.org/x/crypto v0.1.0 // indirect + golang.org/x/net v0.1.0 // indirect + golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect + golang.org/x/sys v0.1.0 // indirect + golang.org/x/term v0.1.0 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220930163606-c98284e70a91 // indirect + google.golang.org/grpc v1.50.1 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..64baff1 --- /dev/null +++ b/go.sum @@ -0,0 +1,505 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI= +github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 h1:NsReiLpErIPzRrnogAXYwSoU7txA977LjDGrbkewJbg= +github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= +github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aws/aws-sdk-go v1.44.92 h1:ayc8sQntRMX84Ib9Eqntar7knfNsWHJY7wnZUk5018w= +github.com/aws/aws-sdk-go v1.44.92/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.2.0 h1:NheeISPSUcYftKlfrLuOo4T62FkmD4t4jviLfFFYaec= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= +github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= +github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= +github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= +github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= +github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA= +github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hc-install v0.4.0 h1:cZkRFr1WVa0Ty6x5fTvL1TuO1flul231rWkGH92oYYk= +github.com/hashicorp/hc-install v0.4.0/go.mod h1:5d155H8EC5ewegao9A4PUTMNPZaq+TbOzkJJZ4vrXeI= +github.com/hashicorp/terraform-exec v0.17.2 h1:EU7i3Fh7vDUI9nNRdMATCEfnm9axzTnad8zszYZ73Go= +github.com/hashicorp/terraform-exec v0.17.2/go.mod h1:tuIbsL2l4MlwwIZx9HPM+LOV9vVyEfBYu2GsO1uH3/8= +github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= +github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= +github.com/hashicorp/terraform-plugin-docs v0.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smPzZrt1Wlm9koLeKazY= +github.com/hashicorp/terraform-plugin-docs v0.13.0/go.mod h1:W0oCmHAjIlTHBbvtppWHe8fLfZ2BznQbuv8+UD8OucQ= +github.com/hashicorp/terraform-plugin-framework v0.16.0 h1:kEHh0d6dp5Ig/ey6PYXkWDZPMLIW8Me41T/Oa7bpO4s= +github.com/hashicorp/terraform-plugin-framework v0.16.0/go.mod h1:Vk5MuIJoE1qksHZawAZr6psx6YXsQBFIKDrWbROrwus= +github.com/hashicorp/terraform-plugin-framework-validators v0.6.0 h1:j8GlgzuTjbbkMnsbiOXerwJTW8Us4saQwo4FfJKd2I0= +github.com/hashicorp/terraform-plugin-framework-validators v0.6.0/go.mod h1:iOYhZQinlZ0R/M3Q3nCXS4dikZ7P41d5b7ezpe9uoIw= +github.com/hashicorp/terraform-plugin-go v0.14.1 h1:cwZzPYla82XwAqpLhSzdVsOMU+6H29tczAwrB0z9Zek= +github.com/hashicorp/terraform-plugin-go v0.14.1/go.mod h1:Bc/K6K26BQ2FHqIELPbpKtt2CzzbQou+0UQF3/0NsCQ= +github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs= +github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= +github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c h1:D8aRO6+mTqHfLsK/BC3j5OAoogv1WLRWzY1AaTo3rBg= +github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI= +github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0= +github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/liqotech/liqo v0.6.0 h1:dluxENa8lM7qHBM4FNJq0ROwOOn570zdVW76J1XKiNE= +github.com/liqotech/liqo v0.6.0/go.mod h1:0BC+FgkCaqvRvhcQUYZqDxxESWM8+0nAkwcI43ZD65Y= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= +github.com/mitchellh/cli v1.1.4 h1:qj8czE26AU4PbiaPXK5uVmMSM+V5BYsFBiM9HhGRLUA= +github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= +github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.2 h1:eKj4SX2Fe7mui28ZgnFW5fmTz1EIr7ugo5s6wDxdHBM= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= +github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= +github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0= +github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= +golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220930163606-c98284e70a91 h1:Ezh2cpcnP5Rq60sLensUsFnxh7P6513NLvNtCm9iyJ4= +google.golang.org/genproto v0.0.0-20220930163606-c98284e70a91/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ= +k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI= +k8s.io/apiextensions-apiserver v0.25.2 h1:8uOQX17RE7XL02ngtnh3TgifY7EhekpK+/piwzQNnBo= +k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc= +k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= +k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0= +k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909 h1:q/70bz7C1/LGuQu/JBX7Fpi55CwcCts/wbvlehe0RRo= +k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/kubectl v0.25.3 h1:HnWJziEtmsm4JaJiKT33kG0kadx68MXxUE8UEbXnN4U= +k8s.io/kubectl v0.25.3/go.mod h1:glU7PiVj/R6Ud4A9FJdTcJjyzOtCJyc0eO7Mrbh3jlI= +k8s.io/utils v0.0.0-20220922133306-665eaaec4324 h1:i+xdFemcSNuJvIfBlaYuXgRondKxK4z4prVPKzEaelI= +k8s.io/utils v0.0.0-20220922133306-665eaaec4324/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= +sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/liqo/attribute_plan_modifier/default_value.go b/liqo/attribute_plan_modifier/default_value.go new file mode 100644 index 0000000..1bc3748 --- /dev/null +++ b/liqo/attribute_plan_modifier/default_value.go @@ -0,0 +1,42 @@ +// Package planmodifier provides a DefaultValue to attributes in provider +package planmodifier + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" +) + +type defaultValueAttributePlanModifier struct { + DefaultValue attr.Value +} + +// DefaultValue used to set a DefaultValue. +func DefaultValue(v attr.Value) tfsdk.AttributePlanModifier { + return &defaultValueAttributePlanModifier{v} +} + +var _ tfsdk.AttributePlanModifier = (*defaultValueAttributePlanModifier)(nil) + +func (apm *defaultValueAttributePlanModifier) Description(ctx context.Context) string { + return apm.MarkdownDescription(ctx) +} + +func (apm *defaultValueAttributePlanModifier) MarkdownDescription(ctx context.Context) string { + return fmt.Sprintf("Sets the default value %q (%s) if the attribute is not set", apm.DefaultValue, apm.DefaultValue.Type(ctx)) +} + +//nolint:gocritic,lll // Terraform Framework template code +func (apm *defaultValueAttributePlanModifier) Modify(_ context.Context, req tfsdk.ModifyAttributePlanRequest, res *tfsdk.ModifyAttributePlanResponse) { + if !req.AttributeConfig.IsNull() { + return + } + + if !req.AttributePlan.IsUnknown() && !req.AttributePlan.IsNull() { + return + } + + res.AttributePlan = apm.DefaultValue +} diff --git a/liqo/generate_resource.go b/liqo/generate_resource.go new file mode 100644 index 0000000..3b766c2 --- /dev/null +++ b/liqo/generate_resource.go @@ -0,0 +1,195 @@ +package liqo + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" + "k8s.io/client-go/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/liqotech/liqo/pkg/auth" + "github.com/liqotech/liqo/pkg/utils" + foreigncluster "github.com/liqotech/liqo/pkg/utils/foreignCluster" + planmodifier "github.com/liqotech/terraform-provider-liqo/liqo/attribute_plan_modifier" +) + +var ( + _ resource.Resource = &generateResource{} + _ resource.ResourceWithConfigure = &generateResource{} +) + +// NewGenerateResource provides the initialization of Generate Resource. +func NewGenerateResource() resource.Resource { + return &generateResource{} +} + +type generateResource struct { + config liqoProviderModel + CRClient client.Client + KubeClient *kubernetes.Clientset +} + +func (r *generateResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_generate" +} + +func (r *generateResource) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { + return tfsdk.Schema{ + Description: "Generate peering parameters for remote clusters", + Attributes: map[string]tfsdk.Attribute{ + "cluster_id": { + Type: types.StringType, + Computed: true, + Description: "Provider cluster ID.", + }, + "cluster_name": { + Type: types.StringType, + Computed: true, + Description: "Provider cluster name.", + }, + "auth_ep": { + Type: types.StringType, + Computed: true, + Description: "Provider authentication endpoint.", + }, + "local_token": { + Type: types.StringType, + Computed: true, + Description: "Provider authentication token.", + }, + "liqo_namespace": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("liqo")), + }, + Computed: true, + Description: "Namespace where is Liqo installed in provider cluster.", + }, + }, + }, nil +} + +// Creation of Generate Resource to obtain necessary pairing parameters used by Peer Resources +// This resource will reproduce the same effect and outputs of "liqoctl generate peer-command" command. +// +//nolint:gocritic // Terraform Framework template code +func (r *generateResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan generateResourceModel + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + overrides, loader, err := CheckParameters(&r.config) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + CRClient, KubeClient, err := NewClients(overrides, loader) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + r.CRClient = CRClient + r.KubeClient = KubeClient + + clusterIdentity, err := utils.GetClusterIdentityWithControllerClient(ctx, r.CRClient, plan.LiqoNamespace.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + localToken, err := auth.GetToken(ctx, r.CRClient, plan.LiqoNamespace.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + authEP, err := foreigncluster.GetHomeAuthURL(ctx, r.CRClient, plan.LiqoNamespace.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + if clusterIdentity.ClusterName == "" { + clusterIdentity.ClusterName = clusterIdentity.ClusterID + } + + plan.ClusterID = types.StringValue(clusterIdentity.ClusterID) + plan.ClusterName = types.StringValue(clusterIdentity.ClusterName) + plan.LocalToken = types.StringValue(localToken) + plan.AuthEP = types.StringValue(authEP) + + diags = resp.State.Set(ctx, plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +//nolint:gocritic // Terraform Framework template code +func (r *generateResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state generateResourceModel + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +//nolint:gocritic // Terraform Framework template code +func (r *generateResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + resp.Diagnostics.AddError( + "Unable to Update Resource", + "Update is not supported/permitted yet.", + ) +} + +//nolint:gocritic // Terraform Framework template code +func (r *generateResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { +} + +// Configure method to obtain kubernetes Clients provided by provider. +func (r *generateResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + r.config = req.ProviderData.(liqoProviderModel) +} + +type generateResourceModel struct { + ClusterID types.String `tfsdk:"cluster_id"` + ClusterName types.String `tfsdk:"cluster_name"` + AuthEP types.String `tfsdk:"auth_ep"` + LocalToken types.String `tfsdk:"local_token"` + LiqoNamespace types.String `tfsdk:"liqo_namespace"` +} diff --git a/liqo/offload_resource.go b/liqo/offload_resource.go new file mode 100644 index 0000000..da8fe30 --- /dev/null +++ b/liqo/offload_resource.go @@ -0,0 +1,276 @@ +package liqo + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1" + "github.com/liqotech/liqo/pkg/consts" + planmodifier "github.com/liqotech/terraform-provider-liqo/liqo/attribute_plan_modifier" +) + +var ( + _ resource.Resource = &offloadResource{} + _ resource.ResourceWithConfigure = &offloadResource{} +) + +// NewOffloadResource provides the initialization of Offload Resource. +func NewOffloadResource() resource.Resource { + return &offloadResource{} +} + +type offloadResource struct { + config liqoProviderModel +} + +func (o *offloadResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_offload" +} + +func (o *offloadResource) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { + return tfsdk.Schema{ + Description: "Offload a namespace.", + Attributes: map[string]tfsdk.Attribute{ + "namespace": { + Type: types.StringType, + Required: true, + Description: "Offload a namespace.", + }, + "pod_offloading_strategy": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("LocalAndRemote")), + }, + Computed: true, + Description: "Namespace to offload.", + }, + "namespace_mapping_strategy": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("DefaultName")), + }, + Computed: true, + Description: "Naming strategy used to create the remote namespace.", + }, + "cluster_selector_terms": { + Optional: true, + Attributes: tfsdk.ListNestedAttributes(map[string]tfsdk.Attribute{ + "match_expressions": { + Optional: true, + Computed: true, + Attributes: tfsdk.ListNestedAttributes(map[string]tfsdk.Attribute{ + "key": { + Type: types.StringType, + Required: true, + Description: " The label key that the selector applies to.", + }, + "operator": { + Type: types.StringType, + Required: true, + Description: "Represents a key's relationship to a set of values.", + }, + "values": { + Type: types.ListType{ElemType: types.StringType}, + Optional: true, + Description: "An array of string values.", + }, + }), + Description: "A list of cluster selector.", + }, + }), + Description: "Selectors to restrict the set of remote clusters.", + }, + }, + }, nil +} + +// Creation of Offload Resource to offload a specific namespace, +// additionally there is a possibility to select clusters with match_expressione +// This resource will reproduce the same effect and outputs of "liqoctl offload" command. +// +//nolint:gocritic // Terraform Framework template code +func (o *offloadResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan offloadResourceModel + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + overrides, loader, err := CheckParameters(&o.config) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + CRClient, _, err := NewClients(overrides, loader) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + var clusterSelector [][]metav1.LabelSelectorRequirement + + for _, selector := range plan.ClusterSelectorTerms { + s := &metav1.LabelSelector{ + MatchLabels: map[string]string{}, + MatchExpressions: []metav1.LabelSelectorRequirement{}, + } + + for _, matchExpression := range selector.MatchExpressions { + var values []string + + for _, value := range matchExpression.Values { + values = append(values, value.ValueString()) + } + req := metav1.LabelSelectorRequirement{ + Key: matchExpression.Key.ValueString(), + Operator: metav1.LabelSelectorOperator(matchExpression.Operator.ValueString()), + Values: values, + } + s.MatchExpressions = append(s.MatchExpressions, req) + } + + clusterSelector = append(clusterSelector, s.MatchExpressions) + } + + terms := []corev1.NodeSelectorTerm{} + + for _, selector := range clusterSelector { + var requirements []corev1.NodeSelectorRequirement + + for _, r := range selector { + requirements = append(requirements, corev1.NodeSelectorRequirement{ + Key: r.Key, + Operator: corev1.NodeSelectorOperator(r.Operator), + Values: r.Values, + }) + } + + terms = append(terms, corev1.NodeSelectorTerm{MatchExpressions: requirements}) + } + + nsoff := &offloadingv1alpha1.NamespaceOffloading{ObjectMeta: metav1.ObjectMeta{ + Name: consts.DefaultNamespaceOffloadingName, Namespace: plan.Namespace.ValueString()}} + + _, err = controllerutil.CreateOrUpdate(ctx, CRClient, nsoff, func() error { + nsoff.Spec.PodOffloadingStrategy = offloadingv1alpha1.PodOffloadingStrategyType(plan.PodOffloadingStrategy.ValueString()) + nsoff.Spec.NamespaceMappingStrategy = offloadingv1alpha1.NamespaceMappingStrategyType(plan.NamespaceMappingStrategy.ValueString()) + nsoff.Spec.ClusterSelector = corev1.NodeSelector{NodeSelectorTerms: terms} + return nil + }) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + + return + } + + diags = resp.State.Set(ctx, plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +//nolint:gocritic // Terraform Framework template code +func (o *offloadResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state offloadResourceModel + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +//nolint:gocritic // Terraform Framework template code +func (o *offloadResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + resp.Diagnostics.AddError( + "Unable to Update Resource", + "Update is not supported/permitted yet.", + ) +} + +//nolint:gocritic // Terraform Framework template code +func (o *offloadResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data offloadResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + overrides, loader, err := CheckParameters(&o.config) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Delete Resource", + err.Error(), + ) + return + } + + CRClient, _, err := NewClients(overrides, loader) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Delete Resource", + err.Error(), + ) + return + } + + nsoff := &offloadingv1alpha1.NamespaceOffloading{ObjectMeta: metav1.ObjectMeta{ + Name: consts.DefaultNamespaceOffloadingName, Namespace: data.Namespace.ValueString()}} + if err := CRClient.Delete(ctx, nsoff); client.IgnoreNotFound(err) != nil { + resp.Diagnostics.AddError( + "Unable to Delete Resource", + err.Error(), + ) + return + } +} + +// Configure method to obtain kubernetes Clients provided by provider. +func (o *offloadResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + o.config = req.ProviderData.(liqoProviderModel) +} + +type matchExpression struct { + Key types.String `tfsdk:"key"` + Operator types.String `tfsdk:"operator"` + Values []types.String `tfsdk:"values"` +} + +type matchExpressions struct { + MatchExpressions []matchExpression `tfsdk:"match_expressions"` +} + +type offloadResourceModel struct { + Namespace types.String `tfsdk:"namespace"` + PodOffloadingStrategy types.String `tfsdk:"pod_offloading_strategy"` + NamespaceMappingStrategy types.String `tfsdk:"namespace_mapping_strategy"` + ClusterSelectorTerms []matchExpressions `tfsdk:"cluster_selector_terms"` +} diff --git a/liqo/peer_resource.go b/liqo/peer_resource.go new file mode 100644 index 0000000..0bd4281 --- /dev/null +++ b/liqo/peer_resource.go @@ -0,0 +1,271 @@ +package liqo + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" + kerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kubeTypes "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1" + "github.com/liqotech/liqo/pkg/discovery" + "github.com/liqotech/liqo/pkg/utils" + authenticationtokenutils "github.com/liqotech/liqo/pkg/utils/authenticationtoken" + foreigncluster "github.com/liqotech/liqo/pkg/utils/foreignCluster" + planmodifier "github.com/liqotech/terraform-provider-liqo/liqo/attribute_plan_modifier" +) + +var ( + _ resource.Resource = &peerResource{} + _ resource.ResourceWithConfigure = &peerResource{} +) + +// NewPeerResource provides the initialization of Peer Resource. +func NewPeerResource() resource.Resource { + return &peerResource{} +} + +type peerResource struct { + config liqoProviderModel +} + +func (p *peerResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_peer" +} + +func (p *peerResource) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { + return tfsdk.Schema{ + Description: "Execute peering.", + Attributes: map[string]tfsdk.Attribute{ + "cluster_id": { + Type: types.StringType, + Required: true, + Description: "Provider cluster ID used for peering.", + }, + "cluster_name": { + Type: types.StringType, + Required: true, + Description: "Provider cluster name used for peering.", + }, + "cluster_authurl": { + Type: types.StringType, + Required: true, + Description: "Provider authentication url used for peering.", + }, + "cluster_token": { + Type: types.StringType, + Required: true, + Description: "Provider authentication token used for peering.", + }, + "liqo_namespace": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("liqo")), + }, + Computed: true, + Description: "Namespace where is Liqo installed in provider cluster.", + }, + }, + }, nil +} + +// Creation of Peer Resource to execute peering between two clusters using auth parameters provided by Generate Resource +// This resource will reproduce the same effect and outputs of "liqoctl peer out-of-band" command. +// +//nolint:gocritic // Terraform Framework template code +func (p *peerResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan peerResourceModel + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + overrides, loader, err := CheckParameters(&p.config) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + CRClient, KubeClient, err := NewClients(overrides, loader) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + clusterIdentity, err := utils.GetClusterIdentityWithControllerClient(ctx, CRClient, plan.LiqoNamespace.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + if clusterIdentity.ClusterID == plan.ClusterID.ValueString() { + resp.Diagnostics.AddError( + "Unable to Create Resource", + "The Cluster ID of the remote cluster is the same of that of the local cluster", + ) + return + } + + //nolint:lll // Long due to method invocation parameters. + err = authenticationtokenutils.StoreInSecret(ctx, KubeClient, plan.ClusterID.ValueString(), plan.ClusterToken.ValueString(), plan.LiqoNamespace.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + fc, err := foreigncluster.GetForeignClusterByID(ctx, CRClient, plan.ClusterID.ValueString()) + if kerrors.IsNotFound(err) { + fc = &discoveryv1alpha1.ForeignCluster{ObjectMeta: metav1.ObjectMeta{Name: plan.ClusterName.ValueString(), + Labels: map[string]string{discovery.ClusterIDLabel: plan.ClusterID.ValueString()}}} + } else if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + return + } + + _, err = controllerutil.CreateOrUpdate(ctx, CRClient, fc, func() error { + if fc.Spec.PeeringType != discoveryv1alpha1.PeeringTypeUnknown && fc.Spec.PeeringType != discoveryv1alpha1.PeeringTypeOutOfBand { + return fmt.Errorf("a peering of type %s already exists towards remote cluster %q, cannot be changed to %s", + fc.Spec.PeeringType, plan.ClusterName.ValueString(), discoveryv1alpha1.PeeringTypeOutOfBand) + } + + fc.Spec.PeeringType = discoveryv1alpha1.PeeringTypeOutOfBand + fc.Spec.ClusterIdentity.ClusterID = plan.ClusterID.ValueString() + if fc.Spec.ClusterIdentity.ClusterName == "" { + fc.Spec.ClusterIdentity.ClusterName = plan.ClusterName.ValueString() + } + + fc.Spec.ForeignAuthURL = plan.ClusterAuthURL.ValueString() + fc.Spec.ForeignProxyURL = "" + fc.Spec.OutgoingPeeringEnabled = discoveryv1alpha1.PeeringEnabledYes + if fc.Spec.IncomingPeeringEnabled == "" { + fc.Spec.IncomingPeeringEnabled = discoveryv1alpha1.PeeringEnabledAuto + } + if fc.Spec.InsecureSkipTLSVerify == nil { + fc.Spec.InsecureSkipTLSVerify = pointer.BoolPtr(true) + } + return nil + }) + + if err != nil { + resp.Diagnostics.AddError( + "Unable to Create Resource", + err.Error(), + ) + + return + } + + diags = resp.State.Set(ctx, plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +//nolint:gocritic // Terraform Framework template code +func (p *peerResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state peerResourceModel + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +//nolint:gocritic // Terraform Framework template code +func (p *peerResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + resp.Diagnostics.AddError( + "Unable to Update Resource", + "Update is not supported/permitted yet.", + ) +} + +//nolint:gocritic // Terraform Framework template code +func (p *peerResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data peerResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + overrides, loader, err := CheckParameters(&p.config) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Delete Resource", + err.Error(), + ) + return + } + + CRClient, _, err := NewClients(overrides, loader) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Delete Resource", + err.Error(), + ) + return + } + + var foreignCluster discoveryv1alpha1.ForeignCluster + if err := CRClient.Get(ctx, kubeTypes.NamespacedName{Name: data.ClusterName.ValueString()}, &foreignCluster); err != nil { + return + } + + if foreignCluster.Spec.PeeringType != discoveryv1alpha1.PeeringTypeOutOfBand { + return + } + + foreignCluster.Spec.OutgoingPeeringEnabled = discoveryv1alpha1.PeeringEnabledNo + if err := CRClient.Update(ctx, &foreignCluster); err != nil { + resp.Diagnostics.AddError( + "Unable to Delete Resource", + err.Error(), + ) + return + } +} + +// Configure method to obtain kubernetes Clients provided by provider. +func (p *peerResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + p.config = req.ProviderData.(liqoProviderModel) +} + +type peerResourceModel struct { + ClusterID types.String `tfsdk:"cluster_id"` + ClusterName types.String `tfsdk:"cluster_name"` + ClusterAuthURL types.String `tfsdk:"cluster_authurl"` + ClusterToken types.String `tfsdk:"cluster_token"` + LiqoNamespace types.String `tfsdk:"liqo_namespace"` +} diff --git a/liqo/provider.go b/liqo/provider.go new file mode 100644 index 0000000..31f4fcf --- /dev/null +++ b/liqo/provider.go @@ -0,0 +1,407 @@ +// Package liqo provides resources and provider methods. +package liqo + +import ( + "bytes" + "context" + "errors" + "os" + "path/filepath" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/provider" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/mitchellh/go-homedir" + apimachineryschema "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/kubectl/pkg/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" + + discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1" + netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1" + offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1" + sharingv1alpha1 "github.com/liqotech/liqo/apis/sharing/v1alpha1" + planmodifier "github.com/liqotech/terraform-provider-liqo/liqo/attribute_plan_modifier" +) + +func init() { + utilruntime.Must(discoveryv1alpha1.AddToScheme(scheme.Scheme)) + utilruntime.Must(netv1alpha1.AddToScheme(scheme.Scheme)) + utilruntime.Must(offloadingv1alpha1.AddToScheme(scheme.Scheme)) + utilruntime.Must(sharingv1alpha1.AddToScheme(scheme.Scheme)) +} + +var ( + _ provider.Provider = &liqoProvider{} +) + +// New provides the initialization of provider. +func New() provider.Provider { + return &liqoProvider{} +} + +type liqoProvider struct { +} + +// CheckParameters method used to check if kubernetes parameters are null. +func CheckParameters(config *liqoProviderModel) (*clientcmd.ConfigOverrides, *clientcmd.ClientConfigLoadingRules, error) { + overrides := &clientcmd.ConfigOverrides{} + loader := &clientcmd.ClientConfigLoadingRules{} + + configPaths := []string{} + + if !config.Kubernetes.KubeConfigPath.IsNull() { + configPaths = []string{config.Kubernetes.KubeConfigPath.ValueString()} + } else if len(config.Kubernetes.KubeConfigPaths) > 0 { + for _, configPath := range config.Kubernetes.KubeConfigPaths { + configPaths = append(configPaths, configPath.ValueString()) + } + } else if v := os.Getenv("KubeConfigPaths"); v != "" { + configPaths = filepath.SplitList(v) + } + + if len(configPaths) > 0 { + expandedPaths := []string{} + for _, p := range configPaths { + path, err := homedir.Expand(p) + if err != nil { + return nil, nil, err + } + expandedPaths = append(expandedPaths, path) + } + + if len(expandedPaths) == 1 { + loader.ExplicitPath = expandedPaths[0] + } else { + loader.Precedence = expandedPaths + } + + ctxNotOk := config.Kubernetes.KubeCtx.IsNull() + authInfoNotOk := config.Kubernetes.KubeCtxAuthInfo.IsNull() + clusterNotOk := config.Kubernetes.KubeCtxCluster.IsNull() + + if ctxNotOk || authInfoNotOk || clusterNotOk { + if ctxNotOk { + overrides.CurrentContext = config.Kubernetes.KubeCtx.ValueString() + } + + overrides.Context = clientcmdapi.Context{} + if authInfoNotOk { + overrides.Context.AuthInfo = config.Kubernetes.KubeCtxAuthInfo.ValueString() + } + if clusterNotOk { + overrides.Context.Cluster = config.Kubernetes.KubeCtxCluster.ValueString() + } + } + } + + if !config.Kubernetes.KubeInsecure.IsNull() { + overrides.ClusterInfo.InsecureSkipTLSVerify = !config.Kubernetes.KubeInsecure.ValueBool() + } + if !config.Kubernetes.KubeClusterCaCertData.IsNull() { + overrides.ClusterInfo.CertificateAuthorityData = bytes.NewBufferString(config.Kubernetes.KubeClusterCaCertData.ValueString()).Bytes() + } + if !config.Kubernetes.KubeClientCertData.IsNull() { + overrides.AuthInfo.ClientCertificateData = bytes.NewBufferString(config.Kubernetes.KubeClientCertData.ValueString()).Bytes() + } + if !config.Kubernetes.KubeHost.IsNull() { + hasCA := len(overrides.ClusterInfo.CertificateAuthorityData) != 0 + hasCert := len(overrides.AuthInfo.ClientCertificateData) != 0 + defaultTLS := hasCA || hasCert || overrides.ClusterInfo.InsecureSkipTLSVerify + host, _, err := rest.DefaultServerURL(config.Kubernetes.KubeHost.ValueString(), "", apimachineryschema.GroupVersion{}, defaultTLS) + if err != nil { + return nil, nil, err + } + + overrides.ClusterInfo.Server = host.String() + } + if !config.Kubernetes.KubeUser.IsNull() { + overrides.AuthInfo.Username = config.Kubernetes.KubeUser.ValueString() + } + if !config.Kubernetes.KubePassword.IsNull() { + overrides.AuthInfo.Password = config.Kubernetes.KubePassword.ValueString() + } + if !config.Kubernetes.KubeClientKeyData.IsNull() { + overrides.AuthInfo.ClientKeyData = bytes.NewBufferString(config.Kubernetes.KubeClientKeyData.ValueString()).Bytes() + } + if !config.Kubernetes.KubeToken.IsNull() { + overrides.AuthInfo.Token = config.Kubernetes.KubeToken.ValueString() + } + + if !config.Kubernetes.KubeProxyURL.IsNull() { + overrides.ClusterDefaults.ProxyURL = config.Kubernetes.KubeProxyURL.ValueString() + } + + if len(config.Kubernetes.KubeExec) > 0 { + exec := &clientcmdapi.ExecConfig{} + exec.InteractiveMode = clientcmdapi.IfAvailableExecInteractiveMode + exec.APIVersion = config.Kubernetes.KubeExec[0].APIVersion.ValueString() + exec.Command = config.Kubernetes.KubeExec[0].Command.ValueString() + for _, arg := range config.Kubernetes.KubeExec[0].Args { + exec.Args = append(exec.Args, arg.ValueString()) + } + + for kk, vv := range config.Kubernetes.KubeExec[0].Env.Elements() { + exec.Env = append(exec.Env, clientcmdapi.ExecEnvVar{Name: kk, Value: vv.String()}) + } + + overrides.AuthInfo.Exec = exec + } + + return overrides, loader, nil +} + +// NewClients method to create CRClient and KubeClient. +func NewClients(overrides *clientcmd.ConfigOverrides, loader *clientcmd.ClientConfigLoadingRules) (client.Client, *kubernetes.Clientset, error) { + clientCfg := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loader, overrides) + if clientCfg == nil { + return nil, nil, errors.New("error while creating clientCfg") + } + + var restCfg *rest.Config + + restCfg, err := clientCfg.ClientConfig() + if err != nil { + return nil, nil, err + } + + var CRClient client.Client + + CRClient, err = client.New(restCfg, client.Options{Scheme: scheme.Scheme}) + if err != nil { + return nil, nil, err + } + + KubeClient, err := kubernetes.NewForConfig(restCfg) + if err != nil { + return nil, nil, err + } + + return CRClient, KubeClient, nil +} + +func (p *liqoProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) { + resp.TypeName = "liqo" +} + +func (p *liqoProvider) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { + return tfsdk.Schema{ + Description: "Interact with Liqo.", + Attributes: map[string]tfsdk.Attribute{ + "kubernetes": { + Optional: true, + Computed: true, + Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{ + "host": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "The hostname (in form of URI) of Kubernetes master.", + }, + "username": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", + }, + "password": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", + }, + "insecure": { + Type: types.BoolType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.BoolValue(false)), + }, + Description: "Whether server should be accessed without verifying the TLS certificate.", + }, + "client_certificate": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "PEM-encoded client certificate for TLS authentication.", + }, + "client_key": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "PEM-encoded client certificate key for TLS authentication.", + }, + "cluster_ca_certificate": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "PEM-encoded root certificates bundle for TLS authentication.", + }, + "config_paths": { + Type: types.ListType{ElemType: types.StringType}, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.ListNull(types.StringType)), + }, + }, + "config_path": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "Path to the kube config file. Can be set with KubeConfigPath.", + }, + "config_context": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + }, + "config_context_auth_info": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "", + }, + "config_context_cluster": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "", + }, + "token": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "Token to authenticate an service account", + }, + "proxy_url": { + Type: types.StringType, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Description: "URL to the proxy to be used for all API requests", + }, + "exec": { + Optional: true, + Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{ + "api_version": { + Type: types.StringType, + Required: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + Validators: []tfsdk.AttributeValidator{ + stringvalidator.NoneOf("client.authentication.k8s.io/v1alpha1"), + }, + }, + "command": { + Type: types.StringType, + Required: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.StringValue("")), + }, + }, + "env": { + Type: types.MapType{ElemType: types.StringType}, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.MapNull(types.StringType)), + }, + }, + "args": { + Type: types.ListType{ElemType: types.StringType}, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + planmodifier.DefaultValue(types.ListNull(types.StringType)), + }, + }, + }), + }, + }), + }, + }, + }, nil +} + +// Configure method to create the two kubernetes Clients using parameters passed in the provider instantiation in Terraform main +// After the creation both Clients will be available in resources and data sources. +// +//nolint:gocritic // Terraform Framework template code +func (p *liqoProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { + var config liqoProviderModel + diags := req.Config.Get(ctx, &config) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.ResourceData = config +} + +func (p *liqoProvider) DataSources(_ context.Context) []func() datasource.DataSource { + return nil +} + +func (p *liqoProvider) Resources(_ context.Context) []func() resource.Resource { + return []func() resource.Resource{ + NewPeerResource, NewGenerateResource, NewOffloadResource, + } +} + +type exec struct { + APIVersion types.String `tfsdk:"api_version"` + Command types.String `tfsdk:"command"` + Env types.Map `tfsdk:"env"` + Args []types.String `tfsdk:"args"` +} + +type kubeConf struct { + KubeHost types.String `tfsdk:"host"` + KubeUser types.String `tfsdk:"username"` + KubePassword types.String `tfsdk:"password"` + KubeInsecure types.Bool `tfsdk:"insecure"` + KubeClientCertData types.String `tfsdk:"client_certificate"` + KubeClientKeyData types.String `tfsdk:"client_key"` + KubeClusterCaCertData types.String `tfsdk:"cluster_ca_certificate"` + KubeConfigPath types.String `tfsdk:"config_path"` + KubeConfigPaths []types.String `tfsdk:"config_paths"` + KubeCtx types.String `tfsdk:"config_context"` + KubeCtxAuthInfo types.String `tfsdk:"config_context_auth_info"` + KubeCtxCluster types.String `tfsdk:"config_context_cluster"` + KubeToken types.String `tfsdk:"token"` + KubeProxyURL types.String `tfsdk:"proxy_url"` + KubeExec []exec `tfsdk:"exec"` +} + +type liqoProviderModel struct { + Kubernetes *kubeConf `tfsdk:"kubernetes"` +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..1272d57 --- /dev/null +++ b/main.go @@ -0,0 +1,20 @@ +// Package main creates the provider instances in Terraform. +package main + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/providerserver" + + "github.com/liqotech/terraform-provider-liqo/liqo" +) + +// Provider documentation generation. +//go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate --provider-name liqo + +func main() { + //nolint:errcheck,gosec // Terraform Framework template code + providerserver.Serve(context.Background(), liqo.New, providerserver.ServeOpts{ + Address: "liqo-provider/liqo/test", + }) +} diff --git a/terraform-registry-manifest.json b/terraform-registry-manifest.json new file mode 100644 index 0000000..fec2a56 --- /dev/null +++ b/terraform-registry-manifest.json @@ -0,0 +1,6 @@ +{ + "version": 1, + "metadata": { + "protocol_versions": ["6.0"] + } +} diff --git a/tools/tools.go b/tools/tools.go new file mode 100644 index 0000000..a82de6b --- /dev/null +++ b/tools/tools.go @@ -0,0 +1,8 @@ +//go:build tools + +package tools + +import ( + // Ensure documentation generator is not removed from go.mod. + _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs" +)