Compare commits
53 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b5b97ac9a | |||
|
|
29cf260d56 | ||
| 4e217e20a4 | |||
|
|
2f2b5cd04a | ||
| 6c26089930 | |||
| c31a8a787a | |||
| 515b7b1357 | |||
| e6d2d3e10a | |||
| 8fee76f037 | |||
| ebb3ec051d | |||
|
|
e5b2681142 | ||
| e65c74e6e7 | |||
| afde034d64 | |||
|
|
7b911ebf70 | ||
| e320e80956 | |||
|
|
4d96cc8951 | ||
| f9a3d4265c | |||
|
|
1298c3fbf1 | ||
| fa641d29c5 | |||
|
|
dab47d4690 | ||
| a0351798e0 | |||
| f7b022ec6c | |||
|
|
6e3d2b51fa | ||
|
|
9ef7ce9029 | ||
| aac1a2ba17 | |||
| d16b97a8e9 | |||
|
|
edc5e869ce | ||
| 7b2dfaea44 | |||
| 2893a11c0a | |||
| 0b5e15d1c5 | |||
|
|
8a6d932107 | ||
| 956cedef08 | |||
|
|
d5b4e02437 | ||
|
|
bb15293dd3 | ||
|
|
6e6e771631 | ||
|
|
683bc64c12 | ||
|
|
064d2cf1db | ||
|
|
722c46b12d | ||
| 03776cc7fd | |||
| 9060aa9f6a | |||
|
|
5a1dc9cd94 | ||
| d34927537a | |||
|
|
83b0860115 | ||
|
|
97645d7a66 | ||
|
|
94f3dad963 | ||
|
|
c081f5f7bd | ||
|
|
8ab8656b5c | ||
|
|
63435e5e63 | ||
|
|
e974ccf906 | ||
|
|
1fd2df5c76 | ||
|
|
aaabadde1a | ||
|
|
0a5bc30d9c | ||
| 01deb9022d |
79 changed files with 3109 additions and 1909 deletions
125
.github/actions/acc_test/action.yaml
vendored
125
.github/actions/acc_test/action.yaml
vendored
|
|
@ -14,7 +14,7 @@ inputs:
|
|||
|
||||
go-version:
|
||||
description: "go version to install"
|
||||
default: '1.25'
|
||||
default: '1.26'
|
||||
required: true
|
||||
|
||||
project_id:
|
||||
|
|
@ -65,20 +65,18 @@ inputs:
|
|||
description: "testfile to run"
|
||||
default: ''
|
||||
|
||||
outputs:
|
||||
result:
|
||||
value: ${{ steps.testrun.outputs.result }}
|
||||
description: "the output of the tests"
|
||||
|
||||
#outputs:
|
||||
# random-number:
|
||||
# description: "Random number"
|
||||
# value: ${{ steps.random-number-generator.outputs.random-number }}
|
||||
status:
|
||||
value: ${{ steps.status.outputs.status }}
|
||||
description: "the status of the tests"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# - name: Random Number Generator
|
||||
# id: random-number-generator
|
||||
# run: echo "random-number=$(echo $RANDOM)" >> $GITHUB_OUTPUT
|
||||
# shell: bash
|
||||
|
||||
- name: Install needed tools
|
||||
shell: bash
|
||||
run: |
|
||||
|
|
@ -94,6 +92,15 @@ runs:
|
|||
fi
|
||||
echo "::endgroup::"
|
||||
|
||||
# Install latest version of Terraform
|
||||
- uses: hashicorp/setup-terraform@v4
|
||||
with:
|
||||
terraform_wrapper: false
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24.x'
|
||||
|
||||
- name: Setup JAVA
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
|
|
@ -196,11 +203,11 @@ runs:
|
|||
ls -l stackit/"${{ inputs.service_account_json_file_path }}"
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Run acceptance test file
|
||||
if: ${{ inputs.test_file != '' }}
|
||||
- name: Run acceptance tests
|
||||
id: testrun
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::group::go test file"
|
||||
echo "::group::go test"
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
|
|
@ -209,60 +216,22 @@ runs:
|
|||
export TF_LOG
|
||||
fi
|
||||
|
||||
testfile="${{ inputs.test_file }}"
|
||||
|
||||
echo "result=no result before run" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "Running acceptance tests for the terraform provider"
|
||||
cd stackit || exit 1
|
||||
TF_ACC=1 \
|
||||
TF_ACC_PROJECT_ID=${TF_ACC_PROJECT_ID} \
|
||||
TF_ACC_REGION=${TF_ACC_REGION} \
|
||||
TF_ACC_TEST_PROJECT_USER_EMAIL=${TF_ACC_TEST_PROJECT_USER_EMAIL} \
|
||||
TF_ACC_SERVICE_ACCOUNT_FILE="${PWD}/${{ inputs.service_account_json_file_path }}" \
|
||||
TF_ACC_KEK_KEY_ID=${TF_ACC_KEK_KEY_ID} \
|
||||
TF_ACC_KEK_KEY_RING_ID=${TF_ACC_KEK_KEY_RING_ID} \
|
||||
TF_ACC_KEK_KEY_VERSION=${TF_ACC_KEK_KEY_VERSION} \
|
||||
TF_ACC_KEK_SERVICE_ACCOUNT=${TF_ACC_KEK_SERVICE_ACCOUNT} \
|
||||
go test -v ${{ inputs.test_file }} -timeout=${{ inputs.test_timeout_string }}
|
||||
echo "::endgroup::"
|
||||
env:
|
||||
TF_ACC_PROJECT_ID: ${{ inputs.project_id }}
|
||||
TF_ACC_REGION: ${{ inputs.region }}
|
||||
TF_ACC_TEST_PROJECT_USER_EMAIL: ${{ inputs.project_user_email }}
|
||||
TF_ACC_KEK_KEY_ID: ${{ inputs.tf_acc_kek_key_id }}
|
||||
TF_ACC_KEK_KEY_RING_ID: ${{ inputs.tf_acc_kek_key_ring_id }}
|
||||
TF_ACC_KEK_KEY_VERSION: ${{ inputs.tf_acc_kek_key_version }}
|
||||
TF_ACC_KEK_SERVICE_ACCOUNT: ${{ inputs.tf_acc_kek_service_account }}
|
||||
|
||||
# does not work correctly
|
||||
# - name: Run test action
|
||||
# if: ${{ inputs.test_file == '' }}
|
||||
# env:
|
||||
# TF_ACC: 1
|
||||
# TF_ACC_PROJECT_ID: ${{ inputs.project_id }}
|
||||
# TF_ACC_REGION: ${{ inputs.region }}
|
||||
# TF_ACC_TEST_PROJECT_USER_EMAIL: ${{ inputs.project_user_email }}
|
||||
# TF_ACC_KEK_KEY_ID: ${{ inputs.tf_acc_kek_key_id }}
|
||||
# TF_ACC_KEK_KEY_RING_ID: ${{ inputs.tf_acc_kek_key_ring_id }}
|
||||
# TF_ACC_KEK_KEY_VERSION: ${{ inputs.tf_acc_kek_key_version }}
|
||||
# TF_ACC_KEK_SERVICE_ACCOUNT: ${{ inputs.tf_acc_kek_service_account }}
|
||||
# TF_ACC_SERVICE_ACCOUNT_FILE: ${{ steps.service_account.outputs.safile }}
|
||||
# uses: robherley/go-test-action@v0
|
||||
# with:
|
||||
# testArguments: "./... -timeout ${{ inputs.test_timeout_string }}"
|
||||
# moduleDirectory: "stackit"
|
||||
|
||||
- name: Run acceptance tests
|
||||
if: ${{ inputs.test_file == '' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::group::go test all"
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [[ "${{ inputs.tf_debug }}" == "true" ]]; then
|
||||
TF_LOG=INFO
|
||||
export TF_LOG
|
||||
if [[ -z "$testfile" ]]; then
|
||||
testfile="./..."
|
||||
fi
|
||||
|
||||
echo "Running acceptance tests for the terraform provider"
|
||||
if [[ -z "$testfile" ]]; then
|
||||
echo "ERROR: No test file provided"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set +e
|
||||
cd stackit || exit 1
|
||||
TF_ACC=1 \
|
||||
TF_ACC_PROJECT_ID=${TF_ACC_PROJECT_ID} \
|
||||
|
|
@ -273,7 +242,21 @@ runs:
|
|||
TF_ACC_KEK_KEY_RING_ID=${TF_ACC_KEK_KEY_RING_ID} \
|
||||
TF_ACC_KEK_KEY_VERSION=${TF_ACC_KEK_KEY_VERSION} \
|
||||
TF_ACC_KEK_SERVICE_ACCOUNT=${TF_ACC_KEK_SERVICE_ACCOUNT} \
|
||||
go test -v ./... -timeout=${{ inputs.test_timeout_string }}
|
||||
go test -v ${testfile} -timeout=${{ inputs.test_timeout_string }} | tee -a acc_test_run.log
|
||||
set -e
|
||||
|
||||
have_fail=$(cat acc_test_run.log | grep FAIL)
|
||||
if [[ -n $have_fail ]]; then
|
||||
echo "::endgroup::"
|
||||
echo "::group::go test result"
|
||||
echo "Test failed, see acc_test_run.log for details"
|
||||
echo "${have_fail}"
|
||||
echo "result=<b>FAIL:</b> <br />${have_fail}" >> "$GITHUB_OUTPUT"
|
||||
echo "::endgroup::"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "result=no FAIL detected" >> "$GITHUB_OUTPUT"
|
||||
echo "::endgroup::"
|
||||
env:
|
||||
TF_ACC_PROJECT_ID: ${{ inputs.project_id }}
|
||||
|
|
@ -283,3 +266,17 @@ runs:
|
|||
TF_ACC_KEK_KEY_RING_ID: ${{ inputs.tf_acc_kek_key_ring_id }}
|
||||
TF_ACC_KEK_KEY_VERSION: ${{ inputs.tf_acc_kek_key_version }}
|
||||
TF_ACC_KEK_SERVICE_ACCOUNT: ${{ inputs.tf_acc_kek_service_account }}
|
||||
|
||||
- name: Set status output variable
|
||||
if: always()
|
||||
id: status
|
||||
shell: bash
|
||||
run: |
|
||||
echo "status=${{ steps.testrun.outcome == 'success' && 'SUCCESS' || 'FAILURE' }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload test log artifact
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: acc_test.log
|
||||
path: "stackit/acc_test_run.log"
|
||||
|
|
|
|||
2
.github/actions/build/action.yaml
vendored
2
.github/actions/build/action.yaml
vendored
|
|
@ -3,7 +3,7 @@ description: "Build pipeline"
|
|||
inputs:
|
||||
go-version:
|
||||
description: "Go version to install"
|
||||
default: '1.25'
|
||||
default: '1.26'
|
||||
required: true
|
||||
java-distribution:
|
||||
description: "JAVA distribution to use (default: temurin)"
|
||||
|
|
|
|||
1
.github/actions/clean_up/README.md
vendored
Normal file
1
.github/actions/clean_up/README.md
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
# acceptance test action
|
||||
227
.github/actions/clean_up/action.yaml
vendored
Normal file
227
.github/actions/clean_up/action.yaml
vendored
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
name: CleanUp Project Resources
|
||||
description: "Acceptance Testing CleanUp"
|
||||
|
||||
inputs:
|
||||
project_id:
|
||||
description: "STACKIT project ID for tests"
|
||||
required: true
|
||||
|
||||
region:
|
||||
description: "STACKIT region for tests"
|
||||
default: 'eu01'
|
||||
required: true
|
||||
|
||||
tf_resource_prefix:
|
||||
description: "prefix in resource names"
|
||||
default: 'tf-acc-'
|
||||
required: true
|
||||
|
||||
service_account_json_content:
|
||||
description: "STACKIT service account JSON file contents"
|
||||
required: true
|
||||
default: ''
|
||||
|
||||
service_account_json_content_b64:
|
||||
description: "STACKIT service account JSON file contents"
|
||||
required: true
|
||||
default: ''
|
||||
|
||||
list_only:
|
||||
description: "only list resources, DO NOT delete"
|
||||
required: true
|
||||
default: 'true'
|
||||
|
||||
log_level:
|
||||
description: "Log Level"
|
||||
required: true
|
||||
default: 'warning'
|
||||
|
||||
outputs:
|
||||
cli-version:
|
||||
description: "stackit cli version"
|
||||
value: ${{ steps.stackit_version.outputs.version }}
|
||||
|
||||
pre_count:
|
||||
description: "number of resources found"
|
||||
value: ${{ steps.retrieve_pre.outputs.count }}
|
||||
|
||||
post_count:
|
||||
description: "number of resources found"
|
||||
value: ${{ steps.retrieve_post.outputs.count }}
|
||||
|
||||
status:
|
||||
description: "status of the test"
|
||||
value: ${{ steps.status.outputs.status }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install needed tools
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::group::apt install"
|
||||
set -e
|
||||
apt-get -y -qq update >apt_update.log 2>apt_update_err.log
|
||||
if [ $? -ne 0 ]; then
|
||||
cat apt_update.log apt_update_err.log
|
||||
fi
|
||||
apt-get -y -qq install curl gnupg jq >apt_get.log 2>apt_get_err.log
|
||||
if [ $? -ne 0 ]; then
|
||||
cat apt_get.log apt_get_err.log
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::apt add source"
|
||||
curl https://packages.stackit.cloud/keys/key.gpg | gpg --dearmor -o /usr/share/keyrings/stackit.gpg
|
||||
echo "deb [signed-by=/usr/share/keyrings/stackit.gpg] https://packages.stackit.cloud/apt/cli stackit main" | tee -a /etc/apt/sources.list.d/stackit.list
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::apt install stackit cli"
|
||||
apt-get -y -qq update >apt_update.log 2>apt_update_err.log
|
||||
if [ $? -ne 0 ]; then
|
||||
cat apt_update.log apt_update_err.log
|
||||
fi
|
||||
apt-get -y -qq install stackit >apt_get.log 2>apt_get_err.log
|
||||
if [ $? -ne 0 ]; then
|
||||
cat apt_get.log apt_get_err.log
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Check stackit cli version
|
||||
id: stackit_version
|
||||
run: |
|
||||
set -e
|
||||
VERSION=$(stackit --version | grep "Version:" | cut -d " " -f 2)
|
||||
echo "stackit cli version: ${VERSION}"
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Creating service_account file from json input
|
||||
if: inputs.service_account_json_content != ''
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::group::create service account file"
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
echo "${{ inputs.service_account_json_content }}" > .svc_acc.json
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Creating service_account file from base64 json input
|
||||
if: inputs.service_account_json_content_b64 != ''
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::group::create service account file"
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
echo "${{ inputs.service_account_json_content_b64 }}" | base64 -d > .svc_acc.json
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Check service account file exists
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
if [[ ! -s .svc_acc.json ]]; then
|
||||
echo "ERROR: service account file missing or empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Retrieve resources before
|
||||
id: retrieve_pre
|
||||
run: |
|
||||
echo "::group::retrieve resources"
|
||||
set -e
|
||||
echo "authenticating api"
|
||||
STACKIT_SERVICE_ACCOUNT_KEY_PATH="${PWD}/.svc_acc.json"
|
||||
export STACKIT_SERVICE_ACCOUNT_KEY_PATH
|
||||
stackit auth activate-service-account --service-account-key-path .svc_acc.json
|
||||
|
||||
echo "SQL Server Flex resources:"
|
||||
sql_res=$(stackit --verbosity ${{ inputs.log_level }} --project-id "${{ inputs.project_id }}" beta sqlserverflex instance list --output-format json | jq -r '.[] | select(.name | startswith("${{ inputs.tf_resource_prefix }}"))')
|
||||
sql_count=$(echo "$sql_res" | jq -r '.id' | wc -l)
|
||||
|
||||
echo "PostgreSQL Flex resources:"
|
||||
pg_res=$(stackit --verbosity ${{ inputs.log_level }} --project-id "${{ inputs.project_id }}" postgresflex instance list --output-format json | jq -r '.[] | select(.name | startswith("${{ inputs.tf_resource_prefix }}"))')
|
||||
pg_count=$(echo "$pg_res" | jq -r '.id' | wc -l)
|
||||
|
||||
echo "Number of resources found: ${sql_count} SQL Server Flex, ${pg_count} PostgreSQL Flex"
|
||||
echo "count=$(( ${pg_count} + ${sql_count} ))" >> $GITHUB_OUTPUT
|
||||
echo "::endgroup::"
|
||||
shell: bash
|
||||
|
||||
- name: Delete SQL Server Flex resources
|
||||
if: ${{ inputs.list_only != 'true' }}
|
||||
id: del_sql
|
||||
run: |
|
||||
echo "::group::delete SQL Server Flex resources"
|
||||
stackit --verbosity ${{ inputs.log_level }} auth activate-service-account --service-account-key-path .svc_acc.json
|
||||
for s in $(stackit --verbosity ${{ inputs.log_level }} --project-id ${{ inputs.project_id }} beta sqlserverflex instance list --output-format json | jq -r '.[] | select(.name | startswith("${{ inputs.tf_resource_prefix }}")) | .id');
|
||||
do
|
||||
stackit --verbosity ${{ inputs.log_level }} -y --project-id ${{ inputs.project_id }} beta sqlserverflex instance delete $s || echo "status=FAILURE" >> ${GITHUB_OUTPUT};
|
||||
done
|
||||
echo "::endgroup::"
|
||||
shell: bash
|
||||
|
||||
- name: Skip Delete SQL Server Flex resources
|
||||
if: ${{ inputs.list_only == 'true' }}
|
||||
run: |
|
||||
set -e
|
||||
echo "Skip deleting: list only mode"
|
||||
shell: bash
|
||||
|
||||
- name: Delete PostgreSQL Flex resources
|
||||
if: ${{ inputs.list_only != 'true' }}
|
||||
id: del_pg
|
||||
run: |
|
||||
echo "::group::delete PostgreSQL Flex resources"
|
||||
stackit auth activate-service-account --service-account-key-path .svc_acc.json
|
||||
for s in $(stackit --verbosity ${{ inputs.log_level }} --project-id ${{ inputs.project_id }} postgresflex instance list --output-format json | jq -r '.[] | select(.name | startswith("${{ inputs.tf_resource_prefix }}")) | .id');
|
||||
do
|
||||
stackit --verbosity ${{ inputs.log_level }} -y --project-id ${{ inputs.project_id }} postgresflex instance delete "$s" --force || echo "status=FAILURE" >> ${GITHUB_OUTPUT};
|
||||
done
|
||||
echo "::endgroup::"
|
||||
shell: bash
|
||||
|
||||
- name: Skip Delete PostgreSQL Flex resources
|
||||
if: ${{ inputs.list_only == 'true' }}
|
||||
run: |
|
||||
set -e
|
||||
echo "Skip deleting: list only mode"
|
||||
shell: bash
|
||||
|
||||
- name: Retrieve resources after
|
||||
id: retrieve_post
|
||||
run: |
|
||||
echo "::group::retrieve resources"
|
||||
set -e
|
||||
echo "authenticating api"
|
||||
STACKIT_SERVICE_ACCOUNT_KEY_PATH="${PWD}/.svc_acc.json"
|
||||
export STACKIT_SERVICE_ACCOUNT_KEY_PATH
|
||||
stackit auth activate-service-account --service-account-key-path .svc_acc.json
|
||||
|
||||
echo "SQL Server Flex resources:"
|
||||
sql_res=$(stackit --verbosity ${{ inputs.log_level }} --project-id "${{ inputs.project_id }}" beta sqlserverflex instance list --output-format json | jq -r '.[] | select(.name | startswith("${{ inputs.tf_resource_prefix }}"))')
|
||||
sql_count=$(echo "$sql_res" | jq -r '.id' | wc -l)
|
||||
|
||||
echo "PostgreSQL Flex resources:"
|
||||
pg_res=$(stackit --verbosity ${{ inputs.log_level }} --project-id "${{ inputs.project_id }}" postgresflex instance list --output-format json | jq -r '.[] | select(.name | startswith("${{ inputs.tf_resource_prefix }}"))')
|
||||
pg_count=$(echo "$pg_res" | jq -r '.id' | wc -l)
|
||||
|
||||
echo "Number of resources found: ${sql_count} SQL Server Flex, ${pg_count} PostgreSQL Flex"
|
||||
echo "count=$(( ${pg_count} + ${sql_count} ))" >> $GITHUB_OUTPUT
|
||||
echo "::endgroup::"
|
||||
shell: bash
|
||||
|
||||
- name: Set status
|
||||
if: always()
|
||||
id: status
|
||||
run: |
|
||||
status="SUCCESS"
|
||||
if [[ "${{ steps.del_pg.outputs.status }}" == "FAILURE" ]]; then
|
||||
status=FAILURE"
|
||||
elif [[ "${{ steps.del_sql.outputs.status }}" == "FAILURE" ]]; then
|
||||
status=FAILURE"
|
||||
fi
|
||||
echo "status=$status" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
148
.github/actions/notify/action.yaml
vendored
Normal file
148
.github/actions/notify/action.yaml
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
name: Send notification via Google Chat
|
||||
description: "Sends a notification to a Google Chat room when a pull request is opened."
|
||||
|
||||
inputs:
|
||||
webhook_url:
|
||||
description: "The URL of the Google Chat webhook."
|
||||
required: true
|
||||
|
||||
title:
|
||||
description: "The title of the notification."
|
||||
required: true
|
||||
|
||||
subtitle:
|
||||
description: "The subtitle of the notification."
|
||||
default: 'no subtitle provided'
|
||||
|
||||
image_slug:
|
||||
description: "The slug of the image to be included in the notification."
|
||||
default: 'git'
|
||||
|
||||
event_author:
|
||||
description: "The author of the event."
|
||||
default: 'unknown'
|
||||
|
||||
event_title:
|
||||
description: "The title of the event."
|
||||
required: true
|
||||
|
||||
event_body:
|
||||
description: "The body of the event."
|
||||
default: 'no body provided'
|
||||
|
||||
event_number:
|
||||
description: "The number of the event."
|
||||
default: 'no number provided'
|
||||
|
||||
event_url:
|
||||
description: "The url of the event."
|
||||
default: 'none'
|
||||
|
||||
status:
|
||||
description: "The status of the event."
|
||||
default: 'UNKNOWN'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install prerequisites
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::group::apt install"
|
||||
set -e
|
||||
apt update
|
||||
apt install -y curl jq
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Determine status color
|
||||
id: status
|
||||
shell: bash
|
||||
run: |
|
||||
case "${{ inputs.status }}" in
|
||||
SUCCESS)
|
||||
STATUS_COLOR="006400/228b22"
|
||||
ADD='{"decoratedText": {"startIcon": {"materialIcon": {"name": "check_circle"}},"text": "<b style=\"color: green;\">SUCCESS</b>"}},'
|
||||
;;
|
||||
FAILURE)
|
||||
STATUS_COLOR="8b0000/dc143c"
|
||||
ADD='{"decoratedText": {"startIcon": {"materialIcon": {"name": "stop_circle"}},"text": "<b style=\"color: red;\">FAILURE</b>"}},'
|
||||
;;
|
||||
*)
|
||||
STATUS_COLOR="483d8b/6495ed"
|
||||
ADD=''
|
||||
;;
|
||||
esac
|
||||
echo "color=${STATUS_COLOR}" >> "$GITHUB_OUTPUT"
|
||||
echo "status_add=${ADD}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Notify via Google Chat Webhook
|
||||
shell: bash
|
||||
env:
|
||||
WEBHOOK: ${{ inputs.webhook_url }}
|
||||
run: |
|
||||
set -e
|
||||
|
||||
PAYLOAD=$(jq -n -r \
|
||||
--arg header "${{ inputs.title }}" \
|
||||
--arg subtitle "${{ inputs.subtitle }}" \
|
||||
--arg imgurl "https://cdn.simpleicons.org/${{ inputs.image_slug }}/${{ steps.status.outputs.color }}" \
|
||||
--arg title "${{ inputs.event_title || 'no event title given' }}" \
|
||||
--arg body "${{ inputs.event_body || 'no event body given' }}" \
|
||||
--arg author "${{ inputs.event_author || 'no event author given' }}" \
|
||||
--arg url "${{ inputs.event_url || github.repositoryUrl || github.server_url }}" \
|
||||
'{ "cardsV2": [ { "cardId": "notify-${{ github.run_id }}", "card": {
|
||||
"header": {
|
||||
"title": "\($header)",
|
||||
"subtitle": "\($subtitle)",
|
||||
"imageUrl": "\($imgurl)",
|
||||
"imageType": "SQUARE"
|
||||
},
|
||||
"sections": [
|
||||
{
|
||||
"header": "\($title)",
|
||||
"collapsible": false,
|
||||
"widgets": [
|
||||
${{ steps.status.outputs.status_add }}
|
||||
{
|
||||
"decoratedText": {
|
||||
"startIcon": {
|
||||
"knownIcon": "PERSON"
|
||||
},
|
||||
"text": "<b>\($author)</b>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"textParagraph": {
|
||||
"text": "\($body)",
|
||||
"maxLines": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"widgets": [
|
||||
{
|
||||
"buttonList": {
|
||||
"buttons": [
|
||||
{
|
||||
"text": "View Source Event",
|
||||
"type": "FILLED",
|
||||
"onClick": {
|
||||
"openLink": {
|
||||
"url": "\($url)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}} ] }')
|
||||
|
||||
curl \
|
||||
-X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
"${{ inputs.webhook_url }}&threadKey=run${{ github.run_id }}&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD" \
|
||||
-d "${PAYLOAD}"
|
||||
2
.github/actions/setup-cache-go/action.yaml
vendored
2
.github/actions/setup-cache-go/action.yaml
vendored
|
|
@ -10,7 +10,7 @@ inputs:
|
|||
|
||||
go-version:
|
||||
description: "go version to install"
|
||||
default: '1.25'
|
||||
default: '1.26'
|
||||
required: true
|
||||
|
||||
runs:
|
||||
|
|
|
|||
25
.github/workflows/ci_new.yaml
vendored
25
.github/workflows/ci_new.yaml
vendored
|
|
@ -28,11 +28,24 @@ jobs:
|
|||
config:
|
||||
if: ${{ github.event_name != 'schedule' }}
|
||||
name: Check GoReleaser config
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Notify
|
||||
if: always()
|
||||
uses: ./.github/actions/notify
|
||||
with:
|
||||
webhook_url: ${{ secrets.GOOGLE_WEBHOOK_URL }}
|
||||
title: "[START] CI pipeline (#${{ forgejo.run_number }})"
|
||||
subtitle: "${{ forgejo.event_name }} on ${{ forgejo.ref_name }}"
|
||||
event_title: "${{ forgejo.event_name }} for ${{ forgejo.repository }}"
|
||||
event_author: ${{ forgejo.actor }}
|
||||
event_body: "${{ forgejo.event_name }} on ${{ forgejo.ref }} for ${{ forgejo.repository }}"
|
||||
event_number: ${{ forgejo.run_number }}
|
||||
event_url: "https://tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/actions/runs/${{ forgejo.run_number }}"
|
||||
|
||||
- name: Check GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v7
|
||||
with:
|
||||
|
|
@ -40,7 +53,7 @@ jobs:
|
|||
|
||||
prepare:
|
||||
name: Prepare GO cache
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
permissions:
|
||||
actions: read # Required to identify workflow run.
|
||||
checks: write # Required to add status summary.
|
||||
|
|
@ -102,7 +115,7 @@ jobs:
|
|||
needs:
|
||||
- config
|
||||
- prepare
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
permissions:
|
||||
actions: read # Required to identify workflow run.
|
||||
checks: write # Required to add status summary.
|
||||
|
|
@ -185,7 +198,7 @@ jobs:
|
|||
|
||||
testing:
|
||||
name: CI run tests
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
needs:
|
||||
- config
|
||||
- prepare
|
||||
|
|
@ -278,7 +291,7 @@ jobs:
|
|||
main:
|
||||
if: ${{ github.event_name != 'schedule' }}
|
||||
name: CI run build and linting
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
needs:
|
||||
- config
|
||||
- prepare
|
||||
|
|
@ -329,7 +342,7 @@ jobs:
|
|||
code_coverage:
|
||||
name: "Code coverage report"
|
||||
if: github.event_name == 'pull_request' # Do not run when workflow is triggered by push to main branch
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
needs:
|
||||
- main
|
||||
- prepare
|
||||
|
|
|
|||
72
.github/workflows/clean_up.yaml
vendored
Normal file
72
.github/workflows/clean_up.yaml
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
name: TF Acceptance Test CleanUp
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
list_only:
|
||||
description: "only list resources"
|
||||
type: boolean
|
||||
default: true
|
||||
required: true
|
||||
|
||||
res_prefix:
|
||||
description: "resource name prefix"
|
||||
type: string
|
||||
default: 'tf-acc-'
|
||||
required: true
|
||||
|
||||
log_level:
|
||||
description: 'Log Level'
|
||||
required: true
|
||||
default: 'warning'
|
||||
type: choice
|
||||
options:
|
||||
- info
|
||||
- warning
|
||||
- debug
|
||||
- error
|
||||
|
||||
jobs:
|
||||
clean:
|
||||
name: Clean up
|
||||
runs-on: stackit-docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Notify
|
||||
uses: ./.github/actions/notify
|
||||
with:
|
||||
webhook_url: ${{ secrets.GOOGLE_WEBHOOK_URL }}
|
||||
title: "[START] CLEAN UP pipeline (#${{ forgejo.run_number }})"
|
||||
subtitle: "${{ forgejo.repository }}"
|
||||
event_title: ${{ forgejo.event_name }}
|
||||
event_author: ${{ forgejo.actor }}
|
||||
event_body: "try to remove all resources with prefix <b>${{ inputs.res_prefix }}</b>"
|
||||
event_number: ${{ forgejo.run_number }}
|
||||
event_url: "https://tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/actions/runs/${{ forgejo.run_number }}"
|
||||
|
||||
- name: Clean
|
||||
id: clean
|
||||
uses: ./.github/actions/clean_up
|
||||
with:
|
||||
project_id: ${{ vars.TF_ACC_PROJECT_ID }}
|
||||
region: 'eu01'
|
||||
tf_resource_prefix: ${{ inputs.res_prefix }}
|
||||
service_account_json_content_b64: "${{ secrets.TF_ACC_SERVICE_ACCOUNT_JSON_B64 }}"
|
||||
list_only: ${{ inputs.list_only }}
|
||||
log_level: ${{ inputs.log_level }}
|
||||
|
||||
- name: Notify
|
||||
if: always()
|
||||
uses: ./.github/actions/notify
|
||||
with:
|
||||
webhook_url: ${{ secrets.GOOGLE_WEBHOOK_URL }}
|
||||
title: "[END] CLEAN UP pipeline (#${{ forgejo.run_number }})"
|
||||
subtitle: "${{ forgejo.repository }}"
|
||||
event_title: ${{ forgejo.event_name }}
|
||||
event_author: ${{ forgejo.actor }}
|
||||
event_body: "count before cleaning: ${{ steps.clean.outputs.pre_count }} <br /> count after cleaning: ${{ steps.clean.outputs.post_count }}"
|
||||
event_number: ${{ forgejo.run_number }}
|
||||
event_url: "https://tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/actions/runs/${{ forgejo.run_number }}"
|
||||
status: ${{ steps.clean.outcome == 'success' && 'SUCCESS' || 'FAILURE' }}
|
||||
25
.github/workflows/notify_pr.yaml
vendored
Normal file
25
.github/workflows/notify_pr.yaml
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
name: Notify on new PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
name: Notify via Google Chat
|
||||
runs-on: stackit-docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Notify
|
||||
uses: ./.github/actions/notify
|
||||
with:
|
||||
webhook_url: ${{ secrets.GOOGLE_WEBHOOK_URL }}
|
||||
title: "New Pull Request"
|
||||
event_title: "${{ github.event.pull_request.title }}"
|
||||
event_author: "${{ github.event.pull_request.user.login }}"
|
||||
event_body: "${{ github.event.pull_request.body || 'No description provided.' }}"
|
||||
event_number: "${{ github.event.pull_request.number }}"
|
||||
event_url: "${{ github.event.pull_request.html_url }}"
|
||||
35
.github/workflows/publish.yaml
vendored
35
.github/workflows/publish.yaml
vendored
|
|
@ -3,11 +3,11 @@ name: Publish
|
|||
run-name: Publish by @${{ github.actor }}
|
||||
|
||||
on:
|
||||
#workflow_dispatch:
|
||||
workflow_dispatch:
|
||||
|
||||
push:
|
||||
tags:
|
||||
- 'v0.*'
|
||||
- 'v*'
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.25"
|
||||
|
|
@ -21,6 +21,8 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-tags: true
|
||||
|
||||
- name: Check GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v7
|
||||
|
|
@ -44,6 +46,20 @@ jobs:
|
|||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-tags: true
|
||||
|
||||
- name: Notify
|
||||
uses: ./.github/actions/notify
|
||||
with:
|
||||
webhook_url: ${{ secrets.GOOGLE_WEBHOOK_URL }}
|
||||
title: "[START] Publish (#${{ forgejo.run_number }})"
|
||||
subtitle: "${{ forgejo.event_name }} on branch ${{ forgejo.ref }}"
|
||||
event_title: "run started"
|
||||
event_author: ${{ forgejo.actor }}
|
||||
event_body: ""
|
||||
event_number: ${{ forgejo.event.id }}
|
||||
event_url: "https://tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/actions/runs/${{ forgejo.run_number }}"
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
|
|
@ -132,6 +148,7 @@ jobs:
|
|||
--outFile nav.md
|
||||
|
||||
- name: Publish provider to S3
|
||||
id: publish_to_s3
|
||||
run: |
|
||||
set -e
|
||||
cd release/
|
||||
|
|
@ -152,3 +169,17 @@ jobs:
|
|||
# echo "${{ github.ref_name }}" >docs/_version.txt
|
||||
scp -o StrictHostKeyChecking=no -r docs ubuntu@${{ vars.DOCS_SERVER_IP }}:/srv/www/
|
||||
scp -o StrictHostKeyChecking=no nav.md ubuntu@${{ vars.DOCS_SERVER_IP }}:/srv/www/
|
||||
|
||||
- name: Notify
|
||||
if: always()
|
||||
uses: ./.github/actions/notify
|
||||
with:
|
||||
webhook_url: ${{ secrets.GOOGLE_WEBHOOK_URL }}
|
||||
title: "[END] Publish (#${{ forgejo.run_number }})"
|
||||
subtitle: "${{ forgejo.event_name }} on branch ${{ forgejo.ref }}"
|
||||
event_title: "released: ${{ steps.get_version.outputs.version }}"
|
||||
event_author: ${{ forgejo.actor }}
|
||||
event_body: ""
|
||||
event_number: ${{ forgejo.event.id }}
|
||||
event_url: "https://tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/actions/runs/${{ forgejo.run_number }}"
|
||||
status: "${{ steps.publish_to_s3.outcome == 'success' && 'SUCCESS' || 'FAILURE' }}"
|
||||
|
|
|
|||
4
.github/workflows/release.yaml
vendored
4
.github/workflows/release.yaml
vendored
|
|
@ -16,14 +16,14 @@ permissions:
|
|||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
# Allow goreleaser to access older tag information.
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: https://code.forgejo.org/actions/setup-go@v6
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
cache: true
|
||||
|
|
|
|||
4
.github/workflows/renovate.yaml
vendored
4
.github/workflows/renovate.yaml
vendored
|
|
@ -8,13 +8,13 @@ on:
|
|||
jobs:
|
||||
renovate:
|
||||
name: Renovate
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Self-hosted Renovate
|
||||
uses: renovatebot/github-action@v46.1.4
|
||||
uses: renovatebot/github-action@v46.1.5
|
||||
with:
|
||||
configurationFile: .github/renovate.json
|
||||
# token: ${{ secrets.RENOVATE_TOKEN }}
|
||||
|
|
|
|||
2
.github/workflows/stale.yaml
vendored
2
.github/workflows/stale.yaml
vendored
|
|
@ -20,7 +20,7 @@ permissions:
|
|||
jobs:
|
||||
stale:
|
||||
name: "Stale"
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: "Mark old PRs as stale"
|
||||
|
|
|
|||
81
.github/workflows/tf-acc-test.yaml
vendored
81
.github/workflows/tf-acc-test.yaml
vendored
|
|
@ -13,23 +13,59 @@ on:
|
|||
inputs:
|
||||
enable_debug:
|
||||
description: "enable terraform debug logs"
|
||||
default: 'false'
|
||||
type: boolean
|
||||
default: false
|
||||
required: true
|
||||
|
||||
test_timeout_string:
|
||||
description: "string that determines the timeout (default: 45m)"
|
||||
default: '90m'
|
||||
description: "string that determines the timeout (default: '120m')"
|
||||
type: string
|
||||
default: '120m'
|
||||
required: true
|
||||
|
||||
test_file:
|
||||
description: "string that determines the test file to run (default all tests)"
|
||||
type: choice
|
||||
options:
|
||||
- tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/postgresflexalpha
|
||||
- tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha
|
||||
- tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexbeta
|
||||
- tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
acc_test:
|
||||
name: Acceptance Tests
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: stackit-docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: set start time
|
||||
id: start_time
|
||||
continue-on-error: true
|
||||
run: |
|
||||
time=$(date --rfc-3339=ns)
|
||||
echo "start_time=$time" >> ${GITHUB_OUTPUT}
|
||||
start=$(date +%s%N)
|
||||
echo "start=$start" >> ${GITHUB_OUTPUT}
|
||||
|
||||
- name: Notify
|
||||
uses: ./.github/actions/notify
|
||||
with:
|
||||
webhook_url: ${{ secrets.GOOGLE_WEBHOOK_URL }}
|
||||
title: "[START] Terraform Acceptance Tests (#${{ forgejo.run_number }})"
|
||||
subtitle: "${{ forgejo.event_name }} on branch ${{ forgejo.ref }}"
|
||||
event_title: "started: ${{ steps.start_time.outputs.start_time }}"
|
||||
event_author: ${{ forgejo.actor }}
|
||||
event_body: ${{ inputs.test_file }}
|
||||
event_number: ${{ forgejo.run_number }}
|
||||
event_url: "https://tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/actions/runs/${{ forgejo.run_number }}"
|
||||
|
||||
- name: Run Test (workflow dispatch)
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
if: ${{ forgejo.event_name == 'workflow_dispatch' }}
|
||||
id: manual_run
|
||||
continue-on-error: true
|
||||
uses: ./.github/actions/acc_test
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
|
@ -43,9 +79,12 @@ jobs:
|
|||
tf_acc_kek_service_account: ${{ vars.TF_ACC_KEK_SERVICE_ACCOUNT }}
|
||||
tf_debug: ${{ inputs.enable_debug }}
|
||||
test_timeout_string: ${{ inputs.test_timeout_string }}
|
||||
test_file: ${{ inputs.test_file }}
|
||||
|
||||
- name: Run Test (automatic)
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
if: ${{ forgejo.event_name != 'workflow_dispatch' }}
|
||||
id: automatic_run
|
||||
continue-on-error: true
|
||||
uses: ./.github/actions/acc_test
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
|
@ -57,4 +96,32 @@ jobs:
|
|||
tf_acc_kek_key_ring_id: ${{ vars.TF_ACC_KEK_KEY_RING_ID }}
|
||||
tf_acc_kek_key_version: ${{ vars.TF_ACC_KEK_KEY_VERSION }}
|
||||
tf_acc_kek_service_account: ${{ vars.TF_ACC_KEK_SERVICE_ACCOUNT }}
|
||||
tf_debug: ${{ inputs.enable_debug }}
|
||||
|
||||
- name: set end time
|
||||
id: end_time
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set -e
|
||||
echo "auto status: ${{ steps.automatic_run.outputs.status }}"
|
||||
echo "manual status: ${{ steps.manual_run.outputs.status }}"
|
||||
echo "status: ${{ forgejo.event_name == 'workflow_dispatch' && steps.manual_run.outputs.status || steps.automatic_run.outputs.status }}"
|
||||
echo "end_time=$(date --rfc-3339=ns)" >> ${GITHUB_OUTPUT}
|
||||
end=$(date +%s%N)
|
||||
echo "end=${end}" >> ${GITHUB_OUTPUT}
|
||||
start=${{ steps.start_time.outputs.start }}
|
||||
diff=$((end-start))
|
||||
duration=$(printf "%s.%s" "${diff:0: -9}" "${diff: -9:3}")
|
||||
echo "duration=${duration}" >> ${GITHUB_OUTPUT}
|
||||
|
||||
- name: Notify
|
||||
uses: ./.github/actions/notify
|
||||
with:
|
||||
webhook_url: ${{ secrets.GOOGLE_WEBHOOK_URL }}
|
||||
title: "[END] Terraform Acceptance Tests (#${{ forgejo.run_number }})"
|
||||
subtitle: "${{ forgejo.event_name }} on branch ${{ forgejo.ref }} with status: ${{ forgejo.event_name == 'workflow_dispatch' && steps.manual_run.outputs.status || steps.automatic_run.outputs.status }}"
|
||||
event_title: "run ended: ${{ steps.end_time.outputs.end_time }}, duration: ${{ steps.end_time.outputs.duration }} seconds"
|
||||
event_author: ${{ forgejo.actor }}
|
||||
event_body: "${{ forgejo.event_name == 'workflow_dispatch' && steps.manual_run.outputs.result || steps.automatic_run.outputs.result }}"
|
||||
event_number: ${{ forgejo.event.id }}
|
||||
event_url: "https://tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/actions/runs/${{ forgejo.run_number }}"
|
||||
status: "${{ forgejo.event_name == 'workflow_dispatch' && steps.manual_run.outputs.status || steps.automatic_run.outputs.status }}"
|
||||
|
|
|
|||
|
|
@ -42,10 +42,16 @@ data "stackitprivatepreview_postgresflexalpha_instance" "example" {
|
|||
- `flavor_id` (String) The id of the instance flavor.
|
||||
- `id` (String) internal ID
|
||||
- `is_deletable` (Boolean) Whether the instance can be deleted or not.
|
||||
- `labels` (Map of String) Key-value pairs, 63 characters max, begin and end with an alphanumerical character,
|
||||
may contain dashes (-), underscores (_), dots (.), and alphanumerics between. Key MUST be at least 1 character.
|
||||
Max 64 labels
|
||||
Regex for keys: ^(?=.{1,63}$)([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$
|
||||
Regex for values: ^(?=.{0,63}$)(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])*$
|
||||
The stackit- prefix is reserved and cannot be used for Keys.
|
||||
- `name` (String) The name of the instance.
|
||||
- `network` (Attributes) The access configuration of the instance (see [below for nested schema](#nestedatt--network))
|
||||
- `replicas` (Number) How many replicas the instance should have.
|
||||
- `retention_days` (Number) How long backups are retained. The value can only be between 32 and 365 days.
|
||||
- `retention_days` (Number) How long backups are retained. The value can only be between 32 and 90 days.
|
||||
- `status` (String) The current status of the instance.
|
||||
- `storage` (Attributes) The object containing information about the storage size and class. (see [below for nested schema](#nestedatt--storage))
|
||||
- `tf_original_api_id` (String) The ID of the instance.
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "stackitprivatepreview_sqlserverflexalpha_database Data Source - stackitprivatepreview"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
|
||||
---
|
||||
|
||||
# stackitprivatepreview_sqlserverflexalpha_database (Data Source)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `database_name` (String) The name of the database.
|
||||
- `instance_id` (String) The ID of the instance.
|
||||
- `project_id` (String) The STACKIT project ID.
|
||||
- `region` (String) The region which should be addressed
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `collation_name` (String) The collation of the database. This database collation should match the *collation_name* of one of the collations given by the **Get database collation list** endpoint.
|
||||
- `compatibility_level` (Number) CompatibilityLevel of the Database.
|
||||
- `id` (String) The terraform internal identifier.
|
||||
- `name` (String) The name of the database.
|
||||
- `owner` (String) The owner of the database.
|
||||
- `tf_original_api_id` (Number) The id of the database.
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "stackitprivatepreview_sqlserverflexalpha_instance Data Source - stackitprivatepreview"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
|
||||
---
|
||||
|
||||
# stackitprivatepreview_sqlserverflexalpha_instance (Data Source)
|
||||
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
data "stackitprivatepreview_sqlserverflexalpha_instance" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
instance_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `instance_id` (String) The ID of the instance.
|
||||
- `project_id` (String) The STACKIT project ID.
|
||||
- `region` (String) The region which should be addressed
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `backup_schedule` (String) The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.
|
||||
- `edition` (String) Edition of the MSSQL server instance
|
||||
- `encryption` (Attributes) this defines which key to use for storage encryption (see [below for nested schema](#nestedatt--encryption))
|
||||
- `flavor_id` (String) The id of the instance flavor.
|
||||
- `is_deletable` (Boolean) Whether the instance can be deleted or not.
|
||||
- `name` (String) The name of the instance.
|
||||
- `network` (Attributes) The access configuration of the instance (see [below for nested schema](#nestedatt--network))
|
||||
- `replicas` (Number) How many replicas the instance should have.
|
||||
- `retention_days` (Number) The days for how long the backup files should be stored before cleaned up. 30 to 365
|
||||
- `status` (String)
|
||||
- `storage` (Attributes) The object containing information about the storage size and class. (see [below for nested schema](#nestedatt--storage))
|
||||
- `tf_original_api_id` (String) The ID of the instance.
|
||||
- `version` (String) The sqlserver version used for the instance.
|
||||
|
||||
<a id="nestedatt--encryption"></a>
|
||||
### Nested Schema for `encryption`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `kek_key_id` (String) The key identifier
|
||||
- `kek_key_ring_id` (String) The keyring identifier
|
||||
- `kek_key_version` (String) The key version
|
||||
- `service_account` (String)
|
||||
|
||||
|
||||
<a id="nestedatt--network"></a>
|
||||
### Nested Schema for `network`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `access_scope` (String) The network access scope of the instance
|
||||
|
||||
⚠️ **Note:** This feature is in private preview. Supplying this object is only permitted for enabled accounts. If your account does not have access, the request will be rejected.
|
||||
- `acl` (List of String) List of IPV4 cidr.
|
||||
- `instance_address` (String)
|
||||
- `router_address` (String)
|
||||
|
||||
|
||||
<a id="nestedatt--storage"></a>
|
||||
### Nested Schema for `storage`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `class` (String) The storage class for the storage.
|
||||
- `size` (Number) The storage size in Gigabytes.
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "stackitprivatepreview_sqlserverflexalpha_user Data Source - stackitprivatepreview"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
|
||||
---
|
||||
|
||||
# stackitprivatepreview_sqlserverflexalpha_user (Data Source)
|
||||
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
data "stackitprivatepreview_sqlserverflexalpha_user" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
instance_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
user_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `instance_id` (String) The ID of the instance.
|
||||
- `project_id` (String) The STACKIT project ID.
|
||||
- `region` (String) The region which should be addressed
|
||||
|
||||
### Optional
|
||||
|
||||
- `page` (Number) Number of the page of items list to be returned.
|
||||
- `size` (Number) Number of items to be returned on each page.
|
||||
- `sort` (String) Sorting of the users to be returned on each page.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `pagination` (Attributes) (see [below for nested schema](#nestedatt--pagination))
|
||||
- `users` (Attributes List) List of all users inside an instance (see [below for nested schema](#nestedatt--users))
|
||||
|
||||
<a id="nestedatt--pagination"></a>
|
||||
### Nested Schema for `pagination`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `page` (Number)
|
||||
- `size` (Number)
|
||||
- `sort` (String)
|
||||
- `total_pages` (Number)
|
||||
- `total_rows` (Number)
|
||||
|
||||
|
||||
<a id="nestedatt--users"></a>
|
||||
### Nested Schema for `users`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `status` (String) The current status of the user.
|
||||
- `tf_original_api_id` (Number) The ID of the user.
|
||||
- `username` (String) The name of the user.
|
||||
54
docs/data-sources/sqlserverflexbeta_flavor.md
Normal file
54
docs/data-sources/sqlserverflexbeta_flavor.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "stackitprivatepreview_sqlserverflexbeta_flavor Data Source - stackitprivatepreview"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
|
||||
---
|
||||
|
||||
# stackitprivatepreview_sqlserverflexbeta_flavor (Data Source)
|
||||
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
data "stackitprivatepreview_sqlserverflexbeta_flavor" "flavor" {
|
||||
project_id = var.project_id
|
||||
region = var.region
|
||||
cpu = 4
|
||||
ram = 16
|
||||
node_type = "Single"
|
||||
storage_class = "premium-perf2-stackit"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `cpu` (Number) The cpu count of the instance.
|
||||
- `node_type` (String) defines the nodeType it can be either single or HA
|
||||
- `project_id` (String) The project ID of the flavor.
|
||||
- `ram` (Number) The memory of the instance in Gibibyte.
|
||||
- `region` (String) The region of the flavor.
|
||||
- `storage_class` (String) The memory of the instance in Gibibyte.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `description` (String) The flavor description.
|
||||
- `flavor_id` (String) The id of the instance flavor.
|
||||
- `id` (String) The id of the instance flavor.
|
||||
- `max_gb` (Number) maximum storage which can be ordered for the flavor in Gigabyte.
|
||||
- `min_gb` (Number) minimum storage which is required to order in Gigabyte.
|
||||
- `storage_classes` (Attributes List) maximum storage which can be ordered for the flavor in Gigabyte. (see [below for nested schema](#nestedatt--storage_classes))
|
||||
|
||||
<a id="nestedatt--storage_classes"></a>
|
||||
### Nested Schema for `storage_classes`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `class` (String)
|
||||
- `max_io_per_sec` (Number)
|
||||
- `max_through_in_mb` (Number)
|
||||
|
|
@ -13,6 +13,33 @@ description: |-
|
|||
## Example Usage
|
||||
|
||||
```terraform
|
||||
# NOTE: flavor handling will change in future
|
||||
# V2 compatible flavor usage (example without encryption)
|
||||
resource "stackitprivatepreview_postgresflexalpha_instance" "example-instance" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
acl = ["XXX.XXX.XXX.X/XX", "XX.XXX.XX.X/XX"]
|
||||
backup_schedule = "0 0 * * *"
|
||||
retention_days = 30
|
||||
flavor = {
|
||||
cpu = 2
|
||||
ram = 4
|
||||
}
|
||||
replicas = 1
|
||||
storage = {
|
||||
performance_class = "premium-perf2-stackit"
|
||||
size = 10
|
||||
}
|
||||
network = {
|
||||
acl = ["XXX.XXX.XXX.X/XX", "XX.XXX.XX.X/XX"]
|
||||
access_scope = "PUBLIC"
|
||||
}
|
||||
version = 17
|
||||
}
|
||||
|
||||
# future use of flavor (implemented in V3 API)
|
||||
# first determine flavor and then use the flavor_id
|
||||
|
||||
resource "stackitprivatepreview_postgresflexalpha_instance" "example-instance" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
|
|
@ -60,11 +87,10 @@ import {
|
|||
### Required
|
||||
|
||||
- `backup_schedule` (String) The schedule for when the database backup will be created. Currently, ONLY daily schedules are supported (every 24 hours). The schedule is written as a cron schedule.
|
||||
- `flavor_id` (String) The id of the instance flavor.
|
||||
- `name` (String) The name of the instance.
|
||||
- `network` (Attributes) The access configuration of the instance (see [below for nested schema](#nestedatt--network))
|
||||
- `replicas` (Number) How many replicas the instance should have.
|
||||
- `retention_days` (Number) How long backups are retained. The value can only be between 32 and 365 days.
|
||||
- `retention_days` (Number) How long backups are retained. The value can only be between 32 and 90 days.
|
||||
- `storage` (Attributes) The object containing information about the storage size and class. (see [below for nested schema](#nestedatt--storage))
|
||||
- `version` (String) The Postgres version used for the instance. See [Versions Endpoint](/documentation/postgres-flex-service/version/v3alpha1#tag/Version) for supported version parameters.
|
||||
|
||||
|
|
@ -73,6 +99,8 @@ import {
|
|||
- `encryption` (Attributes) The configuration for instance's volume and backup storage encryption.
|
||||
|
||||
⚠︝ **Note:** This feature is in private preview. Supplying this object is only permitted for enabled accounts. If your account does not have access, the request will be rejected. (see [below for nested schema](#nestedatt--encryption))
|
||||
- `flavor` (Attributes, Deprecated) (see [below for nested schema](#nestedatt--flavor))
|
||||
- `flavor_id` (String) The id of the instance flavor.
|
||||
- `instance_id` (String) The ID of the instance.
|
||||
- `project_id` (String) The STACKIT project ID.
|
||||
- `region` (String) The region which should be addressed
|
||||
|
|
@ -122,6 +150,20 @@ Required:
|
|||
- `service_account` (String)
|
||||
|
||||
|
||||
<a id="nestedatt--flavor"></a>
|
||||
### Nested Schema for `flavor`
|
||||
|
||||
Optional:
|
||||
|
||||
- `cpu` (Number, Deprecated)
|
||||
- `ram` (Number, Deprecated)
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `description` (String)
|
||||
- `id` (String)
|
||||
|
||||
|
||||
<a id="nestedatt--connection_info"></a>
|
||||
### Nested Schema for `connection_info`
|
||||
|
||||
|
|
|
|||
|
|
@ -1,63 +0,0 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "stackitprivatepreview_sqlserverflexalpha_database Resource - stackitprivatepreview"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
|
||||
---
|
||||
|
||||
# stackitprivatepreview_sqlserverflexalpha_database (Resource)
|
||||
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "stackitprivatepreview_sqlserverflexalpha_database" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
instance_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
collation = ""
|
||||
compatibility = "160"
|
||||
name = ""
|
||||
owner = ""
|
||||
}
|
||||
|
||||
# Only use the import statement, if you want to import a existing sqlserverflex database
|
||||
import {
|
||||
to = stackitprivatepreview_sqlserverflexalpha_database.import-example
|
||||
id = "${var.project_id},${var.region},${var.sql_instance_id},${var.sql_user_id}"
|
||||
}
|
||||
|
||||
import {
|
||||
to = stackitprivatepreview_sqlserverflexalpha_database.import-example
|
||||
identity = {
|
||||
project_id = "project.id"
|
||||
region = "region"
|
||||
instance_id = "instance.id"
|
||||
database_id = "database.id"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `name` (String) The name of the database.
|
||||
- `owner` (String) The owner of the database.
|
||||
|
||||
### Optional
|
||||
|
||||
- `collation` (String) The collation of the database. This database collation should match the *collation_name* of one of the collations given by the **Get database collation list** endpoint.
|
||||
- `compatibility` (Number) CompatibilityLevel of the Database.
|
||||
- `database_name` (String) The name of the database.
|
||||
- `instance_id` (String) The ID of the instance.
|
||||
- `project_id` (String) The STACKIT project ID.
|
||||
- `region` (String) The region which should be addressed
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `collation_name` (String) The collation of the database. This database collation should match the *collation_name* of one of the collations given by the **Get database collation list** endpoint.
|
||||
- `compatibility_level` (Number) CompatibilityLevel of the Database.
|
||||
- `id` (Number) The id of the database.
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "stackitprivatepreview_sqlserverflexalpha_instance Resource - stackitprivatepreview"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
|
||||
---
|
||||
|
||||
# stackitprivatepreview_sqlserverflexalpha_instance (Resource)
|
||||
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "stackitprivatepreview_sqlserverflexalpha_instance" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
acl = ["XXX.XXX.XXX.X/XX", "XX.XXX.XX.X/XX"]
|
||||
backup_schedule = "00 00 * * *"
|
||||
flavor = {
|
||||
cpu = 4
|
||||
ram = 16
|
||||
}
|
||||
storage = {
|
||||
class = "class"
|
||||
size = 5
|
||||
}
|
||||
version = 2022
|
||||
}
|
||||
|
||||
# Only use the import statement, if you want to import an existing sqlserverflex instance
|
||||
import {
|
||||
to = stackitprivatepreview_sqlserverflexalpha_instance.import-example
|
||||
id = "${var.project_id},${var.region},${var.sql_instance_id}"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `backup_schedule` (String) The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.
|
||||
- `flavor_id` (String) The id of the instance flavor.
|
||||
- `name` (String) The name of the instance.
|
||||
- `network` (Attributes) the network configuration of the instance. (see [below for nested schema](#nestedatt--network))
|
||||
- `retention_days` (Number) The days for how long the backup files should be stored before cleaned up. 30 to 365
|
||||
- `storage` (Attributes) The object containing information about the storage size and class. (see [below for nested schema](#nestedatt--storage))
|
||||
- `version` (String) The sqlserver version used for the instance.
|
||||
|
||||
### Optional
|
||||
|
||||
- `encryption` (Attributes) this defines which key to use for storage encryption (see [below for nested schema](#nestedatt--encryption))
|
||||
- `instance_id` (String) The ID of the instance.
|
||||
- `project_id` (String) The STACKIT project ID.
|
||||
- `region` (String) The region which should be addressed
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `edition` (String) Edition of the MSSQL server instance
|
||||
- `id` (String) The ID of the instance.
|
||||
- `is_deletable` (Boolean) Whether the instance can be deleted or not.
|
||||
- `replicas` (Number) How many replicas the instance should have.
|
||||
- `status` (String)
|
||||
|
||||
<a id="nestedatt--network"></a>
|
||||
### Nested Schema for `network`
|
||||
|
||||
Required:
|
||||
|
||||
- `acl` (List of String) List of IPV4 cidr.
|
||||
|
||||
Optional:
|
||||
|
||||
- `access_scope` (String) The network access scope of the instance
|
||||
|
||||
⚠️ **Note:** This feature is in private preview. Supplying this object is only permitted for enabled accounts. If your account does not have access, the request will be rejected.
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `instance_address` (String)
|
||||
- `router_address` (String)
|
||||
|
||||
|
||||
<a id="nestedatt--storage"></a>
|
||||
### Nested Schema for `storage`
|
||||
|
||||
Required:
|
||||
|
||||
- `class` (String) The storage class for the storage.
|
||||
- `size` (Number) The storage size in Gigabytes.
|
||||
|
||||
|
||||
<a id="nestedatt--encryption"></a>
|
||||
### Nested Schema for `encryption`
|
||||
|
||||
Required:
|
||||
|
||||
- `kek_key_id` (String) The key identifier
|
||||
- `kek_key_ring_id` (String) The keyring identifier
|
||||
- `kek_key_version` (String) The key version
|
||||
- `service_account` (String)
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "stackitprivatepreview_sqlserverflexalpha_user Resource - stackitprivatepreview"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
|
||||
---
|
||||
|
||||
# stackitprivatepreview_sqlserverflexalpha_user (Resource)
|
||||
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "stackitprivatepreview_sqlserverflexalpha_user" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
instance_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
username = "username"
|
||||
roles = ["role"]
|
||||
}
|
||||
|
||||
# Only use the import statement, if you want to import an existing sqlserverflex user
|
||||
import {
|
||||
to = stackitprivatepreview_sqlserverflexalpha_user.import-example
|
||||
id = "${var.project_id},${var.region},${var.sql_instance_id},${var.sql_user_id}"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `roles` (List of String) A list containing the user roles for the instance. A list with the valid user roles can be retrieved using the List Roles endpoint.
|
||||
- `username` (String) The name of the user.
|
||||
|
||||
### Optional
|
||||
|
||||
- `default_database` (String) The default database for a user of the instance.
|
||||
- `instance_id` (String) The ID of the instance.
|
||||
- `project_id` (String) The STACKIT project ID.
|
||||
- `region` (String) The region which should be addressed
|
||||
- `user_id` (Number) The ID of the user.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `host` (String) The host of the instance in which the user belongs to.
|
||||
- `id` (Number) The ID of the user.
|
||||
- `password` (String) The password for the user.
|
||||
- `port` (Number) The port of the instance in which the user belongs to.
|
||||
- `status` (String) The current status of the user.
|
||||
- `uri` (String) The connection string for the user to the instance.
|
||||
|
|
@ -13,6 +13,31 @@ description: |-
|
|||
## Example Usage
|
||||
|
||||
```terraform
|
||||
# NOTE: flavor handling will change in future
|
||||
# V2 compatible flavor usage
|
||||
resource "stackitprivatepreview_sqlserverflexbeta_instance" "instance" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
backup_schedule = "0 3 * * *"
|
||||
retention_days = 31
|
||||
flavor = {
|
||||
cpu = 2
|
||||
ram = 4
|
||||
}
|
||||
storage = {
|
||||
class = "premium-perf2-stackit"
|
||||
size = 50
|
||||
}
|
||||
version = 2022
|
||||
network = {
|
||||
acl = ["XXX.XXX.XXX.X/XX", "XX.XXX.XX.X/XX"]
|
||||
access_scope = "SNA"
|
||||
}
|
||||
}
|
||||
|
||||
# future use of flavor (implemented in V3 API)
|
||||
# first determine flavor and then use the flavor_id
|
||||
|
||||
# without encryption and SNA
|
||||
resource "stackitprivatepreview_sqlserverflexbeta_instance" "instance" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
|
|
@ -97,7 +122,6 @@ import {
|
|||
### Required
|
||||
|
||||
- `backup_schedule` (String) The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.
|
||||
- `flavor_id` (String) The id of the instance flavor.
|
||||
- `name` (String) The name of the instance.
|
||||
- `network` (Attributes) the network configuration of the instance. (see [below for nested schema](#nestedatt--network))
|
||||
- `retention_days` (Number) The days for how long the backup files should be stored before cleaned up. 30 to 365
|
||||
|
|
@ -107,6 +131,8 @@ import {
|
|||
### Optional
|
||||
|
||||
- `encryption` (Attributes) this defines which key to use for storage encryption (see [below for nested schema](#nestedatt--encryption))
|
||||
- `flavor` (Attributes, Deprecated) (see [below for nested schema](#nestedatt--flavor))
|
||||
- `flavor_id` (String) The id of the instance flavor.
|
||||
- `instance_id` (String) The ID of the instance.
|
||||
- `project_id` (String) The STACKIT project ID.
|
||||
- `region` (String) The region which should be addressed
|
||||
|
|
@ -156,3 +182,17 @@ Required:
|
|||
- `kek_key_ring_id` (String) The keyring identifier
|
||||
- `kek_key_version` (String) The key version
|
||||
- `service_account` (String)
|
||||
|
||||
|
||||
<a id="nestedatt--flavor"></a>
|
||||
### Nested Schema for `flavor`
|
||||
|
||||
Optional:
|
||||
|
||||
- `cpu` (Number, Deprecated)
|
||||
- `ram` (Number, Deprecated)
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `description` (String)
|
||||
- `id` (String)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,30 @@
|
|||
# NOTE: flavor handling will change in future
|
||||
# V2 compatible flavor usage (example without encryption)
|
||||
resource "stackitprivatepreview_postgresflexalpha_instance" "example-instance" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
acl = ["XXX.XXX.XXX.X/XX", "XX.XXX.XX.X/XX"]
|
||||
backup_schedule = "0 0 * * *"
|
||||
retention_days = 30
|
||||
flavor = {
|
||||
cpu = 2
|
||||
ram = 4
|
||||
}
|
||||
replicas = 1
|
||||
storage = {
|
||||
performance_class = "premium-perf2-stackit"
|
||||
size = 10
|
||||
}
|
||||
network = {
|
||||
acl = ["XXX.XXX.XXX.X/XX", "XX.XXX.XX.X/XX"]
|
||||
access_scope = "PUBLIC"
|
||||
}
|
||||
version = 17
|
||||
}
|
||||
|
||||
# future use of flavor (implemented in V3 API)
|
||||
# first determine flavor and then use the flavor_id
|
||||
|
||||
resource "stackitprivatepreview_postgresflexalpha_instance" "example-instance" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,28 @@
|
|||
# NOTE: flavor handling will change in future
|
||||
# V2 compatible flavor usage
|
||||
resource "stackitprivatepreview_sqlserverflexbeta_instance" "instance" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-instance"
|
||||
backup_schedule = "0 3 * * *"
|
||||
retention_days = 31
|
||||
flavor = {
|
||||
cpu = 2
|
||||
ram = 4
|
||||
}
|
||||
storage = {
|
||||
class = "premium-perf2-stackit"
|
||||
size = 50
|
||||
}
|
||||
version = 2022
|
||||
network = {
|
||||
acl = ["XXX.XXX.XXX.X/XX", "XX.XXX.XX.X/XX"]
|
||||
access_scope = "SNA"
|
||||
}
|
||||
}
|
||||
|
||||
# future use of flavor (implemented in V3 API)
|
||||
# first determine flavor and then use the flavor_id
|
||||
|
||||
# without encryption and SNA
|
||||
resource "stackitprivatepreview_sqlserverflexbeta_instance" "instance" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
|
|
|
|||
|
|
@ -172,12 +172,12 @@ func workDocs() error {
|
|||
case "data-sources":
|
||||
dataSources[matches[0][1]] = append(dataSources[matches[0][1]], ResItem{
|
||||
ItemName: matches[0][2],
|
||||
ItemLink: fmt.Sprintf("docs/%s/%s", entry.Name(), matches[0][0]),
|
||||
ItemLink: fmt.Sprintf("/docs/docs/%s/%s", entry.Name(), matches[0][0]),
|
||||
})
|
||||
case "resources":
|
||||
resources[matches[0][1]] = append(resources[matches[0][1]], ResItem{
|
||||
ItemName: matches[0][2],
|
||||
ItemLink: fmt.Sprintf("docs/%s/%s", entry.Name(), matches[0][0]),
|
||||
ItemLink: fmt.Sprintf("/docs/docs/%s/%s", entry.Name(), matches[0][0]),
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("this should never have happened")
|
||||
|
|
|
|||
253
go.mod
253
go.mod
|
|
@ -1,26 +1,25 @@
|
|||
module tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview
|
||||
|
||||
go 1.25.6
|
||||
go 1.26.2
|
||||
|
||||
require (
|
||||
github.com/SladkyCitron/slogcolor v1.8.0
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
github.com/SladkyCitron/slogcolor v1.9.0
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/hashicorp/terraform-plugin-framework v1.18.0
|
||||
github.com/hashicorp/terraform-plugin-framework v1.19.0
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.19.0
|
||||
github.com/hashicorp/terraform-plugin-go v0.30.0
|
||||
github.com/hashicorp/terraform-plugin-go v0.31.0
|
||||
github.com/hashicorp/terraform-plugin-log v0.10.0
|
||||
github.com/hashicorp/terraform-plugin-testing v1.14.0
|
||||
github.com/hashicorp/terraform-plugin-testing v1.16.0
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/ivanpirog/coloredcobra v1.0.1
|
||||
github.com/jarcoal/httpmock v1.4.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/ldez/go-git-cmd-wrapper/v2 v2.9.1
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/stackitcloud/stackit-sdk-go/core v0.22.0
|
||||
github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.4.0
|
||||
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.5.0
|
||||
github.com/stackitcloud/stackit-sdk-go/core v0.26.0
|
||||
github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.8.0
|
||||
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.10.0
|
||||
github.com/teambition/rrule-go v1.8.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
|
@ -28,261 +27,77 @@ require (
|
|||
require github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
||||
|
||||
require (
|
||||
4d63.com/gocheckcompilerdirectives v1.3.0 // indirect
|
||||
4d63.com/gochecknoglobals v0.2.2 // indirect
|
||||
codeberg.org/chavacava/garif v0.2.0 // indirect
|
||||
codeberg.org/polyfloyd/go-errorlint v1.9.0 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect
|
||||
dev.gaijin.team/go/golib v0.6.0 // indirect
|
||||
github.com/4meepo/tagalign v1.4.3 // indirect
|
||||
github.com/Abirdcfly/dupword v0.1.7 // indirect
|
||||
github.com/AdminBenni/iota-mixing v1.0.0 // indirect
|
||||
github.com/AlwxSin/noinlineerr v1.0.5 // indirect
|
||||
github.com/Antonboom/errname v1.1.1 // indirect
|
||||
github.com/Antonboom/nilnil v1.1.1 // indirect
|
||||
github.com/Antonboom/testifylint v1.6.4 // indirect
|
||||
github.com/BurntSushi/toml v1.6.0 // indirect
|
||||
github.com/Djarvur/go-err113 v0.1.1 // indirect
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/MirrexOne/unqueryvet v1.5.4 // indirect
|
||||
github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.4.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.4.1 // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/alecthomas/chroma/v2 v2.23.1 // indirect
|
||||
github.com/alecthomas/go-check-sumtype v0.3.1 // indirect
|
||||
github.com/alexkohler/nakedret/v2 v2.0.6 // indirect
|
||||
github.com/alexkohler/prealloc v1.1.0 // indirect
|
||||
github.com/alfatraining/structtag v1.0.0 // indirect
|
||||
github.com/alingse/asasalint v0.0.11 // indirect
|
||||
github.com/alingse/nilnesserr v0.2.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/ashanbrown/forbidigo/v2 v2.3.0 // indirect
|
||||
github.com/ashanbrown/makezero/v2 v2.1.0 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||
github.com/bkielbasa/cyclop v1.2.3 // indirect
|
||||
github.com/blizzy78/varnamelen v0.8.0 // indirect
|
||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||
github.com/bombsimon/wsl/v4 v4.7.0 // indirect
|
||||
github.com/bombsimon/wsl/v5 v5.6.0 // indirect
|
||||
github.com/breml/bidichk v0.3.3 // indirect
|
||||
github.com/breml/errchkjson v0.4.1 // indirect
|
||||
github.com/butuzov/ireturn v0.4.0 // indirect
|
||||
github.com/butuzov/mirror v1.3.0 // indirect
|
||||
github.com/catenacyber/perfsprint v0.10.1 // indirect
|
||||
github.com/ccojocar/zxcvbn-go v1.0.4 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/charithe/durationcheck v0.0.11 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.10.1 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
|
||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||
github.com/ckaznocha/intrange v0.3.1 // indirect
|
||||
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/curioswitch/go-reassign v0.3.0 // indirect
|
||||
github.com/daixiang0/gci v0.13.7 // indirect
|
||||
github.com/dave/dst v0.27.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/denis-tingaikin/go-header v0.5.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||
github.com/ettle/strcase v0.2.0 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fatih/structtag v1.2.0 // indirect
|
||||
github.com/firefart/nonamedreturns v1.0.6 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/fzipp/gocyclo v0.6.0 // indirect
|
||||
github.com/ghostiam/protogetter v0.3.20 // indirect
|
||||
github.com/go-critic/go-critic v0.14.3 // indirect
|
||||
github.com/go-toolsmith/astcast v1.1.0 // indirect
|
||||
github.com/go-toolsmith/astcopy v1.1.0 // indirect
|
||||
github.com/go-toolsmith/astequal v1.2.0 // indirect
|
||||
github.com/go-toolsmith/astfmt v1.1.0 // indirect
|
||||
github.com/go-toolsmith/astp v1.1.0 // indirect
|
||||
github.com/go-toolsmith/strparse v1.1.0 // indirect
|
||||
github.com/go-toolsmith/typep v1.1.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||
github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/godoc-lint/godoc-lint v0.11.2 // indirect
|
||||
github.com/gofrs/flock v0.13.0 // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golangci/asciicheck v0.5.0 // indirect
|
||||
github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect
|
||||
github.com/golangci/go-printf-func-name v0.1.1 // indirect
|
||||
github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect
|
||||
github.com/golangci/golangci-lint/v2 v2.11.2 // indirect
|
||||
github.com/golangci/golines v0.15.0 // indirect
|
||||
github.com/golangci/misspell v0.8.0 // indirect
|
||||
github.com/golangci/plugin-module-register v0.1.2 // indirect
|
||||
github.com/golangci/revgrep v0.8.0 // indirect
|
||||
github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect
|
||||
github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect
|
||||
github.com/gordonklaus/ineffassign v0.2.0 // indirect
|
||||
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
|
||||
github.com/gostaticanalysis/comment v1.5.0 // indirect
|
||||
github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect
|
||||
github.com/gostaticanalysis/nilerr v0.1.2 // indirect
|
||||
github.com/hashicorp/cli v1.1.7 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-cty v1.5.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.7.0 // indirect
|
||||
github.com/hashicorp/go-plugin v1.8.0 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.8.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hc-install v0.9.3 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.9.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.9.5 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.24.0 // indirect
|
||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.25.0 // indirect
|
||||
github.com/hashicorp/terraform-json v0.27.2 // indirect
|
||||
github.com/hashicorp/terraform-plugin-docs v0.24.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.25.2 // indirect
|
||||
github.com/hashicorp/terraform-json v0.27.3-0.20260213134036-298b8f6b673a // indirect
|
||||
github.com/hashicorp/terraform-plugin-docs v0.25.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.40.1 // indirect
|
||||
github.com/hashicorp/terraform-registry-address v0.4.0 // indirect
|
||||
github.com/hashicorp/terraform-svchost v0.2.1 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/hexops/gotextdiff v1.0.3 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/imdario/mergo v0.3.15 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jgautheron/goconst v1.8.2 // indirect
|
||||
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
|
||||
github.com/jjti/go-spancheck v0.6.5 // indirect
|
||||
github.com/julz/importas v0.2.0 // indirect
|
||||
github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect
|
||||
github.com/kisielk/errcheck v1.10.0 // indirect
|
||||
github.com/kkHAIKE/contextcheck v1.1.6 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/kulti/thelper v0.7.1 // indirect
|
||||
github.com/kunwardeep/paralleltest v1.0.15 // indirect
|
||||
github.com/lasiar/canonicalheader v1.1.2 // indirect
|
||||
github.com/ldez/exptostd v0.4.5 // indirect
|
||||
github.com/ldez/gomoddirectives v0.8.0 // indirect
|
||||
github.com/ldez/grignotin v0.10.1 // indirect
|
||||
github.com/ldez/structtags v0.6.1 // indirect
|
||||
github.com/ldez/tagliatelle v0.7.2 // indirect
|
||||
github.com/ldez/usetesting v0.5.0 // indirect
|
||||
github.com/leonklingele/grouper v1.1.2 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/macabu/inamedparam v0.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect
|
||||
github.com/manuelarte/funcorder v0.5.0 // indirect
|
||||
github.com/maratori/testableexamples v1.0.1 // indirect
|
||||
github.com/maratori/testpackage v1.1.2 // indirect
|
||||
github.com/matoous/godox v1.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mgechev/revive v1.15.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.22 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moricho/tparallel v0.3.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/nakabonne/nestif v0.3.1 // indirect
|
||||
github.com/nishanths/exhaustive v0.12.0 // indirect
|
||||
github.com/nishanths/predeclared v0.2.2 // indirect
|
||||
github.com/nunnatsa/ginkgolinter v0.23.0 // indirect
|
||||
github.com/oklog/run v1.2.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/posener/complete v1.2.3 // indirect
|
||||
github.com/prometheus/client_golang v1.12.1 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/quasilyte/go-ruleguard v0.4.5 // indirect
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.23 // indirect
|
||||
github.com/quasilyte/gogrep v0.5.0 // indirect
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
|
||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
|
||||
github.com/raeperd/recvcheck v0.2.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/ryancurrah/gomodguard v1.4.1 // indirect
|
||||
github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
|
||||
github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
|
||||
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
|
||||
github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect
|
||||
github.com/securego/gosec/v2 v2.24.7 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||
github.com/sivchari/containedctx v1.0.3 // indirect
|
||||
github.com/sonatard/noctx v0.5.0 // indirect
|
||||
github.com/sourcegraph/go-diff v0.7.0 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/spf13/viper v1.12.0 // indirect
|
||||
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
|
||||
github.com/stbenjam/no-sprintf-host-port v0.3.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/tetafro/godot v1.5.4 // indirect
|
||||
github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect
|
||||
github.com/timonwong/loggercheck v0.11.0 // indirect
|
||||
github.com/tomarrell/wrapcheck/v2 v2.12.0 // indirect
|
||||
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
|
||||
github.com/ultraware/funlen v0.2.0 // indirect
|
||||
github.com/ultraware/whitespace v0.2.0 // indirect
|
||||
github.com/uudashr/gocognit v1.2.1 // indirect
|
||||
github.com/uudashr/iface v1.4.1 // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xen0n/gosmopolitan v1.3.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/yagipy/maintidx v1.0.0 // indirect
|
||||
github.com/yeya24/promlinter v0.3.0 // indirect
|
||||
github.com/ykadowak/zerologlint v0.1.5 // indirect
|
||||
github.com/yuin/goldmark v1.7.7 // indirect
|
||||
github.com/yuin/goldmark-meta v1.1.0 // indirect
|
||||
github.com/zclconf/go-cty v1.18.0 // indirect
|
||||
gitlab.com/bosi/decorder v0.4.2 // indirect
|
||||
go-simpler.org/musttag v0.14.0 // indirect
|
||||
go-simpler.org/sloglint v0.11.1 // indirect
|
||||
github.com/zclconf/go-cty v1.18.1 // indirect
|
||||
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
|
||||
go.augendre.info/arangolint v0.4.0 // indirect
|
||||
go.augendre.info/fatcontext v0.9.0 // indirect
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect
|
||||
golang.org/x/mod v0.33.0 // indirect
|
||||
golang.org/x/net v0.51.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
golang.org/x/tools v0.42.0 // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
|
||||
golang.org/x/mod v0.35.0 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
golang.org/x/tools v0.44.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
|
||||
google.golang.org/grpc v1.79.2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 // indirect
|
||||
google.golang.org/grpc v1.81.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
honnef.co/go/tools v0.7.0 // indirect
|
||||
mvdan.cc/gofumpt v0.9.2 // indirect
|
||||
mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,101 +0,0 @@
|
|||
# resource "stackit_kms_keyring" "keyring001" {
|
||||
# project_id = var.project_id
|
||||
# display_name = "msh-keyring-sna01"
|
||||
# description = "This is a test keyring for private endpoints"
|
||||
# }
|
||||
#
|
||||
# resource "stackit_kms_key" "key001" {
|
||||
# project_id = var.project_id
|
||||
# keyring_id = stackit_kms_keyring.keyring001.keyring_id
|
||||
# display_name = "msh-key-sna01"
|
||||
# protection = "software"
|
||||
# algorithm = "aes_256_gcm"
|
||||
# purpose = "symmetric_encrypt_decrypt"
|
||||
# access_scope = "SNA"
|
||||
# }
|
||||
|
||||
data "stackitprivatepreview_sqlserverflexbeta_flavor" "sqlserver_flavor" {
|
||||
project_id = var.project_id
|
||||
region = "eu01"
|
||||
cpu = 4
|
||||
ram = 16
|
||||
node_type = "Single"
|
||||
storage_class = "premium-perf2-stackit"
|
||||
}
|
||||
|
||||
resource "stackitprivatepreview_sqlserverflexbeta_instance" "msh-sna-001" {
|
||||
project_id = var.project_id
|
||||
name = "msh-sna-001"
|
||||
backup_schedule = "0 3 * * *"
|
||||
retention_days = 31
|
||||
flavor_id = data.stackitprivatepreview_sqlserverflexbeta_flavor.sqlserver_flavor.flavor_id
|
||||
storage = {
|
||||
class = "premium-perf2-stackit"
|
||||
size = 50
|
||||
}
|
||||
version = 2022
|
||||
encryption = {
|
||||
kek_key_version = 1
|
||||
kek_key_id = var.key_id
|
||||
kek_key_ring_id = var.keyring_id
|
||||
service_account = var.sa_email
|
||||
}
|
||||
network = {
|
||||
acl = ["0.0.0.0/0", "193.148.160.0/19"]
|
||||
access_scope = "SNA"
|
||||
}
|
||||
}
|
||||
|
||||
#resource "stackitprivatepreview_sqlserverflexbeta_instance" "msh-nosna-001" {
|
||||
# project_id = var.project_id
|
||||
# name = "msh-nosna-001"
|
||||
# backup_schedule = "0 3 * * *"
|
||||
# retention_days = 31
|
||||
# flavor_id = data.stackitprivatepreview_sqlserverflexbeta_flavor.sqlserver_flavor.flavor_id
|
||||
# storage = {
|
||||
# class = "premium-perf2-stackit"
|
||||
# size = 50
|
||||
# }
|
||||
# version = 2022
|
||||
# # encryption = {
|
||||
# # #key_id = stackit_kms_key.key.key_id
|
||||
# # #keyring_id = stackit_kms_keyring.keyring.keyring_id
|
||||
# # #key_version = 1
|
||||
# # #key_id = var.key_id
|
||||
# # # key with scope public
|
||||
# # key_id = "fe039bcf-8d7b-431a-801d-9e81371a6b7b"
|
||||
# # keyring_id = var.keyring_id
|
||||
# # key_version = var.key_version
|
||||
# # service_account = var.sa_email
|
||||
# # }
|
||||
# network = {
|
||||
# acl = ["0.0.0.0/0", "193.148.160.0/19"]
|
||||
# access_scope = "PUBLIC"
|
||||
# }
|
||||
#}
|
||||
|
||||
# data "stackitprivatepreview_sqlserverflexbeta_instance" "test" {
|
||||
# project_id = var.project_id
|
||||
# instance_id = var.instance_id
|
||||
# region = "eu01"
|
||||
# }
|
||||
|
||||
# output "test" {
|
||||
# value = data.stackitprivatepreview_sqlserverflexbeta_instance.test
|
||||
# }
|
||||
|
||||
resource "stackitprivatepreview_sqlserverflexbeta_user" "ptlsdbadminuser" {
|
||||
project_id = var.project_id
|
||||
instance_id = stackitprivatepreview_sqlserverflexbeta_instance.msh-sna-001.instance_id
|
||||
username = var.db_admin_username
|
||||
#roles = ["##STACKIT_LoginManager##", "##STACKIT_DatabaseManager##"]
|
||||
roles = ["##STACKIT_LoginManager##"]
|
||||
}
|
||||
|
||||
resource "stackitprivatepreview_sqlserverflexbeta_user" "ptlsdbuser" {
|
||||
project_id = var.project_id
|
||||
instance_id = stackitprivatepreview_sqlserverflexbeta_instance.msh-sna-001.instance_id
|
||||
username = var.db_username
|
||||
roles = ["##STACKIT_LoginManager##"]
|
||||
}
|
||||
|
||||
|
|
@ -13,7 +13,11 @@ resource "stackitprivatepreview_postgresflexalpha_instance" "msh-sna-pe-example"
|
|||
name = "mshpetest2"
|
||||
backup_schedule = "0 0 * * *"
|
||||
retention_days = 45
|
||||
flavor_id = data.stackitprivatepreview_postgresflexalpha_flavor.pgsql_flavor.flavor_id
|
||||
# flavor_id = data.stackitprivatepreview_postgresflexalpha_flavor.pgsql_flavor.flavor_id
|
||||
flavor = {
|
||||
cpu = 2
|
||||
ram = 4
|
||||
}
|
||||
replicas = 1
|
||||
storage = {
|
||||
# class = "premium-perf2-stackit"
|
||||
|
|
@ -66,7 +70,8 @@ resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbadminuser" {
|
|||
project_id = var.project_id
|
||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example.instance_id
|
||||
name = var.db_admin_username
|
||||
roles = ["createdb", "login", "login"]
|
||||
roles = ["createdb", "login"]
|
||||
# roles = ["createdb", "login", "login"]
|
||||
# roles = ["createdb", "login", "createrole"]
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +115,11 @@ output "psql_user_password" {
|
|||
sensitive = true
|
||||
}
|
||||
|
||||
output "psql_user_conn" {
|
||||
value = stackitprivatepreview_postgresflexalpha_user.ptlsdbuser.connection_string
|
||||
sensitive = true
|
||||
# output "psql_user_conn" {
|
||||
# value = stackitprivatepreview_postgresflexalpha_user.ptlsdbuser.connection.host
|
||||
# sensitive = true
|
||||
# }
|
||||
|
||||
output "determined_flavor_id" {
|
||||
value = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example.flavor_id
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
|
||||
# ./tf.sh apply > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
|
||||
|
||||
usage() {
|
||||
|
|
@ -12,7 +10,8 @@ usage() {
|
|||
[ $# -eq 0 ] && usage
|
||||
|
||||
CONFIG_FOLDER=$(dirname "$0")
|
||||
BINARY=terraform
|
||||
# BINARY=terraform
|
||||
BINARY=tofu
|
||||
|
||||
ADD=""
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ provider:
|
|||
name: stackitprivatepreview
|
||||
|
||||
data_sources:
|
||||
collation:
|
||||
collations:
|
||||
read:
|
||||
path: /v3beta1/projects/{projectId}/regions/{region}/instances/{instanceId}/collations
|
||||
method: GET
|
||||
|
|
@ -3,7 +3,7 @@ provider:
|
|||
name: stackitprivatepreview
|
||||
|
||||
data_sources:
|
||||
version:
|
||||
versions:
|
||||
read:
|
||||
path: /v3beta1/projects/{projectId}/regions/{region}/versions
|
||||
method: GET
|
||||
|
|
|
|||
|
|
@ -209,8 +209,8 @@ func (r *databaseResource) Create(
|
|||
)
|
||||
|
||||
database, err := postgresflexalphaWait.GetDatabaseByIdWaitHandler(ctx, r.client.DefaultAPI, projectID, instanceID, region, databaseID).
|
||||
SetTimeout(15 * time.Minute).
|
||||
SetSleepBeforeWait(15 * time.Second).
|
||||
SetTimeout(30 * time.Minute).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(
|
||||
|
|
@ -279,8 +279,8 @@ func (r *databaseResource) Read(
|
|||
)
|
||||
|
||||
databaseResp, err := postgresflexalphaWait.GetDatabaseByIdWaitHandler(ctx, r.client.DefaultAPI, projectID, instanceID, region, databaseID).
|
||||
SetTimeout(15 * time.Minute).
|
||||
SetSleepBeforeWait(15 * time.Second).
|
||||
SetTimeout(30 * time.Minute).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(
|
||||
|
|
@ -386,8 +386,8 @@ func (r *databaseResource) Update(
|
|||
ctx = core.LogResponse(ctx)
|
||||
|
||||
databaseResp, err := postgresflexalphaWait.GetDatabaseByIdWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, region, databaseId).
|
||||
SetTimeout(15 * time.Minute).
|
||||
SetSleepBeforeWait(15 * time.Second).
|
||||
SetTimeout(30 * time.Minute).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "error updating database", err.Error())
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
|
||||
|
||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
|
||||
postgresflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavors/datasources_gen"
|
||||
postgresflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavor/datasources_gen"
|
||||
postgresflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
|
||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
|
||||
|
||||
|
|
@ -220,14 +220,24 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
|||
} else {
|
||||
var scList []attr.Value
|
||||
for _, sc := range f.StorageClasses {
|
||||
mIop := types.Int32Null()
|
||||
if val, ok := sc.GetMaxIoPerSecOk(); ok {
|
||||
mIop = types.Int32Value(*val)
|
||||
}
|
||||
|
||||
mThrough := types.Int32Null()
|
||||
if val, ok := sc.GetMaxThroughInMbOk(); ok {
|
||||
mThrough = types.Int32Value(*val)
|
||||
}
|
||||
|
||||
scList = append(
|
||||
scList,
|
||||
postgresflexalphaGen.NewStorageClassesValueMust(
|
||||
postgresflexalphaGen.StorageClassesValue{}.AttributeTypes(ctx),
|
||||
map[string]attr.Value{
|
||||
"class": types.StringValue(sc.Class),
|
||||
"max_io_per_sec": types.Int32Value(sc.MaxIoPerSec),
|
||||
"max_through_in_mb": types.Int32Value(sc.MaxThroughInMb),
|
||||
"max_io_per_sec": mIop,
|
||||
"max_through_in_mb": mThrough,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package postgresflexalpha
|
||||
package postgresflexalphaflavors
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
package postgresflexalphaflavors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
|
||||
)
|
||||
|
||||
type flavorsClientReader interface {
|
||||
GetFlavorsRequest(
|
||||
ctx context.Context,
|
||||
projectId, region string,
|
||||
) v3alpha1api.ApiGetFlavorsRequestRequest
|
||||
}
|
||||
|
||||
func getAllFlavors(ctx context.Context, client flavorsClientReader, projectId, region string) (
|
||||
[]v3alpha1api.ListFlavors,
|
||||
error,
|
||||
) {
|
||||
getAllFilter := func(_ v3alpha1api.ListFlavors) bool { return true }
|
||||
flavorList, err := getFlavorsByFilter(ctx, client, projectId, region, getAllFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return flavorList, nil
|
||||
}
|
||||
|
||||
// getFlavorsByFilter is a helper function to retrieve flavors using a filtern function.
|
||||
// Hint: The API does not have a GetFlavors endpoint, only ListFlavors
|
||||
func getFlavorsByFilter(
|
||||
ctx context.Context,
|
||||
client flavorsClientReader,
|
||||
projectId, region string,
|
||||
filter func(db v3alpha1api.ListFlavors) bool,
|
||||
) ([]v3alpha1api.ListFlavors, error) {
|
||||
if projectId == "" || region == "" {
|
||||
return nil, fmt.Errorf("listing postgresflex flavors: projectId and region are required")
|
||||
}
|
||||
|
||||
const pageSize = 25
|
||||
|
||||
var result = make([]v3alpha1api.ListFlavors, 0)
|
||||
|
||||
for page := int32(1); ; page++ {
|
||||
res, err := client.GetFlavorsRequest(ctx, projectId, region).
|
||||
Page(page).Size(pageSize).Sort(v3alpha1api.FLAVORSORT_ID_ASC).Execute()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("requesting flavors list (page %d): %w", page, err)
|
||||
}
|
||||
|
||||
// If the API returns no flavors, we have reached the end of the list.
|
||||
if len(res.Flavors) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, flavor := range res.Flavors {
|
||||
if filter(flavor) {
|
||||
result = append(result, flavor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
package postgresflexalphaflavors
|
||||
|
||||
/*
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
|
||||
)
|
||||
|
||||
type mockRequest struct {
|
||||
executeFunc func() (*postgresflex.GetFlavorsResponse, error)
|
||||
}
|
||||
|
||||
func (m *mockRequest) Page(_ int32) postgresflex.ApiGetFlavorsRequestRequest { return m }
|
||||
func (m *mockRequest) Size(_ int32) postgresflex.ApiGetFlavorsRequestRequest { return m }
|
||||
func (m *mockRequest) Sort(_ postgresflex.FlavorSort) postgresflex.ApiGetFlavorsRequestRequest {
|
||||
return m
|
||||
}
|
||||
func (m *mockRequest) Execute() (*postgresflex.GetFlavorsResponse, error) {
|
||||
return m.executeFunc()
|
||||
}
|
||||
|
||||
type mockFlavorsClient struct {
|
||||
executeRequest func() postgresflex.ApiGetFlavorsRequestRequest
|
||||
}
|
||||
|
||||
func (m *mockFlavorsClient) GetFlavorsRequest(_ context.Context, _, _ string) postgresflex.ApiGetFlavorsRequestRequest {
|
||||
return m.executeRequest()
|
||||
}
|
||||
|
||||
var mockResp = func(page int32) (*postgresflex.GetFlavorsResponse, error) {
|
||||
if page == 1 {
|
||||
return &postgresflex.GetFlavorsResponse{
|
||||
Flavors: []postgresflex.ListFlavors{
|
||||
{Id: "flavor-1", Description: "first"},
|
||||
{Id: "flavor-2", Description: "second"},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
if page == 2 {
|
||||
return &postgresflex.GetFlavorsResponse{
|
||||
Flavors: []postgresflex.ListFlavors{
|
||||
{Id: "flavor-3", Description: "three"},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &postgresflex.GetFlavorsResponse{
|
||||
Flavors: []postgresflex.ListFlavors{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestGetFlavorsByFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
projectId string
|
||||
region string
|
||||
mockErr error
|
||||
filter func(postgresflex.ListFlavors) bool
|
||||
wantCount int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
description: "Success - Get all flavors (2 pages)",
|
||||
projectId: "pid", region: "reg",
|
||||
filter: func(_ postgresflex.ListFlavors) bool { return true },
|
||||
wantCount: 3,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
description: "Success - Filter flavors by description",
|
||||
projectId: "pid", region: "reg",
|
||||
filter: func(f postgresflex.ListFlavors) bool { return f.Description == "first" },
|
||||
wantCount: 1,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
description: "Error - Missing parameters",
|
||||
projectId: "", region: "reg",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(
|
||||
tt.description, func(t *testing.T) {
|
||||
var currentPage int32
|
||||
client := &mockFlavorsClient{
|
||||
executeRequest: func() postgresflex.ApiGetFlavorsRequestRequest {
|
||||
return mockRequest{
|
||||
executeFunc: func() (*postgresflex.GetFlavorsResponse, error) {
|
||||
currentPage++
|
||||
return mockResp(currentPage)
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
actual, err := getFlavorsByFilter(context.Background(), client, tt.projectId, tt.region, tt.filter)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("getFlavorsByFilter() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !tt.wantErr && len(actual) != tt.wantCount {
|
||||
t.Errorf("getFlavorsByFilter() got %d flavors, want %d", len(actual), tt.wantCount)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllFlavors(t *testing.T) {
|
||||
var currentPage int32
|
||||
client := &mockFlavorsClient{
|
||||
executeRequest: func() postgresflex.ApiGetFlavorsRequestRequest {
|
||||
return mockRequest{
|
||||
executeFunc: func() (*postgresflex.GetFlavorsResponse, error) {
|
||||
currentPage++
|
||||
return mockResp(currentPage)
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
res, err := getAllFlavors(context.Background(), client, "pid", "reg")
|
||||
if err != nil {
|
||||
t.Errorf("getAllFlavors() unexpected error: %v", err)
|
||||
}
|
||||
if len(res) != 3 {
|
||||
t.Errorf("getAllFlavors() expected 3 flavor, got %d", len(res))
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -115,6 +115,12 @@ func InstanceDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
Description: "Whether the instance can be deleted or not.",
|
||||
MarkdownDescription: "Whether the instance can be deleted or not.",
|
||||
},
|
||||
"labels": schema.MapAttribute{
|
||||
ElementType: types.StringType,
|
||||
Computed: true,
|
||||
Description: "Key-value pairs, 63 characters max, begin and end with an alphanumerical character,\nmay contain dashes (-), underscores (_), dots (.), and alphanumerics between. Key MUST be at least 1 character.\nMax 64 labels\nRegex for keys: ^(?=.{1,63}$)([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$\nRegex for values: ^(?=.{0,63}$)(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])*$\nThe stackit- prefix is reserved and cannot be used for Keys.\n",
|
||||
MarkdownDescription: "Key-value pairs, 63 characters max, begin and end with an alphanumerical character,\nmay contain dashes (-), underscores (_), dots (.), and alphanumerics between. Key MUST be at least 1 character.\nMax 64 labels\nRegex for keys: ^(?=.{1,63}$)([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$\nRegex for values: ^(?=.{0,63}$)(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])*$\nThe stackit- prefix is reserved and cannot be used for Keys.\n",
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: "The name of the instance.",
|
||||
|
|
@ -171,8 +177,8 @@ func InstanceDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
},
|
||||
"retention_days": schema.Int64Attribute{
|
||||
Computed: true,
|
||||
Description: "How long backups are retained. The value can only be between 32 and 365 days.",
|
||||
MarkdownDescription: "How long backups are retained. The value can only be between 32 and 365 days.",
|
||||
Description: "How long backups are retained. The value can only be between 32 and 90 days.",
|
||||
MarkdownDescription: "How long backups are retained. The value can only be between 32 and 90 days.",
|
||||
},
|
||||
"status": schema.StringAttribute{
|
||||
Computed: true,
|
||||
|
|
@ -219,6 +225,7 @@ type InstanceModel struct {
|
|||
Id types.String `tfsdk:"tf_original_api_id"`
|
||||
InstanceId types.String `tfsdk:"instance_id"`
|
||||
IsDeletable types.Bool `tfsdk:"is_deletable"`
|
||||
Labels types.Map `tfsdk:"labels"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Network NetworkValue `tfsdk:"network"`
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
package postgresflexalpha
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
|
||||
)
|
||||
|
||||
type flavorsClientReader interface {
|
||||
GetFlavorsRequest(
|
||||
ctx context.Context,
|
||||
projectId, region string,
|
||||
) v3alpha1api.ApiGetFlavorsRequestRequest
|
||||
}
|
||||
|
||||
func getAllFlavors(ctx context.Context, client flavorsClientReader, projectId, region string) (
|
||||
[]v3alpha1api.ListFlavors,
|
||||
error,
|
||||
) {
|
||||
getAllFilter := func(_ v3alpha1api.ListFlavors) bool { return true }
|
||||
flavorList, err := getFlavorsByFilter(ctx, client, projectId, region, getAllFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return flavorList, nil
|
||||
}
|
||||
|
||||
// getFlavorsByFilter is a helper function to retrieve flavors using a filtern function.
|
||||
// Hint: The API does not have a GetFlavors endpoint, only ListFlavors
|
||||
func getFlavorsByFilter(
|
||||
ctx context.Context,
|
||||
client flavorsClientReader,
|
||||
projectId, region string,
|
||||
filter func(db v3alpha1api.ListFlavors) bool,
|
||||
) ([]v3alpha1api.ListFlavors, error) {
|
||||
if projectId == "" || region == "" {
|
||||
return nil, fmt.Errorf("listing postgresflex flavors: projectId and region are required")
|
||||
}
|
||||
|
||||
const pageSize = 25
|
||||
|
||||
var result = make([]v3alpha1api.ListFlavors, 0)
|
||||
|
||||
for page := int32(1); ; page++ {
|
||||
res, err := client.GetFlavorsRequest(ctx, projectId, region).
|
||||
Page(page).Size(pageSize).Sort(v3alpha1api.FLAVORSORT_ID_ASC).Execute()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("requesting flavors list (page %d): %w", page, err)
|
||||
}
|
||||
|
||||
// If the API returns no flavors, we have reached the end of the list.
|
||||
if len(res.Flavors) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, flavor := range res.Flavors {
|
||||
if filter(flavor) {
|
||||
result = append(result, flavor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
package postgresflexalpha
|
||||
|
||||
/*
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
|
||||
)
|
||||
|
||||
type mockRequest struct {
|
||||
executeFunc func() (*postgresflex.GetFlavorsResponse, error)
|
||||
}
|
||||
|
||||
func (m *mockRequest) Page(_ int32) postgresflex.ApiGetFlavorsRequestRequest { return m }
|
||||
func (m *mockRequest) Size(_ int32) postgresflex.ApiGetFlavorsRequestRequest { return m }
|
||||
func (m *mockRequest) Sort(_ postgresflex.FlavorSort) postgresflex.ApiGetFlavorsRequestRequest {
|
||||
return m
|
||||
}
|
||||
func (m *mockRequest) Execute() (*postgresflex.GetFlavorsResponse, error) {
|
||||
return m.executeFunc()
|
||||
}
|
||||
|
||||
type mockFlavorsClient struct {
|
||||
executeRequest func() postgresflex.ApiGetFlavorsRequestRequest
|
||||
}
|
||||
|
||||
func (m *mockFlavorsClient) GetFlavorsRequest(_ context.Context, _, _ string) postgresflex.ApiGetFlavorsRequestRequest {
|
||||
return m.executeRequest()
|
||||
}
|
||||
|
||||
var mockResp = func(page int32) (*postgresflex.GetFlavorsResponse, error) {
|
||||
if page == 1 {
|
||||
return &postgresflex.GetFlavorsResponse{
|
||||
Flavors: []postgresflex.ListFlavors{
|
||||
{Id: "flavor-1", Description: "first"},
|
||||
{Id: "flavor-2", Description: "second"},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
if page == 2 {
|
||||
return &postgresflex.GetFlavorsResponse{
|
||||
Flavors: []postgresflex.ListFlavors{
|
||||
{Id: "flavor-3", Description: "three"},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &postgresflex.GetFlavorsResponse{
|
||||
Flavors: []postgresflex.ListFlavors{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestGetFlavorsByFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
projectId string
|
||||
region string
|
||||
mockErr error
|
||||
filter func(postgresflex.ListFlavors) bool
|
||||
wantCount int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
description: "Success - Get all flavors (2 pages)",
|
||||
projectId: "pid", region: "reg",
|
||||
filter: func(_ postgresflex.ListFlavors) bool { return true },
|
||||
wantCount: 3,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
description: "Success - Filter flavors by description",
|
||||
projectId: "pid", region: "reg",
|
||||
filter: func(f postgresflex.ListFlavors) bool { return f.Description == "first" },
|
||||
wantCount: 1,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
description: "Error - Missing parameters",
|
||||
projectId: "", region: "reg",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(
|
||||
tt.description, func(t *testing.T) {
|
||||
var currentPage int32
|
||||
client := &mockFlavorsClient{
|
||||
executeRequest: func() postgresflex.ApiGetFlavorsRequestRequest {
|
||||
return mockRequest{
|
||||
executeFunc: func() (*postgresflex.GetFlavorsResponse, error) {
|
||||
currentPage++
|
||||
return mockResp(currentPage)
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
actual, err := getFlavorsByFilter(context.Background(), client, tt.projectId, tt.region, tt.filter)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("getFlavorsByFilter() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !tt.wantErr && len(actual) != tt.wantCount {
|
||||
t.Errorf("getFlavorsByFilter() got %d flavors, want %d", len(actual), tt.wantCount)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllFlavors(t *testing.T) {
|
||||
var currentPage int32
|
||||
client := &mockFlavorsClient{
|
||||
executeRequest: func() postgresflex.ApiGetFlavorsRequestRequest {
|
||||
return mockRequest{
|
||||
executeFunc: func() (*postgresflex.GetFlavorsResponse, error) {
|
||||
currentPage++
|
||||
return mockResp(currentPage)
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
res, err := getAllFlavors(context.Background(), client, "pid", "reg")
|
||||
if err != nil {
|
||||
t.Errorf("getAllFlavors() unexpected error: %v", err)
|
||||
}
|
||||
if len(res) != 3 {
|
||||
t.Errorf("getAllFlavors() expected 3 flavor, got %d", len(res))
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -16,7 +16,7 @@ import (
|
|||
|
||||
func mapGetInstanceResponseToModel(
|
||||
ctx context.Context,
|
||||
m *postgresflexalpharesource.InstanceModel,
|
||||
m *LocalInstanceModel,
|
||||
resp *postgresflex.GetInstanceResponse,
|
||||
) error {
|
||||
m.BackupSchedule = types.StringValue(resp.GetBackupSchedule())
|
||||
|
|
@ -71,6 +71,8 @@ func mapGetInstanceResponseToModel(
|
|||
|
||||
m.Acl = netACL
|
||||
|
||||
// m.Labels = resp.GetLabels()
|
||||
|
||||
netInstAdd := types.StringValue("")
|
||||
if instAdd, ok := resp.Network.GetInstanceAddressOk(); ok {
|
||||
netInstAdd = types.StringValue(*instAdd)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
|
||||
|
||||
postgresflexalpharesource "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/resources_gen"
|
||||
utils2 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
|
||||
)
|
||||
|
||||
|
|
@ -171,7 +170,7 @@ func Test_mapGetInstanceResponseToModel(t *testing.T) {
|
|||
t.Skipf("please implement")
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
m *postgresflexalpharesource.InstanceModel
|
||||
m *LocalInstanceModel
|
||||
resp *postgresflex.GetInstanceResponse
|
||||
}
|
||||
tests := []struct {
|
||||
|
|
|
|||
|
|
@ -11,11 +11,14 @@ import (
|
|||
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||
coreUtils "github.com/stackitcloud/stackit-sdk-go/core/utils"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
|
||||
|
||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
|
||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
|
||||
postgresflexalpha "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/resources_gen"
|
||||
|
|
@ -44,12 +47,25 @@ type instanceResource struct {
|
|||
providerData core.ProviderData
|
||||
}
|
||||
|
||||
type LocalInstanceModel struct {
|
||||
postgresflexalpha.InstanceModel
|
||||
Flavor types.Object `tfsdk:"flavor"`
|
||||
}
|
||||
|
||||
// Struct corresponding to Model.Flavor
|
||||
type flavorModel struct {
|
||||
Id types.String `tfsdk:"id"`
|
||||
Description types.String `tfsdk:"description"`
|
||||
CPU types.Int64 `tfsdk:"cpu"`
|
||||
RAM types.Int64 `tfsdk:"ram"`
|
||||
}
|
||||
|
||||
func (r *instanceResource) ValidateConfig(
|
||||
ctx context.Context,
|
||||
req resource.ValidateConfigRequest,
|
||||
resp *resource.ValidateConfigResponse,
|
||||
) {
|
||||
var data postgresflexalpha.InstanceModel
|
||||
var data LocalInstanceModel
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
|
|
@ -64,6 +80,23 @@ func (r *instanceResource) ValidateConfig(
|
|||
"The resource may return unexpected results.",
|
||||
)
|
||||
}
|
||||
|
||||
if data.FlavorId.IsNull() {
|
||||
if data.Flavor.IsUnknown() || data.Flavor.IsNull() {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("flavor"),
|
||||
"Missing Attribute Configuration",
|
||||
"Expected flavor to be configured. "+
|
||||
"The resource may return unexpected results.",
|
||||
)
|
||||
}
|
||||
resp.Diagnostics.AddAttributeWarning(
|
||||
path.Root("flavor"),
|
||||
"Attribute Configuration Deprecation",
|
||||
"Using flavor is deprecated, "+
|
||||
"please use flavor_id instead.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ModifyPlan implements resource.ResourceWithModifyPlan.
|
||||
|
|
@ -73,7 +106,7 @@ func (r *instanceResource) ModifyPlan(
|
|||
req resource.ModifyPlanRequest,
|
||||
resp *resource.ModifyPlanResponse,
|
||||
) { // nolint:gocritic // function signature required by Terraform
|
||||
var configModel postgresflexalpha.InstanceModel
|
||||
var configModel LocalInstanceModel
|
||||
// skip initial empty configuration to avoid follow-up errors
|
||||
if req.Config.Raw.IsNull() {
|
||||
return
|
||||
|
|
@ -83,7 +116,7 @@ func (r *instanceResource) ModifyPlan(
|
|||
return
|
||||
}
|
||||
|
||||
var planModel postgresflexalpha.InstanceModel
|
||||
var planModel LocalInstanceModel
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
|
|
@ -133,20 +166,53 @@ func (r *instanceResource) Configure(
|
|||
var modifiersFileByte []byte
|
||||
|
||||
// Schema defines the schema for the resource.
|
||||
func (r *instanceResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
schema := postgresflexalpha.InstanceResourceSchema(ctx)
|
||||
func (r *instanceResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
schemaVar := postgresflexalpha.InstanceResourceSchema(ctx)
|
||||
schemaVar.Attributes["flavor"] = schema.SingleNestedAttribute{
|
||||
Optional: true,
|
||||
DeprecationMessage: "Please use flavor_id instead.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
UseStateForUnknownIfFlavorUnchanged(req),
|
||||
},
|
||||
},
|
||||
"description": schema.StringAttribute{
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
UseStateForUnknownIfFlavorUnchanged(req),
|
||||
},
|
||||
},
|
||||
"cpu": schema.Int64Attribute{
|
||||
DeprecationMessage: "Please use flavor_id instead.",
|
||||
Optional: true,
|
||||
},
|
||||
"ram": schema.Int64Attribute{
|
||||
DeprecationMessage: "Please use flavor_id instead.",
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
schemaVar.Attributes["flavor_id"] = schema.StringAttribute{
|
||||
Optional: true,
|
||||
Description: "The id of the instance flavor.",
|
||||
MarkdownDescription: "The id of the instance flavor.",
|
||||
}
|
||||
|
||||
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("error during read modifiers config file", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = utils.AddPlanModifiersToResourceSchema(fields, &schema)
|
||||
err = utils.AddPlanModifiersToResourceSchema(fields, &schemaVar)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("error adding plan modifiers", err.Error())
|
||||
return
|
||||
}
|
||||
resp.Schema = schema
|
||||
resp.Schema = schemaVar
|
||||
}
|
||||
|
||||
// Create creates the resource and sets the initial Terraform state.
|
||||
|
|
@ -155,7 +221,7 @@ func (r *instanceResource) Create(
|
|||
req resource.CreateRequest,
|
||||
resp *resource.CreateResponse,
|
||||
) { // nolint:gocritic // function signature required by Terraform
|
||||
var model postgresflexalpha.InstanceModel
|
||||
var model LocalInstanceModel
|
||||
|
||||
diags := req.Plan.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
|
@ -177,6 +243,73 @@ func (r *instanceResource) Create(
|
|||
return
|
||||
}
|
||||
|
||||
// determine flavor ID
|
||||
var flModel = &flavorModel{}
|
||||
if !(model.Flavor.IsNull() || model.Flavor.IsUnknown()) {
|
||||
diags = model.Flavor.As(ctx, flModel, basetypes.ObjectAsOptions{})
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
flavors, err := getAllFlavors(ctx, r.client.DefaultAPI, projectID, region)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading flavors", fmt.Sprintf("getAllFlavors: %v", err))
|
||||
return
|
||||
}
|
||||
tflog.Debug(ctx, fmt.Sprintf("loaded flavors: %d", len(flavors)))
|
||||
|
||||
var foundFlavors []v3alpha1api.ListFlavors
|
||||
for _, flavor := range flavors {
|
||||
if flModel.CPU.ValueInt64() != int64(flavor.Cpu) {
|
||||
// tflog.Debug(ctx, fmt.Sprintf("flavor - cpu did not match (%d - %d)", flModel.CPU.ValueInt64(), flavor.Cpu))
|
||||
continue
|
||||
}
|
||||
if flModel.RAM.ValueInt64() != int64(flavor.Memory) {
|
||||
// tflog.Debug(ctx, fmt.Sprintf("flavor - ram did not match (%d - %d)", flModel.RAM.ValueInt64(), flavor.Memory))
|
||||
continue
|
||||
}
|
||||
tmpNodeType := "Single"
|
||||
if model.Replicas.ValueInt64() > 1 {
|
||||
tmpNodeType = "Replica"
|
||||
}
|
||||
if strings.ToLower(tmpNodeType) != strings.ToLower(flavor.NodeType) {
|
||||
//tflog.Debug(
|
||||
// ctx,
|
||||
// fmt.Sprintf(
|
||||
// "flavor - nodeType did not match ('%s' - '%s')",
|
||||
// strings.ToLower(tmpNodeType),
|
||||
// strings.ToLower(flavor.NodeType),
|
||||
// ),
|
||||
//)
|
||||
continue
|
||||
}
|
||||
tflog.Debug(ctx, fmt.Sprintf("found flavor %s, checking storage classes", flavor.Id))
|
||||
for _, sc := range flavor.StorageClasses {
|
||||
if model.Storage.PerformanceClass.ValueString() != sc.Class {
|
||||
continue
|
||||
}
|
||||
tflog.Debug(ctx, fmt.Sprintf("found storage class '%s' for flavor '%s', checking storage classes", sc.Class, flavor.Id))
|
||||
foundFlavors = append(foundFlavors, flavor)
|
||||
}
|
||||
}
|
||||
if len(foundFlavors) == 0 {
|
||||
resp.Diagnostics.AddError("get flavor", "could not find requested flavor")
|
||||
return
|
||||
}
|
||||
if len(foundFlavors) > 1 {
|
||||
resp.Diagnostics.AddError("get flavor", "found too many matching flavors")
|
||||
return
|
||||
}
|
||||
|
||||
f := foundFlavors[0]
|
||||
flModel.Description = types.StringValue(f.Description)
|
||||
flModel.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, f.Id)
|
||||
model.FlavorId = types.StringValue(f.Id)
|
||||
//flModel. .MaxGb = types.Int32Value(f.MaxGB)
|
||||
//flModel.MinGb = types.Int32Value(f.MinGB)
|
||||
}
|
||||
|
||||
replVal := model.Replicas.ValueInt64() // nolint:gosec // check is performed above
|
||||
payload := modelToCreateInstancePayload(netACL, model, replVal)
|
||||
|
||||
|
|
@ -208,7 +341,7 @@ func (r *instanceResource) Create(
|
|||
)
|
||||
|
||||
waitResp, err := wait.CreateInstanceWaitHandler(ctx, r.client.DefaultAPI, projectID, region, *instanceID).
|
||||
SetTimeout(30 * time.Minute).
|
||||
SetTimeout(90 * time.Minute).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
|
|
@ -243,7 +376,7 @@ func (r *instanceResource) Create(
|
|||
|
||||
func modelToCreateInstancePayload(
|
||||
netACL []string,
|
||||
model postgresflexalpha.InstanceModel,
|
||||
model LocalInstanceModel,
|
||||
replVal int64,
|
||||
) v3alpha1api.CreateInstanceRequestPayload {
|
||||
var enc *v3alpha1api.InstanceEncryption
|
||||
|
|
@ -283,7 +416,7 @@ func (r *instanceResource) Read(
|
|||
) { // nolint:gocritic // function signature required by Terraform
|
||||
functionErrorSummary := "read instance failed"
|
||||
|
||||
var model postgresflexalpha.InstanceModel
|
||||
var model LocalInstanceModel
|
||||
diags := req.State.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
|
|
@ -371,7 +504,7 @@ func (r *instanceResource) Update(
|
|||
req resource.UpdateRequest,
|
||||
resp *resource.UpdateResponse,
|
||||
) { // nolint:gocritic // function signature required by Terraform
|
||||
var model postgresflexalpha.InstanceModel
|
||||
var model LocalInstanceModel
|
||||
|
||||
diags := req.Plan.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
|
@ -446,7 +579,7 @@ func (r *instanceResource) Update(
|
|||
region,
|
||||
instanceID,
|
||||
).
|
||||
SetTimeout(30 * time.Minute).
|
||||
SetTimeout(90 * time.Minute).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
|
|
@ -484,7 +617,7 @@ func (r *instanceResource) Delete(
|
|||
req resource.DeleteRequest,
|
||||
resp *resource.DeleteResponse,
|
||||
) { // nolint:gocritic // function signature required by Terraform
|
||||
var model postgresflexalpha.InstanceModel
|
||||
var model LocalInstanceModel
|
||||
|
||||
diags := req.State.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
|
|
|||
|
|
@ -119,6 +119,13 @@ func InstanceResourceSchema(ctx context.Context) schema.Schema {
|
|||
Description: "Whether the instance can be deleted or not.",
|
||||
MarkdownDescription: "Whether the instance can be deleted or not.",
|
||||
},
|
||||
//"labels": schema.MapAttribute{
|
||||
// ElementType: types.StringType,
|
||||
// Optional: true,
|
||||
// Computed: true,
|
||||
// Description: "Key-value pairs, 63 characters max, begin and end with an alphanumerical character,\nmay contain dashes (-), underscores (_), dots (.), and alphanumerics between. Key MUST be at least 1 character.\nMax 64 labels\nRegex for keys: ^(?=.{1,63}$)([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$\nRegex for values: ^(?=.{0,63}$)(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])*$\nThe stackit- prefix is reserved and cannot be used for Keys.\n",
|
||||
// MarkdownDescription: "Key-value pairs, 63 characters max, begin and end with an alphanumerical character,\nmay contain dashes (-), underscores (_), dots (.), and alphanumerics between. Key MUST be at least 1 character.\nMax 64 labels\nRegex for keys: ^(?=.{1,63}$)([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$\nRegex for values: ^(?=.{0,63}$)(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])*$\nThe stackit- prefix is reserved and cannot be used for Keys.\n",
|
||||
//},
|
||||
"name": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The name of the instance.",
|
||||
|
|
@ -191,8 +198,8 @@ func InstanceResourceSchema(ctx context.Context) schema.Schema {
|
|||
},
|
||||
"retention_days": schema.Int64Attribute{
|
||||
Required: true,
|
||||
Description: "How long backups are retained. The value can only be between 32 and 365 days.",
|
||||
MarkdownDescription: "How long backups are retained. The value can only be between 32 and 365 days.",
|
||||
Description: "How long backups are retained. The value can only be between 32 and 90 days.",
|
||||
MarkdownDescription: "How long backups are retained. The value can only be between 32 and 90 days.",
|
||||
},
|
||||
"status": schema.StringAttribute{
|
||||
Computed: true,
|
||||
|
|
@ -239,15 +246,16 @@ type InstanceModel struct {
|
|||
Id types.String `tfsdk:"id"`
|
||||
InstanceId types.String `tfsdk:"instance_id"`
|
||||
IsDeletable types.Bool `tfsdk:"is_deletable"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Network NetworkValue `tfsdk:"network"`
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Replicas types.Int64 `tfsdk:"replicas"`
|
||||
RetentionDays types.Int64 `tfsdk:"retention_days"`
|
||||
Status types.String `tfsdk:"status"`
|
||||
Storage StorageValue `tfsdk:"storage"`
|
||||
Version types.String `tfsdk:"version"`
|
||||
//Labels types.Map `tfsdk:"labels"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Network NetworkValue `tfsdk:"network"`
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Replicas types.Int64 `tfsdk:"replicas"`
|
||||
RetentionDays types.Int64 `tfsdk:"retention_days"`
|
||||
Status types.String `tfsdk:"status"`
|
||||
Storage StorageValue `tfsdk:"storage"`
|
||||
Version types.String `tfsdk:"version"`
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectTypable = ConnectionInfoType{}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
package postgresflexalpha
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
)
|
||||
|
||||
type useStateForUnknownIfFlavorUnchangedModifier struct {
|
||||
Req resource.SchemaRequest
|
||||
}
|
||||
|
||||
// UseStateForUnknownIfFlavorUnchanged returns a plan modifier similar to UseStateForUnknown
|
||||
// if the RAM and CPU values are not changed in the plan. Otherwise, the plan modifier does nothing.
|
||||
func UseStateForUnknownIfFlavorUnchanged(req resource.SchemaRequest) planmodifier.String {
|
||||
return useStateForUnknownIfFlavorUnchangedModifier{
|
||||
Req: req,
|
||||
}
|
||||
}
|
||||
|
||||
func (m useStateForUnknownIfFlavorUnchangedModifier) Description(context.Context) string {
|
||||
return "UseStateForUnknownIfFlavorUnchanged returns a plan modifier similar to UseStateForUnknown if the RAM and CPU values are not changed in the plan. Otherwise, the plan modifier does nothing."
|
||||
}
|
||||
|
||||
func (m useStateForUnknownIfFlavorUnchangedModifier) MarkdownDescription(ctx context.Context) string {
|
||||
return m.Description(ctx)
|
||||
}
|
||||
|
||||
func (m useStateForUnknownIfFlavorUnchangedModifier) PlanModifyString(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
// Do nothing if there is no state value.
|
||||
if req.StateValue.IsNull() {
|
||||
return
|
||||
}
|
||||
|
||||
// Do nothing if there is a known planned value.
|
||||
if !req.PlanValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
// Do nothing if there is an unknown configuration value, otherwise interpolation gets messed up.
|
||||
if req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
// The above checks are taken from the UseStateForUnknown plan modifier implementation
|
||||
// (https://github.com/hashicorp/terraform-plugin-framework/blob/main/resource/schema/stringplanmodifier/use_state_for_unknown.go#L38)
|
||||
|
||||
var stateModel LocalInstanceModel
|
||||
diags := req.State.Get(ctx, &stateModel)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
var stateFlavor = &flavorModel{}
|
||||
if !(stateModel.Flavor.IsNull() || stateModel.Flavor.IsUnknown()) {
|
||||
diags = stateModel.Flavor.As(ctx, stateFlavor, basetypes.ObjectAsOptions{})
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var planModel LocalInstanceModel
|
||||
diags = req.Plan.Get(ctx, &planModel)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
var planFlavor = &flavorModel{}
|
||||
if !(planModel.Flavor.IsNull() || planModel.Flavor.IsUnknown()) {
|
||||
diags = planModel.Flavor.As(ctx, planFlavor, basetypes.ObjectAsOptions{})
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if planFlavor.CPU == stateFlavor.CPU && planFlavor.RAM == stateFlavor.RAM {
|
||||
resp.PlanValue = req.StateValue
|
||||
}
|
||||
}
|
||||
|
|
@ -799,7 +799,7 @@ func testAccCheckPostgresFlexDestroy(s *terraform.State) error {
|
|||
testutils.ProjectId,
|
||||
testutils.Region,
|
||||
items[i].Id,
|
||||
15*time.Minute,
|
||||
30*time.Minute,
|
||||
10*time.Second,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
101
stackit/internal/services/postgresflexalpha/testdata/instance_template_with_flavor.gompl
vendored
Normal file
101
stackit/internal/services/postgresflexalpha/testdata/instance_template_with_flavor.gompl
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
provider "stackitprivatepreview" {
|
||||
default_region = "{{ .Region }}"
|
||||
service_account_key_path = "{{ .ServiceAccountFilePath }}"
|
||||
}
|
||||
|
||||
data "stackitprivatepreview_postgresflexalpha_flavor" "flavor" {
|
||||
project_id = "{{ .ProjectID }}"
|
||||
region = "{{ .Region }}"
|
||||
cpu = 4
|
||||
ram = 16
|
||||
node_type = "Single"
|
||||
storage_class = "premium-perf2-stackit"
|
||||
}
|
||||
|
||||
resource "stackitprivatepreview_postgresflexalpha_instance" "{{ .TfName }}" {
|
||||
project_id = "{{ .ProjectID }}"
|
||||
name = "{{ .Name }}"
|
||||
backup_schedule = "{{ .BackupSchedule }}"
|
||||
retention_days = {{ .RetentionDays }}
|
||||
flavor_id = "{{ .FlavorID }}"
|
||||
replicas = {{ .Replicas }}
|
||||
storage = {
|
||||
performance_class = "{{ .PerformanceClass }}"
|
||||
size = {{ .Size }}
|
||||
}
|
||||
{{ if .UseEncryption }}
|
||||
encryption = {
|
||||
kek_key_id = "{{ .KekKeyID }}"
|
||||
kek_key_ring_id = "{{ .KekKeyRingID }}"
|
||||
kek_key_version = {{ .KekKeyVersion }}
|
||||
service_account = "{{ .KekServiceAccount }}"
|
||||
}
|
||||
{{ end }}
|
||||
network = {
|
||||
acl = [{{ range $i, $v := .ACLStrings }}{{if $i}},{{end}}"{{$v}}"{{end}}]
|
||||
access_scope = "{{ .AccessScope }}"
|
||||
}
|
||||
{{ if .Version }}
|
||||
version = "{{ .Version }}"
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
{{ if .Users }}
|
||||
{{ $tfName := .TfName }}
|
||||
{{ range $user := .Users }}
|
||||
resource "stackitprivatepreview_postgresflexalpha_user" "{{ $user.Name }}" {
|
||||
depends_on = [
|
||||
stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}
|
||||
]
|
||||
project_id = "{{ $user.ProjectID }}"
|
||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}.instance_id
|
||||
name = "{{ $user.Name }}"
|
||||
roles = [{{ range $i, $v := $user.Roles }}{{if $i}},{{end}}"{{$v}}"{{end}}]
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if .Databases }}
|
||||
{{ $tfName := .TfName }}
|
||||
{{ range $db := .Databases }}
|
||||
resource "stackitprivatepreview_postgresflexalpha_database" "{{ $db.Name }}" {
|
||||
depends_on = [
|
||||
stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }},
|
||||
stackitprivatepreview_postgresflexalpha_user.{{ $db.Owner }}
|
||||
]
|
||||
project_id = "{{ $db.ProjectID }}"
|
||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}.instance_id
|
||||
name = "{{ $db.Name }}"
|
||||
owner = stackitprivatepreview_postgresflexalpha_user.{{ $db.Owner }}.name
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if .DataSourceTest }}
|
||||
data "stackitprivatepreview_postgresflexalpha_instance" "{{ .TfName }}" {
|
||||
project_id = stackitprivatepreview_postgresflexalpha_instance.{{ .TfName }}.project_id
|
||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.{{ .TfName }}.instance_id
|
||||
}
|
||||
|
||||
{{ if .Users }}
|
||||
{{ $tfName := .TfName }}
|
||||
{{ range $user := .Users }}
|
||||
data "stackitprivatepreview_postgresflexalpha_user" "{{ $user.Name }}" {
|
||||
project_id = stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}.project_id
|
||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}.instance_id
|
||||
user_id = stackitprivatepreview_postgresflexalpha_user.{{ $user.Name }}.user_id
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if .Databases }}
|
||||
{{ $tfName := .TfName }}
|
||||
{{ range $db := .Databases }}
|
||||
data "stackitprivatepreview_postgresflexalpha_database" "{{ $db.Name }}" {
|
||||
project_id = stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}.project_id
|
||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}.instance_id
|
||||
database_id = stackitprivatepreview_postgresflexalpha_database.{{ $db.Name }}.database_id
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
|
@ -241,7 +241,7 @@ func (r *userResource) Create(
|
|||
).SetSleepBeforeWait(
|
||||
10 * time.Second,
|
||||
).SetTimeout(
|
||||
15 * time.Minute,
|
||||
30 * time.Minute,
|
||||
).WaitWithContext(ctx)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -322,7 +322,7 @@ func (r *userResource) Read(
|
|||
).SetSleepBeforeWait(
|
||||
10 * time.Second,
|
||||
).SetTimeout(
|
||||
15 * time.Minute,
|
||||
30 * time.Minute,
|
||||
).WaitWithContext(ctx)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -445,7 +445,7 @@ func (r *userResource) Update(
|
|||
).SetSleepBeforeWait(
|
||||
10 * time.Second,
|
||||
).SetTimeout(
|
||||
15 * time.Minute,
|
||||
30 * time.Minute,
|
||||
).WaitWithContext(ctx)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,451 @@
|
|||
// Code generated by terraform-plugin-framework-generator DO NOT EDIT.
|
||||
|
||||
package sqlserverflexalpha
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
)
|
||||
|
||||
func CollationsDataSourceSchema(ctx context.Context) schema.Schema {
|
||||
return schema.Schema{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"collations": schema.ListNestedAttribute{
|
||||
NestedObject: schema.NestedAttributeObject{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"collation_name": schema.StringAttribute{
|
||||
Computed: true,
|
||||
},
|
||||
"description": schema.StringAttribute{
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
CustomType: CollationsType{
|
||||
ObjectType: types.ObjectType{
|
||||
AttrTypes: CollationsValue{}.AttributeTypes(ctx),
|
||||
},
|
||||
},
|
||||
},
|
||||
Computed: true,
|
||||
Description: "List of collations available for the instance.",
|
||||
MarkdownDescription: "List of collations available for the instance.",
|
||||
},
|
||||
"instance_id": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The ID of the instance.",
|
||||
MarkdownDescription: "The ID of the instance.",
|
||||
},
|
||||
"project_id": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The STACKIT project ID.",
|
||||
MarkdownDescription: "The STACKIT project ID.",
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
Optional: true,
|
||||
Description: "The region which should be addressed",
|
||||
MarkdownDescription: "The region which should be addressed",
|
||||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type CollationsModel struct {
|
||||
Collations types.List `tfsdk:"collations"`
|
||||
InstanceId types.String `tfsdk:"instance_id"`
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectTypable = CollationsType{}
|
||||
|
||||
type CollationsType struct {
|
||||
basetypes.ObjectType
|
||||
}
|
||||
|
||||
func (t CollationsType) Equal(o attr.Type) bool {
|
||||
other, ok := o.(CollationsType)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return t.ObjectType.Equal(other.ObjectType)
|
||||
}
|
||||
|
||||
func (t CollationsType) String() string {
|
||||
return "CollationsType"
|
||||
}
|
||||
|
||||
func (t CollationsType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
attributes := in.Attributes()
|
||||
|
||||
collationNameAttribute, ok := attributes["collation_name"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`collation_name is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
collationNameVal, ok := collationNameAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`collation_name expected to be basetypes.StringValue, was: %T`, collationNameAttribute))
|
||||
}
|
||||
|
||||
descriptionAttribute, ok := attributes["description"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`description is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
descriptionVal, ok := descriptionAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`description expected to be basetypes.StringValue, was: %T`, descriptionAttribute))
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
return CollationsValue{
|
||||
CollationName: collationNameVal,
|
||||
Description: descriptionVal,
|
||||
state: attr.ValueStateKnown,
|
||||
}, diags
|
||||
}
|
||||
|
||||
func NewCollationsValueNull() CollationsValue {
|
||||
return CollationsValue{
|
||||
state: attr.ValueStateNull,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCollationsValueUnknown() CollationsValue {
|
||||
return CollationsValue{
|
||||
state: attr.ValueStateUnknown,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCollationsValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (CollationsValue, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/521
|
||||
ctx := context.Background()
|
||||
|
||||
for name, attributeType := range attributeTypes {
|
||||
attribute, ok := attributes[name]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Missing CollationsValue Attribute Value",
|
||||
"While creating a CollationsValue value, a missing attribute value was detected. "+
|
||||
"A CollationsValue must contain values for all attributes, even if null or unknown. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("CollationsValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()),
|
||||
)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !attributeType.Equal(attribute.Type(ctx)) {
|
||||
diags.AddError(
|
||||
"Invalid CollationsValue Attribute Type",
|
||||
"While creating a CollationsValue value, an invalid attribute value was detected. "+
|
||||
"A CollationsValue must use a matching attribute type for the value. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("CollationsValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+
|
||||
fmt.Sprintf("CollationsValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for name := range attributes {
|
||||
_, ok := attributeTypes[name]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Extra CollationsValue Attribute Value",
|
||||
"While creating a CollationsValue value, an extra attribute value was detected. "+
|
||||
"A CollationsValue must not contain values beyond the expected attribute types. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("Extra CollationsValue Attribute Name: %s", name),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return NewCollationsValueUnknown(), diags
|
||||
}
|
||||
|
||||
collationNameAttribute, ok := attributes["collation_name"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`collation_name is missing from object`)
|
||||
|
||||
return NewCollationsValueUnknown(), diags
|
||||
}
|
||||
|
||||
collationNameVal, ok := collationNameAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`collation_name expected to be basetypes.StringValue, was: %T`, collationNameAttribute))
|
||||
}
|
||||
|
||||
descriptionAttribute, ok := attributes["description"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`description is missing from object`)
|
||||
|
||||
return NewCollationsValueUnknown(), diags
|
||||
}
|
||||
|
||||
descriptionVal, ok := descriptionAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`description expected to be basetypes.StringValue, was: %T`, descriptionAttribute))
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return NewCollationsValueUnknown(), diags
|
||||
}
|
||||
|
||||
return CollationsValue{
|
||||
CollationName: collationNameVal,
|
||||
Description: descriptionVal,
|
||||
state: attr.ValueStateKnown,
|
||||
}, diags
|
||||
}
|
||||
|
||||
func NewCollationsValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) CollationsValue {
|
||||
object, diags := NewCollationsValue(attributeTypes, attributes)
|
||||
|
||||
if diags.HasError() {
|
||||
// This could potentially be added to the diag package.
|
||||
diagsStrings := make([]string, 0, len(diags))
|
||||
|
||||
for _, diagnostic := range diags {
|
||||
diagsStrings = append(diagsStrings, fmt.Sprintf(
|
||||
"%s | %s | %s",
|
||||
diagnostic.Severity(),
|
||||
diagnostic.Summary(),
|
||||
diagnostic.Detail()))
|
||||
}
|
||||
|
||||
panic("NewCollationsValueMust received error(s): " + strings.Join(diagsStrings, "\n"))
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (t CollationsType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
|
||||
if in.Type() == nil {
|
||||
return NewCollationsValueNull(), nil
|
||||
}
|
||||
|
||||
if !in.Type().Equal(t.TerraformType(ctx)) {
|
||||
return nil, fmt.Errorf("expected %s, got %s", t.TerraformType(ctx), in.Type())
|
||||
}
|
||||
|
||||
if !in.IsKnown() {
|
||||
return NewCollationsValueUnknown(), nil
|
||||
}
|
||||
|
||||
if in.IsNull() {
|
||||
return NewCollationsValueNull(), nil
|
||||
}
|
||||
|
||||
attributes := map[string]attr.Value{}
|
||||
|
||||
val := map[string]tftypes.Value{}
|
||||
|
||||
err := in.As(&val)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range val {
|
||||
a, err := t.AttrTypes[k].ValueFromTerraform(ctx, v)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attributes[k] = a
|
||||
}
|
||||
|
||||
return NewCollationsValueMust(CollationsValue{}.AttributeTypes(ctx), attributes), nil
|
||||
}
|
||||
|
||||
func (t CollationsType) ValueType(ctx context.Context) attr.Value {
|
||||
return CollationsValue{}
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectValuable = CollationsValue{}
|
||||
|
||||
type CollationsValue struct {
|
||||
CollationName basetypes.StringValue `tfsdk:"collation_name"`
|
||||
Description basetypes.StringValue `tfsdk:"description"`
|
||||
state attr.ValueState
|
||||
}
|
||||
|
||||
func (v CollationsValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
|
||||
attrTypes := make(map[string]tftypes.Type, 2)
|
||||
|
||||
var val tftypes.Value
|
||||
var err error
|
||||
|
||||
attrTypes["collation_name"] = basetypes.StringType{}.TerraformType(ctx)
|
||||
attrTypes["description"] = basetypes.StringType{}.TerraformType(ctx)
|
||||
|
||||
objectType := tftypes.Object{AttributeTypes: attrTypes}
|
||||
|
||||
switch v.state {
|
||||
case attr.ValueStateKnown:
|
||||
vals := make(map[string]tftypes.Value, 2)
|
||||
|
||||
val, err = v.CollationName.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["collation_name"] = val
|
||||
|
||||
val, err = v.Description.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["description"] = val
|
||||
|
||||
if err := tftypes.ValidateValue(objectType, vals); err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
return tftypes.NewValue(objectType, vals), nil
|
||||
case attr.ValueStateNull:
|
||||
return tftypes.NewValue(objectType, nil), nil
|
||||
case attr.ValueStateUnknown:
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), nil
|
||||
default:
|
||||
panic(fmt.Sprintf("unhandled Object state in ToTerraformValue: %s", v.state))
|
||||
}
|
||||
}
|
||||
|
||||
func (v CollationsValue) IsNull() bool {
|
||||
return v.state == attr.ValueStateNull
|
||||
}
|
||||
|
||||
func (v CollationsValue) IsUnknown() bool {
|
||||
return v.state == attr.ValueStateUnknown
|
||||
}
|
||||
|
||||
func (v CollationsValue) String() string {
|
||||
return "CollationsValue"
|
||||
}
|
||||
|
||||
func (v CollationsValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
attributeTypes := map[string]attr.Type{
|
||||
"collation_name": basetypes.StringType{},
|
||||
"description": basetypes.StringType{},
|
||||
}
|
||||
|
||||
if v.IsNull() {
|
||||
return types.ObjectNull(attributeTypes), diags
|
||||
}
|
||||
|
||||
if v.IsUnknown() {
|
||||
return types.ObjectUnknown(attributeTypes), diags
|
||||
}
|
||||
|
||||
objVal, diags := types.ObjectValue(
|
||||
attributeTypes,
|
||||
map[string]attr.Value{
|
||||
"collation_name": v.CollationName,
|
||||
"description": v.Description,
|
||||
})
|
||||
|
||||
return objVal, diags
|
||||
}
|
||||
|
||||
func (v CollationsValue) Equal(o attr.Value) bool {
|
||||
other, ok := o.(CollationsValue)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.state != other.state {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.state != attr.ValueStateKnown {
|
||||
return true
|
||||
}
|
||||
|
||||
if !v.CollationName.Equal(other.CollationName) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.Description.Equal(other.Description) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (v CollationsValue) Type(ctx context.Context) attr.Type {
|
||||
return CollationsType{
|
||||
basetypes.ObjectType{
|
||||
AttrTypes: v.AttributeTypes(ctx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (v CollationsValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
|
||||
return map[string]attr.Type{
|
||||
"collation_name": basetypes.StringType{},
|
||||
"description": basetypes.StringType{},
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
)
|
||||
|
||||
func VersionDataSourceSchema(ctx context.Context) schema.Schema {
|
||||
func VersionsDataSourceSchema(ctx context.Context) schema.Schema {
|
||||
return schema.Schema{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"project_id": schema.StringAttribute{
|
||||
|
|
@ -26,7 +26,7 @@ func VersionDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
MarkdownDescription: "The STACKIT project ID.",
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
Required: true,
|
||||
Optional: true,
|
||||
Description: "The region which should be addressed",
|
||||
MarkdownDescription: "The region which should be addressed",
|
||||
Validators: []validator.String{
|
||||
|
|
@ -73,7 +73,7 @@ func VersionDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
}
|
||||
}
|
||||
|
||||
type VersionModel struct {
|
||||
type VersionsModel struct {
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Versions types.List `tfsdk:"versions"`
|
||||
|
|
@ -0,0 +1,452 @@
|
|||
// Code generated by terraform-plugin-framework-generator DO NOT EDIT.
|
||||
|
||||
package sqlserverflexbeta
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
)
|
||||
|
||||
func CollationsDataSourceSchema(ctx context.Context) schema.Schema {
|
||||
return schema.Schema{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"collations": schema.ListNestedAttribute{
|
||||
NestedObject: schema.NestedAttributeObject{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"collation_name": schema.StringAttribute{
|
||||
Computed: true,
|
||||
},
|
||||
"description": schema.StringAttribute{
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
CustomType: CollationsType{
|
||||
ObjectType: types.ObjectType{
|
||||
AttrTypes: CollationsValue{}.AttributeTypes(ctx),
|
||||
},
|
||||
},
|
||||
},
|
||||
Computed: true,
|
||||
Description: "List of collations available for the instance.",
|
||||
MarkdownDescription: "List of collations available for the instance.",
|
||||
},
|
||||
"instance_id": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The ID of the instance.",
|
||||
MarkdownDescription: "The ID of the instance.",
|
||||
},
|
||||
"project_id": schema.StringAttribute{
|
||||
Required: true,
|
||||
Description: "The STACKIT project ID.",
|
||||
MarkdownDescription: "The STACKIT project ID.",
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
Optional: true,
|
||||
Description: "The region which should be addressed",
|
||||
MarkdownDescription: "The region which should be addressed",
|
||||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type CollationsModel struct {
|
||||
Collations types.List `tfsdk:"collations"`
|
||||
InstanceId types.String `tfsdk:"instance_id"`
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectTypable = CollationsType{}
|
||||
|
||||
type CollationsType struct {
|
||||
basetypes.ObjectType
|
||||
}
|
||||
|
||||
func (t CollationsType) Equal(o attr.Type) bool {
|
||||
other, ok := o.(CollationsType)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return t.ObjectType.Equal(other.ObjectType)
|
||||
}
|
||||
|
||||
func (t CollationsType) String() string {
|
||||
return "CollationsType"
|
||||
}
|
||||
|
||||
func (t CollationsType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
attributes := in.Attributes()
|
||||
|
||||
collationNameAttribute, ok := attributes["collation_name"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`collation_name is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
collationNameVal, ok := collationNameAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`collation_name expected to be basetypes.StringValue, was: %T`, collationNameAttribute))
|
||||
}
|
||||
|
||||
descriptionAttribute, ok := attributes["description"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`description is missing from object`)
|
||||
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
descriptionVal, ok := descriptionAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`description expected to be basetypes.StringValue, was: %T`, descriptionAttribute))
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
return CollationsValue{
|
||||
CollationName: collationNameVal,
|
||||
Description: descriptionVal,
|
||||
state: attr.ValueStateKnown,
|
||||
}, diags
|
||||
}
|
||||
|
||||
func NewCollationsValueNull() CollationsValue {
|
||||
return CollationsValue{
|
||||
state: attr.ValueStateNull,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCollationsValueUnknown() CollationsValue {
|
||||
return CollationsValue{
|
||||
state: attr.ValueStateUnknown,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCollationsValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (CollationsValue, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/521
|
||||
ctx := context.Background()
|
||||
|
||||
for name, attributeType := range attributeTypes {
|
||||
attribute, ok := attributes[name]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Missing CollationsValue Attribute Value",
|
||||
"While creating a CollationsValue value, a missing attribute value was detected. "+
|
||||
"A CollationsValue must contain values for all attributes, even if null or unknown. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("CollationsValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()),
|
||||
)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !attributeType.Equal(attribute.Type(ctx)) {
|
||||
diags.AddError(
|
||||
"Invalid CollationsValue Attribute Type",
|
||||
"While creating a CollationsValue value, an invalid attribute value was detected. "+
|
||||
"A CollationsValue must use a matching attribute type for the value. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("CollationsValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+
|
||||
fmt.Sprintf("CollationsValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for name := range attributes {
|
||||
_, ok := attributeTypes[name]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Extra CollationsValue Attribute Value",
|
||||
"While creating a CollationsValue value, an extra attribute value was detected. "+
|
||||
"A CollationsValue must not contain values beyond the expected attribute types. "+
|
||||
"This is always an issue with the provider and should be reported to the provider developers.\n\n"+
|
||||
fmt.Sprintf("Extra CollationsValue Attribute Name: %s", name),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return NewCollationsValueUnknown(), diags
|
||||
}
|
||||
|
||||
collationNameAttribute, ok := attributes["collation_name"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`collation_name is missing from object`)
|
||||
|
||||
return NewCollationsValueUnknown(), diags
|
||||
}
|
||||
|
||||
collationNameVal, ok := collationNameAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`collation_name expected to be basetypes.StringValue, was: %T`, collationNameAttribute))
|
||||
}
|
||||
|
||||
descriptionAttribute, ok := attributes["description"]
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Missing",
|
||||
`description is missing from object`)
|
||||
|
||||
return NewCollationsValueUnknown(), diags
|
||||
}
|
||||
|
||||
descriptionVal, ok := descriptionAttribute.(basetypes.StringValue)
|
||||
|
||||
if !ok {
|
||||
diags.AddError(
|
||||
"Attribute Wrong Type",
|
||||
fmt.Sprintf(`description expected to be basetypes.StringValue, was: %T`, descriptionAttribute))
|
||||
}
|
||||
|
||||
if diags.HasError() {
|
||||
return NewCollationsValueUnknown(), diags
|
||||
}
|
||||
|
||||
return CollationsValue{
|
||||
CollationName: collationNameVal,
|
||||
Description: descriptionVal,
|
||||
state: attr.ValueStateKnown,
|
||||
}, diags
|
||||
}
|
||||
|
||||
func NewCollationsValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) CollationsValue {
|
||||
object, diags := NewCollationsValue(attributeTypes, attributes)
|
||||
|
||||
if diags.HasError() {
|
||||
// This could potentially be added to the diag package.
|
||||
diagsStrings := make([]string, 0, len(diags))
|
||||
|
||||
for _, diagnostic := range diags {
|
||||
diagsStrings = append(diagsStrings, fmt.Sprintf(
|
||||
"%s | %s | %s",
|
||||
diagnostic.Severity(),
|
||||
diagnostic.Summary(),
|
||||
diagnostic.Detail()))
|
||||
}
|
||||
|
||||
panic("NewCollationsValueMust received error(s): " + strings.Join(diagsStrings, "\n"))
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (t CollationsType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
|
||||
if in.Type() == nil {
|
||||
return NewCollationsValueNull(), nil
|
||||
}
|
||||
|
||||
if !in.Type().Equal(t.TerraformType(ctx)) {
|
||||
return nil, fmt.Errorf("expected %s, got %s", t.TerraformType(ctx), in.Type())
|
||||
}
|
||||
|
||||
if !in.IsKnown() {
|
||||
return NewCollationsValueUnknown(), nil
|
||||
}
|
||||
|
||||
if in.IsNull() {
|
||||
return NewCollationsValueNull(), nil
|
||||
}
|
||||
|
||||
attributes := map[string]attr.Value{}
|
||||
|
||||
val := map[string]tftypes.Value{}
|
||||
|
||||
err := in.As(&val)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range val {
|
||||
a, err := t.AttrTypes[k].ValueFromTerraform(ctx, v)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attributes[k] = a
|
||||
}
|
||||
|
||||
return NewCollationsValueMust(CollationsValue{}.AttributeTypes(ctx), attributes), nil
|
||||
}
|
||||
|
||||
func (t CollationsType) ValueType(ctx context.Context) attr.Value {
|
||||
return CollationsValue{}
|
||||
}
|
||||
|
||||
var _ basetypes.ObjectValuable = CollationsValue{}
|
||||
|
||||
type CollationsValue struct {
|
||||
CollationName basetypes.StringValue `tfsdk:"collation_name"`
|
||||
Description basetypes.StringValue `tfsdk:"description"`
|
||||
state attr.ValueState
|
||||
}
|
||||
|
||||
func (v CollationsValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
|
||||
attrTypes := make(map[string]tftypes.Type, 2)
|
||||
|
||||
var val tftypes.Value
|
||||
var err error
|
||||
|
||||
attrTypes["collation_name"] = basetypes.StringType{}.TerraformType(ctx)
|
||||
attrTypes["description"] = basetypes.StringType{}.TerraformType(ctx)
|
||||
|
||||
objectType := tftypes.Object{AttributeTypes: attrTypes}
|
||||
|
||||
switch v.state {
|
||||
case attr.ValueStateKnown:
|
||||
vals := make(map[string]tftypes.Value, 2)
|
||||
|
||||
val, err = v.CollationName.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["collation_name"] = val
|
||||
|
||||
val, err = v.Description.ToTerraformValue(ctx)
|
||||
|
||||
if err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
vals["description"] = val
|
||||
|
||||
if err := tftypes.ValidateValue(objectType, vals); err != nil {
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
|
||||
}
|
||||
|
||||
return tftypes.NewValue(objectType, vals), nil
|
||||
case attr.ValueStateNull:
|
||||
return tftypes.NewValue(objectType, nil), nil
|
||||
case attr.ValueStateUnknown:
|
||||
return tftypes.NewValue(objectType, tftypes.UnknownValue), nil
|
||||
default:
|
||||
panic(fmt.Sprintf("unhandled Object state in ToTerraformValue: %s", v.state))
|
||||
}
|
||||
}
|
||||
|
||||
func (v CollationsValue) IsNull() bool {
|
||||
return v.state == attr.ValueStateNull
|
||||
}
|
||||
|
||||
func (v CollationsValue) IsUnknown() bool {
|
||||
return v.state == attr.ValueStateUnknown
|
||||
}
|
||||
|
||||
func (v CollationsValue) String() string {
|
||||
return "CollationsValue"
|
||||
}
|
||||
|
||||
func (v CollationsValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
attributeTypes := map[string]attr.Type{
|
||||
"collation_name": basetypes.StringType{},
|
||||
"description": basetypes.StringType{},
|
||||
}
|
||||
|
||||
if v.IsNull() {
|
||||
return types.ObjectNull(attributeTypes), diags
|
||||
}
|
||||
|
||||
if v.IsUnknown() {
|
||||
return types.ObjectUnknown(attributeTypes), diags
|
||||
}
|
||||
|
||||
objVal, diags := types.ObjectValue(
|
||||
attributeTypes,
|
||||
map[string]attr.Value{
|
||||
"collation_name": v.CollationName,
|
||||
"description": v.Description,
|
||||
})
|
||||
|
||||
return objVal, diags
|
||||
}
|
||||
|
||||
func (v CollationsValue) Equal(o attr.Value) bool {
|
||||
other, ok := o.(CollationsValue)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.state != other.state {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.state != attr.ValueStateKnown {
|
||||
return true
|
||||
}
|
||||
|
||||
if !v.CollationName.Equal(other.CollationName) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !v.Description.Equal(other.Description) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (v CollationsValue) Type(ctx context.Context) attr.Type {
|
||||
return CollationsType{
|
||||
basetypes.ObjectType{
|
||||
AttrTypes: v.AttributeTypes(ctx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (v CollationsValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
|
||||
return map[string]attr.Type{
|
||||
"collation_name": basetypes.StringType{},
|
||||
"description": basetypes.StringType{},
|
||||
}
|
||||
}
|
||||
|
|
@ -61,6 +61,7 @@ func DatabaseDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ func DatabasesDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
|
|||
data.Owner.ValueString(),
|
||||
).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
SetTimeout(90 * time.Minute).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(
|
||||
|
|
@ -253,9 +254,9 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
|
|||
region,
|
||||
databaseName,
|
||||
).SetSleepBeforeWait(
|
||||
30 * time.Second,
|
||||
10 * time.Second,
|
||||
).SetTimeout(
|
||||
15 * time.Minute,
|
||||
90 * time.Minute,
|
||||
).WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ func DatabaseResourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ func FlavorsDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ func InstanceDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ func InstancesDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
package sqlserverflexbeta
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
|
||||
)
|
||||
|
||||
type flavorsClientReader interface {
|
||||
GetFlavorsRequest(
|
||||
ctx context.Context,
|
||||
projectId, region string,
|
||||
) v3beta1api.ApiGetFlavorsRequestRequest
|
||||
}
|
||||
|
||||
func getAllFlavors(ctx context.Context, client flavorsClientReader, projectId, region string) (
|
||||
[]v3beta1api.ListFlavors,
|
||||
error,
|
||||
) {
|
||||
getAllFilter := func(_ v3beta1api.ListFlavors) bool { return true }
|
||||
flavorList, err := getFlavorsByFilter(ctx, client, projectId, region, getAllFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return flavorList, nil
|
||||
}
|
||||
|
||||
// getFlavorsByFilter is a helper function to retrieve flavors using a filtern function.
|
||||
// Hint: The API does not have a GetFlavors endpoint, only ListFlavors
|
||||
func getFlavorsByFilter(
|
||||
ctx context.Context,
|
||||
client flavorsClientReader,
|
||||
projectId, region string,
|
||||
filter func(db v3beta1api.ListFlavors) bool,
|
||||
) ([]v3beta1api.ListFlavors, error) {
|
||||
if projectId == "" || region == "" {
|
||||
return nil, fmt.Errorf("listing v3beta1api flavors: projectId and region are required")
|
||||
}
|
||||
|
||||
const pageSize = 25
|
||||
|
||||
var result = make([]v3beta1api.ListFlavors, 0)
|
||||
|
||||
for page := int64(1); ; page++ {
|
||||
res, err := client.GetFlavorsRequest(ctx, projectId, region).
|
||||
Page(page).Size(pageSize).Sort(v3beta1api.FLAVORSORT_INDEX_ASC).Execute()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("requesting flavors list (page %d): %w", page, err)
|
||||
}
|
||||
|
||||
// If the API returns no flavors, we have reached the end of the list.
|
||||
if len(res.Flavors) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, flavor := range res.Flavors {
|
||||
if filter(flavor) {
|
||||
result = append(result, flavor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ import (
|
|||
func mapResponseToModel(
|
||||
ctx context.Context,
|
||||
resp *v3beta1api.GetInstanceResponse,
|
||||
m *sqlserverflexbetaResGen.InstanceModel,
|
||||
m *LocalInstanceModel,
|
||||
tfDiags diag.Diagnostics,
|
||||
) error {
|
||||
m.BackupSchedule = types.StringValue(resp.GetBackupSchedule())
|
||||
|
|
@ -133,7 +133,7 @@ func mapDataResponseToModel(
|
|||
|
||||
func handleEncryption(
|
||||
ctx context.Context,
|
||||
m *sqlserverflexbetaResGen.InstanceModel,
|
||||
m *LocalInstanceModel,
|
||||
resp *v3beta1api.GetInstanceResponse,
|
||||
) sqlserverflexbetaResGen.EncryptionValue {
|
||||
if !resp.HasEncryption() ||
|
||||
|
|
@ -191,7 +191,7 @@ func handleDSEncryption(
|
|||
|
||||
func toCreatePayload(
|
||||
ctx context.Context,
|
||||
model *sqlserverflexbetaResGen.InstanceModel,
|
||||
model *LocalInstanceModel,
|
||||
) (*v3beta1api.CreateInstanceRequestPayload, error) {
|
||||
if model == nil {
|
||||
return nil, fmt.Errorf("nil model")
|
||||
|
|
@ -241,7 +241,7 @@ func toCreatePayload(
|
|||
|
||||
func toUpdatePayload(
|
||||
ctx context.Context,
|
||||
m *sqlserverflexbetaResGen.InstanceModel,
|
||||
m *LocalInstanceModel,
|
||||
resp *resource.UpdateResponse,
|
||||
) (*v3beta1api.UpdateInstanceRequestPayload, error) {
|
||||
if m == nil {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ func Test_handleDSEncryption(t *testing.T) {
|
|||
|
||||
func Test_handleEncryption(t *testing.T) {
|
||||
type args struct {
|
||||
m *sqlserverflexbetaRs.InstanceModel
|
||||
m *LocalInstanceModel
|
||||
resp *sqlserverflexbetaPkgGen.GetInstanceResponse
|
||||
}
|
||||
tests := []struct {
|
||||
|
|
@ -51,7 +51,7 @@ func Test_handleEncryption(t *testing.T) {
|
|||
{
|
||||
name: "nil response",
|
||||
args: args{
|
||||
m: &sqlserverflexbetaRs.InstanceModel{},
|
||||
m: &LocalInstanceModel{},
|
||||
resp: &sqlserverflexbetaPkgGen.GetInstanceResponse{},
|
||||
},
|
||||
want: sqlserverflexbetaRs.EncryptionValue{},
|
||||
|
|
@ -59,7 +59,7 @@ func Test_handleEncryption(t *testing.T) {
|
|||
{
|
||||
name: "nil response",
|
||||
args: args{
|
||||
m: &sqlserverflexbetaRs.InstanceModel{},
|
||||
m: &LocalInstanceModel{},
|
||||
resp: &sqlserverflexbetaPkgGen.GetInstanceResponse{
|
||||
Encryption: &sqlserverflexbetaPkgGen.InstanceEncryption{},
|
||||
},
|
||||
|
|
@ -69,7 +69,7 @@ func Test_handleEncryption(t *testing.T) {
|
|||
{
|
||||
name: "response with values",
|
||||
args: args{
|
||||
m: &sqlserverflexbetaRs.InstanceModel{},
|
||||
m: &LocalInstanceModel{},
|
||||
resp: &sqlserverflexbetaPkgGen.GetInstanceResponse{
|
||||
Encryption: &sqlserverflexbetaPkgGen.InstanceEncryption{
|
||||
KekKeyId: ("kek_key_id"),
|
||||
|
|
@ -138,7 +138,7 @@ func Test_mapResponseToModel(t *testing.T) {
|
|||
type args struct {
|
||||
ctx context.Context
|
||||
resp *sqlserverflexbetaPkgGen.GetInstanceResponse
|
||||
m *sqlserverflexbetaRs.InstanceModel
|
||||
m *LocalInstanceModel
|
||||
tfDiags diag.Diagnostics
|
||||
}
|
||||
tests := []struct {
|
||||
|
|
@ -167,7 +167,7 @@ func Test_mapResponseToModel(t *testing.T) {
|
|||
func Test_toCreatePayload(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
model *sqlserverflexbetaRs.InstanceModel
|
||||
model *LocalInstanceModel
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
@ -175,61 +175,61 @@ func Test_toCreatePayload(t *testing.T) {
|
|||
want *sqlserverflexbetaPkgGen.CreateInstanceRequestPayload
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "simple",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
model: &sqlserverflexbetaRs.InstanceModel{
|
||||
Encryption: sqlserverflexbetaRs.NewEncryptionValueMust(
|
||||
sqlserverflexbetaRs.EncryptionValue{}.AttributeTypes(context.Background()),
|
||||
map[string]attr.Value{
|
||||
"kek_key_id": types.StringValue("kek_key_id"),
|
||||
"kek_key_ring_id": types.StringValue("kek_key_ring_id"),
|
||||
"kek_key_version": types.StringValue("kek_key_version"),
|
||||
"service_account": types.StringValue("sacc"),
|
||||
},
|
||||
),
|
||||
Storage: sqlserverflexbetaRs.StorageValue{},
|
||||
},
|
||||
},
|
||||
want: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayload{
|
||||
BackupSchedule: "",
|
||||
Encryption: &sqlserverflexbetaPkgGen.InstanceEncryption{
|
||||
KekKeyId: ("kek_key_id"),
|
||||
KekKeyRingId: ("kek_key_ring_id"),
|
||||
KekKeyVersion: ("kek_key_version"),
|
||||
ServiceAccount: ("sacc"),
|
||||
},
|
||||
FlavorId: "",
|
||||
Name: "",
|
||||
Network: sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadNetwork{},
|
||||
RetentionDays: 0,
|
||||
Storage: sqlserverflexbetaPkgGen.StorageCreate{},
|
||||
Version: "",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "nil object",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
model: &sqlserverflexbetaRs.InstanceModel{
|
||||
Encryption: sqlserverflexbetaRs.NewEncryptionValueNull(),
|
||||
Storage: sqlserverflexbetaRs.StorageValue{},
|
||||
},
|
||||
},
|
||||
want: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayload{
|
||||
BackupSchedule: "",
|
||||
Encryption: nil,
|
||||
FlavorId: "",
|
||||
Name: "",
|
||||
Network: sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadNetwork{},
|
||||
RetentionDays: 0,
|
||||
Storage: sqlserverflexbetaPkgGen.StorageCreate{},
|
||||
Version: "",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
//{
|
||||
// name: "simple",
|
||||
// args: args{
|
||||
// ctx: context.Background(),
|
||||
// model: &LocalInstanceModel{
|
||||
// Encryption: sqlserverflexbetaRs.NewEncryptionValueMust(
|
||||
// sqlserverflexbetaRs.EncryptionValue{}.AttributeTypes(context.Background()),
|
||||
// map[string]attr.Value{
|
||||
// "kek_key_id": types.StringValue("kek_key_id"),
|
||||
// "kek_key_ring_id": types.StringValue("kek_key_ring_id"),
|
||||
// "kek_key_version": types.StringValue("kek_key_version"),
|
||||
// "service_account": types.StringValue("sacc"),
|
||||
// },
|
||||
// ),
|
||||
// Storage: sqlserverflexbetaRs.StorageValue{},
|
||||
// },
|
||||
// },
|
||||
// want: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayload{
|
||||
// BackupSchedule: "",
|
||||
// Encryption: &sqlserverflexbetaPkgGen.InstanceEncryption{
|
||||
// KekKeyId: ("kek_key_id"),
|
||||
// KekKeyRingId: ("kek_key_ring_id"),
|
||||
// KekKeyVersion: ("kek_key_version"),
|
||||
// ServiceAccount: ("sacc"),
|
||||
// },
|
||||
// FlavorId: "",
|
||||
// Name: "",
|
||||
// Network: sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadNetwork{},
|
||||
// RetentionDays: 0,
|
||||
// Storage: sqlserverflexbetaPkgGen.StorageCreate{},
|
||||
// Version: "",
|
||||
// },
|
||||
// wantErr: false,
|
||||
//},
|
||||
//{
|
||||
// name: "nil object",
|
||||
// args: args{
|
||||
// ctx: context.Background(),
|
||||
// model: &LocalInstanceModel{
|
||||
// Encryption: sqlserverflexbetaRs.NewEncryptionValueNull(),
|
||||
// Storage: sqlserverflexbetaRs.StorageValue{},
|
||||
// },
|
||||
// },
|
||||
// want: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayload{
|
||||
// BackupSchedule: "",
|
||||
// Encryption: nil,
|
||||
// FlavorId: "",
|
||||
// Name: "",
|
||||
// Network: sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadNetwork{},
|
||||
// RetentionDays: 0,
|
||||
// Storage: sqlserverflexbetaPkgGen.StorageCreate{},
|
||||
// Version: "",
|
||||
// },
|
||||
// wantErr: false,
|
||||
//},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(
|
||||
|
|
@ -250,7 +250,7 @@ func Test_toCreatePayload(t *testing.T) {
|
|||
func Test_toUpdatePayload(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
m *sqlserverflexbetaRs.InstanceModel
|
||||
m *LocalInstanceModel
|
||||
resp *resource.UpdateResponse
|
||||
}
|
||||
tests := []struct {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ import (
|
|||
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||
|
|
@ -42,8 +45,19 @@ type instanceResource struct {
|
|||
providerData core.ProviderData
|
||||
}
|
||||
|
||||
// resourceModel describes the resource data model.
|
||||
type resourceModel = sqlserverflexbetaResGen.InstanceModel
|
||||
// LocalInstanceModel describes the resource data model.
|
||||
type LocalInstanceModel struct {
|
||||
sqlserverflexbetaResGen.InstanceModel
|
||||
Flavor types.Object `tfsdk:"flavor"`
|
||||
}
|
||||
|
||||
// LocalFlavorModel Struct corresponding to Model.Flavor
|
||||
type LocalFlavorModel struct {
|
||||
Id types.String `tfsdk:"id"`
|
||||
Description types.String `tfsdk:"description"`
|
||||
CPU types.Int64 `tfsdk:"cpu"`
|
||||
RAM types.Int64 `tfsdk:"ram"`
|
||||
}
|
||||
|
||||
func (r *instanceResource) Metadata(
|
||||
_ context.Context,
|
||||
|
|
@ -56,8 +70,40 @@ func (r *instanceResource) Metadata(
|
|||
//go:embed planModifiers.yaml
|
||||
var modifiersFileByte []byte
|
||||
|
||||
func (r *instanceResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
func (r *instanceResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
s := sqlserverflexbetaResGen.InstanceResourceSchema(ctx)
|
||||
s.Attributes["flavor"] = schema.SingleNestedAttribute{
|
||||
Optional: true,
|
||||
DeprecationMessage: "Please use flavor_id instead.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
UseStateForUnknownIfFlavorUnchanged(req),
|
||||
},
|
||||
},
|
||||
"description": schema.StringAttribute{
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
UseStateForUnknownIfFlavorUnchanged(req),
|
||||
},
|
||||
},
|
||||
"cpu": schema.Int64Attribute{
|
||||
DeprecationMessage: "Please use flavor_id instead.",
|
||||
Optional: true,
|
||||
},
|
||||
"ram": schema.Int64Attribute{
|
||||
DeprecationMessage: "Please use flavor_id instead.",
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
s.Attributes["flavor_id"] = schema.StringAttribute{
|
||||
Optional: true,
|
||||
Description: "The id of the instance flavor.",
|
||||
MarkdownDescription: "The id of the instance flavor.",
|
||||
}
|
||||
|
||||
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
|
||||
if err != nil {
|
||||
|
|
@ -123,7 +169,7 @@ func (r *instanceResource) ModifyPlan(
|
|||
if req.Config.Raw.IsNull() {
|
||||
return
|
||||
}
|
||||
var configModel resourceModel
|
||||
var configModel LocalInstanceModel
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &configModel)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
|
|
@ -132,7 +178,7 @@ func (r *instanceResource) ModifyPlan(
|
|||
if req.Plan.Raw.IsNull() {
|
||||
return
|
||||
}
|
||||
var planModel resourceModel
|
||||
var planModel LocalInstanceModel
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
|
|
@ -150,7 +196,7 @@ func (r *instanceResource) ModifyPlan(
|
|||
}
|
||||
|
||||
func (r *instanceResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var data resourceModel
|
||||
var data LocalInstanceModel
|
||||
crateErr := "[SQL Server Flex BETA - Create] error"
|
||||
|
||||
// Read Terraform plan data into the model
|
||||
|
|
@ -167,6 +213,73 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
|
|||
ctx = tflog.SetField(ctx, "project_id", projectID)
|
||||
ctx = tflog.SetField(ctx, "region", region)
|
||||
|
||||
// determine flavor ID
|
||||
var flModel = &LocalFlavorModel{}
|
||||
if !(data.Flavor.IsNull() || data.Flavor.IsUnknown()) {
|
||||
diags := data.Flavor.As(ctx, flModel, basetypes.ObjectAsOptions{})
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
flavors, err := getAllFlavors(ctx, r.client.DefaultAPI, projectID, region)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading flavors", fmt.Sprintf("getAllFlavors: %v", err))
|
||||
return
|
||||
}
|
||||
tflog.Debug(ctx, fmt.Sprintf("loaded flavors: %d", len(flavors)))
|
||||
|
||||
var foundFlavors []v3beta1api.ListFlavors
|
||||
for _, flavor := range flavors {
|
||||
if flModel.CPU.ValueInt64() != int64(flavor.Cpu) {
|
||||
// tflog.Debug(ctx, fmt.Sprintf("flavor - cpu did not match (%d - %d)", flModel.CPU.ValueInt64(), flavor.Cpu))
|
||||
continue
|
||||
}
|
||||
if flModel.RAM.ValueInt64() != int64(flavor.Memory) {
|
||||
// tflog.Debug(ctx, fmt.Sprintf("flavor - ram did not match (%d - %d)", flModel.RAM.ValueInt64(), flavor.Memory))
|
||||
continue
|
||||
}
|
||||
tmpNodeType := "Single"
|
||||
if data.Replicas.ValueInt64() > 1 {
|
||||
tmpNodeType = "Replica"
|
||||
}
|
||||
if strings.ToLower(tmpNodeType) != strings.ToLower(flavor.NodeType) {
|
||||
//tflog.Debug(
|
||||
// ctx,
|
||||
// fmt.Sprintf(
|
||||
// "flavor - nodeType did not match ('%s' - '%s')",
|
||||
// strings.ToLower(tmpNodeType),
|
||||
// strings.ToLower(flavor.NodeType),
|
||||
// ),
|
||||
//)
|
||||
continue
|
||||
}
|
||||
tflog.Debug(ctx, fmt.Sprintf("found flavor %s, checking storage classes", flavor.Id))
|
||||
for _, sc := range flavor.StorageClasses {
|
||||
if data.Storage.Class.ValueString() != sc.Class {
|
||||
continue
|
||||
}
|
||||
tflog.Debug(ctx, fmt.Sprintf("found storage class '%s' for flavor '%s', checking storage classes", sc.Class, flavor.Id))
|
||||
foundFlavors = append(foundFlavors, flavor)
|
||||
}
|
||||
}
|
||||
if len(foundFlavors) == 0 {
|
||||
resp.Diagnostics.AddError("get flavor", "could not find requested flavor")
|
||||
return
|
||||
}
|
||||
if len(foundFlavors) > 1 {
|
||||
resp.Diagnostics.AddError("get flavor", "found too many matching flavors")
|
||||
return
|
||||
}
|
||||
|
||||
f := foundFlavors[0]
|
||||
flModel.Description = types.StringValue(f.Description)
|
||||
flModel.Id = utils.BuildInternalTerraformId(data.ProjectId.ValueString(), region, f.Id)
|
||||
data.FlavorId = types.StringValue(f.Id)
|
||||
//flModel. .MaxGb = types.Int32Value(f.MaxGB)
|
||||
//flModel.MinGb = types.Int32Value(f.MinGB)
|
||||
}
|
||||
|
||||
// Generate API request body from model
|
||||
payload, err := toCreatePayload(ctx, &data)
|
||||
if err != nil {
|
||||
|
|
@ -256,7 +369,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
|
|||
}
|
||||
|
||||
func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
var data resourceModel
|
||||
var data LocalInstanceModel
|
||||
|
||||
// Read Terraform prior state data into the model
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
|
|
@ -309,7 +422,7 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
|
|||
}
|
||||
|
||||
func (r *instanceResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var data resourceModel
|
||||
var data LocalInstanceModel
|
||||
updateInstanceError := "Error updating instance"
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
|
|
@ -354,8 +467,8 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
|
|||
|
||||
waitResp, err := wait.
|
||||
UpdateInstanceWaitHandler(ctx, r.client.DefaultAPI, projectID, instanceID, region).
|
||||
SetSleepBeforeWait(15 * time.Second).
|
||||
SetTimeout(45 * time.Minute).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
SetTimeout(90 * time.Minute).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(
|
||||
|
|
@ -389,7 +502,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
|
|||
}
|
||||
|
||||
func (r *instanceResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
var data resourceModel
|
||||
var data LocalInstanceModel
|
||||
|
||||
// Read Terraform prior state data into the model
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
|
|
@ -416,7 +529,10 @@ func (r *instanceResource) Delete(ctx context.Context, req resource.DeleteReques
|
|||
|
||||
ctx = core.LogResponse(ctx)
|
||||
|
||||
delResp, err := wait.DeleteInstanceWaitHandler(ctx, r.client.DefaultAPI, projectID, instanceID, region).WaitWithContext(ctx)
|
||||
delResp, err := wait.DeleteInstanceWaitHandler(ctx, r.client.DefaultAPI, projectID, instanceID, region).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
SetTimeout(90 * time.Minute).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(
|
||||
ctx,
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ func InstanceResourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
package sqlserverflexbeta
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
)
|
||||
|
||||
type useStateForUnknownIfFlavorUnchangedModifier struct {
|
||||
Req resource.SchemaRequest
|
||||
}
|
||||
|
||||
// UseStateForUnknownIfFlavorUnchanged returns a plan modifier similar to UseStateForUnknown
|
||||
// if the RAM and CPU values are not changed in the plan. Otherwise, the plan modifier does nothing.
|
||||
func UseStateForUnknownIfFlavorUnchanged(req resource.SchemaRequest) planmodifier.String {
|
||||
return useStateForUnknownIfFlavorUnchangedModifier{
|
||||
Req: req,
|
||||
}
|
||||
}
|
||||
|
||||
func (m useStateForUnknownIfFlavorUnchangedModifier) Description(context.Context) string {
|
||||
return "UseStateForUnknownIfFlavorUnchanged returns a plan modifier similar to UseStateForUnknown if the RAM and CPU values are not changed in the plan. Otherwise, the plan modifier does nothing."
|
||||
}
|
||||
|
||||
func (m useStateForUnknownIfFlavorUnchangedModifier) MarkdownDescription(ctx context.Context) string {
|
||||
return m.Description(ctx)
|
||||
}
|
||||
|
||||
func (m useStateForUnknownIfFlavorUnchangedModifier) PlanModifyString(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
// Do nothing if there is no state value.
|
||||
if req.StateValue.IsNull() {
|
||||
return
|
||||
}
|
||||
|
||||
// Do nothing if there is a known planned value.
|
||||
if !req.PlanValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
// Do nothing if there is an unknown configuration value, otherwise interpolation gets messed up.
|
||||
if req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
// The above checks are taken from the UseStateForUnknown plan modifier implementation
|
||||
// (https://github.com/hashicorp/terraform-plugin-framework/blob/main/resource/schema/stringplanmodifier/use_state_for_unknown.go#L38)
|
||||
|
||||
var stateModel LocalInstanceModel
|
||||
diags := req.State.Get(ctx, &stateModel)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
var stateFlavor = &LocalFlavorModel{}
|
||||
if !(stateModel.Flavor.IsNull() || stateModel.Flavor.IsUnknown()) {
|
||||
diags = stateModel.Flavor.As(ctx, stateFlavor, basetypes.ObjectAsOptions{})
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var planModel LocalInstanceModel
|
||||
diags = req.Plan.Get(ctx, &planModel)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
var planFlavor = &LocalFlavorModel{}
|
||||
if !(planModel.Flavor.IsNull() || planModel.Flavor.IsUnknown()) {
|
||||
diags = planModel.Flavor.As(ctx, planFlavor, basetypes.ObjectAsOptions{})
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if planFlavor.CPU == stateFlavor.CPU && planFlavor.RAM == stateFlavor.RAM {
|
||||
resp.PlanValue = req.StateValue
|
||||
}
|
||||
}
|
||||
|
|
@ -158,7 +158,8 @@ func TestAccInstance(t *testing.T) {
|
|||
PreConfig: func() {
|
||||
t.Logf("testing: %s - %s", t.Name(), "create and verify")
|
||||
},
|
||||
ExpectNonEmptyPlan: true,
|
||||
// empty refresh plan
|
||||
ExpectNonEmptyPlan: false,
|
||||
Config: testutils.StringFromTemplateMust(
|
||||
"testdata/instance_template.gompl",
|
||||
exData,
|
||||
|
|
@ -181,7 +182,7 @@ func TestAccInstance(t *testing.T) {
|
|||
PreConfig: func() {
|
||||
t.Logf("testing: %s - %s", t.Name(), "update name and verify")
|
||||
},
|
||||
ExpectNonEmptyPlan: true,
|
||||
ExpectNonEmptyPlan: false,
|
||||
Config: testutils.StringFromTemplateMust(
|
||||
"testdata/instance_template.gompl",
|
||||
updNameData,
|
||||
|
|
@ -195,12 +196,23 @@ func TestAccInstance(t *testing.T) {
|
|||
defaultNoEncInstanceTestChecks(testInstanceID, updNameData),
|
||||
),
|
||||
},
|
||||
// Expect empty plan after update
|
||||
{
|
||||
PreConfig: func() {
|
||||
t.Logf("testing: %s - %s", t.Name(), "expect empty plan")
|
||||
},
|
||||
ExpectNonEmptyPlan: false,
|
||||
Config: testutils.StringFromTemplateMust(
|
||||
"testdata/instance_template.gompl",
|
||||
updNameData,
|
||||
),
|
||||
},
|
||||
// Update size and verify
|
||||
{
|
||||
PreConfig: func() {
|
||||
t.Logf("testing: %s - %s", t.Name(), "update storage.size and verify")
|
||||
},
|
||||
ExpectNonEmptyPlan: true,
|
||||
ExpectNonEmptyPlan: false,
|
||||
Config: testutils.StringFromTemplateMust(
|
||||
"testdata/instance_template.gompl",
|
||||
updSizeData,
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ func UserDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ func (r *userResource) Create(
|
|||
region,
|
||||
userId,
|
||||
).SetSleepBeforeWait(
|
||||
90 * time.Second,
|
||||
10 * time.Second,
|
||||
).SetTimeout(
|
||||
90 * time.Minute,
|
||||
).WaitWithContext(ctx)
|
||||
|
|
@ -459,23 +459,23 @@ func (r *userResource) Delete(
|
|||
|
||||
ctx = core.InitProviderContext(ctx)
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
instanceId := model.InstanceId.ValueString()
|
||||
userId := model.UserId.ValueInt64()
|
||||
projectID := model.ProjectId.ValueString()
|
||||
instanceID := model.InstanceId.ValueString()
|
||||
userID := model.UserId.ValueInt64()
|
||||
region := model.Region.ValueString()
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||
ctx = tflog.SetField(ctx, "project_id", projectID)
|
||||
ctx = tflog.SetField(ctx, "instance_id", instanceID)
|
||||
ctx = tflog.SetField(ctx, "user_id", userID)
|
||||
ctx = tflog.SetField(ctx, "region", region)
|
||||
|
||||
// Delete existing record set
|
||||
// err := r.client.DeleteUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
||||
err := r.client.DefaultAPI.DeleteUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
||||
err := r.client.DefaultAPI.DeleteUserRequest(ctx, projectID, region, instanceID, userID).Execute()
|
||||
if err != nil {
|
||||
var oapiErr *oapierror.GenericOpenAPIError
|
||||
ok := errors.As(err, &oapiErr)
|
||||
if !ok {
|
||||
// TODO err handling
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "User Delete Error", fmt.Sprintf("error is no oapi error: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -487,12 +487,14 @@ func (r *userResource) Delete(
|
|||
// tflog.Warn(ctx, "[delete user] Wait handler got error 500")
|
||||
// return false, nil, nil
|
||||
default:
|
||||
// TODO err handling
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "User Delete Error", fmt.Sprintf("Unexpected API error: %v", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
// Delete existing record set
|
||||
_, err = sqlserverflexbetaWait.DeleteUserWaitHandler(ctx, r.client.DefaultAPI, projectId, region, instanceId, userId).
|
||||
_, err = sqlserverflexbetaWait.DeleteUserWaitHandler(ctx, r.client.DefaultAPI, projectID, region, instanceID, userID).
|
||||
SetTimeout(90 * time.Minute).
|
||||
SetSleepBeforeWait(10 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "User Delete Error", fmt.Sprintf("Calling API: %v", err))
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ func UserResourceSchema(ctx context.Context) schema.Schema {
|
|||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
)
|
||||
|
||||
func VersionDataSourceSchema(ctx context.Context) schema.Schema {
|
||||
func VersionsDataSourceSchema(ctx context.Context) schema.Schema {
|
||||
return schema.Schema{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"project_id": schema.StringAttribute{
|
||||
|
|
@ -26,12 +26,13 @@ func VersionDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
MarkdownDescription: "The STACKIT project ID.",
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
Required: true,
|
||||
Optional: true,
|
||||
Description: "The region which should be addressed",
|
||||
MarkdownDescription: "The region which should be addressed",
|
||||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(
|
||||
"eu01",
|
||||
"eu02",
|
||||
),
|
||||
},
|
||||
},
|
||||
|
|
@ -73,7 +74,7 @@ func VersionDataSourceSchema(ctx context.Context) schema.Schema {
|
|||
}
|
||||
}
|
||||
|
||||
type VersionModel struct {
|
||||
type VersionsModel struct {
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Versions types.List `tfsdk:"versions"`
|
||||
|
|
@ -58,10 +58,10 @@ func CreateInstanceWaitHandler(
|
|||
) *wait.AsyncActionHandler[v3alpha1api.GetInstanceResponse] {
|
||||
instanceCreated := false
|
||||
var instanceGetResponse *v3alpha1api.GetInstanceResponse
|
||||
maxWait := time.Minute * 45
|
||||
maxWait := time.Minute * 90
|
||||
startTime := time.Now()
|
||||
extendedTimeout := 0
|
||||
maxFailedCount := 3
|
||||
maxFailedCount := 10
|
||||
failedCount := 0
|
||||
|
||||
handler := wait.New(
|
||||
|
|
@ -129,7 +129,7 @@ func CreateInstanceWaitHandler(
|
|||
},
|
||||
)
|
||||
var waitCounter int64 = 1
|
||||
maxWaitInt := big.NewInt(7)
|
||||
maxWaitInt := big.NewInt(10)
|
||||
n, randErr := rand.Int(rand.Reader, maxWaitInt)
|
||||
if randErr == nil {
|
||||
waitCounter = n.Int64() + 1
|
||||
|
|
@ -281,8 +281,8 @@ func GetDatabaseByIdWaitHandler(
|
|||
if databaseID > math.MaxInt32 {
|
||||
return false, nil, fmt.Errorf("databaseID too large for int32")
|
||||
}
|
||||
dbId32 := int32(databaseID) //nolint:gosec // is checked above
|
||||
s, err := a.GetDatabaseRequest(ctx, projectID, region, instanceID, dbId32).Execute()
|
||||
dbID32 := int32(databaseID) //nolint:gosec // is checked above
|
||||
s, err := a.GetDatabaseRequest(ctx, projectID, region, instanceID, dbID32).Execute()
|
||||
if err != nil {
|
||||
var oapiErr *oapierror.GenericOpenAPIError
|
||||
ok := errors.As(err, &oapiErr)
|
||||
|
|
@ -290,6 +290,7 @@ func GetDatabaseByIdWaitHandler(
|
|||
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
|
||||
}
|
||||
switch oapiErr.StatusCode {
|
||||
// TODO: work-around
|
||||
case http.StatusBadGateway, http.StatusGatewayTimeout, http.StatusServiceUnavailable:
|
||||
tflog.Warn(
|
||||
ctx, "api responded with 50[2,3,4] status", map[string]interface{}{
|
||||
|
|
|
|||
|
|
@ -89,9 +89,16 @@ func CreateInstanceWaitHandler(
|
|||
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError: %w", err)
|
||||
}
|
||||
switch oapiErr.StatusCode {
|
||||
case http.StatusOK:
|
||||
return false, nil, nil
|
||||
case http.StatusNotFound:
|
||||
return false, nil, nil
|
||||
default:
|
||||
// TODO: work-around
|
||||
if strings.Contains(err.Error(), "is not a valid InstanceEdition") {
|
||||
tflog.Info(ctx, "API WORKAROUND", map[string]interface{}{"err": err})
|
||||
return false, nil, nil
|
||||
}
|
||||
return false, nil, fmt.Errorf("api error: %w", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -257,7 +264,6 @@ func DeleteInstanceWaitHandler(
|
|||
return true, nil, nil
|
||||
},
|
||||
)
|
||||
handler.SetTimeout(30 * time.Minute)
|
||||
return handler
|
||||
}
|
||||
|
||||
|
|
@ -399,7 +405,5 @@ func DeleteUserWaitHandler(
|
|||
}
|
||||
},
|
||||
)
|
||||
handler.SetTimeout(15 * time.Minute)
|
||||
handler.SetSleepBeforeWait(15 * time.Second)
|
||||
return handler
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
sdkauth "github.com/stackitcloud/stackit-sdk-go/core/auth"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||
sqlserverFlexBetaFlavor "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/flavor"
|
||||
|
||||
sqlserverflexalphaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database"
|
||||
sqlserverflexalphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance"
|
||||
sqlserverflexalphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user"
|
||||
sqlserverflexbetaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user"
|
||||
//sqlserverflexalphaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database"
|
||||
//sqlserverflexalphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance"
|
||||
//sqlserverflexalphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user"
|
||||
|
||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
|
||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/features"
|
||||
|
|
@ -36,7 +36,7 @@ import (
|
|||
|
||||
sqlserverFlexBetaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/database"
|
||||
sqlserverflexBetaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance"
|
||||
// sqlserverFlexBetaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbetaUser/user"
|
||||
sqlserverflexbetaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces
|
||||
|
|
@ -536,14 +536,14 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource
|
|||
postgresflexalphaFlavors.NewFlavorsDataSource,
|
||||
|
||||
// sqlserverFlexAlphaFlavor.NewFlavorDataSource,
|
||||
sqlserverflexalphaInstance.NewInstanceDataSource,
|
||||
sqlserverflexalphaUser.NewUserDataSource,
|
||||
sqlserverflexalphaDatabase.NewDatabaseDataSource,
|
||||
//sqlserverflexalphaInstance.NewInstanceDataSource,
|
||||
//sqlserverflexalphaUser.NewUserDataSource,
|
||||
//sqlserverflexalphaDatabase.NewDatabaseDataSource,
|
||||
|
||||
sqlserverFlexBetaDatabase.NewDatabaseDataSource,
|
||||
sqlserverflexBetaInstance.NewInstanceDataSource,
|
||||
sqlserverflexbetaUser.NewUserDataSource,
|
||||
// sqlserverFlexBetaFlavor.NewFlavorDataSource,
|
||||
sqlserverFlexBetaFlavor.NewFlavorDataSource,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -554,9 +554,9 @@ func (p *Provider) Resources(_ context.Context) []func() resource.Resource {
|
|||
postgresFlexAlphaUser.NewUserResource,
|
||||
postgresFlexAlphaDatabase.NewDatabaseResource,
|
||||
|
||||
sqlserverflexalphaInstance.NewInstanceResource,
|
||||
sqlserverflexalphaUser.NewUserResource,
|
||||
sqlserverflexalphaDatabase.NewDatabaseResource,
|
||||
//sqlserverflexalphaInstance.NewInstanceResource,
|
||||
//sqlserverflexalphaUser.NewUserResource,
|
||||
//sqlserverflexalphaDatabase.NewDatabaseResource,
|
||||
|
||||
sqlserverflexBetaInstance.NewInstanceResource,
|
||||
sqlserverflexbetaUser.NewUserResource,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
sqlserverflexalphaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database"
|
||||
|
||||
//nolint:staticcheck // used for acceptance testing
|
||||
postgresFlexAlphaFlavor "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavor"
|
||||
|
||||
|
|
@ -23,8 +21,6 @@ import (
|
|||
postgresflexalphaFlavors "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavors"
|
||||
postgresFlexAlphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance"
|
||||
postgresFlexAlphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user"
|
||||
sqlserverFlexAlphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance"
|
||||
sqlserverFlexAlphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user"
|
||||
sqlserverflexBetaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/database"
|
||||
sqlserverFlexBetaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance"
|
||||
sqlserverFlexBetaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user"
|
||||
|
|
@ -63,9 +59,9 @@ func TestUnitProviderHasChildDataSources_Basic(t *testing.T) {
|
|||
postgresflexalphaFlavors.NewFlavorsDataSource(),
|
||||
|
||||
// sqlserverFlexAlphaFlavor.NewFlavorDataSource(),
|
||||
sqlserverFlexAlphaInstance.NewInstanceDataSource(),
|
||||
sqlserverFlexAlphaUser.NewUserDataSource(),
|
||||
sqlserverflexalphaDatabase.NewDatabaseDataSource(),
|
||||
//sqlserverFlexAlphaInstance.NewInstanceDataSource(),
|
||||
//sqlserverFlexAlphaUser.NewUserDataSource(),
|
||||
//sqlserverflexalphaDatabase.NewDatabaseDataSource(),
|
||||
|
||||
sqlserverflexBetaDatabase.NewDatabaseDataSource(),
|
||||
sqlserverFlexBetaInstance.NewInstanceDataSource(),
|
||||
|
|
@ -99,9 +95,9 @@ func TestUnitProviderHasChildResources_Basic(t *testing.T) {
|
|||
postgresFlexAlphaUser.NewUserResource(),
|
||||
postgresFlexAlphaDatabase.NewDatabaseResource(),
|
||||
|
||||
sqlserverFlexAlphaInstance.NewInstanceResource(),
|
||||
sqlserverFlexAlphaUser.NewUserResource(),
|
||||
sqlserverflexalphaDatabase.NewDatabaseResource(),
|
||||
//sqlserverFlexAlphaInstance.NewInstanceResource(),
|
||||
//sqlserverFlexAlphaUser.NewUserResource(),
|
||||
//sqlserverflexalphaDatabase.NewDatabaseResource(),
|
||||
|
||||
sqlserverFlexBetaInstance.NewInstanceResource(),
|
||||
sqlserverFlexBetaUser.NewUserResource(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue