diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..8fe2a3c --- /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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + # Allow goreleaser to access older tag information. + fetch-depth: 0 + - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version-file: 'go.mod' + cache: true + - name: Import GPG key + uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.0 + id: import_gpg + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.PASSPHRASE }} + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0 + with: + args: release --clean + env: + # GitHub sets the GITHUB_TOKEN secret automatically. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..3b44e65 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,81 @@ +# Terraform Provider testing workflow. +name: Tests + +# This GitHub action runs your tests for each pull request and push. +# Optionally, you can turn it on using a schedule for regular testing. +on: + pull_request: + paths-ignore: + - 'README.md' + push: + paths-ignore: + - 'README.md' + +# Testing only needs permissions to read the repository contents. +permissions: + contents: read + +jobs: + # Ensure project builds before running testing matrix + build: + name: Build + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version-file: 'go.mod' + cache: true + - run: go mod download + - run: go build -v . + - name: Run linters + uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 + with: + version: latest + + generate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version-file: 'go.mod' + cache: true + - run: go generate ./... + - name: git diff + run: | + git diff --compact-summary --exit-code || \ + (echo; echo "Unexpected difference in directories after code generation. Run 'go generate ./...' command and commit."; exit 1) + + # Run acceptance tests in a matrix with Terraform CLI versions + test: + name: Terraform Provider Acceptance Tests + needs: build + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + # list whatever Terraform versions here you would like to support + terraform: + - '1.0.*' + - '1.1.*' + - '1.2.*' + - '1.3.*' + - '1.4.*' + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version-file: 'go.mod' + cache: true + - uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2.0.3 + with: + terraform_version: ${{ matrix.terraform }} + terraform_wrapper: false + - run: go mod download + - env: + TF_ACC: "1" + run: go test -v -cover ./internal/provider/ + timeout-minutes: 10 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b4f6ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.dll +*.exe +.DS_Store +example.tf +terraform.tfplan +terraform.tfstate +bin/ +dist/ + +.env diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..4c6bb5a --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,27 @@ +# Visit https://golangci-lint.run/ for usage documentation +# and information on other useful linters +issues: + max-per-linter: 0 + max-same-issues: 0 + +linters: + disable-all: true + enable: + - durationcheck + - errcheck + - exportloopref + - forcetypeassert + - godot + - gofmt + - gosimple + - ineffassign + - makezero + - misspell + - nilerr + - predeclared + - staticcheck + - tenv + - unconvert + - unparam + - unused + - vet 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/Makefile b/Makefile new file mode 100644 index 0000000..b8a0cad --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +provider-test: + TF_ACC=a go test ./... diff --git a/docs/data-sources/cidr.md b/docs/data-sources/cidr.md new file mode 100644 index 0000000..d23fcec --- /dev/null +++ b/docs/data-sources/cidr.md @@ -0,0 +1,61 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_cidr Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_cidr (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `spec` (List of Object) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. +- `namespace` (String) Namespace is the namespace of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) + + + +### Nested Schema for `spec` + +Read-Only: + +- `ipv4_cidrs` (Set of String) +- `ipv6_cidrs` (Set of String) diff --git a/docs/data-sources/cluster.md b/docs/data-sources/cluster.md new file mode 100644 index 0000000..4fcb822 --- /dev/null +++ b/docs/data-sources/cluster.md @@ -0,0 +1,96 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_cluster Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_cluster (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `spec` (List of Object) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. +- `namespace` (String) Namespace is the namespace of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) + + + +### Nested Schema for `spec` + +Read-Only: + +- `environment` (String) +- `kubernetes` (List of Object) (see [below for nested schema](#nestedobjatt--spec--kubernetes)) +- `organization_unit` (String) +- `platform` (String) +- `project` (String) +- `pubg` (List of Object) (see [below for nested schema](#nestedobjatt--spec--pubg)) +- `vendor` (List of Object) (see [below for nested schema](#nestedobjatt--spec--vendor)) + + +### Nested Schema for `spec.kubernetes` + +Read-Only: + +- `ca_cert` (String) +- `endpoint` (String) +- `sa_issuer` (String) +- `version` (String) + + + +### Nested Schema for `spec.pubg` + +Read-Only: + +- `infra` (String) +- `site` (String) + + + +### Nested Schema for `spec.vendor` + +Read-Only: + +- `account_id` (String) +- `engine` (String) +- `name` (String) +- `region` (String) diff --git a/docs/data-sources/clusterrolebinding.md b/docs/data-sources/clusterrolebinding.md new file mode 100644 index 0000000..94ff6af --- /dev/null +++ b/docs/data-sources/clusterrolebinding.md @@ -0,0 +1,88 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_clusterrolebinding Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_clusterrolebinding (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `spec` (List of Object) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) + + + +### Nested Schema for `spec` + +Read-Only: + +- `policy_inline` (List of Object) (see [below for nested schema](#nestedobjatt--spec--policy_inline)) +- `policy_ref` (String) +- `subject_ref` (List of Object) (see [below for nested schema](#nestedobjatt--spec--subject_ref)) + + +### Nested Schema for `spec.policy_inline` + +Read-Only: + +- `actions` (Set of String) +- `paths` (Set of String) +- `resources` (Set of Object) (see [below for nested schema](#nestedobjatt--spec--policy_inline--resources)) + + +### Nested Schema for `spec.policy_inline.resources` + +Read-Only: + +- `api_group` (String) +- `kind` (String) + + + + +### Nested Schema for `spec.subject_ref` + +Read-Only: + +- `kind` (String) +- `name` (String) diff --git a/docs/data-sources/image.md b/docs/data-sources/image.md new file mode 100644 index 0000000..cdf065a --- /dev/null +++ b/docs/data-sources/image.md @@ -0,0 +1,65 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_image Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_image (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `spec` (List of Object) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. +- `namespace` (String) Namespace is the namespace of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) + + + +### Nested Schema for `spec` + +Read-Only: + +- `app` (String) +- `branch` (String) +- `commit_hash` (String) +- `repository` (String) +- `tag` (String) +- `timestamp` (Number) diff --git a/docs/data-sources/namespace.md b/docs/data-sources/namespace.md new file mode 100644 index 0000000..7e32067 --- /dev/null +++ b/docs/data-sources/namespace.md @@ -0,0 +1,50 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_namespace Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_namespace (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/data-sources/oidcauth.md b/docs/data-sources/oidcauth.md new file mode 100644 index 0000000..2e81642 --- /dev/null +++ b/docs/data-sources/oidcauth.md @@ -0,0 +1,74 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_oidcauth Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_oidcauth (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `spec` (List of Object) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) + + + +### Nested Schema for `spec` + +Read-Only: + +- `attribute_mapping` (List of Object) (see [below for nested schema](#nestedobjatt--spec--attribute_mapping)) +- `client_id` (String) +- `groups_claim` (String) +- `groups_prefix` (String) +- `issuer` (String) +- `required_claims` (Set of String) +- `username_claim` (String) +- `username_prefix` (String) + + +### Nested Schema for `spec.attribute_mapping` + +Read-Only: + +- `from` (String) +- `to` (String) diff --git a/docs/data-sources/rolebinding.md b/docs/data-sources/rolebinding.md new file mode 100644 index 0000000..92eeaec --- /dev/null +++ b/docs/data-sources/rolebinding.md @@ -0,0 +1,89 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_rolebinding Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_rolebinding (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `spec` (List of Object) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. +- `namespace` (String) Namespace is the namespace of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) + + + +### Nested Schema for `spec` + +Read-Only: + +- `policy_inline` (List of Object) (see [below for nested schema](#nestedobjatt--spec--policy_inline)) +- `policy_ref` (String) +- `subject_ref` (List of Object) (see [below for nested schema](#nestedobjatt--spec--subject_ref)) + + +### Nested Schema for `spec.policy_inline` + +Read-Only: + +- `actions` (Set of String) +- `paths` (Set of String) +- `resources` (Set of Object) (see [below for nested schema](#nestedobjatt--spec--policy_inline--resources)) + + +### Nested Schema for `spec.policy_inline.resources` + +Read-Only: + +- `api_group` (String) +- `kind` (String) + + + + +### Nested Schema for `spec.subject_ref` + +Read-Only: + +- `kind` (String) +- `name` (String) diff --git a/docs/data-sources/user.md b/docs/data-sources/user.md new file mode 100644 index 0000000..684e22a --- /dev/null +++ b/docs/data-sources/user.md @@ -0,0 +1,60 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_user Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_user (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `spec` (List of Object) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) + + + +### Nested Schema for `spec` + +Read-Only: + +- `groups` (Set of String) +- `password` (String) diff --git a/docs/data-sources/vendor.md b/docs/data-sources/vendor.md new file mode 100644 index 0000000..f1b55df --- /dev/null +++ b/docs/data-sources/vendor.md @@ -0,0 +1,62 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_vendor Data Source - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_vendor (Data Source) + + + + + + +## Schema + +### Optional + +- `metadata` (Block List) (see [below for nested schema](#nestedblock--metadata)) +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. +- `spec` (List of Object) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) + + + +### Nested Schema for `spec` + +Read-Only: + +- `code_name` (String) +- `display_name` (String) +- `regions` (Set of String) +- `short_name` (String) diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..bd4c4da --- /dev/null +++ b/docs/index.md @@ -0,0 +1,94 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip Provider" +subcategory: "" +description: |- + +--- + +# bluechip Provider + + + +## Example Usage + +```terraform +provider "bluechip" { + address = "app.bluechip.com" + basic_auth { + username = "myuser" + password = "mypassword" + } +} + +provider "bluechip" { + alias = "token" + address = "app.bluechip.com" + token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" +} + +provider "bluechip" { + alias = "aws" + address = "app.bluechip.com" + aws_auth { + cluster_name = "bluechip-prod" + region = "us-east-1" + } +} + +provider "bluechip" { + alias = "oidc" + address = "app.bluechip.com" + oidc_auth { + validator_name = "kubernetes-centre" + token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } +} +``` + + +## Schema + +### Optional + +- `address` (String) +- `aws_auth` (Block List, Max: 1) (see [below for nested schema](#nestedblock--aws_auth)) +- `basic_auth` (Block List, Max: 1) (see [below for nested schema](#nestedblock--basic_auth)) +- `oidc_auth` (Block List, Max: 1) (see [below for nested schema](#nestedblock--oidc_auth)) +- `token` (String) + + +### Nested Schema for `aws_auth` + +Required: + +- `region` (String) + +Optional: + +- `access_key` (String) +- `cluster_name` (String) +- `profile` (String) +- `secret_access_key` (String) +- `session_token` (String) + + + +### Nested Schema for `basic_auth` + +Optional: + +- `password` (String) +- `username` (String) + + + +### Nested Schema for `oidc_auth` + +Required: + +- `validator_name` (String) + +Optional: + +- `token` (String) diff --git a/docs/resources/cidr.md b/docs/resources/cidr.md new file mode 100644 index 0000000..7346fbb --- /dev/null +++ b/docs/resources/cidr.md @@ -0,0 +1,64 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_cidr Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_cidr (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) +- `spec` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. +- `namespace` (String) Namespace is the namespace of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `spec` + +Optional: + +- `ipv4_cidrs` (Set of String) +- `ipv6_cidrs` (Set of String) + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/resources/cluster.md b/docs/resources/cluster.md new file mode 100644 index 0000000..b1d260b --- /dev/null +++ b/docs/resources/cluster.md @@ -0,0 +1,100 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_cluster Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_cluster (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) +- `spec` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. +- `namespace` (String) Namespace is the namespace of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `spec` + +Required: + +- `environment` (String) +- `kubernetes` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec--kubernetes)) +- `organization_unit` (String) +- `platform` (String) +- `project` (String) +- `pubg` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec--pubg)) +- `vendor` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec--vendor)) + + +### Nested Schema for `spec.kubernetes` + +Required: + +- `ca_cert` (String) +- `endpoint` (String) +- `sa_issuer` (String) +- `version` (String) + + + +### Nested Schema for `spec.pubg` + +Required: + +- `infra` (String) +- `site` (String) + + + +### Nested Schema for `spec.vendor` + +Required: + +- `account_id` (String) +- `engine` (String) +- `name` (String) +- `region` (String) + + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/resources/clusterrolebinding.md b/docs/resources/clusterrolebinding.md new file mode 100644 index 0000000..6d347c2 --- /dev/null +++ b/docs/resources/clusterrolebinding.md @@ -0,0 +1,95 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_clusterrolebinding Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_clusterrolebinding (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) +- `spec` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `spec` + +Required: + +- `subject_ref` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec--subject_ref)) + +Optional: + +- `policy_inline` (Block List) (see [below for nested schema](#nestedblock--spec--policy_inline)) +- `policy_ref` (String) + + +### Nested Schema for `spec.subject_ref` + +Required: + +- `kind` (String) Kind of the referent. Valid kinds are 'User', 'Group'. +- `name` (String) Name of the referent. + + + +### Nested Schema for `spec.policy_inline` + +Required: + +- `actions` (Set of String) Actions is a list of actions this role binding grants access to. +- `paths` (Set of String) Paths is a list of paths this role binding grants access to. +- `resources` (Block Set, Min: 1) Resources is a list of resources this role binding grants access to. (see [below for nested schema](#nestedblock--spec--policy_inline--resources)) + + +### Nested Schema for `spec.policy_inline.resources` + +Required: + +- `api_group` (String) APIGroup is the group for the resource being referenced. +- `kind` (String) Kind is the type of resource being referenced. + + + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/resources/image.md b/docs/resources/image.md new file mode 100644 index 0000000..003d9a8 --- /dev/null +++ b/docs/resources/image.md @@ -0,0 +1,68 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_image Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_image (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) +- `spec` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. +- `namespace` (String) Namespace is the namespace of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `spec` + +Required: + +- `app` (String) +- `branch` (String) +- `commit_hash` (String) +- `repository` (String) +- `tag` (String) +- `timestamp` (Number) + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/resources/namespace.md b/docs/resources/namespace.md new file mode 100644 index 0000000..6ee136d --- /dev/null +++ b/docs/resources/namespace.md @@ -0,0 +1,53 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_namespace Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_namespace (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/resources/oidcauth.md b/docs/resources/oidcauth.md new file mode 100644 index 0000000..61d1f8f --- /dev/null +++ b/docs/resources/oidcauth.md @@ -0,0 +1,81 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_oidcauth Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_oidcauth (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) +- `spec` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `spec` + +Required: + +- `client_id` (String) +- `groups_claim` (String) +- `issuer` (String) +- `username_claim` (String) + +Optional: + +- `attribute_mapping` (Block List) (see [below for nested schema](#nestedblock--spec--attribute_mapping)) +- `groups_prefix` (String) +- `required_claims` (Set of String) +- `username_prefix` (String) + + +### Nested Schema for `spec.attribute_mapping` + +Required: + +- `from` (String) +- `to` (String) + + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/resources/rolebinding.md b/docs/resources/rolebinding.md new file mode 100644 index 0000000..cdea6aa --- /dev/null +++ b/docs/resources/rolebinding.md @@ -0,0 +1,96 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_rolebinding Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_rolebinding (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) +- `spec` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. +- `namespace` (String) Namespace is the namespace of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `spec` + +Required: + +- `subject_ref` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec--subject_ref)) + +Optional: + +- `policy_inline` (Block List) (see [below for nested schema](#nestedblock--spec--policy_inline)) +- `policy_ref` (String) + + +### Nested Schema for `spec.subject_ref` + +Required: + +- `kind` (String) Kind of the referent. Valid kinds are 'User', 'Group'. +- `name` (String) Name of the referent. + + + +### Nested Schema for `spec.policy_inline` + +Required: + +- `actions` (Set of String) Actions is a list of actions this role binding grants access to. +- `paths` (Set of String) Paths is a list of paths this role binding grants access to. +- `resources` (Block Set, Min: 1) Resources is a list of resources this role binding grants access to. (see [below for nested schema](#nestedblock--spec--policy_inline--resources)) + + +### Nested Schema for `spec.policy_inline.resources` + +Required: + +- `api_group` (String) APIGroup is the group for the resource being referenced. +- `kind` (String) Kind is the type of resource being referenced. + + + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/resources/user.md b/docs/resources/user.md new file mode 100644 index 0000000..2e8ceb1 --- /dev/null +++ b/docs/resources/user.md @@ -0,0 +1,63 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_user Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_user (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) +- `spec` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `spec` + +Required: + +- `groups` (Set of String) +- `password` (String) + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/docs/resources/vendor.md b/docs/resources/vendor.md new file mode 100644 index 0000000..77d597a --- /dev/null +++ b/docs/resources/vendor.md @@ -0,0 +1,65 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bluechip_vendor Resource - terraform-provider-bluechip" +subcategory: "" +description: |- + +--- + +# bluechip_vendor (Resource) + + + + + + +## Schema + +### Required + +- `metadata` (Block List, Min: 1) (see [below for nested schema](#nestedblock--metadata)) +- `spec` (Block List, Min: 1) (see [below for nested schema](#nestedblock--spec)) + +### Optional + +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `id` (String) The ID of this resource. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is the name of the resource. + +Optional: + +- `annotations` (Map of String) Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. +- `labels` (Map of String) Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects. + +Read-Only: + +- `creation_timestamp` (String) CreationTimestamp is a timestamp representing the server time when this object was created. +- `update_timestamp` (String) UpdateTimestamp is a timestamp representing the server time when this object was last updated. + + + +### Nested Schema for `spec` + +Required: + +- `code_name` (String) +- `display_name` (String) +- `regions` (Set of String) +- `short_name` (String) + + + +### Nested Schema for `timeouts` + +Optional: + +- `default` (String) diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..026c42c --- /dev/null +++ b/examples/README.md @@ -0,0 +1,9 @@ +# Examples + +This directory contains examples that are mostly used for documentation, but can also be run/tested manually via the Terraform CLI. + +The document generation tool looks for files in the following locations by default. All other *.tf files besides the ones mentioned below are ignored by the documentation tool. This is useful for creating examples that can run and/or ar testable even if some parts are not relevant for the documentation. + +* **provider/provider.tf** example file for the provider index page +* **data-sources/`full data source name`/data-source.tf** example file for the named data source page +* **resources/`full resource name`/resource.tf** example file for the named data source page diff --git a/examples/data-sources/scaffolding_example/data-source.tf b/examples/data-sources/scaffolding_example/data-source.tf new file mode 100644 index 0000000..a852489 --- /dev/null +++ b/examples/data-sources/scaffolding_example/data-source.tf @@ -0,0 +1,3 @@ +data "scaffolding_example" "example" { + configurable_attribute = "some-value" +} diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf new file mode 100644 index 0000000..59cddbe --- /dev/null +++ b/examples/provider/provider.tf @@ -0,0 +1,32 @@ +provider "bluechip" { + address = "app.bluechip.com" + basic_auth { + username = "myuser" + password = "mypassword" + } +} + +provider "bluechip" { + alias = "token" + address = "app.bluechip.com" + token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" +} + +provider "bluechip" { + alias = "aws" + address = "app.bluechip.com" + aws_auth { + cluster_name = "bluechip-prod" + region = "us-east-1" + } +} + +provider "bluechip" { + alias = "oidc" + address = "app.bluechip.com" + oidc_auth { + validator_name = "kubernetes-centre" + token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } +} + diff --git a/examples/resources/scaffolding_example/resource.tf b/examples/resources/scaffolding_example/resource.tf new file mode 100644 index 0000000..9ae3f57 --- /dev/null +++ b/examples/resources/scaffolding_example/resource.tf @@ -0,0 +1,3 @@ +resource "scaffolding_example" "example" { + configurable_attribute = "some-value" +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d7ebeef --- /dev/null +++ b/go.mod @@ -0,0 +1,93 @@ +module github.com/pubg/terraform-provider-bluechip + +go 1.21 + +require ( + github.com/aws/aws-sdk-go-v2 v1.24.0 + github.com/aws/aws-sdk-go-v2/config v1.26.2 + github.com/aws/aws-sdk-go-v2/credentials v1.16.13 + github.com/aws/aws-sdk-go-v2/service/sts v1.26.6 + github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 + github.com/hashicorp/terraform-plugin-docs v0.16.0 + github.com/hashicorp/terraform-plugin-go v0.20.0 + github.com/hashicorp/terraform-plugin-log v0.9.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0 + github.com/hashicorp/terraform-plugin-testing v1.6.0 + github.com/joho/godotenv v1.5.1 + github.com/yudai/gojsondiff v1.0.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/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect + github.com/agext/levenshtein v1.2.2 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/armon/go-radix v1.0.0 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 // indirect + github.com/aws/smithy-go v1.19.0 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/cloudflare/circl v1.3.3 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/uuid v1.3.1 // 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.5.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-plugin v1.6.0 // 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.6.1 // indirect + github.com/hashicorp/hcl/v2 v2.19.1 // indirect + github.com/hashicorp/logutils v1.0.0 // indirect + github.com/hashicorp/terraform-exec v0.19.0 // indirect + github.com/hashicorp/terraform-json v0.18.0 // indirect + github.com/hashicorp/terraform-registry-address v0.2.3 // indirect + github.com/hashicorp/terraform-svchost v0.1.1 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect + github.com/huandu/xstrings v1.3.2 // indirect + github.com/imdario/mergo v0.3.15 // 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.5 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/oklog/run v1.0.0 // indirect + github.com/onsi/ginkgo v1.16.5 // indirect + github.com/onsi/gomega v1.30.0 // indirect + github.com/posener/complete v1.2.3 // indirect + github.com/russross/blackfriday v1.6.0 // indirect + github.com/sergi/go-diff v1.2.0 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect + github.com/yudai/pp v2.0.1+incompatible // indirect + github.com/zclconf/go-cty v1.14.1 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/grpc v1.60.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..fe4c498 --- /dev/null +++ b/go.sum @@ -0,0 +1,377 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +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.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +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.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= +github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +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/aws/aws-sdk-go-v2 v1.24.0 h1:890+mqQ+hTpNuw0gGP6/4akolQkSToDJgHfQE7AwGuk= +github.com/aws/aws-sdk-go-v2 v1.24.0/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4= +github.com/aws/aws-sdk-go-v2/config v1.26.2 h1:+RWLEIWQIGgrz2pBPAUoGgNGs1TOyF4Hml7hCnYj2jc= +github.com/aws/aws-sdk-go-v2/config v1.26.2/go.mod h1:l6xqvUxt0Oj7PI/SUXYLNyZ9T/yBPn3YTQcJLLOdtR8= +github.com/aws/aws-sdk-go-v2/credentials v1.16.13 h1:WLABQ4Cp4vXtXfOWOS3MEZKr6AAYUpMczLhgKtAjQ/8= +github.com/aws/aws-sdk-go-v2/credentials v1.16.13/go.mod h1:Qg6x82FXwW0sJHzYruxGiuApNo31UEtJvXVSZAXeWiw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 h1:w98BT5w+ao1/r5sUuiH6JkVzjowOKeOJRHERyy1vh58= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10/go.mod h1:K2WGI7vUvkIv1HoNbfBA1bvIZ+9kL3YVmWxeKuLQsiw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 h1:v+HbZaCGmOwnTTVS86Fleq0vPzOd7tnJGbFhP0stNLs= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9/go.mod h1:Xjqy+Nyj7VDLBtCMkQYOw1QYfAEZCVLrfI0ezve8wd4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 h1:N94sVhRACtXyVcjXxrwK1SKFIJrA9pOJ5yu2eSHnmls= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9/go.mod h1:hqamLz7g1/4EJP+GH5NBhcUMLjW+gKLQabgyz6/7WAU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 h1:GrSw8s0Gs/5zZ0SX+gX4zQjRnRsMJDJ2sLur1gRBhEM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 h1:Nf2sHxjMJR8CSImIVCONRi4g0Su3J+TSTbS7G0pUeMU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9/go.mod h1:idky4TER38YIjr2cADF1/ugFMKvZV7p//pVeV5LZbF0= +github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 h1:ldSFWz9tEHAwHNmjx2Cvy1MjP5/L9kNoR0skc6wyOOM= +github.com/aws/aws-sdk-go-v2/service/sso v1.18.5/go.mod h1:CaFfXLYL376jgbP7VKC96uFcU8Rlavak0UlAwk1Dlhc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 h1:2k9KmFawS63euAkY4/ixVNsYYwrwnd5fIvgEKkfZFNM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5/go.mod h1:W+nd4wWDVkSUIox9bacmkBP5NMFQeTJ/xqNabpzSR38= +github.com/aws/aws-sdk-go-v2/service/sts v1.26.6 h1:HJeiuZ2fldpd0WqngyMR6KW7ofkXNLyOaHwEIGm39Cs= +github.com/aws/aws-sdk-go-v2/service/sts v1.26.6/go.mod h1:XX5gh4CB7wAs4KhcF46G6C8a2i7eupU19dcAAE+EydU= +github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM= +github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +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/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY= +github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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.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.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +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.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= +github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/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.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= +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.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hc-install v0.6.1 h1:IGxShH7AVhPaSuSJpKtVi/EFORNjO+OYVJJrAtGG2mY= +github.com/hashicorp/hc-install v0.6.1/go.mod h1:0fW3jpg+wraYSnFDJ6Rlie3RvLf1bIqVIkzoon4KoVE= +github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI= +github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/terraform-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM= +github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg= +github.com/hashicorp/terraform-json v0.18.0 h1:pCjgJEqqDESv4y0Tzdqfxr/edOIGkjs8keY42xfNBwU= +github.com/hashicorp/terraform-json v0.18.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= +github.com/hashicorp/terraform-plugin-docs v0.16.0 h1:UmxFr3AScl6Wged84jndJIfFccGyBZn52KtMNsS12dI= +github.com/hashicorp/terraform-plugin-docs v0.16.0/go.mod h1:M3ZrlKBJAbPMtNOPwHicGi1c+hZUh7/g0ifT/z7TVfA= +github.com/hashicorp/terraform-plugin-go v0.20.0 h1:oqvoUlL+2EUbKNsJbIt3zqqZ7wi6lzn4ufkn/UA51xQ= +github.com/hashicorp/terraform-plugin-go v0.20.0/go.mod h1:Rr8LBdMlY53a3Z/HpP+ZU3/xCDqtKNCkeI9qOyT10QE= +github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= +github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0 h1:X7vB6vn5tON2b49ILa4W7mFAsndeqJ7bZFOGbVO+0Cc= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0/go.mod h1:ydFcxbdj6klCqYEPkPvdvFKiNGKZLUs+896ODUXCyao= +github.com/hashicorp/terraform-plugin-testing v1.6.0 h1:Wsnfh+7XSVRfwcr2jZYHsnLOnZl7UeaOBvsx6dl/608= +github.com/hashicorp/terraform-plugin-testing v1.6.0/go.mod h1:cJGG0/8j9XhHaJZRC+0sXFI4uzqQZ9Az4vh6C4GJpFE= +github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= +github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= +github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= +github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +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.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +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/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +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 v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +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/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng= +github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= +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-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +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.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +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/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +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/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= +github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= +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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +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.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= +github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA= +github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819 h1:EDuYyU/MkFXllv9QF9819VlI9a4tzGuCbhG0ExK9o1U= +golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/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-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-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +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= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= +google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +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.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/internal/provider/provider.go b/internal/provider/provider.go new file mode 100644 index 0000000..cbbf679 --- /dev/null +++ b/internal/provider/provider.go @@ -0,0 +1,262 @@ +package provider + +import ( + "context" + "fmt" + "net/http" + "time" + + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_authenticator" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwlog" +) + +func Provider() *schema.Provider { + p := &schema.Provider{ + Schema: map[string]*schema.Schema{ + "address": { + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("BLUECHIP_ADDRESS", ""), + }, + "token": { + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("BLUECHIP_TOKEN", ""), + }, + "basic_auth": { + Type: schema.TypeList, + MinItems: 0, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "username": { + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("BLUECHIP_USERNAME", ""), + }, + "password": { + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("BLUECHIP_PASSWORD", ""), + }, + }, + }, + }, + "aws_auth": { + Type: schema.TypeList, + MinItems: 0, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cluster_name": { + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("BLUECHIP_CLUSTER_NAME", ""), + }, + "access_key": { + Type: schema.TypeString, + Optional: true, + }, + "secret_access_key": { + Type: schema.TypeString, + Optional: true, + }, + "session_token": { + Type: schema.TypeString, + Optional: true, + }, + "region": { + Type: schema.TypeString, + Required: true, + }, + "profile": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "oidc_auth": { + Type: schema.TypeList, + MinItems: 0, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "validator_name": { + Type: schema.TypeString, + Required: true, + }, + "token": { + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("BLUECHIP_OIDC_TOKEN", ""), + }, + }, + }, + }, + }, + ResourcesMap: resourceMap, + DataSourcesMap: dataSourceMap, + } + + p.ConfigureContextFunc = func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { + return providerConfigure(ctx, d, p.TerraformVersion) + } + + return p +} + +type ProviderModel struct { + Version string + Client *bluechip_client.Client +} + +func providerConfigure(ctx context.Context, d *schema.ResourceData, providerVersion string) (interface{}, diag.Diagnostics) { + config := initializeConfiguration(d) + tflog.Debug(ctx, "Read Provider Config", fwlog.Field("config", config)) + + // Validate the auth configuration values + baseClient := &http.Client{Transport: logging.NewLoggingHTTPTransport(http.DefaultTransport)} + authClient := bluechip_authenticator.NewClient(baseClient, providerVersion, config.Address) + token, diags := initializeBluechipToken(ctx, authClient, config) + if diags.HasError() { + tflog.Info(ctx, "Failed to Initialize BlueChip Token", fwlog.Field("diags", diags)) + return nil, diags + } + + client := bluechip_client.NewClient(baseClient, token, providerVersion, config.Address, 3*time.Second, 30*time.Second) + // WhoAmI API로 사용자 정보 검증 + if _, err := client.Whoami(ctx); err != nil { + tflog.Info(ctx, "Failed to validate the provider's auth configuration values", fwlog.Field("error", err)) + return nil, diag.FromErr(fmt.Errorf("failed to validate the provider's auth configuration values: %v", err)) + } + + model := &ProviderModel{ + Version: providerVersion, + Client: client, + } + return model, nil +} + +type ProviderConfig struct { + Address string + Token *string + BasicAuth *struct { + Username string + Password string + } + AwsAuth *struct { + ClusterName string + AccessKey *string + SecretAccessKey *string + SessionToken *string + Region string + Profile *string + } + OidcAuth *struct { + ValidatorName string + Token string + } +} + +func initializeConfiguration(d *schema.ResourceData) ProviderConfig { + var config ProviderConfig + config.Address = d.Get("address").(string) + + if v, ok := d.GetOk("token"); ok { + config.Token = v.(*string) + } + + // Copilot wrote this code + if v, ok := d.GetOk("basic_auth"); ok { + config.BasicAuth = &struct { + Username string + Password string + }{ + Username: v.([]interface{})[0].(map[string]interface{})["username"].(string), + Password: v.([]interface{})[0].(map[string]interface{})["password"].(string), + } + } + + if v, ok := d.GetOk("aws_auth"); ok { + config.AwsAuth = &struct { + ClusterName string + AccessKey *string + SecretAccessKey *string + SessionToken *string + Region string + Profile *string + }{ + ClusterName: v.([]interface{})[0].(map[string]interface{})["cluster_name"].(string), + AccessKey: v.([]interface{})[0].(map[string]interface{})["access_key"].(*string), + SecretAccessKey: v.([]interface{})[0].(map[string]interface{})["secret_access_key"].(*string), + SessionToken: v.([]interface{})[0].(map[string]interface{})["session_token"].(*string), + Region: v.([]interface{})[0].(map[string]interface{})["region"].(string), + Profile: v.([]interface{})[0].(map[string]interface{})["profile"].(*string), + } + } + + if v, ok := d.GetOk("oidc_auth"); ok { + config.OidcAuth = &struct { + ValidatorName string + Token string + }{ + ValidatorName: v.([]interface{})[0].(map[string]interface{})["validator_name"].(string), + Token: v.([]interface{})[0].(map[string]interface{})["token"].(string), + } + } + + return config +} + +func initializeBluechipToken(ctx context.Context, authClient *bluechip_authenticator.Client, config ProviderConfig) (string, diag.Diagnostics) { + if config.Token != nil { + return *config.Token, nil + } else if config.BasicAuth != nil { + token, err := authClient.LoginWithBasic(context.Background(), config.BasicAuth.Username, config.BasicAuth.Password) + if err != nil { + return "", diag.FromErr(err) + } + return token, nil + } else if config.AwsAuth != nil { + token, err := authClient.LoginWithAws(ctx, config.AwsAuth.ClusterName, defaultString(config.AwsAuth.AccessKey, ""), defaultString(config.AwsAuth.SecretAccessKey, ""), defaultString(config.AwsAuth.SessionToken, ""), config.AwsAuth.Region, defaultString(config.AwsAuth.Profile, "")) + if err != nil { + return "", diag.FromErr(err) + } + return token, nil + } else if config.OidcAuth != nil { + token, err := authClient.LoginWithOidc(context.Background(), config.OidcAuth.Token, config.OidcAuth.ValidatorName) + if err != nil { + return "", diag.FromErr(err) + } + return token, nil + } + return "", diag.Errorf("either token, basic_auth, aws_auth or oidc_auth must be specified") +} + +func defaultString(s *string, def string) string { + if s == nil { + return def + } + return *s +} + +var resourceMap = map[string]*schema.Resource{} + +func RegisterResource(name string, resource *schema.Resource) { + resourceMap[name] = resource +} + +var dataSourceMap = map[string]*schema.Resource{} + +func RegisterDataSource(name string, dataSource *schema.Resource) { + dataSourceMap[name] = dataSource +} diff --git a/internal/services/accounts/data_source.go b/internal/services/accounts/data_source.go new file mode 100644 index 0000000..eb6bdaa --- /dev/null +++ b/internal/services/accounts/data_source.go @@ -0,0 +1,23 @@ +package accounts + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformDataSource[bluechip_models.Account, bluechip_models.AccountSpec]{ + Gvk: bluechip_models.AccountGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/accounts/data_source_test.go b/internal/services/accounts/data_source_test.go new file mode 100644 index 0000000..3fc2923 --- /dev/null +++ b/internal/services/accounts/data_source_test.go @@ -0,0 +1,37 @@ +package accounts + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccDataSourceConfig) + "\n" + TestAccResourceConfig, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_account.current", "id", "default/test2"), + resource.TestCheckResourceAttr("data.bluechip_account.current", "metadata.0.name", "test2"), + resource.TestCheckResourceAttrWith("data.bluechip_account.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_account" "current" { + metadata { + name = "test2" + namespace = "default" + } + depends_on = [bluechip_account.current] +} +` diff --git a/internal/services/accounts/register.go b/internal/services/accounts/register.go new file mode 100644 index 0000000..8c287a3 --- /dev/null +++ b/internal/services/accounts/register.go @@ -0,0 +1,10 @@ +package accounts + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_account", NewResource().Resource()) + provider.RegisterDataSource("bluechip_account", NewDataSource().Resource()) +} diff --git a/internal/services/accounts/resource.go b/internal/services/accounts/resource.go new file mode 100644 index 0000000..dcaec06 --- /dev/null +++ b/internal/services/accounts/resource.go @@ -0,0 +1,30 @@ +package accounts + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformResource[bluechip_models.Account, bluechip_models.AccountSpec]{ + Gvk: bluechip_models.AccountGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.Account { + return bluechip_models.Account{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.AccountSpec]{}, + } + }, + } +} diff --git a/internal/services/accounts/resource_test.go b/internal/services/accounts/resource_test.go new file mode 100644 index 0000000..b14033a --- /dev/null +++ b/internal/services/accounts/resource_test.go @@ -0,0 +1,44 @@ +package accounts + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_account.current", "id", "default/test2"), + resource.TestCheckResourceAttr("bluechip_account.current", "metadata.0.name", "test2"), + resource.TestCheckResourceAttrWith("bluechip_account.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_account" "current" { + metadata { + name = "test2" + namespace = "default" + } + spec { + account_id = "12398213" + display_name = "test" + description = "test" + alias = "test" + vendor = "AWS" + regions = ["test"] + } +} +` diff --git a/internal/services/accounts/type.go b/internal/services/accounts/type.go new file mode 100644 index 0000000..e93258d --- /dev/null +++ b/internal/services/accounts/type.go @@ -0,0 +1,81 @@ +package accounts + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "account_id": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "display_name": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "description": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "alias": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "vendor": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "regions": { + Type: schema.TypeSet, + Required: !computed, + Computed: computed, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + } + + blockSchema := fwtype.SingleNestedBlock(innerSchema, computed, true) + fwtype.CleanForDataSource(blockSchema) + return blockSchema +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.AccountSpec) diag.Diagnostics { + attr := d.Get("spec.0").(map[string]any) + out.AccountId = attr["account_id"].(string) + out.DisplayName = attr["display_name"].(string) + out.Description = attr["description"].(string) + out.Alias = attr["alias"].(string) + out.Vendor = attr["vendor"].(string) + out.Regions = fwflex.ExpandStringSet(attr["regions"].(*schema.Set)) + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.AccountSpec) diag.Diagnostics { + attr := map[string]any{ + "account_id": in.AccountId, + "display_name": in.DisplayName, + "description": in.Description, + "alias": in.Alias, + "vendor": in.Vendor, + "regions": in.Regions, + } + + if err := d.Set("spec", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/internal/services/applications/apiresources_data_source.go b/internal/services/applications/apiresources_data_source.go new file mode 100644 index 0000000..46d28a9 --- /dev/null +++ b/internal/services/applications/apiresources_data_source.go @@ -0,0 +1,74 @@ +package applications + +import ( + "context" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/internal/provider" +) + +func NewApiResourcesDataSource() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceApiResourcesRead, + Schema: map[string]*schema.Schema{ + "api_resources": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "group": { + Type: schema.TypeString, + Computed: true, + }, + "version": { + Type: schema.TypeString, + Computed: true, + }, + "kind": { + Type: schema.TypeString, + Computed: true, + }, + "kind_plural": { + Type: schema.TypeString, + Computed: true, + }, + "namespaced": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, + }, + Timeouts: &schema.ResourceTimeout{ + Default: schema.DefaultTimeout(5 * time.Second), + }, + } +} + +func dataSourceApiResourcesRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + model := meta.(*provider.ProviderModel) + apiResourcesResp, err := model.Client.ApiResources(ctx) + if err != nil { + return diag.Errorf("Unable to read example, got error: %s", err) + } + + d.SetId("api-resources") + + var apiResources []map[string]any + for _, apiResource := range apiResourcesResp.Items { + apiResources = append(apiResources, map[string]any{ + "group": apiResource.Group, + "version": apiResource.Version, + "kind": apiResource.Kind, + "kind_plural": apiResource.KindPlural, + "namespaced": apiResource.Namespaced, + }) + } + if err = d.Set("api_resources", apiResources); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/internal/services/applications/apiresources_data_source_test.go b/internal/services/applications/apiresources_data_source_test.go new file mode 100644 index 0000000..d55cf0c --- /dev/null +++ b/internal/services/applications/apiresources_data_source_test.go @@ -0,0 +1,31 @@ +package applications + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccApiResourcesDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccApiResourcesDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_apiresources.current", "id", "api-resources"), + resource.TestCheckResourceAttrWith("data.bluechip_apiresources.current", "api_resources.0.group", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccApiResourcesDataSourceConfig = ` +data "bluechip_apiresources" "current" { +} +` diff --git a/internal/services/applications/register.go b/internal/services/applications/register.go new file mode 100644 index 0000000..6e69f5a --- /dev/null +++ b/internal/services/applications/register.go @@ -0,0 +1,8 @@ +package applications + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +func init() { + provider.RegisterDataSource("bluechip_whoami", NewWhoamiDataSource()) + provider.RegisterDataSource("bluechip_apiresources", NewApiResourcesDataSource()) +} diff --git a/internal/services/applications/whoami_data_source.go b/internal/services/applications/whoami_data_source.go new file mode 100644 index 0000000..782a8e6 --- /dev/null +++ b/internal/services/applications/whoami_data_source.go @@ -0,0 +1,56 @@ +package applications + +import ( + "context" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/internal/provider" +) + +func NewWhoamiDataSource() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceWhoamiRead, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "groups": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "attributes": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + Timeouts: &schema.ResourceTimeout{ + Default: schema.DefaultTimeout(5 * time.Second), + }, + } +} + +func dataSourceWhoamiRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + model := meta.(*provider.ProviderModel) + whoamiResp, err := model.Client.Whoami(ctx) + if err != nil { + return diag.Errorf("Unable to read example, got error: %s", err) + } + + d.SetId(whoamiResp.Name) + if err := d.Set("name", whoamiResp.Name); err != nil { + return diag.FromErr(err) + } + if err := d.Set("groups", whoamiResp.Groups); err != nil { + return diag.FromErr(err) + } + if err := d.Set("attributes", whoamiResp.Attributes); err != nil { + return diag.FromErr(err) + } + + return nil +} diff --git a/internal/services/applications/whoami_data_source_test.go b/internal/services/applications/whoami_data_source_test.go new file mode 100644 index 0000000..3409c82 --- /dev/null +++ b/internal/services/applications/whoami_data_source_test.go @@ -0,0 +1,30 @@ +package applications + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestWhoamiDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccWhoAmiDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_whoami.current", "id", "admin"), + resource.TestCheckResourceAttr("data.bluechip_whoami.current", "name", "admin"), + resource.TestCheckResourceAttr("data.bluechip_whoami.current", "groups.0", "system-admin"), + ), + }, + }, + }) +} + +const TestAccWhoAmiDataSourceConfig = ` +data "bluechip_whoami" "current" { +} +` diff --git a/internal/services/cidrs/data_source.go b/internal/services/cidrs/data_source.go new file mode 100644 index 0000000..22daab0 --- /dev/null +++ b/internal/services/cidrs/data_source.go @@ -0,0 +1,23 @@ +package cidrs + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformDataSource[bluechip_models.Cidr, bluechip_models.CidrSpec]{ + Gvk: bluechip_models.CidrGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/cidrs/data_source_test.go b/internal/services/cidrs/data_source_test.go new file mode 100644 index 0000000..725e991 --- /dev/null +++ b/internal/services/cidrs/data_source_test.go @@ -0,0 +1,38 @@ +package cidrs + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig, TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_cidr.current", "id", "default/my-test"), + resource.TestCheckResourceAttr("data.bluechip_cidr.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("data.bluechip_cidr.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("data.bluechip_cidr.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_cidr" "current" { + metadata { + name = "my-test" + namespace = "default" + } + depends_on = [bluechip_cidr.current] +} +` diff --git a/internal/services/cidrs/register.go b/internal/services/cidrs/register.go new file mode 100644 index 0000000..6658f98 --- /dev/null +++ b/internal/services/cidrs/register.go @@ -0,0 +1,10 @@ +package cidrs + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_cidr", NewResource().Resource()) + provider.RegisterDataSource("bluechip_cidr", NewDataSource().Resource()) +} diff --git a/internal/services/cidrs/resource.go b/internal/services/cidrs/resource.go new file mode 100644 index 0000000..a841c0b --- /dev/null +++ b/internal/services/cidrs/resource.go @@ -0,0 +1,30 @@ +package cidrs + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformResource[bluechip_models.Cidr, bluechip_models.CidrSpec]{ + Gvk: bluechip_models.CidrGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.Cidr { + return bluechip_models.Cidr{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.CidrSpec]{}, + } + }, + } +} diff --git a/internal/services/cidrs/resource_test.go b/internal/services/cidrs/resource_test.go new file mode 100644 index 0000000..9d9181d --- /dev/null +++ b/internal/services/cidrs/resource_test.go @@ -0,0 +1,41 @@ +package cidrs + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_cidr.current", "id", "default/my-test"), + resource.TestCheckResourceAttr("bluechip_cidr.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("bluechip_cidr.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("bluechip_cidr.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_cidr" "current" { + metadata { + name = "my-test" + namespace = "default" + } + spec { + ipv4_cidrs = ["1.1.1.1/32"] + ipv6_cidrs = ["::1/32"] + } +} +` diff --git a/internal/services/cidrs/type.go b/internal/services/cidrs/type.go new file mode 100644 index 0000000..73f6e66 --- /dev/null +++ b/internal/services/cidrs/type.go @@ -0,0 +1,61 @@ +package cidrs + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "ipv4_cidrs": { + Type: schema.TypeSet, + Optional: !computed, + Computed: computed, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.IsCIDR, + }, + }, + "ipv6_cidrs": { + Type: schema.TypeSet, + Optional: !computed, + Computed: computed, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.IsCIDR, + }, + }, + } + + blockSchema := fwtype.SingleNestedBlock(innerSchema, computed, true) + fwtype.CleanForDataSource(blockSchema) + return blockSchema +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.CidrSpec) diag.Diagnostics { + attr := d.Get("spec.0").(map[string]any) + out.Ipv4Cidrs = fwflex.ExpandStringSet(attr["ipv4_cidrs"].(*schema.Set)) + out.Ipv6Cidrs = fwflex.ExpandStringSet(attr["ipv6_cidrs"].(*schema.Set)) + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.CidrSpec) diag.Diagnostics { + attr := map[string]any{ + "ipv4_cidrs": in.Ipv4Cidrs, + "ipv6_cidrs": in.Ipv6Cidrs, + } + + if err := d.Set("spec", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/internal/services/clusterrolebindings/data_source.go b/internal/services/clusterrolebindings/data_source.go new file mode 100644 index 0000000..aa169d6 --- /dev/null +++ b/internal/services/clusterrolebindings/data_source.go @@ -0,0 +1,23 @@ +package clusterrolebindings + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformDataSource[bluechip_models.ClusterRoleBinding, bluechip_models.ClusterRoleBindingSpec]{ + Gvk: bluechip_models.ClusterRoleBindingGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/clusterrolebindings/data_source_test.go b/internal/services/clusterrolebindings/data_source_test.go new file mode 100644 index 0000000..f19ee3e --- /dev/null +++ b/internal/services/clusterrolebindings/data_source_test.go @@ -0,0 +1,37 @@ +package clusterrolebindings + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig, TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_clusterrolebinding.current", "id", "my-test"), + resource.TestCheckResourceAttr("data.bluechip_clusterrolebinding.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("data.bluechip_clusterrolebinding.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("data.bluechip_clusterrolebinding.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_clusterrolebinding" "current" { + metadata { + name = "my-test" + } + depends_on = [bluechip_clusterrolebinding.current] +} +` diff --git a/internal/services/clusterrolebindings/register.go b/internal/services/clusterrolebindings/register.go new file mode 100644 index 0000000..fad457b --- /dev/null +++ b/internal/services/clusterrolebindings/register.go @@ -0,0 +1,10 @@ +package clusterrolebindings + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_clusterrolebinding", NewResource().Resource()) + provider.RegisterDataSource("bluechip_clusterrolebinding", NewDataSource().Resource()) +} diff --git a/internal/services/clusterrolebindings/resource.go b/internal/services/clusterrolebindings/resource.go new file mode 100644 index 0000000..0c3dfcd --- /dev/null +++ b/internal/services/clusterrolebindings/resource.go @@ -0,0 +1,30 @@ +package clusterrolebindings + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformResource[bluechip_models.ClusterRoleBinding, bluechip_models.ClusterRoleBindingSpec]{ + Gvk: bluechip_models.ClusterRoleBindingGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.ClusterRoleBinding { + return bluechip_models.ClusterRoleBinding{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.ClusterRoleBindingSpec]{}, + } + }, + } +} diff --git a/internal/services/clusterrolebindings/resource_test.go b/internal/services/clusterrolebindings/resource_test.go new file mode 100644 index 0000000..49f2637 --- /dev/null +++ b/internal/services/clusterrolebindings/resource_test.go @@ -0,0 +1,43 @@ +package clusterrolebindings + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_clusterrolebinding.current", "id", "my-test"), + resource.TestCheckResourceAttr("bluechip_clusterrolebinding.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("bluechip_clusterrolebinding.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("bluechip_clusterrolebinding.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_clusterrolebinding" "current" { + metadata { + name = "my-test" + } + spec { + subject_ref { + kind = "User" + name = "my-test" + } + policy_ref = "admin" + } +} +` diff --git a/internal/services/clusterrolebindings/type.go b/internal/services/clusterrolebindings/type.go new file mode 100644 index 0000000..0c737b2 --- /dev/null +++ b/internal/services/clusterrolebindings/type.go @@ -0,0 +1,43 @@ +package clusterrolebindings + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + return fwtype.RoleBindingTyp.Schema(computed) +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.ClusterRoleBindingSpec) diag.Diagnostics { + var rb bluechip_models.RoleBindingSpec + diags := fwtype.RoleBindingTyp.Expand(ctx, d, &rb) + if diags.HasError() { + return diags + } + + out.SubjectsRef = rb.SubjectsRef + out.PolicyInline = rb.PolicyInline + out.PolicyRef = rb.PolicyRef + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.ClusterRoleBindingSpec) diag.Diagnostics { + var rb bluechip_models.RoleBindingSpec + rb.SubjectsRef = in.SubjectsRef + rb.PolicyInline = in.PolicyInline + rb.PolicyRef = in.PolicyRef + + diags := fwtype.RoleBindingTyp.Flatten(ctx, d, rb) + if diags.HasError() { + return diags + } + return nil +} diff --git a/internal/services/clusters/data_source.go b/internal/services/clusters/data_source.go new file mode 100644 index 0000000..3a934b1 --- /dev/null +++ b/internal/services/clusters/data_source.go @@ -0,0 +1,23 @@ +package clusters + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformDataSource[bluechip_models.Cluster, bluechip_models.ClusterSpec]{ + Gvk: bluechip_models.ClusterGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/clusters/data_source_test.go b/internal/services/clusters/data_source_test.go new file mode 100644 index 0000000..d375d0d --- /dev/null +++ b/internal/services/clusters/data_source_test.go @@ -0,0 +1,37 @@ +package clusters + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig, TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_cluster.current", "id", "default/test"), + resource.TestCheckResourceAttr("data.bluechip_cluster.current", "metadata.0.name", "test"), + resource.TestCheckResourceAttrWith("data.bluechip_cluster.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_cluster" "current" { + metadata { + name = "test" + namespace = "default" + } + depends_on = [bluechip_cluster.current] +} +` diff --git a/internal/services/clusters/register.go b/internal/services/clusters/register.go new file mode 100644 index 0000000..602fe1e --- /dev/null +++ b/internal/services/clusters/register.go @@ -0,0 +1,10 @@ +package clusters + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_cluster", NewResource().Resource()) + provider.RegisterDataSource("bluechip_cluster", NewDataSource().Resource()) +} diff --git a/internal/services/clusters/resource.go b/internal/services/clusters/resource.go new file mode 100644 index 0000000..5be3930 --- /dev/null +++ b/internal/services/clusters/resource.go @@ -0,0 +1,30 @@ +package clusters + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformResource[bluechip_models.Cluster, bluechip_models.ClusterSpec]{ + Gvk: bluechip_models.ClusterGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.Cluster { + return bluechip_models.Cluster{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.ClusterSpec]{}, + } + }, + } +} diff --git a/internal/services/clusters/resource_test.go b/internal/services/clusters/resource_test.go new file mode 100644 index 0000000..ee9438d --- /dev/null +++ b/internal/services/clusters/resource_test.go @@ -0,0 +1,58 @@ +package clusters + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_cluster.current", "id", "default/test"), + resource.TestCheckResourceAttr("bluechip_cluster.current", "metadata.0.name", "test"), + resource.TestCheckResourceAttrWith("bluechip_cluster.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_cluster" "current" { + metadata { + name = "test" + namespace = "default" + } + spec { + project = "pubg" + environment = "dev" + organization_unit = "devops" + platform = "pc" + pubg { + infra = "common" + site = "devops" + } + vendor { + name = "AWS" + account_id = "12398213" + engine = "EKS" + region = "ap-northeast-2" + } + kubernetes { + endpoint = "https://api.devops.dev.pubg.com" + ca_cert = "-----BEGIN CERTIFI" + sa_issuer = "https://login.microsoftonline.com/1a27bdbf-e6cc-4e33-85d2-e1c81bad930a/v2.0" + version = "1.28" + } + } +} +` diff --git a/internal/services/clusters/type.go b/internal/services/clusters/type.go new file mode 100644 index 0000000..db5764e --- /dev/null +++ b/internal/services/clusters/type.go @@ -0,0 +1,168 @@ +package clusters + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "project": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "environment": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "organization_unit": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "platform": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "pubg": fwtype.SingleNestedBlock(map[string]*schema.Schema{ + "infra": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "site": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + }, computed, true), + "vendor": fwtype.SingleNestedBlock(map[string]*schema.Schema{ + "name": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "account_id": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "engine": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "region": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + }, computed, false), + "kubernetes": fwtype.SingleNestedBlock(map[string]*schema.Schema{ + "endpoint": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "ca_cert": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + "sa_issuer": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + ValidateFunc: validation.IsURLWithHTTPorHTTPS, + }, + "version": { + Required: !computed, + Computed: computed, + Type: schema.TypeString, + }, + }, computed, false), + } + + blockSchema := fwtype.SingleNestedBlock(innerSchema, computed, true) + fwtype.CleanForDataSource(blockSchema) + return blockSchema +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.ClusterSpec) diag.Diagnostics { + attr := d.Get("spec.0").(map[string]any) + out.Project = attr["project"].(string) + out.Environment = attr["environment"].(string) + out.OrganizationUnit = attr["organization_unit"].(string) + out.Platform = attr["platform"].(string) + + if pubgAttr, ok := d.GetOk("spec.0.pubg.0"); ok { + pubg := fwflex.ExpandMap(pubgAttr.(map[string]any)) + out.Pubg = &bluechip_models.ClusterSpecPubg{ + Infra: pubg["infra"], + Site: pubg["site"], + } + } + + vendor := fwflex.ExpandMap(d.Get("spec.0.vendor.0").(map[string]any)) + out.Vendor = bluechip_models.ClusterSpecVendor{ + Name: vendor["name"], + AccountId: vendor["account_id"], + Engine: vendor["engine"], + Region: vendor["region"], + } + + kubernetes := fwflex.ExpandMap(d.Get("spec.0.kubernetes.0").(map[string]any)) + out.Kubernetes = bluechip_models.ClusterSpecKubernetes{ + Endpoint: kubernetes["endpoint"], + CaCert: kubernetes["ca_cert"], + SaIssuer: kubernetes["sa_issuer"], + Version: kubernetes["version"], + } + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.ClusterSpec) diag.Diagnostics { + attr := map[string]any{} + attr["project"] = in.Project + attr["environment"] = in.Environment + attr["organization_unit"] = in.OrganizationUnit + attr["platform"] = in.Platform + + if in.Pubg != nil { + attr["pubg"] = []map[string]any{fwflex.FlattenMap(map[string]string{ + "infra": in.Pubg.Infra, + "site": in.Pubg.Site, + })} + } + + attr["vendor"] = []map[string]any{fwflex.FlattenMap(map[string]string{ + "name": in.Vendor.Name, + "account_id": in.Vendor.AccountId, + "engine": in.Vendor.Engine, + "region": in.Vendor.Region, + })} + + attr["kubernetes"] = []map[string]any{fwflex.FlattenMap(map[string]string{ + "endpoint": in.Kubernetes.Endpoint, + "ca_cert": in.Kubernetes.CaCert, + "sa_issuer": in.Kubernetes.SaIssuer, + "version": in.Kubernetes.Version, + })} + + if err := d.Set("spec", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/internal/services/images/data_source.go b/internal/services/images/data_source.go new file mode 100644 index 0000000..f9edeb1 --- /dev/null +++ b/internal/services/images/data_source.go @@ -0,0 +1,23 @@ +package images + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformDataSource[bluechip_models.Image, bluechip_models.ImageSpec]{ + Gvk: bluechip_models.ImageGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/images/data_source_test.go b/internal/services/images/data_source_test.go new file mode 100644 index 0000000..e417c6a --- /dev/null +++ b/internal/services/images/data_source_test.go @@ -0,0 +1,38 @@ +package images + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig, TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_image.current", "id", "default/my-test"), + resource.TestCheckResourceAttr("data.bluechip_image.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("data.bluechip_image.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("data.bluechip_image.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_image" "current" { + metadata { + name = "my-test" + namespace = "default" + } + depends_on = [bluechip_image.current] +} +` diff --git a/internal/services/images/register.go b/internal/services/images/register.go new file mode 100644 index 0000000..4a22d6f --- /dev/null +++ b/internal/services/images/register.go @@ -0,0 +1,10 @@ +package images + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_image", NewResource().Resource()) + provider.RegisterDataSource("bluechip_image", NewDataSource().Resource()) +} diff --git a/internal/services/images/resource.go b/internal/services/images/resource.go new file mode 100644 index 0000000..4c9dad7 --- /dev/null +++ b/internal/services/images/resource.go @@ -0,0 +1,30 @@ +package images + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformResource[bluechip_models.Image, bluechip_models.ImageSpec]{ + Gvk: bluechip_models.ImageGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.Image { + return bluechip_models.Image{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.ImageSpec]{}, + } + }, + } +} diff --git a/internal/services/images/resource_test.go b/internal/services/images/resource_test.go new file mode 100644 index 0000000..2364f83 --- /dev/null +++ b/internal/services/images/resource_test.go @@ -0,0 +1,45 @@ +package images + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_image.current", "id", "default/my-test"), + resource.TestCheckResourceAttr("bluechip_image.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("bluechip_image.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("bluechip_image.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_image" "current" { + metadata { + name = "my-test" + namespace = "default" + } + spec { + app = "my-test" + timestamp = 1398329823 + commit_hash = "1234567890" + repository = "test" + tag = "test" + branch = "test" + } +} +` diff --git a/internal/services/images/type.go b/internal/services/images/type.go new file mode 100644 index 0000000..f0a3614 --- /dev/null +++ b/internal/services/images/type.go @@ -0,0 +1,79 @@ +package images + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "app": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "timestamp": { + Type: schema.TypeInt, + Required: !computed, + Computed: computed, + }, + "commit_hash": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "repository": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "tag": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "branch": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + } + + blockSchema := fwtype.SingleNestedBlock(innerSchema, computed, true) + fwtype.CleanForDataSource(blockSchema) + return blockSchema +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.ImageSpec) diag.Diagnostics { + attr := d.Get("spec.0").(map[string]any) + out.App = attr["app"].(string) + out.Timestamp = attr["timestamp"].(int) + out.CommitHash = attr["commit_hash"].(string) + out.Repository = attr["repository"].(string) + out.Tag = attr["tag"].(string) + out.Branch = attr["branch"].(string) + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.ImageSpec) diag.Diagnostics { + attr := map[string]any{ + "app": in.App, + "timestamp": in.Timestamp, + "commit_hash": in.CommitHash, + "repository": in.Repository, + "tag": in.Tag, + "branch": in.Branch, + } + + if err := d.Set("spec", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/internal/services/namespaces/data_source.go b/internal/services/namespaces/data_source.go new file mode 100644 index 0000000..da68beb --- /dev/null +++ b/internal/services/namespaces/data_source.go @@ -0,0 +1,22 @@ +package namespaces + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformDataSource[bluechip_models.Namespace, bluechip_models.EmptySpec]{ + Gvk: bluechip_models.NamespaceGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/namespaces/data_source_test.go b/internal/services/namespaces/data_source_test.go new file mode 100644 index 0000000..26beb41 --- /dev/null +++ b/internal/services/namespaces/data_source_test.go @@ -0,0 +1,36 @@ +package namespaces + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_namespace.current", "id", "default"), + resource.TestCheckResourceAttr("data.bluechip_namespace.current", "metadata.0.name", "default"), + resource.TestCheckResourceAttrSet("data.bluechip_namespace.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("data.bluechip_namespace.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_namespace" "current" { + metadata { + name = "default" + } +} +` diff --git a/internal/services/namespaces/register.go b/internal/services/namespaces/register.go new file mode 100644 index 0000000..95531e0 --- /dev/null +++ b/internal/services/namespaces/register.go @@ -0,0 +1,10 @@ +package namespaces + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_namespace", NewResource().Resource()) + provider.RegisterDataSource("bluechip_namespace", NewDataSource().Resource()) +} diff --git a/internal/services/namespaces/resource.go b/internal/services/namespaces/resource.go new file mode 100644 index 0000000..b7f10e2 --- /dev/null +++ b/internal/services/namespaces/resource.go @@ -0,0 +1,28 @@ +package namespaces + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformResource[bluechip_models.Namespace, bluechip_models.EmptySpec]{ + Gvk: bluechip_models.NamespaceGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.Namespace { + return bluechip_models.Namespace{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + } + }, + } +} diff --git a/internal/services/namespaces/resource_test.go b/internal/services/namespaces/resource_test.go new file mode 100644 index 0000000..91aded0 --- /dev/null +++ b/internal/services/namespaces/resource_test.go @@ -0,0 +1,35 @@ +package namespaces + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_namespace.current", "id", "my-test"), + resource.TestCheckResourceAttr("bluechip_namespace.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrWith("bluechip_namespace.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_namespace" "current" { + metadata { + name = "my-test" + } +} +` diff --git a/internal/services/namespaces/type.go b/internal/services/namespaces/type.go new file mode 100644 index 0000000..81810cf --- /dev/null +++ b/internal/services/namespaces/type.go @@ -0,0 +1,24 @@ +package namespaces + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + return nil +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.EmptySpec) diag.Diagnostics { + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.EmptySpec) diag.Diagnostics { + return nil +} diff --git a/internal/services/oidcauths/data_source.go b/internal/services/oidcauths/data_source.go new file mode 100644 index 0000000..77952b4 --- /dev/null +++ b/internal/services/oidcauths/data_source.go @@ -0,0 +1,23 @@ +package oidcauths + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformDataSource[bluechip_models.OidcAuth, bluechip_models.OidcAuthSpec]{ + Gvk: bluechip_models.OidcAuthGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/oidcauths/data_source_test.go b/internal/services/oidcauths/data_source_test.go new file mode 100644 index 0000000..ea5f635 --- /dev/null +++ b/internal/services/oidcauths/data_source_test.go @@ -0,0 +1,37 @@ +package oidcauths + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig, TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_oidcauth.current", "id", "my-test"), + resource.TestCheckResourceAttr("data.bluechip_oidcauth.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("data.bluechip_oidcauth.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("data.bluechip_oidcauth.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_oidcauth" "current" { + metadata { + name = "my-test" + } + depends_on = [bluechip_oidcauth.current] +} +` diff --git a/internal/services/oidcauths/register.go b/internal/services/oidcauths/register.go new file mode 100644 index 0000000..c914cc0 --- /dev/null +++ b/internal/services/oidcauths/register.go @@ -0,0 +1,10 @@ +package oidcauths + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_oidcauth", NewResource().Resource()) + provider.RegisterDataSource("bluechip_oidcauth", NewDataSource().Resource()) +} diff --git a/internal/services/oidcauths/resource.go b/internal/services/oidcauths/resource.go new file mode 100644 index 0000000..3a49f96 --- /dev/null +++ b/internal/services/oidcauths/resource.go @@ -0,0 +1,30 @@ +package oidcauths + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformResource[bluechip_models.OidcAuth, bluechip_models.OidcAuthSpec]{ + Gvk: bluechip_models.OidcAuthGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.OidcAuth { + return bluechip_models.OidcAuth{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.OidcAuthSpec]{}, + } + }, + } +} diff --git a/internal/services/oidcauths/resource_test.go b/internal/services/oidcauths/resource_test.go new file mode 100644 index 0000000..2f0545a --- /dev/null +++ b/internal/services/oidcauths/resource_test.go @@ -0,0 +1,45 @@ +package oidcauths + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_oidcauth.current", "id", "my-test"), + resource.TestCheckResourceAttr("bluechip_oidcauth.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("bluechip_oidcauth.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("bluechip_oidcauth.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_oidcauth" "current" { + metadata { + name = "my-test" + } + spec { + username_claim= "sub" + username_prefix= "string" + issuer = "https://accounts.google.com/" + client_id = "string" + required_claims = ["string"] + groups_claim = "string" + groups_prefix = "string" + } +} +` diff --git a/internal/services/oidcauths/type.go b/internal/services/oidcauths/type.go new file mode 100644 index 0000000..538b4f9 --- /dev/null +++ b/internal/services/oidcauths/type.go @@ -0,0 +1,125 @@ +package oidcauths + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "username_claim": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "username_prefix": { + Type: schema.TypeString, + Optional: !computed, + Computed: computed, + }, + "issuer": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "client_id": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "required_claims": { + Type: schema.TypeSet, + Optional: !computed, + Computed: computed, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "groups_claim": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "groups_prefix": { + Type: schema.TypeString, + Optional: !computed, + Computed: computed, + }, + "attribute_mapping": { + Type: schema.TypeList, + Optional: !computed, + Computed: computed, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "from": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "to": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + }, + }, + }, + } + + blockSchema := fwtype.SingleNestedBlock(innerSchema, computed, true) + fwtype.CleanForDataSource(blockSchema) + return blockSchema +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.OidcAuthSpec) diag.Diagnostics { + attr := d.Get("spec.0").(map[string]any) + out.UsernameClaim = attr["username_claim"].(string) + if attr["username_prefix"] != nil { + out.UsernamePrefix = fwtype.String(attr["username_prefix"].(string)) + } + out.Issuer = attr["issuer"].(string) + out.ClientId = attr["client_id"].(string) + if attr["required_claims"] != nil { + out.RequiredClaims = fwflex.ExpandStringSet(attr["required_claims"].(*schema.Set)) + } + out.GroupsClaim = attr["groups_claim"].(string) + if attr["groups_prefix"] != nil { + out.GroupsPrefix = fwtype.String(attr["groups_prefix"].(string)) + } + if attr["attribute_mapping"] != nil { + rawAttributeMappings := fwflex.ExpandMapList(attr["attribute_mapping"].([]any)) + for _, rawAttributeMapping := range rawAttributeMappings { + out.AttributeMapping = append(out.AttributeMapping, bluechip_models.AttributeMapping{ + From: rawAttributeMapping["from"].(string), + To: rawAttributeMapping["to"].(string), + }) + } + } + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.OidcAuthSpec) diag.Diagnostics { + attr := map[string]any{ + "username_claim": in.UsernameClaim, + "username_prefix": in.UsernamePrefix, + "issuer": in.Issuer, + "client_id": in.ClientId, + "required_claims": in.RequiredClaims, + "groups_claim": in.GroupsClaim, + "groups_prefix": in.GroupsPrefix, + "attribute_mapping": in.AttributeMapping, + } + + if err := d.Set("spec", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/internal/services/rolebindings/data_source.go b/internal/services/rolebindings/data_source.go new file mode 100644 index 0000000..2157a03 --- /dev/null +++ b/internal/services/rolebindings/data_source.go @@ -0,0 +1,23 @@ +package rolebindings + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformDataSource[bluechip_models.RoleBinding, bluechip_models.RoleBindingSpec]{ + Gvk: bluechip_models.RoleBindingGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/rolebindings/data_source_test.go b/internal/services/rolebindings/data_source_test.go new file mode 100644 index 0000000..76f7729 --- /dev/null +++ b/internal/services/rolebindings/data_source_test.go @@ -0,0 +1,38 @@ +package rolebindings + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig, TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_rolebinding.current", "id", "default/my-test"), + resource.TestCheckResourceAttr("data.bluechip_rolebinding.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("data.bluechip_rolebinding.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("data.bluechip_rolebinding.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_rolebinding" "current" { + metadata { + name = "my-test" + namespace = "default" + } + depends_on = [bluechip_rolebinding.current] +} +` diff --git a/internal/services/rolebindings/register.go b/internal/services/rolebindings/register.go new file mode 100644 index 0000000..37103bd --- /dev/null +++ b/internal/services/rolebindings/register.go @@ -0,0 +1,10 @@ +package rolebindings + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_rolebinding", NewResource().Resource()) + provider.RegisterDataSource("bluechip_rolebinding", NewDataSource().Resource()) +} diff --git a/internal/services/rolebindings/resource.go b/internal/services/rolebindings/resource.go new file mode 100644 index 0000000..9e60a0d --- /dev/null +++ b/internal/services/rolebindings/resource.go @@ -0,0 +1,30 @@ +package rolebindings + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.NamespacedTerraformResource[bluechip_models.RoleBinding, bluechip_models.RoleBindingSpec]{ + Gvk: bluechip_models.RoleBindingGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(true, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.RoleBinding { + return bluechip_models.RoleBinding{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.RoleBindingSpec]{}, + } + }, + } +} diff --git a/internal/services/rolebindings/resource_test.go b/internal/services/rolebindings/resource_test.go new file mode 100644 index 0000000..552ab09 --- /dev/null +++ b/internal/services/rolebindings/resource_test.go @@ -0,0 +1,44 @@ +package rolebindings + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_rolebinding.current", "id", "default/my-test"), + resource.TestCheckResourceAttr("bluechip_rolebinding.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("bluechip_rolebinding.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("bluechip_rolebinding.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_rolebinding" "current" { + metadata { + name = "my-test" + namespace = "default" + } + spec { + subject_ref { + kind = "User" + name = "my-test" + } + policy_ref = "admin" + } +} +` diff --git a/internal/services/rolebindings/type.go b/internal/services/rolebindings/type.go new file mode 100644 index 0000000..17a8644 --- /dev/null +++ b/internal/services/rolebindings/type.go @@ -0,0 +1,25 @@ +package rolebindings + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + return fwtype.RoleBindingTyp.Schema(computed) +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.RoleBindingSpec) diag.Diagnostics { + return fwtype.RoleBindingTyp.Expand(ctx, d, out) +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.RoleBindingSpec) diag.Diagnostics { + return fwtype.RoleBindingTyp.Flatten(ctx, d, in) +} diff --git a/internal/services/users/data_source.go b/internal/services/users/data_source.go new file mode 100644 index 0000000..5501d8a --- /dev/null +++ b/internal/services/users/data_source.go @@ -0,0 +1,23 @@ +package users + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformDataSource[bluechip_models.User, bluechip_models.UserSpec]{ + Gvk: bluechip_models.UsersGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/users/data_source_test.go b/internal/services/users/data_source_test.go new file mode 100644 index 0000000..50c92e7 --- /dev/null +++ b/internal/services/users/data_source_test.go @@ -0,0 +1,37 @@ +package users + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig, TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_user.current", "id", "my-test"), + resource.TestCheckResourceAttr("data.bluechip_user.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("data.bluechip_user.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("data.bluechip_user.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_user" "current" { + metadata { + name = "my-test" + } + depends_on = [bluechip_user.current] +} +` diff --git a/internal/services/users/register.go b/internal/services/users/register.go new file mode 100644 index 0000000..a3b1571 --- /dev/null +++ b/internal/services/users/register.go @@ -0,0 +1,10 @@ +package users + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_user", NewResource().Resource()) + provider.RegisterDataSource("bluechip_user", NewDataSource().Resource()) +} diff --git a/internal/services/users/resource.go b/internal/services/users/resource.go new file mode 100644 index 0000000..8a284ae --- /dev/null +++ b/internal/services/users/resource.go @@ -0,0 +1,30 @@ +package users + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformResource[bluechip_models.User, bluechip_models.UserSpec]{ + Gvk: bluechip_models.UsersGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.User { + return bluechip_models.User{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.UserSpec]{}, + } + }, + } +} diff --git a/internal/services/users/resource_test.go b/internal/services/users/resource_test.go new file mode 100644 index 0000000..faa22d4 --- /dev/null +++ b/internal/services/users/resource_test.go @@ -0,0 +1,40 @@ +package users + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_user.current", "id", "my-test"), + resource.TestCheckResourceAttr("bluechip_user.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("bluechip_user.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("bluechip_user.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_user" "current" { + metadata { + name = "my-test" + } + spec { + password = "tetete" + groups = ["asdf"] + } +} +` diff --git a/internal/services/users/type.go b/internal/services/users/type.go new file mode 100644 index 0000000..9755f3c --- /dev/null +++ b/internal/services/users/type.go @@ -0,0 +1,61 @@ +package users + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "password": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "groups": { + Type: schema.TypeSet, + Required: !computed, + Computed: computed, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "attributes": { + Type: schema.TypeMap, + Optional: true, + Computed: computed, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + } + + blockSchema := fwtype.SingleNestedBlock(innerSchema, computed, true) + fwtype.CleanForDataSource(blockSchema) + return blockSchema +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.UserSpec) diag.Diagnostics { + attr := d.Get("spec.0").(map[string]any) + out.Password = attr["password"].(string) + out.Groups = fwflex.ExpandStringSet(attr["groups"].(*schema.Set)) + out.Attributes = fwflex.ExpandMap(attr["attributes"].(map[string]any)) + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.UserSpec) diag.Diagnostics { + attr := map[string]any{ + "password": in.Password, + "groups": in.Groups, + "attributes": in.Attributes, + } + + if err := d.Set("spec", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/internal/services/vendors/data_source.go b/internal/services/vendors/data_source.go new file mode 100644 index 0000000..cfa1a08 --- /dev/null +++ b/internal/services/vendors/data_source.go @@ -0,0 +1,23 @@ +package vendors + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewDataSource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformDataSource[bluechip_models.Vendor, bluechip_models.VendorSpec]{ + Gvk: bluechip_models.VendorGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, true), + "spec": specTyp.Schema(true), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + } +} diff --git a/internal/services/vendors/data_source_test.go b/internal/services/vendors/data_source_test.go new file mode 100644 index 0000000..ed6ea48 --- /dev/null +++ b/internal/services/vendors/data_source_test.go @@ -0,0 +1,37 @@ +package vendors + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig, TestAccDataSourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.bluechip_vendor.current", "id", "my-test"), + resource.TestCheckResourceAttr("data.bluechip_vendor.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("data.bluechip_vendor.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("data.bluechip_vendor.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccDataSourceConfig = ` +data "bluechip_vendor" "current" { + metadata { + name = "my-test" + } + depends_on = [bluechip_vendor.current] +} +` diff --git a/internal/services/vendors/register.go b/internal/services/vendors/register.go new file mode 100644 index 0000000..3b4b4be --- /dev/null +++ b/internal/services/vendors/register.go @@ -0,0 +1,10 @@ +package vendors + +import "github.com/pubg/terraform-provider-bluechip/internal/provider" + +var specTyp = &SpecType{} + +func init() { + provider.RegisterResource("bluechip_vendor", NewResource().Resource()) + provider.RegisterDataSource("bluechip_vendor", NewDataSource().Resource()) +} diff --git a/internal/services/vendors/resource.go b/internal/services/vendors/resource.go new file mode 100644 index 0000000..6d0ed2d --- /dev/null +++ b/internal/services/vendors/resource.go @@ -0,0 +1,30 @@ +package vendors + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwservices" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +func NewResource() fwservices.ResourceFactory { + return &fwservices.ClusterTerraformResource[bluechip_models.Vendor, bluechip_models.VendorSpec]{ + Gvk: bluechip_models.VendorGvk, + Schema: map[string]*schema.Schema{ + "metadata": fwtype.MetadataTyp.Schema(false, false), + "spec": specTyp.Schema(false), + }, + Timeout: 30 * time.Second, + SpecExpander: specTyp.Expand, + SpecFlattener: specTyp.Flatten, + Constructor: func() bluechip_models.Vendor { + return bluechip_models.Vendor{ + TypeMeta: &bluechip_models.TypeMeta{}, + MetadataContainer: &bluechip_models.MetadataContainer{}, + SpecContainer: &bluechip_models.SpecContainer[bluechip_models.VendorSpec]{}, + } + }, + } +} diff --git a/internal/services/vendors/resource_test.go b/internal/services/vendors/resource_test.go new file mode 100644 index 0000000..f003c6c --- /dev/null +++ b/internal/services/vendors/resource_test.go @@ -0,0 +1,42 @@ +package vendors + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/pubg/terraform-provider-bluechip/internal/testacc" +) + +func TestAccResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testacc.TestAccPreCheck(t) }, + ProtoV5ProviderFactories: testacc.TestAccProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testacc.CombinedConfig(TestAccResourceConfig), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("bluechip_vendor.current", "id", "my-test"), + resource.TestCheckResourceAttr("bluechip_vendor.current", "metadata.0.name", "my-test"), + resource.TestCheckResourceAttrSet("bluechip_vendor.current", "metadata.0.creation_timestamp"), + resource.TestCheckResourceAttrWith("bluechip_vendor.current", "metadata.0.name", func(value string) error { + return nil + }), + ), + }, + }, + }) +} + +const TestAccResourceConfig = ` +resource "bluechip_vendor" "current" { + metadata { + name = "my-test" + } + spec { + display_name = "asdf" + code_name = "AWS" + short_name = "aws" + regions = ["asdf"] + } +} +` diff --git a/internal/services/vendors/type.go b/internal/services/vendors/type.go new file mode 100644 index 0000000..d4f6136 --- /dev/null +++ b/internal/services/vendors/type.go @@ -0,0 +1,67 @@ +package vendors + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type SpecType struct { +} + +func (SpecType) Schema(computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "display_name": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "code_name": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "short_name": { + Type: schema.TypeString, + Required: !computed, + Computed: computed, + }, + "regions": { + Type: schema.TypeSet, + Required: !computed, + Computed: computed, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + } + + blockSchema := fwtype.SingleNestedBlock(innerSchema, computed, true) + fwtype.CleanForDataSource(blockSchema) + return blockSchema +} + +func (SpecType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.VendorSpec) diag.Diagnostics { + attr := d.Get("spec.0").(map[string]any) + out.DisplayName = attr["display_name"].(string) + out.CodeName = attr["code_name"].(string) + out.ShortName = attr["short_name"].(string) + out.Regions = fwflex.ExpandStringSet(attr["regions"].(*schema.Set)) + return nil +} + +func (SpecType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.VendorSpec) diag.Diagnostics { + attr := map[string]any{ + "display_name": in.DisplayName, + "code_name": in.CodeName, + "short_name": in.ShortName, + "regions": in.Regions, + } + + if err := d.Set("spec", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/internal/testacc/provider.go b/internal/testacc/provider.go new file mode 100644 index 0000000..7b5df27 --- /dev/null +++ b/internal/testacc/provider.go @@ -0,0 +1,68 @@ +package testacc + +import ( + "os" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/joho/godotenv" + "github.com/pubg/terraform-provider-bluechip/internal/provider" +) + +// testAccProtoV6ProviderFactories are used to instantiate a provider during +// acceptance testing. The factory function will be invoked for every Terraform +// CLI command executed to create a provider server to which the CLI can +// reattach. +var TestAccProtoV5ProviderFactories = map[string]func() (tfprotov5.ProviderServer, error){ + "bluechip": func() (tfprotov5.ProviderServer, error) { + return schema.NewGRPCProviderServer(provider.Provider()), nil + }, +} + +func TestAccPreCheck(t *testing.T) { + // You can add code here to run prior to any test case execution, for example assertions + // about the appropriate environment variables being set are common to see in a pre-check + // function. +} + +func init() { + var errs []error + errs = append(errs, + godotenv.Load(".env"), + godotenv.Load("../.env"), + godotenv.Load("../../.env"), + godotenv.Load("../../../.env"), + ) + if len(errs) != 4 { + panic(errs) + } +} + +func ProviderTerraformConfig() string { + config := ` +provider "bluechip" { + address = "$address" + basic_auth { + username = "$username" + password = "$password" + } +} +` + variables := map[string]string{ + "$address": os.Getenv("BLUECHIP_ADDRESS"), + "$username": os.Getenv("BLUECHIP_USERNAME"), + "$password": os.Getenv("BLUECHIP_PASSWORD"), + } + + for key, val := range variables { + config = strings.ReplaceAll(config, key, val) + } + + return config +} + +func CombinedConfig(config ...string) string { + return ProviderTerraformConfig() + "\n" + strings.Join(config, "\n") +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..ffb0cbb --- /dev/null +++ b/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "flag" + + "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" + "github.com/pubg/terraform-provider-bluechip/internal/provider" +) + +import ( + _ "github.com/pubg/terraform-provider-bluechip/internal/services/cidrs" + _ "github.com/pubg/terraform-provider-bluechip/internal/services/clusterrolebindings" + _ "github.com/pubg/terraform-provider-bluechip/internal/services/clusters" + _ "github.com/pubg/terraform-provider-bluechip/internal/services/images" + _ "github.com/pubg/terraform-provider-bluechip/internal/services/namespaces" + _ "github.com/pubg/terraform-provider-bluechip/internal/services/oidcauths" + _ "github.com/pubg/terraform-provider-bluechip/internal/services/rolebindings" + _ "github.com/pubg/terraform-provider-bluechip/internal/services/users" + _ "github.com/pubg/terraform-provider-bluechip/internal/services/vendors" +) + +// Run the docs generation tool, check its repository for more information on how it works and how docs +// can be customized. +//go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs + +var ( + _ string = "dev" + _ string = "local" +) + +func main() { + var debugMode bool + + flag.BoolVar(&debugMode, "debug", false, "set to true to run the provider with support for debuggers like delve") + flag.Parse() + + opts := &plugin.ServeOpts{ + Debug: debugMode, + ProviderAddr: "registry.terraform.io/pubg/bluechip", + ProviderFunc: provider.Provider, + } + + plugin.Serve(opts) +} diff --git a/pkg/bluechip_authenticator/auth.go b/pkg/bluechip_authenticator/auth.go new file mode 100644 index 0000000..ec62784 --- /dev/null +++ b/pkg/bluechip_authenticator/auth.go @@ -0,0 +1,130 @@ +package bluechip_authenticator + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + "net/http" + "net/url" + + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +type Client struct { + client *http.Client + version string + address string +} + +func NewClient(client *http.Client, version string, address string) *Client { + return &Client{client: client, version: version, address: address} +} + +func (c *Client) doLogin(req *http.Request) (*LoginResponse, *http.Response, error) { + req.Header.Set("User-Agent", "bluechip-go-http/"+c.version) + resp, err := c.client.Do(req) + if err != nil { + return nil, nil, err + } + if resp.StatusCode/100 != 2 { + return nil, resp, fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } + + var loginResponse LoginResponse + if err := json.NewDecoder(resp.Body).Decode(&loginResponse); err != nil { + return nil, resp, err + } + + return &loginResponse, resp, nil +} + +func (c *Client) LoginWithBasic(ctx context.Context, username string, password string) (string, error) { + u, err := url.JoinPath(c.address, "/auth/users/login") + if err != nil { + return "", err + } + + req, _ := http.NewRequestWithContext(ctx, "POST", u, nil) + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password))) + lr, _, err := c.doLogin(req) + if err != nil { + return "", err + } + + return lr.Token, nil +} + +func (c *Client) LoginWithAws(ctx context.Context, clusterName string, accessKey string, secretAccessKey string, sessionToken string, region string, profile string) (string, error) { + var configLoadOoptions []func(*config.LoadOptions) error + if accessKey != "" && secretAccessKey != "" { + configLoadOoptions = append(configLoadOoptions, config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretAccessKey, sessionToken))) + tflog.Debug(ctx, "Using credentials from provider parameters") + } + if region != "" { + configLoadOoptions = append(configLoadOoptions, config.WithRegion(region)) + tflog.Debug(ctx, "Using region from provider parameters") + } + if profile != "" { + configLoadOoptions = append(configLoadOoptions, config.WithSharedConfigProfile(profile)) + tflog.Debug(ctx, "Using profile from provider parameters") + } + + cfg, err := config.LoadDefaultConfig(ctx, configLoadOoptions...) + if err != nil { + return "", err + } + + tflog.Debug(ctx, fmt.Sprintf("Loaded aws config: %v", cfg)) + + stsclient := sts.NewFromConfig(cfg) + presignclient := sts.NewPresignClient(stsclient) + + stsRetriver := NewSTSTokenRetriver(presignclient) + eksToken, err := stsRetriver.GetToken(ctx, clusterName) + if err != nil { + return "", err + } + + u, err := url.JoinPath(c.address, "/auth/aws/login") + if err != nil { + return "", err + } + + req, _ := http.NewRequestWithContext(ctx, "POST", u, nil) + q := req.URL.Query() + q.Add("token", eksToken) + req.URL.RawQuery = q.Encode() + + lr, _, err := c.doLogin(req) + if err != nil { + return "", err + } + + return lr.Token, nil +} + +func (c *Client) LoginWithOidc(ctx context.Context, token string, authMethod string) (string, error) { + u, err := url.JoinPath(c.address, fmt.Sprintf("/auth/oidc/%s/login", authMethod)) + if err != nil { + return "", err + } + + req, _ := http.NewRequestWithContext(ctx, "POST", u, nil) + req.Header.Set("Authorization", "Bearer "+token) + lr, _, err := c.doLogin(req) + if err != nil { + return "", err + } + + return lr.Token, nil +} + +type LoginResponse struct { + Token string `json:"token"` + ExpiresAt string `json:"expiresAt"` + Message string `json:"message,omitempty"` +} diff --git a/pkg/bluechip_authenticator/aws.go b/pkg/bluechip_authenticator/aws.go new file mode 100644 index 0000000..eb7e029 --- /dev/null +++ b/pkg/bluechip_authenticator/aws.go @@ -0,0 +1,65 @@ +package bluechip_authenticator + +// Copy code from https://github.com/aws/aws-sdk-go-v2/issues/1922#issuecomment-1432648495 + +import ( + "context" + "encoding/base64" + "fmt" + "net/http" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" + "github.com/aws/aws-sdk-go-v2/service/sts" +) + +const ( + k8sHeader = "x-k8s-aws-id" + tokenPrefix = "k8s-aws-v1." +) + +type STSTokenRetriever struct { + PresignClient *sts.PresignClient +} + +func NewSTSTokenRetriver(client *sts.PresignClient) STSTokenRetriever { + return STSTokenRetriever{PresignClient: client} +} + +func (s *STSTokenRetriever) GetToken(ctx context.Context, clusterName string) (string, error) { + out, err := s.PresignClient.PresignGetCallerIdentity(ctx, &sts.GetCallerIdentityInput{}, func(opt *sts.PresignOptions) { + opt.Presigner = newCustomHTTPPresignerV4(opt.Presigner, map[string]string{ + k8sHeader: clusterName, + "X-Amz-Expires": "60", + }) + }) + if err != nil { + return "", err + } + token := fmt.Sprintf("%s%s", tokenPrefix, base64.RawURLEncoding.EncodeToString([]byte(out.URL))) //RawURLEncoding + return token, nil +} + +type customHTTPPresignerV4 struct { + client sts.HTTPPresignerV4 + headers map[string]string +} + +func newCustomHTTPPresignerV4(client sts.HTTPPresignerV4, headers map[string]string) sts.HTTPPresignerV4 { + return &customHTTPPresignerV4{ + client: client, + headers: headers, + } +} + +func (p *customHTTPPresignerV4) PresignHTTP( + ctx context.Context, credentials aws.Credentials, r *http.Request, + payloadHash string, service string, region string, signingTime time.Time, + optFns ...func(*v4.SignerOptions), +) (url string, signedHeader http.Header, err error) { + for key, val := range p.headers { + r.Header.Add(key, val) + } + return p.client.PresignHTTP(ctx, credentials, r, payloadHash, service, region, signingTime, optFns...) +} diff --git a/pkg/bluechip_client/bluechip_models/clusters.go b/pkg/bluechip_client/bluechip_models/clusters.go new file mode 100644 index 0000000..75158c6 --- /dev/null +++ b/pkg/bluechip_client/bluechip_models/clusters.go @@ -0,0 +1,28 @@ +package bluechip_models + +type WhoamiResponse struct { + BaseSpec `tfsdk:"-"` + + Name string `json:"name"` + Groups []string `json:"groups"` + Attributes map[string]any `json:"attributes"` +} + +type ApiResourcesResponse struct { + BaseSpec `tfsdk:"-"` + + ApiVersion string `json:"apiVersion"` + Kind string `json:"kind"` + Metadata any `json:"metadata"` + Items []ApiResourceSpec `json:"items"` +} + +type ApiResourceSpec struct { + BaseSpec + + Group string `json:"group"` + Version string `json:"version"` + Kind string `json:"kind"` + KindPlural string `json:"kindPlural"` + Namespaced bool `json:"namespaced"` +} diff --git a/pkg/bluechip_client/bluechip_models/container.go b/pkg/bluechip_client/bluechip_models/container.go new file mode 100644 index 0000000..1efd161 --- /dev/null +++ b/pkg/bluechip_client/bluechip_models/container.go @@ -0,0 +1,46 @@ +package bluechip_models + +type TypeMeta struct { + ApiVersion string `json:"apiVersion"` + Kind string `json:"kind"` +} + +func (m *TypeMeta) GetApiVersion() string { + return m.ApiVersion +} + +func (m *TypeMeta) SetApiVersion(apiVersion string) { + m.ApiVersion = apiVersion +} + +func (m *TypeMeta) GetKind() string { + return m.Kind +} + +func (m *TypeMeta) SetKind(kind string) { + m.Kind = kind +} + +type MetadataContainer struct { + Container Metadata `json:"metadata"` +} + +func (m *MetadataContainer) GetMetadata() Metadata { + return m.Container +} + +func (m *MetadataContainer) SetMetadata(metadata Metadata) { + m.Container = metadata +} + +type SpecContainer[C BaseSpec] struct { + Container C `json:"spec"` +} + +func (s *SpecContainer[C]) GetSpec() C { + return s.Container +} + +func (s *SpecContainer[C]) SetSpec(spec C) { + s.Container = spec +} diff --git a/pkg/bluechip_client/bluechip_models/gvks.go b/pkg/bluechip_client/bluechip_models/gvks.go new file mode 100644 index 0000000..a9d06fc --- /dev/null +++ b/pkg/bluechip_client/bluechip_models/gvks.go @@ -0,0 +1,94 @@ +package bluechip_models + +import ( + "fmt" + "strings" +) + +type GroupVersionKind struct { + Group string `json:"group"` + Version string `json:"version"` + Kind string `json:"kind"` + KindPlural string `json:"kindPlural"` +} + +func (g GroupVersionKind) ToApiPath() string { + return fmt.Sprintf("/apis/%s/%s/%s", g.Group, g.Version, strings.ToLower(g.KindPlural)) +} + +func (g GroupVersionKind) ToTypeMeta() TypeMeta { + meta := TypeMeta{} + meta.SetApiVersion(fmt.Sprintf("%s/%s", g.Group, g.Version)) + meta.SetKind(g.Kind) + return meta +} + +var NamespaceGvk = GroupVersionKind{ + Group: "core", + Version: "v1", + Kind: "Namespace", + KindPlural: "Namespaces", +} + +var ClusterRoleBindingGvk = GroupVersionKind{ + Group: "rbac.bluechip.pubg.io", + Version: "v1", + Kind: "ClusterRoleBinding", + KindPlural: "ClusterRoleBindings", +} + +var RoleBindingGvk = GroupVersionKind{ + Group: "rbac.bluechip.pubg.io", + Version: "v1", + Kind: "RoleBinding", + KindPlural: "RoleBindings", +} + +var VendorGvk = GroupVersionKind{ + Group: "bluechip.pubg.io", + Version: "v1", + Kind: "Vendor", + KindPlural: "Vendors", +} + +var ClusterGvk = GroupVersionKind{ + Group: "bluechip.pubg.io", + Version: "v1", + Kind: "Cluster", + KindPlural: "Clusters", +} + +var AccountGvk = GroupVersionKind{ + Group: "bluechip.pubg.io", + Version: "v1", + Kind: "Account", + KindPlural: "Accounts", +} + +var CidrGvk = GroupVersionKind{ + Group: "bluechip.pubg.io", + Version: "v1", + Kind: "Cidr", + KindPlural: "Cidrs", +} + +var ImageGvk = GroupVersionKind{ + Group: "bluechip.pubg.io", + Version: "v1", + Kind: "Image", + KindPlural: "Images", +} + +var OidcAuthGvk = GroupVersionKind{ + Group: "auth.bluechip.pubg.io", + Version: "v1", + Kind: "OidcAuth", + KindPlural: "OidcAuths", +} + +var UsersGvk = GroupVersionKind{ + Group: "auth.bluechip.pubg.io", + Version: "v1", + Kind: "User", + KindPlural: "Users", +} diff --git a/pkg/bluechip_client/bluechip_models/metadata.go b/pkg/bluechip_client/bluechip_models/metadata.go new file mode 100644 index 0000000..d0928a1 --- /dev/null +++ b/pkg/bluechip_client/bluechip_models/metadata.go @@ -0,0 +1,12 @@ +package bluechip_models + +type Metadata struct { + BaseMetadata `json:"-"` + + Name string `json:"name"` + CreationTimestamp string `json:"creationTimestamp,omitempty"` + UpdateTimestamp string `json:"UpdateTimestamp,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + Namespace string `json:"namespace,omitempty"` +} diff --git a/pkg/bluechip_client/bluechip_models/models.go b/pkg/bluechip_client/bluechip_models/models.go new file mode 100644 index 0000000..196e5b8 --- /dev/null +++ b/pkg/bluechip_client/bluechip_models/models.go @@ -0,0 +1,43 @@ +package bluechip_models + +type BaseResponse interface { + _IsBluechipResponse() +} + +type BaseSpec interface { + _IsBluechipSpec() +} + +type BaseMetadata interface { + _IsBluechipMetadata() +} + +type ClusterApiResource[Spec BaseSpec] interface { + BaseResponse + + GetApiVersion() string + SetApiVersion(apiVersion string) + GetKind() string + SetKind(kind string) + GetMetadata() Metadata + SetMetadata(m Metadata) + GetSpec() Spec + SetSpec(s Spec) +} + +type NamespacedApiResource[Spec BaseSpec] interface { + BaseResponse + + GetApiVersion() string + SetApiVersion(apiVersion string) + GetKind() string + SetKind(kind string) + GetMetadata() Metadata + SetMetadata(m Metadata) + GetSpec() Spec + SetSpec(s Spec) +} + +type EmptySpec struct { + BaseSpec +} diff --git a/pkg/bluechip_client/bluechip_models/resources.go b/pkg/bluechip_client/bluechip_models/resources.go new file mode 100644 index 0000000..ac495de --- /dev/null +++ b/pkg/bluechip_client/bluechip_models/resources.go @@ -0,0 +1,234 @@ +package bluechip_models + +var _ ClusterApiResource[EmptySpec] = &Namespace{} + +type Namespace struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` +} + +func (n Namespace) GetSpec() EmptySpec { + return EmptySpec{} +} + +func (n Namespace) SetSpec(_ EmptySpec) { +} + +var _ ClusterApiResource[VendorSpec] = &Vendor{} + +type Vendor struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[VendorSpec] `json:",inline"` +} + +type VendorSpec struct { + BaseSpec `json:"-"` + + DisplayName string `json:"displayName"` + CodeName string `json:"codeName"` + ShortName string `json:"shortName"` + Regions []string `json:"regions"` +} + +var _ NamespacedApiResource[ClusterSpec] = &Cluster{} + +type Cluster struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[ClusterSpec] `json:",inline"` +} + +type ClusterSpec struct { + BaseSpec `json:"-"` + + Project string `json:"project"` + Environment string `json:"environment"` + OrganizationUnit string `json:"organizationUnit"` + Platform string `json:"platform"` + Pubg *ClusterSpecPubg `json:"pubg"` + Vendor ClusterSpecVendor `json:"vendor"` + Kubernetes ClusterSpecKubernetes `json:"kubernetes"` +} + +type ClusterSpecPubg struct { + Infra string `json:"infra"` + Site string `json:"site"` +} + +type ClusterSpecVendor struct { + Name string `json:"name"` + AccountId string `json:"accountId"` + Engine string `json:"engine"` + Region string `json:"region"` +} + +type ClusterSpecKubernetes struct { + Endpoint string `json:"endpoint"` + CaCert string `json:"caCert"` + SaIssuer string `json:"saIssuer"` + Version string `json:"version"` +} + +var _ NamespacedApiResource[CidrSpec] = &Cidr{} + +type Cidr struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[CidrSpec] `json:",inline"` +} + +type CidrSpec struct { + BaseSpec `json:"-"` + + Ipv4Cidrs []string `json:"ipv4Cidrs"` + Ipv6Cidrs []string `json:"ipv6Cidrs"` +} + +var _ NamespacedApiResource[AccountSpec] = &Account{} + +type Account struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[AccountSpec] `json:",inline"` +} + +type AccountSpec struct { + BaseSpec `json:"-"` + + AccountId string `json:"accountId"` + DisplayName string `json:"displayName"` + Description string `json:"description"` + Alias string `json:"alias"` + Vendor string `json:"vendor"` + Regions []string `json:"regions"` +} + +var _ NamespacedApiResource[ImageSpec] = &Image{} + +type Image struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[ImageSpec] `json:",inline"` +} + +type ImageSpec struct { + BaseSpec `json:"-"` + + App string `json:"app"` + Timestamp int `json:"timestamp"` + CommitHash string `json:"commitHash"` + Repository string `json:"repository"` + Tag string `json:"tag"` + Branch string `json:"branch"` +} + +var _ ClusterApiResource[UserSpec] = &User{} + +type User struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[UserSpec] `json:",inline"` +} + +type UserSpec struct { + BaseSpec `json:"-"` + + Password string `json:"password"` + Groups []string `json:"groups"` + Attributes map[string]string `json:"attributes"` +} + +var _ ClusterApiResource[OidcAuthSpec] = &OidcAuth{} + +type OidcAuth struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[OidcAuthSpec] `json:",inline"` +} + +type OidcAuthSpec struct { + BaseSpec `json:"-"` + + UsernameClaim string `json:"usernameClaim"` + UsernamePrefix *string `json:"usernamePrefix,omitempty"` + Issuer string `json:"issuer"` + ClientId string `json:"clientId"` + RequiredClaims []string `json:"requiredClaims,omitempty"` + GroupsClaim string `json:"groupsClaim"` + GroupsPrefix *string `json:"groupsPrefix,omitempty"` + AttributeMapping []AttributeMapping `json:"attributeMapping,omitempty"` +} + +type AttributeMapping struct { + From string `json:"from"` + To string `json:"to"` +} + +var _ ClusterApiResource[ClusterRoleBindingSpec] = &ClusterRoleBinding{} + +type ClusterRoleBinding struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[ClusterRoleBindingSpec] `json:",inline"` +} + +type ClusterRoleBindingSpec struct { + BaseSpec `json:"-"` + + SubjectsRef SubjectRef `json:"subjectsRef"` + PolicyInline []PolicyStatement `json:"policyInline,omitempty"` + PolicyRef *string `json:"policyRef,omitempty"` +} + +var _ NamespacedApiResource[RoleBindingSpec] = &RoleBinding{} + +type RoleBinding struct { + BaseResponse `json:"-"` + + *TypeMeta `json:",inline"` + *MetadataContainer `json:",inline"` + *SpecContainer[RoleBindingSpec] `json:",inline"` +} + +type RoleBindingSpec struct { + BaseSpec `json:"-"` + + SubjectsRef SubjectRef `json:"subjectsRef"` + PolicyInline []PolicyStatement `json:"policyInline,omitempty"` + PolicyRef *string `json:"policyRef,omitempty"` +} + +type SubjectRef struct { + Kind string `json:"kind"` + Name string `json:"name"` +} + +type PolicyStatement struct { + Actions []string `json:"actions"` + Paths []string + Resources []PolicyResource `json:"resources"` +} + +type PolicyResource struct { + ApiGroup string `json:"apiGroup"` + Kind string `json:"kind"` +} diff --git a/pkg/bluechip_client/bluechip_models/resources_test.go b/pkg/bluechip_client/bluechip_models/resources_test.go new file mode 100644 index 0000000..27a79ce --- /dev/null +++ b/pkg/bluechip_client/bluechip_models/resources_test.go @@ -0,0 +1,73 @@ +package bluechip_models + +import ( + "encoding/json" + "testing" + + "github.com/yudai/gojsondiff" +) + +var jsonResource = ` +{ + "apiVersion": "core/v1", + "kind": "Namespace", + "metadata": { + "name": "kube-system", + "labels": { + "name": "kube-system" + }, + "annotations": { + "scheduler.alpha.kubernetes.io/critical-pod": "" + } + } +} +` +var expectedResource = Namespace{ + TypeMeta: &TypeMeta{ + ApiVersion: "core/v1", + Kind: "Namespace", + }, + MetadataContainer: &MetadataContainer{ + Container: Metadata{ + Name: "kube-system", + Labels: map[string]string{ + "name": "kube-system", + }, + Annotations: map[string]string{ + "scheduler.alpha.kubernetes.io/critical-pod": "", + }, + }, + }, +} +var differ = gojsondiff.New() + +func TestNamespaceMarshal(t *testing.T) { + buf, err := json.Marshal(expectedResource) + if err != nil { + t.Error(err) + return + } + + diff, err := differ.Compare([]byte(jsonResource), buf) + if err != nil { + t.Error(err) + return + } + + if diff.Modified() { + t.Errorf("Expected equals, but got some diffs %s", diff) + } +} + +func TestNamespaceUnmarshal(t *testing.T) { + var resource Namespace + if err := json.Unmarshal([]byte(jsonResource), &resource); err != nil { + t.Error(err) + return + } + + diff := differ.CompareArrays([]any{expectedResource}, []any{resource}) + if diff.Modified() { + t.Errorf("Expected equals, but got some diffs %s", diff) + } +} diff --git a/pkg/bluechip_client/client.go b/pkg/bluechip_client/client.go new file mode 100644 index 0000000..9037be2 --- /dev/null +++ b/pkg/bluechip_client/client.go @@ -0,0 +1,91 @@ +package bluechip_client + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" +) + +type Client struct { + client *http.Client + token string + version string + address string + + // 각 retry 사이의 대기 시간 + // 3초 권장 + retryWait time.Duration + // Do 함수의 timeout, retry count 대신 제한된 timeout 동안 무제한 retry한다 + // 30초 권장 + timeout time.Duration +} + +func NewClient(client *http.Client, token string, version string, address string, retryWait time.Duration, timeout time.Duration) *Client { + return &Client{client: client, token: token, version: version, address: address, retryWait: retryWait, timeout: timeout} +} + +func (c *Client) JoinUrl(urlPath ...string) string { + path, err := url.JoinPath(c.address, urlPath...) + if err != nil { + panic(err) + } + return path +} + +func (c *Client) Do(req *http.Request) (*http.Response, error) { + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", c.token)) + req.Header.Add("User-Agent", "bluechip-go-http/"+c.version) + + var resp *http.Response + var err error + err = retry.RetryContext(req.Context(), c.timeout, func() *retry.RetryError { + resp, err = c.client.Do(req) + if err != nil { + time.Sleep(c.retryWait) + return retry.RetryableError(err) + } + if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode/100 == 5 { + time.Sleep(c.retryWait) + return retry.NonRetryableError(fmt.Errorf("unexpected status code: %d, text: %s", resp.StatusCode, http.StatusText(resp.StatusCode))) + } + return nil + }) + if err != nil { + return nil, err + } + if resp == nil { + return nil, fmt.Errorf("response is nil") + } + + if resp.StatusCode/100 != 2 { + return resp, fmt.Errorf("unexpected status code: %d, text: %s", resp.StatusCode, http.StatusText(resp.StatusCode)) + } + + return resp, nil +} + +func (c *Client) DoWithType(req *http.Request, t any) (*http.Response, error) { + resp, err := c.Do(req) + if err != nil { + return nil, err + } + + if err := json.NewDecoder(resp.Body).Decode(&t); err != nil { + return resp, fmt.Errorf("failed to decode response: %w", err) + } + return resp, nil +} + +func readBodyForError(resp *http.Response) []byte { + if resp == nil { + return nil + } + defer resp.Body.Close() + buf, _ := io.ReadAll(resp.Body) + return buf +} diff --git a/pkg/bluechip_client/cluster_apis.go b/pkg/bluechip_client/cluster_apis.go new file mode 100644 index 0000000..45de77c --- /dev/null +++ b/pkg/bluechip_client/cluster_apis.go @@ -0,0 +1,36 @@ +package bluechip_client + +import ( + "context" + "net/http" + + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" +) + +func (c *Client) Whoami(ctx context.Context) (*bluechip_models.WhoamiResponse, error) { + req, err := http.NewRequestWithContext(ctx, "GET", c.JoinUrl("/auth/whoami"), nil) + if err != nil { + return nil, err + } + + var resp bluechip_models.WhoamiResponse + if _, err := c.DoWithType(req, &resp); err != nil { + return nil, err + } + + return &resp, nil +} + +func (c *Client) ApiResources(ctx context.Context) (*bluechip_models.ApiResourcesResponse, error) { + req, err := http.NewRequestWithContext(ctx, "GET", c.JoinUrl("/apis"), nil) + if err != nil { + return nil, err + } + + var resp bluechip_models.ApiResourcesResponse + if _, err := c.DoWithType(req, &resp); err != nil { + return nil, err + } + + return &resp, nil +} diff --git a/pkg/bluechip_client/cluster_resource_apis.go b/pkg/bluechip_client/cluster_resource_apis.go new file mode 100644 index 0000000..12bfa52 --- /dev/null +++ b/pkg/bluechip_client/cluster_resource_apis.go @@ -0,0 +1,82 @@ +package bluechip_client + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" +) + +func NewClusterClient[T bluechip_models.ClusterApiResource[P], P bluechip_models.BaseSpec](client *Client, gvk bluechip_models.GroupVersionKind) *ClusterResourceClient[T, P] { + return &ClusterResourceClient[T, P]{ + Client: client, + gvk: gvk, + } +} + +type ClusterResourceClient[T bluechip_models.ClusterApiResource[P], P bluechip_models.BaseSpec] struct { + *Client + gvk bluechip_models.GroupVersionKind +} + +func (c *ClusterResourceClient[T, P]) Get(ctx context.Context, name string) (T, error) { + var data T + req, err := http.NewRequest("GET", c.JoinUrl(c.gvk.ToApiPath(), name), nil) + if err != nil { + return data, err + } + _, err = c.DoWithType(req, &data) + return data, err +} + +func (c *ClusterResourceClient[T, P]) Upsert(ctx context.Context, data T) error { + buf, err := json.Marshal(data) + if err != nil { + return err + } + + req, err := http.NewRequest("PUT", c.JoinUrl(c.gvk.ToApiPath()), bytes.NewBuffer(buf)) + if err != nil { + return err + } + req.Header.Add("Content-Type", "application/json") + + resp, err := c.Do(req) + body := readBodyForError(resp) + if err != nil { + return fmt.Errorf("http request failed: %w, body: %s", err, body) + } + if len(body) != 0 { + tflog.Debug(ctx, "response body: %s", map[string]any{"body": string(body), "resp": resp}) + } + return nil +} + +func (c *ClusterResourceClient[T, P]) Delete(ctx context.Context, name string) error { + req, err := http.NewRequest("DELETE", c.JoinUrl(c.gvk.ToApiPath(), name), nil) + if err != nil { + return err + } + + resp, err := c.Do(req) + body := readBodyForError(resp) + if err != nil { + return fmt.Errorf("http request failed: %w, body: %s", err, body) + } + if len(body) != 0 { + tflog.Debug(ctx, "response body: %s", map[string]any{"body": string(body), "resp": resp}) + } + return nil +} + +func (c *ClusterResourceClient[T, P]) List(ctx context.Context) { + panic("implement me") +} + +func (c *ClusterResourceClient[T, P]) Search(ctx context.Context, query any) { + panic("implement me") +} diff --git a/pkg/bluechip_client/namespaced_resource_apis.go b/pkg/bluechip_client/namespaced_resource_apis.go new file mode 100644 index 0000000..bf9da36 --- /dev/null +++ b/pkg/bluechip_client/namespaced_resource_apis.go @@ -0,0 +1,83 @@ +package bluechip_client + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" +) + +func NewNamespacedClient[T bluechip_models.NamespacedApiResource[P], P bluechip_models.BaseSpec](client *Client, gvk bluechip_models.GroupVersionKind) *NamespacedResourceClient[T, P] { + return &NamespacedResourceClient[T, P]{ + Client: client, + gvk: gvk, + } +} + +type NamespacedResourceClient[T bluechip_models.NamespacedApiResource[P], P bluechip_models.BaseSpec] struct { + *Client + gvk bluechip_models.GroupVersionKind +} + +func (c *NamespacedResourceClient[T, P]) Get(ctx context.Context, namespace string, name string) (T, error) { + var data T + req, err := http.NewRequest("GET", c.JoinUrl(c.gvk.ToApiPath(), namespace, name), nil) + if err != nil { + return data, err + } + _, err = c.DoWithType(req, &data) + return data, err +} + +func (c *NamespacedResourceClient[T, P]) Upsert(ctx context.Context, namespace string, object T) error { + reqBuf, err := json.Marshal(object) + if err != nil { + return err + } + + reqStream := bytes.NewBuffer(reqBuf) + req, err := http.NewRequestWithContext(ctx, "PUT", c.JoinUrl(c.gvk.ToApiPath(), namespace), reqStream) + if err != nil { + return err + } + req.Header.Add("Content-Type", "application/json") + + resp, err := c.Do(req) + body := readBodyForError(resp) + if err != nil { + return fmt.Errorf("http request failed: %w, body: %s", err, body) + } + if len(body) != 0 { + tflog.Debug(ctx, "response body: %s", map[string]any{"body": string(body), "resp": resp}) + } + return nil +} + +func (c *NamespacedResourceClient[T, P]) Delete(ctx context.Context, namespace string, name string) error { + req, err := http.NewRequest("DELETE", c.JoinUrl(c.gvk.ToApiPath(), namespace, name), nil) + if err != nil { + return err + } + + resp, err := c.Do(req) + body := readBodyForError(resp) + if err != nil { + return fmt.Errorf("http request failed: %w, body: %s", err, body) + } + if len(body) != 0 { + tflog.Debug(ctx, "response body: %s", map[string]any{"body": string(body), "resp": resp}) + } + return nil +} + +func (c *NamespacedResourceClient[T, P]) List(ctx context.Context, namespace string) ([]T, error) { + panic("implement me") +} + +func (c *NamespacedResourceClient[T, P]) Search(ctx context.Context, namespace string, query any) { + panic("implement me") +} diff --git a/pkg/framework/fwflex/expander.go b/pkg/framework/fwflex/expander.go new file mode 100644 index 0000000..5ee2630 --- /dev/null +++ b/pkg/framework/fwflex/expander.go @@ -0,0 +1,66 @@ +package fwflex + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" +) + +type Expander[T bluechip_models.BaseSpec] func(ctx context.Context, d *schema.ResourceData, out *T) diag.Diagnostics + +func ExtractSingleBlock(ctx context.Context, d *schema.ResourceData, blockName string) (map[string]any, diag.Diagnostics) { + rawBlocks, ok := d.GetOk(blockName) + if !ok { + return nil, diag.Errorf("block %q is required", blockName) + } + + rawBlockList, ok := rawBlocks.([]any) + if !ok { + return nil, diag.Errorf("block %q is not a list", blockName) + } + + if len(rawBlockList) == 0 || rawBlockList[0] == nil { + return nil, diag.Errorf("block %q is empty", blockName) + } + + data, ok := rawBlockList[0].(map[string]any) + if !ok { + return nil, diag.Errorf("block %q is not a object", blockName) + } + + return data, nil +} + +func ExpandMap(attr map[string]any) map[string]string { + m := make(map[string]string) + for k, v := range attr { + m[k] = v.(string) + } + return m +} + +func ExpandStringList(attr []any) []string { + l := make([]string, len(attr)) + for i, v := range attr { + l[i] = v.(string) + } + return l +} + +func ExpandMapList(attr []any) []map[string]any { + l := make([]map[string]any, len(attr)) + for i, v := range attr { + l[i] = v.(map[string]any) + } + return l +} + +func ExpandStringSet(set *schema.Set) []string { + l := make([]string, set.Len()) + for i, v := range set.List() { + l[i] = v.(string) + } + return l +} diff --git a/pkg/framework/fwflex/flattener.go b/pkg/framework/fwflex/flattener.go new file mode 100644 index 0000000..37647a9 --- /dev/null +++ b/pkg/framework/fwflex/flattener.go @@ -0,0 +1,19 @@ +package fwflex + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" +) + +type Flattener[T bluechip_models.BaseSpec] func(ctx context.Context, d *schema.ResourceData, in T) diag.Diagnostics + +func FlattenMap(m map[string]string) map[string]any { + attr := make(map[string]any) + for k, v := range m { + attr[k] = v + } + return attr +} diff --git a/pkg/framework/fwlog/log.go b/pkg/framework/fwlog/log.go new file mode 100644 index 0000000..c9b9b7f --- /dev/null +++ b/pkg/framework/fwlog/log.go @@ -0,0 +1,7 @@ +package fwlog + +func Field(key string, value any) map[string]any { + return map[string]any{ + key: value, + } +} diff --git a/pkg/framework/fwservices/cluster_resource_tfdata_source.go b/pkg/framework/fwservices/cluster_resource_tfdata_source.go new file mode 100644 index 0000000..36d3164 --- /dev/null +++ b/pkg/framework/fwservices/cluster_resource_tfdata_source.go @@ -0,0 +1,63 @@ +package fwservices + +import ( + "context" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/internal/provider" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" +) + +type ClusterTerraformDataSource[T bluechip_models.ClusterApiResource[P], P bluechip_models.BaseSpec] struct { + Schema map[string]*schema.Schema + Timeout time.Duration + Gvk bluechip_models.GroupVersionKind + SpecExpander fwflex.Expander[P] + SpecFlattener fwflex.Flattener[P] +} + +func (r *ClusterTerraformDataSource[T, P]) Resource() *schema.Resource { + return &schema.Resource{ + Schema: r.Schema, + ReadContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Read(ctx, data, r.clusterWideClient(meta)) + }, + Timeouts: &schema.ResourceTimeout{ + Default: schema.DefaultTimeout(r.Timeout), + }, + } +} + +func (r *ClusterTerraformDataSource[T, P]) Read(ctx context.Context, d *schema.ResourceData, client *bluechip_client.ClusterResourceClient[T, P]) diag.Diagnostics { + var metadata bluechip_models.Metadata + diags := metadataTyp.Expand(ctx, d, &metadata) + if diags.HasError() { + return diags + } + + object, err := client.Get(ctx, metadata.Name) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(ClusterResourceIdentity(metadata.Name)) + + if diags := metadataTyp.Flatten(ctx, d, object.GetMetadata()); diags.HasError() { + return diags + } + + if diags := r.SpecFlattener(ctx, d, object.GetSpec()); diags.HasError() { + return diags + } + + return nil +} + +func (r *ClusterTerraformDataSource[T, P]) clusterWideClient(meta interface{}) *bluechip_client.ClusterResourceClient[T, P] { + model := meta.(*provider.ProviderModel) + return bluechip_client.NewClusterClient[T, P](model.Client, r.Gvk) +} diff --git a/pkg/framework/fwservices/cluster_resource_tfresource.go b/pkg/framework/fwservices/cluster_resource_tfresource.go new file mode 100644 index 0000000..24bd5bb --- /dev/null +++ b/pkg/framework/fwservices/cluster_resource_tfresource.go @@ -0,0 +1,154 @@ +package fwservices + +import ( + "context" + "time" + + "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/internal/provider" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwlog" +) + +type ClusterTerraformResource[T bluechip_models.ClusterApiResource[P], P bluechip_models.BaseSpec] struct { + Schema map[string]*schema.Schema + Timeout time.Duration + Gvk bluechip_models.GroupVersionKind + SpecExpander fwflex.Expander[P] + SpecFlattener fwflex.Flattener[P] + Constructor func() T +} + +func (r *ClusterTerraformResource[T, P]) Resource() *schema.Resource { + return &schema.Resource{ + Schema: r.Schema, + CreateContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Upsert(ctx, data, r.clusterWideClient(meta)) + }, + ReadContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Read(ctx, data, r.clusterWideClient(meta)) + }, + UpdateContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Upsert(ctx, data, r.clusterWideClient(meta)) + }, + DeleteContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Delete(ctx, data, r.clusterWideClient(meta)) + }, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Timeouts: &schema.ResourceTimeout{ + Default: schema.DefaultTimeout(r.Timeout), + }, + } +} + +func (r *ClusterTerraformResource[T, P]) Upsert(ctx context.Context, d *schema.ResourceData, client *bluechip_client.ClusterResourceClient[T, P]) diag.Diagnostics { + ctx = tflog.SetField(ctx, "gvk", r.Gvk) + + var metadata bluechip_models.Metadata + if diags := metadataTyp.Expand(ctx, d, &metadata); diags.HasError() { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "metadata Expansion Failed", + Detail: "metadata Expansion Failed", + AttributePath: cty.GetAttrPath("metadata.0"), + }) + tflog.Info(ctx, "metadata Expansion Failed", fwlog.Field("diags", diags)) + return diags + } + + var spec P + if diags := r.SpecExpander(ctx, d, &spec); diags.HasError() { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "spec Expansion Failed", + Detail: "spec Expansion Failed", + AttributePath: cty.GetAttrPath("spec.0"), + }) + tflog.Info(ctx, "spec Expansion Failed", fwlog.Field("diags", diags)) + return diags + } + + object := r.Constructor() + typeMeta := r.Gvk.ToTypeMeta() + object.SetApiVersion(typeMeta.GetApiVersion()) + object.SetKind(typeMeta.GetKind()) + object.SetMetadata(metadata) + object.SetSpec(spec) + if err := client.Upsert(ctx, object); err != nil { + diags := append(diag.FromErr(err), diag.Diagnostic{ + Severity: diag.Error, + Summary: "Upsert Request Failed", + Detail: "Upsert Request Failed", + }) + tflog.Info(ctx, "Upsert Request Failed", fwlog.Field("object", object), fwlog.Field("diags", diags)) + return diags + } + + d.SetId(ClusterResourceIdentity(metadata.Name)) + return r.Read(ctx, d, client) +} + +func (r *ClusterTerraformResource[T, P]) Read(ctx context.Context, d *schema.ResourceData, client *bluechip_client.ClusterResourceClient[T, P]) diag.Diagnostics { + name := ClusterResourceIdentityFrom(d.Id()) + object, err := client.Get(ctx, name) + if err != nil { + diags := append(diag.FromErr(err), diag.Diagnostic{ + Severity: diag.Error, + Summary: "Get Request Failed", + Detail: "Get Request Failed", + }) + tflog.Info(ctx, "Get Request Failed", fwlog.Field("diags", diags)) + return diags + } + + if diags := metadataTyp.Flatten(ctx, d, object.GetMetadata()); diags.HasError() { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "metadata Flatten Failed", + Detail: "metadata Flatten Failed", + AttributePath: cty.GetAttrPath("metadata.0"), + }) + tflog.Info(ctx, "metadata Flatten Failed", fwlog.Field("diags", diags)) + return diags + } + + if diags := r.SpecFlattener(ctx, d, object.GetSpec()); diags.HasError() { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "spec Flatten Failed", + Detail: "spec Flatten Failed", + AttributePath: cty.GetAttrPath("spec.0"), + }) + tflog.Info(ctx, "spec Flatten Failed", fwlog.Field("diags", diags)) + return diags + } + + return nil +} + +func (r *ClusterTerraformResource[T, P]) Delete(ctx context.Context, d *schema.ResourceData, client *bluechip_client.ClusterResourceClient[T, P]) diag.Diagnostics { + name := ClusterResourceIdentityFrom(d.Id()) + + if err := client.Delete(ctx, name); err != nil { + diags := append(diag.FromErr(err), diag.Diagnostic{ + Severity: diag.Error, + Summary: "Delete Request Failed", + Detail: "Delete Request Failed", + }) + tflog.Info(ctx, "Delete Request Failed", fwlog.Field("diags", diags)) + return diags + } + return nil +} + +func (r *ClusterTerraformResource[T, P]) clusterWideClient(meta interface{}) *bluechip_client.ClusterResourceClient[T, P] { + model := meta.(*provider.ProviderModel) + return bluechip_client.NewClusterClient[T, P](model.Client, r.Gvk) +} diff --git a/pkg/framework/fwservices/factory.go b/pkg/framework/fwservices/factory.go new file mode 100644 index 0000000..82baff5 --- /dev/null +++ b/pkg/framework/fwservices/factory.go @@ -0,0 +1,32 @@ +package fwservices + +import ( + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwtype" +) + +type ResourceFactory interface { + Resource() *schema.Resource +} + +var metadataTyp = &fwtype.MetadataType{} + +func NamespacedResourceIdentity(namespace, name string) string { + return fmt.Sprintf("%s/%s", namespace, name) +} + +func NamespacedResourceIdentityFrom(id string) (string, string) { + parts := strings.Split(id, "/") + return parts[0], parts[1] +} + +func ClusterResourceIdentity(name string) string { + return name +} + +func ClusterResourceIdentityFrom(id string) string { + return id +} diff --git a/pkg/framework/fwservices/namespaced_resource_tfdata_source.go b/pkg/framework/fwservices/namespaced_resource_tfdata_source.go new file mode 100644 index 0000000..040c032 --- /dev/null +++ b/pkg/framework/fwservices/namespaced_resource_tfdata_source.go @@ -0,0 +1,63 @@ +package fwservices + +import ( + "context" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/internal/provider" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" +) + +type NamespacedTerraformDataSource[T bluechip_models.NamespacedApiResource[P], P bluechip_models.BaseSpec] struct { + Schema map[string]*schema.Schema + Timeout time.Duration + Gvk bluechip_models.GroupVersionKind + SpecExpander fwflex.Expander[P] + SpecFlattener fwflex.Flattener[P] +} + +func (r *NamespacedTerraformDataSource[T, P]) Resource() *schema.Resource { + return &schema.Resource{ + Schema: r.Schema, + ReadContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Read(ctx, data, r.namespacedClient(meta)) + }, + Timeouts: &schema.ResourceTimeout{ + Default: schema.DefaultTimeout(r.Timeout), + }, + } +} + +func (r *NamespacedTerraformDataSource[T, P]) Read(ctx context.Context, d *schema.ResourceData, client *bluechip_client.NamespacedResourceClient[T, P]) diag.Diagnostics { + var metadata bluechip_models.Metadata + diags := metadataTyp.Expand(ctx, d, &metadata) + if diags.HasError() { + return diags + } + + object, err := client.Get(ctx, metadata.Namespace, metadata.Name) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(NamespacedResourceIdentity(metadata.Namespace, metadata.Name)) + + if diags := metadataTyp.Flatten(ctx, d, object.GetMetadata()); diags.HasError() { + return diags + } + + if diags := r.SpecFlattener(ctx, d, object.GetSpec()); diags.HasError() { + return diags + } + + return nil +} + +func (r *NamespacedTerraformDataSource[T, P]) namespacedClient(meta interface{}) *bluechip_client.NamespacedResourceClient[T, P] { + model := meta.(*provider.ProviderModel) + return bluechip_client.NewNamespacedClient[T, P](model.Client, r.Gvk) +} diff --git a/pkg/framework/fwservices/namespaced_resource_tfresource.go b/pkg/framework/fwservices/namespaced_resource_tfresource.go new file mode 100644 index 0000000..553aa58 --- /dev/null +++ b/pkg/framework/fwservices/namespaced_resource_tfresource.go @@ -0,0 +1,155 @@ +package fwservices + +import ( + "context" + "time" + + "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/internal/provider" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwlog" +) + +type NamespacedTerraformResource[T bluechip_models.NamespacedApiResource[P], P bluechip_models.BaseSpec] struct { + Schema map[string]*schema.Schema + Timeout time.Duration + Gvk bluechip_models.GroupVersionKind + SpecExpander fwflex.Expander[P] + SpecFlattener fwflex.Flattener[P] + Constructor func() T +} + +func (r *NamespacedTerraformResource[T, P]) Resource() *schema.Resource { + return &schema.Resource{ + Schema: r.Schema, + CreateContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Upsert(ctx, data, r.namespacedClient(meta)) + }, + ReadContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Read(ctx, data, r.namespacedClient(meta)) + }, + UpdateContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Upsert(ctx, data, r.namespacedClient(meta)) + }, + DeleteContext: func(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { + return r.Delete(ctx, data, r.namespacedClient(meta)) + }, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Timeouts: &schema.ResourceTimeout{ + Default: schema.DefaultTimeout(r.Timeout), + }, + } +} + +func (r *NamespacedTerraformResource[T, P]) Upsert(ctx context.Context, d *schema.ResourceData, client *bluechip_client.NamespacedResourceClient[T, P]) diag.Diagnostics { + ctx = tflog.SetField(ctx, "gvk", r.Gvk) + + var metadata bluechip_models.Metadata + if diags := metadataTyp.Expand(ctx, d, &metadata); diags.HasError() { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "metadata Expansion Failed", + Detail: "metadata Expansion Failed", + AttributePath: cty.GetAttrPath("metadata.0"), + }) + tflog.Info(ctx, "metadata Expansion Failed", fwlog.Field("diags", diags)) + return diags + } + + var spec P + if diags := r.SpecExpander(ctx, d, &spec); diags.HasError() { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "spec Expansion Failed", + Detail: "spec Expansion Failed", + AttributePath: cty.GetAttrPath("spec.0"), + }) + tflog.Info(ctx, "spec Expansion Failed", fwlog.Field("diags", diags)) + return diags + } + + object := r.Constructor() + typeMeta := r.Gvk.ToTypeMeta() + object.SetApiVersion(typeMeta.GetApiVersion()) + object.SetKind(typeMeta.GetKind()) + object.SetMetadata(metadata) + object.SetSpec(spec) + if err := client.Upsert(ctx, metadata.Namespace, object); err != nil { + diags := append(diag.FromErr(err), diag.Diagnostic{ + Severity: diag.Error, + Summary: "Upsert Request Failed", + Detail: "Upsert Request Failed", + AttributePath: cty.GetAttrPath("spec.0"), + }) + tflog.Info(ctx, "Upsert Request Failed", fwlog.Field("object", object), fwlog.Field("diags", diags)) + return diags + } + + d.SetId(NamespacedResourceIdentity(metadata.Namespace, metadata.Name)) + return r.Read(ctx, d, client) +} + +func (r *NamespacedTerraformResource[T, P]) Read(ctx context.Context, d *schema.ResourceData, client *bluechip_client.NamespacedResourceClient[T, P]) diag.Diagnostics { + namespace, name := NamespacedResourceIdentityFrom(d.Id()) + object, err := client.Get(ctx, namespace, name) + if err != nil { + diags := append(diag.FromErr(err), diag.Diagnostic{ + Severity: diag.Error, + Summary: "Get Request Failed", + Detail: "Get Request Failed", + }) + tflog.Info(ctx, "Get Request Failed", fwlog.Field("diags", diags)) + return diags + } + + if diags := metadataTyp.Flatten(ctx, d, object.GetMetadata()); diags.HasError() { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "metadata Flatten Failed", + Detail: "metadata Flatten Failed", + AttributePath: cty.GetAttrPath("metadata.0"), + }) + tflog.Info(ctx, "metadata Flatten Failed", fwlog.Field("diags", diags)) + return diags + } + + if diags := r.SpecFlattener(ctx, d, object.GetSpec()); diags.HasError() { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "spec Flatten Failed", + Detail: "spec Flatten Failed", + AttributePath: cty.GetAttrPath("spec.0"), + }) + tflog.Info(ctx, "spec Flatten Failed", fwlog.Field("diags", diags)) + return diags + } + + return nil +} + +func (r *NamespacedTerraformResource[T, P]) Delete(ctx context.Context, d *schema.ResourceData, client *bluechip_client.NamespacedResourceClient[T, P]) diag.Diagnostics { + namespace, name := NamespacedResourceIdentityFrom(d.Id()) + + if err := client.Delete(ctx, namespace, name); err != nil { + diags := append(diag.FromErr(err), diag.Diagnostic{ + Severity: diag.Error, + Summary: "Delete Request Failed", + Detail: "Delete Request Failed", + }) + tflog.Info(ctx, "Delete Request Failed", fwlog.Field("diags", diags)) + return diags + } + return nil +} + +func (r *NamespacedTerraformResource[T, P]) namespacedClient(meta interface{}) *bluechip_client.NamespacedResourceClient[T, P] { + model := meta.(*provider.ProviderModel) + return bluechip_client.NewNamespacedClient[T, P](model.Client, r.Gvk) +} diff --git a/pkg/framework/fwtype/metadata.go b/pkg/framework/fwtype/metadata.go new file mode 100644 index 0000000..2162c35 --- /dev/null +++ b/pkg/framework/fwtype/metadata.go @@ -0,0 +1,107 @@ +package fwtype + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" +) + +var MetadataTyp = &MetadataType{} + +type MetadataType struct { +} + +func (MetadataType) Schema(namespaced bool, computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "annotations": { + Type: schema.TypeMap, + Elem: schema.TypeString, + Description: "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects.", + Computed: computed, + Optional: true, + }, + "labels": { + Type: schema.TypeMap, + Elem: schema.TypeString, + Description: "Labels are key value pairs that may be used to scope and select individual resources. They are not queryable and should be preserved when modifying objects.", + Computed: computed, + Optional: true, + }, + "name": { + Type: schema.TypeString, + Description: "Name is the name of the resource.", + Required: true, + }, + "creation_timestamp": { + Type: schema.TypeString, + Description: "CreationTimestamp is a timestamp representing the server time when this object was created.", + Computed: true, + }, + "update_timestamp": { + Type: schema.TypeString, + Description: "UpdateTimestamp is a timestamp representing the server time when this object was last updated.", + Computed: true, + }, + } + + if namespaced { + innerSchema["namespace"] = &schema.Schema{ + Type: schema.TypeString, + Description: "Namespace is the namespace of the resource.", + Required: true, + } + } + + blockSchema := SingleNestedBlock(innerSchema, computed, false) + blockSchema.Optional = computed + CleanForDataSource(blockSchema) + return blockSchema +} + +func (MetadataType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.Metadata) diag.Diagnostics { + attr, diags := fwflex.ExtractSingleBlock(ctx, d, "metadata") + if diags.HasError() { + return diags + } + + out.Name = attr["name"].(string) + if attr["namespace"] != nil { + out.Namespace = attr["namespace"].(string) + } + if attr["annotations"] != nil { + out.Annotations = fwflex.ExpandMap(attr["annotations"].(map[string]any)) + } + if attr["labels"] != nil { + out.Labels = fwflex.ExpandMap(attr["labels"].(map[string]any)) + } + if attr["creation_timestamp"] != nil { + out.CreationTimestamp = attr["creation_timestamp"].(string) + } + if attr["update_timestamp"] != nil { + out.UpdateTimestamp = attr["update_timestamp"].(string) + } + return nil +} + +func (MetadataType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.Metadata) diag.Diagnostics { + attr := map[string]any{} + attr["name"] = in.Name + if in.Namespace != "" { + attr["namespace"] = in.Namespace + } + attr["annotations"] = fwflex.FlattenMap(in.Annotations) + attr["labels"] = fwflex.FlattenMap(in.Labels) + if in.CreationTimestamp != "" { + attr["creation_timestamp"] = in.CreationTimestamp + } + if in.UpdateTimestamp != "" { + attr["update_timestamp"] = in.UpdateTimestamp + } + if err := d.Set("metadata", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/pkg/framework/fwtype/ptr.go b/pkg/framework/fwtype/ptr.go new file mode 100644 index 0000000..5699e46 --- /dev/null +++ b/pkg/framework/fwtype/ptr.go @@ -0,0 +1,5 @@ +package fwtype + +func String(s string) *string { + return &s +} diff --git a/pkg/framework/fwtype/rolebinding.go b/pkg/framework/fwtype/rolebinding.go new file mode 100644 index 0000000..1c70c33 --- /dev/null +++ b/pkg/framework/fwtype/rolebinding.go @@ -0,0 +1,153 @@ +package fwtype + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/pubg/terraform-provider-bluechip/pkg/bluechip_client/bluechip_models" + "github.com/pubg/terraform-provider-bluechip/pkg/framework/fwflex" +) + +var RoleBindingTyp = &RoleBindingType{} + +type RoleBindingType struct { +} + +func (RoleBindingType) Schema(computed bool) *schema.Schema { + innerSchema := map[string]*schema.Schema{ + "subject_ref": SingleNestedBlock(map[string]*schema.Schema{ + "kind": { + Type: schema.TypeString, + Description: "Kind of the referent. Valid kinds are 'User', 'Group'.", + Required: !computed, + Computed: computed, + }, + "name": { + Type: schema.TypeString, + Description: "Name of the referent.", + Required: !computed, + Computed: computed, + }, + }, computed, true), + "policy_inline": { + Type: schema.TypeList, + Optional: !computed, + Computed: computed, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "actions": { + Type: schema.TypeSet, + Description: "Actions is a list of actions this role binding grants access to.", + Required: !computed, + Computed: computed, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "paths": { + Type: schema.TypeSet, + Description: "Paths is a list of paths this role binding grants access to.", + Required: !computed, + Computed: computed, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "resources": { + Type: schema.TypeSet, + Description: "Resources is a list of resources this role binding grants access to.", + Required: !computed, + Computed: computed, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "api_group": { + Type: schema.TypeString, + Description: "APIGroup is the group for the resource being referenced.", + Required: !computed, + Computed: computed, + }, + "kind": { + Type: schema.TypeString, + Description: "Kind is the type of resource being referenced.", + Required: !computed, + Computed: computed, + }, + }, + }, + }, + }, + }, + }, + "policy_ref": { + Type: schema.TypeString, + Optional: !computed, + Computed: computed, + }, + } + + blockSchema := SingleNestedBlock(innerSchema, computed, true) + CleanForDataSource(blockSchema) + return blockSchema +} + +func (RoleBindingType) Expand(ctx context.Context, d *schema.ResourceData, out *bluechip_models.RoleBindingSpec) diag.Diagnostics { + attr := d.Get("spec.0").(map[string]any) + + rawSubjectRef := fwflex.ExpandMapList(attr["subject_ref"].([]any)) + out.SubjectsRef = bluechip_models.SubjectRef{ + Kind: rawSubjectRef[0]["kind"].(string), + Name: rawSubjectRef[0]["name"].(string), + } + + rawPolicyInlineList := fwflex.ExpandMapList(attr["policy_inline"].([]any)) + for _, rawPolicyInline := range rawPolicyInlineList { + policyInline := bluechip_models.PolicyStatement{ + Actions: fwflex.ExpandStringSet(rawPolicyInline["actions"].(*schema.Set)), + Paths: fwflex.ExpandStringSet(rawPolicyInline["paths"].(*schema.Set)), + Resources: []bluechip_models.PolicyResource{}, + } + rawPolicyResourceList := fwflex.ExpandMapList(rawPolicyInline["resources"].([]any)) + for _, rawPolicyResource := range rawPolicyResourceList { + policyResource := bluechip_models.PolicyResource{ + ApiGroup: rawPolicyResource["api_group"].(string), + Kind: rawPolicyResource["kind"].(string), + } + policyInline.Resources = append(policyInline.Resources, policyResource) + } + out.PolicyInline = append(out.PolicyInline, policyInline) + } + + if attr["policy_ref"] != nil { + out.PolicyRef = String(attr["policy_ref"].(string)) + } + return nil +} + +func (RoleBindingType) Flatten(ctx context.Context, d *schema.ResourceData, in bluechip_models.RoleBindingSpec) diag.Diagnostics { + attr := map[string]any{ + "subject_ref": []map[string]any{{ + "kind": in.SubjectsRef.Kind, + "name": in.SubjectsRef.Name, + }}, + "policy_inline": []map[string]any{}, + "policy_ref": in.PolicyRef, + } + + for _, policyInline := range in.PolicyInline { + rawPolicyInline := map[string]any{ + "actions": policyInline.Actions, + "paths": policyInline.Paths, + "resources": []map[string]any{}, + } + for _, policyResource := range policyInline.Resources { + rawPolicyResource := map[string]any{ + "api_group": policyResource.ApiGroup, + "kind": policyResource.Kind, + } + rawPolicyInline["resources"] = append(rawPolicyInline["resources"].([]map[string]any), rawPolicyResource) + } + attr["policy_inline"] = append(attr["policy_inline"].([]map[string]any), rawPolicyInline) + } + + if err := d.Set("spec", []map[string]any{attr}); err != nil { + return diag.FromErr(err) + } + return nil +} diff --git a/pkg/framework/fwtype/schema_cleaner.go b/pkg/framework/fwtype/schema_cleaner.go new file mode 100644 index 0000000..6609c1e --- /dev/null +++ b/pkg/framework/fwtype/schema_cleaner.go @@ -0,0 +1,20 @@ +package fwtype + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func CleanForDataSourceMap(s map[string]*schema.Schema) { + for _, scheme := range s { + CleanForDataSource(scheme) + } +} + +func CleanForDataSource(scheme *schema.Schema) { + scheme.ValidateFunc = nil + scheme.ValidateDiagFunc = nil + scheme.MinItems = 0 + scheme.MaxItems = 0 + + if resource, ok := scheme.Elem.(*schema.Resource); ok { + CleanForDataSourceMap(resource.Schema) + } +} diff --git a/pkg/framework/fwtype/single_nested_block.go b/pkg/framework/fwtype/single_nested_block.go new file mode 100644 index 0000000..e39946c --- /dev/null +++ b/pkg/framework/fwtype/single_nested_block.go @@ -0,0 +1,22 @@ +package fwtype + +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + +func SingleNestedBlock(in map[string]*schema.Schema, computed bool, optional bool) *schema.Schema { + block := &schema.Schema{ + Type: schema.TypeList, + Required: !computed, + Computed: computed, + Elem: &schema.Resource{Schema: in}, + } + + if !computed { + block.MaxItems = 1 + if optional { + block.MinItems = 0 + } else { + block.MinItems = 1 + } + } + return block +} 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/test/main.tf b/test/main.tf new file mode 100644 index 0000000..dae5656 --- /dev/null +++ b/test/main.tf @@ -0,0 +1,37 @@ +provider "bluechip" { + address = "" + basic_auth { + } + aws_auth { + cluster_name = "bluechip" + region = "ap-northeast-2" + profile = "pubg-dev" + } + jwt_auth { + token = "" + auth_method_name = "" + } +} + +#data "bluechip_apiresources" "current" { +# +#} +# +#output "asdf" { +# value = data.bluechip_apiresources.current +#} + +resource "bluechip_cluster" "current" { + metadata { + } +} + + + +terraform { + required_providers { + bluechip = { + source = "pubg/bluechip" + } + } +} diff --git a/tools/tools.go b/tools/tools.go new file mode 100644 index 0000000..2c4f8fb --- /dev/null +++ b/tools/tools.go @@ -0,0 +1,8 @@ +//go:build tools + +package tools + +import ( + // Documentation generation + _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs" +)