diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..fcadb2cf
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* text eol=lf
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
index 292d119c..aff2f452 100644
--- a/.github/workflows/changelog.yml
+++ b/.github/workflows/changelog.yml
@@ -3,12 +3,13 @@ on:
pull_request:
paths:
- 'vkcs/**'
+ - '!vkcs/**_test.go'
jobs:
error:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- - uses: tj-actions/changed-files@v23.1
+ - uses: tj-actions/changed-files@v35
id: changelog
with:
files: |
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index 1f373474..7918dbb4 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -13,12 +13,12 @@ jobs:
go-mod:
runs-on: ubuntu-latest
steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
- name: Install Go
- uses: actions/setup-go@v2
+ uses: actions/setup-go@v4
with:
go-version: 1.18
- - name: Checkout code
- uses: actions/checkout@v2
- name: Check go mod
run: |
go mod tidy
@@ -28,9 +28,13 @@ jobs:
golangci-lint:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
+ - name: Install Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.18
- name: lint
- uses: golangci/golangci-lint-action@v2.5.2
+ uses: golangci/golangci-lint-action@v3
with:
version: latest
# skip cache because of flaky behaviors
@@ -41,23 +45,22 @@ jobs:
needs: golangci-lint # run after golangci-lint action to not produce duplicated errors
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Install Go
- uses: actions/setup-go@v2
+ uses: actions/setup-go@v4
with:
- go-version: 1.18 # test only the latest go version to speed up CI
+ go-version: 1.18 # test only release go version to speed up CI
- name: Run tests
run: make.exe test
- continue-on-error: true
tests-on-macos:
needs: golangci-lint # run after golangci-lint action to not produce duplicated errors
runs-on: macos-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Install Go
- uses: actions/setup-go@v2
+ uses: actions/setup-go@v4
with:
- go-version: 1.18 # test only the latest go version to speed up CI
+ go-version: 1.18 # test only release go version to speed up CI
- name: Run tests
run: make test
tests-on-unix:
@@ -66,19 +69,13 @@ jobs:
strategy:
matrix:
golang:
- - 1.17
- 1.18
+ - 1.19
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Install Go
- uses: actions/setup-go@v2
+ uses: actions/setup-go@v4
with:
go-version: ${{ matrix.golang }}
- - uses: actions/cache@v2.1.6
- with:
- path: ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ matrix.golang }}-${{ hashFiles('**/go.sum') }}
- restore-keys: |
- ${{ runner.os }}-go-${{ matrix.golang }}-
- name: Run tests
- run: make test
\ No newline at end of file
+ run: make test
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b9dc0fde..4ae18076 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -20,13 +20,13 @@ jobs:
steps:
-
name: Checkout
- uses: actions/checkout@v2.3.4
+ uses: actions/checkout@v3
-
name: Unshallow
run: git fetch --prune --unshallow
-
name: Set up Go
- uses: actions/setup-go@v2
+ uses: actions/setup-go@v4
with:
go-version: 1.18
-
@@ -42,10 +42,10 @@ jobs:
run: CURRENT_TAG=$(git describe --abbrev=0 --match='v*.*.*' --tags); PREVIOUS_TAG=$(git describe --abbrev=0 --exclude="$CURRENT_TAG" --match='v*.*.*' --tags); sed -n -e "0,/#### $CURRENT_TAG/d" -e "/#### $PREVIOUS_TAG/q;p" CHANGELOG.md > release-notes.txt
-
name: Run GoReleaser
- uses: goreleaser/goreleaser-action@v2.5.0
+ uses: goreleaser/goreleaser-action@v4
with:
version: latest
- args: release --rm-dist --release-notes=release-notes.txt
+ args: release --clean --release-notes=release-notes.txt
env:
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
# GitHub sets this automatically
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6db36776..aec9fc84 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,45 @@ description: |-
# VKCS Provider's changelog
-#### v0.1.13 (unreleased)
+#### v0.2.1
+- Support shards/instances/volumes resizing in DB cluster with shards
+- Fix reading state of DB cluster with shards
+
+#### v0.2.0
+- Provide support for Public DNS service
+- Add datasources for DB datastores
+- Add datasources for DB datastore capabilities and configuration parameters
+- Support cloud monitoring for DB instances/clusters
+- Add security_group argument to DB instance/cluster resources
+- Fix searching of shared network with datasource
+
+#### v0.1.16
+- Add config option to run against clouds with old cloud containers API
+
+#### v0.1.15
+- Fix error of incorrect setting a value of resource_vkcs_compute_instance.access_ip_v4 to an empty string
+- Add "subnet_id" argument to resource_vkcs_db_instance.network, resource_vkcs_db_cluster.network, and resource_vkcs_db_cluster_with_shards.shard.network
+- Add a warning that is thrown when arguments "network.fixed_ip_v4" and "replica_of" of resource_vkcs_db_instance are set simultaneously
+- Deprecate "port" argument of resource_vkcs_db_instance.network, resource_vkcs_db_cluster.network, and resource_vkcs_db_cluster_with_shards.shard.network
+- Fix error of not resolving referenced network resources that were created with sdn = "sprut"
+- Deprecate "security_group_ids" argument of resource_vkcs_lb_loadbalancer
+- Add "instances" computed attribute to resource_vkcs_db_cluster_with_shards.shard
+- Add "loadbalancer_id" computed attribute to resource_vkcs_db_cluster
+- Fix error of not expecting "retyping" status when modifying resource_vkcs_blockstorage_volume.volume_type
+- Add vkcs_lb_loadbalancer datasource
+- Make "export_location_path" attribute of data_source_vkcs_sharedfilesystem_share computed
+- Add "export_location_path" computed attribute to resource_vkcs_sharedfilesystem_share
+- Fix error of ignoring "restore_point" argument in resource_vkcs_db_instance and resource_vkcs_db_cluster
+
+#### v0.1.14
+- Add "instances" computed field to resource_vkcs_kubernetes_cluster
+- Add ability to control which cluster instances should remain after shrinking cluster via "shrink_options" field of resource_vkcs_kubernetes_cluster
+- Add "ip" computed field to resource_vkcs_db_instance
+- Allow creation of resource_vkcs_images_image in clouds without s3 support
+- Added description for cluster_node_volume_type labels field in resource_vkcs_kubernetes_cluster
+
+#### v0.1.13
+- Updated description for labels field in resource_vkcs_kubernetes_cluster
- Added conflicts_with property to remote_group_id and remote_ip_prefix fields of resource_vkcs_networking_secgroup_rule
- Added deprecation warning to ethertype field of resource_vkcs_networking_secgroup_rule
- Removed dns_name and dns_domain attributes from resource_vkcs_networking_floatingip
diff --git a/README.md b/README.md
index f3244522..e0c79e48 100755
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ $ terraform plan
Provider development
--------------------
-To start improve it grab the repository, build it and install into local registry repository.
+To start improving grab the repository, build it and install into local registry repository.
Builds for MacOS, Windows and Linux are available.
The example is for MacOS.
```sh
@@ -47,8 +47,18 @@ EOF
$ terraform init
```
+When submitting PR make sure that if golang code has been changed, PR has updates to CHANGELOG.md. Add description of changes under last version with "(unreleased)" mark.
+
+Documenting provider
+--------------------
+To update documentation contents, please, update "description" field of necessary resource/data_source schema and create/modify documentation templates.
+Documentation templates are located in templates/ folder.
+PR with renewed provider documentation is generated automatically when updates are merged into master branch.
+
Publishing provider
-------------------
+Before publishing, remove "(unreleased)" mark from CHANGELOG in separate PR. After this PR is merged, you can publish the provider.
+
Provider publishes via action [release](https://github.com/vk-cs/terraform-provider-vkcs/blob/master/.github/workflows/release.yml).
To call the action create new tag.
```sh
diff --git a/automation b/automation
index 0900d7ee..3169db7e 160000
--- a/automation
+++ b/automation
@@ -1 +1 @@
-Subproject commit 0900d7ee902b95884a7e93efbd181cbac07bdbd5
+Subproject commit 3169db7e6739e7cca263fdbf9ab2b5c7e7426ebe
diff --git a/docs/data-sources/vkcs_blockstorage_snapshot.md b/docs/data-sources/vkcs_blockstorage_snapshot.md
index 339133a1..b5819454 100644
--- a/docs/data-sources/vkcs_blockstorage_snapshot.md
+++ b/docs/data-sources/vkcs_blockstorage_snapshot.md
@@ -31,16 +31,7 @@ data "vkcs_blockstorage_snapshot" "snapshot_1" {
## Attributes Reference
-- `most_recent` **Boolean** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
-- `volume_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `description` **String** The snapshot's description.
- `id` **String** ID of the resource.
diff --git a/docs/data-sources/vkcs_blockstorage_volume.md b/docs/data-sources/vkcs_blockstorage_volume.md
index fdf85be2..4b0fe33b 100644
--- a/docs/data-sources/vkcs_blockstorage_volume.md
+++ b/docs/data-sources/vkcs_blockstorage_volume.md
@@ -32,18 +32,7 @@ data "vkcs_blockstorage_volume" "volume_1" {
## Attributes Reference
-- `bootable` **String** See Argument Reference above.
-
-- `metadata` Map of **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
-- `volume_type` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `availability_zone` **String** The name of the availability zone of the volume.
- `id` **String** ID of the resource.
diff --git a/docs/data-sources/vkcs_compute_availability_zones.md b/docs/data-sources/vkcs_compute_availability_zones.md
index 77571e45..705c083e 100644
--- a/docs/data-sources/vkcs_compute_availability_zones.md
+++ b/docs/data-sources/vkcs_compute_availability_zones.md
@@ -22,10 +22,7 @@ data "vkcs_compute_availability_zones" "zones" {}
## Attributes Reference
-- `region` **String** See Argument Reference above.
-
-- `state` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** Hash of the returned zone list.
- `names` **String** The names of the availability zones, ordered alphanumerically, that match the queried `state`
diff --git a/docs/data-sources/vkcs_compute_flavor.md b/docs/data-sources/vkcs_compute_flavor.md
index 3ce76081..70ba5962 100644
--- a/docs/data-sources/vkcs_compute_flavor.md
+++ b/docs/data-sources/vkcs_compute_flavor.md
@@ -43,28 +43,7 @@ data "vkcs_compute_flavor" "small" {
## Attributes Reference
-- `disk` **Number** See Argument Reference above.
-
-- `flavor_id` **String** See Argument Reference above.
-
-- `is_public` **Boolean** See Argument Reference above.
-
-- `min_disk` **Number** See Argument Reference above.
-
-- `min_ram` **Number** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `ram` **Number** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `rx_tx_factor` **Number** See Argument Reference above.
-
-- `swap` **Number** See Argument Reference above.
-
-- `vcpus` **Number** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `extra_specs` Map of **String** Key/Value pairs of metadata for the flavor.
- `id` **String** ID of the found flavor.
diff --git a/docs/data-sources/vkcs_compute_instance.md b/docs/data-sources/vkcs_compute_instance.md
index 4eb7020d..226a25f6 100644
--- a/docs/data-sources/vkcs_compute_instance.md
+++ b/docs/data-sources/vkcs_compute_instance.md
@@ -27,12 +27,7 @@ data "vkcs_compute_instance" "instance" {
## Attributes Reference
-- `id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `user_data` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `access_ip_v4` **String** The first IPv4 address assigned to this server.
- `availability_zone` **String** The availability zone of this server.
diff --git a/docs/data-sources/vkcs_compute_keypair.md b/docs/data-sources/vkcs_compute_keypair.md
index 74a07826..68c60ad1 100644
--- a/docs/data-sources/vkcs_compute_keypair.md
+++ b/docs/data-sources/vkcs_compute_keypair.md
@@ -24,10 +24,7 @@ data "vkcs_compute_keypair" "kp" {
## Attributes Reference
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `fingerprint` **String** The fingerprint of the OpenSSH key.
- `id` **String** ID of the resource.
diff --git a/docs/data-sources/vkcs_compute_quotaset.md b/docs/data-sources/vkcs_compute_quotaset.md
index e30274fd..7f81981f 100644
--- a/docs/data-sources/vkcs_compute_quotaset.md
+++ b/docs/data-sources/vkcs_compute_quotaset.md
@@ -24,10 +24,7 @@ data "vkcs_compute_quotaset" "quota" {
## Attributes Reference
-- `project_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `cores` **Number** The number of allowed server cores.
- `id` **String** ID of the resource.
diff --git a/docs/data-sources/vkcs_db_backup.md b/docs/data-sources/vkcs_db_backup.md
index e48d8882..459026f1 100644
--- a/docs/data-sources/vkcs_db_backup.md
+++ b/docs/data-sources/vkcs_db_backup.md
@@ -24,10 +24,7 @@ data "vkcs_db_backup" "db-backup" {
## Attributes Reference
-- `backup_id` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `created` **String** Backup creation timestamp
- `datastore` **Object** Object that represents datastore of backup
@@ -42,7 +39,7 @@ data "vkcs_db_backup" "db-backup" {
- `meta` **String** Metadata of the backup
-- `name` **String** The name of the backup.
+- `name` **String** The name of the backup1.
- `size` **Number** Backup's volume size
diff --git a/docs/data-sources/vkcs_db_config_group.md b/docs/data-sources/vkcs_db_config_group.md
index 9dcf9fb8..dd1b7c83 100644
--- a/docs/data-sources/vkcs_db_config_group.md
+++ b/docs/data-sources/vkcs_db_config_group.md
@@ -23,8 +23,7 @@ data "vkcs_db_config_group" "db-config-group" {
## Attributes Reference
-- `config_group_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `created` **String** Timestamp of config group's creation.
- `datastore` **Object** Object that represents datastore of backup
diff --git a/docs/data-sources/vkcs_db_database.md b/docs/data-sources/vkcs_db_database.md
index c3af9fa8..1b2765fd 100644
--- a/docs/data-sources/vkcs_db_database.md
+++ b/docs/data-sources/vkcs_db_database.md
@@ -30,14 +30,5 @@ data "vkcs_db_database" "db-database" {
## Attributes Reference
-- `id` **String** See Argument Reference above.
-
-- `charset` **String** See Argument Reference above.
-
-- `collate` **String** See Argument Reference above.
-
-- `dbms_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
+No additional attributes are exported.
diff --git a/docs/data-sources/vkcs_db_datastore.md b/docs/data-sources/vkcs_db_datastore.md
new file mode 100644
index 00000000..9bcb9429
--- /dev/null
+++ b/docs/data-sources/vkcs_db_datastore.md
@@ -0,0 +1,45 @@
+---
+layout: "vkcs"
+page_title: "vkcs: vkcs_db_datastore"
+description: |-
+ Get information on a VKCS db datastore.
+---
+
+# vkcs_db_datastore
+
+Use this data source to get information on a VKCS db datastore. **New since v.0.2.0**.
+
+## Example Usage
+
+```terraform
+data "vkcs_db_datastore" "datastore" {
+ name = "mysql"
+}
+
+output "mysql_versions" {
+ value = data.vkcs_db_datastore.datastore.versions
+ description = "List of versions of MySQL that are available within VKCS."
+}
+```
+
+## Argument Reference
+- `id` **String** (*Optional*) The id of the datastore.
+
+- `name` **String** (*Optional*) The name of the datastore.
+
+- `region` **String** (*Optional*) The `region` to fetch availability zones from, defaults to the provider's `region`
+
+
+## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
+- `cluster_volume_types` **String** Supported volume types for the datastore when used in a cluster.
+
+- `minimum_cpu` **Number** Minimum CPU required for instance of the datastore.
+
+- `minimum_ram` **Number** Minimum RAM required for instance of the datastore.
+
+- `versions` **Object** Versions of the datastore.
+
+- `volume_types` **String** Supported volume types for the datastore.
+
+
diff --git a/docs/data-sources/vkcs_db_datastore_capabilities.md b/docs/data-sources/vkcs_db_datastore_capabilities.md
new file mode 100644
index 00000000..5934b0b1
--- /dev/null
+++ b/docs/data-sources/vkcs_db_datastore_capabilities.md
@@ -0,0 +1,40 @@
+---
+layout: "vkcs"
+page_title: "vkcs: vkcs_db_datastore_capabilities"
+description: |-
+ Get information on capabilities supported for a VKCS db datastore.
+---
+
+# vkcs_db_datastore_capabilities
+
+Use this data source to get capabilities supported for a VKCS datastore. **New since v.0.2.0**.
+
+## Example Usage
+
+```terraform
+data "vkcs_db_datastore_capabilities" "postgres_caps" {
+ datastore_name = data.vkcs_db_datastore.postgres
+ datastore_version_id = local.pg_v14_version_id
+}
+
+output "postgresql_capabilities" {
+ value = data.vkcs_db_datastore_capabilities.postgres_caps.capabilities
+ description = "Available capabilities of the latest version of PostgreSQL datastore."
+}
+```
+
+## Argument Reference
+- `datastore_name` **String** (***Required***) Name of the data store.
+
+- `datastore_version_id` **String** (***Required***) ID of the version of the data store.
+
+- `region` **String** (*Optional*) The `region` to fetch availability zones from, defaults to the provider's `region`.
+
+
+## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
+- `capabilities` **Object** Versions of the datastore.
+
+- `id` **String** ID of the resource.
+
+
diff --git a/docs/data-sources/vkcs_db_datastore_parameters.md b/docs/data-sources/vkcs_db_datastore_parameters.md
new file mode 100644
index 00000000..8d80bb46
--- /dev/null
+++ b/docs/data-sources/vkcs_db_datastore_parameters.md
@@ -0,0 +1,40 @@
+---
+layout: "vkcs"
+page_title: "vkcs: vkcs_db_datastore_parameters"
+description: |-
+ Get information on configuration parameters supported for a VKCS db datastore.
+---
+
+# vkcs_db_datastore_parameters
+
+Use this data source to get configuration parameters supported for a VKCS datastore. **New since v.0.2.0**.
+
+## Example Usage
+
+```terraform
+data "vkcs_db_datastore_parameters" "mysql_params" {
+ datastore_name = data.vkcs_db_datastore.mysql
+ datastore_version_id = local.mysql_v8_version_id
+}
+
+output "mysql_parameters" {
+ value = data.vkcs_db_datastore_parameters.mysql_params.parameters
+ description = "Available configuration parameters of the latest version of MySQL datastore."
+}
+```
+
+## Argument Reference
+- `datastore_name` **String** (***Required***) Name of the data store.
+
+- `datastore_version_id` **String** (***Required***) ID of the version of the data store.
+
+- `region` **String** (*Optional*) The `region` to fetch availability zones from, defaults to the provider's `region`.
+
+
+## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
+- `id` **String** ID of the resource.
+
+- `parameters` **Object** Versions of the datastore.
+
+
diff --git a/docs/data-sources/vkcs_db_datastores.md b/docs/data-sources/vkcs_db_datastores.md
new file mode 100644
index 00000000..46d5442e
--- /dev/null
+++ b/docs/data-sources/vkcs_db_datastores.md
@@ -0,0 +1,33 @@
+---
+layout: "vkcs"
+page_title: "vkcs: vkcs_db_datastores"
+description: |-
+ Get information on db datastores that are available within VKCS.
+---
+
+# vkcs_db_datastores
+
+Use this data source to get a list of datastores from VKCS. **New since v.0.2.0**.
+
+## Example Usage
+
+```terraform
+data "vkcs_db_datastores" "datastores" {}
+
+output "available_datastores" {
+ value = data.vkcs_db_datastores.datastores.datastores
+ description = "List of datastores that are available within VKCS."
+}
+```
+
+## Argument Reference
+- `region` **String** (*Optional*) The `region` to fetch availability zones from, defaults to the provider's `region`
+
+
+## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
+- `datastores` **Object**
+
+- `id` **String** ID of the resource.
+
+
diff --git a/docs/data-sources/vkcs_db_instance.md b/docs/data-sources/vkcs_db_instance.md
index e506decf..df3185f2 100644
--- a/docs/data-sources/vkcs_db_instance.md
+++ b/docs/data-sources/vkcs_db_instance.md
@@ -59,43 +59,5 @@ data "vkcs_db_instance" "db-instance" {
## Attributes Reference
-- `id` **String** See Argument Reference above.
-
-- `backup_schedule` See Argument Reference above.
- - `interval_hours` **Number** See Argument Reference above.
-
- - `keep_count` **Number** See Argument Reference above.
-
- - `name` **String** See Argument Reference above.
-
- - `start_hours` **Number** See Argument Reference above.
-
- - `start_minutes` **Number** See Argument Reference above.
-
-- `datastore` See Argument Reference above.
- - `type` **String** See Argument Reference above.
-
- - `version` **String** See Argument Reference above.
-
-- `flavor_id` **String** See Argument Reference above.
-
-- `hostname` **String** See Argument Reference above.
-
-- `ip` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
-- `volume` See Argument Reference above.
- - `size` **Number** See Argument Reference above.
-
- - `used` **Number** See Argument Reference above.
-
- - `volume_id` **String** See Argument Reference above.
-
- - `volume_type` **String** See Argument Reference above.
-
+No additional attributes are exported.
diff --git a/docs/data-sources/vkcs_db_user.md b/docs/data-sources/vkcs_db_user.md
index 14b2e093..6e5af908 100644
--- a/docs/data-sources/vkcs_db_user.md
+++ b/docs/data-sources/vkcs_db_user.md
@@ -32,16 +32,5 @@ data "vkcs_db_user" "db-user" {
## Attributes Reference
-- `id` **String** See Argument Reference above.
-
-- `databases` **String** See Argument Reference above.
-
-- `dbms_id` **String** See Argument Reference above.
-
-- `host` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `password` **String** See Argument Reference above.
-
+No additional attributes are exported.
diff --git a/docs/data-sources/vkcs_images_image.md b/docs/data-sources/vkcs_images_image.md
index e7ecda76..67c32693 100644
--- a/docs/data-sources/vkcs_images_image.md
+++ b/docs/data-sources/vkcs_images_image.md
@@ -45,26 +45,7 @@ data "vkcs_images_image" "ubuntu" {
## Attributes Reference
-- `member_status` **String** See Argument Reference above.
-
-- `most_recent` **Boolean** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `owner` **String** See Argument Reference above.
-
-- `properties` Map of **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `size_max` **Number** See Argument Reference above.
-
-- `size_min` **Number** See Argument Reference above.
-
-- `tag` **String** See Argument Reference above.
-
-- `visibility` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `checksum` **String** The checksum of the data associated with the image.
- `container_format` **String** The format of the image's container.
diff --git a/docs/data-sources/vkcs_keymanager_container.md b/docs/data-sources/vkcs_keymanager_container.md
index 8e6664e7..ccf4d2ed 100644
--- a/docs/data-sources/vkcs_keymanager_container.md
+++ b/docs/data-sources/vkcs_keymanager_container.md
@@ -24,10 +24,7 @@ data "vkcs_keymanager_container" "example" {
## Attributes Reference
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `acl` **Object** The list of ACLs assigned to a container.
- `consumers` **Object** The list of the container consumers.
diff --git a/docs/data-sources/vkcs_keymanager_secret.md b/docs/data-sources/vkcs_keymanager_secret.md
index edccdd2a..95afbe81 100644
--- a/docs/data-sources/vkcs_keymanager_secret.md
+++ b/docs/data-sources/vkcs_keymanager_secret.md
@@ -43,26 +43,7 @@ data "vkcs_keymanager_secret" "example" {
## Attributes Reference
-- `acl_only` **Boolean** See Argument Reference above.
-
-- `algorithm` **String** See Argument Reference above.
-
-- `bit_length` **Number** See Argument Reference above.
-
-- `created_at_filter` **String** See Argument Reference above.
-
-- `expiration_filter` **String** See Argument Reference above.
-
-- `mode` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `secret_type` **String** See Argument Reference above.
-
-- `updated_at_filter` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `acl` **Object** The list of ACLs assigned to a secret.
- `content_types` Map of **String** The map of the content types, assigned on the secret.
diff --git a/docs/data-sources/vkcs_kubernetes_cluster.md b/docs/data-sources/vkcs_kubernetes_cluster.md
index 842e473b..61c75ffd 100755
--- a/docs/data-sources/vkcs_kubernetes_cluster.md
+++ b/docs/data-sources/vkcs_kubernetes_cluster.md
@@ -32,14 +32,7 @@ data "vkcs_kubernetes_cluster" "mycluster" {
## Attributes Reference
-- `cluster_id` **String** See Argument Reference above.
-
-- `dns_domain` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `api_address` **String** COE API address.
- `api_lb_fip` **String** API LoadBalancer fip.
diff --git a/docs/data-sources/vkcs_kubernetes_clustertemplate.md b/docs/data-sources/vkcs_kubernetes_clustertemplate.md
index 9cca559c..f992b0d0 100755
--- a/docs/data-sources/vkcs_kubernetes_clustertemplate.md
+++ b/docs/data-sources/vkcs_kubernetes_clustertemplate.md
@@ -40,14 +40,7 @@ output "example_template_id" {
## Attributes Reference
-- `cluster_template_uuid` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `version` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `apiserver_port` **Number** The API server port for the Container Orchestration Engine for this cluster template.
- `cluster_distro` **String** The distro for the cluster (fedora-atomic, coreos, etc.).
diff --git a/docs/data-sources/vkcs_kubernetes_clustertemplates.md b/docs/data-sources/vkcs_kubernetes_clustertemplates.md
index 71fa2733..659ce329 100755
--- a/docs/data-sources/vkcs_kubernetes_clustertemplates.md
+++ b/docs/data-sources/vkcs_kubernetes_clustertemplates.md
@@ -18,6 +18,7 @@ data "vkcs_kubernetes_clustertemplates" "templates" {}
## Argument Reference
## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
- `cluster_templates` **Object** A list of available kubernetes cluster templates.
- `cluster_template_uuid` **String** The UUID of the cluster template.
diff --git a/docs/data-sources/vkcs_kubernetes_node_group.md b/docs/data-sources/vkcs_kubernetes_node_group.md
index f215dacb..add17c2d 100755
--- a/docs/data-sources/vkcs_kubernetes_node_group.md
+++ b/docs/data-sources/vkcs_kubernetes_node_group.md
@@ -38,26 +38,7 @@ data "vkcs_kubernetes_node_group" "mynodegroup" {
## Attributes Reference
-- `uuid` **String** See Argument Reference above.
-
-- `autoscaling_enabled` **Boolean** See Argument Reference above.
-
-- `flavor_id` **String** See Argument Reference above.
-
-- `max_node_unavailable` **Number** See Argument Reference above.
-
-- `max_nodes` **Number** See Argument Reference above.
-
-- `min_nodes` **Number** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `node_count` **Number** See Argument Reference above.
-
-- `volume_size` **Number** See Argument Reference above.
-
-- `volume_type` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `availability_zones` **String** The list of availability zones of the node group.
- `cluster_id` **String** The UUID of cluster that node group belongs.
diff --git a/docs/data-sources/vkcs_lb_loadbalancer.md b/docs/data-sources/vkcs_lb_loadbalancer.md
new file mode 100644
index 00000000..ed9a2912
--- /dev/null
+++ b/docs/data-sources/vkcs_lb_loadbalancer.md
@@ -0,0 +1,48 @@
+---
+layout: "vkcs"
+page_title: "vkcs: vkcs_lb_loadbalancer"
+description: |-
+ Get information on a VKCS Loadbalancer
+---
+
+# vkcs_lb_loadbalancer
+
+Use this data source to get the details of a loadbalancer
+
+## Example Usage
+
+```terraform
+data "vkcs_lb_loadbalancer" "loadbalancer" {
+ id = "35082f6e-14c4-478c-ba4c-77bcdb222743"
+}
+```
+
+## Argument Reference
+- `id` **String** (***Required***) The UUID of the Loadbalancer
+
+- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used.
+
+
+## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
+- `admin_state_up` **Boolean** The administrative state of the Loadbalancer.
+
+- `availability_zone` **String** The availability zone of the Loadbalancer.
+
+- `description` **String** Human-readable description of the Loadbalancer.
+
+- `name` **String** The name of the Loadbalancer.
+
+- `security_group_ids` Set of **String** A list of security group IDs applied to the Loadbalancer.
+
+- `tags` Set of **String** A list of simple strings assigned to the loadbalancer.
+
+- `vip_address` **String** The ip address of the Loadbalancer.
+
+- `vip_network_id` **String** The network on which to allocate the Loadbalancer's address. A tenant can only create Loadbalancers on networks authorized by policy (e.g. networks that belong to them or networks that are shared). Changing this creates a new loadbalancer.
+
+- `vip_port_id` **String** The port UUID of the Loadbalancer.
+
+- `vip_subnet_id` **String** The subnet on which the Loadbalancer's address is allocated.
+
+
diff --git a/docs/data-sources/vkcs_networking_floatingip.md b/docs/data-sources/vkcs_networking_floatingip.md
index 9a1d59f0..8404f818 100644
--- a/docs/data-sources/vkcs_networking_floatingip.md
+++ b/docs/data-sources/vkcs_networking_floatingip.md
@@ -38,24 +38,7 @@ data "vkcs_networking_floatingip" "floatingip_1" {
## Attributes Reference
-- `address` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `fixed_ip` **String** See Argument Reference above.
-
-- `pool` **String** See Argument Reference above.
-
-- `port_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
-- `tenant_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the found floating IP.
diff --git a/docs/data-sources/vkcs_networking_network.md b/docs/data-sources/vkcs_networking_network.md
index c5658957..74cd0624 100644
--- a/docs/data-sources/vkcs_networking_network.md
+++ b/docs/data-sources/vkcs_networking_network.md
@@ -42,28 +42,7 @@ data "vkcs_networking_network" "network" {
## Attributes Reference
-- `description` **String** See Argument Reference above.
-
-- `external` **Boolean** See Argument Reference above.
-
-- `matching_subnet_cidr` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `network_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `tenant_id` **String** See Argument Reference above.
-
-- `vkcs_services_access` **Boolean** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `admin_state_up` **String** The administrative state of the network.
- `all_tags` Set of **String** The set of string tags applied on the network.
diff --git a/docs/data-sources/vkcs_networking_port.md b/docs/data-sources/vkcs_networking_port.md
index 349f08fe..61ac2766 100644
--- a/docs/data-sources/vkcs_networking_port.md
+++ b/docs/data-sources/vkcs_networking_port.md
@@ -54,40 +54,7 @@ data "vkcs_networking_port" "port_1" {
## Attributes Reference
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `device_id` **String** See Argument Reference above.
-
-- `device_owner` **String** See Argument Reference above.
-
-- `dns_name` **String** See Argument Reference above.
-
-- `fixed_ip` **String** See Argument Reference above.
-
-- `mac_address` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `network_id` **String** See Argument Reference above.
-
-- `port_id` **String** See Argument Reference above.
-
-- `project_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `security_group_ids` Set of **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `tenant_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_fixed_ips` **String** The collection of Fixed IP addresses on the port in the order returned by the Network v2 API.
- `all_security_group_ids` Set of **String** The set of security group IDs applied on the port.
diff --git a/docs/data-sources/vkcs_networking_router.md b/docs/data-sources/vkcs_networking_router.md
index 42393ed6..0a5e7b04 100644
--- a/docs/data-sources/vkcs_networking_router.md
+++ b/docs/data-sources/vkcs_networking_router.md
@@ -40,26 +40,7 @@ data "vkcs_networking_router" "router" {
## Attributes Reference
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `enable_snat` **Boolean** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `router_id` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `tenant_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_tags` Set of **String** The set of string tags applied on the router.
- `external_network_id` **String** The network UUID of an external gateway for the router.
diff --git a/docs/data-sources/vkcs_networking_secgroup.md b/docs/data-sources/vkcs_networking_secgroup.md
index f207384e..d44e3aaa 100644
--- a/docs/data-sources/vkcs_networking_secgroup.md
+++ b/docs/data-sources/vkcs_networking_secgroup.md
@@ -34,20 +34,7 @@ data "vkcs_networking_secgroup" "secgroup" {
## Attributes Reference
-- `description` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `secgroup_id` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `tenant_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_tags` Set of **String** The set of string tags applied on the security group.
- `id` **String** ID of the found security group.
diff --git a/docs/data-sources/vkcs_networking_subnet.md b/docs/data-sources/vkcs_networking_subnet.md
index 3bb4b1f6..5f3aedc1 100644
--- a/docs/data-sources/vkcs_networking_subnet.md
+++ b/docs/data-sources/vkcs_networking_subnet.md
@@ -44,30 +44,7 @@ data "vkcs_networking_subnet" "subnet_1" {
## Attributes Reference
-- `cidr` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `dhcp_enabled` **Boolean** See Argument Reference above.
-
-- `gateway_ip` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `network_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `subnet_id` **String** See Argument Reference above.
-
-- `subnetpool_id` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `tenant_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_tags` Set of **String** A set of string tags applied on the subnet.
- `allocation_pools` **Object** Allocation pools of the subnet.
diff --git a/docs/data-sources/vkcs_publicdns_zone.md b/docs/data-sources/vkcs_publicdns_zone.md
new file mode 100644
index 00000000..9a70def2
--- /dev/null
+++ b/docs/data-sources/vkcs_publicdns_zone.md
@@ -0,0 +1,46 @@
+---
+layout: "vkcs"
+page_title: "vkcs: vkcs_publicdns_zone"
+description: |-
+ Get information on a public DNS zone.
+---
+
+# vkcs_publicdns_zone
+
+Use this data source to get the ID of a VKCS public DNS zone. **New since v.0.2.0**.
+
+## Example Usage
+
+```terraform
+data "vkcs_publicdns_zone" "zone" {
+ zone = "example.com"
+}
+```
+
+## Argument Reference
+- `admin_email` **String** (*Optional*) The admin email of the zone SOA.
+
+- `expire` **Number** (*Optional*) The expire time of the zone SOA.
+
+- `id` **String** (*Optional*) The UUID of the DNS zone.
+
+- `primary_dns` **String** (*Optional*) The primary DNS of the zone SOA.
+
+- `refresh` **Number** (*Optional*) The refresh time of the zone SOA.
+
+- `region` **String** (*Optional*) The region in which to obtain the V2 Public DNS client. If omitted, the `region` argument of the provider is used.
+
+- `retry` **Number** (*Optional*) The retry time of the zone SOA.
+
+- `serial` **Number** (*Optional*) The serial number of the zone SOA.
+
+- `status` **String** (*Optional*) The status of the zone.
+
+- `ttl` **Number** (*Optional*) The TTL (time to live) of the zone SOA.
+
+- `zone` **String** (*Optional*) The name of the zone.
+
+
+## Attributes Reference
+No additional attributes are exported.
+
diff --git a/docs/data-sources/vkcs_region.md b/docs/data-sources/vkcs_region.md
index b08b2add..53cc7919 100755
--- a/docs/data-sources/vkcs_region.md
+++ b/docs/data-sources/vkcs_region.md
@@ -22,8 +22,7 @@ data "vkcs_region" "current" {}
## Attributes Reference
-- `id` **String** ID of the region to learn or use. Use empty value to learn current region on the provider.
-
+In addition to all arguments above, the following attributes are exported:
- `description` **String** Description of the region.
- `parent_region` **String** Parent of the region.
diff --git a/docs/data-sources/vkcs_regions.md b/docs/data-sources/vkcs_regions.md
index b8b400c8..f58ca072 100755
--- a/docs/data-sources/vkcs_regions.md
+++ b/docs/data-sources/vkcs_regions.md
@@ -26,6 +26,7 @@ data "vkcs_regions" "current" {
## Argument Reference
## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
- `id` **String** Random identifier of the data source.
- `names` Set of **String** Names of regions that meets the criteria.
diff --git a/docs/data-sources/vkcs_sharedfilesystem_share.md b/docs/data-sources/vkcs_sharedfilesystem_share.md
index 9ea3b572..1beb0ef8 100644
--- a/docs/data-sources/vkcs_sharedfilesystem_share.md
+++ b/docs/data-sources/vkcs_sharedfilesystem_share.md
@@ -34,20 +34,7 @@ data "vkcs_sharedfilesystem_share" "share_1" {
## Attributes Reference
-- `share_network_id` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `export_location_path` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `snapshot_id` **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `availability_zone` **String** The share availability zone.
- `id` **String** ID of the resource.
diff --git a/docs/data-sources/vkcs_sharedfilesystem_sharenetwork.md b/docs/data-sources/vkcs_sharedfilesystem_sharenetwork.md
index 3dd20a02..31f8b77c 100644
--- a/docs/data-sources/vkcs_sharedfilesystem_sharenetwork.md
+++ b/docs/data-sources/vkcs_sharedfilesystem_sharenetwork.md
@@ -32,18 +32,7 @@ data "vkcs_sharedfilesystem_sharenetwork" "sharenetwork_1" {
## Attributes Reference
-- `description` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `neutron_net_id` **String** See Argument Reference above.
-
-- `neutron_subnet_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `security_service_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `cidr` **String** The share network CIDR.
- `id` **String** ID of the resource.
diff --git a/docs/index.md b/docs/index.md
index 4834dc74..fd796417 100755
--- a/docs/index.md
+++ b/docs/index.md
@@ -49,6 +49,9 @@ provider "vkcs" {
## Argument Reference
- `auth_url` **String** (*Optional*) The Identity authentication URL.
+- `cloud_containers_api_version` **String** (*Optional*) Cloud Containers API version to use.
+_NOTE_ Only for custom VKCS deployments.
+
- `password` **String** (*Optional* Sensitive) Password to login with.
- `project_id` **String** (*Optional*) The ID of Project to login with.
diff --git a/docs/resources/vkcs_blockstorage_snapshot.md b/docs/resources/vkcs_blockstorage_snapshot.md
index 7914a1d6..a5074275 100644
--- a/docs/resources/vkcs_blockstorage_snapshot.md
+++ b/docs/resources/vkcs_blockstorage_snapshot.md
@@ -47,18 +47,7 @@ resource "vkcs_blockstorage_snapshot" "snapshot" {
## Attributes Reference
-- `volume_id` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `force` **Boolean** See Argument Reference above.
-
-- `metadata` Map of **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String**
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_blockstorage_volume.md b/docs/resources/vkcs_blockstorage_volume.md
index d1a48b17..2f98aa01 100644
--- a/docs/resources/vkcs_blockstorage_volume.md
+++ b/docs/resources/vkcs_blockstorage_volume.md
@@ -46,26 +46,7 @@ resource "vkcs_blockstorage_volume" "volume" {
## Attributes Reference
-- `availability_zone` **String** See Argument Reference above.
-
-- `size` **Number** See Argument Reference above.
-
-- `volume_type` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `image_id` **String** See Argument Reference above.
-
-- `metadata` Map of **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `snapshot_id` **String** See Argument Reference above.
-
-- `source_vol_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_compute_floatingip_associate.md b/docs/resources/vkcs_compute_floatingip_associate.md
index 4bc519f6..70c41d4e 100644
--- a/docs/resources/vkcs_compute_floatingip_associate.md
+++ b/docs/resources/vkcs_compute_floatingip_associate.md
@@ -71,16 +71,7 @@ resource "vkcs_compute_floatingip_associate" "fip_1" {
## Attributes Reference
-- `floating_ip` **String** See Argument Reference above.
-
-- `instance_id` **String** See Argument Reference above.
-
-- `fixed_ip` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `wait_until_associated` **Boolean** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_compute_instance.md b/docs/resources/vkcs_compute_instance.md
index 3f807123..23051207 100755
--- a/docs/resources/vkcs_compute_instance.md
+++ b/docs/resources/vkcs_compute_instance.md
@@ -412,97 +412,16 @@ resource "vkcs_compute_instance" "instance_1" {
## Attributes Reference
-- `name` **String** See Argument Reference above.
-
-- `access_ip_v4` **String** See Argument Reference above.
-
-- `admin_pass` **String** See Argument Reference above.
-
-- `availability_zone` **String** See Argument Reference above.
-
-- `block_device` See Argument Reference above.
- - `source_type` **String** See Argument Reference above.
-
- - `boot_index` **Number** See Argument Reference above.
-
- - `delete_on_termination` **Boolean** See Argument Reference above.
-
- - `destination_type` **String** See Argument Reference above.
-
- - `device_type` **String** See Argument Reference above.
-
- - `disk_bus` **String** See Argument Reference above.
-
- - `guest_format` **String** See Argument Reference above.
-
- - `uuid` **String** See Argument Reference above.
-
- - `volume_size` **Number** See Argument Reference above.
-
- - `volume_type` **String** See Argument Reference above.
-
-- `config_drive` **Boolean** See Argument Reference above.
-
-- `flavor_id` **String** See Argument Reference above.
-
-- `flavor_name` **String** See Argument Reference above.
-
-- `force_delete` **Boolean** See Argument Reference above.
-
-- `image_id` **String** See Argument Reference above.
-
-- `image_name` **String** See Argument Reference above.
-
-- `key_pair` **String** See Argument Reference above.
-
-- `metadata` Map of **String** See Argument Reference above.
-
-- `network` See Argument Reference above.
- - `access_network` **Boolean** See Argument Reference above.
-
- - `fixed_ip_v4` **String** See Argument Reference above.
-
- - `name` **String** See Argument Reference above.
-
- - `port` **String** See Argument Reference above.
-
- - `uuid` **String** See Argument Reference above.
-
- - `mac` **String** The MAC address of the NIC on that network.
-
-- `network_mode` **String** See Argument Reference above.
-
-- `personality` See Argument Reference above.
- - `content` **String** See Argument Reference above.
-
- - `file` **String** See Argument Reference above.
-
-- `power_state` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `scheduler_hints` See Argument Reference above.
- - `group` **String** See Argument Reference above.
-
-- `security_groups` Set of **String** See Argument Reference above.
-
-- `stop_before_destroy` **Boolean** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `user_data` **String** See Argument Reference above.
-
-- `vendor_options` See Argument Reference above.
- - `detach_ports_before_destroy` **Boolean** See Argument Reference above.
-
- - `ignore_resize_confirmation` **Boolean** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_metadata` Map of **String** Contains all instance metadata, even metadata not set by Terraform.
- `all_tags` Set of **String** The collection of tags assigned on the instance, which have been explicitly and implicitly added.
- `id` **String** ID of the resource.
+- `network`
+ - `mac` **String** The MAC address of the NIC on that network.
+
## Notes
diff --git a/docs/resources/vkcs_compute_interface_attach.md b/docs/resources/vkcs_compute_interface_attach.md
index fbe97a37..3113a846 100644
--- a/docs/resources/vkcs_compute_interface_attach.md
+++ b/docs/resources/vkcs_compute_interface_attach.md
@@ -145,16 +145,7 @@ _NOTE_: This option and `network_id` are mutually exclusive.
## Attributes Reference
-- `instance_id` **String** See Argument Reference above.
-
-- `fixed_ip` **String** See Argument Reference above.
-
-- `network_id` **String** See Argument Reference above.
-
-- `port_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_compute_keypair.md b/docs/resources/vkcs_compute_keypair.md
index a5b5f532..0bbb8c54 100644
--- a/docs/resources/vkcs_compute_keypair.md
+++ b/docs/resources/vkcs_compute_keypair.md
@@ -46,14 +46,7 @@ output "private_key" {
## Attributes Reference
-- `name` **String** See Argument Reference above.
-
-- `public_key` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `value_specs` Map of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `fingerprint` **String** The fingerprint of the public key.
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_compute_servergroup.md b/docs/resources/vkcs_compute_servergroup.md
index f2b4c4ea..5480f21c 100644
--- a/docs/resources/vkcs_compute_servergroup.md
+++ b/docs/resources/vkcs_compute_servergroup.md
@@ -27,14 +27,7 @@ resource "vkcs_compute_servergroup" "test-sg" {
## Attributes Reference
-- `name` **String** See Argument Reference above.
-
-- `policies` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `value_specs` Map of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
- `members` **String** The instances that are part of this server group.
diff --git a/docs/resources/vkcs_compute_volume_attach.md b/docs/resources/vkcs_compute_volume_attach.md
index d7d27a8b..a8a0535e 100644
--- a/docs/resources/vkcs_compute_volume_attach.md
+++ b/docs/resources/vkcs_compute_volume_attach.md
@@ -96,12 +96,7 @@ output "volume_devices" {
## Attributes Reference
-- `instance_id` **String** See Argument Reference above.
-
-- `volume_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_db_backup.md b/docs/resources/vkcs_db_backup.md
index fc7f8d28..dade83b7 100644
--- a/docs/resources/vkcs_db_backup.md
+++ b/docs/resources/vkcs_db_backup.md
@@ -13,45 +13,44 @@ Provides a db backup resource. This can be used to create and delete db backup.
## Example Usage
```terraform
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
- disk_autoexpand {
- autoexpand = true
- max_disk_size = 1000
- }
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- capabilities {
- name = "node_exporter"
- settings = {
- "listen_port" : "9100"
- }
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
-
-resource "vkcs_db_backup" "db-backup" {
- name = "db-backup"
- dbms_id = vkcs_db_instance.db-instance.id
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+ disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 1000
+ }
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ capabilities {
+ name = "node_exporter"
+ settings = {
+ "listen_port" : "9100"
+ }
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+resource "vkcs_db_backup" "db-backup" {
+ name = "db-backup"
+ dbms_id = vkcs_db_instance.db-instance.id
}
```
## Argument Reference
@@ -65,14 +64,7 @@ resource "vkcs_db_backup" "db-backup" {
## Attributes Reference
-- `dbms_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `container_prefix` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `created` **String** Backup creation timestamp
- `datastore` **Object** Object that represents datastore of backup
diff --git a/docs/resources/vkcs_db_cluster.md b/docs/resources/vkcs_db_cluster.md
index c27891c1..a7a6371d 100644
--- a/docs/resources/vkcs_db_cluster.md
+++ b/docs/resources/vkcs_db_cluster.md
@@ -12,30 +12,43 @@ Provides a db cluster resource. This can be used to create, modify and delete db
## Example Usage
### Basic cluster
```terraform
-resource "vkcs_db_cluster" "db-cluster" {
- name = "db-cluster"
-
- availability_zone = "GZ1"
- datastore {
- type = "postgresql"
- version = "12"
- }
-
- cluster_size = 3
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 10
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
+resource "vkcs_db_cluster" "db-cluster" {
+ name = "db-cluster"
+
+ availability_zone = "GZ1"
+ datastore {
+ type = "postgresql"
+ version = "12"
+ }
+
+ cluster_size = 3
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+ cloud_monitoring_enabled = true
+
+ volume_size = 10
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+data "vkcs_lb_loadbalancer" "loadbalancer" {
+ id = "${vkcs_db_cluster.db-cluster.loadbalancer_id}"
+}
+
+data "vkcs_networking_port" "loadbalancer-port" {
+ port_id = "${data.vkcs_lb_loadbalancer.loadbalancer.vip_port_id}"
+}
+
+output "cluster_ips" {
+ value = "${data.vkcs_networking_port.loadbalancer-port.all_fixed_ips}"
+ description = "IP addresses of the cluster."
}
```
@@ -130,6 +143,8 @@ resource "vkcs_db_cluster" "mydb-cluster" {
- `settings` Map of **String** (*Optional*) Map of key-value settings of the capability.
+- `cloud_monitoring_enabled` **Boolean** (*Optional*) Enable cloud monitoring for the cluster. Changing this for Redis or MongoDB creates a new instance. **New since v.0.2.0**
+
- `configuration_id` **String** (*Optional*) The id of the configuration attached to cluster.
- `disk_autoexpand` (*Optional*) Object that represents autoresize properties of the cluster.
@@ -142,9 +157,13 @@ resource "vkcs_db_cluster" "mydb-cluster" {
- `keypair` **String** (*Optional*) Name of the keypair to be attached to cluster. Changing this creates a new cluster.
- `network` (*Optional*) Object that represents network of the cluster. Changing this creates a new cluster.
- - `port` **String** (*Optional*) The port id of the network. Changing this creates a new cluster.
+ - `port` **String** (*Optional* Deprecated) The port id of the network. Changing this creates a new cluster. ***Deprecated*** This argument is deprecated, please do not use it.
- - `uuid` **String** (*Optional*) The id of the network. Changing this creates a new cluster.
+ - `security_groups` Set of **String** (*Optional*) An array of one or more security group IDs to associate with the cluster instances. Changing this creates a new cluster. **New since v.0.2.0**.
+
+ - `subnet_id` **String** (*Optional*) The id of the subnet. Changing this creates a new cluster. **New since v.0.1.15**.
+
+ - `uuid` **String** (*Optional*) The id of the network. Changing this creates a new cluster.**Note** Although this argument is marked as optional, it is actually required at the moment. Not setting a value for it may cause an error.
- `region` **String** (*Optional*) Region to create resource in.
@@ -157,6 +176,8 @@ resource "vkcs_db_cluster" "mydb-cluster" {
- `root_password` **String** (*Optional* Sensitive) Password for the root user of the cluster.
+- `shrink_options` **String** (*Optional*) Used only for shrinking cluster. List of IDs of instances that should remain after shrink. If no options are supplied, shrink operation will choose first non-leader instance to delete.
+
- `wal_disk_autoexpand` (*Optional*) Object that represents autoresize properties of wal volume of the cluster.
- `autoexpand` **Boolean** (*Optional*) Indicates whether wal volume autoresize is enabled.
@@ -169,77 +190,12 @@ resource "vkcs_db_cluster" "mydb-cluster" {
## Attributes Reference
-- `cluster_size` **Number** See Argument Reference above.
-
-- `datastore` See Argument Reference above.
- - `type` **String** See Argument Reference above.
-
- - `version` **String** See Argument Reference above.
-
-- `flavor_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `volume_size` **Number** See Argument Reference above.
-
-- `volume_type` **String** See Argument Reference above.
-
-- `availability_zone` **String** See Argument Reference above.
-
-- `backup_schedule` See Argument Reference above.
- - `interval_hours` **Number** See Argument Reference above.
-
- - `keep_count` **Number** See Argument Reference above.
-
- - `name` **String** See Argument Reference above.
-
- - `start_hours` **Number** See Argument Reference above.
-
- - `start_minutes` **Number** See Argument Reference above.
-
-- `capabilities` See Argument Reference above.
- - `name` **String** See Argument Reference above.
-
- - `settings` Map of **String** See Argument Reference above.
-
-- `configuration_id` **String** See Argument Reference above.
-
-- `disk_autoexpand` See Argument Reference above.
- - `autoexpand` **Boolean** See Argument Reference above.
-
- - `max_disk_size` **Number** See Argument Reference above.
-
-- `floating_ip_enabled` **Boolean** See Argument Reference above.
-
-- `keypair` **String** See Argument Reference above.
-
-- `network` See Argument Reference above.
- - `port` **String** See Argument Reference above.
-
- - `uuid` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `restore_point` See Argument Reference above.
- - `backup_id` **String** See Argument Reference above.
-
- - `target` **String** See Argument Reference above.
-
-- `root_enabled` **Boolean** See Argument Reference above.
-
-- `root_password` **String** See Argument Reference above.
-
-- `wal_disk_autoexpand` See Argument Reference above.
- - `autoexpand` **Boolean** See Argument Reference above.
-
- - `max_disk_size` **Number** See Argument Reference above.
-
-- `wal_volume` See Argument Reference above.
- - `size` **Number** See Argument Reference above.
+In addition to all arguments above, the following attributes are exported:
+- `id` **String** ID of the resource.
- - `volume_type` **String** See Argument Reference above.
+- `instances` **Object** Cluster instances info.
-- `id` **String** ID of the resource.
+- `loadbalancer_id` **String** The id of the loadbalancer attached to the cluster. **New since v.0.1.15**.
diff --git a/docs/resources/vkcs_db_cluster_with_shards.md b/docs/resources/vkcs_db_cluster_with_shards.md
index d87cb6a4..f78508de 100644
--- a/docs/resources/vkcs_db_cluster_with_shards.md
+++ b/docs/resources/vkcs_db_cluster_with_shards.md
@@ -12,46 +12,65 @@ Provides a db cluster with shards resource. This can be used to create, modify a
## Example Usage
### Basic cluster with shards
```terraform
-resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
- name = "db-cluster-with-shards"
-
- datastore {
- type = "clickhouse"
- version = "20.8"
- }
-
- shard {
- availability_zone = "GZ1"
- size = 1
- shard_id = "shard0"
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
- }
-
- shard {
- availability_zone = "GZ1"
- size = 1
- shard_id = "shard1"
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
+resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
+ name = "db-cluster-with-shards"
+
+ datastore {
+ type = "clickhouse"
+ version = "20.8"
+ }
+
+ cloud_monitoring_enabled = true
+
+ shard {
+ availability_zone = "GZ1"
+ size = 1
+ shard_id = "shard0"
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ volume_size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ security_groups = [vkcs_networking_secgroup.secgroup.id]
+ }
+ }
+
+ shard {
+ availability_zone = "GZ1"
+ size = 1
+ shard_id = "shard1"
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ volume_size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ security_groups = [vkcs_networking_secgroup.secgroup.id]
+ }
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db,
+ vkcs_networking_secgroup.secgroup
+ ]
+}
+
+locals {
+ cluster = vkcs_db_cluster_with_shards.db-cluster-with-shards
+ shards_ips = {
+ for shard in local.cluster.shard : shard.shard_id => [for i in shard.instances : {
+ "internal_ip" = i.ip[0]
+ "external_ip" = length(i.ip) > 1 ? i.ip[1] : null
+ }]
+ }
+}
+
+output "shard0-ips" {
+ value = local.shards_ips["shard0"]
+ description = "IPs of instances in shard with \"id\" = \"shard0\""
}
```
@@ -118,9 +137,15 @@ resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
- `availability_zone` **String** (*Optional*) The name of the availability zone of the cluster shard. Changing this creates a new cluster.
- `network` (*Optional*)
- - `port` **String** (*Optional*) The port id of the network. Changing this creates a new cluster.
+ - `port` **String** (*Optional* Deprecated) The port id of the network. Changing this creates a new cluster. ***Deprecated*** This argument is deprecated, please do not use it.
- - `uuid` **String** (*Optional*) The id of the network. Changing this creates a new cluster.
+ - `security_groups` Set of **String** (*Optional*) An array of one or more security group IDs to associate with the shard instances. Changing this creates a new cluster. **New since v.0.2.0**.
+
+ - `subnet_id` **String** (*Optional*) The id of the subnet. Changing this creates a new cluster. **New since v.0.1.15**.
+
+ - `uuid` **String** (*Optional*) The id of the network. Changing this creates a new cluster.**Note** Although this argument is marked as optional, it is actually required at the moment. Not setting a value for it may cause an error.
+
+ - `shrink_options` **String** (*Optional*) Used only for shrinking cluster. List of IDs of instances that should remain after shrink. If no options are supplied, shrink operation will choose first non-leader instance to delete.
- `wal_volume` (*Optional*) Object that represents wal volume of the cluster.
- `size` **Number** (***Required***) Size of the instance wal volume.
@@ -132,6 +157,8 @@ resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
- `settings` Map of **String** (*Optional*) Map of key-value settings of the capability.
+- `cloud_monitoring_enabled` **Boolean** (*Optional*) Enable cloud monitoring for the cluster. Changing this for Redis or MongoDB creates a new instance. **New since v.0.2.0**
+
- `configuration_id` **String** (*Optional*) The id of the configuration attached to cluster.
- `disk_autoexpand` (*Optional*) Object that represents autoresize properties of the cluster.
@@ -159,68 +186,12 @@ resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
## Attributes Reference
-- `datastore` See Argument Reference above.
- - `type` **String** See Argument Reference above.
-
- - `version` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `shard` See Argument Reference above.
- - `flavor_id` **String** See Argument Reference above.
-
- - `shard_id` **String** See Argument Reference above.
-
- - `size` **Number** See Argument Reference above.
-
- - `volume_size` **Number** See Argument Reference above.
-
- - `volume_type` **String** See Argument Reference above.
-
- - `availability_zone` **String** See Argument Reference above.
-
- - `network`
- - `port` **String** See Argument Reference above.
-
- - `uuid` **String** See Argument Reference above.
-
- - `wal_volume` See Argument Reference above.
- - `size` **Number** See Argument Reference above.
-
- - `volume_type` **String** See Argument Reference above.
-
-- `capabilities` See Argument Reference above.
- - `name` **String** See Argument Reference above.
-
- - `settings` Map of **String** See Argument Reference above.
-
-- `configuration_id` **String** See Argument Reference above.
-
-- `disk_autoexpand` See Argument Reference above.
- - `autoexpand` **Boolean** See Argument Reference above.
-
- - `max_disk_size` **Number** See Argument Reference above.
-
-- `floating_ip_enabled` **Boolean** See Argument Reference above.
-
-- `keypair` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `restore_point` See Argument Reference above.
- - `backup_id` **String** See Argument Reference above.
-
-- `root_enabled` **Boolean** See Argument Reference above.
-
-- `root_password` **String** See Argument Reference above.
-
-- `wal_disk_autoexpand` See Argument Reference above.
- - `autoexpand` **Boolean** See Argument Reference above.
-
- - `max_disk_size` **Number** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
+- `shard`
+ - `instances` **Object** Shard instances info. **New since v.0.1.15**.
+
## Import
diff --git a/docs/resources/vkcs_db_config_group.md b/docs/resources/vkcs_db_config_group.md
index 1c349a87..d405a04e 100644
--- a/docs/resources/vkcs_db_config_group.md
+++ b/docs/resources/vkcs_db_config_group.md
@@ -46,6 +46,10 @@ resource "vkcs_db_instance" "db-instance" {
flavor_id = data.vkcs_compute_flavor.db.id
volume_type = "ceph-ssd"
size = 8
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
}
```
## Argument Reference
@@ -62,17 +66,7 @@ resource "vkcs_db_instance" "db-instance" {
## Attributes Reference
-- `datastore` See Argument Reference above.
- - `type` **String** See Argument Reference above.
-
- - `version` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `values` Map of **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `created` **String** Timestamp of config group's creation
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_db_database.md b/docs/resources/vkcs_db_database.md
index 75b034fc..9cd16641 100644
--- a/docs/resources/vkcs_db_database.md
+++ b/docs/resources/vkcs_db_database.md
@@ -12,36 +12,35 @@ Provides a db database resource. This can be used to create, modify and delete d
## Example Usage
```terraform
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
-
-resource "vkcs_db_database" "db-database" {
- name = "testdb"
- dbms_id = vkcs_db_instance.db-instance.id
- charset = "utf8"
- collate = "utf8_general_ci"
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+resource "vkcs_db_database" "db-database" {
+ name = "testdb"
+ dbms_id = vkcs_db_instance.db-instance.id
+ charset = "utf8"
+ collate = "utf8_general_ci"
}
```
## Argument Reference
@@ -55,14 +54,7 @@ resource "vkcs_db_database" "db-database" {
## Attributes Reference
-- `dbms_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `charset` **String** See Argument Reference above.
-
-- `collate` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `dbms_type` **String** Type of dbms for the database, can be "instance" or "cluster".
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_db_instance.md b/docs/resources/vkcs_db_instance.md
index 5c7241f5..c352d079 100644
--- a/docs/resources/vkcs_db_instance.md
+++ b/docs/resources/vkcs_db_instance.md
@@ -12,40 +12,42 @@ Provides a db instance resource. This can be used to create, modify and delete d
## Example Usage
### Basic instance
```terraform
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
- disk_autoexpand {
- autoexpand = true
- max_disk_size = 1000
- }
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- capabilities {
- name = "node_exporter"
- settings = {
- "listen_port" : "9100"
- }
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+ cloud_monitoring_enabled = true
+
+ size = 8
+ volume_type = "ceph-ssd"
+ disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 1000
+ }
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ security_groups = [vkcs_networking_secgroup.secgroup.id]
+ }
+
+ capabilities {
+ name = "node_exporter"
+ settings = {
+ "listen_port" : "9100"
+ }
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db,
+ vkcs_networking_secgroup.secgroup
+ ]
}
```
@@ -164,6 +166,8 @@ resource "vkcs_db_instance" "db-instance" {
- `settings` Map of **String** (*Optional*) Map of key-value settings of the capability.
+- `cloud_monitoring_enabled` **Boolean** (*Optional*) Enable cloud monitoring for the instance. Changing this for Redis or MongoDB creates a new instance. **New since v.0.2.0**
+
- `configuration_id` **String** (*Optional*) The id of the configuration attached to instance.
- `disk_autoexpand` (*Optional*) Object that represents autoresize properties of the instance.
@@ -173,14 +177,20 @@ resource "vkcs_db_instance" "db-instance" {
- `floating_ip_enabled` **Boolean** (*Optional*) Indicates whether floating ip is created for instance. Changing this creates a new instance.
+- `ip` **String** (*Optional*) IP address of the instance.
+
- `keypair` **String** (*Optional*) Name of the keypair to be attached to instance. Changing this creates a new instance.
- `network` (*Optional*) Object that represents network of the instance. Changing this creates a new instance.
- - `fixed_ip_v4` **String** (*Optional*) The IPv4 address. Changing this creates a new instance.
+ - `fixed_ip_v4` **String** (*Optional*) The IPv4 address. Changing this creates a new instance. **Note** This argument conflicts with "replica_of". Setting both at the same time causes "fixed_ip_v4" to be ignored.
- - `port` **String** (*Optional*) The port id of the network. Changing this creates a new instance.
+ - `port` **String** (*Optional* Deprecated) The port id of the network. Changing this creates a new instance. ***Deprecated*** This argument is deprecated, please do not use it.
- - `uuid` **String** (*Optional*) The id of the network. Changing this creates a new instance.
+ - `security_groups` Set of **String** (*Optional*) An array of one or more security group IDs to associate with the instance. Changing this creates a new instance. **New since v.0.2.0**.
+
+ - `subnet_id` **String** (*Optional*) The id of the subnet. Changing this creates a new instance. **New since v.0.1.15**.
+
+ - `uuid` **String** (*Optional*) The id of the network. Changing this creates a new instance.**Note** Although this argument is marked as optional, it is actually required at the moment. Not setting a value for it may cause an error.
- `region` **String** (*Optional*) Region to create resource in.
@@ -211,82 +221,7 @@ resource "vkcs_db_instance" "db-instance" {
## Attributes Reference
-- `datastore` See Argument Reference above.
- - `type` **String** See Argument Reference above.
-
- - `version` **String** See Argument Reference above.
-
-- `flavor_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `size` **Number** See Argument Reference above.
-
-- `volume_type` **String** See Argument Reference above.
-
-- `availability_zone` **String** See Argument Reference above.
-
-- `backup_schedule` See Argument Reference above.
- - `interval_hours` **Number** See Argument Reference above.
-
- - `keep_count` **Number** See Argument Reference above.
-
- - `name` **String** See Argument Reference above.
-
- - `start_hours` **Number** See Argument Reference above.
-
- - `start_minutes` **Number** See Argument Reference above.
-
-- `capabilities` See Argument Reference above.
- - `name` **String** See Argument Reference above.
-
- - `settings` Map of **String** See Argument Reference above.
-
-- `configuration_id` **String** See Argument Reference above.
-
-- `disk_autoexpand` See Argument Reference above.
- - `autoexpand` **Boolean** See Argument Reference above.
-
- - `max_disk_size` **Number** See Argument Reference above.
-
-- `floating_ip_enabled` **Boolean** See Argument Reference above.
-
-- `keypair` **String** See Argument Reference above.
-
-- `network` See Argument Reference above.
- - `fixed_ip_v4` **String** See Argument Reference above.
-
- - `port` **String** See Argument Reference above.
-
- - `uuid` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `replica_of` **String** See Argument Reference above.
-
-- `restore_point` See Argument Reference above.
- - `backup_id` **String** See Argument Reference above.
-
- - `target` **String** See Argument Reference above.
-
-- `root_enabled` **Boolean** See Argument Reference above.
-
-- `root_password` **String** See Argument Reference above.
-
-- `wal_disk_autoexpand` See Argument Reference above.
- - `autoexpand` **Boolean** See Argument Reference above.
-
- - `max_disk_size` **Number** See Argument Reference above.
-
-- `wal_volume` See Argument Reference above.
- - `size` **Number** See Argument Reference above.
-
- - `volume_type` **String** See Argument Reference above.
-
- - `autoexpand` **Boolean** See Argument Reference above.
-
- - `max_disk_size` **Number** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_db_user.md b/docs/resources/vkcs_db_user.md
index 107be0d1..bd6be695 100644
--- a/docs/resources/vkcs_db_user.md
+++ b/docs/resources/vkcs_db_user.md
@@ -12,45 +12,44 @@ Provides a db user resource. This can be used to create, modify and delete db us
## Example Usage
```terraform
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
-
-resource "vkcs_db_database" "db-database" {
- name = "testdb"
- dbms_id = vkcs_db_instance.db-instance.id
- charset = "utf8"
- collate = "utf8_general_ci"
-}
-
-resource "vkcs_db_user" "db-user" {
- name = "testuser"
- password = "SomePass1_"
-
- dbms_id = vkcs_db_instance.db-instance.id
-
- databases = [vkcs_db_database.db-database.name]
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+resource "vkcs_db_database" "db-database" {
+ name = "testdb"
+ dbms_id = vkcs_db_instance.db-instance.id
+ charset = "utf8"
+ collate = "utf8_general_ci"
+}
+
+resource "vkcs_db_user" "db-user" {
+ name = "testuser"
+ password = "SomePass1_"
+
+ dbms_id = vkcs_db_instance.db-instance.id
+
+ databases = [vkcs_db_database.db-database.name]
}
```
## Argument Reference
@@ -66,16 +65,7 @@ resource "vkcs_db_user" "db-user" {
## Attributes Reference
-- `dbms_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `password` **String** See Argument Reference above.
-
-- `databases` **String** See Argument Reference above.
-
-- `host` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `dbms_type` **String** Type of dbms for the user, can be "instance" or "cluster".
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_images_image.md b/docs/resources/vkcs_images_image.md
index 0be78d38..097e94ea 100644
--- a/docs/resources/vkcs_images_image.md
+++ b/docs/resources/vkcs_images_image.md
@@ -60,38 +60,7 @@ resource "vkcs_images_image" "rancheros" {
## Attributes Reference
-- `container_format` **String** See Argument Reference above.
-
-- `disk_format` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `image_cache_path` **String** See Argument Reference above.
-
-- `image_source_password` **String** See Argument Reference above.
-
-- `image_source_url` **String** See Argument Reference above.
-
-- `image_source_username` **String** See Argument Reference above.
-
-- `local_file_path` **String** See Argument Reference above.
-
-- `min_disk_gb` **Number** See Argument Reference above.
-
-- `min_ram_mb` **Number** See Argument Reference above.
-
-- `properties` Map of **String** See Argument Reference above.
-
-- `protected` **Boolean** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `verify_checksum` **Boolean** See Argument Reference above.
-
-- `visibility` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `checksum` **String** The checksum of the data associated with the image.
- `created_at` **String** The date the image was created.
diff --git a/docs/resources/vkcs_keymanager_container.md b/docs/resources/vkcs_keymanager_container.md
index ab40e906..70db6302 100644
--- a/docs/resources/vkcs_keymanager_container.md
+++ b/docs/resources/vkcs_keymanager_container.md
@@ -126,27 +126,13 @@ resource "vkcs_keymanager_container" "tls_1" {
## Attributes Reference
-- `type` **String** See Argument Reference above.
-
-- `acl` See Argument Reference above.
- - `read` See Argument Reference above.
- - `project_access` **Boolean** See Argument Reference above.
-
- - `users` Set of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
+- `acl`
+ - `read`
- `created_at` **String** The date the container ACL was created.
- `updated_at` **String** The date the container ACL was last updated.
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `secret_refs` See Argument Reference above.
- - `secret_ref` **String** See Argument Reference above.
-
- - `name` **String** See Argument Reference above.
-
- `consumers` **Object** The list of the container consumers. The structure is described below.
- `container_ref` **String** The container reference / where to find the container.
diff --git a/docs/resources/vkcs_keymanager_secret.md b/docs/resources/vkcs_keymanager_secret.md
index 6e27e94c..4b2042d1 100644
--- a/docs/resources/vkcs_keymanager_secret.md
+++ b/docs/resources/vkcs_keymanager_secret.md
@@ -109,38 +109,13 @@ resource "vkcs_keymanager_secret" "secret_1" {
## Attributes Reference
-- `acl` See Argument Reference above.
- - `read` See Argument Reference above.
- - `project_access` **Boolean** See Argument Reference above.
-
- - `users` Set of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
+- `acl`
+ - `read`
- `created_at` **String** The date the container ACL was created.
- `updated_at` **String** The date the container ACL was last updated.
-- `algorithm` **String** See Argument Reference above.
-
-- `bit_length` **Number** See Argument Reference above.
-
-- `expiration` **String** See Argument Reference above.
-
-- `metadata` Map of **String** See Argument Reference above.
-
-- `mode` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `payload` **String** See Argument Reference above.
-
-- `payload_content_encoding` **String** See Argument Reference above.
-
-- `payload_content_type` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `secret_type` **String** See Argument Reference above.
-
- `all_metadata` Map of **String** The map of metadata, assigned on the secret, which has been explicitly and implicitly added.
- `content_types` Map of **String** The map of the content types, assigned on the secret.
diff --git a/docs/resources/vkcs_kubernetes_cluster.md b/docs/resources/vkcs_kubernetes_cluster.md
index 5b8c6d99..63d4ed65 100755
--- a/docs/resources/vkcs_kubernetes_cluster.md
+++ b/docs/resources/vkcs_kubernetes_cluster.md
@@ -12,7 +12,7 @@ Provides a kubernetes cluster resource. This can be used to create, modify and d
## Example Usage
```terraform
data "vkcs_kubernetes_clustertemplate" "ct" {
- version = "1.21.4"
+ version = "1.24"
}
resource "vkcs_kubernetes_cluster" "k8s-cluster" {
@@ -59,9 +59,16 @@ resource "vkcs_kubernetes_cluster" "k8s-cluster" {
- `labels` Map of **String** (*Optional*) The list of optional key value pairs representing additional properties of the cluster. Changing this creates a new cluster.
+ * `calico_ipv4pool` to set subnet where pods will be created. Default 10.100.0.0/16.
+ * `clean_volumes` to remove pvc volumes when deleting a cluster. Default False.
+ * `cloud_monitoring` to enable cloud monitoring feature.
* `docker_registry_enabled=true` to preinstall Docker Registry.
- * `prometheus_monitoring=true` to preinstall monitoring system based on Prometheus and Grafana.
+ * `etcd_volume_size` to set etcd volume size. Default 10Gb.
* `ingress_controller="nginx"` to preinstall NGINX Ingress Controller.
+ * `kube_log_level` to set log level for kubelet in range 0 to 8.
+ * `master_volume_size` to set master vm volume size. Default 50Gb.
+ * `cluster_node_volume_type` to set master vm volume type. Default ceph-hdd.
+ * `prometheus_monitoring=true` to preinstall monitoring system based on Prometheus and Grafana.
- `loadbalancer_subnet_id` **String** (*Optional*) The UUID of the load balancer's subnet. Changing this creates new cluster.
@@ -79,46 +86,7 @@ resource "vkcs_kubernetes_cluster" "k8s-cluster" {
## Attributes Reference
-- `availability_zone` **String** See Argument Reference above.
-
-- `cluster_template_id` **String** See Argument Reference above.
-
-- `floating_ip_enabled` **Boolean** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `network_id` **String** See Argument Reference above.
-
-- `subnet_id` **String** See Argument Reference above.
-
-- `api_lb_fip` **String** See Argument Reference above.
-
-- `api_lb_vip` **String** See Argument Reference above.
-
-- `dns_domain` **String** See Argument Reference above.
-
-- `ingress_floating_ip` **String** See Argument Reference above.
-
-- `insecure_registries` **String** See Argument Reference above.
-
-- `keypair` **String** See Argument Reference above.
-
-- `labels` Map of **String** See Argument Reference above.
-
-- `loadbalancer_subnet_id` **String** See Argument Reference above.
-
-- `master_count` **Number** See Argument Reference above.
-
-- `master_flavor` **String** See Argument Reference above.
-
-- `pods_network_cidr` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `registry_auth_password` **String** See Argument Reference above.
-
-- `status` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `api_address` **String** COE API address.
- `created_at` **String** The time at which cluster was created.
diff --git a/docs/resources/vkcs_kubernetes_node_group.md b/docs/resources/vkcs_kubernetes_node_group.md
index 860394da..149aabcb 100755
--- a/docs/resources/vkcs_kubernetes_node_group.md
+++ b/docs/resources/vkcs_kubernetes_node_group.md
@@ -12,7 +12,7 @@ Provides a cluster node group resource. This can be used to create, modify and d
## Example Usage
```terraform
data "vkcs_kubernetes_clustertemplate" "ct" {
- version = "1.21.4"
+ version = "1.24"
}
resource "vkcs_kubernetes_cluster" "k8s-cluster" {
@@ -101,40 +101,7 @@ resource "vkcs_kubernetes_node_group" "default_ng" {
## Attributes Reference
-- `cluster_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `node_count` **Number** See Argument Reference above.
-
-- `autoscaling_enabled` **Boolean** See Argument Reference above.
-
-- `availability_zones` **String** See Argument Reference above.
-
-- `flavor_id` **String** See Argument Reference above.
-
-- `labels` See Argument Reference above.
- - `key` **String**
-
- - `value` **String**
-
-- `max_node_unavailable` **Number** See Argument Reference above.
-
-- `max_nodes` **Number** See Argument Reference above.
-
-- `min_nodes` **Number** See Argument Reference above.
-
-- `taints` See Argument Reference above.
- - `effect` **String**
-
- - `key` **String**
-
- - `value` **String**
-
-- `volume_size` **Number** See Argument Reference above.
-
-- `volume_type` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `created_at` **String** The time at which node group was created.
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_lb_l7policy.md b/docs/resources/vkcs_lb_l7policy.md
index 9ae8b7c4..64fabb6b 100644
--- a/docs/resources/vkcs_lb_l7policy.md
+++ b/docs/resources/vkcs_lb_l7policy.md
@@ -67,28 +67,11 @@ resource "vkcs_lb_l7policy" "l7policy_1" {
- `redirect_url` **String** (*Optional*) Requests matching this policy will be redirected to this URL. Only valid if action is REDIRECT\_TO\_URL.
-- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used. Changing this creates a new L7 Policy.
+- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used. Changing this creates a new L7 Policy.
## Attributes Reference
-- `action` **String** See Argument Reference above.
-
-- `listener_id` **String** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `position` **Number** See Argument Reference above.
-
-- `redirect_pool_id` **String** See Argument Reference above.
-
-- `redirect_url` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_lb_l7rule.md b/docs/resources/vkcs_lb_l7rule.md
index 8803b9c9..a82a52db 100644
--- a/docs/resources/vkcs_lb_l7rule.md
+++ b/docs/resources/vkcs_lb_l7rule.md
@@ -76,22 +76,7 @@ resource "vkcs_lb_l7rule" "l7rule_1" {
## Attributes Reference
-- `compare_type` **String** See Argument Reference above.
-
-- `l7policy_id` **String** See Argument Reference above.
-
-- `type` **String** See Argument Reference above.
-
-- `value` **String** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `invert` **Boolean** See Argument Reference above.
-
-- `key` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
- `listener_id` **String** The ID of the Listener owning this resource.
diff --git a/docs/resources/vkcs_lb_listener.md b/docs/resources/vkcs_lb_listener.md
index 8852d206..0349eb3b 100644
--- a/docs/resources/vkcs_lb_listener.md
+++ b/docs/resources/vkcs_lb_listener.md
@@ -44,7 +44,7 @@ resource "vkcs_lb_listener" "listener_1" {
- `name` **String** (*Optional*) Human-readable name for the Listener. Does not have to be unique.
-- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used. Changing this creates a new Listener.
+- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used. Changing this creates a new Listener.1
- `sni_container_refs` **String** (*Optional*) A list of references to Keymanager Secrets containers which store SNI information.
@@ -58,40 +58,7 @@ resource "vkcs_lb_listener" "listener_1" {
## Attributes Reference
-- `loadbalancer_id` **String** See Argument Reference above.
-
-- `protocol` **String** See Argument Reference above.
-
-- `protocol_port` **Number** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `allowed_cidrs` **String** See Argument Reference above.
-
-- `connection_limit` **Number** See Argument Reference above.
-
-- `default_pool_id` **String** See Argument Reference above.
-
-- `default_tls_container_ref` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `insert_headers` Map of **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sni_container_refs` **String** See Argument Reference above.
-
-- `timeout_client_data` **Number** See Argument Reference above.
-
-- `timeout_member_connect` **Number** See Argument Reference above.
-
-- `timeout_member_data` **Number** See Argument Reference above.
-
-- `timeout_tcp_inspect` **Number** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_lb_loadbalancer.md b/docs/resources/vkcs_lb_loadbalancer.md
index 75a8427d..f44120b5 100644
--- a/docs/resources/vkcs_lb_loadbalancer.md
+++ b/docs/resources/vkcs_lb_loadbalancer.md
@@ -24,9 +24,9 @@ resource "vkcs_lb_loadbalancer" "lb_1" {
- `name` **String** (*Optional*) Human-readable name for the Loadbalancer. Does not have to be unique.
-- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used. Changing this creates a new LB loadbalancer.
+- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used. Changing this creates a new LB loadbalancer.
-- `security_group_ids` Set of **String** (*Optional*) A list of security group IDs to apply to the loadbalancer. The security groups must be specified by ID and not name (as opposed to how they are configured with the Compute Instance).
+- `security_group_ids` Set of **String** (*Optional* Deprecated) A list of security group IDs to apply to the loadbalancer. The security groups must be specified by ID and not name (as opposed to how they are configured with the Compute Instance). ***Deprecated*** This argument is deprecated, please do not use it.
- `tags` Set of **String** (*Optional*) A list of simple strings assigned to the loadbalancer.
@@ -40,28 +40,7 @@ resource "vkcs_lb_loadbalancer" "lb_1" {
## Attributes Reference
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `availability_zone` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `security_group_ids` Set of **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `vip_address` **String** See Argument Reference above.
-
-- `vip_network_id` **String** See Argument Reference above.
-
-- `vip_port_id` **String** See Argument Reference above.
-
-- `vip_subnet_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_lb_member.md b/docs/resources/vkcs_lb_member.md
index 769951cb..2fa4d1be 100644
--- a/docs/resources/vkcs_lb_member.md
+++ b/docs/resources/vkcs_lb_member.md
@@ -36,22 +36,7 @@ resource "vkcs_lb_member" "member_1" {
## Attributes Reference
-- `address` **String** See Argument Reference above.
-
-- `pool_id` **String** See Argument Reference above.
-
-- `protocol_port` **Number** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `subnet_id` **String** See Argument Reference above.
-
-- `weight` **Number** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_lb_members.md b/docs/resources/vkcs_lb_members.md
index 3dda5b6b..209dedcb 100644
--- a/docs/resources/vkcs_lb_members.md
+++ b/docs/resources/vkcs_lb_members.md
@@ -47,29 +47,12 @@ resource "vkcs_lb_members" "members_1" {
## Attributes Reference
-- `pool_id` **String** See Argument Reference above.
-
-- `member` See Argument Reference above.
- - `address` **String** See Argument Reference above.
-
- - `protocol_port` **Number** See Argument Reference above.
-
- - `admin_state_up` **Boolean** See Argument Reference above.
-
- - `backup` **Boolean** See Argument Reference above.
-
- - `name` **String** See Argument Reference above.
-
- - `subnet_id` **String** See Argument Reference above.
-
- - `weight` **Number** See Argument Reference above.
+In addition to all arguments above, the following attributes are exported:
+- `id` **String** ID of the resource.
+- `member`
- `id` **String** The unique ID for the member.
-- `region` **String** See Argument Reference above.
-
-- `id` **String** ID of the resource.
-
## Import
diff --git a/docs/resources/vkcs_lb_monitor.md b/docs/resources/vkcs_lb_monitor.md
index a974fa97..b229718d 100644
--- a/docs/resources/vkcs_lb_monitor.md
+++ b/docs/resources/vkcs_lb_monitor.md
@@ -40,36 +40,13 @@ resource "vkcs_lb_monitor" "monitor_1" {
- `name` **String** (*Optional*) The Name of the Monitor.
-- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used. Changing this creates a new monitor.
+- `region` **String** (*Optional*) The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used. Changing this creates a new monitor.
- `url_path` **String** (*Optional*) Required for HTTP(S) types. URI path that will be accessed if monitor type is HTTP or HTTPS.
## Attributes Reference
-- `delay` **Number** See Argument Reference above.
-
-- `max_retries` **Number** See Argument Reference above.
-
-- `pool_id` **String** See Argument Reference above.
-
-- `timeout` **Number** See Argument Reference above.
-
-- `type` **String** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `expected_codes` **String** See Argument Reference above.
-
-- `http_method` **String** See Argument Reference above.
-
-- `max_retries_down` **Number** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `url_path` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_lb_pool.md b/docs/resources/vkcs_lb_pool.md
index 708f7bf9..0471dfaf 100644
--- a/docs/resources/vkcs_lb_pool.md
+++ b/docs/resources/vkcs_lb_pool.md
@@ -46,27 +46,7 @@ resource "vkcs_lb_pool" "pool_1" {
## Attributes Reference
-- `lb_method` **String** See Argument Reference above.
-
-- `protocol` **String** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `listener_id` **String** See Argument Reference above.
-
-- `loadbalancer_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `persistence` See Argument Reference above.
- - `type` **String** See Argument Reference above.
-
- - `cookie_name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_floatingip.md b/docs/resources/vkcs_networking_floatingip.md
index fc5e8a13..af4cd64f 100644
--- a/docs/resources/vkcs_networking_floatingip.md
+++ b/docs/resources/vkcs_networking_floatingip.md
@@ -55,26 +55,7 @@ resource "vkcs_networking_floatingip" "floatip_1" {
## Attributes Reference
-- `pool` **String** See Argument Reference above.
-
-- `address` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `fixed_ip` **String** See Argument Reference above.
-
-- `port_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `subnet_id` **String** See Argument Reference above.
-
-- `subnet_ids` **String** See Argument Reference above.
-
-- `value_specs` Map of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_floatingip_associate.md b/docs/resources/vkcs_networking_floatingip_associate.md
index 84493cf0..7da58327 100644
--- a/docs/resources/vkcs_networking_floatingip_associate.md
+++ b/docs/resources/vkcs_networking_floatingip_associate.md
@@ -33,16 +33,7 @@ resource "vkcs_networking_floatingip_associate" "fip_1" {
## Attributes Reference
-- `floating_ip` **String** See Argument Reference above.
-
-- `port_id` **String** See Argument Reference above.
-
-- `fixed_ip` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_network.md b/docs/resources/vkcs_networking_network.md
index 8b63f45a..7b3f1c6f 100644
--- a/docs/resources/vkcs_networking_network.md
+++ b/docs/resources/vkcs_networking_network.md
@@ -78,26 +78,7 @@ resource "vkcs_compute_instance" "instance_1" {
## Attributes Reference
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `port_security_enabled` **Boolean** See Argument Reference above.
-
-- `private_dns_domain` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `value_specs` Map of **String** See Argument Reference above.
-
-- `vkcs_services_access` **Boolean** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_tags` Set of **String** The collection of tags assigned on the network, which have been explicitly and implicitly added.
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_port.md b/docs/resources/vkcs_networking_port.md
index f18de31c..aa53bb97 100644
--- a/docs/resources/vkcs_networking_port.md
+++ b/docs/resources/vkcs_networking_port.md
@@ -74,53 +74,7 @@ resource "vkcs_networking_port" "port_1" {
## Attributes Reference
-- `network_id` **String** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `allowed_address_pairs` See Argument Reference above.
- - `ip_address` **String** See Argument Reference above.
-
- - `mac_address` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `device_id` **String** See Argument Reference above.
-
-- `device_owner` **String** See Argument Reference above.
-
-- `dns_name` **String** See Argument Reference above.
-
-- `extra_dhcp_option` See Argument Reference above.
- - `name` **String** See Argument Reference above.
-
- - `value` **String** See Argument Reference above.
-
-- `fixed_ip` See Argument Reference above.
- - `subnet_id` **String** See Argument Reference above.
-
- - `ip_address` **String** See Argument Reference above.
-
-- `mac_address` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `no_fixed_ip` **Boolean** See Argument Reference above.
-
-- `no_security_groups` **Boolean** See Argument Reference above.
-
-- `port_security_enabled` **Boolean** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `security_group_ids` Set of **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `value_specs` Map of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_fixed_ips` **String** The collection of Fixed IP addresses on the port in the order returned by the Network v2 API.
- `all_security_group_ids` Set of **String** The collection of Security Group IDs on the port which have been explicitly and implicitly added.
diff --git a/docs/resources/vkcs_networking_port_secgroup_associate.md b/docs/resources/vkcs_networking_port_secgroup_associate.md
index aa0f33fb..f247bb1d 100644
--- a/docs/resources/vkcs_networking_port_secgroup_associate.md
+++ b/docs/resources/vkcs_networking_port_secgroup_associate.md
@@ -74,16 +74,7 @@ resource "vkcs_networking_port_secgroup_associate" "port_1" {
## Attributes Reference
-- `port_id` **String** See Argument Reference above.
-
-- `security_group_ids` Set of **String** See Argument Reference above.
-
-- `enforce` **Boolean** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_security_group_ids` Set of **String** The collection of Security Group IDs on the port which have been explicitly and implicitly added.
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_router.md b/docs/resources/vkcs_networking_router.md
index ee2efb12..e2e6f931 100644
--- a/docs/resources/vkcs_networking_router.md
+++ b/docs/resources/vkcs_networking_router.md
@@ -40,25 +40,7 @@ resource "vkcs_networking_router" "router_1" {
## Attributes Reference
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `external_network_id` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `value_specs` Map of **String** See Argument Reference above.
-
-- `vendor_options` See Argument Reference above.
- - `set_router_gateway_after_create` **Boolean** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_tags` Set of **String** The collection of tags assigned on the router, which have been explicitly and implicitly added.
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_router_interface.md b/docs/resources/vkcs_networking_router_interface.md
index dd2cfac6..e85f50ea 100644
--- a/docs/resources/vkcs_networking_router_interface.md
+++ b/docs/resources/vkcs_networking_router_interface.md
@@ -45,16 +45,7 @@ resource "vkcs_networking_router_interface" "router_interface_1" {
## Attributes Reference
-- `router_id` **String** See Argument Reference above.
-
-- `port_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `subnet_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_router_route.md b/docs/resources/vkcs_networking_router_route.md
index 3a8bf6c5..7d794367 100644
--- a/docs/resources/vkcs_networking_router_route.md
+++ b/docs/resources/vkcs_networking_router_route.md
@@ -52,16 +52,7 @@ resource "vkcs_networking_router_route" "router_route_1" {
## Attributes Reference
-- `destination_cidr` **String** See Argument Reference above.
-
-- `next_hop` **String** See Argument Reference above.
-
-- `router_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_secgroup.md b/docs/resources/vkcs_networking_secgroup.md
index dbfe35c0..df35df86 100644
--- a/docs/resources/vkcs_networking_secgroup.md
+++ b/docs/resources/vkcs_networking_secgroup.md
@@ -32,18 +32,7 @@ resource "vkcs_networking_secgroup" "secgroup_1" {
## Attributes Reference
-- `name` **String** See Argument Reference above.
-
-- `delete_default_rules` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_tags` Set of **String** The collection of tags assigned on the security group, which have been explicitly and implicitly added.
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_secgroup_rule.md b/docs/resources/vkcs_networking_secgroup_rule.md
index f655c3e5..d4e5b8aa 100644
--- a/docs/resources/vkcs_networking_secgroup_rule.md
+++ b/docs/resources/vkcs_networking_secgroup_rule.md
@@ -67,28 +67,7 @@ resource "vkcs_networking_secgroup_rule" "secgroup_rule_1" {
## Attributes Reference
-- `direction` **String** See Argument Reference above.
-
-- `security_group_id` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `ethertype` **String** See Argument Reference above.
-
-- `port_range_max` **Number** See Argument Reference above.
-
-- `port_range_min` **Number** See Argument Reference above.
-
-- `protocol` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `remote_group_id` **String** See Argument Reference above.
-
-- `remote_ip_prefix` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_subnet.md b/docs/resources/vkcs_networking_subnet.md
index 2341db70..06d35e64 100644
--- a/docs/resources/vkcs_networking_subnet.md
+++ b/docs/resources/vkcs_networking_subnet.md
@@ -57,39 +57,7 @@ resource "vkcs_networking_subnet" "subnet_1" {
## Attributes Reference
-- `network_id` **String** See Argument Reference above.
-
-- `allocation_pool` See Argument Reference above.
- - `end` **String** See Argument Reference above.
-
- - `start` **String** See Argument Reference above.
-
-- `cidr` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `dns_nameservers` **String** See Argument Reference above.
-
-- `enable_dhcp` **Boolean** See Argument Reference above.
-
-- `gateway_ip` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `no_gateway` **Boolean** See Argument Reference above.
-
-- `prefix_length` **Number** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
-- `subnetpool_id` **String** See Argument Reference above.
-
-- `tags` Set of **String** See Argument Reference above.
-
-- `value_specs` Map of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_tags` Set of **String** The collection of ags assigned on the subnet, which have been explicitly and implicitly added.
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_networking_subnet_route.md b/docs/resources/vkcs_networking_subnet_route.md
index 77397407..ebb81b5e 100644
--- a/docs/resources/vkcs_networking_subnet_route.md
+++ b/docs/resources/vkcs_networking_subnet_route.md
@@ -45,16 +45,7 @@ resource "vkcs_networking_subnet_route" "subnet_route_1" {
## Attributes Reference
-- `destination_cidr` **String** See Argument Reference above.
-
-- `next_hop` **String** See Argument Reference above.
-
-- `subnet_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `sdn` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_publicdns_record.md b/docs/resources/vkcs_publicdns_record.md
new file mode 100644
index 00000000..f30b8eec
--- /dev/null
+++ b/docs/resources/vkcs_publicdns_record.md
@@ -0,0 +1,102 @@
+---
+layout: "vkcs"
+page_title: "vkcs: vkcs_publicdns_record"
+description: |-
+ Manages a public DNS record.
+---
+
+# vkcs_publicdns_record
+
+Manages a public DNS zone record resource within VKCS. **New since v.0.2.0**.
+**Note:** Although some arguments are marked as optional, it is actually required to set values for them depending on record \"type\". Use this map to get information about which arguments you have to set:
+
+| Record type | Required arguments |
+| ----------- | ------------------ |
+| A | ip |
+| AAAA | ip |
+| CNAME | name, content |
+| MX | priority, content |
+| NS | content |
+| SRV | service, proto, priority, weight, host, port |
+| TXT | content |
+
+
+
+
+## Example Usage
+### Single record
+```terraform
+resource "vkcs_publicdns_record" "srv" {
+ zone_id = vkcs_publicdns_zone.zone.id
+ type = "SRV"
+ service = "_sip"
+ proto = "_udp"
+ priority = 10
+ weight = 5
+ host = "siptarget.com"
+ port = 5060
+ ttl = 60
+}
+```
+
+### Multiple A records
+```terraform
+locals {
+ google_public_dns_ips = tomap({
+ "ip_1" = "8.8.8.8"
+ "ip_2" = "8.8.4.4"
+ })
+}
+
+resource "vkcs_publicdns_record" "a" {
+ for_each = local.google_public_dns_ips
+ zone_id = vkcs_publicdns_zone.zone.id
+ type = "A"
+ name = "google-dns-servers"
+ ip = each.value
+ ttl = 60
+}
+```
+
+## Argument Reference
+- `type` **String** (***Required***) The type of the record. Must be one of following: "A", "AAAA", "CNAME", "MX", "NS", "SRV", "TXT".
+
+- `zone_id` **String** (***Required***) The ID of the zone to attach the record to.
+
+- `content` **String** (*Optional*) The content of the record.
+
+- `host` **String** (*Optional*) The domain name of the target host.
+
+- `ip` **String** (*Optional*) The IP address of the record. It should be IPv4 for record of type "A" and IPv6 for record of type "AAAA".
+
+- `name` **String** (*Optional*) The name of the record.
+
+- `port` **Number** (*Optional*) The port on the target host of the service.
+
+- `priority` **Number** (*Optional*) The priority of the record's server.
+
+- `proto` **String** (*Optional*) The name of the desired protocol.
+
+- `region` **String** (*Optional*) The region in which to obtain the V2 Public DNS client. If omitted, the `region` argument of the provider is used. Changing this creates a new record.
+
+- `service` **String** (*Optional*) The name of the desired service.
+
+- `ttl` **Number** (*Optional*) The time to live of the record.
+
+- `weight` **Number** (*Optional*) The relative weight of the record's server.
+
+
+## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
+- `full_name` **String** The full name of the SRV record.
+
+- `id` **String** ID of the resource.
+
+
+## Import
+
+Public DNS records can be imported using the `id` in the form `//`, e.g.
+
+```shell
+terraform import vkcs_publicdns_record.record 7582c61b-99b7-4730-a74f-7062fbadb94c/a/96b11adf-2627-4a06-bceb-a7f3b61b709e
+```
diff --git a/docs/resources/vkcs_publicdns_zone.md b/docs/resources/vkcs_publicdns_zone.md
new file mode 100644
index 00000000..c97db8d8
--- /dev/null
+++ b/docs/resources/vkcs_publicdns_zone.md
@@ -0,0 +1,55 @@
+---
+layout: "vkcs"
+page_title: "vkcs: vkcs_publicdns_zone"
+description: |-
+ Manages a public DNS zone.
+---
+
+# vkcs_publicdns_zone
+
+Manages a public DNS record resource within VKCS. **New since v.0.2.0**.
+
+## Example Usage
+```terraform
+resource "vkcs_publicdns_zone" "zone" {
+ zone = local.zone_name
+ primary_dns = "ns1.mcs.mail.ru"
+ admin_email = "admin@example.com"
+ expire = 3600000
+}
+```
+## Argument Reference
+- `zone` **String** (***Required***) The name of the zone. **Changes this creates a new zone**.
+
+- `admin_email` **String** (*Optional*) The admin email of the zone SOA.
+
+- `expire` **Number** (*Optional*) The expire time of the zone SOA.
+
+- `primary_dns` **String** (*Optional*) The primary DNS of the zone SOA.
+
+- `refresh` **Number** (*Optional*) The refresh time of the zone SOA.
+
+- `region` **String** (*Optional*) The region in which to obtain the V2 Public DNS client. If omitted, the `region` argument of the provider is used. Changing this creates a new zone.
+
+- `retry` **Number** (*Optional*) The retry time of the zone SOA.
+
+- `ttl` **Number** (*Optional*) The TTL (time to live) of the zone SOA.
+
+
+## Attributes Reference
+In addition to all arguments above, the following attributes are exported:
+- `id` **String** ID of the resource.
+
+- `serial` **Number** The serial number of the zone SOA.
+
+- `status` **String** The status of the zone.
+
+
+
+## Import
+
+Public DNS zones can be imported using the `id`, e.g.
+
+```shell
+terraform import vkcs_publicdns_zone.zone b758c4e5-ec13-4dfa-8458-b8502625499c
+```
diff --git a/docs/resources/vkcs_sharedfilesystem_securityservice.md b/docs/resources/vkcs_sharedfilesystem_securityservice.md
index ab137263..5632f1bd 100644
--- a/docs/resources/vkcs_sharedfilesystem_securityservice.md
+++ b/docs/resources/vkcs_sharedfilesystem_securityservice.md
@@ -48,24 +48,7 @@ resource "vkcs_sharedfilesystem_securityservice" "securityservice_1" {
## Attributes Reference
-- `type` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `dns_ip` **String** See Argument Reference above.
-
-- `domain` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `password` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `server` **String** See Argument Reference above.
-
-- `user` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
- `project_id` **String** The owner of the Security Service.
diff --git a/docs/resources/vkcs_sharedfilesystem_share.md b/docs/resources/vkcs_sharedfilesystem_share.md
index 717d2d64..ce449dea 100644
--- a/docs/resources/vkcs_sharedfilesystem_share.md
+++ b/docs/resources/vkcs_sharedfilesystem_share.md
@@ -59,26 +59,11 @@ resource "vkcs_sharedfilesystem_share" "share_1" {
## Attributes Reference
-- `name` **String** See Argument Reference above.
-
-- `share_network_id` **String** See Argument Reference above.
-
-- `share_proto` **String** See Argument Reference above.
-
-- `size` **Number** See Argument Reference above.
-
-- `availability_zone` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `share_type` **String** See Argument Reference above.
-
-- `snapshot_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `all_metadata` Map of **String** The map of metadata, assigned on the share, which has been explicitly and implicitly added.
+- `export_location_path` **String** The export location path of the share. **New since v.0.1.15**.
+
- `id` **String** ID of the resource.
- `project_id` **String** The owner of the Share.
diff --git a/docs/resources/vkcs_sharedfilesystem_share_access.md b/docs/resources/vkcs_sharedfilesystem_share_access.md
index b5112419..8c84f103 100644
--- a/docs/resources/vkcs_sharedfilesystem_share_access.md
+++ b/docs/resources/vkcs_sharedfilesystem_share_access.md
@@ -119,16 +119,7 @@ resource "vkcs_sharedfilesystem_share_access" "share_access_2" {
## Attributes Reference
-- `access_level` **String** See Argument Reference above.
-
-- `access_to` **String** See Argument Reference above.
-
-- `access_type` **String** See Argument Reference above.
-
-- `share_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_sharedfilesystem_sharenetwork.md b/docs/resources/vkcs_sharedfilesystem_sharenetwork.md
index 391c33f6..1c44a30e 100644
--- a/docs/resources/vkcs_sharedfilesystem_sharenetwork.md
+++ b/docs/resources/vkcs_sharedfilesystem_sharenetwork.md
@@ -84,18 +84,7 @@ resource "vkcs_sharedfilesystem_sharenetwork" "sharenetwork_1" {
## Attributes Reference
-- `neutron_net_id` **String** See Argument Reference above.
-
-- `neutron_subnet_id` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `security_service_ids` Set of **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `cidr` **String** The share network CIDR.
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_vpnaas_endpoint_group.md b/docs/resources/vkcs_vpnaas_endpoint_group.md
index 99759627..a79653a4 100644
--- a/docs/resources/vkcs_vpnaas_endpoint_group.md
+++ b/docs/resources/vkcs_vpnaas_endpoint_group.md
@@ -33,16 +33,7 @@ resource "vkcs_vpnaas_endpoint_group" "group_1" {
## Attributes Reference
-- `description` **String** See Argument Reference above.
-
-- `endpoints` Set of **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `type` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_vpnaas_ike_policy.md b/docs/resources/vkcs_vpnaas_ike_policy.md
index 3731c7e9..11fb5505 100644
--- a/docs/resources/vkcs_vpnaas_ike_policy.md
+++ b/docs/resources/vkcs_vpnaas_ike_policy.md
@@ -39,27 +39,7 @@ resource "vkcs_vpnaas_ike_policy" "policy_2" {
## Attributes Reference
-- `auth_algorithm` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `encryption_algorithm` **String** See Argument Reference above.
-
-- `ike_version` **String** See Argument Reference above.
-
-- `lifetime` See Argument Reference above.
- - `units` **String** See Argument Reference above.
-
- - `value` **Number** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `pfs` **String** See Argument Reference above.
-
-- `phase1_negotiation_mode` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_vpnaas_ipsec_policy.md b/docs/resources/vkcs_vpnaas_ipsec_policy.md
index 18306f5a..23616e0c 100644
--- a/docs/resources/vkcs_vpnaas_ipsec_policy.md
+++ b/docs/resources/vkcs_vpnaas_ipsec_policy.md
@@ -39,27 +39,7 @@ resource "vkcs_vpnaas_ipsec_policy" "policy_1" {
## Attributes Reference
-- `auth_algorithm` **String** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `encapsulation_mode` **String** See Argument Reference above.
-
-- `encryption_algorithm` **String** See Argument Reference above.
-
-- `lifetime` See Argument Reference above.
- - `units` **String** See Argument Reference above.
-
- - `value` **Number** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `pfs` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `transform_protocol` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/docs/resources/vkcs_vpnaas_service.md b/docs/resources/vkcs_vpnaas_service.md
index 940f5ef4..d89e0d85 100644
--- a/docs/resources/vkcs_vpnaas_service.md
+++ b/docs/resources/vkcs_vpnaas_service.md
@@ -32,18 +32,7 @@ resource "vkcs_vpnaas_service" "service_1" {
## Attributes Reference
-- `router_id` **String** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
-- `subnet_id` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `external_v4_ip` **String** The read-only external (public) IPv4 address that is used for the VPN service.
- `external_v6_ip` **String** The read-only external (public) IPv6 address that is used for the VPN service.
diff --git a/docs/resources/vkcs_vpnaas_site_connection.md b/docs/resources/vkcs_vpnaas_site_connection.md
index 2f79950d..c01ef373 100644
--- a/docs/resources/vkcs_vpnaas_site_connection.md
+++ b/docs/resources/vkcs_vpnaas_site_connection.md
@@ -92,45 +92,7 @@ resource "vkcs_vpnaas_site_connection" "connection" {
## Attributes Reference
-- `ikepolicy_id` **String** See Argument Reference above.
-
-- `ipsecpolicy_id` **String** See Argument Reference above.
-
-- `peer_address` **String** See Argument Reference above.
-
-- `peer_id` **String** See Argument Reference above.
-
-- `psk` **String** See Argument Reference above.
-
-- `vpnservice_id` **String** See Argument Reference above.
-
-- `admin_state_up` **Boolean** See Argument Reference above.
-
-- `description` **String** See Argument Reference above.
-
-- `dpd` See Argument Reference above.
- - `action` **String** See Argument Reference above.
-
- - `interval` **Number** See Argument Reference above.
-
- - `timeout` **Number** See Argument Reference above.
-
-- `initiator` **String** See Argument Reference above.
-
-- `local_ep_group_id` **String** See Argument Reference above.
-
-- `local_id` **String** See Argument Reference above.
-
-- `mtu` **Number** See Argument Reference above.
-
-- `name` **String** See Argument Reference above.
-
-- `peer_cidrs` **String** See Argument Reference above.
-
-- `peer_ep_group_id` **String** See Argument Reference above.
-
-- `region` **String** See Argument Reference above.
-
+In addition to all arguments above, the following attributes are exported:
- `id` **String** ID of the resource.
diff --git a/examples/README.md b/examples/README.md
index c4361860..8c585c7c 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -12,13 +12,12 @@
Examples are used by canary tests on vkcs side to verify the latests terraform
and vkcs provider over vkcs cloud.
- Also examples are used by developers manually or via CI (**in construction**)
- to verify changes.
+ Also examples are used by developers manually or via CI to verify changes.
-- Documentation generator (**in construction**)
+- Documentation generator
- Some examples are planned to be built inside documentation on guide/resource pages
- by documentation generator.
+ Documentation is automatically generated using examples that are located here
+ and with additional examples from templates folder.
## Running an example
diff --git a/examples/update-vkcs-db-cluster-with-shards/main.tf b/examples/update-vkcs-db-cluster-with-shards/main.tf
index c2e8b12d..cf03ee89 100755
--- a/examples/update-vkcs-db-cluster-with-shards/main.tf
+++ b/examples/update-vkcs-db-cluster-with-shards/main.tf
@@ -1,51 +1,51 @@
-terraform {
- required_providers {
- vkcs = {
- source = "vk-cs/vkcs"
- version = "~> 0.1.0"
- }
- }
-}
-
-data "vkcs_compute_flavor" "db" {
- name = var.db-instance-flavor
-}
-
-resource "vkcs_networking_network" "db" {
- name = "db-net"
-}
-
-resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
- name = "db-cluster-with-shards"
-
- datastore {
- type = "clickhouse"
- version = "20"
- }
-
- shard {
- size = 2
- shard_id = "shard0"
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 12
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
- }
-
- shard {
- size = 2
- shard_id = "shard1"
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 12
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
- }
-}
\ No newline at end of file
+terraform {
+ required_providers {
+ vkcs = {
+ source = "vk-cs/vkcs"
+ version = "~> 0.1.0"
+ }
+ }
+}
+
+data "vkcs_compute_flavor" "db" {
+ name = var.db-instance-flavor
+}
+
+resource "vkcs_networking_network" "db" {
+ name = "db-net"
+}
+
+resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
+ name = "db-cluster-with-shards"
+
+ datastore {
+ type = "clickhouse"
+ version = "20"
+ }
+
+ shard {
+ size = 2
+ shard_id = "shard0"
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ volume_size = 12
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+ }
+
+ shard {
+ size = 2
+ shard_id = "shard1"
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ volume_size = 12
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+ }
+}
diff --git a/examples/update-vkcs-db-cluster/main.tf b/examples/update-vkcs-db-cluster/main.tf
index 6a2a7656..403b0668 100755
--- a/examples/update-vkcs-db-cluster/main.tf
+++ b/examples/update-vkcs-db-cluster/main.tf
@@ -1,36 +1,36 @@
-terraform {
- required_providers {
- vkcs = {
- source = "vk-cs/vkcs"
- version = "~> 0.1.0"
- }
- }
-}
-
-data "vkcs_compute_flavor" "db" {
- name = var.db-instance-flavor
-}
-
-resource "vkcs_networking_network" "db" {
- name = "db-net"
-}
-
-resource "vkcs_db_cluster" "db-cluster" {
- name = "db-cluster"
-
- datastore {
- type = "postgresql"
- version = "12"
- }
-
- cluster_size = 5
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 12
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-}
\ No newline at end of file
+terraform {
+ required_providers {
+ vkcs = {
+ source = "vk-cs/vkcs"
+ version = "~> 0.1.0"
+ }
+ }
+}
+
+data "vkcs_compute_flavor" "db" {
+ name = var.db-instance-flavor
+}
+
+resource "vkcs_networking_network" "db" {
+ name = "db-net"
+}
+
+resource "vkcs_db_cluster" "db-cluster" {
+ name = "db-cluster"
+
+ datastore {
+ type = "postgresql"
+ version = "12"
+ }
+
+ cluster_size = 5
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ volume_size = 12
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+}
diff --git a/examples/update-vkcs-db-instance/main.tf b/examples/update-vkcs-db-instance/main.tf
index 05226d8a..d9ff4796 100755
--- a/examples/update-vkcs-db-instance/main.tf
+++ b/examples/update-vkcs-db-instance/main.tf
@@ -1,53 +1,53 @@
-terraform {
- required_providers {
- vkcs = {
- source = "vk-cs/vkcs"
- version = "~> 0.1.0"
- }
- }
-}
-
-data "vkcs_compute_flavor" "db" {
- name = var.db-instance-flavor
-}
-
-resource "vkcs_compute_keypair" "keypair" {
- name = "default"
- public_key = file(var.public-key-file)
-}
-
-resource "vkcs_networking_network" "db" {
- name = "db-net"
-}
-
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- keypair = vkcs_compute_keypair.keypair.id
- public_access = true
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 10
- volume_type = "ceph-ssd"
- disk_autoexpand {
- autoexpand = true
- max_disk_size = 1000
- }
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- capabilities {
- name = "node_exporter"
- settings = {
- "listen_port" : "9100"
- }
- }
-}
\ No newline at end of file
+terraform {
+ required_providers {
+ vkcs = {
+ source = "vk-cs/vkcs"
+ version = "~> 0.1.0"
+ }
+ }
+}
+
+data "vkcs_compute_flavor" "db" {
+ name = var.db-instance-flavor
+}
+
+resource "vkcs_compute_keypair" "keypair" {
+ name = "default"
+ public_key = file(var.public-key-file)
+}
+
+resource "vkcs_networking_network" "db" {
+ name = "db-net"
+}
+
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ keypair = vkcs_compute_keypair.keypair.id
+ public_access = true
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 10
+ volume_type = "ceph-ssd"
+ disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 1000
+ }
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ capabilities {
+ name = "node_exporter"
+ settings = {
+ "listen_port" : "9100"
+ }
+ }
+}
diff --git a/examples/vkcs-db-instance-root-user-create/main.tf b/examples/vkcs-db-instance-root-user-create/main.tf
index 2beae60d..1df165b9 100755
--- a/examples/vkcs-db-instance-root-user-create/main.tf
+++ b/examples/vkcs-db-instance-root-user-create/main.tf
@@ -1,30 +1,29 @@
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "postgresql"
- version = "13"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- root_enabled = true
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
-
-output "root_user_password" {
- value = vkcs_db_instance.db-instance.root_password
- sensitive = true
-}
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "postgresql"
+ version = "13"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ root_enabled = true
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+output "root_user_password" {
+ value = vkcs_db_instance.db-instance.root_password
+ sensitive = true
+}
diff --git a/examples/vkcs-db-instance-with-replica-create/main.tf b/examples/vkcs-db-instance-with-replica-create/main.tf
index 4c46c38b..08253a0d 100755
--- a/examples/vkcs-db-instance-with-replica-create/main.tf
+++ b/examples/vkcs-db-instance-with-replica-create/main.tf
@@ -1,53 +1,52 @@
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
- disk_autoexpand {
- autoexpand = true
- max_disk_size = 1000
- }
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- capabilities {
- name = "node_exporter"
- settings = {
- "listen_port" : "9100"
- }
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
-
-resource "vkcs_db_instance" "db-replica" {
- name = "db-instance-replica"
- datastore {
- type = "mysql"
- version = "5.7"
- }
- replica_of = vkcs_db_instance.db-instance.id
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-}
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+ disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 1000
+ }
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ capabilities {
+ name = "node_exporter"
+ settings = {
+ "listen_port" : "9100"
+ }
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+resource "vkcs_db_instance" "db-replica" {
+ name = "db-instance-replica"
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+ replica_of = vkcs_db_instance.db-instance.id
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+}
diff --git a/examples/vkcs-db-instance-with-wal-create/main.tf b/examples/vkcs-db-instance-with-wal-create/main.tf
index 61334987..c2138095 100755
--- a/examples/vkcs-db-instance-with-wal-create/main.tf
+++ b/examples/vkcs-db-instance-with-wal-create/main.tf
@@ -1,37 +1,36 @@
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "postgresql"
- version = "11"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 10
- volume_type = "ceph-ssd"
- disk_autoexpand {
- autoexpand = true
- max_disk_size = 1000
- }
- wal_volume {
- size = 10
- volume_type = "ceph-ssd"
- }
-
- wal_disk_autoexpand {
- autoexpand = true
- max_disk_size = 20
- }
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "postgresql"
+ version = "11"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 10
+ volume_type = "ceph-ssd"
+ disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 1000
+ }
+ wal_volume {
+ size = 10
+ volume_type = "ceph-ssd"
+ }
+
+ wal_disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 20
+ }
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
diff --git a/examples/vkcs-sharedfilesystem-share-create/main.tf b/examples/vkcs-sharedfilesystem-share-create/main.tf
index 63c8c3d5..5cd85f78 100644
--- a/examples/vkcs-sharedfilesystem-share-create/main.tf
+++ b/examples/vkcs-sharedfilesystem-share-create/main.tf
@@ -26,3 +26,14 @@ resource "vkcs_sharedfilesystem_share_access" "share_access_2" {
access_to = "192.168.199.11"
access_level = "rw"
}
+
+locals {
+ mount_type = lower(vkcs_sharedfilesystem_share.share.share_proto)
+ mount_device = vkcs_sharedfilesystem_share.share.export_location_path
+ mount_dir = "/${vkcs_sharedfilesystem_share.share.name}"
+}
+
+output "mount" {
+ value = "mount -t ${local.mount_type} ${local.mount_device} ${local.mount_dir}"
+ description = "Mount to vkcs_sharedfilestystem_share"
+}
diff --git a/examples/vkcs_db_backup/main.tf b/examples/vkcs_db_backup/main.tf
index b19fa36b..bf35d98b 100755
--- a/examples/vkcs_db_backup/main.tf
+++ b/examples/vkcs_db_backup/main.tf
@@ -1,40 +1,39 @@
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
- disk_autoexpand {
- autoexpand = true
- max_disk_size = 1000
- }
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- capabilities {
- name = "node_exporter"
- settings = {
- "listen_port" : "9100"
- }
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
-
-resource "vkcs_db_backup" "db-backup" {
- name = "db-backup"
- dbms_id = vkcs_db_instance.db-instance.id
-}
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+ disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 1000
+ }
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ capabilities {
+ name = "node_exporter"
+ settings = {
+ "listen_port" : "9100"
+ }
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+resource "vkcs_db_backup" "db-backup" {
+ name = "db-backup"
+ dbms_id = vkcs_db_instance.db-instance.id
+}
diff --git a/examples/vkcs_db_cluster/main.tf b/examples/vkcs_db_cluster/main.tf
index 35201522..668fbb0d 100755
--- a/examples/vkcs_db_cluster/main.tf
+++ b/examples/vkcs_db_cluster/main.tf
@@ -1,25 +1,38 @@
-resource "vkcs_db_cluster" "db-cluster" {
- name = "db-cluster"
-
- availability_zone = "GZ1"
- datastore {
- type = "postgresql"
- version = "12"
- }
-
- cluster_size = 3
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 10
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
+resource "vkcs_db_cluster" "db-cluster" {
+ name = "db-cluster"
+
+ availability_zone = "GZ1"
+ datastore {
+ type = "postgresql"
+ version = "12"
+ }
+
+ cluster_size = 3
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+ cloud_monitoring_enabled = true
+
+ volume_size = 10
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+data "vkcs_lb_loadbalancer" "loadbalancer" {
+ id = "${vkcs_db_cluster.db-cluster.loadbalancer_id}"
+}
+
+data "vkcs_networking_port" "loadbalancer-port" {
+ port_id = "${data.vkcs_lb_loadbalancer.loadbalancer.vip_port_id}"
+}
+
+output "cluster_ips" {
+ value = "${data.vkcs_networking_port.loadbalancer-port.all_fixed_ips}"
+ description = "IP addresses of the cluster."
+}
diff --git a/examples/vkcs_db_cluster_with_shards/base.tf b/examples/vkcs_db_cluster_with_shards/base.tf
index eb75e699..0fa6f917 100644
--- a/examples/vkcs_db_cluster_with_shards/base.tf
+++ b/examples/vkcs_db_cluster_with_shards/base.tf
@@ -27,3 +27,19 @@ resource "vkcs_networking_router_interface" "db" {
router_id = vkcs_networking_router.db.id
subnet_id = vkcs_networking_subnet.db.id
}
+
+resource "vkcs_networking_secgroup" "secgroup" {
+ name = "security_group"
+ description = "terraform security group"
+}
+
+resource "vkcs_networking_secgroup_rule" "secgroup_rule_1" {
+ direction = "ingress"
+ ethertype = "IPv4"
+ port_range_max = 22
+ port_range_min = 22
+ protocol = "tcp"
+ remote_ip_prefix = "0.0.0.0/0"
+ security_group_id = vkcs_networking_secgroup.secgroup.id
+ description = "secgroup_rule_1"
+}
diff --git a/examples/vkcs_db_cluster_with_shards/main.tf b/examples/vkcs_db_cluster_with_shards/main.tf
index a3807904..2aed7987 100755
--- a/examples/vkcs_db_cluster_with_shards/main.tf
+++ b/examples/vkcs_db_cluster_with_shards/main.tf
@@ -1,41 +1,60 @@
-resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
- name = "db-cluster-with-shards"
-
- datastore {
- type = "clickhouse"
- version = "20.8"
- }
-
- shard {
- availability_zone = "GZ1"
- size = 1
- shard_id = "shard0"
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
- }
-
- shard {
- availability_zone = "GZ1"
- size = 1
- shard_id = "shard1"
- flavor_id = data.vkcs_compute_flavor.db.id
-
- volume_size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
+resource "vkcs_db_cluster_with_shards" "db-cluster-with-shards" {
+ name = "db-cluster-with-shards"
+
+ datastore {
+ type = "clickhouse"
+ version = "20.8"
+ }
+
+ cloud_monitoring_enabled = true
+
+ shard {
+ availability_zone = "GZ1"
+ size = 1
+ shard_id = "shard0"
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ volume_size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ security_groups = [vkcs_networking_secgroup.secgroup.id]
+ }
+ }
+
+ shard {
+ availability_zone = "GZ1"
+ size = 1
+ shard_id = "shard1"
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ volume_size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ security_groups = [vkcs_networking_secgroup.secgroup.id]
+ }
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db,
+ vkcs_networking_secgroup.secgroup
+ ]
+}
+
+locals {
+ cluster = vkcs_db_cluster_with_shards.db-cluster-with-shards
+ shards_ips = {
+ for shard in local.cluster.shard : shard.shard_id => [for i in shard.instances : {
+ "internal_ip" = i.ip[0]
+ "external_ip" = length(i.ip) > 1 ? i.ip[1] : null
+ }]
+ }
+}
+
+output "shard0-ips" {
+ value = local.shards_ips["shard0"]
+ description = "IPs of instances in shard with \"id\" = \"shard0\""
+}
diff --git a/examples/vkcs_db_config_group/main.tf b/examples/vkcs_db_config_group/main.tf
index a8cd2d7c..82381729 100644
--- a/examples/vkcs_db_config_group/main.tf
+++ b/examples/vkcs_db_config_group/main.tf
@@ -31,4 +31,8 @@ resource "vkcs_db_instance" "db-instance" {
flavor_id = data.vkcs_compute_flavor.db.id
volume_type = "ceph-ssd"
size = 8
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
}
diff --git a/examples/vkcs_db_database/main.tf b/examples/vkcs_db_database/main.tf
index bec7570e..25fca4c5 100755
--- a/examples/vkcs_db_database/main.tf
+++ b/examples/vkcs_db_database/main.tf
@@ -1,31 +1,30 @@
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
-
-resource "vkcs_db_database" "db-database" {
- name = "testdb"
- dbms_id = vkcs_db_instance.db-instance.id
- charset = "utf8"
- collate = "utf8_general_ci"
-}
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+resource "vkcs_db_database" "db-database" {
+ name = "testdb"
+ dbms_id = vkcs_db_instance.db-instance.id
+ charset = "utf8"
+ collate = "utf8_general_ci"
+}
diff --git a/examples/vkcs_db_instance/base.tf b/examples/vkcs_db_instance/base.tf
index eb75e699..0fa6f917 100644
--- a/examples/vkcs_db_instance/base.tf
+++ b/examples/vkcs_db_instance/base.tf
@@ -27,3 +27,19 @@ resource "vkcs_networking_router_interface" "db" {
router_id = vkcs_networking_router.db.id
subnet_id = vkcs_networking_subnet.db.id
}
+
+resource "vkcs_networking_secgroup" "secgroup" {
+ name = "security_group"
+ description = "terraform security group"
+}
+
+resource "vkcs_networking_secgroup_rule" "secgroup_rule_1" {
+ direction = "ingress"
+ ethertype = "IPv4"
+ port_range_max = 22
+ port_range_min = 22
+ protocol = "tcp"
+ remote_ip_prefix = "0.0.0.0/0"
+ security_group_id = vkcs_networking_secgroup.secgroup.id
+ description = "secgroup_rule_1"
+}
diff --git a/examples/vkcs_db_instance/main.tf b/examples/vkcs_db_instance/main.tf
index fa8794d9..a7578778 100755
--- a/examples/vkcs_db_instance/main.tf
+++ b/examples/vkcs_db_instance/main.tf
@@ -1,35 +1,37 @@
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
- disk_autoexpand {
- autoexpand = true
- max_disk_size = 1000
- }
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- capabilities {
- name = "node_exporter"
- settings = {
- "listen_port" : "9100"
- }
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+ cloud_monitoring_enabled = true
+
+ size = 8
+ volume_type = "ceph-ssd"
+ disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 1000
+ }
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ security_groups = [vkcs_networking_secgroup.secgroup.id]
+ }
+
+ capabilities {
+ name = "node_exporter"
+ settings = {
+ "listen_port" : "9100"
+ }
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db,
+ vkcs_networking_secgroup.secgroup
+ ]
+}
diff --git a/examples/vkcs_db_user/main.tf b/examples/vkcs_db_user/main.tf
index 1a0e25e4..042e434d 100755
--- a/examples/vkcs_db_user/main.tf
+++ b/examples/vkcs_db_user/main.tf
@@ -1,40 +1,39 @@
-resource "vkcs_db_instance" "db-instance" {
- name = "db-instance"
-
- availability_zone = "GZ1"
-
- datastore {
- type = "mysql"
- version = "5.7"
- }
-
- flavor_id = data.vkcs_compute_flavor.db.id
-
- size = 8
- volume_type = "ceph-ssd"
-
- network {
- uuid = vkcs_networking_network.db.id
- }
-
- depends_on = [
- vkcs_networking_network.db,
- vkcs_networking_subnet.db
- ]
-}
-
-resource "vkcs_db_database" "db-database" {
- name = "testdb"
- dbms_id = vkcs_db_instance.db-instance.id
- charset = "utf8"
- collate = "utf8_general_ci"
-}
-
-resource "vkcs_db_user" "db-user" {
- name = "testuser"
- password = "SomePass1_"
-
- dbms_id = vkcs_db_instance.db-instance.id
-
- databases = [vkcs_db_database.db-database.name]
-}
+resource "vkcs_db_instance" "db-instance" {
+ name = "db-instance"
+
+ availability_zone = "GZ1"
+
+ datastore {
+ type = "mysql"
+ version = "5.7"
+ }
+
+ flavor_id = data.vkcs_compute_flavor.db.id
+
+ size = 8
+ volume_type = "ceph-ssd"
+
+ network {
+ uuid = vkcs_networking_network.db.id
+ }
+
+ depends_on = [
+ vkcs_networking_router_interface.db
+ ]
+}
+
+resource "vkcs_db_database" "db-database" {
+ name = "testdb"
+ dbms_id = vkcs_db_instance.db-instance.id
+ charset = "utf8"
+ collate = "utf8_general_ci"
+}
+
+resource "vkcs_db_user" "db-user" {
+ name = "testuser"
+ password = "SomePass1_"
+
+ dbms_id = vkcs_db_instance.db-instance.id
+
+ databases = [vkcs_db_database.db-database.name]
+}
diff --git a/examples/vkcs_kubernetes_cluster/main.tf b/examples/vkcs_kubernetes_cluster/main.tf
index 68b92d29..4e4479af 100644
--- a/examples/vkcs_kubernetes_cluster/main.tf
+++ b/examples/vkcs_kubernetes_cluster/main.tf
@@ -1,5 +1,5 @@
data "vkcs_kubernetes_clustertemplate" "ct" {
- version = "1.21.4"
+ version = "1.24"
}
resource "vkcs_kubernetes_cluster" "k8s-cluster" {
diff --git a/examples/vkcs_kubernetes_node_group/main.tf b/examples/vkcs_kubernetes_node_group/main.tf
index e88b27b3..43114608 100644
--- a/examples/vkcs_kubernetes_node_group/main.tf
+++ b/examples/vkcs_kubernetes_node_group/main.tf
@@ -1,5 +1,5 @@
data "vkcs_kubernetes_clustertemplate" "ct" {
- version = "1.21.4"
+ version = "1.24"
}
resource "vkcs_kubernetes_cluster" "k8s-cluster" {
diff --git a/examples/vkcs_publicdns/base.tf b/examples/vkcs_publicdns/base.tf
new file mode 100644
index 00000000..4e207481
--- /dev/null
+++ b/examples/vkcs_publicdns/base.tf
@@ -0,0 +1,10 @@
+// Workaround for Terraform version < 1.4 because there is no
+// terraform_data resource
+resource "vkcs_networking_secgroup" "base" {
+ name = "test"
+ description = "Dummy security group for saving public DNS zone name"
+}
+
+locals {
+ zone_name = "example-${vkcs_networking_secgroup.base.id}.com"
+}
diff --git a/examples/vkcs_publicdns/import_record.sh b/examples/vkcs_publicdns/import_record.sh
new file mode 100644
index 00000000..d4ec4788
--- /dev/null
+++ b/examples/vkcs_publicdns/import_record.sh
@@ -0,0 +1 @@
+terraform import vkcs_publicdns_record.record 7582c61b-99b7-4730-a74f-7062fbadb94c/a/96b11adf-2627-4a06-bceb-a7f3b61b709e
diff --git a/examples/vkcs_publicdns/import_zone.sh b/examples/vkcs_publicdns/import_zone.sh
new file mode 100644
index 00000000..c0d4f5e3
--- /dev/null
+++ b/examples/vkcs_publicdns/import_zone.sh
@@ -0,0 +1 @@
+terraform import vkcs_publicdns_zone.zone b758c4e5-ec13-4dfa-8458-b8502625499c
diff --git a/examples/vkcs_publicdns/multirecord.tf b/examples/vkcs_publicdns/multirecord.tf
new file mode 100644
index 00000000..ce9b86c4
--- /dev/null
+++ b/examples/vkcs_publicdns/multirecord.tf
@@ -0,0 +1,15 @@
+locals {
+ google_public_dns_ips = tomap({
+ "ip_1" = "8.8.8.8"
+ "ip_2" = "8.8.4.4"
+ })
+}
+
+resource "vkcs_publicdns_record" "a" {
+ for_each = local.google_public_dns_ips
+ zone_id = vkcs_publicdns_zone.zone.id
+ type = "A"
+ name = "google-dns-servers"
+ ip = each.value
+ ttl = 60
+}
diff --git a/examples/vkcs_publicdns/record.tf b/examples/vkcs_publicdns/record.tf
new file mode 100644
index 00000000..0953faf4
--- /dev/null
+++ b/examples/vkcs_publicdns/record.tf
@@ -0,0 +1,11 @@
+resource "vkcs_publicdns_record" "srv" {
+ zone_id = vkcs_publicdns_zone.zone.id
+ type = "SRV"
+ service = "_sip"
+ proto = "_udp"
+ priority = 10
+ weight = 5
+ host = "siptarget.com"
+ port = 5060
+ ttl = 60
+}
diff --git a/examples/vkcs_publicdns/zone.tf b/examples/vkcs_publicdns/zone.tf
new file mode 100644
index 00000000..dcccdca4
--- /dev/null
+++ b/examples/vkcs_publicdns/zone.tf
@@ -0,0 +1,6 @@
+resource "vkcs_publicdns_zone" "zone" {
+ zone = local.zone_name
+ primary_dns = "ns1.mcs.mail.ru"
+ admin_email = "admin@example.com"
+ expire = 3600000
+}
diff --git a/go.mod b/go.mod
index 60101967..356fdaac 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.18
require (
github.com/gophercloud/gophercloud v0.24.0
github.com/gophercloud/utils v0.0.0-20220307143606-8e7800759d16
+ github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/terraform-plugin-sdk/v2 v2.16.0
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.5.0
@@ -23,7 +24,6 @@ require (
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-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
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.4 // indirect
@@ -53,9 +53,9 @@ require (
github.com/vmihailenco/tagparser v0.1.2 // indirect
github.com/zclconf/go-cty v1.10.0 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
- golang.org/x/net v0.0.0-20220526153639-5463443f8c37 // indirect
- golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
- golang.org/x/text v0.3.7 // indirect
+ golang.org/x/net v0.7.0 // indirect
+ golang.org/x/sys v0.5.0 // indirect
+ golang.org/x/text v0.7.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220525015930-6ca3db687a9d // indirect
google.golang.org/grpc v1.46.2 // indirect
diff --git a/go.sum b/go.sum
index ad8d078c..24271deb 100644
--- a/go.sum
+++ b/go.sum
@@ -260,8 +260,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8=
-golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -295,18 +295,18 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
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-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
diff --git a/templates/data-sources/vkcs_db_datastore.md.tmpl b/templates/data-sources/vkcs_db_datastore.md.tmpl
new file mode 100644
index 00000000..05db8598
--- /dev/null
+++ b/templates/data-sources/vkcs_db_datastore.md.tmpl
@@ -0,0 +1,16 @@
+---
+layout: "vkcs"
+page_title: "vkcs: {{.Name}}"
+description: |-
+ Get information on a VKCS db datastore.
+---
+
+# {{.Name}}
+
+{{ .Description }}
+
+## Example Usage
+
+{{tffile .ExampleFile}}
+
+{{ .SchemaMarkdown }}
diff --git a/templates/data-sources/vkcs_db_datastore/main.tf b/templates/data-sources/vkcs_db_datastore/main.tf
new file mode 100644
index 00000000..0a222bf9
--- /dev/null
+++ b/templates/data-sources/vkcs_db_datastore/main.tf
@@ -0,0 +1,8 @@
+data "vkcs_db_datastore" "datastore" {
+ name = "mysql"
+}
+
+output "mysql_versions" {
+ value = data.vkcs_db_datastore.datastore.versions
+ description = "List of versions of MySQL that are available within VKCS."
+}
diff --git a/templates/data-sources/vkcs_db_datastore_capabilities.md.tmpl b/templates/data-sources/vkcs_db_datastore_capabilities.md.tmpl
new file mode 100644
index 00000000..95620876
--- /dev/null
+++ b/templates/data-sources/vkcs_db_datastore_capabilities.md.tmpl
@@ -0,0 +1,16 @@
+---
+layout: "vkcs"
+page_title: "vkcs: {{.Name}}"
+description: |-
+ Get information on capabilities supported for a VKCS db datastore.
+---
+
+# {{.Name}}
+
+{{ .Description }}
+
+## Example Usage
+
+{{tffile .ExampleFile}}
+
+{{ .SchemaMarkdown }}
diff --git a/templates/data-sources/vkcs_db_datastore_capabilities/main.tf b/templates/data-sources/vkcs_db_datastore_capabilities/main.tf
new file mode 100644
index 00000000..8099f319
--- /dev/null
+++ b/templates/data-sources/vkcs_db_datastore_capabilities/main.tf
@@ -0,0 +1,9 @@
+data "vkcs_db_datastore_capabilities" "postgres_caps" {
+ datastore_name = data.vkcs_db_datastore.postgres
+ datastore_version_id = local.pg_v14_version_id
+}
+
+output "postgresql_capabilities" {
+ value = data.vkcs_db_datastore_capabilities.postgres_caps.capabilities
+ description = "Available capabilities of the latest version of PostgreSQL datastore."
+}
diff --git a/templates/data-sources/vkcs_db_datastore_parameters.md.tmpl b/templates/data-sources/vkcs_db_datastore_parameters.md.tmpl
new file mode 100644
index 00000000..fa9da003
--- /dev/null
+++ b/templates/data-sources/vkcs_db_datastore_parameters.md.tmpl
@@ -0,0 +1,16 @@
+---
+layout: "vkcs"
+page_title: "vkcs: {{.Name}}"
+description: |-
+ Get information on configuration parameters supported for a VKCS db datastore.
+---
+
+# {{.Name}}
+
+{{ .Description }}
+
+## Example Usage
+
+{{tffile .ExampleFile}}
+
+{{ .SchemaMarkdown }}
diff --git a/templates/data-sources/vkcs_db_datastore_parameters/main.tf b/templates/data-sources/vkcs_db_datastore_parameters/main.tf
new file mode 100644
index 00000000..860731c5
--- /dev/null
+++ b/templates/data-sources/vkcs_db_datastore_parameters/main.tf
@@ -0,0 +1,9 @@
+data "vkcs_db_datastore_parameters" "mysql_params" {
+ datastore_name = data.vkcs_db_datastore.mysql
+ datastore_version_id = local.mysql_v8_version_id
+}
+
+output "mysql_parameters" {
+ value = data.vkcs_db_datastore_parameters.mysql_params.parameters
+ description = "Available configuration parameters of the latest version of MySQL datastore."
+}
diff --git a/templates/data-sources/vkcs_db_datastores.md.tmpl b/templates/data-sources/vkcs_db_datastores.md.tmpl
new file mode 100644
index 00000000..59156b1c
--- /dev/null
+++ b/templates/data-sources/vkcs_db_datastores.md.tmpl
@@ -0,0 +1,16 @@
+---
+layout: "vkcs"
+page_title: "vkcs: {{.Name}}"
+description: |-
+ Get information on db datastores that are available within VKCS.
+---
+
+# {{.Name}}
+
+{{ .Description }}
+
+## Example Usage
+
+{{tffile .ExampleFile}}
+
+{{ .SchemaMarkdown }}
diff --git a/templates/data-sources/vkcs_db_datastores/main.tf b/templates/data-sources/vkcs_db_datastores/main.tf
new file mode 100644
index 00000000..92ff8801
--- /dev/null
+++ b/templates/data-sources/vkcs_db_datastores/main.tf
@@ -0,0 +1,6 @@
+data "vkcs_db_datastores" "datastores" {}
+
+output "available_datastores" {
+ value = data.vkcs_db_datastores.datastores.datastores
+ description = "List of datastores that are available within VKCS."
+}
diff --git a/templates/data-sources/vkcs_lb_loadbalancer.md.tmpl b/templates/data-sources/vkcs_lb_loadbalancer.md.tmpl
new file mode 100644
index 00000000..9beeea9e
--- /dev/null
+++ b/templates/data-sources/vkcs_lb_loadbalancer.md.tmpl
@@ -0,0 +1,16 @@
+---
+layout: "vkcs"
+page_title: "vkcs: {{.Name}}"
+description: |-
+ Get information on a VKCS Loadbalancer
+---
+
+# {{.Name}}
+
+{{ .Description }}
+
+## Example Usage
+
+{{tffile .ExampleFile}}
+
+{{ .SchemaMarkdown }}
diff --git a/templates/data-sources/vkcs_lb_loadbalancer/main.tf b/templates/data-sources/vkcs_lb_loadbalancer/main.tf
new file mode 100644
index 00000000..6535098f
--- /dev/null
+++ b/templates/data-sources/vkcs_lb_loadbalancer/main.tf
@@ -0,0 +1,3 @@
+data "vkcs_lb_loadbalancer" "loadbalancer" {
+ id = "35082f6e-14c4-478c-ba4c-77bcdb222743"
+}
diff --git a/templates/data-sources/vkcs_publicdns_zone.md.tmpl b/templates/data-sources/vkcs_publicdns_zone.md.tmpl
new file mode 100644
index 00000000..7a3b5f38
--- /dev/null
+++ b/templates/data-sources/vkcs_publicdns_zone.md.tmpl
@@ -0,0 +1,16 @@
+---
+layout: "vkcs"
+page_title: "vkcs: {{.Name}}"
+description: |-
+ Get information on a public DNS zone.
+---
+
+# {{.Name}}
+
+{{ .Description }}
+
+## Example Usage
+
+{{tffile .ExampleFile}}
+
+{{ .SchemaMarkdown }}
diff --git a/templates/data-sources/vkcs_publicdns_zone/main.tf b/templates/data-sources/vkcs_publicdns_zone/main.tf
new file mode 100644
index 00000000..45d94175
--- /dev/null
+++ b/templates/data-sources/vkcs_publicdns_zone/main.tf
@@ -0,0 +1,3 @@
+data "vkcs_publicdns_zone" "zone" {
+ zone = "example.com"
+}
diff --git a/templates/resources/vkcs_publicdns_record.md.tmpl b/templates/resources/vkcs_publicdns_record.md.tmpl
new file mode 100644
index 00000000..21c79f93
--- /dev/null
+++ b/templates/resources/vkcs_publicdns_record.md.tmpl
@@ -0,0 +1,24 @@
+---
+layout: "vkcs"
+page_title: "vkcs: {{.Name}}"
+description: |-
+ Manages a public DNS record.
+---
+
+# {{.Name}}
+
+{{ .Description }}
+
+## Example Usage
+### Single record
+{{tffile "examples/vkcs_publicdns/record.tf"}}
+
+### Multiple A records
+{{tffile "examples/vkcs_publicdns/multirecord.tf"}}
+
+{{ .SchemaMarkdown }}
+## Import
+
+Public DNS records can be imported using the `id` in the form `//`, e.g.
+
+{{codefile "shell" "examples/vkcs_publicdns/import_record.sh"}}
diff --git a/templates/resources/vkcs_publicdns_zone.md.tmpl b/templates/resources/vkcs_publicdns_zone.md.tmpl
new file mode 100644
index 00000000..8c4e1572
--- /dev/null
+++ b/templates/resources/vkcs_publicdns_zone.md.tmpl
@@ -0,0 +1,20 @@
+---
+layout: "vkcs"
+page_title: "vkcs: {{.Name}}"
+description: |-
+ Manages a public DNS zone.
+---
+
+# {{.Name}}
+
+{{ .Description }}
+
+## Example Usage
+{{tffile "examples/vkcs_publicdns/zone.tf"}}
+{{ .SchemaMarkdown }}
+
+## Import
+
+Public DNS zones can be imported using the `id`, e.g.
+
+{{codefile "shell" "examples/vkcs_publicdns/import_zone.sh"}}
diff --git a/vkcs/client.go b/vkcs/client.go
new file mode 100644
index 00000000..c14575cb
--- /dev/null
+++ b/vkcs/client.go
@@ -0,0 +1,22 @@
+package vkcs
+
+import "github.com/gophercloud/gophercloud"
+
+func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, clientType string) (*gophercloud.ServiceClient, error) {
+ sc := new(gophercloud.ServiceClient)
+ eo.ApplyDefaults(clientType)
+ url, err := client.EndpointLocator(eo)
+ if err != nil {
+ return sc, err
+ }
+ sc.ProviderClient = client
+ sc.Endpoint = url
+ sc.Type = clientType
+ return sc, nil
+}
+
+func newPublicDNSV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
+ sc, err := initClientOpts(client, eo, "publicdns")
+ sc.ResourceBase = sc.Endpoint + "v2/"
+ return sc, err
+}
diff --git a/vkcs/compute_instance.go b/vkcs/compute_instance.go
index 6a9b19de..f2fd3bea 100755
--- a/vkcs/compute_instance.go
+++ b/vkcs/compute_instance.go
@@ -147,7 +147,7 @@ func getAllInstanceNetworks(d *schema.ResourceData, meta interface{}) ([]Instanc
func getInstanceNetworkInfo(d *schema.ResourceData, meta interface{}, queryType, queryTerm string) (map[string]interface{}, error) {
config := meta.(configer)
- networkClient, err := config.NetworkingV2Client(getRegion(d, config), getSDN(d))
+ networkClient, err := config.NetworkingV2Client(getRegion(d, config), searchInAllSDNs)
if err == nil {
networkInfo, err := getInstanceNetworkInfoNeutron(networkClient, queryType, queryTerm)
if err != nil {
@@ -290,7 +290,9 @@ func getInstanceAddresses(addresses map[string]interface{}) []InstanceAddresses
for i, v := range instanceAddresses.InstanceNICs {
if v.MAC == instanceNIC.MAC {
exists = true
- instanceAddresses.InstanceNICs[i].FixedIPv4 = instanceNIC.FixedIPv4
+ if instanceNIC.FixedIPv4 != "" {
+ instanceAddresses.InstanceNICs[i].FixedIPv4 = instanceNIC.FixedIPv4
+ }
}
}
diff --git a/vkcs/data_source_vkcs_compute_instance_test.go b/vkcs/data_source_vkcs_compute_instance_test.go
index b9fcc208..d6079cea 100644
--- a/vkcs/data_source_vkcs_compute_instance_test.go
+++ b/vkcs/data_source_vkcs_compute_instance_test.go
@@ -50,7 +50,7 @@ const testAccComputeInstanceDataSourceBasic = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
security_groups = ["default"]
metadata = {
diff --git a/vkcs/data_source_vkcs_db_config_group.go b/vkcs/data_source_vkcs_db_config_group.go
index bc5fda70..a9979e69 100644
--- a/vkcs/data_source_vkcs_db_config_group.go
+++ b/vkcs/data_source_vkcs_db_config_group.go
@@ -64,7 +64,8 @@ func dataSourceDatabaseConfigGroup() *schema.Resource {
Description: "The description of the config group.",
},
},
- Description: "Use this data source to get the information on a db config group resource.\n**New since v.0.1.7**.",
+ Description: "Use this data source to get the information on a db config group resource.\n" +
+ "**New since v.0.1.7**.",
}
}
@@ -83,7 +84,7 @@ func dataSourceDatabaseConfigGroupRead(ctx context.Context, d *schema.ResourceDa
log.Printf("[DEBUG] Retrieved vkcs_db_config_group %s: %#v", configGroupID, configGroup)
d.Set("name", configGroup.Name)
- ds := dataStore{
+ ds := dataStoreShort{
Type: configGroup.DatastoreName,
Version: configGroup.DatastoreVersionName,
}
diff --git a/vkcs/data_source_vkcs_db_datastore.go b/vkcs/data_source_vkcs_db_datastore.go
new file mode 100644
index 00000000..2ef921b3
--- /dev/null
+++ b/vkcs/data_source_vkcs_db_datastore.go
@@ -0,0 +1,159 @@
+package vkcs
+
+import (
+ "context"
+ "log"
+ "sort"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func dataSourceDatabaseDatastore() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourceDatabaseDatastoreRead,
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Computed: true,
+ Optional: true,
+ Description: "The `region` to fetch availability zones from, defaults to the provider's `region`",
+ },
+
+ "id": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The id of the datastore.",
+ },
+
+ "name": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The name of the datastore.",
+ },
+
+ "minimum_cpu": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: "Minimum CPU required for instance of the datastore.",
+ },
+
+ "minimum_ram": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: "Minimum RAM required for instance of the datastore.",
+ },
+
+ "volume_types": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: "Supported volume types for the datastore.",
+ },
+
+ "cluster_volume_types": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: "Supported volume types for the datastore when used in a cluster.",
+ },
+
+ "versions": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "ID of a version of the datastore.",
+ },
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Name of a version of the datastore.",
+ },
+ },
+ },
+ Description: "Versions of the datastore.",
+ },
+ },
+ Description: "Use this data source to get information on a VKCS db datastore. **New since v.0.2.0**.",
+ }
+}
+
+func dataSourceDatabaseDatastoreRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ region := getRegion(d, config)
+ dbClient, err := config.DatabaseV1Client(region)
+ if err != nil {
+ return diag.Errorf("Error creating VKCS database client: %s", err)
+ }
+
+ allPages, err := dataStoreList(dbClient).AllPages()
+ if err != nil {
+ return diag.Errorf("Error retrieving datastores: %s", err)
+ }
+
+ datastoresInfo, err := extractDatastores(allPages)
+ if err != nil {
+ return diag.Errorf("Error extracting datastores from response: %s", err)
+ }
+
+ id, name := d.Get("id").(string), d.Get("name").(string)
+ allDatastores := filterDatabaseDatastores(datastoresInfo, id, name)
+
+ if len(allDatastores) < 1 {
+ return diag.Errorf("Your query returned no results. " +
+ "Please change your search criteria and try again.")
+ }
+
+ if len(allDatastores) > 1 {
+ log.Printf("[DEBUG] Multiple results found: %#v", allDatastores)
+ return diag.Errorf("Your query returned more than one result. " +
+ "Please try a more specific search criteria")
+ }
+
+ dsID := allDatastores[0].ID
+ ds, err := dataStoreGet(dbClient, dsID).Extract()
+ if err != nil {
+ return diag.Errorf("Error retrieving vkcs_db_datastore: %s", err)
+ }
+
+ flattenedVersions := flattenDatabaseDatastoreVersions(ds.Versions)
+ sort.SliceStable(flattenedVersions, func(i, j int) bool {
+ return flattenedVersions[i]["name"].(string) > flattenedVersions[j]["name"].(string)
+ })
+
+ d.SetId(ds.ID)
+ d.Set("name", ds.Name)
+ d.Set("minimum_cpu", ds.MinimumCPU)
+ d.Set("minimum_ram", ds.MinimumRAM)
+ d.Set("volume_types", ds.VolumeTypes)
+ d.Set("cluster_volume_types", ds.ClusterVolumeTypes)
+ d.Set("versions", flattenedVersions)
+
+ return nil
+}
+
+func filterDatabaseDatastores(dsSlice []dataStore, id, name string) []dataStore {
+ var res []dataStore
+ for _, ds := range dsSlice {
+ if (name == "" || ds.Name == name) && (id == "" || ds.ID == id) {
+ res = append(res, ds)
+ }
+ }
+ return res
+}
+
+func flattenDatabaseDatastoreVersions(versions []dataStoreVersion) (r []map[string]interface{}) {
+ for _, v := range versions {
+ r = append(r, map[string]interface{}{
+ "id": v.ID,
+ "name": v.Name,
+ })
+ }
+ return
+}
diff --git a/vkcs/data_source_vkcs_db_datastore_capabilities.go b/vkcs/data_source_vkcs_db_datastore_capabilities.go
new file mode 100644
index 00000000..4217d5a5
--- /dev/null
+++ b/vkcs/data_source_vkcs_db_datastore_capabilities.go
@@ -0,0 +1,198 @@
+package vkcs
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func dataSourceDatabaseDatastoreCapabilities() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourceDatabaseDatastoreCapabilitiesRead,
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Computed: true,
+ Optional: true,
+ Description: "The `region` to fetch availability zones from, defaults to the provider's `region`.",
+ },
+
+ "datastore_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Name of the data store.",
+ },
+
+ "datastore_version_id": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "ID of the version of the data store.",
+ },
+
+ "capabilities": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Name of data store capability.",
+ },
+ "description": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Description of data store capability.",
+ },
+ "params": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataSourceDatabaseDatastoreCapabilitiesParam(),
+ },
+ "should_be_on_master": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "This attribute indicates whether a capability applies only to the master node.",
+ },
+ "allow_major_upgrade": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "This attribute indicates whether a capability can be applied in the next major version of data store.",
+ },
+ "allow_upgrade_from_backup": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "This attribute indicates whether a capability can be applied to upgrade from backup.",
+ },
+ },
+ },
+ Description: "Versions of the datastore.",
+ },
+ },
+ Description: "Use this data source to get capabilities supported for a VKCS datastore. **New since v.0.2.0**.",
+ }
+}
+
+func dataSourceDatabaseDatastoreCapabilitiesParam() *schema.Resource {
+ return &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Name of a parameter.",
+ },
+ "required": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "Required indicates whether a parameter value must be set.",
+ },
+ "type": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Type of value for a parameter.",
+ },
+ "element_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Type of element value for a parameter of `list` type.",
+ },
+ "enum_values": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: "Supported values for a parameter.",
+ },
+ "default_value": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Default value for a parameter.",
+ },
+ "min": {
+ Type: schema.TypeFloat,
+ Computed: true,
+ Description: "Minimum value for a parameter.",
+ },
+ "max": {
+ Type: schema.TypeFloat,
+ Computed: true,
+ Description: "Maximum value for a parameter.",
+ },
+ "regex": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Regular expression that a parameter value must match.",
+ },
+ "masked": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "Masked indicates whether a parameter value must be a boolean mask.",
+ },
+ },
+ }
+}
+
+func dataSourceDatabaseDatastoreCapabilitiesRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ region := getRegion(d, config)
+ dbClient, err := config.DatabaseV1Client(region)
+ if err != nil {
+ return diag.Errorf("Error creating VKCS database client: %s", err)
+ }
+
+ dsName := d.Get("datastore_name").(string)
+ dsVersionID := d.Get("datastore_version_id").(string)
+
+ capabilities, err := dataStoreListCapabilities(dbClient, dsName, dsVersionID).Extract()
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err, "Error retrieving vkcs_db_backup"))
+ }
+
+ flattenedCapabilities := flattenDatabaseDatastoreCapabilities(capabilities)
+
+ d.SetId(fmt.Sprintf("%s/%s/capabilities", dsName, dsVersionID))
+ d.Set("capabilities", flattenedCapabilities)
+
+ return nil
+}
+
+func flattenDatabaseDatastoreCapabilities(capabilities []dataStoreCapability) (r []map[string]interface{}) {
+ for _, c := range capabilities {
+ r = append(r, map[string]interface{}{
+ "name": c.Name,
+ "description": c.Description,
+ "params": flattenDatabaseDatastoreCapabilityParams(c.Params),
+ "should_be_on_master": c.ShouldBeOnMaster,
+ "allow_major_upgrade": c.AllowMajorUpgrade,
+ "allow_upgrade_from_backup": c.AllowUpgradeFromBackup,
+ })
+ }
+ return
+}
+
+func flattenDatabaseDatastoreCapabilityParams(params map[string]*capabilityParam) (r []map[string]interface{}) {
+ for name, p := range params {
+ var defaultValue string
+ switch v := p.DefaultValue.(type) {
+ case string:
+ defaultValue = v
+ case float64:
+ defaultValue = strconv.FormatFloat(p.DefaultValue.(float64), 'f', -1, 64)
+ }
+ r = append(r, map[string]interface{}{
+ "name": name,
+ "required": p.Required,
+ "type": p.Type,
+ "element_type": p.ElementType,
+ "enum_values": p.EnumValues,
+ "default_value": defaultValue,
+ "min": p.MinValue,
+ "max": p.MaxValue,
+ "regex": p.Regex,
+ "masked": p.Masked,
+ })
+ }
+ return
+}
diff --git a/vkcs/data_source_vkcs_db_datastore_capabilities_test.go b/vkcs/data_source_vkcs_db_datastore_capabilities_test.go
new file mode 100644
index 00000000..01e4df87
--- /dev/null
+++ b/vkcs/data_source_vkcs_db_datastore_capabilities_test.go
@@ -0,0 +1,33 @@
+package vkcs
+
+import (
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccDatabaseDatastoreCapabilitiesDataSource_basic(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDatabaseDatastoreCapabilitiesDataSourceBasic,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("data.vkcs_db_datastore_capabilities.capabilities", "datastore_name", "mysql"),
+ ),
+ },
+ },
+ })
+}
+
+const testAccDatabaseDatastoreCapabilitiesDataSourceBasic = `
+data "vkcs_db_datastore" "datastore" {
+ name = "mysql"
+}
+
+data "vkcs_db_datastore_capabilities" "capabilities" {
+ datastore_name = data.vkcs_db_datastore.datastore.name
+ datastore_version_id = data.vkcs_db_datastore.datastore.versions.0.id
+}
+`
diff --git a/vkcs/data_source_vkcs_db_datastore_parameters.go b/vkcs/data_source_vkcs_db_datastore_parameters.go
new file mode 100644
index 00000000..5d5cceb1
--- /dev/null
+++ b/vkcs/data_source_vkcs_db_datastore_parameters.go
@@ -0,0 +1,108 @@
+package vkcs
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func dataSourceDatabaseDatastoreParameters() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourceDatabaseDatastoreParametersRead,
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Computed: true,
+ Optional: true,
+ Description: "The `region` to fetch availability zones from, defaults to the provider's `region`.",
+ },
+
+ "datastore_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "Name of the data store.",
+ },
+
+ "datastore_version_id": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "ID of the version of the data store.",
+ },
+
+ "parameters": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Name of a configuration parameter.",
+ },
+ "type": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Type of a configuration parameter.",
+ },
+ "min": {
+ Type: schema.TypeFloat,
+ Computed: true,
+ Description: "Minimum value of a configuration parameter.",
+ },
+ "max": {
+ Type: schema.TypeFloat,
+ Computed: true,
+ Description: "Maximum value of a configuration parameter.",
+ },
+ "restart_required": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "This attribute indicates whether a restart required when a parameter is set.",
+ },
+ },
+ },
+ Description: "Versions of the datastore.",
+ },
+ },
+ Description: "Use this data source to get configuration parameters supported for a VKCS datastore. **New since v.0.2.0**.",
+ }
+}
+
+func dataSourceDatabaseDatastoreParametersRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ region := getRegion(d, config)
+ dbClient, err := config.DatabaseV1Client(region)
+ if err != nil {
+ return diag.Errorf("Error creating VKCS database client: %s", err)
+ }
+
+ dsName := d.Get("datastore_name").(string)
+ dsVersionID := d.Get("datastore_version_id").(string)
+
+ params, err := dataStoreListParameters(dbClient, dsName, dsVersionID).Extract()
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err, "Error retrieving vkcs_db_backup"))
+ }
+
+ flattenedParams := flattenDatabaseDatastoreParameters(params)
+
+ d.SetId(fmt.Sprintf("%s/%s/params", dsName, dsVersionID))
+ d.Set("parameters", flattenedParams)
+
+ return nil
+}
+
+func flattenDatabaseDatastoreParameters(params []dataStoreParam) (r []map[string]interface{}) {
+ for _, p := range params {
+ r = append(r, map[string]interface{}{
+ "name": p.Name,
+ "type": p.Type,
+ "min": p.MinValue,
+ "max": p.MaxValue,
+ "restart_required": p.RestartRequried,
+ })
+ }
+ return
+}
diff --git a/vkcs/data_source_vkcs_db_datastore_parameters_test.go b/vkcs/data_source_vkcs_db_datastore_parameters_test.go
new file mode 100644
index 00000000..27009631
--- /dev/null
+++ b/vkcs/data_source_vkcs_db_datastore_parameters_test.go
@@ -0,0 +1,33 @@
+package vkcs
+
+import (
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccDatabaseDatastoreParametersDataSource_basic(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDatabaseDatastoreParametersDataSourceBasic,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("data.vkcs_db_datastore_parameters.parameters", "datastore_name", "mysql"),
+ ),
+ },
+ },
+ })
+}
+
+const testAccDatabaseDatastoreParametersDataSourceBasic = `
+data "vkcs_db_datastore" "datastore" {
+ name = "mysql"
+}
+
+data "vkcs_db_datastore_parameters" "parameters" {
+ datastore_name = data.vkcs_db_datastore.datastore.name
+ datastore_version_id = data.vkcs_db_datastore.datastore.versions.0.id
+}
+`
diff --git a/vkcs/data_source_vkcs_db_datastore_test.go b/vkcs/data_source_vkcs_db_datastore_test.go
new file mode 100644
index 00000000..4e2f75a3
--- /dev/null
+++ b/vkcs/data_source_vkcs_db_datastore_test.go
@@ -0,0 +1,30 @@
+package vkcs
+
+import (
+ "regexp"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccDatabaseDatastoreDataSource_basic(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDatabaseDatastoreDataSourceConfig,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("data.vkcs_db_datastore.datastore", "name", "mysql"),
+ resource.TestMatchResourceAttr("data.vkcs_db_datastore.datastore", "versions.#", regexp.MustCompile(`[1-9]\d*`)),
+ ),
+ },
+ },
+ })
+}
+
+const testAccDatabaseDatastoreDataSourceConfig = `
+data "vkcs_db_datastore" "datastore" {
+ name = "mysql"
+}
+`
diff --git a/vkcs/data_source_vkcs_db_datastores.go b/vkcs/data_source_vkcs_db_datastores.go
new file mode 100644
index 00000000..dd3d8d9f
--- /dev/null
+++ b/vkcs/data_source_vkcs_db_datastores.go
@@ -0,0 +1,89 @@
+package vkcs
+
+import (
+ "context"
+ "sort"
+
+ "github.com/gophercloud/utils/terraform/hashcode"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func dataSourceDatabaseDatastores() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourceDatabaseDatastoresRead,
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Computed: true,
+ Optional: true,
+ Description: "The `region` to fetch availability zones from, defaults to the provider's `region`",
+ },
+
+ "datastores": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The id of the datastore.",
+ },
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Name of the datastore.",
+ },
+ },
+ },
+ },
+ },
+ Description: "Use this data source to get a list of datastores from VKCS. **New since v.0.2.0**.",
+ }
+}
+
+func dataSourceDatabaseDatastoresRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ region := getRegion(d, config)
+ dbClient, err := config.DatabaseV1Client(region)
+ if err != nil {
+ return diag.Errorf("Error creating VKCS database client: %s", err)
+ }
+
+ allPages, err := dataStoreList(dbClient).AllPages()
+ if err != nil {
+ return diag.Errorf("Error retrieving vkcs_db_datastores: %s", err)
+ }
+
+ allDatastores, err := extractDatastores(allPages)
+ if err != nil {
+ return diag.Errorf("Error extracting vkcs_db_datastores from response: %s", err)
+ }
+
+ flattenedDatastores := flattenDatabaseDatastoresDatastores(allDatastores)
+ sort.SliceStable(flattenedDatastores, func(i, j int) bool {
+ return flattenedDatastores[i]["name"].(string) < flattenedDatastores[j]["name"].(string)
+ })
+
+ var names []string
+ for _, d := range flattenedDatastores {
+ names = append(names, d["name"].(string))
+ }
+
+ d.SetId(hashcode.Strings(names))
+ d.Set("region", region)
+ d.Set("datastores", flattenedDatastores)
+
+ return nil
+}
+
+func flattenDatabaseDatastoresDatastores(datastores []dataStore) (r []map[string]interface{}) {
+ for _, d := range datastores {
+ r = append(r, map[string]interface{}{
+ "id": d.ID,
+ "name": d.Name,
+ })
+ }
+ return
+}
diff --git a/vkcs/data_source_vkcs_db_datastores_test.go b/vkcs/data_source_vkcs_db_datastores_test.go
new file mode 100644
index 00000000..301e874d
--- /dev/null
+++ b/vkcs/data_source_vkcs_db_datastores_test.go
@@ -0,0 +1,29 @@
+package vkcs
+
+import (
+ "regexp"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccDatabaseDatastoresDataSource_basic(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDatabaseDatastoresDataSourceConfig,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestMatchResourceAttr("data.vkcs_db_datastores.datastores", "datastores.#", regexp.MustCompile(`[1-9]\d*`)),
+ resource.TestCheckResourceAttrSet("data.vkcs_db_datastores.datastores", "datastores.0.id"),
+ resource.TestCheckResourceAttrSet("data.vkcs_db_datastores.datastores", "datastores.0.name"),
+ ),
+ },
+ },
+ })
+}
+
+const testAccDatabaseDatastoresDataSourceConfig = `
+data "vkcs_db_datastores" "datastores" {}
+`
diff --git a/vkcs/data_source_vkcs_db_instance.go b/vkcs/data_source_vkcs_db_instance.go
index fb2843a7..7e1bb5b8 100755
--- a/vkcs/data_source_vkcs_db_instance.go
+++ b/vkcs/data_source_vkcs_db_instance.go
@@ -193,10 +193,13 @@ func dataSourceDatabaseInstanceRead(ctx context.Context, d *schema.ResourceData,
m := map[string]interface{}{
"size": *instance.Volume.Size,
- "used": *instance.Volume.Used,
+ "used": 0,
"volume_id": instance.Volume.VolumeID,
"volume_type": instance.Volume.VolumeType,
}
+ if instance.Volume.Used != nil {
+ m["used"] = *instance.Volume.Used
+ }
d.Set("volume", schema.NewSet(volInstHash, []interface{}{m}))
diff --git a/vkcs/data_source_vkcs_keymanager_secret.go b/vkcs/data_source_vkcs_keymanager_secret.go
index 43ce6fde..3c419e1f 100644
--- a/vkcs/data_source_vkcs_keymanager_secret.go
+++ b/vkcs/data_source_vkcs_keymanager_secret.go
@@ -175,7 +175,8 @@ func dataSourceKeyManagerSecret() *schema.Resource {
Description: "The map of metadata, assigned on the secret, which has been explicitly and implicitly added.",
},
},
- Description: "Use this data source to get the ID and the payload of an available Key secret\n\n~> **Important Security Notice** The payload of this data source will be stored *unencrypted* in your Terraform state file. **Use of this resource for production deployments is *not* recommended**. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
+ Description: "Use this data source to get the ID and the payload of an available Key secret\n\n" +
+ "~> **Important Security Notice** The payload of this data source will be stored *unencrypted* in your Terraform state file. **Use of this resource for production deployments is *not* recommended**. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
}
elem := &schema.Resource{
diff --git a/vkcs/data_source_vkcs_kubernetes_cluster_templates.go b/vkcs/data_source_vkcs_kubernetes_cluster_templates.go
index 13dd71cb..7570466f 100755
--- a/vkcs/data_source_vkcs_kubernetes_cluster_templates.go
+++ b/vkcs/data_source_vkcs_kubernetes_cluster_templates.go
@@ -36,7 +36,10 @@ func dataSourceKubernetesClusterTemplates() *schema.Resource {
},
},
// Currently, Computed composite fields are treated by terraform-schema as "Objects". Thus, subfields and their descriptions are not available to documentation generator. We have to put these descriptions into parent field description as workaround.
- Description: "A list of available kubernetes cluster templates.\n - `cluster_template_uuid` **String** The UUID of the cluster template.\n\n - `name` **String** The name of the cluster template.\n\n - `version` **String** The version of the cluster template.",
+ Description: "A list of available kubernetes cluster templates.\n" +
+ " - `cluster_template_uuid` **String** The UUID of the cluster template.\n\n" +
+ " - `name` **String** The name of the cluster template.\n\n" +
+ " - `version` **String** The version of the cluster template.",
},
"id": {
Type: schema.TypeString,
diff --git a/vkcs/data_source_vkcs_lb_loadbalancer.go b/vkcs/data_source_vkcs_lb_loadbalancer.go
new file mode 100644
index 00000000..d032b6dc
--- /dev/null
+++ b/vkcs/data_source_vkcs_lb_loadbalancer.go
@@ -0,0 +1,139 @@
+package vkcs
+
+import (
+ "context"
+ "log"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+
+ octavialoadbalancers "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers"
+)
+
+func dataSourceLoadBalancer() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourceLoadBalancerRead,
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The region in which to obtain the Loadbalancer client. If omitted, the `region` argument of the provider is used.",
+ },
+
+ "id": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: "The UUID of the Loadbalancer",
+ },
+
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The name of the Loadbalancer.",
+ },
+
+ "description": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "Human-readable description of the Loadbalancer.",
+ },
+
+ "vip_address": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The ip address of the Loadbalancer.",
+ },
+
+ "vip_network_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The network on which to allocate the Loadbalancer's address. A tenant can only create Loadbalancers on networks authorized by policy (e.g. networks that belong to them or networks that are shared). Changing this creates a new loadbalancer.",
+ },
+
+ "vip_subnet_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The subnet on which the Loadbalancer's address is allocated.",
+ },
+
+ "vip_port_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The port UUID of the Loadbalancer.",
+ },
+
+ "admin_state_up": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: "The administrative state of the Loadbalancer.",
+ },
+
+ "availability_zone": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The availability zone of the Loadbalancer.",
+ },
+
+ "security_group_ids": {
+ Type: schema.TypeSet,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Set: schema.HashString,
+ Description: "A list of security group IDs applied to the Loadbalancer.",
+ },
+
+ "tags": {
+ Type: schema.TypeSet,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Set: schema.HashString,
+ Description: "A list of simple strings assigned to the loadbalancer.",
+ },
+ },
+ Description: "Use this data source to get the details of a loadbalancer",
+ }
+}
+
+func dataSourceLoadBalancerRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(*config)
+ lbClient, err := config.LoadBalancerV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS loadbalancer client: %s", err)
+ }
+
+ var vipPortID string
+ lbID := d.Get("id").(string)
+ lb, err := octavialoadbalancers.Get(lbClient, lbID).Extract()
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err, "Unable to retrieve vkcs_lb_loadbalancer"))
+ }
+
+ log.Printf("[DEBUG] Retrieved vkcs_lb_loadbalancer %s: %#v", lbID, lb)
+
+ d.SetId(lb.ID)
+ d.Set("name", lb.Name)
+ d.Set("description", lb.Description)
+ d.Set("vip_subnet_id", lb.VipSubnetID)
+ d.Set("vip_network_id", lb.VipNetworkID)
+ d.Set("vip_port_id", lb.VipPortID)
+ d.Set("vip_address", lb.VipAddress)
+ d.Set("admin_state_up", lb.AdminStateUp)
+ d.Set("availability_zone", lb.AvailabilityZone)
+ d.Set("region", getRegion(d, config))
+ d.Set("tags", lb.Tags)
+ vipPortID = lb.VipPortID
+
+ // Get any security groups on the VIP Port.
+ if vipPortID != "" {
+ networkingClient, err := config.NetworkingV2Client(getRegion(d, config), getSDN(d))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS networking client: %s", err)
+ }
+ if err := resourceLoadBalancerGetSecurityGroups(networkingClient, vipPortID, d); err != nil {
+ return diag.Errorf("Error getting port security groups for vkcs_lb_loadbalancer: %s", err)
+ }
+ }
+
+ return nil
+}
diff --git a/vkcs/data_source_vkcs_lb_loadbalancer_test.go b/vkcs/data_source_vkcs_lb_loadbalancer_test.go
new file mode 100644
index 00000000..14efef62
--- /dev/null
+++ b/vkcs/data_source_vkcs_lb_loadbalancer_test.go
@@ -0,0 +1,70 @@
+package vkcs
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+)
+
+func TestAccLBLoadBalancerDataSource(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfig(testAccLBLoadBalancerDataSourceBasic),
+ },
+ {
+ Config: testAccRenderConfig(testAccLBLoadBalancerDataSourceSource, map[string]string{"TestAccLBLoadBalancerDataSourceBasic": testAccRenderConfig(testAccLBLoadBalancerDataSourceBasic)}),
+ Check: resource.ComposeTestCheckFunc(
+ testAccLBCheckLoadBalancerDataSourceID("data.vkcs_lb_loadbalancer.source_1"),
+ resource.TestCheckResourceAttr("data.vkcs_lb_loadbalancer.source_1", "name", "loadbalancer_1"),
+ resource.TestCheckResourceAttrPair("data.vkcs_lb_loadbalancer.source_1", "vip_subnet_id", "vkcs_lb_loadbalancer.loadbalancer_1", "vip_subnet_id"),
+ resource.TestCheckResourceAttr("data.vkcs_lb_loadbalancer.source_1", "tags.#", "1"),
+ ),
+ },
+ },
+ })
+}
+
+func testAccLBCheckLoadBalancerDataSourceID(n string) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ rs, ok := s.RootModule().Resources[n]
+ if !ok {
+ return fmt.Errorf("Can't find loadbalancer data source: %s", n)
+ }
+
+ if rs.Primary.ID == "" {
+ return fmt.Errorf("Loadbalancer data source ID not set")
+ }
+
+ return nil
+ }
+}
+
+const testAccLBLoadBalancerDataSourceBasic = `
+{{.BaseNetwork}}
+
+resource "vkcs_lb_loadbalancer" "loadbalancer_1" {
+ depends_on = ["vkcs_networking_router_interface.base"]
+ name = "loadbalancer_1"
+ vip_subnet_id = vkcs_networking_subnet.base.id
+ tags = ["tag1"]
+
+ timeouts {
+ create = "15m"
+ update = "15m"
+ delete = "15m"
+ }
+}
+`
+
+const testAccLBLoadBalancerDataSourceSource = `
+{{.TestAccLBLoadBalancerDataSourceBasic}}
+
+data "vkcs_lb_loadbalancer" "source_1" {
+ id = vkcs_lb_loadbalancer.loadbalancer_1.id
+}
+`
diff --git a/vkcs/data_source_vkcs_publicdns_zone.go b/vkcs/data_source_vkcs_publicdns_zone.go
new file mode 100644
index 00000000..f8a894e6
--- /dev/null
+++ b/vkcs/data_source_vkcs_publicdns_zone.go
@@ -0,0 +1,177 @@
+package vkcs
+
+import (
+ "context"
+ "log"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func dataSourcePublicDNSZone() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourcePublicDNSZoneRead,
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The region in which to obtain the V2 Public DNS client. If omitted, the `region` argument of the provider is used.",
+ },
+
+ "id": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The UUID of the DNS zone.",
+ },
+
+ "zone": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The name of the zone.",
+ },
+
+ "primary_dns": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The primary DNS of the zone SOA.",
+ },
+
+ "admin_email": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The admin email of the zone SOA.",
+ },
+
+ "serial": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The serial number of the zone SOA.",
+ },
+
+ "refresh": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The refresh time of the zone SOA.",
+ },
+
+ "retry": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The retry time of the zone SOA.",
+ },
+
+ "expire": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The expire time of the zone SOA.",
+ },
+
+ "ttl": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The TTL (time to live) of the zone SOA.",
+ },
+
+ "status": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The status of the zone.",
+ },
+ },
+ Description: "Use this data source to get the ID of a VKCS public DNS zone. **New since v.0.2.0**.",
+ }
+}
+
+func dataSourcePublicDNSZoneRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ opts := zoneListOpts{}
+
+ if v, ok := d.GetOk("id"); ok {
+ opts.ID = v.(string)
+ }
+
+ if v, ok := d.GetOk("zone"); ok {
+ opts.Zone = v.(string)
+ }
+
+ if v, ok := d.GetOk("primary_dns"); ok {
+ opts.PrimaryDNS = v.(string)
+ }
+
+ if v, ok := d.GetOk("admin_email"); ok {
+ opts.AdminEmail = v.(string)
+ }
+
+ if v, ok := d.GetOk("serial"); ok {
+ opts.Serial = v.(int)
+ }
+
+ if v, ok := d.GetOk("refresh"); ok {
+ opts.Refresh = v.(int)
+ }
+
+ if v, ok := d.GetOk("retry"); ok {
+ opts.Retry = v.(int)
+ }
+
+ if v, ok := d.GetOk("expire"); ok {
+ opts.Expire = v.(int)
+ }
+
+ if v, ok := d.GetOk("ttl"); ok {
+ opts.TTL = v.(int)
+ }
+
+ if v, ok := d.GetOk("status"); ok {
+ opts.Status = v.(string)
+ }
+
+ log.Printf("[DEBUG] vkcs_publicdns_zone list options: %#v", opts)
+
+ zones, err := zoneList(client, opts).Extract()
+ if err != nil {
+ return diag.Errorf("Error retrieving vkcs_publicdns_zone: %s", err)
+ }
+
+ if len(zones) < 1 {
+ return diag.Errorf("Your query returned no results. Please change your search criteria and try again.")
+ }
+
+ if len(zones) > 1 {
+ return diag.Errorf("Your query returned more than one result. Please try a more specific search criteria.")
+ }
+
+ zone := zones[0]
+
+ log.Printf("[DEBUG] Retrieved vkcs_publicdns_zone %s: %#v", zone.ID, zone)
+
+ d.SetId(zone.ID)
+ d.Set("region", getRegion(d, config))
+ d.Set("zone", zone.Zone)
+ d.Set("primary_dns", zone.PrimaryDNS)
+ d.Set("admin_email", zone.AdminEmail)
+ d.Set("serial", zone.Serial)
+ d.Set("refresh", zone.Refresh)
+ d.Set("retry", zone.Retry)
+ d.Set("expire", zone.Expire)
+ d.Set("ttl", zone.TTL)
+ d.Set("status", zone.Status)
+
+ return nil
+}
diff --git a/vkcs/data_source_vkcs_publicdns_zone_test.go b/vkcs/data_source_vkcs_publicdns_zone_test.go
new file mode 100644
index 00000000..b8fb5fb2
--- /dev/null
+++ b/vkcs/data_source_vkcs_publicdns_zone_test.go
@@ -0,0 +1,58 @@
+package vkcs
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+)
+
+func TestAccPublicDNSZoneDataSource_basic(t *testing.T) {
+ zoneName := fmt.Sprintf("vkcs-tf-acctest-%s.com", acctest.RandString(5))
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfig(testAccPublicDNSZoneDataSourceConfigBasic, map[string]string{"ZoneName": zoneName}),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckPublicDNSDataSourceID("data.vkcs_publicdns_zone.zone_1"),
+ resource.TestCheckResourceAttr("data.vkcs_publicdns_zone.zone_1", "primary_dns", "ns1.mcs.mail.ru"),
+ resource.TestCheckResourceAttr("data.vkcs_publicdns_zone.zone_1", "admin_email", "admin@example.com"),
+ resource.TestCheckResourceAttr("data.vkcs_publicdns_zone.zone_1", "zone", zoneName),
+ ),
+ },
+ },
+ })
+}
+
+func testAccCheckPublicDNSDataSourceID(n string) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ rs, ok := s.RootModule().Resources[n]
+ if !ok {
+ return fmt.Errorf("Can't find router data source: %s", n)
+ }
+
+ if rs.Primary.ID == "" {
+ return fmt.Errorf("Router data source ID not set")
+ }
+
+ return nil
+ }
+}
+
+const testAccPublicDNSZoneDataSourceConfigBasic = `
+resource "vkcs_publicdns_zone" "zone_1" {
+ primary_dns = "ns1.mcs.mail.ru"
+ admin_email = "admin@example.com"
+ expire = 3600000
+ zone = "{{.ZoneName}}"
+}
+
+data "vkcs_publicdns_zone" "zone_1" {
+ zone = vkcs_publicdns_zone.zone_1.zone
+}
+`
diff --git a/vkcs/data_source_vkcs_sharedfilesystem_share.go b/vkcs/data_source_vkcs_sharedfilesystem_share.go
index 3ae77687..f0927947 100644
--- a/vkcs/data_source_vkcs_sharedfilesystem_share.go
+++ b/vkcs/data_source_vkcs_sharedfilesystem_share.go
@@ -70,6 +70,7 @@ func dataSourceSharedFilesystemShare() *schema.Resource {
"export_location_path": {
Type: schema.TypeString,
Optional: true,
+ Computed: true,
Description: "The export location path of the share.",
},
@@ -139,6 +140,11 @@ func dataSourceSharedFilesystemShareRead(ctx context.Context, d *schema.Resource
}
share = allShares[0]
+ exportLocationPath, err := getShareExportLocationPath(sfsClient, share.ID)
+ if err != nil {
+ return diag.Errorf("Unable to retrieve export location path: %s", err)
+ }
+
d.SetId(share.ID)
d.Set("name", share.Name)
d.Set("region", getRegion(d, config))
@@ -149,6 +155,7 @@ func dataSourceSharedFilesystemShareRead(ctx context.Context, d *schema.Resource
d.Set("description", share.Description)
d.Set("size", share.Size)
d.Set("status", share.Status)
+ d.Set("export_location_path", exportLocationPath)
d.Set("share_proto", share.ShareProto)
return nil
diff --git a/vkcs/data_source_vkcs_sharedfilesystem_sharenetwork.go b/vkcs/data_source_vkcs_sharedfilesystem_sharenetwork.go
index 63773e32..29b64534 100644
--- a/vkcs/data_source_vkcs_sharedfilesystem_sharenetwork.go
+++ b/vkcs/data_source_vkcs_sharedfilesystem_sharenetwork.go
@@ -7,7 +7,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
- "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharenetworks"
)
@@ -98,8 +97,6 @@ func dataSourceSharedFilesystemShareNetworkRead(ctx context.Context, d *schema.R
NeutronSubnetID: d.Get("neutron_subnet_id").(string),
}
- listOpts.IPVersion = gophercloud.IPVersion(4)
-
allPages, err := sharenetworks.ListDetail(sfsClient, listOpts).AllPages()
if err != nil {
return diag.Errorf("Unable to query share networks: %s", err)
diff --git a/vkcs/db_backup_client.go b/vkcs/db_backup_client.go
index 5d5b0086..a42ca23d 100644
--- a/vkcs/db_backup_client.go
+++ b/vkcs/db_backup_client.go
@@ -19,19 +19,19 @@ type dbBackupCreateOpts struct {
}
type dbBackupResp struct {
- ID string `json:"id"`
- Name string `json:"name"`
- Description string `json:"description"`
- LocationRef string `json:"location_ref"`
- InstanceID string `json:"instance_id"`
- ClusterID string `json:"cluster_id"`
- Created string `json:"created"`
- Updated string `json:"updated"`
- Size float64 `json:"size"`
- WalSize float64 `json:"wal_size"`
- Status string `json:"status"`
- Datastore *dataStore `json:"datastore"`
- Meta string `json:"meta"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ LocationRef string `json:"location_ref"`
+ InstanceID string `json:"instance_id"`
+ ClusterID string `json:"cluster_id"`
+ Created string `json:"created"`
+ Updated string `json:"updated"`
+ Size float64 `json:"size"`
+ WalSize float64 `json:"wal_size"`
+ Status string `json:"status"`
+ Datastore *dataStoreShort `json:"datastore"`
+ Meta string `json:"meta"`
}
type dbBackupRespOpts struct {
@@ -72,7 +72,7 @@ func dbBackupCreate(client databaseClient, opts optsBuilder) (r getDBBackupResul
return
}
var result *http.Response
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
result, r.Err = client.Post(baseURL(client, dbBackupsAPIPath), b, &r.Body, reqOpts)
if r.Err == nil {
r.Header = result.Header
@@ -81,7 +81,7 @@ func dbBackupCreate(client databaseClient, opts optsBuilder) (r getDBBackupResul
}
func dbBackupGet(client databaseClient, id string) (r getDBBackupResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(getURL(client, dbBackupsAPIPath, id), &r.Body, reqOpts)
if r.Err == nil {
@@ -91,7 +91,7 @@ func dbBackupGet(client databaseClient, id string) (r getDBBackupResult) {
}
func dbBackupDelete(client databaseClient, id string) (r deleteDBBackupResult) {
- reqOpts := getDBRequestOpts()
+ reqOpts := getRequestOpts()
var result *http.Response
result, r.Err = client.Delete(getURL(client, dbBackupsAPIPath, id), reqOpts)
if r.Err == nil {
diff --git a/vkcs/db_cluster.go b/vkcs/db_cluster.go
index adb89866..d7dfe571 100755
--- a/vkcs/db_cluster.go
+++ b/vkcs/db_cluster.go
@@ -1,10 +1,14 @@
package vkcs
import (
+ "context"
+ "errors"
"fmt"
+ "log"
"github.com/gophercloud/gophercloud"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func flattenDatabaseClusterWalVolume(w walVolume) []map[string]interface{} {
@@ -15,13 +19,582 @@ func flattenDatabaseClusterWalVolume(w walVolume) []map[string]interface{} {
return walvolume
}
-func flattenDatabaseClusterShard(inst dbClusterInstanceResp) map[string]interface{} {
- newShard := make(map[string]interface{})
- newShard["shard_id"] = inst.ShardID
- newShard["flavor_id"] = inst.Flavor.ID
- newShard["volume_size"] = inst.Volume.Size
- newShard["volume_type"] = dbImportedStatus
- return newShard
+func flattenDatabaseClusterInstances(insts []dbClusterInstanceResp) []map[string]interface{} {
+ instances := make([]map[string]interface{}, len(insts))
+ for i, inst := range insts {
+ instances[i] = flattenDatabaseClusterInstance(inst)
+ }
+
+ return instances
+}
+
+func flattenDatabaseClusterInstance(inst dbClusterInstanceResp) map[string]interface{} {
+ instance := make(map[string]interface{})
+ instance["instance_id"] = inst.ID
+ instance["ip"] = inst.IP
+ instance["role"] = inst.Role
+
+ return instance
+}
+
+func flattenDatabaseClusterShards(shardsInsts map[string][]dbClusterInstanceResp) (r []map[string]interface{}) {
+ for id, insts := range shardsInsts {
+ r = append(r, flattenDatabaseClusterShard(id, insts))
+ }
+ return
+}
+
+func flattenDatabaseClusterShard(id string, shardInsts []dbClusterInstanceResp) map[string]interface{} {
+ shard := make(map[string]interface{})
+ shard["shard_id"] = id
+ shard["size"] = len(shardInsts)
+ shard["flavor_id"] = shardInsts[0].Flavor.ID
+ shard["volume_size"] = shardInsts[0].Volume.Size
+ shard["volume_type"] = shardInsts[0].Volume.VolumeType
+ if walVolume := shardInsts[0].WalVolume; walVolume != nil {
+ shard["wal_volume"] = flattenDatabaseClusterWalVolume(*walVolume)
+ }
+ shard["instances"] = flattenDatabaseClusterShardInstances(shardInsts)
+ return shard
+}
+
+func getDatabaseClusterShardInstances(insts []dbClusterInstanceResp) map[string][]dbClusterInstanceResp {
+ shardsInstances := make(map[string][]dbClusterInstanceResp)
+ for _, inst := range insts {
+ shardsInstances[inst.ShardID] = append(shardsInstances[inst.ShardID], inst)
+ }
+ return shardsInstances
+}
+
+func flattenDatabaseClusterShardInstances(insts []dbClusterInstanceResp) (r []map[string]interface{}) {
+ for _, inst := range insts {
+ r = append(r, flattenDatabaseClusterShardInstance(inst))
+ }
+ return
+}
+
+func flattenDatabaseClusterShardInstance(inst dbClusterInstanceResp) map[string]interface{} {
+ instance := make(map[string]interface{})
+ instance["instance_id"] = inst.ID
+ instance["ip"] = inst.IP
+ return instance
+}
+
+func expandDatabaseClusterShrinkOptions(v []interface{}) []string {
+ opts := make([]string, len(v))
+ for i, opt := range v {
+ opts[i] = opt.(string)
+ }
+ return opts
+}
+
+func databaseClusterDetermineShrinkedInstances(toDelete int, shrinkOptions []string, instances []dbClusterInstanceResp, shardID string) ([]dbClusterShrinkOpts, error) {
+ ids := []dbClusterShrinkOpts{}
+ foundIDs := 0
+ if len(shrinkOptions) == 0 {
+ for _, instance := range instances {
+ if instance.Role != dbClusterInstanceRoleLeader && instance.ShardID == shardID {
+ ids = append(ids, dbClusterShrinkOpts{ID: instance.ID})
+ foundIDs++
+ if foundIDs == toDelete {
+ break
+ }
+ }
+ }
+ if foundIDs != toDelete {
+ return nil, fmt.Errorf("not enough instances to shrink cluster")
+ }
+ } else {
+ err := databaseClusterValidateShrinkOptions(shrinkOptions, instances, shardID)
+ if err != nil {
+ return nil, fmt.Errorf("invalid shrink options: %s", err)
+ }
+ for _, instance := range instances {
+ needToRemain := false
+ for _, opt := range shrinkOptions {
+ if instance.ID == opt {
+ needToRemain = true
+ }
+ }
+ if !needToRemain {
+ ids = append(ids, dbClusterShrinkOpts{ID: instance.ID})
+ foundIDs++
+ }
+ }
+ if foundIDs != toDelete {
+ return nil, fmt.Errorf("invalid shrink options: not enough instances to delete")
+ }
+ }
+
+ return ids, nil
+}
+
+func databaseClusterValidateShrinkOptions(shrinkOptions []string, instances []dbClusterInstanceResp, shardID string) error {
+ for _, opt := range shrinkOptions {
+ optIsValid := false
+ for _, instance := range instances {
+ if instance.ID == opt && instance.ShardID == shardID {
+ optIsValid = true
+ }
+ }
+ if !optIsValid {
+ if shardID != "" {
+ return fmt.Errorf("shard %s does not have instance: %s", shardID, opt)
+ }
+ return fmt.Errorf("cluster does not have instance: %s", opt)
+ }
+ }
+ return nil
+}
+
+func databaseClusterExpandShards(d *schema.ResourceData) (r []map[string]interface{}) {
+ shardsRaw := d.Get("shard").([]interface{})
+ for _, shRaw := range shardsRaw {
+ r = append(r, shRaw.(map[string]interface{}))
+ }
+ return
+}
+
+func shardIndex(d *schema.ResourceData, shardID string) (int, error) {
+ shards := databaseClusterExpandShards(d)
+ for i, sh := range shards {
+ if sh["shard_id"] == shardID {
+ return i, nil
+ }
+ }
+ return 0, fmt.Errorf("shard with %s not found", shardID)
+}
+
+func shardPathPrefix(d *schema.ResourceData, shardID string) (string, error) {
+ if shardID != "" {
+ i, err := shardIndex(d, shardID)
+ if err != nil {
+ return "", fmt.Errorf("%w: %s", errDBClusterShardNotFound, err)
+ }
+ return fmt.Sprintf("shard.%d.", i), nil
+ }
+ return "", nil
+}
+
+func databaseClusterCheckDeleted(d *schema.ResourceData, err error) error {
+ if _, ok := err.(gophercloud.ErrDefault404); ok {
+ d.SetId("")
+ return nil
+ }
+ return fmt.Errorf("%w: %s", errDBClusterNotFound, err)
+}
+
+type dbResourceUpdateContext struct {
+ Ctx context.Context
+ Client databaseClient
+ D *schema.ResourceData
+ StateConf *resource.StateChangeConf
+}
+
+func (uCtx *dbResourceUpdateContext) WaitForStateContext() error {
+ _, err := uCtx.StateConf.WaitForStateContext(uCtx.Ctx)
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterUpdateWait, err)
+ }
+ return nil
+}
+
+var (
+ errDBClusterNotFound = errors.New("cluster not found")
+ errDBClusterShardNotFound = errors.New("unable to determine shard")
+ errDBClusterUpdateWait = errors.New("error waiting for cluster to become ready")
+
+ errDBClusterUpdateDiskAutoexpand = errors.New("error updating disk_autoexpand")
+ errDBClusterUpdateDiskAutoexpandExtract = errors.New("unable to determine disk_autoexpand")
+ errDBClusterUpdateWalDiskAutoexpand = errors.New("error updating wal_disk_autoexpand")
+ errDBClusterUpdateWalDiskAutoexpandExtract = errors.New("unable to determine wal_disk_autoexpand")
+ errDBClusterUpdateCloudMonitoring = errors.New("error updating cloud_monitoring_enabled")
+
+ errDBClusterActionUpdateConfiguration = errors.New("error updating configuration for cluster")
+ errDBClusterActionApplyCapabitilies = errors.New("error applying capabilities")
+ errDBClusterActionApplyCapabilitiesExtract = errors.New("error extracting capabilities")
+ errDBClusterActionResizeWalVolumeExtract = errors.New("unable to determine wal_volume")
+ errDBClusterActionGrow = errors.New("error growing cluster")
+ errDBClusterActionShrink = errors.New("error shrinking cluster")
+ errDBClusterActionShrinkWrongOptions = errors.New("invalid shrink options")
+ errDBClusterActionShrinkInstancesExtract = errors.New("error determining instances to shrink")
+ errDBClusterActionResizeVolume = errors.New("error resizing volume")
+ errDBClusterActionResizeWalVolume = errors.New("error resizing wal_volume")
+ errDBClusterActionResizeFlavor = errors.New("error resizing flavor")
+)
+
+func databaseClusterActionUpdateConfiguration(updateCtx *dbResourceUpdateContext) error {
+ old, new := updateCtx.D.GetChange("configuration_id")
+
+ var detachOpts dbClusterDetachConfigurationGroupOpts
+ detachOpts.ConfigurationDetach.ConfigurationID = old.(string)
+
+ var attachOpts *dbClusterAttachConfigurationGroupOpts
+ if new != "" {
+ attachOpts = &dbClusterAttachConfigurationGroupOpts{}
+ attachOpts.ConfigurationAttach.ConfigurationID = new.(string)
+ }
+
+ return databaseClusterActionUpdateConfigurationBase(updateCtx, &detachOpts, attachOpts)
+}
+
+func databaseClusterActionUpdateConfigurationBase(updateCtx *dbResourceUpdateContext, detachOpts *dbClusterDetachConfigurationGroupOpts, attachOpts *dbClusterAttachConfigurationGroupOpts) error {
+ dbClient, clusterID := updateCtx.Client, updateCtx.D.Id()
+
+ err := dbClusterAction(dbClient, clusterID, detachOpts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionUpdateConfiguration, err)
+ }
+
+ log.Printf("[DEBUG] Detaching configuration %s from cluster %s", detachOpts.ConfigurationDetach.ConfigurationID, clusterID)
+ err = updateCtx.WaitForStateContext()
+ if err != nil {
+ return err
+ }
+
+ if attachOpts != nil {
+ err := dbClusterAction(dbClient, clusterID, attachOpts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionUpdateConfiguration, err)
+ }
+
+ log.Printf("[DEBUG] Attaching configuration %s to cluster %s", attachOpts.ConfigurationAttach.ConfigurationID, clusterID)
+ return updateCtx.WaitForStateContext()
+ }
+
+ return nil
+}
+
+func databaseClusterUpdateDiskAutoexpand(updateCtx *dbResourceUpdateContext) error {
+ diskAutoexp := updateCtx.D.Get("disk_autoexpand")
+ autoExpandProperties, err := extractDatabaseAutoExpand(diskAutoexp.([]interface{}))
+ if err != nil {
+ return errDBClusterUpdateDiskAutoexpandExtract
+ }
+
+ var autoExpandOpts dbClusterUpdateAutoExpandOpts
+ if autoExpandProperties.AutoExpand {
+ autoExpandOpts.Cluster.VolumeAutoresizeEnabled = 1
+ } else {
+ autoExpandOpts.Cluster.VolumeAutoresizeEnabled = 0
+ }
+ autoExpandOpts.Cluster.VolumeAutoresizeMaxSize = autoExpandProperties.MaxDiskSize
+
+ return databaseClusterUpdateDiskAutoexpandBase(updateCtx, autoExpandOpts)
+}
+
+func databaseClusterUpdateDiskAutoexpandBase(updateCtx *dbResourceUpdateContext, autoExpandOpts dbClusterUpdateAutoExpandOpts) error {
+ dbClient, clusterID := updateCtx.Client, updateCtx.D.Id()
+
+ err := dbClusterUpdateAutoExpand(dbClient, clusterID, &autoExpandOpts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterUpdateDiskAutoexpand, err)
+ }
+
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusUpdating)}
+ updateCtx.StateConf.Target = []string{string(dbClusterStatusActive)}
+
+ log.Printf("[DEBUG] Waiting for cluster %s to become ready after updating disk_autoexpand", clusterID)
+ return updateCtx.WaitForStateContext()
+}
+
+func databaseClusterUpdateWalDiskAutoexpand(updateCtx *dbResourceUpdateContext) error {
+ walDiskAutoexp := updateCtx.D.Get("wal_disk_autoexpand")
+ walAutoExpandProperties, err := extractDatabaseAutoExpand(walDiskAutoexp.([]interface{}))
+ if err != nil {
+ return errDBClusterUpdateWalDiskAutoexpandExtract
+ }
+
+ var walAutoExpandOpts dbClusterUpdateAutoExpandWalOpts
+ if walAutoExpandProperties.AutoExpand {
+ walAutoExpandOpts.Cluster.WalVolume.VolumeAutoresizeEnabled = 1
+ } else {
+ walAutoExpandOpts.Cluster.WalVolume.VolumeAutoresizeEnabled = 0
+ }
+ walAutoExpandOpts.Cluster.WalVolume.VolumeAutoresizeMaxSize = walAutoExpandProperties.MaxDiskSize
+
+ return databaseClusterUpdateWalDiskAutoexpandBase(updateCtx, walAutoExpandOpts)
+}
+
+func databaseClusterUpdateWalDiskAutoexpandBase(updateCtx *dbResourceUpdateContext, walAutoExpandOpts dbClusterUpdateAutoExpandWalOpts) error {
+ dbClient, clusterID := updateCtx.Client, updateCtx.D.Id()
+
+ err := dbClusterUpdateAutoExpand(dbClient, clusterID, &walAutoExpandOpts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterUpdateWalDiskAutoexpand, err)
+ }
+
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusUpdating)}
+ updateCtx.StateConf.Target = []string{string(dbClusterStatusActive)}
+
+ log.Printf("[DEBUG] Waiting for cluster %s to become ready after updating wal_disk_autoexpand", clusterID)
+ return updateCtx.WaitForStateContext()
+}
+
+func databaseClusterUpdateCloudMonitoring(updateCtx *dbResourceUpdateContext) error {
+ enabled := updateCtx.D.Get("cloud_monitoring_enabled").(bool)
+ var cloudMonitoringOpts updateCloudMonitoringOpts
+ cloudMonitoringOpts.CloudMonitoring.Enable = enabled
+ return databaseClusterUpdateCloudMonitoringBase(updateCtx, cloudMonitoringOpts)
+}
+
+func databaseClusterUpdateCloudMonitoringBase(updateCtx *dbResourceUpdateContext, cloudMonitoringOpts updateCloudMonitoringOpts) error {
+ clusterID := updateCtx.D.Id()
+ err := dbClusterAction(updateCtx.Client, clusterID, &cloudMonitoringOpts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterUpdateCloudMonitoring, err)
+ }
+ log.Printf("[DEBUG] Updated cloud_monitoring_enabled in cluster %s", clusterID)
+ return nil
+}
+
+func databaseClusterActionApplyCapabilities(updateCtx *dbResourceUpdateContext) error {
+ dbClient, clusterID := updateCtx.Client, updateCtx.D.Id()
+
+ caps := updateCtx.D.Get("capabilities")
+ opts, err := extractDatabaseCapabilities(caps.([]interface{}))
+ if err != nil {
+ return errDBClusterActionApplyCapabilitiesExtract
+ }
+
+ var applyCapabilityOpts dbClusterApplyCapabilityOpts
+ applyCapabilityOpts.ApplyCapability.Capabilities = opts
+
+ updateCtx.StateConf.Refresh = databaseClusterStateRefreshFunc(dbClient, clusterID, &opts)
+
+ return databaseClusterActionApplyCapabilitiesBase(updateCtx, applyCapabilityOpts)
+}
+
+func databaseClusterActionApplyCapabilitiesBase(updateCtx *dbResourceUpdateContext, applyCapabilityOpts dbClusterApplyCapabilityOpts) error {
+ dbClient, clusterID := updateCtx.Client, updateCtx.D.Id()
+
+ err := dbClusterAction(dbClient, clusterID, &applyCapabilityOpts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionApplyCapabitilies, err)
+ }
+
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusCapabilityApplying), string(dbClusterStatusBuild)}
+ updateCtx.StateConf.Target = []string{string(dbClusterStatusActive)}
+
+ log.Printf("[DEBUG] Waiting for cluster %s to become ready after applying capability", clusterID)
+ return updateCtx.WaitForStateContext()
+}
+
+func databaseClusterActionGrow(updateCtx *dbResourceUpdateContext, shardID string) error {
+ d := updateCtx.D
+ pathPrefix, err := shardPathPrefix(d, shardID)
+ if err != nil {
+ return err
+ }
+
+ volumeSize := d.Get(pathPrefix + "volume_size").(int)
+ growOpts := dbClusterGrowOpts{
+ Keypair: d.Get("keypair").(string),
+ AvailabilityZone: d.Get(pathPrefix + "availability_zone").(string),
+ FlavorRef: d.Get(pathPrefix + "flavor_id").(string),
+ Volume: &volume{Size: &volumeSize, VolumeType: d.Get(pathPrefix + "volume_type").(string)},
+ ShardID: shardID,
+ }
+
+ if v, ok := d.GetOk(pathPrefix + "wal_volume"); ok {
+ walVolumeOpts, err := extractDatabaseWalVolume(v.([]interface{}))
+ if err != nil {
+ return errDBClusterActionResizeWalVolumeExtract
+ }
+ growOpts.Walvolume = &walVolume{
+ Size: &walVolumeOpts.Size,
+ VolumeType: walVolumeOpts.VolumeType,
+ }
+ }
+
+ var old, new interface{}
+ if shardID != "" {
+ old, new = d.GetChange(pathPrefix + "size")
+ } else {
+ old, new = d.GetChange("cluster_size")
+ }
+ growSize := new.(int) - old.(int)
+
+ if shardID != "" {
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusGrow), string(dbClusterStatusBuild)}
+ } else {
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusGrow)}
+ }
+ updateCtx.StateConf.Target = []string{string(dbClusterStatusActive)}
+
+ return databaseClusterActionGrowBase(updateCtx, growOpts, growSize)
+}
+
+func databaseClusterActionGrowBase(updateCtx *dbResourceUpdateContext, growOpts dbClusterGrowOpts, growSize int) error {
+ clusterID := updateCtx.D.Id()
+ opts := make([]dbClusterGrowOpts, growSize)
+ for i := 0; i < growSize; i++ {
+ opts[i] = growOpts
+ }
+ growClusterOpts := dbClusterGrowClusterOpts{Grow: opts}
+
+ err := dbClusterAction(updateCtx.Client, clusterID, &growClusterOpts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionGrow, err)
+ }
+
+ log.Printf("[DEBUG] Growing cluster %s", clusterID)
+ return updateCtx.WaitForStateContext()
+}
+
+func databaseClusterActionShrink(updateCtx *dbResourceUpdateContext, shardID string) error {
+ d := updateCtx.D
+ pathPrefix, err := shardPathPrefix(d, shardID)
+ if err != nil {
+ return err
+ }
+
+ var old, new interface{}
+ if shardID != "" {
+ old, new = d.GetChange(pathPrefix + "size")
+ } else {
+ old, new = d.GetChange("cluster_size")
+ }
+ newSize, shrinkSize := new.(int), old.(int)-new.(int)
+
+ rawShrinkOptions := d.Get(pathPrefix + "shrink_options").([]interface{})
+ shrinkOptions := expandDatabaseClusterShrinkOptions(rawShrinkOptions)
+ if len(shrinkOptions) > 0 && len(shrinkOptions) != newSize {
+ return fmt.Errorf("%w: number of instances in shrink options should equal new size",
+ errDBClusterActionShrinkWrongOptions)
+ }
+
+ cluster, err := dbClusterGet(updateCtx.Client, d.Id()).extract()
+ if err != nil {
+ return databaseClusterCheckDeleted(d, err)
+ }
+
+ ids, err := databaseClusterDetermineShrinkedInstances(shrinkSize, shrinkOptions, cluster.Instances, shardID)
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionShrinkInstancesExtract, err)
+ }
+
+ if shardID != "" {
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusShrink), string(dbClusterStatusBuild)}
+ } else {
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusShrink)}
+ }
+ updateCtx.StateConf.Target = []string{string(dbClusterStatusActive)}
+
+ return databaseClusterActionShrinkBase(updateCtx, ids)
+}
+
+func databaseClusterActionShrinkBase(updateCtx *dbResourceUpdateContext, shrinkOpts []dbClusterShrinkOpts) error {
+ clusterID := updateCtx.D.Id()
+ shrinkClusterOpts := dbClusterShrinkClusterOpts{
+ Shrink: shrinkOpts,
+ }
+
+ err := dbClusterAction(updateCtx.Client, clusterID, &shrinkClusterOpts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionShrink, err)
+ }
+
+ log.Printf("[DEBUG] Shrinking cluster %s", clusterID)
+ return updateCtx.WaitForStateContext()
+}
+
+func databaseClusterActionResizeVolume(updateCtx *dbResourceUpdateContext, shardID string) error {
+ d := updateCtx.D
+ pathPrefix, err := shardPathPrefix(d, shardID)
+ if err != nil {
+ return err
+ }
+
+ _, volumeSize := d.GetChange(pathPrefix + "volume_size")
+ var resizeVolumeOpts dbClusterResizeVolumeOpts
+ resizeVolumeOpts.Resize.Volume.Size = volumeSize.(int)
+ resizeVolumeOpts.Resize.ShardID = shardID
+
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusResize)}
+ updateCtx.StateConf.Target = []string{string(dbClusterStatusActive)}
+
+ return databaseClusterActionResizeVolumeBase(updateCtx, resizeVolumeOpts)
+}
+
+func databaseClusterActionResizeVolumeBase(updateCtx *dbResourceUpdateContext, opts dbClusterResizeVolumeOpts) error {
+ clusterID := updateCtx.D.Id()
+ err := dbClusterAction(updateCtx.Client, clusterID, &opts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionResizeVolume, err)
+ }
+ log.Printf("[DEBUG] Resizing volume from cluster %s", clusterID)
+ return updateCtx.WaitForStateContext()
+}
+
+func databaseClusterActionResizeWalVolume(updateCtx *dbResourceUpdateContext, shardID string) error {
+ d := updateCtx.D
+ pathPrefix, err := shardPathPrefix(d, shardID)
+ if err != nil {
+ return err
+ }
+
+ old, new := d.GetChange(pathPrefix + "wal_volume")
+ walVolumeOptsNew, err := extractDatabaseWalVolume(new.([]interface{}))
+ if err != nil {
+ return errDBClusterActionResizeWalVolumeExtract
+ }
+
+ walVolumeOptsOld, err := extractDatabaseWalVolume(old.([]interface{}))
+ if err != nil {
+ return errDBClusterActionResizeWalVolumeExtract
+ }
+
+ if walVolumeOptsNew.Size != walVolumeOptsOld.Size {
+ var resizeWalVolumeOpts dbClusterResizeWalVolumeOpts
+ resizeWalVolumeOpts.Resize.Volume.Size = walVolumeOptsNew.Size
+ resizeWalVolumeOpts.Resize.Volume.Kind = "wal"
+ resizeWalVolumeOpts.Resize.ShardID = shardID
+
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusResize)}
+ updateCtx.StateConf.Target = []string{string(dbClusterStatusActive)}
+
+ return databaseClusterActionResizeWalVolumeBase(updateCtx, resizeWalVolumeOpts)
+ }
+
+ return nil
+}
+
+func databaseClusterActionResizeWalVolumeBase(updateCtx *dbResourceUpdateContext, opts dbClusterResizeWalVolumeOpts) error {
+ clusterID := updateCtx.D.Id()
+ err := dbClusterAction(updateCtx.Client, clusterID, &opts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionResizeWalVolume, err)
+ }
+ log.Printf("[DEBUG] Resizing wal_folume from cluster %s", clusterID)
+ return updateCtx.WaitForStateContext()
+}
+
+func databaseClusterActionResizeFlavor(updateCtx *dbResourceUpdateContext, shardID string) error {
+ d := updateCtx.D
+ pathPrefix, err := shardPathPrefix(d, shardID)
+ if err != nil {
+ return err
+ }
+
+ var resizeOpts dbClusterResizeOpts
+ resizeOpts.Resize.FlavorRef = d.Get(pathPrefix + "flavor_id").(string)
+ resizeOpts.Resize.ShardID = shardID
+
+ updateCtx.StateConf.Pending = []string{string(dbClusterStatusResize)}
+ updateCtx.StateConf.Target = []string{string(dbClusterStatusActive)}
+
+ return databaseClusterActionResizeFlavorBase(updateCtx, resizeOpts)
+}
+
+func databaseClusterActionResizeFlavorBase(updateCtx *dbResourceUpdateContext, opts dbClusterResizeOpts) error {
+ clusterID := updateCtx.D.Id()
+ err := dbClusterAction(updateCtx.Client, clusterID, &opts).ExtractErr()
+ if err != nil {
+ return fmt.Errorf("%w: %s", errDBClusterActionResizeFlavor, err)
+ }
+ log.Printf("[DEBUG] Resizing flavor from cluster %s", clusterID)
+ return updateCtx.WaitForStateContext()
}
func getClusterStatus(c *dbClusterResp) string {
diff --git a/vkcs/db_cluster_client.go b/vkcs/db_cluster_client.go
index 4b651640..ce8f5f36 100755
--- a/vkcs/db_cluster_client.go
+++ b/vkcs/db_cluster_client.go
@@ -13,17 +13,18 @@ type dbCluster struct {
// dbClusterCreateOpts represents database cluster creation parameters
type dbClusterCreateOpts struct {
- Name string `json:"name" required:"true"`
- Datastore *dataStore `json:"datastore" required:"true"`
- FloatingIPEnabled bool `json:"allow_remote_access,omitempty"`
- AutoExpand int `json:"volume_autoresize_enabled,omitempty"`
- MaxDiskSize int `json:"volume_autoresize_max_size,omitempty"`
- WalAutoExpand int `json:"wal_autoresize_enabled,omitempty"`
- WalMaxDiskSize int `json:"wal_autoresize_max_size,omitempty"`
- Instances []dbClusterInstanceCreateOpts `json:"instances"`
- Capabilities []instanceCapabilityOpts `json:"capabilities,omitempty"`
- RestorePoint *restorePoint `json:"restore_point,omitempty"`
- BackupSchedule *backupSchedule `json:"backup_schedule,omitempty"`
+ Name string `json:"name" required:"true"`
+ Datastore *dataStoreShort `json:"datastore" required:"true"`
+ FloatingIPEnabled bool `json:"allow_remote_access,omitempty"`
+ AutoExpand int `json:"volume_autoresize_enabled,omitempty"`
+ MaxDiskSize int `json:"volume_autoresize_max_size,omitempty"`
+ WalAutoExpand int `json:"wal_autoresize_enabled,omitempty"`
+ WalMaxDiskSize int `json:"wal_autoresize_max_size,omitempty"`
+ Instances []dbClusterInstanceCreateOpts `json:"instances"`
+ Capabilities []instanceCapabilityOpts `json:"capabilities,omitempty"`
+ RestorePoint *restorePoint `json:"restorePoint,omitempty"`
+ BackupSchedule *backupSchedule `json:"backup_schedule,omitempty"`
+ CloudMonitoringEnabled bool `json:"cloud_monitoring_enabled,omitempty"`
}
// dbClusterInstanceCreateOpts represents database cluster instance creation parameters
@@ -35,6 +36,7 @@ type dbClusterInstanceCreateOpts struct {
Volume *volume `json:"volume" required:"true"`
Walvolume *walVolume `json:"wal_volume,omitempty"`
ShardID string `json:"shard_id,omitempty"`
+ SecurityGroups []string `json:"security_groups,omitempty"`
}
// dbClusterAttachConfigurationGroupOpts represents parameters of configuration group to be attached to database cluster
@@ -57,6 +59,7 @@ type dbClusterResizeVolumeOpts struct {
Volume struct {
Size int `json:"size"`
} `json:"volume"`
+ ShardID string `json:"shard_id,omitempty"`
} `json:"resize"`
}
@@ -67,6 +70,7 @@ type dbClusterResizeWalVolumeOpts struct {
Size int `json:"size"`
Kind string `json:"kind"`
} `json:"volume"`
+ ShardID string `json:"shard_id,omitempty"`
} `json:"resize"`
}
@@ -74,6 +78,7 @@ type dbClusterResizeWalVolumeOpts struct {
type dbClusterResizeOpts struct {
Resize struct {
FlavorRef string `json:"flavorRef"`
+ ShardID string `json:"shard_id,omitempty"`
} `json:"resize"`
}
@@ -114,6 +119,7 @@ type dbClusterGrowOpts struct {
FlavorRef string `json:"flavorRef" required:"true"`
Volume *volume `json:"volume" required:"true"`
Walvolume *walVolume `json:"wal_volume,omitempty"`
+ ShardID string `json:"shard_id,omitempty"`
}
// dbClusterShrinkClusterOpts is used to send proper request to shrink database cluster
@@ -130,7 +136,7 @@ type dbClusterShrinkOpts struct {
type dbClusterResp struct {
ConfigurationID string `json:"configuration_id"`
Created dateTimeWithoutTZFormat `json:"created"`
- DataStore *dataStore `json:"datastore"`
+ DataStore *dataStoreShort `json:"datastore"`
HealthStatus string `json:"health_status"`
ID string `json:"id"`
Instances []dbClusterInstanceResp `json:"instances"`
@@ -151,6 +157,7 @@ type dbClusterInstanceResp struct {
Flavor *links `json:"flavor"`
GaVersion string `json:"ga_version"`
ID string `json:"id"`
+ IP *[]string `json:"ip"`
Links *[]link `json:"links"`
Name string `json:"name"`
Role string `json:"role"`
@@ -301,7 +308,7 @@ func dbClusterCreate(client databaseClient, opts optsBuilder) (r createClusterRe
return
}
var result *http.Response
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
result, r.Err = client.Post(baseURL(client, dbClustersAPIPath), b, &r.Body, reqOpts)
if r.Err == nil {
r.Header = result.Header
@@ -311,7 +318,7 @@ func dbClusterCreate(client databaseClient, opts optsBuilder) (r createClusterRe
// dbClusterGet performs request to get database cluster
func dbClusterGet(client databaseClient, id string) (r getClusterResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(getURL(client, dbClustersAPIPath, id), &r.Body, reqOpts)
if r.Err == nil {
@@ -321,7 +328,7 @@ func dbClusterGet(client databaseClient, id string) (r getClusterResult) {
}
func dbClusterDelete(client databaseClient, id string) (r deleteClusterResult) {
- reqOpts := getDBRequestOpts()
+ reqOpts := getRequestOpts()
var result *http.Response
result, r.Err = client.Delete(getURL(client, dbClustersAPIPath, id), reqOpts)
if r.Err == nil {
@@ -337,7 +344,7 @@ func dbClusterAction(client databaseClient, id string, opts optsBuilder) (r clus
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
result, r.Err = client.Post(getURL(client, dbClustersAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -353,7 +360,7 @@ func dbClusterUpdateAutoExpand(client databaseClient, id string, opts optsBuilde
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
result, r.Err = client.Patch(getURL(client, dbClustersAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -368,7 +375,7 @@ func dbClusterUpdateBackupSchedule(client databaseClient, id string, opts optsBu
r.Err = err
return
}
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Put(backupScheduleURL(client, clustersAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -378,7 +385,7 @@ func dbClusterUpdateBackupSchedule(client databaseClient, id string, opts optsBu
}
func dbClusterGetBackupSchedule(client databaseClient, id string) (r getClusterBackupScheduleResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(backupScheduleURL(client, clustersAPIPath, id), &r.Body, reqOpts)
if r.Err == nil {
diff --git a/vkcs/db_config_group.go b/vkcs/db_config_group.go
index 0420853e..4d5bebdd 100644
--- a/vkcs/db_config_group.go
+++ b/vkcs/db_config_group.go
@@ -57,7 +57,7 @@ func getDSParameterTypesMap(dsParameters []dbDatastoreParametersResp) map[string
return dsParameterTypes
}
-func retrieveDatabaseConfigGroupValues(client databaseClient, datastore dataStore, v map[string]interface{}) (map[string]interface{}, error) {
+func retrieveDatabaseConfigGroupValues(client databaseClient, datastore dataStoreShort, v map[string]interface{}) (map[string]interface{}, error) {
dsParameters, err := dbDatastoreParametersGet(client, datastore.Type, datastore.Version).extract()
if err != nil {
return nil, fmt.Errorf("unable to determine vkcs_db_config_group parameter types")
diff --git a/vkcs/db_config_group_client.go b/vkcs/db_config_group_client.go
index 7126ade8..c0dfb216 100644
--- a/vkcs/db_config_group_client.go
+++ b/vkcs/db_config_group_client.go
@@ -11,7 +11,7 @@ type dbConfigGroup struct {
}
type dbConfigGroupCreateOpts struct {
- Datastore *dataStore `json:"datastore"`
+ Datastore *dataStoreShort `json:"datastore"`
Name string `json:"name"`
Values map[string]interface{} `json:"values"`
Description string `json:"description,omitempty"`
@@ -107,7 +107,7 @@ func dbConfigGroupCreate(client databaseClient, opts optsBuilder) (r getDBConfig
return
}
var result *http.Response
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
result, r.Err = client.Post(baseURL(client, dbConfigGroupsAPIPath), b, &r.Body, reqOpts)
if r.Err == nil {
r.Header = result.Header
@@ -116,7 +116,7 @@ func dbConfigGroupCreate(client databaseClient, opts optsBuilder) (r getDBConfig
}
func dbConfigGroupGet(client databaseClient, id string) (r getDBConfigGroupResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(getURL(client, dbConfigGroupsAPIPath, id), &r.Body, reqOpts)
if r.Err == nil {
@@ -131,7 +131,7 @@ func dbConfigGroupUpdate(client databaseClient, id string, opts optsBuilder) (r
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
result, r.Err = client.Put(getURL(client, dbConfigGroupsAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -141,7 +141,7 @@ func dbConfigGroupUpdate(client databaseClient, id string, opts optsBuilder) (r
}
func dbConfigGroupDelete(client databaseClient, id string) (r deleteDBConfigGroupResult) {
- reqOpts := getDBRequestOpts()
+ reqOpts := getRequestOpts()
var result *http.Response
result, r.Err = client.Delete(getURL(client, dbConfigGroupsAPIPath, id), reqOpts)
if r.Err == nil {
@@ -151,7 +151,7 @@ func dbConfigGroupDelete(client databaseClient, id string) (r deleteDBConfigGrou
}
func dbDatastoreParametersGet(client databaseClient, dsType string, dsVersion string) (r getDBDatastoreParametersResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(datastoreParametersURL(client, dbDatastoresAPIPath, dsType, dsVersion), &r.Body, reqOpts)
if r.Err == nil {
diff --git a/vkcs/db_datastore_client.go b/vkcs/db_datastore_client.go
new file mode 100644
index 00000000..6fd40980
--- /dev/null
+++ b/vkcs/db_datastore_client.go
@@ -0,0 +1,162 @@
+package vkcs
+
+import (
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
+)
+
+// dataStoreVersion represents a version API resource
+// Multiple versions belong to a dataStore.
+type dataStoreVersion struct {
+ ID string
+ Links []gophercloud.Link
+ Name string
+}
+
+// dataStore represents a Datastore API resource.
+type dataStore struct {
+ Name string `json:"name"`
+ ID string `json:"id"`
+ MinimumCPU int `json:"minimum_cpu"`
+ MinimumRAM int `json:"minimum_ram"`
+ Versions []dataStoreVersion `json:"versions"`
+ VolumeTypes []string `json:"volume_types"`
+ ClusterVolumeTypes []string `json:"cluster_volume_types"`
+}
+
+// capabilityParam represents a parameter of a Datastore capability.
+type capabilityParam struct {
+ Required bool `json:"required"`
+ Type string `json:"type"`
+ ElementType string `json:"element_type"`
+ EnumValues []string `json:"enum_values"`
+ DefaultValue interface{} `json:"default_value"` // workaround since there's bug in API response
+ MinValue float64 `json:"min"`
+ MaxValue float64 `json:"max"`
+ Regex string `json:"regex"`
+ Masked bool `json:"masked"`
+}
+
+// dataStoreCapability represents a Datastore capability.
+type dataStoreCapability struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Status string `json:"status"`
+ Params map[string]*capabilityParam `json:"params"`
+ ShouldBeOnMaster bool `json:"should_be_on_master"`
+ AllowUpgradeFromBackup bool `json:"allow_upgrade_from_backup"`
+ AllowMajorUpgrade bool `json:"allow_major_upgrade"`
+}
+
+// dataStoreCapabilities represents a object containing all datastore
+// capabilities.
+type dataStoreCapabilities struct {
+ Capabilities []dataStoreCapability `json:"capabilities"`
+}
+
+// dataStoreParam represents a configuration parameter supported by a datastore
+type dataStoreParam struct {
+ Name string `json:"name"`
+ Type string `json:"type"`
+ MinValue float64 `json:"min"`
+ MaxValue float64 `json:"max"`
+ RestartRequried bool `json:"restart_required"`
+}
+
+// dataStoreParams represents a object containing all datastore
+// configuration parameters.
+type dataStoreParams struct {
+ Params []dataStoreParam `json:"configuration-parameters"`
+}
+
+// dataStoreGetResult represents the result of a dataStoreGet operation.
+type dataStoreGetResult struct {
+ gophercloud.Result
+}
+
+// dataStorePage represents a page of datastore resources.
+type dataStorePage struct {
+ pagination.SinglePageBase
+}
+
+// dataStoreListCapabilitiesResult represents the result of
+// dataStoreListCapabilities operation.
+type dataStoreListCapabilitiesResult struct {
+ gophercloud.Result
+}
+
+// Extract retrieves a single dataStore struct from an operation result.
+func (r dataStoreGetResult) Extract() (*dataStore, error) {
+ var s struct {
+ Datastore *dataStore `json:"datastore"`
+ }
+ err := r.ExtractInto(&s)
+ return s.Datastore, err
+}
+
+// IsEmpty indicates whether a Datastore collection is empty.
+func (r dataStorePage) IsEmpty() (bool, error) {
+ is, err := extractDatastores(r)
+ return len(is) == 0, err
+}
+
+// extractDatastores retrieves a slice of dataStore structs from a paginated
+// collection.
+func extractDatastores(r pagination.Page) ([]dataStore, error) {
+ var s struct {
+ Datastores []dataStore `json:"datastores"`
+ }
+ err := (r.(dataStorePage)).ExtractInto(&s)
+ return s.Datastores, err
+}
+
+// dataStoreListParametersResult represents the result of
+// dataStoreListParameters operation.
+type dataStoreListParametersResult struct {
+ gophercloud.Result
+}
+
+func (r dataStoreListCapabilitiesResult) Extract() ([]dataStoreCapability, error) {
+ var dsCapabilities dataStoreCapabilities
+ err := r.ExtractInto(&dsCapabilities)
+ return dsCapabilities.Capabilities, err
+}
+
+func (r dataStoreListParametersResult) Extract() ([]dataStoreParam, error) {
+ var dsParams dataStoreParams
+ err := r.ExtractInto(&dsParams)
+ return dsParams.Params, err
+}
+
+var datastoresAPIPath = "datastores"
+
+// dataStoreList will list all available datastores that instances can use.
+func dataStoreList(client databaseClient) pagination.Pager {
+ return pagination.NewPager(client.(*gophercloud.ServiceClient), datastoresURL(client, datastoresAPIPath),
+ func(r pagination.PageResult) pagination.Page {
+ return dataStorePage{pagination.SinglePageBase(r)}
+ })
+}
+
+// dataStoreGet will retrieve the details of a specified datastore type.
+func dataStoreGet(client databaseClient, datastoreID string) (r dataStoreGetResult) {
+ resp, err := client.Get(datastoreURL(client, datastoresAPIPath, datastoreID), &r.Body, nil)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+func dataStoreListCapabilities(client databaseClient, dsName string, versionID string) (r dataStoreListCapabilitiesResult) {
+ url := datastoreCapabilitiesURL(client, datastoresAPIPath, dsName, versionID)
+ resp, err := client.Get(url, &r.Body, nil)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+// dataStoreListParameters will list all available configuration parameters
+// for a specific version of a datastore.
+func dataStoreListParameters(client databaseClient, dsName string, versionID string) (r dataStoreListParametersResult) {
+ url := datastoreParametersURL(client, datastoresAPIPath, dsName, versionID)
+ resp, err := client.Get(url, &r.Body, nil)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
diff --git a/vkcs/db_instance.go b/vkcs/db_instance.go
index e2ba9378..5366da73 100755
--- a/vkcs/db_instance.go
+++ b/vkcs/db_instance.go
@@ -7,6 +7,7 @@ import (
"github.com/mitchellh/mapstructure"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
// Datastore names
@@ -39,8 +40,8 @@ func extractDatabaseRestorePoint(v []interface{}) (restorePoint, error) {
return R, nil
}
-func extractDatabaseDatastore(v []interface{}) (dataStore, error) {
- var D dataStore
+func extractDatabaseDatastore(v []interface{}) (dataStoreShort, error) {
+ var D dataStoreShort
in := v[0].(map[string]interface{})
err := mapStructureDecoder(&D, &in, decoderConfig)
if err != nil {
@@ -49,7 +50,7 @@ func extractDatabaseDatastore(v []interface{}) (dataStore, error) {
return D, nil
}
-func flattenDatabaseInstanceDatastore(d dataStore) []map[string]interface{} {
+func flattenDatabaseInstanceDatastore(d dataStoreShort) []map[string]interface{} {
datastore := make([]map[string]interface{}, 1)
datastore[0] = make(map[string]interface{})
datastore[0]["type"] = d.Type
@@ -57,17 +58,23 @@ func flattenDatabaseInstanceDatastore(d dataStore) []map[string]interface{} {
return datastore
}
-func extractDatabaseNetworks(v []interface{}) ([]networkOpts, error) {
+func extractDatabaseNetworks(v []interface{}) ([]networkOpts, []string, error) {
Networks := make([]networkOpts, len(v))
+ var SecurityGroups []string
for i, network := range v {
var N networkOpts
- err := mapstructure.Decode(network.(map[string]interface{}), &N)
+ networkMap := network.(map[string]interface{})
+ sg, ok := networkMap["security_groups"]
+ if ok {
+ SecurityGroups = expandToStringSlice(sg.(*schema.Set).List())
+ }
+ err := mapstructure.Decode(networkMap, &N)
if err != nil {
- return nil, err
+ return nil, nil, err
}
Networks[i] = N
}
- return Networks, nil
+ return Networks, SecurityGroups, nil
}
func extractDatabaseAutoExpand(v []interface{}) (instanceAutoExpandOpts, error) {
diff --git a/vkcs/db_instance_client.go b/vkcs/db_instance_client.go
index 97e1acd4..d49f027a 100755
--- a/vkcs/db_instance_client.go
+++ b/vkcs/db_instance_client.go
@@ -28,7 +28,7 @@ type instanceResp struct {
ID string `json:"id"`
Created dateTimeWithoutTZFormat `json:"created"`
Updated dateTimeWithoutTZFormat `json:"updated"`
- DataStore *dataStore `json:"datastore"`
+ DataStore *dataStoreShort `json:"datastore"`
Flavor *links `json:"flavor"`
GaVersion string `json:"ga_version"`
HealthStatus string `json:"health_status"`
@@ -79,8 +79,8 @@ type links struct {
Links *[]link `json:"links"`
}
-// dataStore represents dbaas datastore
-type dataStore struct {
+// dataStoreShort represents dbaas datastore short response
+type dataStoreShort struct {
Type string `json:"type" required:"true"`
Version string `json:"version" required:"true"`
}
@@ -99,7 +99,7 @@ type configuration struct {
}
type restorePoint struct {
- BackupRef string `json:"backup_ref" required:"true" mapstructure:"backup_id"`
+ BackupRef string `json:"backupRef" required:"true" mapstructure:"backup_id"`
Target string `json:"target,omitempty"`
}
@@ -189,6 +189,13 @@ type instanceRootUserEnableOpts struct {
Password string `json:"password,omitempty"`
}
+// iinstanceUpdateCloudMonitoringOpts represents parameters of request to update cloud monitoring options
+type updateCloudMonitoringOpts struct {
+ CloudMonitoring struct {
+ Enable bool `json:"enable"`
+ } `json:"cloud_monitoring"`
+}
+
// instanceRespOpts is used to get instance response
type instanceRespOpts struct {
Instance *instanceResp `json:"instance"`
@@ -313,6 +320,12 @@ func (opts *instanceRootUserEnableOpts) Map() (map[string]interface{}, error) {
return body, err
}
+// Map converts opts to a map (for a request body)
+func (opts *updateCloudMonitoringOpts) Map() (map[string]interface{}, error) {
+ body, err := gophercloud.BuildRequestBody(*opts, "")
+ return body, err
+}
+
// Map converts opts to a map (for a request body)
func (opts *instanceUpdateAutoExpandOpts) Map() (map[string]interface{}, error) {
body, err := gophercloud.BuildRequestBody(*opts, "")
@@ -367,21 +380,23 @@ type dbInstance struct {
// dbInstanceCreateOpts represents parameters of creation of database instance
type dbInstanceCreateOpts struct {
- FlavorRef string `json:"flavorRef,omitempty"`
- Volume *volume `json:"volume" required:"true"`
- Name string `json:"name" required:"true"`
- Datastore *dataStore `json:"datastore" required:"true"`
- Nics []networkOpts `json:"nics" required:"true"`
- ReplicaOf string `json:"replica_of,omitempty"`
- AvailabilityZone string `json:"availability_zone,omitempty"`
- FloatingIPEnabled bool `json:"allow_remote_access,omitempty"`
- Keypair string `json:"key_name,omitempty"`
- AutoExpand *int `json:"volume_autoresize_enabled,omitempty"`
- MaxDiskSize int `json:"volume_autoresize_max_size,omitempty"`
- Walvolume *walVolume `json:"wal_volume,omitempty"`
- Capabilities []instanceCapabilityOpts `json:"capabilities,omitempty"`
- RestorePoint *restorePoint `json:"restore_point,omitempty"`
- BackupSchedule *backupSchedule `json:"backup_schedule,omitempty"`
+ FlavorRef string `json:"flavorRef,omitempty"`
+ Volume *volume `json:"volume" required:"true"`
+ Name string `json:"name" required:"true"`
+ Datastore *dataStoreShort `json:"datastore" required:"true"`
+ Nics []networkOpts `json:"nics" required:"true"`
+ ReplicaOf string `json:"replica_of,omitempty"`
+ AvailabilityZone string `json:"availability_zone,omitempty"`
+ FloatingIPEnabled bool `json:"allow_remote_access,omitempty"`
+ Keypair string `json:"key_name,omitempty"`
+ AutoExpand *int `json:"volume_autoresize_enabled,omitempty"`
+ MaxDiskSize int `json:"volume_autoresize_max_size,omitempty"`
+ Walvolume *walVolume `json:"wal_volume,omitempty"`
+ Capabilities []instanceCapabilityOpts `json:"capabilities,omitempty"`
+ RestorePoint *restorePoint `json:"restorePoint,omitempty"`
+ BackupSchedule *backupSchedule `json:"backup_schedule,omitempty"`
+ CloudMonitoringEnabled bool `json:"cloud_monitoring_enabled,omitempty"`
+ SecurityGroups []string `json:"security_groups,omitempty"`
}
// networkOpts represents network parameters of database instance
@@ -389,6 +404,7 @@ type networkOpts struct {
UUID string `json:"net-id,omitempty"`
Port string `json:"port-id,omitempty"`
V4FixedIP string `json:"v4-fixed-ip,omitempty" mapstructure:"fixed_ip_v4"`
+ SubnetID string `json:"subnet-id,omitempty" mapstructure:"subnet_id"`
}
type commonInstanceResult struct {
@@ -584,7 +600,7 @@ func instanceCreate(client databaseClient, opts optsBuilder) (r getInstanceShort
return
}
var result *http.Response
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
result, r.Err = client.Post(baseURL(client, instancesAPIPath), b, &r.Body, reqOpts)
if r.Err == nil {
r.Header = result.Header
@@ -594,7 +610,7 @@ func instanceCreate(client databaseClient, opts optsBuilder) (r getInstanceShort
// instanceGet performs request to get database instance
func instanceGet(client databaseClient, id string) (r getInstanceResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(getURL(client, instancesAPIPath, id), &r.Body, reqOpts)
if r.Err == nil {
@@ -604,7 +620,7 @@ func instanceGet(client databaseClient, id string) (r getInstanceResult) {
}
func instanceGetCapabilities(client databaseClient, id string) (r getInstanceCapabilitiesResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(instanceCapabilitiesURL(client, instancesAPIPath, id), &r.Body, reqOpts)
if r.Err == nil {
@@ -614,7 +630,7 @@ func instanceGetCapabilities(client databaseClient, id string) (r getInstanceCap
}
func clusterGetCapabilities(client databaseClient, id string) (r getInstanceCapabilitiesResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(instanceCapabilitiesURL(client, dbClustersAPIPath, id), &r.Body, reqOpts)
if r.Err == nil {
@@ -624,7 +640,7 @@ func clusterGetCapabilities(client databaseClient, id string) (r getInstanceCapa
}
func instanceGetBackupSchedule(client databaseClient, id string) (r getInstanceBackupScheduleResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Get(backupScheduleURL(client, instancesAPIPath, id), &r.Body, reqOpts)
if r.Err == nil {
@@ -640,7 +656,7 @@ func instanceDetachReplica(client databaseClient, id string, opts optsBuilder) (
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
result, r.Err = client.Patch(getURL(client, instancesAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -656,7 +672,7 @@ func instanceUpdateAutoExpand(client databaseClient, id string, opts optsBuilder
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
result, r.Err = client.Patch(getURL(client, instancesAPIPath, id), &b, nil, reqOpts)
if r.Err == nil {
@@ -675,7 +691,7 @@ func instanceDetachConfigurationGroup(client databaseClient, id string) (r confi
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
result, r.Err = client.Put(getURL(client, instancesAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -691,7 +707,7 @@ func instanceAttachConfigurationGroup(client databaseClient, id string, opts opt
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
result, r.Err = client.Put(getURL(client, instancesAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -707,7 +723,7 @@ func instanceAction(client databaseClient, id string, opts optsBuilder) (r actio
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
result, r.Err = client.Post(instanceActionURL(client, instancesAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -723,7 +739,7 @@ func instanceRootUserEnable(client databaseClient, id string, opts optsBuilder)
r.Err = err
return
}
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Post(rootUserURL(client, instancesAPIPath, id), b, &r.Body, reqOpts)
if r.Err == nil {
@@ -735,7 +751,7 @@ func instanceRootUserEnable(client databaseClient, id string, opts optsBuilder)
// instanceRootUserGet performs request to get root user of database instance
func instanceRootUserGet(client databaseClient, id string) (r isRootUserEnabledResult) {
var result *http.Response
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
result, err := client.Get(rootUserURL(client, instancesAPIPath, id), &r.Body, reqOpts)
if err == nil {
r.Header = result.Header
@@ -745,7 +761,7 @@ func instanceRootUserGet(client databaseClient, id string) (r isRootUserEnabledR
// instanceRootUserDisable performs request to disable root user on database instance
func instanceRootUserDisable(client databaseClient, id string) (r deleteRootUserResult) {
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Delete(rootUserURL(client, instancesAPIPath, id), reqOpts)
if r.Err == nil {
@@ -760,7 +776,7 @@ func instanceUpdateBackupSchedule(client databaseClient, id string, opts optsBui
r.Err = err
return
}
- reqOpts := getDBRequestOpts(200)
+ reqOpts := getRequestOpts(200)
var result *http.Response
result, r.Err = client.Put(backupScheduleURL(client, instancesAPIPath, id), b, nil, reqOpts)
if r.Err == nil {
@@ -771,7 +787,7 @@ func instanceUpdateBackupSchedule(client databaseClient, id string, opts optsBui
// instanceDelete performs request to delete database instance
func instanceDelete(client databaseClient, id string) (r deleteResult) {
- reqOpts := getDBRequestOpts()
+ reqOpts := getRequestOpts()
var result *http.Response
result, r.Err = client.Delete(getURL(client, instancesAPIPath, id), reqOpts)
if r.Err == nil {
@@ -787,7 +803,7 @@ func userCreate(client databaseClient, id string, opts createOptsBuilder, dbmsTy
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
if dbmsType == dbmsTypeInstance {
result, r.Err = client.Post(instanceUsersURL(client, instancesAPIPath, id), b, nil, reqOpts)
@@ -815,7 +831,7 @@ func userList(client databaseClient, id string, dbmsType string) pagination.Page
// userDelete performs request to delete database user
func userDelete(client databaseClient, id string, userName string, dbmsType string) (r userDeleteResult) {
- reqOpts := getDBRequestOpts()
+ reqOpts := getRequestOpts()
var result *http.Response
var APIPath string
if dbmsType == dbmsTypeInstance {
@@ -837,7 +853,7 @@ func userUpdate(client databaseClient, id string, name string, opts optsBuilder,
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var APIPath string
if dbmsType == dbmsTypeInstance {
APIPath = instancesAPIPath
@@ -859,7 +875,7 @@ func userUpdateDatabases(client databaseClient, id string, name string, opts opt
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
var APIPath string
if dbmsType == dbmsTypeInstance {
@@ -876,7 +892,7 @@ func userUpdateDatabases(client databaseClient, id string, name string, opts opt
// userDeleteDatabase performs request to delete database user
func userDeleteDatabase(client databaseClient, id string, userName string, dbName string, dbmsType string) (r deleteUserDatabaseResult) {
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
var APIPath string
if dbmsType == dbmsTypeInstance {
@@ -898,7 +914,7 @@ func databaseCreate(client databaseClient, id string, opts createOptsBuilder, db
r.Err = err
return
}
- reqOpts := getDBRequestOpts(202)
+ reqOpts := getRequestOpts(202)
var result *http.Response
var APIPath string
if dbmsType == dbmsTypeInstance {
@@ -929,7 +945,7 @@ func databaseList(client databaseClient, id string, dbmsType string) pagination.
// databaseDelete performs request to delete database
func databaseDelete(client databaseClient, id string, dbName string, dbmsType string) (r databaseDeleteResult) {
- reqOpts := getDBRequestOpts()
+ reqOpts := getRequestOpts()
var result *http.Response
var APIPath string
if dbmsType == dbmsTypeInstance {
diff --git a/vkcs/db_instance_test.go b/vkcs/db_instance_test.go
index ff9f1c32..787aff6c 100755
--- a/vkcs/db_instance_test.go
+++ b/vkcs/db_instance_test.go
@@ -17,7 +17,7 @@ func TestExtractInstanceDatastore(t *testing.T) {
},
}
- expected := dataStore{
+ expected := dataStoreShort{
Version: "foo",
Type: "bar",
}
diff --git a/vkcs/db_shared.go b/vkcs/db_shared.go
new file mode 100644
index 00000000..72a89314
--- /dev/null
+++ b/vkcs/db_shared.go
@@ -0,0 +1,65 @@
+package vkcs
+
+import (
+ "context"
+ "errors"
+
+ "github.com/hashicorp/go-cty/cty"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceDatabaseCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error {
+ if diff.Id() != "" && diff.HasChange("cloud_monitoring_enabled") {
+ t, exists := diff.GetOk("datastore.0.type")
+ if !exists {
+ return errors.New("datastore.0.type is not found")
+ }
+ if exists && isOperationNotSupported(t.(string), Redis, MongoDB) {
+ return diff.ForceNew("cloud_monitoring_enabled")
+ }
+ }
+ return nil
+}
+
+func checkDBNetworks(
+ rawNetworks []interface{}, path cty.Path, diags diag.Diagnostics,
+) diag.Diagnostics {
+ if len(rawNetworks) < 2 {
+ return diags
+ }
+ p := path
+ p = append(p,
+ cty.GetAttrStep{Name: "network"},
+ cty.IndexStep{Key: cty.NumberIntVal(1)},
+ )
+ diags = append(diags, diag.Diagnostic{
+ Severity: diag.Warning,
+ Summary: "Multiple networks are deprecated",
+ Detail: "Multiple networks are deprecated and won't be supported in next major release.",
+ AttributePath: p,
+ })
+ hasNetWithSecGroup := -1
+ for i, n := range rawNetworks {
+ rawNetwork := n.(map[string]interface{})
+ if rawNetwork["security_groups"] != nil {
+ if hasNetWithSecGroup < 0 {
+ hasNetWithSecGroup = i
+ continue
+ }
+ p := path
+ p = append(p,
+ cty.GetAttrStep{Name: "network"},
+ cty.IndexStep{Key: cty.NumberIntVal(int64(hasNetWithSecGroup))},
+ cty.GetAttrStep{Name: "security_groups"},
+ )
+ diags = append(diags, diag.Diagnostic{
+ Severity: diag.Warning,
+ Summary: "Argument \"security_group\" is ignored",
+ Detail: "Argument \"security_group\" is overwritten by the last occurrence.",
+ AttributePath: p,
+ })
+ }
+ }
+ return diags
+}
diff --git a/vkcs/images_image.go b/vkcs/images_image.go
index 5a919611..df154967 100644
--- a/vkcs/images_image.go
+++ b/vkcs/images_image.go
@@ -8,8 +8,10 @@ import (
"io"
"log"
"net/http"
+ "net/url"
"os"
"path/filepath"
+ "regexp"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
@@ -19,6 +21,8 @@ import (
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
)
+var imagesDefaultStoreEndpointMasks = []string{"*.devmail.ru$", "^ams.*"}
+
func resourceImagesImageMemberStatusFromString(v string) images.ImageMemberStatus {
switch v {
case string(images.ImageMemberStatusAccepted):
@@ -165,11 +169,22 @@ func resourceImagesImageExpandProperties(v map[string]interface{}) map[string]st
properties[key] = v
}
}
- properties["store"] = "s3"
return properties
}
+func resourceImagesImageNeedsDefaultStore(endpoint string) bool {
+ endpointURL, _ := url.Parse(endpoint)
+ hostname := endpointURL.Hostname()
+ for _, mask := range imagesDefaultStoreEndpointMasks {
+ matches, _ := regexp.MatchString(mask, hostname)
+ if matches {
+ return true
+ }
+ }
+ return false
+}
+
func resourceImagesImageUpdateComputedAttributes(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error {
if diff.HasChange("properties") {
// Only check if the image has been created.
@@ -191,6 +206,12 @@ func resourceImagesImageUpdateComputedAttributes(_ context.Context, diff *schema
}
}
+ if oldKey == "store" {
+ if v, ok := oldValue.(string); ok {
+ newProperties[oldKey] = v
+ }
+ }
+
// direct_url is provided by some storage drivers.
if oldKey == "direct_url" {
if v, ok := oldValue.(string); ok {
diff --git a/vkcs/import_vkcs_publicdns_record_test.go b/vkcs/import_vkcs_publicdns_record_test.go
new file mode 100644
index 00000000..6e682035
--- /dev/null
+++ b/vkcs/import_vkcs_publicdns_record_test.go
@@ -0,0 +1,46 @@
+package vkcs
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+)
+
+func TestAccPublicDNSRecord_importBasic(t *testing.T) {
+ resourceName := "vkcs_publicdns_record.record_a"
+ zoneName := fmt.Sprintf("vkcs-tf-acctest-%s.com", acctest.RandString(5))
+
+ resource.Test(t, resource.TestCase{
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckPublicDNSRecordDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfigWithZone(testAccPublicDNSRecordConfigBasic, zoneName),
+ },
+
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateIdFunc: func(s *terraform.State) (string, error) {
+ for _, rs := range s.RootModule().Resources {
+ if rs.Type != "vkcs_publicdns_record" {
+ continue
+ }
+
+ zoneID := rs.Primary.Attributes["zone_id"]
+ recordType := strings.ToLower(rs.Primary.Attributes["type"])
+ recordID := rs.Primary.ID
+
+ return fmt.Sprintf("%s/%s/%s", zoneID, recordType, recordID), nil
+ }
+ return "", fmt.Errorf("Record not found")
+ },
+ },
+ },
+ })
+}
diff --git a/vkcs/import_vkcs_publicdns_zone_test.go b/vkcs/import_vkcs_publicdns_zone_test.go
new file mode 100644
index 00000000..f12898c6
--- /dev/null
+++ b/vkcs/import_vkcs_publicdns_zone_test.go
@@ -0,0 +1,30 @@
+package vkcs
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccPublicDNSZone_importBasic(t *testing.T) {
+ resourceName := "vkcs_publicdns_zone.zone_1"
+ zoneName := fmt.Sprintf("vkcs-tf-acctest-%s.com", acctest.RandString(5))
+
+ resource.Test(t, resource.TestCase{
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckPublicDNSZoneDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfigWithZone(testAccPublicDNSZoneConfigBasic, zoneName),
+ },
+
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
diff --git a/vkcs/internal/pathorcontents/read_test.go b/vkcs/internal/pathorcontents/read_test.go
index d42fa50b..976866bd 100755
--- a/vkcs/internal/pathorcontents/read_test.go
+++ b/vkcs/internal/pathorcontents/read_test.go
@@ -4,6 +4,7 @@ import (
"io"
"os"
"os/user"
+ "runtime"
"strings"
"testing"
@@ -70,6 +71,9 @@ func TestRead_PathNoPermission(t *testing.T) {
if u, err := user.Current(); err == nil && u.Uid == "0" {
t.Skip("This test is invalid when running as root, since root can read every file")
}
+ if runtime.GOOS == "windows" {
+ t.Skip("This test is invalid when running on Windows, since chmod does not work")
+ }
isPath := true
f, cleanup := testTempFile(t)
diff --git a/vkcs/kubernetes_cluster_client.go b/vkcs/kubernetes_cluster_client.go
index cd89f2b3..0dcf6fde 100755
--- a/vkcs/kubernetes_cluster_client.go
+++ b/vkcs/kubernetes_cluster_client.go
@@ -2,7 +2,6 @@ package vkcs
import (
"bytes"
- "fmt"
"io"
"log"
"net/http"
@@ -13,15 +12,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clustertemplates"
)
-const magnumAPIMicroVersion = "1.28"
-
-var magnumAPIMicroVersionHeader = map[string]string{
- "MCS-API-Version": fmt.Sprintf("container-infra %s", magnumAPIMicroVersion),
-}
-
-func addMagnumMicroVersionHeader(reqOpts *gophercloud.RequestOpts) {
- reqOpts.MoreHeaders = magnumAPIMicroVersionHeader
-}
+const cloudContainersAPIVersion = "1.28"
type node struct {
Name string `json:"name"`
diff --git a/vkcs/lb_shared.go b/vkcs/lb_shared.go
index 5f93f84d..971c29dc 100644
--- a/vkcs/lb_shared.go
+++ b/vkcs/lb_shared.go
@@ -634,27 +634,6 @@ func expandLBMembers(members *schema.Set, lbClient *gophercloud.ServiceClient) [
return m
}
-func resourceLoadBalancerSetSecurityGroups(networkingClient *gophercloud.ServiceClient, vipPortID string, d *schema.ResourceData) error {
- if vipPortID != "" {
- if v, ok := d.GetOk("security_group_ids"); ok {
- securityGroups := expandToStringSlice(v.(*schema.Set).List())
- updateOpts := ports.UpdateOpts{
- SecurityGroups: &securityGroups,
- }
-
- log.Printf("[DEBUG] Adding security groups to vkcs_lb_loadbalancer "+
- "VIP port %s: %#v", vipPortID, updateOpts)
-
- _, err := ports.Update(networkingClient, vipPortID, updateOpts).Extract()
- if err != nil {
- return err
- }
- }
- }
-
- return nil
-}
-
func resourceLoadBalancerGetSecurityGroups(networkingClient *gophercloud.ServiceClient, vipPortID string, d *schema.ResourceData) error {
port, err := ports.Get(networkingClient, vipPortID).Extract()
if err != nil {
diff --git a/vkcs/networking_shared.go b/vkcs/networking_shared.go
index 3a8a35de..9936c237 100644
--- a/vkcs/networking_shared.go
+++ b/vkcs/networking_shared.go
@@ -10,6 +10,7 @@ import (
)
const defaultSDN = "neutron"
+const searchInAllSDNs = "all"
func networkingReadAttributesTags(d *schema.ResourceData, tags []string) {
expandObjectReadTags(d, tags)
diff --git a/vkcs/provider.go b/vkcs/provider.go
index a8e60d74..0d3173d5 100755
--- a/vkcs/provider.go
+++ b/vkcs/provider.go
@@ -2,6 +2,7 @@ package vkcs
import (
"context"
+ "fmt"
"net/http"
"time"
@@ -29,6 +30,7 @@ type configer interface {
ComputeV2Client(region string) (*gophercloud.ServiceClient, error)
ImageV2Client(region string) (*gophercloud.ServiceClient, error)
NetworkingV2Client(region string, sdn string) (*gophercloud.ServiceClient, error)
+ PublicDNSV2Client(region string) (*gophercloud.ServiceClient, error)
BlockStorageV3Client(region string) (*gophercloud.ServiceClient, error)
KeyManagerV1Client(region string) (*gophercloud.ServiceClient, error)
ContainerInfraV1Client(region string) (ContainerClient, error)
@@ -40,6 +42,7 @@ type configer interface {
// config uses openstackbase.Config as the base/foundation of this provider's
type config struct {
auth.Config
+ ContainerInfraV1MicroVersion string
}
var _ configer = &config{}
@@ -62,12 +65,18 @@ func (c *config) NetworkingV2Client(region string, sdn string) (*gophercloud.Ser
if err != nil {
return client, err
}
- client.MoreHeaders = map[string]string{
- "X-SDN": sdn,
+ if sdn != searchInAllSDNs {
+ client.MoreHeaders = map[string]string{
+ "X-SDN": sdn,
+ }
}
return client, err
}
+func (c *config) PublicDNSV2Client(region string) (*gophercloud.ServiceClient, error) {
+ return c.CommonServiceClientInit(newPublicDNSV2, region, "publicdns")
+}
+
func (c *config) BlockStorageV3Client(region string) (*gophercloud.ServiceClient, error) {
return c.Config.BlockStorageV3Client(region)
}
@@ -102,7 +111,14 @@ func (c *config) DatabaseV1Client(region string) (*gophercloud.ServiceClient, er
// ContainerInfraV1Client is implementation of ContainerInfraV1Client method
func (c *config) ContainerInfraV1Client(region string) (ContainerClient, error) {
- return c.Config.ContainerInfraV1Client(region)
+ client, err := c.Config.ContainerInfraV1Client(region)
+ if err != nil {
+ return client, err
+ }
+ client.MoreHeaders = map[string]string{
+ "MCS-API-Version": fmt.Sprintf("container-infra %s", c.ContainerInfraV1MicroVersion),
+ }
+ return client, err
}
// IdentityV3Client is implementation of ContainerInfraV1Client method
@@ -130,6 +146,7 @@ func newConfig(d *schema.ResourceData, terraformVersion string) (configer, diag.
SDKVersion: meta.SDKVersionString(),
MutexKV: mutexkv.NewMutexKV(),
},
+ d.Get("cloud_containers_api_version").(string),
}
if config.UserDomainID != "" {
@@ -189,6 +206,13 @@ func Provider() *schema.Provider {
DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", defaultRegionName),
Description: "A region to use.",
},
+ "cloud_containers_api_version": {
+ Type: schema.TypeString,
+ Optional: true,
+ Default: cloudContainersAPIVersion,
+ Description: "Cloud Containers API version to use.\n" +
+ "_NOTE_ Only for custom VKCS deployments.",
+ },
},
DataSourcesMap: map[string]*schema.Resource{
@@ -208,9 +232,14 @@ func Provider() *schema.Provider {
"vkcs_keymanager_container": dataSourceKeyManagerContainer(),
"vkcs_blockstorage_volume": dataSourceBlockStorageVolume(),
"vkcs_blockstorage_snapshot": dataSourceBlockStorageSnapshot(),
+ "vkcs_lb_loadbalancer": dataSourceLoadBalancer(),
"vkcs_sharedfilesystem_sharenetwork": dataSourceSharedFilesystemShareNetwork(),
"vkcs_sharedfilesystem_share": dataSourceSharedFilesystemShare(),
"vkcs_db_database": dataSourceDatabaseDatabase(),
+ "vkcs_db_datastore": dataSourceDatabaseDatastore(),
+ "vkcs_db_datastore_capabilities": dataSourceDatabaseDatastoreCapabilities(),
+ "vkcs_db_datastore_parameters": dataSourceDatabaseDatastoreParameters(),
+ "vkcs_db_datastores": dataSourceDatabaseDatastores(),
"vkcs_db_instance": dataSourceDatabaseInstance(),
"vkcs_db_user": dataSourceDatabaseUser(),
"vkcs_db_backup": dataSourceDatabaseBackup(),
@@ -221,6 +250,7 @@ func Provider() *schema.Provider {
"vkcs_kubernetes_node_group": dataSourceKubernetesNodeGroup(),
"vkcs_region": dataSourceVkcsRegion(),
"vkcs_regions": dataSourceVkcsRegions(),
+ "vkcs_publicdns_zone": dataSourcePublicDNSZone(),
},
ResourcesMap: map[string]*schema.Resource{
@@ -273,6 +303,8 @@ func Provider() *schema.Provider {
"vkcs_db_config_group": resourceDatabaseConfigGroup(),
"vkcs_kubernetes_cluster": resourceKubernetesCluster(),
"vkcs_kubernetes_node_group": resourceKubernetesNodeGroup(),
+ "vkcs_publicdns_zone": resourcePublicDNSZone(),
+ "vkcs_publicdns_record": resourcePublicDNSRecord(),
},
}
diff --git a/vkcs/publicdns_record.go b/vkcs/publicdns_record.go
new file mode 100644
index 00000000..6d22d2e9
--- /dev/null
+++ b/vkcs/publicdns_record.go
@@ -0,0 +1,83 @@
+package vkcs
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+type recordResult interface {
+ ExtractA() (*recordA, error)
+ ExtractAAAA() (*recordAAAA, error)
+ ExtractCNAME() (*recordCNAME, error)
+ ExtractMX() (*recordMX, error)
+ ExtractNS() (*recordNS, error)
+ ExtractSRV() (*recordSRV, error)
+ ExtractTXT() (*recordTXT, error)
+}
+
+func publicDNSRecordExtract(res recordResult, recordType string) (interface{}, error) {
+ var (
+ r interface{}
+ err error
+ )
+
+ switch recordType {
+ case recordTypeA:
+ r, err = res.ExtractA()
+ case recordTypeAAAA:
+ r, err = res.ExtractAAAA()
+ case recordTypeCNAME:
+ r, err = res.ExtractCNAME()
+ case recordTypeMX:
+ r, err = res.ExtractMX()
+ case recordTypeNS:
+ r, err = res.ExtractNS()
+ case recordTypeSRV:
+ r, err = res.ExtractSRV()
+ case recordTypeTXT:
+ r, err = res.ExtractTXT()
+ }
+
+ return r, err
+}
+
+func publicDNSRecordStateRefreshFunc(client publicDNSClient, zoneID string, id string, recordType string) resource.StateRefreshFunc {
+ return func() (interface{}, string, error) {
+ res := recordGet(client, zoneID, id, recordType)
+ record, err := publicDNSRecordExtract(res, recordType)
+
+ if err != nil {
+ if _, ok := err.(gophercloud.ErrDefault404); ok {
+ return record, recordStatusDeleted, nil
+ }
+ return nil, "", err
+ }
+
+ return record, recordStatusActive, nil
+ }
+}
+
+func publicDNSRecordParseZoneID(dns string) (string, error) {
+ dnsParts := strings.Split(dns, "/") // /v2/dns/
+ if len(dnsParts) != 4 {
+ return "", fmt.Errorf("unable to determine vkcs_publicdns_record zone ID from raw DNS: %s", dns)
+ }
+ zoneID := dnsParts[3]
+ return zoneID, nil
+}
+
+func publicDNSRecordParseID(id string) (string, string, string, error) {
+ parts := strings.Split(id, "/") // //
+ if len(parts) != 3 {
+ return "", "", "", fmt.Errorf("unable to determine vkcs_publicdns_record ID from %s", id)
+ }
+
+ zoneID := parts[0]
+ recordType := parts[1]
+ recordID := parts[2]
+
+ return zoneID, recordType, recordID, nil
+}
diff --git a/vkcs/publicdns_record_client.go b/vkcs/publicdns_record_client.go
new file mode 100644
index 00000000..f9209d00
--- /dev/null
+++ b/vkcs/publicdns_record_client.go
@@ -0,0 +1,394 @@
+package vkcs
+
+import (
+ "github.com/gophercloud/gophercloud"
+)
+
+type commonRecordResult struct {
+ gophercloud.Result
+ Type string
+}
+
+// ExtractA interprets a recordGetResult, recordCreateResult or recordUpdateResult as a recordA.
+// An error is returned if the original call or the extraction failed.
+func (r commonRecordResult) ExtractA() (*recordA, error) {
+ var s recordA
+ err := r.ExtractInto(&s)
+ return &s, err
+}
+
+// ExtractAAAA interprets a recordGetResult, recordCreateResult or recordUpdateResult as a recordAAA.
+// An error is returned if the original call or the extraction failed.
+func (r commonRecordResult) ExtractAAAA() (*recordAAAA, error) {
+ var s recordAAAA
+ err := r.ExtractInto(&s)
+ return &s, err
+}
+
+// ExtractCNAME interprets a recordGetResult, recordCreateResult or recordUpdateResult as a recordCNAME.
+// An error is returned if the original call or the extraction failed.
+func (r commonRecordResult) ExtractCNAME() (*recordCNAME, error) {
+ var s recordCNAME
+ err := r.ExtractInto(&s)
+ return &s, err
+}
+
+// ExtractMX interprets a recordGetResult, recordCreateResult or recordUpdateResult as a recordMX.
+// An error is returned if the original call or the extraction failed.
+func (r commonRecordResult) ExtractMX() (*recordMX, error) {
+ var s recordMX
+ err := r.ExtractInto(&s)
+ return &s, err
+}
+
+// ExtractNS interprets a recordGetResult, recordCreateResult or recordUpdateResult as a recordNS.
+// An error is returned if the original call or the extraction failed.
+func (r commonRecordResult) ExtractNS() (*recordNS, error) {
+ var s recordNS
+ err := r.ExtractInto(&s)
+ return &s, err
+}
+
+// ExtractSRV interprets a recordGetResult, recordCreateResult or recordUpdateResult as a recordSRV.
+// An error is returned if the original call or the extraction failed.
+func (r commonRecordResult) ExtractSRV() (*recordSRV, error) {
+ var s recordSRV
+ err := r.ExtractInto(&s)
+ return &s, err
+}
+
+// ExtractTXT interprets a recordGetResult, recordCreateResult or recordUpdateResult as a recordTXT.
+// An error is returned if the original call or the extraction failed.
+func (r commonRecordResult) ExtractTXT() (*recordTXT, error) {
+ var s recordTXT
+ err := r.ExtractInto(&s)
+ return &s, err
+}
+
+// recordCreateResult is the result of a recordCreate request. Call its Extract method
+// to interpret the result as a record.
+type recordCreateResult struct {
+ commonRecordResult
+}
+
+// recordGetResult is the result of a recordGet request. Call its Extract method
+// to interpret the result as a record.
+type recordGetResult struct {
+ commonRecordResult
+}
+
+// recordUpdateResult is the result of a recordUpdate request. Call its Extract method
+// to interpret the result as a record.
+type recordUpdateResult struct {
+ commonRecordResult
+}
+
+// recordDeleteResult is the result of a recordDelete request. Call its ExtractErr method
+// to determine if the request succeeded or failed.
+type recordDeleteResult struct {
+ gophercloud.ErrResult
+}
+
+// recordA represents a public DNS zone record A.
+type recordA struct {
+ UUID string `json:"uuid"`
+ DNS string `json:"dns"`
+ Name string `json:"name"`
+ IPv4 string `json:"ipv4"`
+ TTL int `json:"ttl"`
+}
+
+// recordACreateOpts specifies the attributes used to create a record A.
+type recordACreateOpts struct {
+ Name *string `json:"name" required:"true"`
+ IPv4 string `json:"ipv4" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordAAAA represents a public DNS zone record AAAA.
+type recordAAAA struct {
+ UUID string `json:"uuid"`
+ DNS string `json:"dns"`
+ Name string `json:"name"`
+ IPv6 string `json:"ipv6"`
+ TTL int `json:"ttl"`
+}
+
+// recordAAAACreateOpts specifies the attributes used to create a record AAAA.
+type recordAAAACreateOpts struct {
+ Name *string `json:"name" required:"true"`
+ IPv6 string `json:"ipv6" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordCNAME represents a public DNS zone record CNAME.
+type recordCNAME struct {
+ UUID string `json:"uuid"`
+ DNS string `json:"dns"`
+ Name string `json:"name"`
+ Content string `json:"content"`
+ TTL int `json:"ttl"`
+}
+
+// recordCNAMECreateOpts specifies the attributes used to create a record CNAME.
+type recordCNAMECreateOpts struct {
+ Name string `json:"name" required:"true"`
+ Content string `json:"content" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordMX represents a public DNS zone record MX.
+type recordMX struct {
+ UUID string `json:"uuid"`
+ DNS string `json:"dns"`
+ Name string `json:"name"`
+ Priority int `json:"priority"`
+ Content string `json:"content"`
+ TTL int `json:"ttl"`
+}
+
+// recordMXCreateOpts specifies the attributes used to create a record MX.
+type recordMXCreateOpts struct {
+ Name string `json:"name"`
+ Priority int `json:"priority" required:"true"`
+ Content string `json:"content" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordNS represents a public DNS zone record NS.
+type recordNS struct {
+ UUID string `json:"uuid"`
+ DNS string `json:"dns"`
+ Name string `json:"name"`
+ Content string `json:"content"`
+ TTL int `json:"ttl"`
+}
+
+// recordNSCreateOpts specifies the attributes used to create a record NS.
+type recordNSCreateOpts struct {
+ Name string `json:"name"`
+ Content string `json:"content" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordSRV represents a public DNS zone record SRV.
+type recordSRV struct {
+ UUID string `json:"uuid"`
+ DNS string `json:"dns"`
+ Name string `json:"name"`
+ Priority int `json:"priority"`
+ Weight int `json:"weight"`
+ Host string `json:"host"`
+ Port int `json:"port"`
+ TTL int `json:"ttl"`
+}
+
+// recordSRVCreateOpts specifies the attributes used to create a record SRV.
+type recordSRVCreateOpts struct {
+ Name string `json:"name"`
+ Priority int `json:"priority" required:"true"`
+ Weight int `json:"weight" required:"true"`
+ Host string `json:"host" required:"true"`
+ Port int `json:"port" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordTXT represents a public DNS zone record TXT.
+type recordTXT struct {
+ UUID string `json:"uuid"`
+ DNS string `json:"dns"`
+ Name string `json:"name"`
+ Content string `json:"content"`
+ TTL int `json:"ttl"`
+}
+
+// recordTXTCreateOpts specifies the attributes used to create a record TXT.
+type recordTXTCreateOpts struct {
+ Name string `json:"name"`
+ Content string `json:"content" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// Map formats a recordACreateOpts structure into a request body.
+func (opts recordACreateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordAAAACreateOpts structure into a request body.
+func (opts recordAAAACreateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordCNAMECreateOpts structure into a request body.
+func (opts recordCNAMECreateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordMXCreateOpts structure into a request body.
+func (opts recordMXCreateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordNSCreateOpts structure into a request body.
+func (opts recordNSCreateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordSRVCreateOpts structure into a request body.
+func (opts recordSRVCreateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordTXTCreateOpts structure into a request body.
+func (opts recordTXTCreateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// recordCreate implements a record create request.
+func recordCreate(client publicDNSClient, zoneID string, opts optsBuilder, recordType string) (r recordCreateResult) {
+ r.Type = recordType
+ b, err := opts.Map()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ reqOpts := getRequestOpts(201)
+ resp, err := client.Post(recordsURL(client, zonesAPIPath, zoneID, recordType), &b, &r.Body, reqOpts)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+// recordGet returns information about a record, given zone ID, its ID, and recordType.
+func recordGet(client publicDNSClient, zoneID string, id string, recordType string) (r recordGetResult) {
+ r.Type = recordType
+ url := recordURL(client, zonesAPIPath, zoneID, recordType, id)
+ resp, err := client.Get(url, &r.Body, nil)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+// recordAUpdateOpts specifies the attributes used to update a record A.
+type recordAUpdateOpts struct {
+ Name string `json:"name" required:"true"`
+ IPv4 string `json:"ipv4" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordAAAAUpdateOpts specifies the attributes used to update a record AAAA.
+type recordAAAAUpdateOpts struct {
+ Name string `json:"name" required:"true"`
+ IPv6 string `json:"ipv6" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordCNAMEUpdateOpts specifies the attributes used to update a record CNAME.
+type recordCNAMEUpdateOpts struct {
+ Name string `json:"name" required:"true"`
+ Content string `json:"content" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordMXUpdateOpts specifies the attributes used to update a record MX.
+type recordMXUpdateOpts struct {
+ Name string `json:"name" required:"true"`
+ Priority int `json:"priority" required:"true"`
+ Content string `json:"content" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordNSUpdateOpts specifies the attributes used to update a record NS.
+type recordNSUpdateOpts struct {
+ Name string `json:"name" required:"true"`
+ Content string `json:"content" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordSRVUpdateOpts specifies the attributes used to update a record SRV.
+type recordSRVUpdateOpts struct {
+ Name string `json:"name" required:"true"`
+ Priority int `json:"priority" required:"true"`
+ Weight int `json:"weight" required:"true"`
+ Host string `json:"host" required:"true"`
+ Port int `json:"port" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// recordTXTUpdateOpts specifies the attributes used to update a record TXT.
+type recordTXTUpdateOpts struct {
+ Name string `json:"name" required:"true"`
+ Content string `json:"content" required:"true"`
+ TTL int `json:"ttl,omitempty"`
+}
+
+// Map formats a recordAUpdateOpts structure into a request body.
+func (opts recordAUpdateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordAAAAUpdateOpts structure into a request body.
+func (opts recordAAAAUpdateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordCNAMEUpdateOpts structure into a request body.
+func (opts recordCNAMEUpdateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordMXUpdateOpts structure into a request body.
+func (opts recordMXUpdateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordNSUpdateOpts structure into a request body.
+func (opts recordNSUpdateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordSRVUpdateOpts structure into a request body.
+func (opts recordSRVUpdateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// Map formats a recordTXTUpdateOpts structure into a request body.
+func (opts recordTXTUpdateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// recordUpdate implements a record update request.
+func recordUpdate(client publicDNSClient, zoneID string, id string, opts optsBuilder, recordType string) (r recordUpdateResult) {
+ r.Type = recordType
+ b, err := opts.Map()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ reqOpts := getRequestOpts(200)
+ resp, err := client.Put(recordURL(client, zonesAPIPath, zoneID, recordType, id), &b, &r.Body, reqOpts)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+// Delete implements a record delete request.
+func recordDelete(client *gophercloud.ServiceClient, zoneID string, id string, recordType string) (r recordDeleteResult) {
+ resp, err := client.Delete(recordURL(client, zonesAPIPath, zoneID, recordType, id), &gophercloud.RequestOpts{
+ OkCodes: []int{204},
+ JSONResponse: &r.Body,
+ })
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
diff --git a/vkcs/publicdns_zone.go b/vkcs/publicdns_zone.go
new file mode 100644
index 00000000..3dca9bae
--- /dev/null
+++ b/vkcs/publicdns_zone.go
@@ -0,0 +1,20 @@
+package vkcs
+
+import (
+ "github.com/gophercloud/gophercloud"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func publicDNSZoneStateRefreshFunc(client publicDNSClient, zoneID string) resource.StateRefreshFunc {
+ return func() (interface{}, string, error) {
+ zone, err := zoneGet(client, zoneID).Extract()
+
+ if err != nil {
+ if _, ok := err.(gophercloud.ErrDefault404); ok {
+ return zone, zoneStatusDeleted, nil
+ }
+ return nil, "", err
+ }
+ return zone, zone.Status, nil
+ }
+}
diff --git a/vkcs/publicdns_zone_client.go b/vkcs/publicdns_zone_client.go
new file mode 100644
index 00000000..5157852a
--- /dev/null
+++ b/vkcs/publicdns_zone_client.go
@@ -0,0 +1,209 @@
+package vkcs
+
+import (
+ "net/http"
+
+ "github.com/gophercloud/gophercloud"
+)
+
+type publicDNSClient interface {
+ Get(url string, JSONResponse interface{}, opts *gophercloud.RequestOpts) (*http.Response, error)
+ Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *gophercloud.RequestOpts) (*http.Response, error)
+ Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *gophercloud.RequestOpts) (*http.Response, error)
+ Delete(url string, opts *gophercloud.RequestOpts) (*http.Response, error)
+ Head(url string, opts *gophercloud.RequestOpts) (*http.Response, error)
+ Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *gophercloud.RequestOpts) (*http.Response, error)
+ ServiceURL(parts ...string) string
+}
+
+type commonZoneResult struct {
+ gophercloud.Result
+}
+
+// Extract interprets a zoneGetResult, zoneCreateResult or zoneUpdateResult as a zone.
+// An error is returned if the original call or the extraction failed.
+func (r commonZoneResult) Extract() (*zone, error) {
+ var s *zone
+ err := r.ExtractInto(&s)
+ return s, err
+}
+
+// zoneCreateResult is the result of a zoneCreate request. Call its Extract method
+// to interpret the result as a zone.
+type zoneCreateResult struct {
+ commonZoneResult
+}
+
+// zoneGetResult is the result of a zoneGet request. Call its Extract method
+// to interpret the result as a zone.
+type zoneGetResult struct {
+ commonZoneResult
+}
+
+// zoneListResult is the result of a zoneList request. Call its Extract method
+// to interpret the result as a slice of zones.
+type zoneListResult struct {
+ commonZoneResult
+}
+
+// Extract extracts a slice of zones from a zoneListResult.
+func (r zoneListResult) Extract() ([]zone, error) {
+ var zones []zone
+ err := r.ExtractInto(&zones)
+ return zones, err
+}
+
+// zoneUpdateResult is the result of a zoneUpdate request. Call its Extract method
+// to interpret the result as a zone.
+type zoneUpdateResult struct {
+ commonZoneResult
+}
+
+// zoneDeleteResult is the result of a zoneDelete request. Call its ExtractErr method
+// to determine if the request succeeded or failed.
+type zoneDeleteResult struct {
+ gophercloud.ErrResult
+}
+
+// zone represents a public DNS zone.
+type zone struct {
+ ID string `json:"uuid"`
+ Zone string `json:"zone"`
+ PrimaryDNS string `json:"soa_primary_dns"`
+ AdminEmail string `json:"soa_admin_email"`
+ Serial int `json:"soa_serial"`
+ Refresh int `json:"soa_refresh"`
+ Retry int `json:"soa_retry"`
+ Expire int `json:"soa_expire"`
+ TTL int `json:"soa_ttl"`
+ Status string `json:"status"`
+}
+
+var zonesAPIPath = "dns"
+
+// zoneCreateOpts specifies the attributes used to create a zone.
+type zoneCreateOpts struct {
+ Zone string `json:"zone" required:"true"`
+ PrimaryDNS string `json:"soa_primary_dns,omitempty"`
+ AdminEmail string `json:"soa_admin_email,omitempty"`
+ Refresh int `json:"soa_refresh,omitempty"`
+ Retry int `json:"soa_retry,omitempty"`
+ Expire int `json:"soa_expire,omitempty"`
+ TTL int `json:"soa_ttl,omitempty"`
+}
+
+// Map formats a zoneCreateOpts structure into a request body.
+func (opts zoneCreateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// zoneCreate implements a zone create request.
+func zoneCreate(client publicDNSClient, opts optsBuilder) (r zoneCreateResult) {
+ b, err := opts.Map()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ reqOpts := getRequestOpts(201)
+ resp, err := client.Post(zonesURL(client, zonesAPIPath), &b, &r.Body, reqOpts)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+// zoneGet returns information about a zone, given its ID.
+func zoneGet(client publicDNSClient, id string) (r zoneGetResult) {
+ resp, err := client.Get(getURL(client, zonesAPIPath, id), &r.Body, nil)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+// listOptsBuilder allows extensions to add additional parameters to the
+// list request.
+type listOptsBuilder interface {
+ ToListQuery() (string, error)
+}
+
+// listOpts allows the filtering and sorting of paginated collections through
+// the API. Filtering is achieved by passing in struct field values that map to
+// the server attributes you want to see returned. Marker and Limit are used
+// for pagination.
+type zoneListOpts struct {
+ // Integer value for the limit of values to return.
+ Limit int `q:"limit"`
+
+ // UUID of the zone at which you want to set a marker.
+ Marker string `q:"marker"`
+
+ ID string `q:"uuid"`
+ Zone string `q:"zone"`
+ PrimaryDNS string `q:"soa_primary_dns"`
+ AdminEmail string `q:"soa_admin_email"`
+ Serial int `q:"soa_serial"`
+ Refresh int `q:"soa_refresh"`
+ Retry int `q:"soa_retry"`
+ Expire int `q:"soa_expire"`
+ TTL int `q:"soa_ttl"`
+ Status string `q:"status"`
+}
+
+// ToListQuery formats a listOpts structure into a query string.
+func (opts zoneListOpts) ToListQuery() (string, error) {
+ q, err := gophercloud.BuildQueryString(opts)
+ return q.String(), err
+}
+
+// zoneList implements a zone list request.
+func zoneList(client *gophercloud.ServiceClient, opts listOptsBuilder) (r zoneListResult) {
+ url := zonesURL(client, zonesAPIPath)
+ if opts != nil {
+ query, err := opts.ToListQuery()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ url += query
+ }
+ resp, err := client.Get(url, &r.Body, nil)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+// zoneUpdateOpts specifies the attributes to update a zone.
+type zoneUpdateOpts struct {
+ PrimaryDNS string `json:"soa_primary_dns,omitempty"`
+ AdminEmail string `json:"soa_admin_email,omitempty"`
+ Refresh int `json:"soa_refresh,omitempty"`
+ Retry int `json:"soa_retry,omitempty"`
+ Expire int `json:"soa_expire,omitempty"`
+ TTL int `json:"soa_ttl,omitempty"`
+}
+
+// Map formats a zoneUpdateOpts structure into a request body.
+func (opts zoneUpdateOpts) Map() (map[string]interface{}, error) {
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ return b, err
+}
+
+// zoneUpdate implements a zone update request.
+func zoneUpdate(client publicDNSClient, id string, opts optsBuilder) (r zoneUpdateResult) {
+ b, err := opts.Map()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ reqOpts := getRequestOpts(200)
+ resp, err := client.Put(getURL(client, zonesAPIPath, id), &b, &r.Body, reqOpts)
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
+
+// zoneDelete implements a zone delete request.
+func zoneDelete(client *gophercloud.ServiceClient, id string) (r zoneDeleteResult) {
+ resp, err := client.Delete(getURL(client, zonesAPIPath, id), &gophercloud.RequestOpts{
+ OkCodes: []int{204},
+ JSONResponse: &r.Body,
+ })
+ _, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
+ return
+}
diff --git a/vkcs/resource_vkcs_blockstorage_volume.go b/vkcs/resource_vkcs_blockstorage_volume.go
index 2c5a1671..a9c76ef5 100644
--- a/vkcs/resource_vkcs_blockstorage_volume.go
+++ b/vkcs/resource_vkcs_blockstorage_volume.go
@@ -22,6 +22,7 @@ var (
bsVolumeStatusBuild = "creating"
bsVolumeStatusActive = "available"
bsVolumeStatusInUse = "in-use"
+ bsVolumeStatusRetype = "retyping"
bsVolumeStatusShutdown = "deleting"
bsVolumeStatusDeleted = "deleted"
bsVolumeStatusDownloading = "downloading"
@@ -263,7 +264,7 @@ func resourceBlockStorageVolumeUpdate(ctx context.Context, d *schema.ResourceDat
return diag.Errorf("error changing type of vkcs_blockstorage_volume %s", d.Id())
}
stateConf := &resource.StateChangeConf{
- Pending: []string{bsVolumeStatusBuild},
+ Pending: []string{bsVolumeStatusBuild, bsVolumeStatusRetype},
Target: []string{bsVolumeStatusActive, bsVolumeStatusInUse},
Refresh: blockStorageVolumeStateRefreshFunc(blockStorageClient, d.Id()),
Timeout: d.Timeout(schema.TimeoutCreate),
diff --git a/vkcs/resource_vkcs_blockstorage_volume_test.go b/vkcs/resource_vkcs_blockstorage_volume_test.go
index f8cac292..f9b4251b 100644
--- a/vkcs/resource_vkcs_blockstorage_volume_test.go
+++ b/vkcs/resource_vkcs_blockstorage_volume_test.go
@@ -68,6 +68,30 @@ func TestAccBlockStorageVolume_online_resize(t *testing.T) {
})
}
+func TestAccBlockStorageVolume_retype(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckBlockStorageVolumeDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfig(testAccBlockStorageVolumeRetype),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(
+ "vkcs_blockstorage_volume.volume_1", "volume_type", "ceph-hdd"),
+ ),
+ },
+ {
+ Config: testAccRenderConfig(testAccBlockStorageVolumeRetypeUpdate),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(
+ "vkcs_blockstorage_volume.volume_1", "volume_type", "ceph-ssd"),
+ ),
+ },
+ },
+ })
+}
+
func TestAccBlockStorageVolume_image(t *testing.T) {
var volume volumes.Volume
@@ -224,6 +248,32 @@ resource "vkcs_compute_volume_attach" "va_1" {
}
`
+const testAccBlockStorageVolumeRetype = `
+resource "vkcs_blockstorage_volume" "volume_1" {
+ name = "volume_1"
+ description = "first test volume"
+ metadata = {
+ foo = "bar"
+ }
+ size = 1
+ availability_zone = "{{.AvailabilityZone}}"
+ volume_type = "ceph-hdd"
+}
+`
+
+const testAccBlockStorageVolumeRetypeUpdate = `
+resource "vkcs_blockstorage_volume" "volume_1" {
+ name = "volume_1"
+ description = "first test volume"
+ metadata = {
+ foo = "bar"
+ }
+ size = 1
+ availability_zone = "{{.AvailabilityZone}}"
+ volume_type = "ceph-ssd"
+}
+`
+
const testAccBlockStorageVolumeUpdate = `
resource "vkcs_blockstorage_volume" "volume_1" {
name = "volume_1-updated"
diff --git a/vkcs/resource_vkcs_compute_floatingip_associate.go b/vkcs/resource_vkcs_compute_floatingip_associate.go
index 66cbe5c1..64c89c6e 100644
--- a/vkcs/resource_vkcs_compute_floatingip_associate.go
+++ b/vkcs/resource_vkcs_compute_floatingip_associate.go
@@ -141,7 +141,7 @@ func resourceComputeFloatingIPAssociateRead(_ context.Context, d *schema.Resourc
// Now check and see whether the floating IP still exists.
// First try to do this by querying the Network API.
networkEnabled := true
- networkClient, err := config.NetworkingV2Client(getRegion(d, config), getSDN(d))
+ networkClient, err := config.NetworkingV2Client(getRegion(d, config), searchInAllSDNs)
if err != nil {
networkEnabled = false
}
diff --git a/vkcs/resource_vkcs_compute_floatingip_associate_test.go b/vkcs/resource_vkcs_compute_floatingip_associate_test.go
index 97b31ea6..1914d807 100644
--- a/vkcs/resource_vkcs_compute_floatingip_associate_test.go
+++ b/vkcs/resource_vkcs_compute_floatingip_associate_test.go
@@ -194,7 +194,7 @@ const testAccComputeFloatingIPAssociateBasic = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = [vkcs_networking_subnet.base]
+ depends_on = [vkcs_networking_router_interface.base]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -221,7 +221,7 @@ const testAccComputeFloatingIPAssociateUpdate = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
security_groups = ["default"]
network {
@@ -248,7 +248,7 @@ const testAccComputeFloatingIPAssociateFixedIP = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
security_groups = ["default"]
network {
@@ -275,7 +275,7 @@ const testAccComputeFloatingIPAssociateAttachNew1 = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
security_groups = ["default"]
network {
@@ -305,7 +305,7 @@ const testAccComputeFloatingIPAssociateAttachNew2 = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
security_groups = ["default"]
network {
@@ -335,7 +335,7 @@ const testAccComputeFloatingIPAssociateWaitUntilAssociated = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
security_groups = ["default"]
network {
diff --git a/vkcs/resource_vkcs_compute_instance.go b/vkcs/resource_vkcs_compute_instance.go
index de985f76..2a6a1e49 100755
--- a/vkcs/resource_vkcs_compute_instance.go
+++ b/vkcs/resource_vkcs_compute_instance.go
@@ -389,7 +389,8 @@ func resourceComputeInstance() *schema.Resource {
Description: "Map of additional vendor-specific options. Supported options are described below.",
},
},
- Description: "Manages a compute VM instance resource.\n\n~> **Note:** All arguments including the instance admin password will be stored in the raw state as plain-text. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
+ Description: "Manages a compute VM instance resource.\n\n" +
+ "~> **Note:** All arguments including the instance admin password will be stored in the raw state as plain-text. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
}
}
diff --git a/vkcs/resource_vkcs_compute_instance_test.go b/vkcs/resource_vkcs_compute_instance_test.go
index 8f8170b7..2be2c13e 100755
--- a/vkcs/resource_vkcs_compute_instance_test.go
+++ b/vkcs/resource_vkcs_compute_instance_test.go
@@ -810,7 +810,7 @@ const testAccComputeInstanceBasic = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -831,7 +831,7 @@ const testAccComputeInstanceBootFromVolumeImage = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -864,7 +864,7 @@ resource "vkcs_blockstorage_volume" "vol_1" {
}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -888,7 +888,7 @@ const testAccComputeInstanceBootFromVolumeForceNew1 = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -913,7 +913,7 @@ const testAccComputeInstanceBootFromVolumeForceNew2 = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -938,7 +938,7 @@ const testAccComputeInstanceBlockDeviceNewVolume = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -970,7 +970,7 @@ const testAccComputeInstanceBlockDeviceNewVolumeTypeAndBus = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1012,7 +1012,7 @@ resource "vkcs_blockstorage_volume" "volume_1" {
}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1044,7 +1044,7 @@ const testAccComputeInstancePersonality = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1108,7 +1108,7 @@ const testAccComputeInstanceChangeFixedIP1 = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1127,7 +1127,7 @@ const testAccComputeInstanceChangeFixedIP2 = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1146,7 +1146,7 @@ const testAccComputeInstanceStopBeforeDestroy = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1165,7 +1165,7 @@ const testAccComputeInstanceMetadataRemove1 = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1187,7 +1187,7 @@ const testAccComputeInstanceMetadataRemove2 = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1209,7 +1209,7 @@ const testAccComputeInstanceForceDelete = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1228,7 +1228,7 @@ const testAccComputeInstanceTimeout = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1276,7 +1276,7 @@ resource "vkcs_networking_subnet" "subnet_1" {
}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base", "vkcs_networking_subnet.subnet_1"]
+ depends_on = ["vkcs_networking_router_interface.base", "vkcs_networking_subnet.subnet_1"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
@@ -1370,7 +1370,7 @@ resource "vkcs_networking_port" "port_4" {
resource "vkcs_compute_instance" "instance_1" {
depends_on = [
- "vkcs_networking_subnet.base",
+ "vkcs_networking_router_interface.base",
"vkcs_networking_subnet.subnet_1",
"vkcs_networking_subnet.subnet_2",
"vkcs_networking_port.port_1",
@@ -1432,7 +1432,7 @@ const testAccComputeInstanceStateActive = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = [vkcs_networking_subnet.base]
+ depends_on = [vkcs_networking_router_interface.base]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1451,7 +1451,7 @@ const testAccComputeInstanceStateShutoff = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1470,7 +1470,7 @@ const testAccComputeInstanceStateShelve = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1489,7 +1489,7 @@ const testAccComputeInstanceTagsCreate = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1507,7 +1507,7 @@ const testAccComputeInstanceTagsAdd = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1526,7 +1526,7 @@ const testAccComputeInstanceTagsDelete = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -1545,7 +1545,7 @@ const testAccComputeInstanceTagsClear = `
{{.BaseFlavor}}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
diff --git a/vkcs/resource_vkcs_compute_interface_attach.go b/vkcs/resource_vkcs_compute_interface_attach.go
index d255cf1a..67992451 100644
--- a/vkcs/resource_vkcs_compute_interface_attach.go
+++ b/vkcs/resource_vkcs_compute_interface_attach.go
@@ -42,7 +42,8 @@ func resourceComputeInterfaceAttach() *schema.Resource {
Computed: true,
ForceNew: true,
ConflictsWith: []string{"network_id"},
- Description: "The ID of the Port to attach to an Instance.\n_NOTE_: This option and `network_id` are mutually exclusive.",
+ Description: "The ID of the Port to attach to an Instance.\n" +
+ "_NOTE_: This option and `network_id` are mutually exclusive.",
},
"network_id": {
@@ -51,7 +52,8 @@ func resourceComputeInterfaceAttach() *schema.Resource {
Computed: true,
ForceNew: true,
ConflictsWith: []string{"port_id"},
- Description: "The ID of the Network to attach to an Instance. A port will be created automatically.\n_NOTE_: This option and `port_id` are mutually exclusive.",
+ Description: "The ID of the Network to attach to an Instance. A port will be created automatically.\n" +
+ "_NOTE_: This option and `port_id` are mutually exclusive.",
},
"instance_id": {
@@ -67,7 +69,8 @@ func resourceComputeInterfaceAttach() *schema.Resource {
Computed: true,
ForceNew: true,
ConflictsWith: []string{"port_id"},
- Description: "An IP address to assosciate with the port.\n_NOTE_: This option cannot be used with port_id. You must specify a network_id. The IP address must lie in a range on the supplied network.",
+ Description: "An IP address to assosciate with the port.\n" +
+ "_NOTE_: This option cannot be used with port_id. You must specify a network_id. The IP address must lie in a range on the supplied network.",
},
},
Description: "Attaches a Network Interface (a Port) to an Instance using the VKCS Compute API.",
diff --git a/vkcs/resource_vkcs_compute_interface_attach_test.go b/vkcs/resource_vkcs_compute_interface_attach_test.go
index a64fd79e..0c8e9edb 100644
--- a/vkcs/resource_vkcs_compute_interface_attach_test.go
+++ b/vkcs/resource_vkcs_compute_interface_attach_test.go
@@ -134,7 +134,7 @@ resource "vkcs_networking_port" "port_1" {
}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -169,7 +169,7 @@ resource "vkcs_networking_subnet" "subnet_1" {
}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
diff --git a/vkcs/resource_vkcs_compute_keypair.go b/vkcs/resource_vkcs_compute_keypair.go
index a6504a4f..082e2dfc 100644
--- a/vkcs/resource_vkcs_compute_keypair.go
+++ b/vkcs/resource_vkcs_compute_keypair.go
@@ -63,7 +63,8 @@ func resourceComputeKeypair() *schema.Resource {
Description: "The fingerprint of the public key.",
},
},
- Description: "Manages a keypair resource within VKCS.\n\n~> **Important Security Notice** The private key generated by this resource will be stored *unencrypted* in your Terraform state file. **Use of this resource for production deployments is *not* recommended**. Instead, generate a private key file outside of Terraform and distribute it securely to the system where Terraform will be run.",
+ Description: "Manages a keypair resource within VKCS.\n\n" +
+ "~> **Important Security Notice** The private key generated by this resource will be stored *unencrypted* in your Terraform state file. **Use of this resource for production deployments is *not* recommended**. Instead, generate a private key file outside of Terraform and distribute it securely to the system where Terraform will be run.",
}
}
diff --git a/vkcs/resource_vkcs_compute_servergroup_test.go b/vkcs/resource_vkcs_compute_servergroup_test.go
index 946d5ad2..755b835c 100644
--- a/vkcs/resource_vkcs_compute_servergroup_test.go
+++ b/vkcs/resource_vkcs_compute_servergroup_test.go
@@ -168,7 +168,7 @@ resource "vkcs_compute_servergroup" "sg_1" {
}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
@@ -194,7 +194,7 @@ resource "vkcs_compute_servergroup" "sg_1" {
}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
diff --git a/vkcs/resource_vkcs_compute_volume_attach_test.go b/vkcs/resource_vkcs_compute_volume_attach_test.go
index be09812f..46a1b9e1 100644
--- a/vkcs/resource_vkcs_compute_volume_attach_test.go
+++ b/vkcs/resource_vkcs_compute_volume_attach_test.go
@@ -103,7 +103,7 @@ resource "vkcs_blockstorage_volume" "volume_1" {
}
resource "vkcs_compute_instance" "instance_1" {
- depends_on = ["vkcs_networking_subnet.base"]
+ depends_on = ["vkcs_networking_router_interface.base"]
name = "instance_1"
availability_zone = "{{.AvailabilityZone}}"
security_groups = ["default"]
diff --git a/vkcs/resource_vkcs_db_backup.go b/vkcs/resource_vkcs_db_backup.go
index 6e92fbda..44abdda6 100644
--- a/vkcs/resource_vkcs_db_backup.go
+++ b/vkcs/resource_vkcs_db_backup.go
@@ -131,7 +131,8 @@ func resourceDatabaseBackup() *schema.Resource {
Description: "Metadata of the backup",
},
},
- Description: "Provides a db backup resource. This can be used to create and delete db backup.\n**New since v.0.1.4**.",
+ Description: "Provides a db backup resource. This can be used to create and delete db backup.\n" +
+ "**New since v.0.1.4**.",
}
}
diff --git a/vkcs/resource_vkcs_db_cluster.go b/vkcs/resource_vkcs_db_cluster.go
index 1a56090c..68a24867 100755
--- a/vkcs/resource_vkcs_db_cluster.go
+++ b/vkcs/resource_vkcs_db_cluster.go
@@ -2,9 +2,12 @@ package vkcs
import (
"context"
+ "errors"
"fmt"
"log"
+ "strings"
+ "github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -26,12 +29,17 @@ var (
dbClusterStatusBackup dbClusterStatus = "BACKUP"
)
+const (
+ dbClusterInstanceRoleLeader string = "leader"
+)
+
func resourceDatabaseCluster() *schema.Resource {
return &schema.Resource{
CreateContext: resourceDatabaseClusterCreate,
ReadContext: resourceDatabaseClusterRead,
DeleteContext: resourceDatabaseClusterDelete,
UpdateContext: resourceDatabaseClusterUpdate,
+ CustomizeDiff: resourceDatabaseCustomizeDiff,
Importer: &schema.ResourceImporter{
StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(configer)
@@ -159,6 +167,12 @@ func resourceDatabaseCluster() *schema.Resource {
Description: "Object that represents datastore of the cluster. Changing this creates a new cluster.",
},
+ "loadbalancer_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The id of the loadbalancer attached to the cluster. **New since v.0.1.15**.",
+ },
+
"network": {
Type: schema.TypeList,
Optional: true,
@@ -166,16 +180,32 @@ func resourceDatabaseCluster() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"uuid": {
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Description: "The id of the network. Changing this creates a new cluster." +
+ "**Note** Although this argument is marked as optional, it is actually required at the moment. Not setting a value for it may cause an error.",
+ },
+ "port": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
- Description: "The id of the network. Changing this creates a new cluster.",
+ Description: "The port id of the network. Changing this creates a new cluster. ***Deprecated*** This argument is deprecated, please do not use it.",
+ Deprecated: "This argument is deprecated, please do not use it.",
},
- "port": {
+ "subnet_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
- Description: "The port id of the network. Changing this creates a new cluster.",
+ Description: "The id of the subnet. Changing this creates a new cluster. **New since v.0.1.15**.",
+ },
+ "security_groups": {
+ Type: schema.TypeSet,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Set: schema.HashString,
+ Description: "An array of one or more security group IDs to associate with the cluster instances. Changing this creates a new cluster. **New since v.0.2.0**.",
},
},
},
@@ -359,6 +389,52 @@ func resourceDatabaseCluster() *schema.Resource {
},
Description: "Object that represents configuration of PITR backup. This functionality is available only for postgres datastore. **New since v.0.1.4**",
},
+
+ "shrink_options": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: "Used only for shrinking cluster. List of IDs of instances that should remain after shrink. If no options are supplied, shrink operation will choose first non-leader instance to delete.",
+ DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
+ return true
+ },
+ },
+
+ "cloud_monitoring_enabled": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ForceNew: false,
+ Description: "Enable cloud monitoring for the cluster. Changing this for Redis or MongoDB creates a new instance. **New since v.0.2.0**",
+ },
+
+ // Computed values
+ "instances": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "instance_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The id of the instance.",
+ },
+ "ip": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ Description: "IP address of the instance.",
+ },
+ "role": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The role of the instance in cluster.",
+ },
+ },
+ },
+ Description: "Cluster instances info.",
+ },
},
Description: "Provides a db cluster resource. This can be used to create, modify and delete db cluster for galera_mysql, postgresql, tarantool datastores.",
}
@@ -372,8 +448,9 @@ func resourceDatabaseClusterCreate(ctx context.Context, d *schema.ResourceData,
}
createOpts := &dbClusterCreateOpts{
- Name: d.Get("name").(string),
- FloatingIPEnabled: d.Get("floating_ip_enabled").(bool),
+ Name: d.Get("name").(string),
+ FloatingIPEnabled: d.Get("floating_ip_enabled").(bool),
+ CloudMonitoringEnabled: d.Get("cloud_monitoring_enabled").(bool),
}
message := "unable to determine vkcs_db_cluster"
@@ -431,7 +508,7 @@ func resourceDatabaseClusterCreate(ctx context.Context, d *schema.ResourceData,
}
if v, ok := d.GetOk("network"); ok {
- createDBInstanceOpts.Nics, err = extractDatabaseNetworks(v.([]interface{}))
+ createDBInstanceOpts.Nics, createDBInstanceOpts.SecurityGroups, err = extractDatabaseNetworks(v.([]interface{}))
if err != nil {
return diag.Errorf("%s network", message)
}
@@ -535,6 +612,7 @@ func resourceDatabaseClusterRead(ctx context.Context, d *schema.ResourceData, me
d.Set("flavor_id", cluster.Instances[0].Flavor.ID)
d.Set("cluster_size", len(cluster.Instances))
d.Set("volume_size", cluster.Instances[0].Volume.Size)
+ d.Set("loadbalancer_id", cluster.LoadbalancerID)
d.Set("configuration_id", cluster.ConfigurationID)
if _, ok := d.GetOk("disk_autoexpand"); ok {
@@ -554,6 +632,8 @@ func resourceDatabaseClusterRead(ctx context.Context, d *schema.ResourceData, me
}
}
+ d.Set("instances", flattenDatabaseClusterInstances(cluster.Instances))
+
backupSchedule, err := dbClusterGetBackupSchedule(DatabaseV1Client, d.Id()).extract()
if err != nil {
return diag.Errorf("error getting backup schedule for cluster: %s: %s", d.Id(), err)
@@ -565,275 +645,98 @@ func resourceDatabaseClusterRead(ctx context.Context, d *schema.ResourceData, me
d.Set("backup_schedule", nil)
}
- return nil
+ if !d.HasChangesExcept() {
+ return nil
+ }
+
+ var diags diag.Diagnostics
+
+ rawNetworks := d.Get("network").([]interface{})
+ diags = checkDBNetworks(rawNetworks, cty.Path{}, diags)
+ return diags
}
func resourceDatabaseClusterUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
config := meta.(configer)
- DatabaseV1Client, err := config.DatabaseV1Client(getRegion(d, config))
+ dbClient, err := config.DatabaseV1Client(getRegion(d, config))
if err != nil {
return diag.Errorf("Error creating VKCS database client: %s", err)
}
+ clusterID := d.Id()
stateConf := &resource.StateChangeConf{
Pending: []string{string(dbClusterStatusBuild)},
Target: []string{string(dbClusterStatusActive)},
- Refresh: databaseClusterStateRefreshFunc(DatabaseV1Client, d.Id(), nil),
+ Refresh: databaseClusterStateRefreshFunc(dbClient, d.Id(), nil),
Timeout: d.Timeout(schema.TimeoutCreate),
Delay: dbInstanceDelay,
MinTimeout: dbInstanceMinTimeout,
}
+ updateCtx := &dbResourceUpdateContext{
+ Ctx: ctx,
+ Client: dbClient,
+ D: d,
+ StateConf: stateConf,
+ }
if d.HasChange("configuration_id") {
- old, new := d.GetChange("configuration_id")
-
- var detachConfigurationOpts dbClusterDetachConfigurationGroupOpts
- detachConfigurationOpts.ConfigurationDetach.ConfigurationID = old.(string)
- err := dbClusterAction(DatabaseV1Client, d.Id(), &detachConfigurationOpts).ExtractErr()
+ err = databaseClusterActionUpdateConfiguration(updateCtx)
if err != nil {
- return diag.FromErr(err)
- }
- log.Printf("Detaching configuration %s from vkcs_db_cluster %s", old, d.Id())
-
- _, err = stateConf.WaitForStateContext(ctx)
- if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
- }
-
- if new != "" {
- var attachConfigurationOpts dbClusterAttachConfigurationGroupOpts
- attachConfigurationOpts.ConfigurationAttach.ConfigurationID = new.(string)
- err := dbClusterAction(DatabaseV1Client, d.Id(), &attachConfigurationOpts).ExtractErr()
- if err != nil {
- return diag.FromErr(err)
- }
- log.Printf("Attaching configuration %s to vkcs_db_cluster %s", new, d.Id())
-
- _, err = stateConf.WaitForStateContext(ctx)
- if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
- }
+ return databaseClusterUpdateProcessError(err, clusterID)
}
}
if d.HasChange("volume_size") {
- _, new := d.GetChange("volume_size")
- var resizeVolumeOpts dbClusterResizeVolumeOpts
- resizeVolumeOpts.Resize.Volume.Size = new.(int)
- err := dbClusterAction(DatabaseV1Client, d.Id(), &resizeVolumeOpts).ExtractErr()
- if err != nil {
- return diag.FromErr(err)
- }
- log.Printf("Resizing volume from vkcs_db_cluster %s", d.Id())
-
- stateConf.Pending = []string{string(dbClusterStatusResize)}
- stateConf.Target = []string{string(dbClusterStatusActive)}
-
- _, err = stateConf.WaitForStateContext(ctx)
+ err = databaseClusterActionResizeVolume(updateCtx, "")
if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
+ return databaseClusterUpdateProcessError(err, clusterID)
}
}
if d.HasChange("flavor_id") {
- var resizeOpts dbClusterResizeOpts
- resizeOpts.Resize.FlavorRef = d.Get("flavor_id").(string)
- err := dbClusterAction(DatabaseV1Client, d.Id(), &resizeOpts).ExtractErr()
- if err != nil {
- return diag.FromErr(err)
- }
- log.Printf("Resizing flavor from vkcs_db_cluster %s", d.Id())
-
- stateConf.Pending = []string{string(dbClusterStatusResize)}
- stateConf.Target = []string{string(dbClusterStatusActive)}
-
- _, err = stateConf.WaitForStateContext(ctx)
+ err = databaseClusterActionResizeFlavor(updateCtx, "")
if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
+ return databaseClusterUpdateProcessError(err, clusterID)
}
}
if d.HasChange("disk_autoexpand") {
- _, new := d.GetChange("disk_autoexpand")
- autoExpandProperties, err := extractDatabaseAutoExpand(new.([]interface{}))
+ err = databaseClusterUpdateDiskAutoexpand(updateCtx)
if err != nil {
- return diag.Errorf("unable to determine vkcs_db_cluster disk_autoexpand")
- }
- var autoExpandOpts dbClusterUpdateAutoExpandOpts
- if autoExpandProperties.AutoExpand {
- autoExpandOpts.Cluster.VolumeAutoresizeEnabled = 1
- } else {
- autoExpandOpts.Cluster.VolumeAutoresizeEnabled = 0
- }
- autoExpandOpts.Cluster.VolumeAutoresizeMaxSize = autoExpandProperties.MaxDiskSize
- err = dbClusterUpdateAutoExpand(DatabaseV1Client, d.Id(), &autoExpandOpts).ExtractErr()
- if err != nil {
- return diag.FromErr(err)
- }
-
- stateConf.Pending = []string{string(dbClusterStatusUpdating)}
- stateConf.Target = []string{string(dbClusterStatusActive)}
-
- _, err = stateConf.WaitForStateContext(ctx)
- if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
+ return databaseClusterUpdateProcessError(err, clusterID)
}
}
if d.HasChange("wal_volume") {
- old, new := d.GetChange("wal_volume")
- walVolumeOptsNew, err := extractDatabaseWalVolume(new.([]interface{}))
- if err != nil {
- return diag.Errorf("unable to determine vkcs_db_cluster wal_volume")
- }
-
- walVolumeOptsOld, err := extractDatabaseWalVolume(old.([]interface{}))
+ err = databaseClusterActionResizeWalVolume(updateCtx, "")
if err != nil {
- return diag.Errorf("unable to determine vkcs_db_cluster wal_volume")
+ return databaseClusterUpdateProcessError(err, clusterID)
}
-
- if walVolumeOptsNew.Size != walVolumeOptsOld.Size {
- var resizeWalVolumeOpts dbClusterResizeWalVolumeOpts
- resizeWalVolumeOpts.Resize.Volume.Size = walVolumeOptsNew.Size
- resizeWalVolumeOpts.Resize.Volume.Kind = "wal"
- err = dbClusterAction(DatabaseV1Client, d.Id(), &resizeWalVolumeOpts).ExtractErr()
- if err != nil {
- return diag.FromErr(err)
- }
-
- stateConf.Pending = []string{string(dbClusterStatusResize)}
- stateConf.Target = []string{string(dbClusterStatusActive)}
-
- _, err = stateConf.WaitForStateContext(ctx)
- if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
- }
- }
-
}
- if d.HasChange("wal_disk_autoexpand") {
- _, new := d.GetChange("wal_disk_autoexpand")
- walAutoExpandProperties, err := extractDatabaseAutoExpand(new.([]interface{}))
- if err != nil {
- return diag.Errorf("unable to determine vkcs_db_cluster wal_disk_autoexpand")
- }
- var walAutoExpandOpts dbClusterUpdateAutoExpandWalOpts
- if walAutoExpandProperties.AutoExpand {
- walAutoExpandOpts.Cluster.WalVolume.VolumeAutoresizeEnabled = 1
- } else {
- walAutoExpandOpts.Cluster.WalVolume.VolumeAutoresizeEnabled = 0
- }
- walAutoExpandOpts.Cluster.WalVolume.VolumeAutoresizeMaxSize = walAutoExpandProperties.MaxDiskSize
- err = dbClusterUpdateAutoExpand(DatabaseV1Client, d.Id(), &walAutoExpandOpts).ExtractErr()
- if err != nil {
- return diag.FromErr(err)
- }
- stateConf.Pending = []string{string(dbClusterStatusUpdating)}
- stateConf.Target = []string{string(dbClusterStatusActive)}
-
- _, err = stateConf.WaitForStateContext(ctx)
+ if d.HasChange("wal_disk_autoexpand") {
+ err = databaseClusterUpdateWalDiskAutoexpand(updateCtx)
if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
+ return databaseClusterUpdateProcessError(err, clusterID)
}
}
if d.HasChange("capabilities") {
- _, newCapabilities := d.GetChange("capabilities")
- newCapabilitiesOpts, err := extractDatabaseCapabilities(newCapabilities.([]interface{}))
- if err != nil {
- return diag.Errorf("unable to determine vkcs_db_cluster capability")
- }
- var applyCapabilityOpts dbClusterApplyCapabilityOpts
- applyCapabilityOpts.ApplyCapability.Capabilities = newCapabilitiesOpts
-
- err = dbClusterAction(DatabaseV1Client, d.Id(), &applyCapabilityOpts).ExtractErr()
-
- if err != nil {
- return diag.Errorf("error applying capability to vkcs_db_cluster %s: %s", d.Id(), err)
- }
-
- applyCapabilityClusterConf := &resource.StateChangeConf{
- Pending: []string{string(dbClusterStatusCapabilityApplying), string(dbClusterStatusBuild)},
- Target: []string{string(dbClusterStatusActive)},
- Refresh: databaseClusterStateRefreshFunc(DatabaseV1Client, d.Id(), &newCapabilitiesOpts),
- Timeout: d.Timeout(schema.TimeoutCreate),
- Delay: dbInstanceDelay,
- MinTimeout: dbInstanceMinTimeout,
- }
- log.Printf("[DEBUG] Waiting for cluster to become ready after applying capability")
- _, err = applyCapabilityClusterConf.WaitForStateContext(ctx)
+ err = databaseClusterActionApplyCapabilities(updateCtx)
if err != nil {
- return diag.Errorf("error applying capability to vkcs_db_cluster %s: %s", d.Id(), err)
+ return databaseClusterUpdateProcessError(err, clusterID)
}
}
if d.HasChange("cluster_size") {
old, new := d.GetChange("cluster_size")
- if new.(int) > old.(int) {
- opts := make([]dbClusterGrowOpts, new.(int)-old.(int))
-
- volumeSize := d.Get("volume_size").(int)
- growOpts := dbClusterGrowOpts{
- Keypair: d.Get("keypair").(string),
- AvailabilityZone: d.Get("availability_zone").(string),
- FlavorRef: d.Get("flavor_id").(string),
- Volume: &volume{Size: &volumeSize, VolumeType: d.Get("volume_type").(string)},
- }
- if v, ok := d.GetOk("wal_volume"); ok {
- walVolumeOpts, err := extractDatabaseWalVolume(v.([]interface{}))
- if err != nil {
- return diag.Errorf("unable to determine vkcs_db_cluster wal_volume")
- }
- growOpts.Walvolume = &walVolume{
- Size: &walVolumeOpts.Size,
- VolumeType: walVolumeOpts.VolumeType,
- }
- }
- for i := 0; i < len(opts); i++ {
- opts[i] = growOpts
- }
- growClusterOpts := dbClusterGrowClusterOpts{
- Grow: opts,
- }
- err = dbClusterAction(DatabaseV1Client, d.Id(), &growClusterOpts).ExtractErr()
-
- if err != nil {
- return diag.Errorf("error growing vkcs_db_cluster %s: %s", d.Id(), err)
- }
- stateConf.Pending = []string{string(dbClusterStatusGrow)}
- stateConf.Target = []string{string(dbClusterStatusActive)}
-
- _, err = stateConf.WaitForStateContext(ctx)
- if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
- }
- } else {
- cluster, err := dbClusterGet(DatabaseV1Client, d.Id()).extract()
- if err != nil {
- return diag.FromErr(checkDeleted(d, err, "Error retrieving vkcs_db_cluster"))
- }
- ids := make([]dbClusterShrinkOpts, old.(int)-new.(int))
- for i := 0; i < len(ids); i++ {
- ids[i].ID = cluster.Instances[i].ID
- }
-
- shrinkClusterOpts := dbClusterShrinkClusterOpts{
- Shrink: ids,
- }
-
- err = dbClusterAction(DatabaseV1Client, d.Id(), &shrinkClusterOpts).ExtractErr()
-
- if err != nil {
- return diag.Errorf("error growing vkcs_db_cluster %s: %s", d.Id(), err)
- }
- stateConf.Pending = []string{string(dbClusterStatusShrink)}
- stateConf.Target = []string{string(dbClusterStatusActive)}
-
- _, err = stateConf.WaitForStateContext(ctx)
- if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster %s to become ready: %s", d.Id(), err)
- }
+ if sizeChange := new.(int) - old.(int); sizeChange > 0 {
+ err = databaseClusterActionGrow(updateCtx, "")
+ } else if sizeChange < 0 {
+ err = databaseClusterActionShrink(updateCtx, "")
+ }
+ if err != nil {
+ return databaseClusterUpdateProcessError(err, clusterID)
}
}
@@ -844,7 +747,7 @@ func resourceDatabaseClusterUpdate(ctx context.Context, d *schema.ResourceData,
return diag.Errorf("unable to determine vkcs_db_cluster backup_schedule")
}
- err = dbClusterUpdateBackupSchedule(DatabaseV1Client, d.Id(), &backupScheduleUpdateOpts).ExtractErr()
+ err = dbClusterUpdateBackupSchedule(dbClient, clusterID, &backupScheduleUpdateOpts).ExtractErr()
if err != nil {
return diag.Errorf("error updating backup schedule for vkcs_db_cluster %s: %s", d.Id(), err)
@@ -859,6 +762,13 @@ func resourceDatabaseClusterUpdate(ctx context.Context, d *schema.ResourceData,
}
}
+ if d.HasChange("cloud_monitoring_enabled") {
+ err = databaseClusterUpdateCloudMonitoring(updateCtx)
+ if err != nil {
+ return databaseClusterUpdateProcessError(err, clusterID)
+ }
+ }
+
return resourceDatabaseClusterRead(ctx, d, meta)
}
@@ -890,3 +800,55 @@ func resourceDatabaseClusterDelete(ctx context.Context, d *schema.ResourceData,
return nil
}
+
+func databaseClusterUpdateProcessError(err error, clusterID string) diag.Diagnostics {
+ baseErr := err
+ if unwrappedErr := errors.Unwrap(err); unwrappedErr != nil {
+ baseErr = unwrappedErr
+ }
+
+ newErrMsg := baseErr.Error()
+ switch baseErr {
+ case errDBClusterNotFound:
+ newErrMsg = fmt.Sprintf("error retrieving vkcs_db_cluster %s", clusterID)
+ case errDBClusterUpdateWait:
+ newErrMsg = fmt.Sprintf("error waiting for vkcs_db_cluster %s to become ready", clusterID)
+
+ case errDBClusterUpdateDiskAutoexpand:
+ newErrMsg = fmt.Sprintf("error updating disk_autoexpand for vkcs_db_cluster %s", clusterID)
+ case errDBClusterUpdateDiskAutoexpandExtract:
+ newErrMsg = fmt.Sprintf("unable to determine disk_autoexpand from vkcs_db_cluster %s", clusterID)
+ case errDBClusterUpdateWalDiskAutoexpand:
+ newErrMsg = fmt.Sprintf("error updating wal_disk_autoexpand for vkcs_db_cluster %s", clusterID)
+ case errDBClusterUpdateWalDiskAutoexpandExtract:
+ newErrMsg = fmt.Sprintf("unable to determine wal_disk_autoexpand from vkcs_db_cluster %s", clusterID)
+ case errDBClusterUpdateCloudMonitoring:
+ newErrMsg = fmt.Sprintf("error updating cloud_monitoring_enabled for vkcs_db_cluster %s", clusterID)
+
+ case errDBClusterActionUpdateConfiguration:
+ newErrMsg = fmt.Sprintf("error updating configuration for vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionApplyCapabitilies:
+ newErrMsg = fmt.Sprintf("error updating capabilities for vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionApplyCapabilitiesExtract:
+ newErrMsg = fmt.Sprintf("error extracting capabilities for vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionResizeWalVolumeExtract:
+ newErrMsg = fmt.Sprintf("unable to determine wal_volume from vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionGrow:
+ newErrMsg = fmt.Sprintf("error growing vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionShrink:
+ newErrMsg = fmt.Sprintf("error shrinking vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionShrinkWrongOptions:
+ newErrMsg = fmt.Sprintf("invalid shrink options for vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionShrinkInstancesExtract:
+ newErrMsg = fmt.Sprintf("error determining instances to shrink vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionResizeVolume:
+ newErrMsg = fmt.Sprintf("error resizing volume for vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionResizeWalVolume:
+ newErrMsg = fmt.Sprintf("error resizing wal_volume for vkcs_db_cluster %s", clusterID)
+ case errDBClusterActionResizeFlavor:
+ newErrMsg = fmt.Sprintf("error changing flavor for vkcs_db_cluster %s", clusterID)
+ }
+
+ errMsg := strings.Replace(err.Error(), baseErr.Error(), newErrMsg, 1)
+ return diag.Errorf(errMsg)
+}
diff --git a/vkcs/resource_vkcs_db_cluster_test.go b/vkcs/resource_vkcs_db_cluster_test.go
index d450043f..fd142e6c 100755
--- a/vkcs/resource_vkcs_db_cluster_test.go
+++ b/vkcs/resource_vkcs_db_cluster_test.go
@@ -87,6 +87,33 @@ func TestAccDatabaseCluster_wal_no_update(t *testing.T) {
})
}
+func TestAccDatabaseCluster_shrink(t *testing.T) {
+ var cluster dbClusterResp
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckDatabaseClusterDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfig(testAccDatabaseClusterShrinkInitial),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckDatabaseClusterExists(
+ "vkcs_db_cluster.basic", &cluster),
+ ),
+ },
+ {
+ Config: testAccRenderConfig(testAccDatabaseClusterShrinkUpdated),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckDatabaseClusterExists(
+ "vkcs_db_cluster.basic", &cluster),
+ testAccCheckDatabaseClusterLeaderExists(&cluster),
+ ),
+ },
+ },
+ })
+}
+
func testAccCheckDatabaseClusterExists(n string, cluster *dbClusterResp) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
@@ -140,6 +167,17 @@ func testAccCheckDatabaseClusterDestroy(s *terraform.State) error {
return nil
}
+func testAccCheckDatabaseClusterLeaderExists(cluster *dbClusterResp) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ for _, inst := range cluster.Instances {
+ if inst.Role == dbClusterInstanceRoleLeader {
+ return nil
+ }
+ }
+ return fmt.Errorf("cluster leader instance is absent")
+ }
+}
+
const testAccDatabaseClusterBasic = `
{{.BaseNetwork}}
{{.BaseFlavor}}
@@ -162,8 +200,7 @@ const testAccDatabaseClusterBasic = `
availability_zone = "{{.AvailabilityZone}}"
depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
+ vkcs_networking_router_interface.base
]
}
`
@@ -175,6 +212,7 @@ const testAccDatabaseClusterUpdate = `
resource "vkcs_db_cluster" "basic" {
name = "basic"
flavor_id = data.vkcs_compute_flavor.base.id
+ cloud_monitoring_enabled = true
volume_size = 9
volume_type = "{{.VolumeType}}"
cluster_size = 3
@@ -189,10 +227,7 @@ resource "vkcs_db_cluster" "basic" {
availability_zone = "{{.AvailabilityZone}}"
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
`
@@ -227,9 +262,54 @@ const testAccDatabaseClusterWal = `
max_disk_size = 1000
}
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
+ }
+`
+
+const testAccDatabaseClusterShrinkInitial = `
+{{.BaseNetwork}}
+
+{{.BaseFlavor}}
+
+ resource "vkcs_db_cluster" "basic" {
+ name = "basic"
+ flavor_id = data.vkcs_compute_flavor.base.id
+ volume_size = 8
+ volume_type = "ceph-ssd"
+ cluster_size = 4
+ datastore {
+ version = "13"
+ type = "postgresql"
+ }
+ network {
+ uuid = vkcs_networking_network.base.id
+ }
+
+ availability_zone = "GZ1"
+ depends_on = [vkcs_networking_router_interface.base]
+ }
+`
+
+var testAccDatabaseClusterShrinkUpdated = `
+{{.BaseNetwork}}
+
+{{.BaseFlavor}}
+
+ resource "vkcs_db_cluster" "basic" {
+ name = "basic"
+ flavor_id = data.vkcs_compute_flavor.base.id
+ volume_size = 8
+ volume_type = "ceph-ssd"
+ cluster_size = 3
+ datastore {
+ version = "13"
+ type = "postgresql"
+ }
+ network {
+ uuid = vkcs_networking_network.base.id
+ }
+
+ availability_zone = "GZ1"
+ depends_on = [vkcs_networking_router_interface.base]
}
`
diff --git a/vkcs/resource_vkcs_db_cluster_with_shards.go b/vkcs/resource_vkcs_db_cluster_with_shards.go
index 16369b7e..4c78cc31 100755
--- a/vkcs/resource_vkcs_db_cluster_with_shards.go
+++ b/vkcs/resource_vkcs_db_cluster_with_shards.go
@@ -2,9 +2,13 @@ package vkcs
import (
"context"
+ "errors"
"fmt"
"log"
+ "sort"
+ "strings"
+ "github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -16,6 +20,7 @@ func resourceDatabaseClusterWithShards() *schema.Resource {
ReadContext: resourceDatabaseClusterWithShardsRead,
DeleteContext: resourceDatabaseClusterWithShardsDelete,
UpdateContext: resourceDatabaseClusterWithShardsUpdate,
+ CustomizeDiff: resourceDatabaseCustomizeDiff,
Importer: &schema.ResourceImporter{
StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(configer)
@@ -41,7 +46,8 @@ func resourceDatabaseClusterWithShards() *schema.Resource {
continue
}
shardIDs[inst.ShardID] = 1
- newShard := flattenDatabaseClusterShard(inst)
+ newShard := flattenDatabaseClusterShard(inst.ShardID, []dbClusterInstanceResp{inst})
+ newShard["volume_type"] = dbImportedStatus
if inst.WalVolume != nil {
newShard["wal_volume"] = flattenDatabaseClusterWalVolume(*inst.WalVolume)
}
@@ -241,6 +247,13 @@ func resourceDatabaseClusterWithShards() *schema.Resource {
Description: "Object that represents backup to restore instance from. **New since v.0.1.4**.",
},
+ "cloud_monitoring_enabled": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ForceNew: false,
+ Description: "Enable cloud monitoring for the cluster. Changing this for Redis or MongoDB creates a new instance. **New since v.0.2.0**",
+ },
+
"shard": {
Type: schema.TypeList,
Required: true,
@@ -261,6 +274,16 @@ func resourceDatabaseClusterWithShards() *schema.Resource {
Description: "The number of instances in the cluster shard.",
},
+ "shrink_options": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: "Used only for shrinking cluster. List of IDs of instances that should remain after shrink. If no options are supplied, shrink operation will choose first non-leader instance to delete.",
+ DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
+ return true
+ },
+ },
+
"flavor_id": {
Type: schema.TypeString,
Required: true,
@@ -314,16 +337,32 @@ func resourceDatabaseClusterWithShards() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"uuid": {
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Description: "The id of the network. Changing this creates a new cluster." +
+ "**Note** Although this argument is marked as optional, it is actually required at the moment. Not setting a value for it may cause an error.",
+ },
+ "port": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
- Description: "The id of the network. Changing this creates a new cluster.",
+ Description: "The port id of the network. Changing this creates a new cluster. ***Deprecated*** This argument is deprecated, please do not use it.",
+ Deprecated: "This argument is deprecated, please do not use it.",
},
- "port": {
+ "subnet_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
- Description: "The port id of the network. Changing this creates a new cluster.",
+ Description: "The id of the subnet. Changing this creates a new cluster. **New since v.0.1.15**.",
+ },
+ "security_groups": {
+ Type: schema.TypeSet,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Set: schema.HashString,
+ Description: "An array of one or more security group IDs to associate with the shard instances. Changing this creates a new cluster. **New since v.0.2.0**.",
},
},
Description: "Object that represents network of the cluster shard. Changing this creates a new cluster.",
@@ -337,6 +376,29 @@ func resourceDatabaseClusterWithShards() *schema.Resource {
ForceNew: true,
Description: "The name of the availability zone of the cluster shard. Changing this creates a new cluster.",
},
+
+ "instances": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "instance_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The id of the instance.",
+ },
+ "ip": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ Description: "IP address of the instance.",
+ },
+ },
+ },
+ Description: "Shard instances info. **New since v.0.1.15**.",
+ },
},
},
Description: "Object that represents cluster shard. There can be several instances of this object.",
@@ -354,8 +416,9 @@ func resourceDatabaseClusterWithShardsCreate(ctx context.Context, d *schema.Reso
}
createOpts := &dbClusterCreateOpts{
- Name: d.Get("name").(string),
- FloatingIPEnabled: d.Get("floating_ip_enabled").(bool),
+ Name: d.Get("name").(string),
+ FloatingIPEnabled: d.Get("floating_ip_enabled").(bool),
+ CloudMonitoringEnabled: d.Get("cloud_monitoring_enabled").(bool),
}
message := "unable to determine vkcs_db_cluster_with_shards"
@@ -414,7 +477,7 @@ func resourceDatabaseClusterWithShardsCreate(ctx context.Context, d *schema.Reso
instanceCount += shardSize
volumeSize := shardMap["volume_size"].(int)
shardInfo[i].Volume = &volume{Size: &volumeSize, VolumeType: shardMap["volume_type"].(string)}
- shardInfo[i].Nics, _ = extractDatabaseNetworks(shardMap["network"].([]interface{}))
+ shardInfo[i].Nics, shardInfo[i].SecurityGroups, _ = extractDatabaseNetworks(shardMap["network"].([]interface{}))
shardInfo[i].AvailabilityZone = shardMap["availability_zone"].(string)
shardInfo[i].FlavorRef = shardMap["flavor_id"].(string)
shardInfo[i].ShardID = shardMap["shard_id"].(string)
@@ -520,111 +583,164 @@ func resourceDatabaseClusterWithShardsRead(ctx context.Context, d *schema.Resour
d.Set("wal_disk_autoexpand", flattenDatabaseInstanceAutoExpand(cluster.WalAutoExpand, cluster.WalMaxDiskSize))
}
- return nil
+ hasChanges := d.HasChangesExcept()
+
+ var diags diag.Diagnostics
+
+ shardsInstances := getDatabaseClusterShardInstances(cluster.Instances)
+ flattenedShards := flattenDatabaseClusterShards(shardsInstances)
+ // Workaround to persist user order of shards
+ sort.Slice(flattenedShards, func(i, j int) bool {
+ return flattenedShards[i]["shard_id"].(string) < flattenedShards[j]["shard_id"].(string)
+ })
+
+ rawShards := d.Get("shard").([]interface{})
+ shards := make([]map[string]interface{}, 0, len(flattenedShards))
+ newShards := make([]map[string]interface{}, 0, len(flattenedShards))
+
+OuterLoop:
+ for _, fSh := range flattenedShards {
+ for _, rawSh := range rawShards {
+ rawShMap := rawSh.(map[string]interface{})
+ if fSh["shard_id"].(string) == rawShMap["shard_id"].(string) {
+ shards = append(shards, fSh)
+ continue OuterLoop
+ }
+ }
+ newShards = append(newShards, fSh)
+ }
+
+ shards = append(shards, newShards...)
+ for i := range shards {
+ shards[i]["availability_zone"] = d.Get(fmt.Sprintf("shard.%d.availability_zone", i))
+ shards[i]["network"] = d.Get(fmt.Sprintf("shard.%d.network", i))
+
+ // Workaround since we don't retrieve info about volume_type
+ // NOTE: remove this when add getting info about volumes from
+ // blockstorage service
+ if v, ok := d.GetOk(fmt.Sprintf("shard.%d.volume_type", i)); ok {
+ shards[i]["volume_type"] = v
+ }
+ if v, ok := d.GetOk(fmt.Sprintf("shard.%d.wal_volume.volume_type", i)); ok {
+ if wV, ok := shards[i]["wal_volume"]; ok {
+ m := wV.(map[string]interface{})
+ m["volume_type"] = v
+ shards[i]["wal_volume"] = m
+ }
+ }
+
+ rawNetworks := shards[i]["network"].([]interface{})
+ p := cty.Path{
+ cty.GetAttrStep{Name: "shard"},
+ cty.IndexStep{Key: cty.NumberIntVal(int64(i))},
+ cty.GetAttrStep{Name: "network"},
+ }
+ if hasChanges {
+ diags = checkDBNetworks(rawNetworks, p, diags)
+ }
+ }
+
+ log.Printf("[DEBUG] Retrieved shards for vkcs_db_cluster_with_shards %s: %#v", d.Id(), flattenedShards)
+
+ d.Set("shard", shards)
+ return diags
}
func resourceDatabaseClusterWithShardsUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
config := meta.(configer)
- DatabaseV1Client, err := config.DatabaseV1Client(getRegion(d, config))
+ dbClient, err := config.DatabaseV1Client(getRegion(d, config))
if err != nil {
return diag.Errorf("Error creating VKCS database client: %s", err)
}
+ clusterID := d.Id()
stateConf := &resource.StateChangeConf{
Pending: []string{string(dbClusterStatusBuild)},
Target: []string{string(dbClusterStatusActive)},
- Refresh: databaseClusterStateRefreshFunc(DatabaseV1Client, d.Id(), nil),
+ Refresh: databaseClusterStateRefreshFunc(dbClient, clusterID, nil),
Timeout: d.Timeout(schema.TimeoutCreate),
Delay: dbInstanceDelay,
MinTimeout: dbInstanceMinTimeout,
}
+ updateCtx := &dbResourceUpdateContext{
+ Ctx: ctx,
+ Client: dbClient,
+ D: d,
+ StateConf: stateConf,
+ }
if d.HasChange("configuration_id") {
- old, new := d.GetChange("configuration_id")
-
- var detachConfigurationOpts dbClusterDetachConfigurationGroupOpts
- detachConfigurationOpts.ConfigurationDetach.ConfigurationID = old.(string)
- err := dbClusterAction(DatabaseV1Client, d.Id(), &detachConfigurationOpts).ExtractErr()
- if err != nil {
- return diag.FromErr(err)
- }
- log.Printf("Detaching configuration %s from vkcs_db_cluster_with_shards %s", old, d.Id())
-
- _, err = stateConf.WaitForStateContext(ctx)
+ err = databaseClusterActionUpdateConfiguration(updateCtx)
if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster_with_shards %s to become ready: %s", d.Id(), err)
- }
-
- if new != "" {
- var attachConfigurationOpts dbClusterAttachConfigurationGroupOpts
- attachConfigurationOpts.ConfigurationAttach.ConfigurationID = new.(string)
- err := dbClusterAction(DatabaseV1Client, d.Id(), &attachConfigurationOpts).ExtractErr()
- if err != nil {
- return diag.FromErr(err)
- }
- log.Printf("Attaching configuration %s to vkcs_db_cluster_with_shards %s", new, d.Id())
-
- _, err = stateConf.WaitForStateContext(ctx)
- if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster_with_shards %s to become ready: %s", d.Id(), err)
- }
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, "")
}
}
if d.HasChange("disk_autoexpand") {
- _, new := d.GetChange("disk_autoexpand")
- autoExpandProperties, err := extractDatabaseAutoExpand(new.([]interface{}))
+ err = databaseClusterUpdateDiskAutoexpand(updateCtx)
if err != nil {
- return diag.Errorf("unable to determine vkcs_db_cluster_with_shards disk_autoexpand")
- }
- var autoExpandOpts dbClusterUpdateAutoExpandOpts
- if autoExpandProperties.AutoExpand {
- autoExpandOpts.Cluster.VolumeAutoresizeEnabled = 1
- } else {
- autoExpandOpts.Cluster.VolumeAutoresizeEnabled = 0
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, "")
}
- autoExpandOpts.Cluster.VolumeAutoresizeMaxSize = autoExpandProperties.MaxDiskSize
- err = dbClusterUpdateAutoExpand(DatabaseV1Client, d.Id(), &autoExpandOpts).ExtractErr()
+ }
+
+ if d.HasChange("wal_disk_autoexpand") {
+ err = databaseClusterUpdateWalDiskAutoexpand(updateCtx)
if err != nil {
- return diag.FromErr(err)
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, "")
}
+ }
- stateConf.Pending = []string{string(dbClusterStatusUpdating)}
- stateConf.Target = []string{string(dbClusterStatusActive)}
-
- _, err = stateConf.WaitForStateContext(ctx)
+ if d.HasChange("capabilities") {
+ err = databaseClusterActionApplyCapabilities(updateCtx)
if err != nil {
- return diag.Errorf("error waiting for vkcs_db_cluster_with_shards %s to become ready: %s", d.Id(), err)
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, "")
}
}
- if d.HasChange("capabilities") {
- _, newCapabilities := d.GetChange("capabilities")
- newCapabilitiesOpts, err := extractDatabaseCapabilities(newCapabilities.([]interface{}))
+ if d.HasChange("cloud_monitoring_enabled") {
+ err = databaseClusterUpdateCloudMonitoring(updateCtx)
if err != nil {
- return diag.Errorf("unable to determine vkcs_db_cluster_with_shards capability")
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, "")
}
- var applyCapabilityOpts dbClusterApplyCapabilityOpts
- applyCapabilityOpts.ApplyCapability.Capabilities = newCapabilitiesOpts
+ }
- err = dbClusterAction(DatabaseV1Client, d.Id(), &applyCapabilityOpts).ExtractErr()
+ shardsRaw := d.Get("shard").([]interface{})
+ for i, shardRaw := range shardsRaw {
+ shard := shardRaw.(map[string]interface{})
+ shardID := shard["shard_id"].(string)
+ pathPrefix := fmt.Sprintf("shard.%d.", i)
- if err != nil {
- return diag.Errorf("error applying capability to vkcs_db_cluster_with_shards %s: %s", d.Id(), err)
+ if p := pathPrefix + "volume_size"; d.HasChange(p) {
+ err = databaseClusterActionResizeVolume(updateCtx, shardID)
+ if err != nil {
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, shardID)
+ }
}
- applyCapabilityClusterConf := &resource.StateChangeConf{
- Pending: []string{string(dbClusterStatusCapabilityApplying), string(dbClusterStatusBuild)},
- Target: []string{string(dbClusterStatusActive)},
- Refresh: databaseClusterStateRefreshFunc(DatabaseV1Client, d.Id(), &newCapabilitiesOpts),
- Timeout: d.Timeout(schema.TimeoutCreate),
- Delay: dbInstanceDelay,
- MinTimeout: dbInstanceMinTimeout,
+ if p := pathPrefix + "wal_volume"; d.HasChange(p) {
+ err = databaseClusterActionResizeWalVolume(updateCtx, shardID)
+ if err != nil {
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, shardID)
+ }
}
- log.Printf("[DEBUG] Waiting for cluster to become ready after applying capability")
- _, err = applyCapabilityClusterConf.WaitForStateContext(ctx)
- if err != nil {
- return diag.Errorf("error applying capability to vkcs_db_cluster_with_shards %s: %s", d.Id(), err)
+
+ if p := pathPrefix + "flavor_id"; d.HasChange(p) {
+ err = databaseClusterActionResizeFlavor(updateCtx, shardID)
+ if err != nil {
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, shardID)
+ }
+ }
+
+ if p := pathPrefix + "size"; d.HasChange(p) {
+ old, new := d.GetChange(p)
+ if sizeChange := new.(int) - old.(int); sizeChange > 0 {
+ err = databaseClusterActionGrow(updateCtx, shardID)
+ } else if sizeChange < 0 {
+ err = databaseClusterActionShrink(updateCtx, shardID)
+ }
+ if err != nil {
+ return databaseClusterWithShardsUpdateProcessError(err, clusterID, shardID)
+ }
}
}
@@ -659,3 +775,57 @@ func resourceDatabaseClusterWithShardsDelete(ctx context.Context, d *schema.Reso
return nil
}
+
+func databaseClusterWithShardsUpdateProcessError(err error, clusterID string, shardID string) diag.Diagnostics {
+ baseErr := err
+ if unwrappedErr := errors.Unwrap(err); unwrappedErr != nil {
+ baseErr = unwrappedErr
+ }
+
+ newErrMsg := baseErr.Error()
+ switch baseErr {
+ case errDBClusterNotFound:
+ newErrMsg = fmt.Sprintf("error retrieving vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterShardNotFound:
+ newErrMsg = fmt.Sprintf("unable to extract shard from vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterUpdateWait:
+ newErrMsg = fmt.Sprintf("error waiting for vkcs_db_cluster_with_shards %s to become ready", clusterID)
+
+ case errDBClusterUpdateDiskAutoexpand:
+ newErrMsg = fmt.Sprintf("error updating disk_autoexpand for vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterUpdateDiskAutoexpandExtract:
+ newErrMsg = fmt.Sprintf("unable to determine disk_autoexpand fron vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterUpdateWalDiskAutoexpand:
+ newErrMsg = fmt.Sprintf("error updating wal_disk_autoexpand for vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterUpdateWalDiskAutoexpandExtract:
+ newErrMsg = fmt.Sprintf("unable to determine wal_disk_autoexpand from vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterUpdateCloudMonitoring:
+ newErrMsg = fmt.Sprintf("error updating cloud_monitoring_enabled for vkcs_db_cluster_with_shards %s", clusterID)
+
+ case errDBClusterActionUpdateConfiguration:
+ newErrMsg = fmt.Sprintf("error updating configuration for vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterActionApplyCapabitilies:
+ newErrMsg = fmt.Sprintf("error updating capabilities for vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterActionApplyCapabilitiesExtract:
+ newErrMsg = fmt.Sprintf("error extracting capabilities for vkcs_db_cluster_with_shards %s", clusterID)
+ case errDBClusterActionResizeWalVolumeExtract:
+ newErrMsg = fmt.Sprintf("unable to determine wal_volume from shard %s of vkcs_db_cluster_with_shards %s", shardID, clusterID)
+ case errDBClusterActionGrow:
+ newErrMsg = fmt.Sprintf("error growing shard %s of vkcs_db_cluster_with_shards %s", shardID, clusterID)
+ case errDBClusterActionShrink:
+ newErrMsg = fmt.Sprintf("error shrinking shard %s of vkcs_db_cluster_with_shards %s", shardID, clusterID)
+ case errDBClusterActionShrinkWrongOptions:
+ newErrMsg = fmt.Sprintf("invalid shrink options for shard %s of vkcs_db_cluster_with_shards %s", shardID, clusterID)
+ case errDBClusterActionShrinkInstancesExtract:
+ newErrMsg = fmt.Sprintf("error determining instances to shrink shard %s of vkcs_db_cluster_with_shards %s", shardID, clusterID)
+ case errDBClusterActionResizeVolume:
+ newErrMsg = fmt.Sprintf("error resizing volume for shard %s of vkcs_db_cluster_with_shards %s", shardID, clusterID)
+ case errDBClusterActionResizeWalVolume:
+ newErrMsg = fmt.Sprintf("error resizing wal_volume for shard %s of vkcs_db_cluster_with_shards %s", shardID, clusterID)
+ case errDBClusterActionResizeFlavor:
+ newErrMsg = fmt.Sprintf("error changing flavor for shard %s of vkcs_db_cluster_with_shards %s", shardID, clusterID)
+ }
+
+ errMsg := strings.Replace(err.Error(), baseErr.Error(), newErrMsg, 1)
+ return diag.Errorf(errMsg)
+}
diff --git a/vkcs/resource_vkcs_db_cluster_with_shards_test.go b/vkcs/resource_vkcs_db_cluster_with_shards_test.go
index 715b1a8e..3db0dfde 100755
--- a/vkcs/resource_vkcs_db_cluster_with_shards_test.go
+++ b/vkcs/resource_vkcs_db_cluster_with_shards_test.go
@@ -19,10 +19,120 @@ func TestAccDatabaseClusterWithShards_basic(t *testing.T) {
{
Config: testAccRenderConfig(testAccDatabaseClusterWithShardsBasic),
Check: resource.ComposeTestCheckFunc(
- testAccCheckDatabaseClusterExists(
- "vkcs_db_cluster_with_shards.basic", &cluster),
- resource.TestCheckResourceAttrPtr(
- "vkcs_db_cluster_with_shards.basic", "name", &cluster.Name),
+ testAccCheckDatabaseClusterExists("vkcs_db_cluster_with_shards.basic", &cluster),
+ resource.TestCheckResourceAttrPtr("vkcs_db_cluster_with_shards.basic", "name", &cluster.Name),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccDatabaseClusterWithShards_update(t *testing.T) {
+ var cluster dbClusterResp
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckDatabaseClusterWithShardsDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfig(testAccDatabaseClusterWithShardsUpdateInitial),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckDatabaseClusterExists("vkcs_db_cluster_with_shards.update", &cluster),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "name", "update"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "datastore.0.version", "20.8"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "datastore.0.type", "clickhouse"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "cloud_monitoring_enabled", "false"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "shard.#", "1"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.update", "shard.0.flavor_id",
+ "data.vkcs_compute_flavor.base", "id"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.update", "shard.0.network.0.uuid",
+ "vkcs_networking_network.base", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "shard.0.volume_size", "8"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "shard.0.volume_type", "ceph-ssd"),
+ ),
+ },
+ {
+ Config: testAccRenderConfig(testAccDatabaseClusterWithShardsUpdateUpdated),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "name", "update"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "datastore.0.version", "20.8"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "datastore.0.type", "clickhouse"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "cloud_monitoring_enabled", "true"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "shard.#", "1"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.update", "shard.0.flavor_id",
+ "data.vkcs_compute_flavor.new_flavor", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "shard.0.volume_size", "10"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.update", "shard.0.volume_type", "ceph-hdd"),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccDatabaseClusterWithShards_resize(t *testing.T) {
+ var cluster dbClusterResp
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckDatabaseClusterWithShardsDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfig(testAccDatabaseClusterWithShardsResizeInitial),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckDatabaseClusterExists("vkcs_db_cluster_with_shards.resize", &cluster),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.#", "1"),
+
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.size", "1"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.resize", "shard.0.flavor_id",
+ "data.vkcs_compute_flavor.base", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.volume_size", "8"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.volume_type", "ceph-ssd"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.resize", "shard.0.network.0.uuid",
+ "vkcs_networking_network.base", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.instances.#", "1"),
+ ),
+ },
+ {
+ Config: testAccRenderConfig(testAccDatabaseClusterWithShardsResizeGrow),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckDatabaseClusterExists("vkcs_db_cluster_with_shards.resize", &cluster),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.#", "2"),
+
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.size", "3"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.resize", "shard.0.flavor_id",
+ "data.vkcs_compute_flavor.new_flavor", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.volume_size", "10"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.volume_type", "ceph-hdd"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.resize", "shard.0.network.0.uuid",
+ "vkcs_networking_network.base", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.instances.#", "3"),
+
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.1.size", "1"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.resize", "shard.1.flavor_id",
+ "data.vkcs_compute_flavor.base", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.1.volume_size", "8"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.1.volume_type", "ceph-ssd"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.resize", "shard.1.network.0.uuid",
+ "vkcs_networking_network.base", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.1.instances.#", "1"),
+ ),
+ },
+ {
+ Config: testAccRenderConfig(testAccDatabaseClusterWithShardsResizeShrink),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckDatabaseClusterExists("vkcs_db_cluster_with_shards.resize", &cluster),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.#", "1"),
+
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.size", "1"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.resize", "shard.0.flavor_id",
+ "data.vkcs_compute_flavor.base", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.volume_size", "10"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.volume_type", "ceph-ssd"),
+ resource.TestCheckResourceAttrPair("vkcs_db_cluster_with_shards.resize", "shard.0.network.0.uuid",
+ "vkcs_networking_network.base", "id"),
+ resource.TestCheckResourceAttr("vkcs_db_cluster_with_shards.resize", "shard.0.instances.#", "1"),
),
},
},
@@ -62,7 +172,6 @@ const testAccDatabaseClusterWithShardsBasic = `
type = "clickhouse"
}
-
shard {
size = 1
shard_id = "shard0"
@@ -75,9 +184,175 @@ const testAccDatabaseClusterWithShardsBasic = `
availability_zone = "{{.AvailabilityZone}}"
}
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
`
+
+const testAccDatabaseClusterWithShardsUpdateInitial = `
+{{.BaseNetwork}}
+{{.BaseFlavor}}
+
+resource "vkcs_db_cluster_with_shards" "update" {
+ name = "update"
+
+ datastore {
+ version = "20.8"
+ type = "clickhouse"
+ }
+
+ cloud_monitoring_enabled = false
+
+ shard {
+ size = 1
+ shard_id = "shard0"
+ flavor_id = data.vkcs_compute_flavor.base.id
+ volume_size = 8
+ volume_type = "ceph-ssd"
+ network {
+ uuid = vkcs_networking_network.base.id
+ }
+ availability_zone = "{{.AvailabilityZone}}"
+ }
+
+ depends_on = [vkcs_networking_router_interface.base]
+}
+`
+
+const testAccDatabaseClusterWithShardsUpdateUpdated = `
+{{.BaseNetwork}}
+{{.BaseFlavor}}
+
+data "vkcs_compute_flavor" "new_flavor" {
+ name = "Standard-4-8-80"
+}
+
+resource "vkcs_db_cluster_with_shards" "update" {
+ name = "update"
+
+ datastore {
+ version = "20.8"
+ type = "clickhouse"
+ }
+
+ disk_autoexpand {
+ autoexpand = true
+ max_disk_size = 1000
+ }
+
+ cloud_monitoring_enabled = true
+
+ shard {
+ size = 1
+ shard_id = "shard0"
+ flavor_id = data.vkcs_compute_flavor.new_flavor.id
+ volume_size = 10
+ volume_type = "ceph-hdd"
+ network {
+ uuid = vkcs_networking_network.base.id
+ }
+ availability_zone = "{{.AvailabilityZone}}"
+ }
+
+ depends_on = [vkcs_networking_router_interface.base]
+}
+`
+
+const testAccDatabaseClusterWithShardsResizeInitial = `
+{{.BaseNetwork}}
+{{.BaseFlavor}}
+
+resource "vkcs_db_cluster_with_shards" "resize" {
+ name = "resize"
+
+ datastore {
+ version = "20.8"
+ type = "clickhouse"
+ }
+
+ shard {
+ size = 1
+ shard_id = "shard0"
+ flavor_id = data.vkcs_compute_flavor.base.id
+ volume_size = 8
+ volume_type = "ceph-ssd"
+ network {
+ uuid = vkcs_networking_network.base.id
+ }
+ availability_zone = "{{.AvailabilityZone}}"
+ }
+
+ depends_on = [vkcs_networking_router_interface.base]
+}
+`
+
+const testAccDatabaseClusterWithShardsResizeGrow = `
+{{.BaseNetwork}}
+{{.BaseFlavor}}
+
+data "vkcs_compute_flavor" "new_flavor" {
+ name = "Standard-4-8-80"
+}
+
+resource "vkcs_db_cluster_with_shards" "resize" {
+ name = "resize"
+
+ datastore {
+ version = "20.8"
+ type = "clickhouse"
+ }
+
+ shard {
+ size = 3
+ shard_id = "shard0"
+ flavor_id = data.vkcs_compute_flavor.new_flavor.id
+ volume_size = 10
+ volume_type = "ceph-hdd"
+ network {
+ uuid = vkcs_networking_network.base.id
+ }
+ availability_zone = "{{.AvailabilityZone}}"
+ }
+
+ shard {
+ size = 1
+ shard_id = "shard1"
+ flavor_id = data.vkcs_compute_flavor.base.id
+ volume_size = 8
+ volume_type = "ceph-ssd"
+ network {
+ uuid = vkcs_networking_network.base.id
+ }
+ availability_zone = "{{.AvailabilityZone}}"
+ }
+
+ depends_on = [vkcs_networking_router_interface.base]
+}
+`
+
+const testAccDatabaseClusterWithShardsResizeShrink = `
+{{.BaseNetwork}}
+{{.BaseFlavor}}
+
+resource "vkcs_db_cluster_with_shards" "resize" {
+ name = "resize"
+
+ datastore {
+ version = "20.8"
+ type = "clickhouse"
+ }
+
+ shard {
+ size = 1
+ shard_id = "shard0"
+ flavor_id = data.vkcs_compute_flavor.base.id
+ volume_size = 10
+ volume_type = "ceph-ssd"
+ network {
+ uuid = vkcs_networking_network.base.id
+ }
+ availability_zone = "{{.AvailabilityZone}}"
+ }
+
+ depends_on = [vkcs_networking_router_interface.base]
+}
+`
diff --git a/vkcs/resource_vkcs_db_config_group.go b/vkcs/resource_vkcs_db_config_group.go
index ff69482f..e737c738 100644
--- a/vkcs/resource_vkcs_db_config_group.go
+++ b/vkcs/resource_vkcs_db_config_group.go
@@ -72,7 +72,8 @@ func resourceDatabaseConfigGroup() *schema.Resource {
Description: "Timestamp of config group's creation",
},
},
- Description: "Provides a db config group resource. This can be used to create, update and delete db config group.\n**New since v.0.1.7**.",
+ Description: "Provides a db config group resource. This can be used to create, update and delete db config group.\n" +
+ "**New since v.0.1.7**.",
}
}
@@ -134,7 +135,7 @@ func resourceDatabaseConfigGroupRead(ctx context.Context, d *schema.ResourceData
log.Printf("[DEBUG] Retrieved vkcs_db_config_group %s: %#v", d.Id(), configGroup)
d.Set("name", configGroup.Name)
- ds := dataStore{
+ ds := dataStoreShort{
Type: configGroup.DatastoreName,
Version: configGroup.DatastoreVersionName,
}
diff --git a/vkcs/resource_vkcs_db_config_group_test.go b/vkcs/resource_vkcs_db_config_group_test.go
index cb4a3cd6..30e66a5d 100644
--- a/vkcs/resource_vkcs_db_config_group_test.go
+++ b/vkcs/resource_vkcs_db_config_group_test.go
@@ -144,10 +144,7 @@ resource "vkcs_db_instance" "basic" {
autoexpand = true
max_disk_size = 1000
}
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
`
@@ -187,9 +184,6 @@ resource "vkcs_db_instance" "basic" {
autoexpand = true
max_disk_size = 1000
}
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
`
diff --git a/vkcs/resource_vkcs_db_database_test.go b/vkcs/resource_vkcs_db_database_test.go
index d8ce3c2c..e096df16 100755
--- a/vkcs/resource_vkcs_db_database_test.go
+++ b/vkcs/resource_vkcs_db_database_test.go
@@ -140,10 +140,7 @@ resource "vkcs_db_instance" "basic" {
uuid = vkcs_networking_network.base.id
}
availability_zone = "{{.AvailabilityZone}}"
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
resource "vkcs_db_database" "basic" {
diff --git a/vkcs/resource_vkcs_db_instance.go b/vkcs/resource_vkcs_db_instance.go
index a63c1ff2..00611079 100755
--- a/vkcs/resource_vkcs_db_instance.go
+++ b/vkcs/resource_vkcs_db_instance.go
@@ -6,6 +6,7 @@ import (
"log"
"time"
+ "github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -58,6 +59,7 @@ func resourceDatabaseInstance() *schema.Resource {
ReadContext: resourceDatabaseInstanceRead,
DeleteContext: resourceDatabaseInstanceDelete,
UpdateContext: resourceDatabaseInstanceUpdate,
+ CustomizeDiff: resourceDatabaseCustomizeDiff,
Importer: &schema.ResourceImporter{
StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(configer)
@@ -202,22 +204,39 @@ func resourceDatabaseInstance() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"uuid": {
- Type: schema.TypeString,
- Optional: true,
- ForceNew: true,
- Description: "The id of the network. Changing this creates a new instance.",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Description: "The id of the network. Changing this creates a new instance." +
+ "**Note** Although this argument is marked as optional, it is actually required at the moment. Not setting a value for it may cause an error.",
},
"port": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
- Description: "The port id of the network. Changing this creates a new instance.",
+ Description: "The port id of the network. Changing this creates a new instance. ***Deprecated*** This argument is deprecated, please do not use it.",
+ Deprecated: "This argument is deprecated, please do not use it.",
},
"fixed_ip_v4": {
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Description: "The IPv4 address. Changing this creates a new instance. " +
+ "**Note** This argument conflicts with \"replica_of\". Setting both at the same time causes \"fixed_ip_v4\" to be ignored.",
+ },
+ "subnet_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
- Description: "The IPv4 address. Changing this creates a new instance.",
+ Description: "The id of the subnet. Changing this creates a new instance. **New since v.0.1.15**.",
+ },
+ "security_groups": {
+ Type: schema.TypeSet,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Set: schema.HashString,
+ Description: "An array of one or more security group IDs to associate with the instance. Changing this creates a new instance. **New since v.0.2.0**.",
},
},
},
@@ -415,6 +434,24 @@ func resourceDatabaseInstance() *schema.Resource {
},
Description: "Object that represents configuration of PITR backup. This functionality is available only for postgres datastore. **New since v.0.1.4**.",
},
+
+ "cloud_monitoring_enabled": {
+ Type: schema.TypeBool,
+ Optional: true,
+ ForceNew: false,
+ Description: "Enable cloud monitoring for the instance. Changing this for Redis or MongoDB creates a new instance. **New since v.0.2.0**",
+ },
+
+ // Computed values
+ "ip": {
+ Type: schema.TypeList,
+ Optional: true,
+ Computed: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ Description: "IP address of the instance.",
+ },
},
Description: "Provides a db instance resource. This can be used to create, modify and delete db instance.",
}
@@ -429,13 +466,14 @@ func resourceDatabaseInstanceCreate(ctx context.Context, d *schema.ResourceData,
size := d.Get("size").(int)
createOpts := &dbInstanceCreateOpts{
- FlavorRef: d.Get("flavor_id").(string),
- Name: d.Get("name").(string),
- Volume: &volume{Size: &size, VolumeType: d.Get("volume_type").(string)},
- ReplicaOf: d.Get("replica_of").(string),
- AvailabilityZone: d.Get("availability_zone").(string),
- FloatingIPEnabled: d.Get("floating_ip_enabled").(bool),
- Keypair: d.Get("keypair").(string),
+ FlavorRef: d.Get("flavor_id").(string),
+ Name: d.Get("name").(string),
+ Volume: &volume{Size: &size, VolumeType: d.Get("volume_type").(string)},
+ ReplicaOf: d.Get("replica_of").(string),
+ AvailabilityZone: d.Get("availability_zone").(string),
+ FloatingIPEnabled: d.Get("floating_ip_enabled").(bool),
+ Keypair: d.Get("keypair").(string),
+ CloudMonitoringEnabled: d.Get("cloud_monitoring_enabled").(bool),
}
message := "unable to determine vkcs_db_instance"
@@ -464,7 +502,7 @@ func resourceDatabaseInstanceCreate(ctx context.Context, d *schema.ResourceData,
}
if v, ok := d.GetOk("network"); ok {
- createOpts.Nics, err = extractDatabaseNetworks(v.([]interface{}))
+ createOpts.Nics, createOpts.SecurityGroups, err = extractDatabaseNetworks(v.([]interface{}))
if err != nil {
return diag.Errorf("%s network", message)
}
@@ -661,7 +699,40 @@ func resourceDatabaseInstanceRead(ctx context.Context, d *schema.ResourceData, m
d.Set("backup_schedule", nil)
}
- return nil
+ d.Set("ip", instance.IP)
+
+ if !d.HasChangesExcept() {
+ return nil
+ }
+
+ var diags diag.Diagnostics
+
+ rawNetworks := d.Get("network").([]interface{})
+ diags = checkDBNetworks(rawNetworks, cty.Path{}, diags)
+
+ // Check if user set both "replica_of" and "network.fixed_ip_v4"
+ if _, ok := d.GetOk("replica_of"); !ok {
+ return diags
+ }
+ for i, n := range rawNetworks {
+ rawNetwork := n.(map[string]interface{})
+ if v := rawNetwork["fixed_ip_v4"].(string); v != "" {
+ path := cty.Path{
+ cty.GetAttrStep{Name: "network"},
+ cty.IndexStep{Key: cty.NumberIntVal(int64(i))},
+ cty.GetAttrStep{Name: "fixed_ip_v4"},
+ }
+ diags = append(diags, diag.Diagnostic{
+ Severity: diag.Warning,
+ Summary: "Field conflicts with attribute \"replica_of\".",
+ Detail: "Setting \"fixed_ip_v4\" and \"replica_of\" at the same time " +
+ "causes the \"fixed_ip_v4\" field to be ignored.",
+ AttributePath: path,
+ })
+ }
+ }
+
+ return diags
}
func resourceDatabaseInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
@@ -928,6 +999,18 @@ func resourceDatabaseInstanceUpdate(ctx context.Context, d *schema.ResourceData,
}
}
+ if d.HasChange("cloud_monitoring_enabled") {
+ _, new := d.GetChange("cloud_monitoring_enabled")
+ var cloudMonitoringOpts updateCloudMonitoringOpts
+ cloudMonitoringOpts.CloudMonitoring.Enable = new.(bool)
+
+ err := instanceAction(DatabaseV1Client, d.Id(), &cloudMonitoringOpts).ExtractErr()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ log.Printf("Update cloud_monitoring_enabled in vkcs_db_instance %s", d.Id())
+ }
+
return resourceDatabaseInstanceRead(ctx, d, meta)
}
diff --git a/vkcs/resource_vkcs_db_instance_test.go b/vkcs/resource_vkcs_db_instance_test.go
index c9b53104..6ed17a7e 100755
--- a/vkcs/resource_vkcs_db_instance_test.go
+++ b/vkcs/resource_vkcs_db_instance_test.go
@@ -217,10 +217,7 @@ resource "vkcs_db_instance" "basic" {
autoexpand = true
max_disk_size = 1000
}
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
`
@@ -244,15 +241,13 @@ resource "vkcs_db_instance" "basic" {
}
availability_zone = "{{.AvailabilityZone}}"
floating_ip_enabled = true
+ cloud_monitoring_enabled = true
disk_autoexpand {
autoexpand = true
max_disk_size = 2000
}
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
`
@@ -276,10 +271,7 @@ resource "vkcs_db_instance" "basic" {
uuid = vkcs_networking_network.base.id
}
root_enabled = true
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
`
@@ -319,5 +311,6 @@ resource "vkcs_db_instance" "basic" {
max_disk_size = 1000
}
+ depends_on = [vkcs_networking_router_interface.base]
}
`
diff --git a/vkcs/resource_vkcs_db_user_test.go b/vkcs/resource_vkcs_db_user_test.go
index f36d424b..fd934cd1 100755
--- a/vkcs/resource_vkcs_db_user_test.go
+++ b/vkcs/resource_vkcs_db_user_test.go
@@ -191,10 +191,7 @@ resource "vkcs_db_instance" "basic" {
uuid = vkcs_networking_network.base.id
}
availability_zone = "{{.AvailabilityZone}}"
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
resource "vkcs_db_database" "testdb1" {
@@ -236,10 +233,7 @@ resource "vkcs_db_instance" "basic" {
uuid = vkcs_networking_network.base.id
}
availability_zone = "{{.AvailabilityZone}}"
- depends_on = [
- vkcs_networking_network.base,
- vkcs_networking_subnet.base
- ]
+ depends_on = [vkcs_networking_router_interface.base]
}
resource "vkcs_db_database" "testdb1" {
diff --git a/vkcs/resource_vkcs_images_image.go b/vkcs/resource_vkcs_images_image.go
index 63b94e0d..1943b83f 100644
--- a/vkcs/resource_vkcs_images_image.go
+++ b/vkcs/resource_vkcs_images_image.go
@@ -17,6 +17,10 @@ import (
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
)
+const (
+ storeS3 = "s3"
+)
+
func resourceImagesImage() *schema.Resource {
return &schema.Resource{
CreateContext: resourceImagesImageCreate,
@@ -215,7 +219,8 @@ func resourceImagesImage() *schema.Resource {
Description: "The date the image was last updated.",
},
},
- Description: "Manages an Image resource within VKCS.\n\n~> **Note:** All arguments including the source image URL password will be stored in the raw state as plain-text. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
+ Description: "Manages an Image resource within VKCS.\n\n" +
+ "~> **Note:** All arguments including the source image URL password will be stored in the raw state as plain-text. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
}
}
@@ -231,6 +236,9 @@ func resourceImagesImageCreate(ctx context.Context, d *schema.ResourceData, meta
properties := d.Get("properties").(map[string]interface{})
imageProperties := resourceImagesImageExpandProperties(properties)
+ if !resourceImagesImageNeedsDefaultStore(imageClient.Endpoint) {
+ imageProperties["store"] = storeS3
+ }
createOpts := &images.CreateOpts{
Name: d.Get("name").(string),
diff --git a/vkcs/resource_vkcs_keymanager_secret.go b/vkcs/resource_vkcs_keymanager_secret.go
index db516f72..4fed77e5 100644
--- a/vkcs/resource_vkcs_keymanager_secret.go
+++ b/vkcs/resource_vkcs_keymanager_secret.go
@@ -182,7 +182,8 @@ func resourceKeyManagerSecret() *schema.Resource {
Description: "The map of metadata, assigned on the secret, which has been explicitly and implicitly added.",
},
},
- Description: "Manages a key secret resource within VKCS.\n\n~> **Important Security Notice** The payload of this resource will be stored *unencrypted* in your Terraform state file. **Use of this resource for production deployments is *not* recommended**. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
+ Description: "Manages a key secret resource within VKCS.\n\n" +
+ "~> **Important Security Notice** The payload of this resource will be stored *unencrypted* in your Terraform state file. **Use of this resource for production deployments is *not* recommended**. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
CustomizeDiff: customdiff.Sequence(
// Clear the diff if the source payload is base64 encoded.
diff --git a/vkcs/resource_vkcs_kubernetes_cluster.go b/vkcs/resource_vkcs_kubernetes_cluster.go
index 92508153..0be17dfe 100755
--- a/vkcs/resource_vkcs_kubernetes_cluster.go
+++ b/vkcs/resource_vkcs_kubernetes_cluster.go
@@ -127,13 +127,23 @@ func resourceKubernetesCluster() *schema.Resource {
Description: "The name of the Compute service SSH keypair. Changing this creates a new cluster.",
},
"labels": {
- Type: schema.TypeMap,
- Optional: true,
- Computed: true,
- ForceNew: true,
- Elem: &schema.Schema{Type: schema.TypeString},
- Set: schema.HashString,
- Description: "The list of optional key value pairs representing additional properties of the cluster. Changing this creates a new cluster.\n\n * `docker_registry_enabled=true` to preinstall Docker Registry.\n * `prometheus_monitoring=true` to preinstall monitoring system based on Prometheus and Grafana.\n * `ingress_controller=\"nginx\"` to preinstall NGINX Ingress Controller.",
+ Type: schema.TypeMap,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Set: schema.HashString,
+ Description: "The list of optional key value pairs representing additional properties of the cluster. Changing this creates a new cluster.\n\n" +
+ " * `calico_ipv4pool` to set subnet where pods will be created. Default 10.100.0.0/16.\n" +
+ " * `clean_volumes` to remove pvc volumes when deleting a cluster. Default False.\n" +
+ " * `cloud_monitoring` to enable cloud monitoring feature.\n" +
+ " * `docker_registry_enabled=true` to preinstall Docker Registry.\n" +
+ " * `etcd_volume_size` to set etcd volume size. Default 10Gb.\n" +
+ " * `ingress_controller=\"nginx\"` to preinstall NGINX Ingress Controller.\n" +
+ " * `kube_log_level` to set log level for kubelet in range 0 to 8.\n" +
+ " * `master_volume_size` to set master vm volume size. Default 50Gb.\n" +
+ " * `cluster_node_volume_type` to set master vm volume type. Default ceph-hdd.\n" +
+ " * `prometheus_monitoring=true` to preinstall monitoring system based on Prometheus and Grafana.\n",
},
"master_count": {
Type: schema.TypeInt,
diff --git a/vkcs/resource_vkcs_kubernetes_node_group.go b/vkcs/resource_vkcs_kubernetes_node_group.go
index ea31e95b..3eceacbc 100755
--- a/vkcs/resource_vkcs_kubernetes_node_group.go
+++ b/vkcs/resource_vkcs_kubernetes_node_group.go
@@ -160,12 +160,13 @@ func resourceKubernetesNodeGroup() *schema.Resource {
Description: "The time at which node group was created.",
},
"availability_zones": {
- Type: schema.TypeList,
- Optional: true,
- ForceNew: true,
- Computed: true,
- Elem: &schema.Schema{Type: schema.TypeString},
- Description: "The list of availability zones of the node group. Zones `MS1` and `GZ1` are available. By default, node group is being created at cluster's zone.\n**Important:** Receiving default AZ add it manually to your main.tf config to sync it with state to avoid node groups force recreation in the future.",
+ Type: schema.TypeList,
+ Optional: true,
+ ForceNew: true,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: "The list of availability zones of the node group. Zones `MS1` and `GZ1` are available. By default, node group is being created at cluster's zone.\n" +
+ "**Important:** Receiving default AZ add it manually to your main.tf config to sync it with state to avoid node groups force recreation in the future.",
},
"max_node_unavailable": {
Type: schema.TypeInt,
diff --git a/vkcs/resource_vkcs_lb_loadbalancer.go b/vkcs/resource_vkcs_lb_loadbalancer.go
index 18152f8b..0b87e5b1 100644
--- a/vkcs/resource_vkcs_lb_loadbalancer.go
+++ b/vkcs/resource_vkcs_lb_loadbalancer.go
@@ -101,8 +101,10 @@ func resourceLoadBalancer() *schema.Resource {
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
- Description: "A list of security group IDs to apply to the loadbalancer. The security groups must be specified by ID and not name (as opposed to how they are configured with the Compute Instance).",
+ Description: "A list of security group IDs to apply to the loadbalancer. The security groups must be specified by ID and not name (as opposed to how they are configured with the Compute Instance). ***Deprecated*** This argument is deprecated, please do not use it.",
+ Deprecated: "This argument is deprecated, please do not use it",
},
+
"tags": {
Type: schema.TypeSet,
Optional: true,
@@ -122,10 +124,7 @@ func resourceLoadBalancerCreate(ctx context.Context, d *schema.ResourceData, met
return diag.Errorf("Error creating VKCS loadbalancer client: %s", err)
}
- var (
- lbID string
- vipPortID string
- )
+ var lbID string
adminStateUp := d.Get("admin_state_up").(bool)
@@ -156,7 +155,6 @@ func resourceLoadBalancerCreate(ctx context.Context, d *schema.ResourceData, met
return diag.Errorf("Error creating vkcs_lb_loadbalancer: %s", err)
}
lbID = lb.ID
- vipPortID = lb.VipPortID
// Wait for load-balancer to become active before continuing.
timeout := d.Timeout(schema.TimeoutCreate)
@@ -165,16 +163,6 @@ func resourceLoadBalancerCreate(ctx context.Context, d *schema.ResourceData, met
return diag.FromErr(err)
}
- // Once the load-balancer has been created, apply any requested security groups
- // to the port that was created behind the scenes.
- networkingClient, err := config.NetworkingV2Client(getRegion(d, config), getSDN(d))
- if err != nil {
- return diag.Errorf("Error creating VKCS networking client: %s", err)
- }
- if err := resourceLoadBalancerSetSecurityGroups(networkingClient, vipPortID, d); err != nil {
- return diag.Errorf("Error setting vkcs_lb_loadbalancer security groups: %s", err)
- }
-
d.SetId(lbID)
return resourceLoadBalancerRead(ctx, d, meta)
@@ -210,7 +198,7 @@ func resourceLoadBalancerRead(ctx context.Context, d *schema.ResourceData, meta
// Get any security groups on the VIP Port.
if vipPortID != "" {
- networkingClient, err := config.NetworkingV2Client(getRegion(d, config), getSDN(d))
+ networkingClient, err := config.NetworkingV2Client(getRegion(d, config), searchInAllSDNs)
if err != nil {
return diag.Errorf("Error creating VKCS networking client: %s", err)
}
@@ -285,18 +273,6 @@ func resourceLoadBalancerUpdate(ctx context.Context, d *schema.ResourceData, met
}
}
- // Security Groups get updated separately.
- if d.HasChange("security_group_ids") {
- networkingClient, err := config.NetworkingV2Client(getRegion(d, config), getSDN(d))
- if err != nil {
- return diag.Errorf("Error creating VKCS networking client: %s", err)
- }
- vipPortID := d.Get("vip_port_id").(string)
- if err := resourceLoadBalancerSetSecurityGroups(networkingClient, vipPortID, d); err != nil {
- return diag.Errorf("Error setting vkcs_lb_loadbalancer security groups: %s", err)
- }
- }
-
return resourceLoadBalancerRead(ctx, d, meta)
}
diff --git a/vkcs/resource_vkcs_lb_loadbalancer_test.go b/vkcs/resource_vkcs_lb_loadbalancer_test.go
index 4c1a1ff1..88b4bf07 100644
--- a/vkcs/resource_vkcs_lb_loadbalancer_test.go
+++ b/vkcs/resource_vkcs_lb_loadbalancer_test.go
@@ -9,7 +9,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
)
@@ -42,49 +41,6 @@ func TestAccLBLoadBalancer_basic(t *testing.T) {
})
}
-func TestAccLBLoadBalancer_secGroup(t *testing.T) {
- var lb loadbalancers.LoadBalancer
- var sg1, sg2 groups.SecGroup
-
- resource.Test(t, resource.TestCase{
- ProviderFactories: testAccProviders,
- CheckDestroy: testAccCheckLBLoadBalancerDestroy,
- Steps: []resource.TestStep{
- {
- Config: testAccLbLoadBalancerSecGroup,
- Check: resource.ComposeTestCheckFunc(
- testAccCheckLBLoadBalancerExists("vkcs_lb_loadbalancer.loadbalancer_1", &lb),
- testAccCheckNetworkingSecGroupExists("vkcs_networking_secgroup.secgroup_1", &sg1),
- testAccCheckNetworkingSecGroupExists("vkcs_networking_secgroup.secgroup_1", &sg2),
- resource.TestCheckResourceAttr("vkcs_lb_loadbalancer.loadbalancer_1", "security_group_ids.#", "1"),
- testAccCheckLBLoadBalancerHasSecGroup(&lb, &sg1),
- ),
- },
- {
- Config: testAccLbLoadBalancerSecGroupUpdate1,
- Check: resource.ComposeTestCheckFunc(
- testAccCheckLBLoadBalancerExists("vkcs_lb_loadbalancer.loadbalancer_1", &lb),
- testAccCheckNetworkingSecGroupExists("vkcs_networking_secgroup.secgroup_2", &sg1),
- testAccCheckNetworkingSecGroupExists("vkcs_networking_secgroup.secgroup_2", &sg2),
- resource.TestCheckResourceAttr("vkcs_lb_loadbalancer.loadbalancer_1", "security_group_ids.#", "2"),
- testAccCheckLBLoadBalancerHasSecGroup(&lb, &sg1),
- testAccCheckLBLoadBalancerHasSecGroup(&lb, &sg2),
- ),
- },
- {
- Config: testAccLbLoadBalancerSecGroupUpdate2,
- Check: resource.ComposeTestCheckFunc(
- testAccCheckLBLoadBalancerExists("vkcs_lb_loadbalancer.loadbalancer_1", &lb),
- testAccCheckNetworkingSecGroupExists("vkcs_networking_secgroup.secgroup_2", &sg1),
- testAccCheckNetworkingSecGroupExists("vkcs_networking_secgroup.secgroup_2", &sg2),
- resource.TestCheckResourceAttr("vkcs_lb_loadbalancer.loadbalancer_1", "security_group_ids.#", "1"),
- testAccCheckLBLoadBalancerHasSecGroup(&lb, &sg2),
- ),
- },
- },
- })
-}
-
func TestAccLBLoadBalancer_vip_network(t *testing.T) {
var lb loadbalancers.LoadBalancer
@@ -245,29 +201,6 @@ func testAccCheckLBLoadBalancerTagCount(n string, expected int) resource.TestChe
}
}
-func testAccCheckLBLoadBalancerHasSecGroup(lb *loadbalancers.LoadBalancer, sg *groups.SecGroup) resource.TestCheckFunc {
- return func(s *terraform.State) error {
- config := testAccProvider.Meta().(*config)
- networkingClient, err := config.NetworkingV2Client(osRegionName, defaultSDN)
- if err != nil {
- return fmt.Errorf("Error creating VKCS networking client: %s", err)
- }
-
- port, err := ports.Get(networkingClient, lb.VipPortID).Extract()
- if err != nil {
- return err
- }
-
- for _, p := range port.SecurityGroups {
- if p == sg.ID {
- return nil
- }
- }
-
- return fmt.Errorf("LoadBalancer does not have the security group")
- }
-}
-
const testAccLbLoadBalancerConfigBasic = `
resource "vkcs_networking_network" "network_1" {
name = "network_1"
@@ -317,119 +250,6 @@ const testAccLbLoadBalancerConfigUpdate = `
}
}`
-const testAccLbLoadBalancerSecGroup = `
-resource "vkcs_networking_secgroup" "secgroup_1" {
- name = "secgroup_1"
- description = "secgroup_1"
-}
-
-resource "vkcs_networking_secgroup" "secgroup_2" {
- name = "secgroup_2"
- description = "secgroup_2"
-}
-
-resource "vkcs_networking_network" "network_1" {
- name = "network_1"
- admin_state_up = "true"
-}
-
-resource "vkcs_networking_subnet" "subnet_1" {
- name = "subnet_1"
- network_id = vkcs_networking_network.network_1.id
- cidr = "192.168.199.0/24"
-}
-
-resource "vkcs_lb_loadbalancer" "loadbalancer_1" {
- name = "loadbalancer_1"
- vip_subnet_id = vkcs_networking_subnet.subnet_1.id
- security_group_ids = [
- vkcs_networking_secgroup.secgroup_1.id
- ]
-
- timeouts {
- create = "15m"
- update = "15m"
- delete = "15m"
- }
-}
-`
-
-const testAccLbLoadBalancerSecGroupUpdate1 = `
-resource "vkcs_networking_secgroup" "secgroup_1" {
- name = "secgroup_1"
- description = "secgroup_1"
-}
-
-resource "vkcs_networking_secgroup" "secgroup_2" {
- name = "secgroup_2"
- description = "secgroup_2"
-}
-
-resource "vkcs_networking_network" "network_1" {
- name = "network_1"
- admin_state_up = "true"
-}
-
-resource "vkcs_networking_subnet" "subnet_1" {
- name = "subnet_1"
- network_id = vkcs_networking_network.network_1.id
- cidr = "192.168.199.0/24"
-}
-
-resource "vkcs_lb_loadbalancer" "loadbalancer_1" {
- name = "loadbalancer_1"
- vip_subnet_id = vkcs_networking_subnet.subnet_1.id
- security_group_ids = [
- vkcs_networking_secgroup.secgroup_1.id,
- vkcs_networking_secgroup.secgroup_2.id
- ]
-
- timeouts {
- create = "15m"
- update = "15m"
- delete = "15m"
- }
-}
-`
-
-const testAccLbLoadBalancerSecGroupUpdate2 = `
-resource "vkcs_networking_secgroup" "secgroup_1" {
- name = "secgroup_1"
- description = "secgroup_1"
-}
-
-resource "vkcs_networking_secgroup" "secgroup_2" {
- name = "secgroup_2"
- description = "secgroup_2"
-}
-
-resource "vkcs_networking_network" "network_1" {
- name = "network_1"
- admin_state_up = "true"
-}
-
-resource "vkcs_networking_subnet" "subnet_1" {
- name = "subnet_1"
- network_id = vkcs_networking_network.network_1.id
- cidr = "192.168.199.0/24"
-}
-
-resource "vkcs_lb_loadbalancer" "loadbalancer_1" {
- name = "loadbalancer_1"
- vip_subnet_id = vkcs_networking_subnet.subnet_1.id
- security_group_ids = [
- vkcs_networking_secgroup.secgroup_2.id
- ]
- depends_on = ["vkcs_networking_secgroup.secgroup_1"]
-
- timeouts {
- create = "15m"
- update = "15m"
- delete = "15m"
- }
-}
-`
-
const testAccLbLoadBalancerConfigVIPNetwork = `
resource "vkcs_networking_network" "network_1" {
name = "network_1"
diff --git a/vkcs/resource_vkcs_networking_port_secgroup_associate.go b/vkcs/resource_vkcs_networking_port_secgroup_associate.go
index 3b4bdd6d..2de606ee 100644
--- a/vkcs/resource_vkcs_networking_port_secgroup_associate.go
+++ b/vkcs/resource_vkcs_networking_port_secgroup_associate.go
@@ -66,7 +66,8 @@ func resourceNetworkingPortSecGroupAssociate() *schema.Resource {
Description: "SDN to use for this resource. Must be one of following: \"neutron\", \"sprut\". Default value is \"neutron\".",
},
},
- Description: "Manages a port's security groups within VKCS. Useful, when the port was created not by Terraform. It should not be used, when the port was created directly within Terraform.\n\nWhen the resource is deleted, Terraform doesn't delete the port, but unsets the list of user defined security group IDs. However, if `enforce` is set to `true` and the resource is deleted, Terraform will remove all assigned security group IDs.",
+ Description: "Manages a port's security groups within VKCS. Useful, when the port was created not by Terraform. It should not be used, when the port was created directly within Terraform.\n\n" +
+ "When the resource is deleted, Terraform doesn't delete the port, but unsets the list of user defined security group IDs. However, if `enforce` is set to `true` and the resource is deleted, Terraform will remove all assigned security group IDs.",
}
}
diff --git a/vkcs/resource_vkcs_networking_secgroup_rule.go b/vkcs/resource_vkcs_networking_secgroup_rule.go
index 7be2c360..dd84c382 100644
--- a/vkcs/resource_vkcs_networking_secgroup_rule.go
+++ b/vkcs/resource_vkcs_networking_secgroup_rule.go
@@ -78,11 +78,26 @@ func resourceNetworkingSecGroupRule() *schema.Resource {
},
"protocol": {
- Type: schema.TypeString,
- Optional: true,
- ForceNew: true,
- Computed: true,
- Description: "The layer 4 protocol type, valid values are following. Changing this creates a new security group rule. This is required if you want to specify a port range.\n * __tcp__\n * __udp__\n * __icmp__\n * __ah__\n * __dccp__\n * __egp__\n * __esp__\n * __gre__\n * __igmp__\n * __ospf__\n * __pgm__\n * __rsvp__\n * __sctp__\n * __udplite__\n * __vrrp__",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Computed: true,
+ Description: "The layer 4 protocol type, valid values are following. Changing this creates a new security group rule. This is required if you want to specify a port range.\n" +
+ " * __tcp__\n" +
+ " * __udp__\n" +
+ " * __icmp__\n" +
+ " * __ah__\n" +
+ " * __dccp__\n" +
+ " * __egp__\n" +
+ " * __esp__\n" +
+ " * __gre__\n" +
+ " * __igmp__\n" +
+ " * __ospf__\n" +
+ " * __pgm__\n" +
+ " * __rsvp__\n" +
+ " * __sctp__\n" +
+ " * __udplite__\n" +
+ " * __vrrp__",
},
"remote_group_id": {
diff --git a/vkcs/resource_vkcs_publicdns_record.go b/vkcs/resource_vkcs_publicdns_record.go
new file mode 100644
index 00000000..37111fd8
--- /dev/null
+++ b/vkcs/resource_vkcs_publicdns_record.go
@@ -0,0 +1,502 @@
+package vkcs
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "log"
+ "strings"
+ "text/template"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+ "github.com/mitchellh/mapstructure"
+)
+
+const (
+ recordDelay = 10 * time.Second
+ recordMinTimeout = 3 * time.Second
+ recordCreateTimeout = 10 * time.Minute
+ recordDeleteTimeout = 10 * time.Minute
+)
+
+const (
+ recordStatusActive = "active"
+ recordStatusDeleted = "deleted"
+)
+
+const (
+ recordTypeA = "A"
+ recordTypeAAAA = "AAAA"
+ recordTypeCNAME = "CNAME"
+ recordTypeMX = "MX"
+ recordTypeNS = "NS"
+ recordTypeSRV = "SRV"
+ recordTypeTXT = "TXT"
+)
+
+var (
+ recordTypeSharedArgs = [5]string{"region", "zone_id", "type", "name", "ttl"}
+ recordTypeAArgs = [1]string{"ip"}
+ recordTypeAAAAArgs = [1]string{"ip"}
+ recordTypeCNAMEArgs = [2]string{"name", "content"}
+ recordTypeMXArgs = [2]string{"priority", "content"}
+ recordTypeNSArgs = [1]string{"content"}
+ recordTypeSRVArgs = [6]string{"service", "proto", "priority", "weight", "host", "port"}
+ recordTypeTXTArgs = [1]string{"content"}
+)
+
+func resourcePublicDNSRecord() *schema.Resource {
+ return &schema.Resource{
+ CustomizeDiff: resourcePublicDNSRecordCustomizeDiff,
+
+ CreateContext: resourcePublicDNSRecordCreate,
+ ReadContext: resourcePublicDNSRecordRead,
+ UpdateContext: resourcePublicDNSRecordUpdate,
+ DeleteContext: resourcePublicDNSRecordDelete,
+ Importer: &schema.ResourceImporter{
+ StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
+ zoneID, recordType, recordID, err := publicDNSRecordParseID(d.Id())
+ if err != nil {
+ return nil, err
+ }
+
+ recordType = strings.ToUpper(recordType)
+ d.Set("zone_id", zoneID)
+ d.Set("type", recordType)
+ d.SetId(recordID)
+
+ return []*schema.ResourceData{d}, nil
+ },
+ },
+
+ Timeouts: &schema.ResourceTimeout{
+ Create: schema.DefaultTimeout(recordCreateTimeout),
+ Delete: schema.DefaultTimeout(recordDeleteTimeout),
+ },
+
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ Description: "The region in which to obtain the V2 Public DNS client. If omitted, the `region` argument of the provider is used. Changing this creates a new record.",
+ },
+
+ "zone_id": {
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ Description: "The ID of the zone to attach the record to.",
+ },
+
+ "type": {
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ ValidateFunc: validation.StringInSlice([]string{
+ recordTypeA,
+ recordTypeAAAA,
+ recordTypeCNAME,
+ recordTypeMX,
+ recordTypeNS,
+ recordTypeSRV,
+ recordTypeTXT,
+ }, false),
+ Description: "The type of the record. Must be one of following: \"A\", \"AAAA\", \"CNAME\", \"MX\", \"NS\", \"SRV\", \"TXT\".",
+ },
+
+ "name": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The name of the record.",
+ },
+
+ "ip": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The IP address of the record. It should be IPv4 for record of type \"A\" and IPv6 for record of type \"AAAA\".",
+ },
+
+ "content": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The content of the record.",
+ },
+
+ "priority": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The priority of the record's server.",
+ },
+
+ "weight": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The relative weight of the record's server.",
+ },
+
+ "service": {
+ Type: schema.TypeString,
+ Optional: true,
+ Description: "The name of the desired service.",
+ },
+
+ "proto": {
+ Type: schema.TypeString,
+ Optional: true,
+ Description: "The name of the desired protocol.",
+ },
+
+ "host": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The domain name of the target host.",
+ },
+
+ "port": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The port on the target host of the service.",
+ },
+
+ "ttl": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The time to live of the record.",
+ },
+
+ // Computed values
+ "full_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The full name of the SRV record.",
+ },
+ },
+ Description: resourcePublicDNSRecordDescription(),
+ }
+}
+
+func resourcePublicDNSRecordDescription() string {
+ var templ = `Manages a public DNS zone record resource within VKCS. **New since v.0.2.0**.
+**Note:** Although some arguments are marked as optional, it is actually required to set values for them depending on record \"type\". Use this map to get information about which arguments you have to set:
+
+| Record type | Required arguments |
+| ----------- | ------------------ |
+{{range $k, $v := .}}| {{$k}} | {{join $v ", "}} |
+{{end}}
+
+`
+ t := template.Must(template.New("").Funcs(template.FuncMap{"join": strings.Join}).Parse(templ))
+ args := getPublicDNSRecordArgsMap()
+ buf := &bytes.Buffer{}
+ _ = t.Execute(buf, args)
+ return buf.String()
+}
+
+func resourcePublicDNSRecordCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ zoneID := d.Get("zone_id").(string)
+ recordType := d.Get("type").(string)
+
+ var createOpts optsBuilder
+ switch recordType {
+ case recordTypeA:
+ createOpts = recordACreateOpts{}
+ case recordTypeAAAA:
+ createOpts = recordAAAACreateOpts{}
+ case recordTypeCNAME:
+ createOpts = recordCNAMECreateOpts{}
+ case recordTypeMX:
+ createOpts = recordMXCreateOpts{}
+ case recordTypeNS:
+ createOpts = recordNSCreateOpts{}
+ case recordTypeSRV:
+ createOpts = recordSRVCreateOpts{}
+ case recordTypeTXT:
+ createOpts = recordTXTCreateOpts{}
+ }
+
+ m := publicDNSRecordResourceDataMap(d)
+ if err = mapstructure.Decode(m, &createOpts); err != nil {
+ return diag.Errorf("Error retrieving VKCS public DNS record create options: %s", err)
+ }
+
+ log.Printf("[DEBUG] vkcs_publicdns_record create options: zone_id: %s, type: %s, opts: %#v",
+ zoneID, recordType, createOpts)
+
+ res := recordCreate(client, zoneID, createOpts, recordType)
+ r, err := publicDNSRecordExtract(res, recordType)
+ if err != nil {
+ return diag.Errorf("Error creating vkcs_publicdns_record: %s", err)
+ }
+
+ record, err := structToMap(r)
+ if err != nil {
+ return diag.Errorf("Error creating vkcs_publicdns_record: %s", err)
+ }
+
+ d.SetId(record["uuid"].(string))
+ log.Printf("[DEBUG] Created vkcs_publicdns_record %#v", record)
+
+ return resourcePublicDNSRecordRead(ctx, d, meta)
+}
+
+func resourcePublicDNSRecordRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ zoneID := d.Get("zone_id").(string)
+ recordType := d.Get("type").(string)
+
+ res := recordGet(client, zoneID, d.Id(), recordType)
+ r, err := publicDNSRecordExtract(res, recordType)
+
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err, "Error retrieving vkcs_publicdns_record"))
+ }
+
+ record, err := structToMap(r)
+ if err != nil {
+ return diag.Errorf("Error retrieving vkcs_publicdns_record: %s", err)
+ }
+
+ log.Printf("[DEBUG] Retrieved vkcs_publicdns_record %s: %#v", d.Id(), record)
+
+ zoneID, err = publicDNSRecordParseZoneID(record["dns"].(string))
+ if err != nil {
+ return diag.Errorf("Error retrieving vkcs_publicdns_record: %s", err)
+ }
+
+ d.Set("zone_id", zoneID)
+
+ if recordType == recordTypeSRV {
+ fullN := record["name"].(string)
+ d.Set("full_name", fullN)
+
+ n, err := extractPublicDNSRecordSRVName(fullN)
+ if err != nil {
+ return diag.Errorf("Error retrieving vkcs_publicdns_record: %s", err)
+ }
+ d.Set("name", n)
+ } else {
+ d.Set("name", record["name"].(string))
+ }
+
+ switch recordType {
+ case recordTypeA:
+ d.Set("ip", record["ipv4"].(string))
+ case recordTypeAAAA:
+ d.Set("ip", record["ipv6"].(string))
+ case recordTypeCNAME, recordTypeNS, recordTypeTXT:
+ d.Set("content", record["content"].(string))
+ case recordTypeMX:
+ d.Set("priority", record["priority"].(int))
+ d.Set("content", record["content"].(string))
+ case recordTypeSRV:
+ d.Set("priority", record["priority"].(int))
+ d.Set("weight", record["weight"].(int))
+ d.Set("host", record["host"].(string))
+ d.Set("port", record["port"].(int))
+ }
+
+ d.Set("ttl", record["ttl"].(int))
+
+ return nil
+}
+
+func resourcePublicDNSRecordUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ zoneID := d.Get("zone_id").(string)
+ recordType := d.Get("type").(string)
+
+ var updateOpts optsBuilder
+ switch recordType {
+ case recordTypeA:
+ updateOpts = recordAUpdateOpts{}
+ case recordTypeAAAA:
+ updateOpts = recordAAAAUpdateOpts{}
+ case recordTypeCNAME:
+ updateOpts = recordCNAMEUpdateOpts{}
+ case recordTypeMX:
+ updateOpts = recordMXUpdateOpts{}
+ case recordTypeNS:
+ updateOpts = recordNSUpdateOpts{}
+ case recordTypeSRV:
+ updateOpts = recordSRVUpdateOpts{}
+ case recordTypeTXT:
+ updateOpts = recordTXTUpdateOpts{}
+ }
+
+ m := publicDNSRecordResourceDataMap(d)
+ if err = mapstructure.Decode(m, &updateOpts); err != nil {
+ return diag.Errorf("Error retrieving VKCS public DNS record update options: %s", err)
+ }
+
+ log.Printf("[DEBUG] vkcs_publicdns_record update options: zone_id: %s, type: %s, opts: %#v",
+ zoneID, recordType, updateOpts)
+
+ res := recordUpdate(client, zoneID, d.Id(), updateOpts, recordType)
+ _, err = publicDNSRecordExtract(res, recordType)
+
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err, "Error updating vkcs_publicdns_record"))
+ }
+
+ return resourcePublicDNSRecordRead(ctx, d, meta)
+}
+
+func resourcePublicDNSRecordDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ zoneID := d.Get("zone_id").(string)
+ recordType := d.Get("type").(string)
+
+ err = recordDelete(client, zoneID, d.Id(), recordType).ExtractErr()
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err,
+ fmt.Sprintf("Error deleting vkcs_publicdns_record: zone_id: %s, type: %s, id:", zoneID, recordType)))
+ }
+
+ stateConf := &resource.StateChangeConf{
+ Pending: []string{recordStatusActive},
+ Target: []string{recordStatusDeleted},
+ Refresh: publicDNSRecordStateRefreshFunc(client, zoneID, d.Id(), recordType),
+ Timeout: d.Timeout(schema.TimeoutCreate),
+ Delay: recordDelay,
+ MinTimeout: recordMinTimeout,
+ }
+
+ _, err = stateConf.WaitForStateContext(ctx)
+ if err != nil {
+ return diag.Errorf("Error waiting for vkcs_publicdns_record %s to become deleted: %s", d.Id(), err)
+ }
+
+ return nil
+}
+
+func resourcePublicDNSRecordCustomizeDiff(ctx context.Context, diff *schema.ResourceDiff, v interface{}) error {
+ recordType := diff.Get("type").(string)
+
+ args := getPublicDNSRecordArgs(recordType)
+
+ var changedArgs []string
+ for k := range diff.GetRawPlan().AsValueMap() {
+ if diff.HasChange(k) {
+ changedArgs = append(changedArgs, k)
+ }
+ }
+
+OuterLoop:
+ for _, k := range changedArgs {
+ for _, ak := range args {
+ if k == ak {
+ continue OuterLoop
+ }
+ }
+ return fmt.Errorf("\"%s\" is not supported for records of type \"%s\", supported args are: %v", k, recordType, args)
+ }
+
+ if recordType == recordTypeSRV {
+ diff.SetNew("full_name", extractPublicDNSRecordSRVFullName(diff))
+ }
+
+ return nil
+}
+
+func extractPublicDNSRecordSRVName(fullName string) (string, error) {
+ parts := strings.SplitN(fullName, ".", 3)
+ if len(parts) == 3 {
+ return parts[2], nil
+ }
+ if len(parts) == 2 {
+ return "", nil
+ }
+ return "", fmt.Errorf("error extracting SRV record name from %s", fullName)
+}
+
+func extractPublicDNSRecordSRVFullName(diff *schema.ResourceDiff) string {
+ s := diff.Get("service").(string)
+ p := diff.Get("proto").(string)
+ n := fmt.Sprintf("%s.%s", s, p)
+
+ if v, ok := diff.GetOk("name"); ok {
+ n += fmt.Sprintf(".%s", v.(string))
+ }
+
+ return n
+}
+
+func getPublicDNSRecordArgs(recordType string) []string {
+ argsMap := getPublicDNSRecordArgsMap()
+ var args []string
+ args = append(args, recordTypeSharedArgs[:]...)
+ args = append(args, argsMap[recordType]...)
+ return args
+}
+
+func getPublicDNSRecordArgsMap() map[string][]string {
+ return map[string][]string{
+ recordTypeA: recordTypeAArgs[:],
+ recordTypeAAAA: recordTypeAAAAArgs[:],
+ recordTypeCNAME: recordTypeCNAMEArgs[:],
+ recordTypeMX: recordTypeMXArgs[:],
+ recordTypeNS: recordTypeNSArgs[:],
+ recordTypeSRV: recordTypeSRVArgs[:],
+ recordTypeTXT: recordTypeTXTArgs[:],
+ }
+}
+
+func publicDNSRecordResourceDataMap(d *schema.ResourceData) map[string]interface{} {
+ recordType := d.Get("type").(string)
+
+ m := map[string]interface{}{
+ "content": d.Get("content"),
+ "priority": d.Get("priority"),
+ "weight": d.Get("weight"),
+ "host": d.Get("host"),
+ "port": d.Get("port"),
+ "ttl": d.Get("ttl"),
+ }
+ if recordType == recordTypeSRV {
+ m["name"] = d.Get("full_name")
+ } else {
+ m["name"] = d.Get("name")
+ }
+ if recordType == recordTypeA {
+ m["ipv4"] = d.Get("ip")
+ } else if recordType == recordTypeAAAA {
+ m["ipv6"] = d.Get("ip")
+ }
+
+ return m
+}
diff --git a/vkcs/resource_vkcs_publicdns_record_test.go b/vkcs/resource_vkcs_publicdns_record_test.go
new file mode 100644
index 00000000..cb68f741
--- /dev/null
+++ b/vkcs/resource_vkcs_publicdns_record_test.go
@@ -0,0 +1,256 @@
+package vkcs
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+)
+
+func TestAccPublicDNSRecord_basic(t *testing.T) {
+ var z zone
+ var r map[string]interface{}
+ zoneName := fmt.Sprintf("vkcs-tf-acctest-%s.com", acctest.RandString(5))
+
+ resource.Test(t, resource.TestCase{
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckPublicDNSRecordDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfigWithZone(testAccPublicDNSRecordConfigBasic, zoneName),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckPublicDNSZoneExists("vkcs_publicdns_zone.zone_1", &z),
+ testAccCheckPublicDNSRecordExists("vkcs_publicdns_record.record_a", &r),
+ resource.TestCheckResourceAttrPtr("vkcs_publicdns_record.record_a", "zone_id", &z.ID),
+ resource.TestCheckResourceAttr("vkcs_publicdns_record.record_a", "ip", "8.8.8.8"),
+ resource.TestCheckResourceAttr("vkcs_publicdns_record.record_a", "ttl", "60"),
+ resource.TestCheckResourceAttr("vkcs_publicdns_record.record_srv", "full_name", "_sip._udp"),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccPublicDNSRecord_update(t *testing.T) {
+ zoneName := fmt.Sprintf("vkcs-tf-acctest-%s.com", acctest.RandString(5))
+
+ resource.Test(t, resource.TestCase{
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckPublicDNSRecordDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfigWithZone(testAccPublicDNSRecordConfigBasic, zoneName),
+ },
+ {
+ Config: testAccRenderConfigWithZone(testAccPublicDNSRecordConfigUpdate, zoneName),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("vkcs_publicdns_record.record_a", "type", "AAAA"),
+ resource.TestCheckResourceAttr("vkcs_publicdns_record.record_a", "ip", "2001:0DB8:AA10:0001:0000:0000:0000:00FB"),
+ resource.TestCheckResourceAttr("vkcs_publicdns_record.record_a", "ttl", "86400"),
+ resource.TestCheckResourceAttr("vkcs_publicdns_record.record_srv", "full_name", "_sip._tcp.test"),
+ ),
+ },
+ },
+ })
+}
+
+func testAccCheckPublicDNSRecordDestroy(s *terraform.State) error {
+ config := testAccProvider.Meta().(*config)
+ client, err := config.PublicDNSV2Client(osRegionName)
+ if err != nil {
+ return fmt.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ for _, rs := range s.RootModule().Resources {
+ if rs.Type != "vkcs_publicdns_record" {
+ continue
+ }
+
+ zoneID := rs.Primary.Attributes["zone_id"]
+ recordType := rs.Primary.Attributes["type"]
+ res := recordGet(client, zoneID, rs.Primary.ID, recordType)
+ _, err := publicDNSRecordExtract(res, recordType)
+ if err == nil {
+ return fmt.Errorf("Record still exists: %s", rs.Primary.ID)
+ }
+ }
+
+ return nil
+}
+
+func testAccCheckPublicDNSRecordExists(n string, r *map[string]interface{}) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ rs, ok := s.RootModule().Resources[n]
+ if !ok {
+ return fmt.Errorf("Not found: %s", n)
+ }
+
+ if rs.Primary.ID == "" {
+ return fmt.Errorf("No ID is set")
+ }
+
+ config := testAccProvider.Meta().(*config)
+ client, err := config.PublicDNSV2Client(osRegionName)
+ if err != nil {
+ return fmt.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ zoneID := rs.Primary.Attributes["zone_id"]
+ recordType := rs.Primary.Attributes["type"]
+ res := recordGet(client, zoneID, rs.Primary.ID, recordType)
+
+ record, err := publicDNSRecordExtract(res, recordType)
+ if err != nil {
+ return err
+ }
+
+ found, err := structToMap(record)
+ if err != nil {
+ return err
+ }
+
+ if found["uuid"] != rs.Primary.ID {
+ return fmt.Errorf("Record not found")
+ }
+
+ *r = found
+
+ return nil
+ }
+}
+
+const testAccPublicDNSRecordConfigBasic = `
+resource "vkcs_publicdns_zone" "zone_1" {
+ primary_dns = "ns1.mcs.mail.ru"
+ admin_email = "admin@example.com"
+ expire = 3600000
+ zone = "{{.ZoneName}}"
+}
+
+resource "vkcs_publicdns_record" "record_a" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "A"
+ name = "test"
+ ip = "8.8.8.8"
+ ttl = 60
+}
+
+resource "vkcs_publicdns_record" "record_aaaa" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "AAAA"
+ name = "test"
+ ip = "2001:0DB8:AA10:0001:0000:0000:0000:00FB"
+ ttl = 86400
+}
+
+resource "vkcs_publicdns_record" "record_cname" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "CNAME"
+ name = "alias"
+ content = "example.com"
+}
+
+resource "vkcs_publicdns_record" "record_mx" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "MX"
+ name = "@"
+ priority = 10
+ content = "mx.example.com"
+}
+
+resource "vkcs_publicdns_record" "record_ns" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "NS"
+ name = "@"
+ content = "ns1.example.com"
+}
+
+resource "vkcs_publicdns_record" "record_srv" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "SRV"
+ service = "_sip"
+ proto = "_udp"
+ priority = 10
+ name = ""
+ weight = 5
+ host = "example.com"
+ port = 5060
+ ttl = 86400
+}
+
+resource "vkcs_publicdns_record" "record_txt" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "TXT"
+ name = ""
+ content = "Example"
+}
+`
+
+const testAccPublicDNSRecordConfigUpdate = `
+resource "vkcs_publicdns_zone" "zone_1" {
+ primary_dns = "ns1.mcs.mail.ru"
+ admin_email = "admin@example.com"
+ expire = 3600000
+ zone = "{{.ZoneName}}"
+}
+
+resource "vkcs_publicdns_record" "record_a" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "AAAA"
+ name = "test"
+ ip = "2001:0DB8:AA10:0001:0000:0000:0000:00FB"
+ ttl = 86400
+}
+
+resource "vkcs_publicdns_record" "record_aaaa" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "A"
+ name = "test"
+ ip = "8.8.8.8"
+ ttl = 86400
+}
+
+resource "vkcs_publicdns_record" "record_cname" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "CNAME"
+ name = ""
+ content = "new-example.com"
+}
+
+resource "vkcs_publicdns_record" "record_mx" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "MX"
+ name = "@"
+ priority = 20
+ content = "mx.example.com"
+}
+
+resource "vkcs_publicdns_record" "record_ns" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "NS"
+ name = "@"
+ content = "ns2.example.com"
+}
+
+resource "vkcs_publicdns_record" "record_srv" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "SRV"
+ service = "_sip"
+ proto = "_tcp"
+ priority = 20
+ weight = 1
+ name = "test"
+ host = "new-example.com"
+ port = 5061
+ ttl = 3600
+}
+
+resource "vkcs_publicdns_record" "record_txt" {
+ zone_id = vkcs_publicdns_zone.zone_1.id
+ type = "TXT"
+ name = "test"
+ content = "New example"
+}
+`
diff --git a/vkcs/resource_vkcs_publicdns_zone.go b/vkcs/resource_vkcs_publicdns_zone.go
new file mode 100644
index 00000000..4be481dd
--- /dev/null
+++ b/vkcs/resource_vkcs_publicdns_zone.go
@@ -0,0 +1,226 @@
+package vkcs
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+const (
+ zoneDelay = 10 * time.Second
+ zoneMinTimeout = 3 * time.Second
+ zoneCreateTimeout = 10 * time.Minute
+ zoneDeleteTimeout = 10 * time.Minute
+)
+
+const (
+ zoneStatusActive = "active"
+ zoneStatusDeleted = "deleted"
+)
+
+func resourcePublicDNSZone() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourcePublicDNSZoneCreate,
+ ReadContext: resourcePublicDNSZoneRead,
+ UpdateContext: resourcePublicDNSZoneUpdate,
+ DeleteContext: resourcePublicDNSZoneDelete,
+ Importer: &schema.ResourceImporter{
+ StateContext: schema.ImportStatePassthroughContext,
+ },
+
+ Timeouts: &schema.ResourceTimeout{
+ Create: schema.DefaultTimeout(zoneCreateTimeout),
+ Delete: schema.DefaultTimeout(zoneDeleteTimeout),
+ },
+
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ Description: "The region in which to obtain the V2 Public DNS client. If omitted, the `region` argument of the provider is used. Changing this creates a new zone.",
+ },
+
+ "zone": {
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ Description: "The name of the zone. **Changes this creates a new zone**.",
+ },
+
+ "primary_dns": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: "The primary DNS of the zone SOA.",
+ },
+
+ "admin_email": {
+ Type: schema.TypeString,
+ Optional: true,
+ Description: "The admin email of the zone SOA.",
+ },
+
+ "serial": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: "The serial number of the zone SOA.",
+ },
+
+ "refresh": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The refresh time of the zone SOA.",
+ },
+
+ "retry": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The retry time of the zone SOA.",
+ },
+
+ "expire": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The expire time of the zone SOA.",
+ },
+
+ "ttl": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ Description: "The TTL (time to live) of the zone SOA.",
+ },
+
+ "status": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The status of the zone.",
+ },
+ },
+ Description: "Manages a public DNS record resource within VKCS. **New since v.0.2.0**.",
+ }
+}
+
+func resourcePublicDNSZoneCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ createOpts := zoneCreateOpts{
+ PrimaryDNS: d.Get("primary_dns").(string),
+ AdminEmail: d.Get("admin_email").(string),
+ Refresh: d.Get("refresh").(int),
+ Retry: d.Get("retry").(int),
+ Expire: d.Get("expire").(int),
+ TTL: d.Get("ttl").(int),
+ Zone: d.Get("zone").(string),
+ }
+
+ log.Printf("[DEBUG] vkcs_publicdns_zone create options: %#v", createOpts)
+
+ zone, err := zoneCreate(client, createOpts).Extract()
+ if err != nil {
+ return diag.FromErr(checkAlreadyExists(err, "Error creating vkcs_publicdns_zone",
+ "vkcs_publicdns_zone", fmt.Sprintf("\"zone\" = %s", createOpts.Zone)))
+ }
+
+ d.SetId(zone.ID)
+ log.Printf("[DEBUG] Created vkcs_publicdns_zone %s: %#v", zone.ID, zone)
+
+ return resourcePublicDNSZoneRead(ctx, d, meta)
+}
+
+func resourcePublicDNSZoneRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ zone, err := zoneGet(client, d.Id()).Extract()
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err, "Error retrieving vkcs_publicdns_zone"))
+ }
+
+ log.Printf("[DEBUG] Retrieved vkcs_publicdns_zone %s: %#v", d.Id(), zone)
+
+ d.Set("region", getRegion(d, config))
+ d.Set("zone", zone.Zone)
+ d.Set("primary_dns", zone.PrimaryDNS)
+ d.Set("admin_email", zone.AdminEmail)
+ d.Set("serial", zone.Serial)
+ d.Set("refresh", zone.Refresh)
+ d.Set("retry", zone.Retry)
+ d.Set("expire", zone.Expire)
+ d.Set("ttl", zone.TTL)
+ d.Set("status", zone.Status)
+
+ return nil
+}
+
+func resourcePublicDNSZoneUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ updateOpts := zoneUpdateOpts{
+ PrimaryDNS: d.Get("primary_dns").(string),
+ AdminEmail: d.Get("admin_email").(string),
+ Refresh: d.Get("refresh").(int),
+ Retry: d.Get("retry").(int),
+ Expire: d.Get("expire").(int),
+ TTL: d.Get("ttl").(int),
+ }
+
+ log.Printf("[DEBUG] vkcs_publicdns_zone create options: %#v", updateOpts)
+
+ _, err = zoneUpdate(client, d.Id(), updateOpts).Extract()
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err, "Error updating vkcs_publicdns_zone"))
+ }
+
+ return resourcePublicDNSZoneRead(ctx, d, meta)
+}
+
+func resourcePublicDNSZoneDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ config := meta.(configer)
+ client, err := config.PublicDNSV2Client(getRegion(d, config))
+ if err != nil {
+ return diag.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ err = zoneDelete(client, d.Id()).ExtractErr()
+ if err != nil {
+ return diag.FromErr(checkDeleted(d, err, "Error deleting vkcs_publicdns_zone"))
+ }
+
+ stateConf := &resource.StateChangeConf{
+ Pending: []string{zoneStatusActive},
+ Target: []string{zoneStatusDeleted},
+ Refresh: publicDNSZoneStateRefreshFunc(client, d.Id()),
+ Timeout: d.Timeout(schema.TimeoutCreate),
+ Delay: zoneDelay,
+ MinTimeout: zoneMinTimeout,
+ }
+
+ _, err = stateConf.WaitForStateContext(ctx)
+ if err != nil {
+ return diag.Errorf("Error waiting for vkcs_publicdns_zone %s to become deleted: %s", d.Id(), err)
+ }
+
+ return nil
+}
diff --git a/vkcs/resource_vkcs_publicdns_zone_test.go b/vkcs/resource_vkcs_publicdns_zone_test.go
new file mode 100644
index 00000000..7b2da860
--- /dev/null
+++ b/vkcs/resource_vkcs_publicdns_zone_test.go
@@ -0,0 +1,114 @@
+package vkcs
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+)
+
+func TestAccPublicDNSZone_basic(t *testing.T) {
+ var z zone
+ zoneName := fmt.Sprintf("vkcs-tf-acctest-%s.com", acctest.RandString(5))
+
+ resource.Test(t, resource.TestCase{
+ ProviderFactories: testAccProviders,
+ CheckDestroy: testAccCheckPublicDNSZoneDestroy,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccRenderConfigWithZone(testAccPublicDNSZoneConfigBasic, zoneName),
+ Check: resource.ComposeTestCheckFunc(
+ testAccCheckPublicDNSZoneExists("vkcs_publicdns_zone.zone_1", &z),
+ resource.TestCheckResourceAttr("vkcs_publicdns_zone.zone_1", "primary_dns", "ns1.mcs.mail.ru"),
+ resource.TestCheckResourceAttr("vkcs_publicdns_zone.zone_1", "zone", zoneName),
+ resource.TestCheckResourceAttrPtr("vkcs_publicdns_zone.zone_1", "status", &z.Status),
+ ),
+ },
+ {
+ Config: testAccRenderConfigWithZone(testAccPublicDNSZoneConfigUpdate, zoneName),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("vkcs_publicdns_zone.zone_1", "primary_dns", "ns2.mcs.mail.ru"),
+ resource.TestCheckResourceAttr("vkcs_publicdns_zone.zone_1", "expire", "7200000"),
+ resource.TestCheckResourceAttr("vkcs_publicdns_zone.zone_1", "admin_email", "new-admin@example.com"),
+ ),
+ },
+ },
+ })
+}
+
+func testAccCheckPublicDNSZoneDestroy(s *terraform.State) error {
+ config := testAccProvider.Meta().(*config)
+ client, err := config.PublicDNSV2Client(osRegionName)
+ if err != nil {
+ return fmt.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ for _, rs := range s.RootModule().Resources {
+ if rs.Type != "vkcs_publicdns_zone" {
+ continue
+ }
+
+ _, err := zoneGet(client, rs.Primary.ID).Extract()
+ if err == nil {
+ return fmt.Errorf("Zone still exists: %s", rs.Primary.ID)
+ }
+ }
+
+ return nil
+}
+
+func testAccCheckPublicDNSZoneExists(n string, z *zone) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ rs, ok := s.RootModule().Resources[n]
+ if !ok {
+ return fmt.Errorf("Not found: %s", n)
+ }
+
+ if rs.Primary.ID == "" {
+ return fmt.Errorf("No ID is set")
+ }
+
+ config := testAccProvider.Meta().(*config)
+ client, err := config.PublicDNSV2Client(osRegionName)
+ if err != nil {
+ return fmt.Errorf("Error creating VKCS public DNS client: %s", err)
+ }
+
+ found, err := zoneGet(client, rs.Primary.ID).Extract()
+ if err != nil {
+ return err
+ }
+
+ if found.ID != rs.Primary.ID {
+ return fmt.Errorf("Zone not found")
+ }
+
+ *z = *found
+
+ return nil
+ }
+}
+
+func testAccRenderConfigWithZone(testConfig string, zoneName string) string {
+ return testAccRenderConfig(testConfig, map[string]string{"ZoneName": zoneName})
+}
+
+const testAccPublicDNSZoneConfigBasic = `
+resource "vkcs_publicdns_zone" "zone_1" {
+ primary_dns = "ns1.mcs.mail.ru"
+ admin_email = "admin@example.com"
+ expire = 3600000
+ zone = "{{.ZoneName}}"
+}
+`
+
+const testAccPublicDNSZoneConfigUpdate = `
+resource "vkcs_publicdns_zone" "zone_1" {
+ primary_dns = "ns2.mcs.mail.ru"
+ admin_email = "new-admin@example.com"
+ expire = 7200000
+ zone = "{{.ZoneName}}"
+}
+`
diff --git a/vkcs/resource_vkcs_sharedfilesystem_securityservice.go b/vkcs/resource_vkcs_sharedfilesystem_securityservice.go
index b8230fe9..bc39accc 100644
--- a/vkcs/resource_vkcs_sharedfilesystem_securityservice.go
+++ b/vkcs/resource_vkcs_sharedfilesystem_securityservice.go
@@ -96,7 +96,9 @@ func resourceSharedFilesystemSecurityService() *schema.Resource {
Description: "The security service host name or IP address.",
},
},
- Description: "Use this resource to configure a security service.\n\n~> **Note:** All arguments including the security service password will be stored in the raw state as plain-text. [Read more about sensitive data in state](/docs/state/sensitive-data.html).\n\nA security service stores configuration information for clients for authentication and authorization (AuthN/AuthZ). For example, a share server will be the client for an existing service such as LDAP, Kerberos, or Microsoft Active Directory.",
+ Description: "Use this resource to configure a security service.\n\n" +
+ "~> **Note:** All arguments including the security service password will be stored in the raw state as plain-text. [Read more about sensitive data in state](/docs/state/sensitive-data.html).\n\n" +
+ "A security service stores configuration information for clients for authentication and authorization (AuthN/AuthZ). For example, a share server will be the client for an existing service such as LDAP, Kerberos, or Microsoft Active Directory.",
}
}
diff --git a/vkcs/resource_vkcs_sharedfilesystem_share.go b/vkcs/resource_vkcs_sharedfilesystem_share.go
index d75c3020..e146e1e5 100644
--- a/vkcs/resource_vkcs_sharedfilesystem_share.go
+++ b/vkcs/resource_vkcs_sharedfilesystem_share.go
@@ -65,6 +65,12 @@ func resourceSharedFilesystemShare() *schema.Resource {
Description: "The human-readable description for the share. Changing this updates the description of the existing share.",
},
+ "export_location_path": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: "The export location path of the share. **New since v.0.1.15**.",
+ },
+
"share_proto": {
Type: schema.TypeString,
Required: true,
@@ -202,6 +208,11 @@ func resourceSharedFilesystemShareRead(ctx context.Context, d *schema.ResourceDa
log.Printf("[DEBUG] Retrieved share %s: %#v", d.Id(), share)
+ exportLocationPath, err := getShareExportLocationPath(sfsClient, share.ID)
+ if err != nil {
+ return diag.Errorf("Error retrieving share export location path: %s", err)
+ }
+
d.Set("name", share.Name)
d.Set("description", share.Description)
d.Set("share_proto", share.ShareProto)
@@ -214,6 +225,7 @@ func resourceSharedFilesystemShareRead(ctx context.Context, d *schema.ResourceDa
// Computed
d.Set("region", getRegion(d, config))
d.Set("project_id", share.ProjectID)
+ d.Set("export_location_path", exportLocationPath)
d.Set("share_server_id", share.ShareServerID)
return nil
diff --git a/vkcs/resource_vkcs_sharedfilesystem_share_access.go b/vkcs/resource_vkcs_sharedfilesystem_share_access.go
index dbcac871..cc19475b 100644
--- a/vkcs/resource_vkcs_sharedfilesystem_share_access.go
+++ b/vkcs/resource_vkcs_sharedfilesystem_share_access.go
@@ -75,7 +75,8 @@ func resourceSharedFilesystemShareAccess() *schema.Resource {
Description: "The access level to the share. Can either be `rw` or `ro`.",
},
},
- Description: "Use this resource to control the share access lists.\n\n~> **Important Security Notice** The access key assigned by this resource will be stored *unencrypted* in your Terraform state file. If you use this resource in production, please make sure your state file is sufficiently protected. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
+ Description: "Use this resource to control the share access lists.\n\n" +
+ "~> **Important Security Notice** The access key assigned by this resource will be stored *unencrypted* in your Terraform state file. If you use this resource in production, please make sure your state file is sufficiently protected. [Read more about sensitive data in state](https://www.terraform.io/docs/language/state/sensitive-data.html).",
}
}
diff --git a/vkcs/resource_vkcs_sharedfilesystem_sharenetwork.go b/vkcs/resource_vkcs_sharedfilesystem_sharenetwork.go
index c7fb735d..a6389b09 100644
--- a/vkcs/resource_vkcs_sharedfilesystem_sharenetwork.go
+++ b/vkcs/resource_vkcs_sharedfilesystem_sharenetwork.go
@@ -83,7 +83,8 @@ func resourceSharedFilesystemShareNetwork() *schema.Resource {
Description: "The share network CIDR.",
},
},
- Description: "Use this resource to configure a share network.\n\nA share network stores network information that share servers can use when shares are created.",
+ Description: "Use this resource to configure a share network.\n\n" +
+ "A share network stores network information that share servers can use when shares are created.",
}
}
diff --git a/vkcs/sharedfilesystem_shared.go b/vkcs/sharedfilesystem_shared.go
index 7a908820..f14756e4 100644
--- a/vkcs/sharedfilesystem_shared.go
+++ b/vkcs/sharedfilesystem_shared.go
@@ -1,6 +1,24 @@
package vkcs
+import (
+ "fmt"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/shares"
+)
+
const (
sharedFilesystemMinMicroversion = "2.7"
sharedFilesystemSharedAccessCephXMicroversion = "2.13"
)
+
+func getShareExportLocationPath(client *gophercloud.ServiceClient, id string) (string, error) {
+ exportLocations, err := shares.ListExportLocations(client, id).Extract()
+ if err != nil {
+ return "", fmt.Errorf("unable to retrieve export location from the Shares API: %s", err)
+ }
+ if len(exportLocations) > 0 {
+ return exportLocations[0].Path, nil
+ }
+ return "", nil
+}
diff --git a/vkcs/test_suite.go b/vkcs/test_suite.go
index 119a4e3e..7d470890 100755
--- a/vkcs/test_suite.go
+++ b/vkcs/test_suite.go
@@ -73,6 +73,10 @@ func (d *dummyConfig) NetworkingV2Client(region string, sdn string) (*gopherclou
return nil, nil
}
+func (d *dummyConfig) PublicDNSV2Client(region string) (*gophercloud.ServiceClient, error) {
+ return nil, nil
+}
+
func (d *dummyConfig) GetMutex() *mutexkv.MutexKV {
return nil
}
diff --git a/vkcs/urls.go b/vkcs/urls.go
index 1f1c514c..4abb9b90 100755
--- a/vkcs/urls.go
+++ b/vkcs/urls.go
@@ -1,5 +1,7 @@
package vkcs
+import "strings"
+
func baseURL(c ContainerClient, api string) string {
return c.ServiceURL(api)
}
@@ -72,6 +74,30 @@ func scaleURL(c ContainerClient, api string, id string) string {
return c.ServiceURL(api, id, "actions", "scale")
}
+func datastoresURL(c ContainerClient, api string) string {
+ return c.ServiceURL(api)
+}
+
+func datastoreURL(c ContainerClient, api string, dsID string) string {
+ return c.ServiceURL(api, dsID)
+}
+
func datastoreParametersURL(c ContainerClient, api string, dsType string, dsVersion string) string {
return c.ServiceURL(api, dsType, "versions", dsVersion, "parameters")
}
+
+func datastoreCapabilitiesURL(c ContainerClient, api string, dsType string, dsVersion string) string {
+ return c.ServiceURL(api, dsType, "versions", dsVersion, "capabilities")
+}
+
+func zonesURL(c ContainerClient, api string) string {
+ return c.ServiceURL(api, "")
+}
+
+func recordsURL(c ContainerClient, api string, zoneID string, recordType string) string {
+ return c.ServiceURL(api, zoneID, strings.ToLower(recordType), "")
+}
+
+func recordURL(c ContainerClient, api string, zoneID string, recordType string, id string) string {
+ return c.ServiceURL(api, zoneID, strings.ToLower(recordType), id)
+}
diff --git a/vkcs/util.go b/vkcs/util.go
index 5e9cd03f..277ac5f8 100755
--- a/vkcs/util.go
+++ b/vkcs/util.go
@@ -2,6 +2,8 @@ package vkcs
import (
"fmt"
+ "reflect"
+ "strings"
"time"
"github.com/gophercloud/gophercloud"
@@ -21,6 +23,31 @@ func mapStructureDecoder(strct interface{}, v *map[string]interface{}, config *m
return decoder.Decode(*v)
}
+// structToMap converts a structure to map with keys set to lowered
+// structure field names
+// NOTE: This function does not implement mapping nested structures
+func structToMap(s interface{}) (map[string]interface{}, error) {
+ v := reflect.ValueOf(s)
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+
+ if v.Kind() != reflect.Struct {
+ return nil, fmt.Errorf("got %T instead of struct", s)
+ }
+
+ m := make(map[string]interface{})
+ t := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ f := t.Field(i)
+ if f.IsExported() {
+ m[strings.ToLower(f.Name)] = v.Field(i).Interface()
+ }
+ }
+
+ return m, nil
+}
+
// getTimestamp ...
func getTimestamp(t *time.Time) string {
if t != nil {
@@ -53,6 +80,14 @@ func checkDeleted(d *schema.ResourceData, err error, msg string) error {
return fmt.Errorf("%s %s: %s", msg, d.Id(), err)
}
+func checkAlreadyExists(err error, msg, resourceName, conflict string) error {
+ if _, ok := err.(gophercloud.ErrDefault409); ok {
+ return fmt.Errorf("%s: %s with %s already exists", msg, resourceName, conflict)
+ }
+
+ return fmt.Errorf("%s: %s", msg, err)
+}
+
// getRegion returns the region that was specified in the resource. If a
// region was not set, the provider-level region is checked. The provider-level
// region can either be set by the region argument or by OS_REGION_NAME.
diff --git a/vkcs/vkcs_common.go b/vkcs/vkcs_common.go
index e5cb392d..3c0f2f06 100644
--- a/vkcs/vkcs_common.go
+++ b/vkcs/vkcs_common.go
@@ -19,16 +19,6 @@ type ContainerClient interface {
ServiceURL(parts ...string) string
}
-func getDBRequestOpts(codes ...int) *gophercloud.RequestOpts {
- reqOpts := &gophercloud.RequestOpts{
- OkCodes: codes,
- }
- if len(codes) != 0 {
- reqOpts.OkCodes = codes
- }
- return reqOpts
-}
-
func getRequestOpts(codes ...int) *gophercloud.RequestOpts {
reqOpts := &gophercloud.RequestOpts{
OkCodes: codes,
@@ -36,7 +26,6 @@ func getRequestOpts(codes ...int) *gophercloud.RequestOpts {
if len(codes) != 0 {
reqOpts.OkCodes = codes
}
- addMagnumMicroVersionHeader(reqOpts)
return reqOpts
}