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"
+)