From 3086a4579107cc62d2eb648d07177e318c65a236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Collignon-Ducret=20R=C3=A9mi?= Date: Thu, 28 Apr 2022 15:32:15 +0200 Subject: [PATCH] feat(app): NodeJS (#14) Co-authored-by: miton18 --- .github/workflows/testacc.yml | 6 +- docs/data-sources/coffee.md | 37 ----- docs/data-sources/ingredient.md | 37 ----- docs/data-sources/order.md | 45 ------ docs/index.md | 35 ++--- docs/resources/nodejs.md | 51 +++++++ docs/resources/order.md | 57 ------- docs/resources/postgresql.md | 37 +++++ examples/main.tf | 9 ++ go.mod | 19 ++- go.sum | 53 ++++++- main.go | 6 +- pkg/provider/provider_schema.go | 35 +++-- pkg/provider/resource_nodejs_crud.go | 102 +++++++++++-- pkg/provider/resource_nodejs_meta.go | 2 +- pkg/provider/resource_nodejs_schema.go | 167 ++++++++++++++++++--- pkg/provider/resource_nodejs_test.go | 20 ++- pkg/provider/resource_postgresql_crud.go | 30 ++-- pkg/provider/resource_postgresql_schema.go | 28 ++-- pkg/provider/strings.go | 13 ++ pkg/tmp/app.go | 57 ++++++- tools/tools.go | 8 + 22 files changed, 568 insertions(+), 286 deletions(-) delete mode 100644 docs/data-sources/coffee.md delete mode 100644 docs/data-sources/ingredient.md delete mode 100644 docs/data-sources/order.md create mode 100644 docs/resources/nodejs.md delete mode 100644 docs/resources/order.md create mode 100644 docs/resources/postgresql.md create mode 100644 pkg/provider/strings.go create mode 100644 tools/tools.go diff --git a/.github/workflows/testacc.yml b/.github/workflows/testacc.yml index da758c1..5714fcd 100644 --- a/.github/workflows/testacc.yml +++ b/.github/workflows/testacc.yml @@ -1,7 +1,7 @@ name: Acceptance Tests on: - push: + pull_request: types: [ labeled ] jobs: @@ -17,4 +17,6 @@ jobs: go-version: 1.18 - name: Acceptance Tests - run: make testacc \ No newline at end of file + run: make testacc + env: + ORGANISATION: ${{ secrets.ORG }} \ No newline at end of file diff --git a/docs/data-sources/coffee.md b/docs/data-sources/coffee.md deleted file mode 100644 index 7e68d36..0000000 --- a/docs/data-sources/coffee.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -page_title: "coffee Data Source - terraform-provider-hashicups" -subcategory: "" -description: |- - The coffee data source allows you to retrieve information all available HashiCups coffees. ---- - -# Data Source `coffee` - -The coffee data source allows you to retrieve information all available HashiCups coffees. - -## Example Usage - -```terraform -data "hashicups_coffees" "all" {} - -``` - -## Attributes Reference - -The following attributes are exported. - -- `coffees` - A list of HashiCups coffee objects. See [Coffee](#coffee) below for details. - -### Coffee - -- `id` - The coffee ID. -- `image` - The coffee's image URL path. -- `name` - The coffee name. -- `price` - The coffee price. -- `teaser` - The coffee teaser. -- `description` - The coffee description. -- `ingredients` - A list of coffee ingredients. See [Ingredients](#ingredients) below for details. - -### Ingredients - -- `ingredient_id` - The ingredient ID. \ No newline at end of file diff --git a/docs/data-sources/ingredient.md b/docs/data-sources/ingredient.md deleted file mode 100644 index 290a462..0000000 --- a/docs/data-sources/ingredient.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -page_title: "ingredient Data Source - terraform-provider-hashicups" -subcategory: "" -description: |- - The ingredient data source allows you to retrieve a coffee's ingredients. ---- - -# Data Source `ingredient` - -The ingredient data source allows you to retrieve a coffee's ingredients. - -## Example Usage - -```terraform -data "hashicups_coffees" "all" {} - -data "hashicups_ingredients" "psl" { - coffee_id = values(hashicups_coffees.all)[0].id -} -``` - -## Argument Reference - -- `coffee_id` - The coffee ID. - -## Attributes Reference - -In addition to all the arguments above, the following attributes are exported. - -- `ingredients` - A list of coffee ingredients. See [Ingredients](#ingredients) below for details. - -### Ingredients - -- `id` - The ingredient ID. -- `name` - The ingredient name. -- `quantity` - The ingredient quantity. -- `unit` - The ingredient unit. \ No newline at end of file diff --git a/docs/data-sources/order.md b/docs/data-sources/order.md deleted file mode 100644 index b1ab7d1..0000000 --- a/docs/data-sources/order.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -page_title: "order Data Source - terraform-provider-hashicups" -subcategory: "" -description: |- - The order data source allows you to retrieve information about a particular HashiCups order. ---- - -# Data Source `hashicups_order` - --> Visit the [Perform CRUD operations with Providers](https://learn.hashicorp.com/tutorials/terraform/provider-use?in=terraform/providers&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) Learn tutorial for an interactive getting started experience. - -The order data source allows you to retrieve information about a particular HashiCups order. - -## Example Usage - -```terraform -data "hashicups_order" "edu" { - id = 1 -} -``` - -## Argument Reference - -- `id` - (Required) HashiCups order ID. - -## Attributes Reference - -In addition to all the arguments above, the following attributes are exported. - -- `items` - Items in a HashiCups order. See [Order item](#order-item) below for details. - -### Order item - -Each order item contains a `coffee` object and a `quantity`. - -- `coffee` - Represents a HashiCups coffee object. See [Coffee](#coffee) below for details. -- `quantity` - The number of coffee in an order item. - -### Coffee - -- `id` - The coffee ID. -- `image` - The coffee's image URL path. -- `name` - The coffee name. -- `price` - The coffee price. -- `teaser` - The coffee teaser. diff --git a/docs/index.md b/docs/index.md index 4b3b3a1..132e5a9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,37 +1,26 @@ --- -page_title: "Provider: HashiCups" +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "clevercloud Provider" subcategory: "" description: |- - Terraform provider for interacting with HashiCups API. + CleverCloud provider allow you to interract with CleverCloud platform. --- -# HashiCups Provider +# clevercloud Provider --> Visit the [Call APIs with Terraform Providers](https://learn.hashicorp.com/collections/terraform/providers?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) Learn tutorials for an interactive getting started experience. +CleverCloud provider allow you to interract with CleverCloud platform. -The HashiCups provider is used to interact with a fictional coffee-shop application, HashiCups. This provider is meant to serve as an educational tool to show users how: -1. use providers to [create, read, update and delete (CRUD) resources](https://learn.hashicorp.com/tutorials/terraform/provider-use?in=terraform/providers) using Terraform. -1. create a custom Terraform provider. -To learn how to re-create the HashiCups provider, refer to the [Call APIs with Terraform Providers](https://learn.hashicorp.com/collections/terraform/providers?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) Learn tutorials. -Use the navigation to the left to read about the available resources. - -## Example Usage - -Do not keep your authentication password in HCL for production environments, use Terraform environment variables. + +## Schema -```terraform -provider "hashicups" { - username = "education" - password = "test123" -} -``` +### Required -## Schema +- `organisation` (String, Sensitive) CleverCloud organisation, can be either org_xxx, or user_xxx for personal spaces ### Optional -- **username** (String, Optional) Username to authenticate to HashiCups API -- **password** (String, Optional) Password to authenticate to HashiCups API -- **host** (String, Optional) HashiCups API address (defaults to `localhost:19090`) \ No newline at end of file +- `endpoint` (String) CleverCloud API endpoint, default to https://api.clever-cloud.com +- `secret` (String, Sensitive) CleverCloud OAuth1 secret, can be took from clever-tools after login +- `token` (String) CleverCloud OAuth1 token, can be took from clever-tools after login diff --git a/docs/resources/nodejs.md b/docs/resources/nodejs.md new file mode 100644 index 0000000..dd34c04 --- /dev/null +++ b/docs/resources/nodejs.md @@ -0,0 +1,51 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "clevercloud_nodejs Resource - terraform-provider-clevercloud" +subcategory: "" +description: |- + Manage NodeJS https://nodejs.org/ applications. + See NodeJS product https://www.clever-cloud.com/nodejs-hosting/ specification. +--- + +# clevercloud_nodejs (Resource) + +Manage [NodeJS](https://nodejs.org/) applications. + +See [NodeJS product](https://www.clever-cloud.com/nodejs-hosting/) specification. + + + + +## Schema + +### Required + +- `biggest_flavor` (String) Biggest intance flavor, if different from smallest, enable autoscaling +- `max_instance_count` (Number) Maximum instance count, if different from min value, enable autoscaling +- `min_instance_count` (Number) Minimum instance count +- `name` (String) Application name +- `region` (String) Geographical region where the app will be deployed +- `smallest_flavor` (String) Smallest instance flavor + +### Optional + +- `additional_vhosts` (List of String) Add custom hostname in addition to the default one, see [documentation](https://www.clever-cloud.com/doc/administrate/domain-names/) +- `app_folder` (String) Folder in which the application is located (inside the git repository) +- `build_flavor` (String) Use dedicated instance with given flavor for build step +- `commit` (String) Deploy application on the given commit/tag +- `description` (String) Application description +- `dev_dependencies` (Boolean) Install development dependencies specified in package.json +- `package_manager` (String) Either npm, npm-ci, yarn, yarn2 or custom +- `redirect_https` (Boolean) Redirect client from plain to TLS port +- `registry` (String) The host of your private repository, available values: github or the registry host +- `registry_token` (String, Sensitive) Private repository token +- `start_script` (String) Set custom start script, instead of `npm start` +- `sticky_sessions` (Boolean) Enable sticky sessions, use it when your client sessions are instances scoped + +### Read-Only + +- `deploy_url` (String) Git URL used to push source code +- `id` (String) Unique identifier generated during application creation +- `vhost` (String) Default vhost to access your app + + diff --git a/docs/resources/order.md b/docs/resources/order.md deleted file mode 100644 index 0da7966..0000000 --- a/docs/resources/order.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -page_title: "order Resource - terraform-provider-hashicups" -subcategory: "" -description: |- - The order resource allows you to configure a HashiCups order. ---- - -# Resource `hashicups_order` - --> Visit the [Perform CRUD operations with Providers](https://learn.hashicorp.com/tutorials/terraform/provider-use?in=terraform/providers&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) Learn tutorial for an interactive getting started experience. - -The order resource allows you to configure a HashiCups order. - -## Example Usage - -```terraform -resource "hashicups_order" "edu" { - items { - coffee { - id = 3 - } - quantity = 2 - } - items { - coffee { - id = 2 - } - quantity = 2 - } -} -``` - -## Argument Reference - -- `items` - (Required) Items in a HashiCups order. See [Order item](#order-item) below for details. - -### Order item - -Each order item contains a `coffee` object and a `quantity`. - -- `coffee` - (Required) Represents a HashiCups coffee object. See [Coffee](#coffee) below for details. -- `quantity` - (Required) The number of coffee in an order item. - -### Coffee - -- `id` - (Required) The HashiCups coffee ID. - -## Attributes Reference - -In addition to all the arguments above, the following attributes are exported. - -### Coffee - -- `image` - The coffee's image URL path. -- `name` - The coffee name. -- `price` - The coffee price. -- `teaser` - The coffee teaser. \ No newline at end of file diff --git a/docs/resources/postgresql.md b/docs/resources/postgresql.md new file mode 100644 index 0000000..c0473b6 --- /dev/null +++ b/docs/resources/postgresql.md @@ -0,0 +1,37 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "clevercloud_postgresql Resource - terraform-provider-clevercloud" +subcategory: "" +description: |- + Manage PostgreSQL https://www.postgresql.org/ product. + See product specification https://www.clever-cloud.com/postgresql-hosting/. +--- + +# clevercloud_postgresql (Resource) + +Manage [PostgreSQL](https://www.postgresql.org/) product. + +See [product specification](https://www.clever-cloud.com/postgresql-hosting/). + + + + +## Schema + +### Required + +- `name` (String) Name of the service +- `plan` (String) Database size and spec +- `region` (String) Geographical region where the database will be deployed + +### Read-Only + +- `creation_date` (Number) Date of database creation +- `database` (String) Database name on the PostgreSQL server +- `host` (String) Database host, used to connect to +- `id` (String) Generated unique identifier +- `password` (String, Sensitive) Login password +- `port` (Number) Database port +- `user` (String) Login username + + diff --git a/examples/main.tf b/examples/main.tf index 9476636..0de1993 100644 --- a/examples/main.tf +++ b/examples/main.tf @@ -22,6 +22,15 @@ resource "clevercloud_postgresql" "PG1" { region = "par" } +resource "clevercloud_nodejs" "node1" { + name = "myNodeApp" + region = "par" + min_instance_count = 1 + max_instance_count = 2 + smallest_flavor = "XS" + biggest_flavor = "M" +} + output "host" { value = clevercloud_postgresql.PG1.host } diff --git a/go.mod b/go.mod index 9e036a2..697dd76 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( github.com/go-git/go-billy/v5 v5.3.1 github.com/go-git/go-git/v5 v5.4.2 + github.com/hashicorp/terraform-plugin-docs v0.7.0 github.com/hashicorp/terraform-plugin-framework v0.6.1 github.com/hashicorp/terraform-plugin-go v0.8.0 github.com/hashicorp/terraform-plugin-log v0.3.0 @@ -14,12 +15,17 @@ require ( ) 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/Microsoft/go-winio v0.5.2 // indirect github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 // indirect github.com/acomagu/bufpipe v1.0.3 // indirect github.com/adrg/xdg v0.4.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/armon/go-radix v1.0.0 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fatih/color v1.13.0 // indirect @@ -28,6 +34,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.7 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -35,21 +42,23 @@ require ( github.com/hashicorp/go-hclog v1.2.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.4.3 // indirect - github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.4.0 // indirect github.com/hashicorp/hc-install v0.3.1 // indirect github.com/hashicorp/hcl/v2 v2.11.1 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-exec v0.16.0 // indirect + github.com/hashicorp/terraform-exec v0.16.1 // indirect github.com/hashicorp/terraform-json v0.13.0 // indirect github.com/hashicorp/terraform-registry-address v0.0.0-20220131103327-5c1c5e123275 // indirect github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect + github.com/huandu/xstrings v1.3.2 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mitchellh/cli v1.1.3 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -58,7 +67,11 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.1.0 // indirect github.com/pkg/errors v0.9.1 // 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.4.1 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect github.com/vmihailenco/tagparser v0.1.2 // indirect @@ -67,7 +80,7 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.31.0 // indirect go.opentelemetry.io/otel v1.6.3 // indirect go.opentelemetry.io/otel/trace v1.6.3 // indirect - golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect + golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect golang.org/x/text v0.3.7 // indirect diff --git a/go.sum b/go.sum index 384e33c..195b9b6 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,14 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI= +github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= @@ -29,8 +37,13 @@ github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/ github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -104,7 +117,10 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -120,13 +136,15 @@ github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBM github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM= github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= @@ -137,10 +155,13 @@ github.com/hashicorp/hcl/v2 v2.11.1 h1:yTyWcXcm9XB0TEkyU/JCRU6rYy4K+mgLtzn2wlrJb github.com/hashicorp/hcl/v2 v2.11.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= 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.16.0 h1:XUh9pJPcbfZsuhReVvmRarQTaiiCnYogFCCjOvEYuug= github.com/hashicorp/terraform-exec v0.16.0/go.mod h1:wB5JHmjxZ/YVNZuv9npAXKmz5pGyxy8PSi0GRR0+YjA= +github.com/hashicorp/terraform-exec v0.16.1 h1:NAwZFJW2L2SaCBVZoVaH8LPImLOGbPLkSHy0IYbs2uE= +github.com/hashicorp/terraform-exec v0.16.1/go.mod h1:aj0lVshy8l+MHhFNoijNHtqTJQI3Xlowv5EOsEaGO7M= github.com/hashicorp/terraform-json v0.13.0 h1:Li9L+lKD1FO5RVFRM1mMMIBDoUHslOniyEi5CM+FWGY= github.com/hashicorp/terraform-json v0.13.0/go.mod h1:y5OdLBCT+rxbwnpxZs9kGL7R9ExU76+cpdY8zHwoazk= +github.com/hashicorp/terraform-plugin-docs v0.7.0 h1:7XKAOYHAxghe7q4/vx468X43X9GikdQ2dxtmcu2gQv0= +github.com/hashicorp/terraform-plugin-docs v0.7.0/go.mod h1:57CICKfW7/KbW4lPhKOledyT6vu1LeAOzuvWXsVaxUE= github.com/hashicorp/terraform-plugin-framework v0.6.1 h1:zUblz+sQ8xEnW0MWWWYRja0mJMabGJig4uJUXSsuY98= github.com/hashicorp/terraform-plugin-framework v0.6.1/go.mod h1:dgISV1z4CKDmi3uu/YpcvHeCSLtaKgena9Ix27tkKIQ= github.com/hashicorp/terraform-plugin-go v0.8.0 h1:MvY43PcDj9VlBjYifBWCO/6j1wf106xU8d5Tob/WRs0= @@ -158,6 +179,10 @@ github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKe github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -181,15 +206,20 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mitchellh/cli v1.1.3 h1:xrX6lWnp1wgXZ65TGY2SB5URdQYcXu6VILdxDf5NttQ= +github.com/mitchellh/cli v1.1.3/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -203,6 +233,7 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -216,17 +247,28 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/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/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -234,6 +276,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -271,13 +314,15 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= diff --git a/main.go b/main.go index 9aa1145..d2f4d27 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,4 @@ +//go:generate tfplugindocs package main import ( @@ -20,5 +21,8 @@ func main() { Debug: debug, } - tfsdk.Serve(ctx, provider.New, opts) + err := tfsdk.Serve(ctx, provider.New, opts) + if err != nil { + panic(err.Error()) + } } diff --git a/pkg/provider/provider_schema.go b/pkg/provider/provider_schema.go index 87fa205..001efa7 100644 --- a/pkg/provider/provider_schema.go +++ b/pkg/provider/provider_schema.go @@ -18,30 +18,39 @@ type ProviderData struct { Organisation types.String `tfsdk:"organisation"` } +const providerDoc = ` +CleverCloud provider allow you to interract with CleverCloud platform. +` + // GetSchema return provider schema func (p *Provider) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { return tfsdk.Schema{ + MarkdownDescription: providerDoc, Attributes: map[string]tfsdk.Attribute{ "endpoint": { - Type: types.StringType, - Optional: true, - Computed: true, + Type: types.StringType, + Optional: true, + Computed: true, + MarkdownDescription: "CleverCloud API endpoint, default to https://api.clever-cloud.com", }, "token": { - Type: types.StringType, - Optional: true, - Computed: true, + Type: types.StringType, + Optional: true, + Computed: true, + MarkdownDescription: "CleverCloud OAuth1 token, can be took from clever-tools after login", }, "secret": { - Type: types.StringType, - Optional: true, - Computed: true, - Sensitive: true, + Type: types.StringType, + Optional: true, + Computed: true, + Sensitive: true, + MarkdownDescription: "CleverCloud OAuth1 secret, can be took from clever-tools after login", }, "organisation": { - Type: types.StringType, - Sensitive: true, - Required: true, + Type: types.StringType, + Sensitive: true, + Required: true, + MarkdownDescription: "CleverCloud organisation, can be either org_xxx, or user_xxx for personal spaces", Validators: []tfsdk.AttributeValidator{ pkg.NewValidatorRegex("valid owner name", regexp.MustCompile(`^(user|org)_.{36}`)), }, diff --git a/pkg/provider/resource_nodejs_crud.go b/pkg/provider/resource_nodejs_crud.go index 3f6ee97..c929868 100644 --- a/pkg/provider/resource_nodejs_crud.go +++ b/pkg/provider/resource_nodejs_crud.go @@ -4,19 +4,20 @@ import ( "context" "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-go/tftypes" "github.com/hashicorp/terraform-plugin-log/tflog" "go.clever-cloud.com/terraform-provider/pkg/tmp" "go.clever-cloud.dev/client" ) -type ResourceNodejsType struct { +type ResourceNodeJS struct { cc *client.Client org string } // Create a new resource -func (r ResourceNodejsType) Create(ctx context.Context, req tfsdk.CreateResourceRequest, resp *tfsdk.CreateResourceResponse) { +func (r ResourceNodeJS) Create(ctx context.Context, req tfsdk.CreateResourceRequest, resp *tfsdk.CreateResourceResponse) { app := NodeJS{} resp.Diagnostics.Append(req.Plan.Get(ctx, &app)...) @@ -25,11 +26,39 @@ func (r ResourceNodejsType) Create(ctx context.Context, req tfsdk.CreateResource } // GET variants - - // GET plans + var version string + var variantID string + productRes := tmp.GetProductInstance(ctx, r.cc) + if productRes.HasError() { + resp.Diagnostics.AddError("failed to get variant", productRes.Error().Error()) + return + } + for _, product := range *productRes.Payload() { + if product.Type != "node" || product.Name != "Node" { + continue + } + + version = product.Version + variantID = product.Variant.ID + break + } + if version == "" || variantID == "" { + resp.Diagnostics.AddError("failed to get variant", "there id no product matching 'node'") + return + } createAppReq := tmp.CreateAppRequest{ - Name: app.Name.Value, + Name: app.Name.Value, + Deploy: "git", + Description: app.Description.Value, + InstanceType: "node", + InstanceVariant: variantID, + InstanceVersion: version, + MinFlavor: app.SmallestFlavor.Value, + MaxFlavor: app.BiggestFlavor.Value, + MinInstances: app.MaxInstanceCount.Value, + MaxInstances: app.MaxInstanceCount.Value, + Zone: app.Region.Value, } res := tmp.CreateApp(ctx, r.cc, r.org, createAppReq) @@ -38,8 +67,12 @@ func (r ResourceNodejsType) Create(ctx context.Context, req tfsdk.CreateResource return } + appRes := res.Payload() // TODO set fields - tflog.Info(ctx, "create response", map[string]interface{}{"plan": res.Payload()}) + tflog.Info(ctx, "create response", map[string]interface{}{"plan": appRes}) + app.ID = fromStr(appRes.ID) + app.DeployURL = fromStr(appRes.DeployURL) + app.VHost = fromStr(appRes.Vhosts[0].Fqdn) resp.Diagnostics.Append(resp.State.Set(ctx, app)...) if resp.Diagnostics.HasError() { @@ -48,23 +81,70 @@ func (r ResourceNodejsType) Create(ctx context.Context, req tfsdk.CreateResource } // Read resource information -func (r ResourceNodejsType) Read(ctx context.Context, req tfsdk.ReadResourceRequest, resp *tfsdk.ReadResourceResponse) { +func (r ResourceNodeJS) Read(ctx context.Context, req tfsdk.ReadResourceRequest, resp *tfsdk.ReadResourceResponse) { + tflog.Debug(ctx, "NodeJS READ", map[string]interface{}{"request": req}) + + var app NodeJS + diags := req.State.Get(ctx, &app) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + appRes := tmp.GetApp(ctx, r.cc, r.org, app.ID.Value) + if appRes.IsNotFoundError() { + diags = resp.State.SetAttribute(ctx, tftypes.NewAttributePath().WithAttributeName("id"), types.String{Unknown: true}) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + } + if appRes.HasError() { + resp.Diagnostics.AddError("failed to get app", appRes.Error().Error()) + } + + appNode := appRes.Payload() + app.DeployURL = fromStr(appNode.DeployURL) + app.VHost = fromStr(appNode.Vhosts[0].Fqdn) + diags = resp.State.Set(ctx, app) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } } // Update resource -func (r ResourceNodejsType) Update(ctx context.Context, req tfsdk.UpdateResourceRequest, resp *tfsdk.UpdateResourceResponse) { +func (r ResourceNodeJS) Update(ctx context.Context, req tfsdk.UpdateResourceRequest, resp *tfsdk.UpdateResourceResponse) { // TODO } // Delete resource -func (r ResourceNodejsType) Delete(ctx context.Context, req tfsdk.DeleteResourceRequest, resp *tfsdk.DeleteResourceResponse) { +func (r ResourceNodeJS) Delete(ctx context.Context, req tfsdk.DeleteResourceRequest, resp *tfsdk.DeleteResourceResponse) { + var app NodeJS + + diags := req.State.Get(ctx, &app) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + tflog.Debug(ctx, "NodeJS DELETE", map[string]interface{}{"app": app}) + + res := tmp.DeleteApp(ctx, r.cc, r.org, app.ID.Value) + if res.IsNotFoundError() { + resp.State.RemoveResource(ctx) + return + } + if res.HasError() { + resp.Diagnostics.AddError("failed to delete app", res.Error().Error()) + return + } - //resp.State.RemoveResource(ctx) + resp.State.RemoveResource(ctx) } // Import resource -func (r ResourceNodejsType) ImportState(ctx context.Context, req tfsdk.ImportResourceStateRequest, resp *tfsdk.ImportResourceStateResponse) { +func (r ResourceNodeJS) ImportState(ctx context.Context, req tfsdk.ImportResourceStateRequest, resp *tfsdk.ImportResourceStateResponse) { // Save the import identifier in the id attribute // and call Read() to fill fields tfsdk.ResourceImportStatePassthroughID(ctx, tftypes.NewAttributePath().WithAttributeName("id"), req, resp) diff --git a/pkg/provider/resource_nodejs_meta.go b/pkg/provider/resource_nodejs_meta.go index 603f0e8..734e26f 100644 --- a/pkg/provider/resource_nodejs_meta.go +++ b/pkg/provider/resource_nodejs_meta.go @@ -18,7 +18,7 @@ func init() { func (r resourceNodejsType) NewResource(ctx context.Context, provider tfsdk.Provider) (tfsdk.Resource, diag.Diagnostics) { p := (provider.(*Provider)) - return ResourcePostgreSQL{ + return ResourceNodeJS{ cc: p.cc, org: p.Organisation, }, nil diff --git a/pkg/provider/resource_nodejs_schema.go b/pkg/provider/resource_nodejs_schema.go index 842716d..3a02673 100644 --- a/pkg/provider/resource_nodejs_schema.go +++ b/pkg/provider/resource_nodejs_schema.go @@ -9,30 +9,161 @@ import ( ) type NodeJS struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - // TODO + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + MinInstanceCount types.Int64 `tfsdk:"min_instance_count"` + MaxInstanceCount types.Int64 `tfsdk:"max_instance_count"` + SmallestFlavor types.String `tfsdk:"smallest_flavor"` + BiggestFlavor types.String `tfsdk:"biggest_flavor"` + BuildFlavor types.String `tfsdk:"build_flavor"` + Region types.String `tfsdk:"region"` + StickySessions types.Bool `tfsdk:"sticky_sessions"` + RedirectHTTPS types.Bool `tfsdk:"redirect_https"` + Commit types.String `tfsdk:"commit"` + VHost types.String `tfsdk:"vhost"` + AdditionalVHosts types.List `tfsdk:"additional_vhosts"` + DeployURL types.String `tfsdk:"deploy_url"` + AppFolder types.String `tfsdk:"app_folder"` + DevDependencies types.Bool `tfsdk:"dev_dependencies"` + StartScript types.String `tfsdk:"start_script"` + PackageManager types.String `tfsdk:"package_manager"` + Registry types.String `tfsdk:"registry"` + RegistryToken types.String `tfsdk:"registry_token"` } +const nodejsDoc = ` +Manage [NodeJS](https://nodejs.org/) applications. + +See [NodeJS product](https://www.clever-cloud.com/nodejs-hosting/) specification. +` + func (r resourceNodejsType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { return tfsdk.Schema{ + MarkdownDescription: nodejsDoc, Attributes: map[string]tfsdk.Attribute{ // customer provided - "name": {Type: types.StringType, Required: true}, - "description": {Type: types.StringType, Required: true}, - "min_flavor": {Type: types.StringType, Optional: true}, - "max_flavor": {Type: types.StringType, Required: true}, - "region": {Type: types.StringType, Required: true}, - "sticky_sessions": {Type: types.BoolType, Optional: true}, - "build_flavor": {Type: types.StringType, Optional: true}, - "redirect_https": {Type: types.BoolType, Optional: true}, - "commit": {Type: types.StringType, Optional: true, Description: "Support either full commit sha or tag"}, - "additional_vhosts": {Type: types.ListType{ElemType: types.StringType}, Computed: true}, - - // provider - "id": {Type: types.StringType, Computed: true}, // for acceptance test retro compat - "deploy_url": {Type: types.StringType, Computed: true}, - "vhost": {Type: types.StringType, Computed: true}, // cleverapps one + + "name": { + Type: types.StringType, + Required: true, + MarkdownDescription: "Application name", + }, + "description": { + Type: types.StringType, + Optional: true, + MarkdownDescription: "Application description", + }, + "min_instance_count": { + Type: types.Int64Type, + Required: true, + MarkdownDescription: "Minimum instance count", + }, + "max_instance_count": { + Type: types.Int64Type, + Required: true, + MarkdownDescription: "Maximum instance count, if different from min value, enable autoscaling", + }, + "smallest_flavor": { + Type: types.StringType, + Required: true, + MarkdownDescription: "Smallest instance flavor", + }, + "biggest_flavor": { + Type: types.StringType, + Required: true, + MarkdownDescription: "Biggest intance flavor, if different from smallest, enable autoscaling", + }, + "build_flavor": { + Type: types.StringType, + Optional: true, + MarkdownDescription: "Use dedicated instance with given flavor for build step", + }, + "region": { + Type: types.StringType, + Required: true, + MarkdownDescription: "Geographical region where the app will be deployed", + }, + "sticky_sessions": { + Type: types.BoolType, + Optional: true, + MarkdownDescription: "Enable sticky sessions, use it when your client sessions are instances scoped", + }, + "redirect_https": { + Type: types.BoolType, + Optional: true, + MarkdownDescription: "Redirect client from plain to TLS port", + }, + "commit": { + Type: types.StringType, + Optional: true, + Description: "Support either ':' or ''", + MarkdownDescription: "Deploy application on the given commit/tag", + }, + "additional_vhosts": { + Type: types.ListType{ElemType: types.StringType}, + Optional: true, + MarkdownDescription: "Add custom hostname in addition to the default one, see [documentation](https://www.clever-cloud.com/doc/administrate/domain-names/)", + }, + // APP_FOLDER + "app_folder": { + Type: types.StringType, + Optional: true, + MarkdownDescription: "Folder in which the application is located (inside the git repository)", + }, + + // Node specifique + + // CC_NODE_DEV_DEPENDENCIES + "dev_dependencies": { + Type: types.BoolType, + Optional: true, + MarkdownDescription: "Install development dependencies specified in package.json", + }, + // CC_RUN_COMMAND + "start_script": { + Type: types.StringType, + Optional: true, + MarkdownDescription: "Set custom start script, instead of `npm start`", + }, + // CC_NODE_BUILD_TOOL / CC_CUSTOM_BUILD_TOOL + "package_manager": { + Type: types.StringType, + Optional: true, + MarkdownDescription: "Either npm, npm-ci, yarn, yarn2 or custom", + }, + // CC_NPM_REGISTRY + "registry": { + Type: types.StringType, + Optional: true, + MarkdownDescription: "The host of your private repository, available values: github or the registry host", + }, + // NPM_TOKEN + "registry_token": { + Type: types.StringType, + Optional: true, + Sensitive: true, + MarkdownDescription: "Private repository token", + }, + + // provider provided + + "id": { + Type: types.StringType, + Computed: true, + MarkdownDescription: "Unique identifier generated during application creation", + }, + "deploy_url": { + Type: types.StringType, + Computed: true, + MarkdownDescription: "Git URL used to push source code", + }, + // cleverapps one + "vhost": { + Type: types.StringType, + Computed: true, + MarkdownDescription: "Default vhost to access your app", + }, }, }, nil } diff --git a/pkg/provider/resource_nodejs_test.go b/pkg/provider/resource_nodejs_test.go index a3dfcba..aeb3a8c 100644 --- a/pkg/provider/resource_nodejs_test.go +++ b/pkg/provider/resource_nodejs_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "regexp" "testing" "time" @@ -15,14 +16,17 @@ import ( const nodejsBlock = `resource "%s" "%s" { name = "%s" - plan = "dev" region = "par" + min_instance_count = 1 + max_instance_count = 2 + smallest_flavor = "XS" + biggest_flavor = "M" } ` func TestAccNodejs_basic(t *testing.T) { rName := fmt.Sprintf("tf-test-node-%d", time.Now().UnixMilli()) - //fullName := fmt.Sprintf("%s.%s", NodejsTypeName, rName) + fullName := fmt.Sprintf("%s.%s", NodejsTypeName, rName) cc := client.New(client.WithAutoOauthConfig()) org := os.Getenv("ORGANISATION") @@ -35,18 +39,18 @@ func TestAccNodejs_basic(t *testing.T) { ProtoV6ProviderFactories: protoV6Provider, CheckDestroy: func(state *terraform.State) error { for _, resource := range state.RootModule().Resources { - res := tmp.GetPostgreSQL(context.Background(), cc, resource.Primary.ID) + res := tmp.GetApp(context.Background(), cc, org, resource.Primary.ID) if res.IsNotFoundError() { continue } if res.HasError() { return fmt.Errorf("unexpectd error: %s", res.Error().Error()) } - if res.Payload().Status == "TO_DELETE" { + if res.Payload().State == "TO_DELETE" { continue } - return fmt.Errorf("expect resource '%s' to be deleted", resource.Primary.ID) + return fmt.Errorf("expect resource '%s' to be deleted state: '%s'", resource.Primary.ID, res.Payload().State) } return nil }, @@ -54,7 +58,11 @@ func TestAccNodejs_basic(t *testing.T) { ResourceName: rName, Config: fmt.Sprintf(providerBlock, org) + fmt.Sprintf(nodejsBlock, NodejsTypeName, rName, rName), - Check: resource.ComposeTestCheckFunc(), + Check: resource.ComposeTestCheckFunc( + resource.TestMatchResourceAttr(fullName, "id", regexp.MustCompile(`^app_.*$`)), + resource.TestMatchResourceAttr(fullName, "deploy_url", regexp.MustCompile(`^git\+ssh.*\.git$`)), + resource.TestCheckResourceAttr(fullName, "region", "par"), + ), }}, }) } diff --git a/pkg/provider/resource_postgresql_crud.go b/pkg/provider/resource_postgresql_crud.go index 32225b8..902b16e 100644 --- a/pkg/provider/resource_postgresql_crud.go +++ b/pkg/provider/resource_postgresql_crud.go @@ -63,9 +63,9 @@ func (r ResourcePostgreSQL) Create(ctx context.Context, req tfsdk.CreateResource return } - pg.ID = types.String{Value: res.Payload().ID} - pg.CreationDate = types.Int64{Value: res.Payload().CreationDate} - pg.Plan = types.String{Value: res.Payload().Plan.Slug} + pg.ID = fromStr(res.Payload().ID) + pg.CreationDate = fromI(res.Payload().CreationDate) + pg.Plan = fromStr(res.Payload().Plan.Slug) tflog.Info(ctx, "create response", map[string]interface{}{"plan": res.Payload()}) resp.Diagnostics.Append(resp.State.Set(ctx, pg)...) @@ -83,11 +83,11 @@ func (r ResourcePostgreSQL) Create(ctx context.Context, req tfsdk.CreateResource tflog.Debug(ctx, "API response", map[string]interface{}{ "payload": fmt.Sprintf("%+v", addonPG), }) - pg.Host = types.String{Value: addonPG.Host} - pg.Port = types.Int64{Value: int64(addonPG.Port)} - pg.Database = types.String{Value: addonPG.Database} - pg.User = types.String{Value: addonPG.User} - pg.Password = types.String{Value: addonPG.Password} + pg.Host = fromStr(addonPG.Host) + pg.Port = fromI(int64(addonPG.Port)) + pg.Database = fromStr(addonPG.Database) + pg.User = fromStr(addonPG.User) + pg.Password = fromStr(addonPG.Password) resp.Diagnostics.Append(resp.State.Set(ctx, pg)...) if resp.Diagnostics.HasError() { @@ -121,14 +121,14 @@ func (r ResourcePostgreSQL) Read(ctx context.Context, req tfsdk.ReadResourceRequ addonPG := addonPGRes.Payload() tflog.Debug(ctx, "STATE", map[string]interface{}{"pg": pg}) tflog.Debug(ctx, "API", map[string]interface{}{"pg": addonPG}) - pg.Plan = types.String{Value: addonPG.Plan} - pg.Region = types.String{Value: addonPG.Zone} + pg.Plan = fromStr(addonPG.Plan) + pg.Region = fromStr(addonPG.Zone) //pg.Name = types.String{Value: addonPG.} - pg.Host = types.String{Value: addonPG.Host} - pg.Port = types.Int64{Value: int64(addonPG.Port)} - pg.Database = types.String{Value: addonPG.Database} - pg.User = types.String{Value: addonPG.User} - pg.Password = types.String{Value: addonPG.Password} + pg.Host = fromStr(addonPG.Host) + pg.Port = fromI(int64(addonPG.Port)) + pg.Database = fromStr(addonPG.Database) + pg.User = fromStr(addonPG.User) + pg.Password = fromStr(addonPG.Password) diags = resp.State.Set(ctx, pg) resp.Diagnostics.Append(diags...) diff --git a/pkg/provider/resource_postgresql_schema.go b/pkg/provider/resource_postgresql_schema.go index 510167e..1a3f0ee 100644 --- a/pkg/provider/resource_postgresql_schema.go +++ b/pkg/provider/resource_postgresql_schema.go @@ -21,22 +21,30 @@ type PostgreSQL struct { Password types.String `tfsdk:"password"` } +const resourcePostgresqlDoc = ` +Manage [PostgreSQL](https://www.postgresql.org/) product. + +See [product specification](https://www.clever-cloud.com/postgresql-hosting/). + +` + func (r resourcePostgresqlType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { return tfsdk.Schema{ + MarkdownDescription: resourcePostgresqlDoc, Attributes: map[string]tfsdk.Attribute{ // customer provided - "name": {Type: types.StringType, Required: true}, - "plan": {Type: types.StringType, Required: true}, - "region": {Type: types.StringType, Required: true}, + "name": {Type: types.StringType, Required: true, MarkdownDescription: "Name of the service"}, + "plan": {Type: types.StringType, Required: true, MarkdownDescription: "Database size and spec"}, + "region": {Type: types.StringType, Required: true, MarkdownDescription: "Geographical region where the database will be deployed"}, // provider - "id": {Type: types.StringType, Computed: true}, // for acceptance test retro compat - "creation_date": {Type: types.Int64Type, Computed: true}, - "host": {Type: types.StringType, Computed: true}, - "port": {Type: types.Int64Type, Computed: true}, - "database": {Type: types.StringType, Computed: true}, - "user": {Type: types.StringType, Computed: true}, - "password": {Type: types.StringType, Computed: true, Sensitive: true}, + "id": {Type: types.StringType, Computed: true, MarkdownDescription: "Generated unique identifier"}, + "creation_date": {Type: types.Int64Type, Computed: true, MarkdownDescription: "Date of database creation"}, + "host": {Type: types.StringType, Computed: true, MarkdownDescription: "Database host, used to connect to"}, + "port": {Type: types.Int64Type, Computed: true, MarkdownDescription: "Database port"}, + "database": {Type: types.StringType, Computed: true, MarkdownDescription: "Database name on the PostgreSQL server"}, + "user": {Type: types.StringType, Computed: true, MarkdownDescription: "Login username"}, + "password": {Type: types.StringType, Computed: true, Sensitive: true, MarkdownDescription: "Login password"}, }, }, nil } diff --git a/pkg/provider/strings.go b/pkg/provider/strings.go new file mode 100644 index 0000000..f7a22e3 --- /dev/null +++ b/pkg/provider/strings.go @@ -0,0 +1,13 @@ +package provider + +import "github.com/hashicorp/terraform-plugin-framework/types" + +// Convert a native string into a tfsdk one +func fromStr(str string) types.String { + return types.String{Value: str} +} + +// Convert a native int64 into a tfsdk one +func fromI(i int64) types.Int64 { + return types.Int64{Value: i} +} diff --git a/pkg/tmp/app.go b/pkg/tmp/app.go index 524298c..98bbe04 100644 --- a/pkg/tmp/app.go +++ b/pkg/tmp/app.go @@ -8,6 +8,7 @@ import ( ) type CreateAppRequest struct { + Name string `json:"name" example:"SOME_NAME"` Deploy string `json:"deploy" example:"git"` Description string `json:"description" example:"SOME_DESC"` InstanceType string `json:"instanceType" example:"node"` @@ -15,9 +16,8 @@ type CreateAppRequest struct { InstanceVersion string `json:"instanceVersion" example:"20220330"` MinFlavor string `json:"minFlavor" example:"pico"` MaxFlavor string `json:"maxFlavor" example:"M"` - MinInstance int64 `json:"minInstances" example:"1"` + MinInstances int64 `json:"minInstances" example:"1"` MaxInstances int64 `json:"maxInstances" example:"4"` - Name string `json:"name" example:"SOME_NAME"` Zone string `json:"zone" example:"par"` } @@ -143,6 +143,57 @@ type BuildFlavor struct { } func CreateApp(ctx context.Context, cc *client.Client, organisationID string, app CreateAppRequest) client.Response[CreatAppResponse] { - path := fmt.Sprintf("/v2/organisation/%s/applications", organisationID) + path := fmt.Sprintf("/v2/organisations/%s/applications", organisationID) return client.Post[CreatAppResponse](ctx, cc, path, app) } + +func GetApp(ctx context.Context, cc *client.Client, organisationID, applicationID string) client.Response[CreatAppResponse] { + path := fmt.Sprintf("/v2/organisations/%s/applications/%s", organisationID, applicationID) + return client.Get[CreatAppResponse](ctx, cc, path) +} + +func DeleteApp(ctx context.Context, cc *client.Client, organisationID, applicationID string) client.Response[interface{}] { + path := fmt.Sprintf("/v2/organisations/%s/applications/%s", organisationID, applicationID) + return client.Delete[interface{}](ctx, cc, path) +} + +func UpdateAppEnv(ctx context.Context, cc *client.Client, organisationID, applicationID, envs map[string]string) client.Response[interface{}] { + path := fmt.Sprintf("/v2/organisations/%s/applications/%s/env", organisationID, applicationID) + return client.Put[interface{}](ctx, cc, path, envs) +} + +type ProductInstance struct { + Type string `json:"type"` + Version string `json:"version"` + Name string `json:"name"` + Variant Variant `json:"variant"` + Description string `json:"description"` + Enabled bool `json:"enabled"` + ComingSoon bool `json:"comingSoon"` + MaxInstances int `json:"maxInstances"` + Tags []string `json:"tags"` + Deployments []string `json:"deployments"` + Flavors []Flavors `json:"flavors"` + DefaultFlavor DefaultFlavor `json:"defaultFlavor"` + BuildFlavor BuildFlavor `json:"buildFlavor"` +} + +type DefaultFlavor struct { + Name string `json:"name"` + Mem int `json:"mem"` + Cpus int `json:"cpus"` + Gpus int `json:"gpus"` + Disk interface{} `json:"disk"` + Price float64 `json:"price"` + Available bool `json:"available"` + Microservice bool `json:"microservice"` + MachineLearning bool `json:"machine_learning"` + Nice int `json:"nice"` + PriceID string `json:"price_id"` + Memory Memory `json:"memory"` +} + +func GetProductInstance(ctx context.Context, cc *client.Client) client.Response[[]ProductInstance] { + path := "/v2/products/instances" + return client.Get[[]ProductInstance](ctx, cc, path) +} diff --git a/tools/tools.go b/tools/tools.go new file mode 100644 index 0000000..f770edf --- /dev/null +++ b/tools/tools.go @@ -0,0 +1,8 @@ +//go:build tools +// +build tools + +package tools + +import ( + _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs" +)