mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-06-29 18:21:10 +00:00
feat(vm): add network device resources (#376)
* wip * experimenting with terraform plugin framework * cleaning up poc and adding tests * adding read / update / delete * update bridge_vlan_aware and MTU * add ipv6 and simplify IP support * fix provider's schema * add docs * run linter from cmdline * disable TF acceptance tests * add VLAN * update docs * add examole * cleanup
This commit is contained in:
parent
2863aa6e2d
commit
343e8045c1
6
.github/workflows/golangci-lint.yml
vendored
6
.github/workflows/golangci-lint.yml
vendored
@ -21,7 +21,5 @@ jobs:
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.52
|
||||
only-new-issues: true
|
||||
run: |
|
||||
go run -modfile=tools/go.mod github.com/golangci/golangci-lint/cmd/golangci-lint run -v --timeout 5m
|
||||
|
12
.github/workflows/test.yml
vendored
12
.github/workflows/test.yml
vendored
@ -65,11 +65,15 @@ jobs:
|
||||
- name: Get dependencies
|
||||
run: go mod download
|
||||
|
||||
- name: TF acceptance tests
|
||||
# - name: TF acceptance tests
|
||||
# timeout-minutes: 10
|
||||
# env:
|
||||
# TF_ACC: "1"
|
||||
# TF_ACC_TERRAFORM_VERSION: ${{ matrix.terraform }}
|
||||
# run: go test -v -cover ./...
|
||||
|
||||
- name: Unit tests
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
TF_ACC: "1"
|
||||
TF_ACC_TERRAFORM_VERSION: ${{ matrix.terraform }}
|
||||
run: go test -v -cover ./...
|
||||
|
||||
all-tests-passed:
|
||||
|
@ -73,6 +73,7 @@ linters:
|
||||
- funlen
|
||||
- gocognit
|
||||
# others
|
||||
- depguard
|
||||
- exhaustivestruct
|
||||
- exhaustruct
|
||||
- gci
|
||||
|
@ -35,7 +35,20 @@ We expect that all commit messages follow the
|
||||
|
||||
Please use the `scope` field to indicate the area of the codebase that is being
|
||||
changed. For example, `vm` for changes in the Virtual Machine resource, or
|
||||
`lcx` for changes in the Container resource:
|
||||
`lcx` for changes in the Container resource.
|
||||
|
||||
Common scopes are:
|
||||
|
||||
- `vm` - Virtual Machine resources
|
||||
- `lcx` - Container resources
|
||||
- `provider` - Provider configuration and resources
|
||||
- `core` - Core libraries and utilities
|
||||
- `docs` - Documentation
|
||||
- `ci` - Continuous Integration / Actions / GitHub Workflows
|
||||
|
||||
Please use lowercase for the description and do not end it with a period.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
feat(vm): add support for the `clone` operation
|
||||
@ -56,7 +69,7 @@ well.
|
||||
We use automated release management orchestrated
|
||||
by https://github.com/googleapis/release-please GitHub Action. The action
|
||||
creates a new release PR with the changelog and bumps the version based on the
|
||||
commit messages. The release PR is merged by the maintainers.
|
||||
commit messages. The release PR is merged by the maintainers.
|
||||
|
||||
The release will be published to the GitHub Releases page and the Terraform
|
||||
Registry.
|
||||
|
46
docs/resources/virtual_environment_network_linux_bridge.md
Normal file
46
docs/resources/virtual_environment_network_linux_bridge.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
layout: page
|
||||
title: proxmox_virtual_environment_network_linux_bridge
|
||||
permalink: /resources/virtual_environment_network_linux_bridge
|
||||
nav_order: 13
|
||||
parent: Resources
|
||||
subcategory: Virtual Environment
|
||||
---
|
||||
|
||||
# Resource: proxmox_virtual_environment_network_linux_bridge
|
||||
|
||||
Manages a Linux Bridge network interface in a Proxmox VE node.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "proxmox_virtual_environment_network_linux_bridge" "bridge99" {
|
||||
node_name = "pve"
|
||||
iface = "vmbr99"
|
||||
address = "3.3.3.3/24"
|
||||
comment = "created by terraform"
|
||||
mtu = 1499
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
- `node_name` - (Required) The name of the node to manage the interface on.
|
||||
- `name` - (Required) The interface name. Must be "vmbrN", where N is a number
|
||||
between 0 and 9999.
|
||||
|
||||
- `address` - (Optional) The interface IPv4/CIDR address.
|
||||
- `address6` - (Optional) The interface IPv6/CIDR address.
|
||||
- `autostart` - (Optional) Automatically start interface on boot (defaults
|
||||
to `true`).
|
||||
- `ports` - (Optional) Specify the list of the interface bridge ports.
|
||||
- `vlan_aware` - (Optional) Whether the interface bridge is VLAN aware (defaults
|
||||
to `true`).
|
||||
- `comment` - (Optional) Comment for the interface.
|
||||
- `gateway` - (Optional) Default gateway address.
|
||||
- `gateway6` - (Optional) Default IPv6 gateway address.
|
||||
- `mtu` - (Optional) The interface MTU.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) A unique identifier with format '<node name>:<iface>'
|
43
docs/resources/virtual_environment_network_linux_vlan.md
Normal file
43
docs/resources/virtual_environment_network_linux_vlan.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
layout: page
|
||||
title: proxmox_virtual_environment_network_linux_vlan
|
||||
permalink: /resources/virtual_environment_network_linux_vlan
|
||||
nav_order: 13
|
||||
parent: Resources
|
||||
subcategory: Virtual Environment
|
||||
---
|
||||
|
||||
# Resource: proxmox_virtual_environment_network_linux_vlan
|
||||
|
||||
Manages a Linux VLAN network interface in a Proxmox VE node.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "proxmox_virtual_environment_network_linux_vlan" "vlan21" {
|
||||
node_name = "pve"
|
||||
iface = "ens18.21"
|
||||
comment = "created by terraform"
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
- `node_name` - (Required) The name of the node to manage the interface on.
|
||||
- `name` - (Required) The interface name. Add the VLAN tag number to an
|
||||
existing interface name, e.g. "ens18.21".
|
||||
|
||||
- `address` - (Optional) The interface IPv4/CIDR address.
|
||||
- `address6` - (Optional) The interface IPv6/CIDR address.
|
||||
- `autostart` - (Optional) Automatically start interface on boot (defaults
|
||||
to `true`).
|
||||
- `comment` - (Optional) Comment for the interface.
|
||||
- `gateway` - (Optional) Default gateway address.
|
||||
- `gateway6` - (Optional) Default IPv6 gateway address.
|
||||
- `mtu` - (Optional) The interface MTU.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) A unique identifier with format '<node name>:<iface>'
|
||||
- `interface` (String) The VLAN raw device.
|
||||
- `vlan` (Number) The VLAN tag
|
@ -1,7 +1,7 @@
|
||||
data "proxmox_virtual_environment_vm" "example" {
|
||||
depends_on = [proxmox_virtual_environment_vm.example]
|
||||
vm_id = proxmox_virtual_environment_vm.example.vm_id
|
||||
node_name = data.proxmox_virtual_environment_nodes.example.names[0]
|
||||
vm_id = proxmox_virtual_environment_vm.example.vm_id
|
||||
node_name = data.proxmox_virtual_environment_nodes.example.names[0]
|
||||
}
|
||||
|
||||
output "proxmox_virtual_environment_vm_example" {
|
||||
|
@ -1,6 +1,6 @@
|
||||
data "proxmox_virtual_environment_vms" "example" {
|
||||
depends_on = [proxmox_virtual_environment_vm.example]
|
||||
tags = ["ubuntu"]
|
||||
tags = ["ubuntu"]
|
||||
|
||||
lifecycle {
|
||||
postcondition {
|
||||
|
@ -18,8 +18,8 @@ resource "proxmox_virtual_environment_firewall_alias" "vm_alias" {
|
||||
resource "proxmox_virtual_environment_firewall_alias" "container_alias" {
|
||||
depends_on = [proxmox_virtual_environment_container.example]
|
||||
|
||||
node_name = proxmox_virtual_environment_container.example.node_name
|
||||
container_id = proxmox_virtual_environment_container.example.vm_id
|
||||
node_name = proxmox_virtual_environment_container.example.node_name
|
||||
container_id = proxmox_virtual_environment_container.example.vm_id
|
||||
|
||||
name = "container-alias"
|
||||
cidr = "192.168.2.0/23"
|
||||
|
@ -38,8 +38,8 @@ resource "proxmox_virtual_environment_firewall_ipset" "vm_ipset" {
|
||||
resource "proxmox_virtual_environment_firewall_ipset" "container_ipset" {
|
||||
depends_on = [proxmox_virtual_environment_container.example]
|
||||
|
||||
node_name = proxmox_virtual_environment_container.example.node_name
|
||||
container_id = proxmox_virtual_environment_container.example.vm_id
|
||||
node_name = proxmox_virtual_environment_container.example.node_name
|
||||
container_id = proxmox_virtual_environment_container.example.vm_id
|
||||
|
||||
name = "container-ipset"
|
||||
comment = "Managed by Terraform"
|
||||
|
@ -34,8 +34,8 @@ resource "proxmox_virtual_environment_firewall_options" "vm_options" {
|
||||
resource "proxmox_virtual_environment_firewall_options" "container_options" {
|
||||
depends_on = [proxmox_virtual_environment_container.example]
|
||||
|
||||
node_name = proxmox_virtual_environment_container.example.node_name
|
||||
container_id = proxmox_virtual_environment_container.example.vm_id
|
||||
node_name = proxmox_virtual_environment_container.example.node_name
|
||||
container_id = proxmox_virtual_environment_container.example.vm_id
|
||||
|
||||
dhcp = false
|
||||
enabled = false
|
||||
|
@ -58,8 +58,8 @@ resource "proxmox_virtual_environment_firewall_rules" "vm_rules" {
|
||||
resource "proxmox_virtual_environment_firewall_rules" "container_rules" {
|
||||
depends_on = [proxmox_virtual_environment_container.example]
|
||||
|
||||
node_name = proxmox_virtual_environment_container.example.node_name
|
||||
container_id = proxmox_virtual_environment_container.example.vm_id
|
||||
node_name = proxmox_virtual_environment_container.example.node_name
|
||||
container_id = proxmox_virtual_environment_container.example.vm_id
|
||||
|
||||
rule {
|
||||
type = "in"
|
||||
|
23
example/resource_virtual_environment_network.tf
Normal file
23
example/resource_virtual_environment_network.tf
Normal file
@ -0,0 +1,23 @@
|
||||
resource "proxmox_virtual_environment_network_linux_vlan" "vlan99" {
|
||||
node_name = "pve"
|
||||
name = "ens18.99"
|
||||
|
||||
comment = "VLAN 99"
|
||||
}
|
||||
|
||||
resource "proxmox_virtual_environment_network_linux_bridge" "vmbr99" {
|
||||
depends_on = [
|
||||
proxmox_virtual_environment_network_linux_vlan.vlan99
|
||||
]
|
||||
|
||||
node_name = "pve"
|
||||
name = "vmbr99"
|
||||
|
||||
address = "99.99.99.99/16"
|
||||
|
||||
comment = "vmbr99 comment"
|
||||
|
||||
ports = [
|
||||
"ens18.99"
|
||||
]
|
||||
}
|
@ -9,12 +9,12 @@ resource "proxmox_virtual_environment_vm" "example_template" {
|
||||
|
||||
description = "Managed by Terraform"
|
||||
|
||||
# disk {
|
||||
# datastore_id = local.datastore_id
|
||||
# file_id = proxmox_virtual_environment_file.ubuntu_cloud_image.id
|
||||
# interface = "virtio0"
|
||||
# iothread = true
|
||||
# }
|
||||
# disk {
|
||||
# datastore_id = local.datastore_id
|
||||
# file_id = proxmox_virtual_environment_file.ubuntu_cloud_image.id
|
||||
# interface = "virtio0"
|
||||
# iothread = true
|
||||
# }
|
||||
|
||||
disk {
|
||||
datastore_id = local.datastore_id
|
||||
@ -24,12 +24,12 @@ resource "proxmox_virtual_environment_vm" "example_template" {
|
||||
ssd = true
|
||||
}
|
||||
|
||||
# disk {
|
||||
# datastore_id = "nfs"
|
||||
# interface = "scsi1"
|
||||
# discard = "ignore"
|
||||
# file_format = "raw"
|
||||
# }
|
||||
# disk {
|
||||
# datastore_id = "nfs"
|
||||
# interface = "scsi1"
|
||||
# discard = "ignore"
|
||||
# file_format = "raw"
|
||||
# }
|
||||
|
||||
initialization {
|
||||
datastore_id = local.datastore_id
|
||||
@ -47,14 +47,14 @@ resource "proxmox_virtual_environment_vm" "example_template" {
|
||||
#}
|
||||
}
|
||||
|
||||
user_data_file_id = proxmox_virtual_environment_file.user_config.id
|
||||
user_data_file_id = proxmox_virtual_environment_file.user_config.id
|
||||
vendor_data_file_id = proxmox_virtual_environment_file.vendor_config.id
|
||||
}
|
||||
|
||||
name = "terraform-provider-proxmox-example-template"
|
||||
|
||||
network_device {
|
||||
mtu = 1450
|
||||
mtu = 1450
|
||||
}
|
||||
|
||||
network_device {
|
||||
@ -81,7 +81,7 @@ resource "proxmox_virtual_environment_vm" "example" {
|
||||
node_name = data.proxmox_virtual_environment_nodes.example.names[0]
|
||||
pool_id = proxmox_virtual_environment_pool.example.id
|
||||
vm_id = 2041
|
||||
tags = ["terraform", "ubuntu"]
|
||||
tags = ["terraform", "ubuntu"]
|
||||
|
||||
clone {
|
||||
vm_id = proxmox_virtual_environment_vm.example_template.id
|
||||
@ -105,13 +105,13 @@ resource "proxmox_virtual_environment_vm" "example" {
|
||||
]
|
||||
}
|
||||
|
||||
# While overwriting the initialization block when cloning a template is possible, it is not recommended.
|
||||
# This will cause the coned VM to be reinitialized each time on re-apply.
|
||||
# initialization {
|
||||
# dns {
|
||||
# server = "8.8.8.8"
|
||||
# }
|
||||
# }
|
||||
# While overwriting the initialization block when cloning a template is possible, it is not recommended.
|
||||
# This will cause the coned VM to be reinitialized each time on re-apply.
|
||||
# initialization {
|
||||
# dns {
|
||||
# server = "8.8.8.8"
|
||||
# }
|
||||
# }
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
resource "local_sensitive_file" "example_ssh_private_key" {
|
||||
filename = "${path.module}/autogenerated/id_rsa"
|
||||
content = tls_private_key.example.private_key_pem
|
||||
filename = "${path.module}/autogenerated/id_rsa"
|
||||
content = tls_private_key.example.private_key_pem
|
||||
}
|
||||
|
||||
resource "local_sensitive_file" "example_ssh_public_key" {
|
||||
filename = "${path.module}/autogenerated/id_rsa.pub"
|
||||
content = tls_private_key.example.public_key_openssh
|
||||
filename = "${path.module}/autogenerated/id_rsa.pub"
|
||||
content = tls_private_key.example.public_key_openssh
|
||||
}
|
||||
|
||||
resource "tls_private_key" "example" {
|
||||
|
@ -9,7 +9,7 @@ terraform {
|
||||
version = "3.1.0"
|
||||
}
|
||||
proxmox = {
|
||||
source = "bpg/proxmox"
|
||||
source = "bpg/proxmox"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
31
go.mod
31
go.mod
@ -7,7 +7,11 @@ require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/terraform-plugin-framework v1.3.0
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.10.0
|
||||
github.com/hashicorp/terraform-plugin-go v0.15.0
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.0
|
||||
github.com/hashicorp/terraform-plugin-mux v0.10.0
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1
|
||||
github.com/pkg/sftp v1.13.5
|
||||
github.com/skeema/knownhosts v1.1.1
|
||||
@ -17,26 +21,31 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fatih/color v1.14.1 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.5.0 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.8 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.9 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.5.2 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.16.2 // indirect
|
||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-go v0.14.3 // indirect
|
||||
github.com/hashicorp/terraform-registry-address v0.1.0 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.18.1 // indirect
|
||||
github.com/hashicorp/terraform-json v0.16.0 // indirect
|
||||
github.com/hashicorp/terraform-registry-address v0.2.0 // indirect
|
||||
github.com/hashicorp/terraform-svchost v0.1.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/kr/pretty v0.2.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
@ -47,16 +56,16 @@ require (
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
|
||||
github.com/vmihailenco/tagparser v0.1.2 // indirect
|
||||
github.com/zclconf/go-cty v1.13.1 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/zclconf/go-cty v1.13.2 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.9.0 // indirect
|
||||
golang.org/x/text v0.10.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 // indirect
|
||||
google.golang.org/grpc v1.53.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
google.golang.org/grpc v1.54.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
105
go.sum
105
go.sum
@ -1,22 +1,30 @@
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
|
||||
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
|
||||
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
|
||||
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
|
||||
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
|
||||
github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk=
|
||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
@ -32,48 +40,65 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
|
||||
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
|
||||
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
|
||||
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM=
|
||||
github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
|
||||
github.com/hashicorp/go-plugin v1.4.9 h1:ESiK220/qE0aGxWdzKIvRH69iLiuN/PjoLTm69RoWtU=
|
||||
github.com/hashicorp/go-plugin v1.4.9/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hc-install v0.5.2 h1:SfwMFnEXVVirpwkDuSF5kymUOhrUxrTq3udEseZdOD0=
|
||||
github.com/hashicorp/hc-install v0.5.2/go.mod h1:9QISwe6newMWIfEiXpzuu1k9HAGtQYgnSH8H9T8wmoI=
|
||||
github.com/hashicorp/hcl/v2 v2.16.2 h1:mpkHZh/Tv+xet3sy3F9Ld4FyI2tUpWe9x3XtPx9f1a0=
|
||||
github.com/hashicorp/hcl/v2 v2.16.2/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng=
|
||||
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/terraform-plugin-go v0.14.3 h1:nlnJ1GXKdMwsC8g1Nh05tK2wsC3+3BL/DBBxFEki+j0=
|
||||
github.com/hashicorp/terraform-plugin-go v0.14.3/go.mod h1:7ees7DMZ263q8wQ6E4RdIdR6nHHJtrdt4ogX5lPkX1A=
|
||||
github.com/hashicorp/terraform-exec v0.18.1 h1:LAbfDvNQU1l0NOQlTuudjczVhHj061fNX5H8XZxHlH4=
|
||||
github.com/hashicorp/terraform-exec v0.18.1/go.mod h1:58wg4IeuAJ6LVsLUeD2DWZZoc/bYi6dzhLHzxM41980=
|
||||
github.com/hashicorp/terraform-json v0.16.0 h1:UKkeWRWb23do5LNAFlh/K3N0ymn1qTOO8c+85Albo3s=
|
||||
github.com/hashicorp/terraform-json v0.16.0/go.mod h1:v0Ufk9jJnk6tcIZvScHvetlKfiNTC+WS21mnXIlc0B0=
|
||||
github.com/hashicorp/terraform-plugin-framework v1.3.0 h1:WtP1CIaWAfbzME17xoUXvJcyh5Ewu9attdhbfWNnYLs=
|
||||
github.com/hashicorp/terraform-plugin-framework v1.3.0/go.mod h1:A1WD3Ry7FhrThViUTbkx4ZDsMq9oaAv4U9oTI8bBzCU=
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.10.0 h1:4L0tmy/8esP6OcvocVymw52lY0HyQ5OxB7VNl7k4bS0=
|
||||
github.com/hashicorp/terraform-plugin-framework-validators v0.10.0/go.mod h1:qdQJCdimB9JeX2YwOpItEu+IrfoJjWQ5PhLpAOMDQAE=
|
||||
github.com/hashicorp/terraform-plugin-go v0.15.0 h1:1BJNSUFs09DS8h/XNyJNJaeusQuWc/T9V99ylU9Zwp0=
|
||||
github.com/hashicorp/terraform-plugin-go v0.15.0/go.mod h1:tk9E3/Zx4RlF/9FdGAhwxHExqIHHldqiQGt20G6g+nQ=
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
|
||||
github.com/hashicorp/terraform-plugin-mux v0.10.0 h1:VejY1BffxGy2iYOaa8DDHavY4k9jbvAE8F3lhruspKY=
|
||||
github.com/hashicorp/terraform-plugin-mux v0.10.0/go.mod h1:9sdnpmY20xIsl4ItsfODZYE+MgpSy/osXpSf+RwaZCY=
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1 h1:G9WAfb8LHeCxu7Ae8nc1agZlQOSCUWsb610iAogBhCs=
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1/go.mod h1:xcOSYlRVdPLmDUoqPhO9fiO/YCN/l6MGYeTzGt5jgkQ=
|
||||
github.com/hashicorp/terraform-registry-address v0.1.0 h1:W6JkV9wbum+m516rCl5/NjKxCyTVaaUBbzYcMzBDO3U=
|
||||
github.com/hashicorp/terraform-registry-address v0.1.0/go.mod h1:EnyO2jYO6j29DTHbJcm00E5nQTFeTtyZH3H5ycydQ5A=
|
||||
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg=
|
||||
github.com/hashicorp/terraform-registry-address v0.2.0 h1:92LUg03NhfgZv44zpNTLBGIbiyTokQCDcdH5BhVHT3s=
|
||||
github.com/hashicorp/terraform-registry-address v0.2.0/go.mod h1:478wuzJPzdmqT6OGbB/iH82EDcI8VFM4yujknh/1nIs=
|
||||
github.com/hashicorp/terraform-svchost v0.1.0 h1:0+RcgZdZYNd81Vw7tu62g9JiLLvbOigp7QtyNh6CjXk=
|
||||
github.com/hashicorp/terraform-svchost v0.1.0/go.mod h1:ut8JaH0vumgdCfJaihdcZULqkAwHdQNwNH7taIDdsZM=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
@ -96,13 +121,18 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go=
|
||||
github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/skeema/knownhosts v1.1.1 h1:MTk78x9FPgDFVFkDLTrsnnfCJl7g1C/nnKvePgrIngE=
|
||||
github.com/skeema/knownhosts v1.1.1/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
@ -110,34 +140,29 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
|
||||
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
|
||||
github.com/zclconf/go-cty v1.13.1 h1:0a6bRwuiSHtAmqCqNOE+c2oHgepv0ctoxU4FUe43kwc=
|
||||
github.com/zclconf/go-cty v1.13.1/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0=
|
||||
github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo=
|
||||
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -146,6 +171,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -162,22 +188,21 @@ golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 h1:EfLuoKW5WfkgVdDy7dTK8qSbH37AX5mj/MFh+bGPz14=
|
||||
google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA=
|
||||
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
|
||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
|
||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
8
internal/internal.go
Normal file
8
internal/internal.go
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// Package internal contains implementation of the provider created with Terraform Plugin Framework.
|
||||
package internal
|
488
internal/network/resource_linux_bridge.go
Normal file
488
internal/network/resource_linux_bridge.go
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
|
||||
pvetypes "github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes"
|
||||
)
|
||||
|
||||
var (
|
||||
_ resource.Resource = &linuxBridgeResource{}
|
||||
_ resource.ResourceWithConfigure = &linuxBridgeResource{}
|
||||
_ resource.ResourceWithImportState = &linuxBridgeResource{}
|
||||
)
|
||||
|
||||
type linuxBridgeResourceModel struct {
|
||||
// Base attributes
|
||||
ID types.String `tfsdk:"id"`
|
||||
NodeName types.String `tfsdk:"node_name"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Address pvetypes.IPCIDRValue `tfsdk:"address"`
|
||||
Gateway pvetypes.IPAddrValue `tfsdk:"gateway"`
|
||||
Address6 pvetypes.IPCIDRValue `tfsdk:"address6"`
|
||||
Gateway6 pvetypes.IPAddrValue `tfsdk:"gateway6"`
|
||||
Autostart types.Bool `tfsdk:"autostart"`
|
||||
MTU types.Int64 `tfsdk:"mtu"`
|
||||
Comment types.String `tfsdk:"comment"`
|
||||
// Linux bridge attributes
|
||||
Ports []types.String `tfsdk:"ports"`
|
||||
VLANAware types.Bool `tfsdk:"vlan_aware"`
|
||||
}
|
||||
|
||||
//nolint:lll
|
||||
func (m *linuxBridgeResourceModel) exportToNetworkInterfaceCreateUpdateBody() *nodes.NetworkInterfaceCreateUpdateRequestBody {
|
||||
body := &nodes.NetworkInterfaceCreateUpdateRequestBody{
|
||||
Iface: m.Name.ValueString(),
|
||||
Type: "bridge",
|
||||
Autostart: pvetypes.CustomBool(m.Autostart.ValueBool()).Pointer(),
|
||||
}
|
||||
|
||||
body.CIDR = m.Address.ValueStringPointer()
|
||||
body.Gateway = m.Gateway.ValueStringPointer()
|
||||
body.CIDR6 = m.Address6.ValueStringPointer()
|
||||
body.Gateway6 = m.Gateway6.ValueStringPointer()
|
||||
|
||||
if !m.MTU.IsUnknown() {
|
||||
body.MTU = m.MTU.ValueInt64Pointer()
|
||||
}
|
||||
|
||||
body.Comments = m.Comment.ValueStringPointer()
|
||||
|
||||
var sanitizedPorts []string
|
||||
|
||||
for i := 0; i < len(m.Ports); i++ {
|
||||
port := strings.TrimSpace(m.Ports[i].ValueString())
|
||||
if len(port) > 0 {
|
||||
sanitizedPorts = append(sanitizedPorts, port)
|
||||
}
|
||||
}
|
||||
sort.Strings(sanitizedPorts)
|
||||
bridgePorts := strings.Join(sanitizedPorts, " ")
|
||||
|
||||
if len(bridgePorts) > 0 {
|
||||
body.BridgePorts = &bridgePorts
|
||||
}
|
||||
|
||||
body.BridgeVLANAware = pvetypes.CustomBool(m.VLANAware.ValueBool()).Pointer()
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
func (m *linuxBridgeResourceModel) importFromNetworkInterfaceList(
|
||||
ctx context.Context,
|
||||
iface *nodes.NetworkInterfaceListResponseData,
|
||||
) error {
|
||||
m.Address = pvetypes.NewIPCIDRPointerValue(iface.CIDR)
|
||||
m.Gateway = pvetypes.NewIPAddrPointerValue(iface.Gateway)
|
||||
m.Address6 = pvetypes.NewIPCIDRPointerValue(iface.CIDR6)
|
||||
m.Gateway6 = pvetypes.NewIPAddrPointerValue(iface.Gateway6)
|
||||
m.Autostart = types.BoolPointerValue(iface.Autostart.PointerBool())
|
||||
|
||||
if iface.MTU != nil {
|
||||
if v, err := strconv.Atoi(*iface.MTU); err == nil {
|
||||
m.MTU = types.Int64Value(int64(v))
|
||||
}
|
||||
} else {
|
||||
m.MTU = types.Int64Null()
|
||||
}
|
||||
|
||||
if iface.Comments != nil {
|
||||
m.Comment = types.StringValue(strings.TrimSpace(*iface.Comments))
|
||||
} else {
|
||||
m.Comment = types.StringNull()
|
||||
}
|
||||
|
||||
if iface.BridgeVLANAware != nil {
|
||||
m.VLANAware = types.BoolPointerValue(iface.BridgeVLANAware.PointerBool())
|
||||
} else {
|
||||
m.VLANAware = types.BoolValue(false)
|
||||
}
|
||||
|
||||
if iface.BridgePorts != nil && len(*iface.BridgePorts) > 0 {
|
||||
ports, diags := types.ListValueFrom(ctx, types.StringType, strings.Split(*iface.BridgePorts, " "))
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("failed to parse bridge ports: %s", *iface.BridgePorts)
|
||||
}
|
||||
|
||||
diags = ports.ElementsAs(ctx, &m.Ports, false)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("failed to build bridge ports list: %s", *iface.BridgePorts)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewLinuxBridgeResource creates a new resource for managing Linux Bridge network interfaces.
|
||||
func NewLinuxBridgeResource() resource.Resource {
|
||||
return &linuxBridgeResource{}
|
||||
}
|
||||
|
||||
type linuxBridgeResource struct {
|
||||
client proxmox.Client
|
||||
}
|
||||
|
||||
func (r *linuxBridgeResource) Metadata(
|
||||
_ context.Context,
|
||||
req resource.MetadataRequest,
|
||||
resp *resource.MetadataResponse,
|
||||
) {
|
||||
resp.TypeName = req.ProviderTypeName + "_network_linux_bridge"
|
||||
}
|
||||
|
||||
// Schema defines the schema for the resource.
|
||||
func (r *linuxBridgeResource) Schema(
|
||||
_ context.Context,
|
||||
_ resource.SchemaRequest,
|
||||
resp *resource.SchemaResponse,
|
||||
) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Manages a Linux Bridge network interface in a Proxmox VE node.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
// Base attributes
|
||||
"id": schema.StringAttribute{
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
Description: "A unique identifier with format '<node name>:<iface>'",
|
||||
},
|
||||
"node_name": schema.StringAttribute{
|
||||
Description: "The name of the node.",
|
||||
Required: true,
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: "The interface name.",
|
||||
Required: true,
|
||||
Validators: []validator.String{
|
||||
stringvalidator.RegexMatches(
|
||||
regexp.MustCompile(`^vmbr(\d{1,4})$`),
|
||||
`must be "vmbrN", where N is a number between 0 and 9999`,
|
||||
),
|
||||
},
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"address": schema.StringAttribute{
|
||||
Description: "The interface IPv4/CIDR address.",
|
||||
CustomType: pvetypes.IPCIDRType{},
|
||||
Optional: true,
|
||||
},
|
||||
"gateway": schema.StringAttribute{
|
||||
Description: "Default gateway address.",
|
||||
CustomType: pvetypes.IPAddrType{},
|
||||
Optional: true,
|
||||
},
|
||||
"address6": schema.StringAttribute{
|
||||
Description: "The interface IPv6/CIDR address.",
|
||||
CustomType: pvetypes.IPCIDRType{},
|
||||
Optional: true,
|
||||
},
|
||||
"gateway6": schema.StringAttribute{
|
||||
Description: "Default IPv6 gateway address.",
|
||||
CustomType: pvetypes.IPAddrType{},
|
||||
Optional: true,
|
||||
},
|
||||
"autostart": schema.BoolAttribute{
|
||||
Description: "Automatically start interface on boot.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: booldefault.StaticBool(true),
|
||||
},
|
||||
"mtu": schema.Int64Attribute{
|
||||
Description: "The interface MTU.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"comment": schema.StringAttribute{
|
||||
Description: "Comment for the interface.",
|
||||
Optional: true,
|
||||
},
|
||||
// Linux Bridge attributes
|
||||
"ports": schema.ListAttribute{
|
||||
Description: "The interface bridge ports.",
|
||||
Optional: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"vlan_aware": schema.BoolAttribute{
|
||||
Description: "Whether the interface bridge is VLAN aware.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *linuxBridgeResource) Configure(
|
||||
_ context.Context,
|
||||
req resource.ConfigureRequest,
|
||||
resp *resource.ConfigureResponse,
|
||||
) {
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
|
||||
client, ok := req.ProviderData.(proxmox.Client)
|
||||
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Resource Configure Type",
|
||||
fmt.Sprintf("Expected *proxmox.Client, got: %T. Please report this issue to the provider developers.",
|
||||
req.ProviderData),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
r.client = client
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func (r *linuxBridgeResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var plan linuxBridgeResourceModel
|
||||
diags := req.Plan.Get(ctx, &plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
body := plan.exportToNetworkInterfaceCreateUpdateBody()
|
||||
|
||||
err := r.client.Node(plan.NodeName.ValueString()).CreateNetworkInterface(ctx, body)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error creating Linux Bridge interface",
|
||||
"Could not create Linux Bridge, unexpected error: "+err.Error(),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
plan.ID = types.StringValue(plan.NodeName.ValueString() + ":" + plan.Name.ValueString())
|
||||
|
||||
r.read(ctx, &plan, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.State.Set(ctx, plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
err = r.client.Node(plan.NodeName.ValueString()).ReloadNetworkConfiguration(ctx)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reloading network configuration",
|
||||
fmt.Sprintf("Could not reload network configuration on node '%s', unexpected error: %s",
|
||||
plan.NodeName.ValueString(), err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *linuxBridgeResource) read(ctx context.Context, model *linuxBridgeResourceModel, diags *diag.Diagnostics) {
|
||||
ifaces, err := r.client.Node(model.NodeName.ValueString()).ListNetworkInterfaces(ctx)
|
||||
if err != nil {
|
||||
diags.AddError(
|
||||
"Error listing network interfaces",
|
||||
"Could not list network interfaces, unexpected error: "+err.Error(),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, iface := range ifaces {
|
||||
if iface.Iface != model.Name.ValueString() {
|
||||
continue
|
||||
}
|
||||
|
||||
err = model.importFromNetworkInterfaceList(ctx, iface)
|
||||
if err != nil {
|
||||
diags.AddError(
|
||||
"Error converting network interface to a model",
|
||||
"Could not import network interface from API response, unexpected error: "+err.Error(),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Read reads a Linux Bridge interface.
|
||||
func (r *linuxBridgeResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
// Get current state
|
||||
var state linuxBridgeResourceModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
r.read(ctx, &state, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
diags = resp.State.Set(ctx, state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
||||
|
||||
// Update updates a Linux Bridge interface.
|
||||
func (r *linuxBridgeResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var plan, state linuxBridgeResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
body := plan.exportToNetworkInterfaceCreateUpdateBody()
|
||||
|
||||
var toDelete []string
|
||||
|
||||
if !plan.MTU.Equal(state.MTU) && (plan.MTU.IsUnknown() || plan.MTU.ValueInt64() == 0) {
|
||||
toDelete = append(toDelete, "mtu")
|
||||
body.MTU = nil
|
||||
}
|
||||
|
||||
// VLANAware is computed, will never be null
|
||||
if !plan.VLANAware.Equal(state.VLANAware) && !plan.VLANAware.ValueBool() {
|
||||
toDelete = append(toDelete, "bridge_vlan_aware")
|
||||
body.BridgeVLANAware = nil
|
||||
}
|
||||
|
||||
if len(toDelete) > 0 {
|
||||
body.Delete = &toDelete
|
||||
}
|
||||
|
||||
err := r.client.Node(plan.NodeName.ValueString()).UpdateNetworkInterface(ctx, plan.Name.ValueString(), body)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error updating Linux Bridge interface",
|
||||
"Could not update Linux Bridge, unexpected error: "+err.Error(),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
r.read(ctx, &plan, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
|
||||
|
||||
err = r.client.Node(state.NodeName.ValueString()).ReloadNetworkConfiguration(ctx)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reloading network configuration",
|
||||
fmt.Sprintf("Could not reload network configuration on node '%s', unexpected error: %s",
|
||||
state.NodeName.ValueString(), err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete deletes a Linux Bridge interface.
|
||||
//
|
||||
//nolint:dupl
|
||||
func (r *linuxBridgeResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
var state linuxBridgeResourceModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
err := r.client.Node(state.NodeName.ValueString()).DeleteNetworkInterface(ctx, state.Name.ValueString())
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "interface does not exist") {
|
||||
resp.Diagnostics.AddWarning(
|
||||
"Linux Bridge interface does not exist",
|
||||
fmt.Sprintf("Could not delete Linux Bridge '%s', interface does not exist, "+
|
||||
"or has already been deleted outside of Terraform.", state.Name.ValueString()),
|
||||
)
|
||||
} else {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error deleting Linux Bridge interface",
|
||||
fmt.Sprintf("Could not delete Linux Bridge '%s', unexpected error: %s",
|
||||
state.Name.ValueString(), err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = r.client.Node(state.NodeName.ValueString()).ReloadNetworkConfiguration(ctx)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reloading network configuration",
|
||||
fmt.Sprintf("Could not reload network configuration on node '%s', unexpected error: %s",
|
||||
state.NodeName.ValueString(), err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *linuxBridgeResource) ImportState(
|
||||
ctx context.Context,
|
||||
req resource.ImportStateRequest,
|
||||
resp *resource.ImportStateResponse,
|
||||
) {
|
||||
idParts := strings.Split(req.ID, ":")
|
||||
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Import Identifier",
|
||||
fmt.Sprintf("Expected import identifier with format: node_name:iface. Got: %q", req.ID),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nodeName := idParts[0]
|
||||
iface := idParts[1]
|
||||
|
||||
state := linuxBridgeResourceModel{
|
||||
ID: types.StringValue(req.ID),
|
||||
NodeName: types.StringValue(nodeName),
|
||||
Name: types.StringValue(iface),
|
||||
}
|
||||
r.read(ctx, &state, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
diags := resp.State.Set(ctx, state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
451
internal/network/resource_linux_vlan.go
Normal file
451
internal/network/resource_linux_vlan.go
Normal file
@ -0,0 +1,451 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
|
||||
pvetypes "github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes"
|
||||
)
|
||||
|
||||
var (
|
||||
_ resource.Resource = &linuxVLANResource{}
|
||||
_ resource.ResourceWithConfigure = &linuxVLANResource{}
|
||||
_ resource.ResourceWithImportState = &linuxVLANResource{}
|
||||
)
|
||||
|
||||
type linuxVLANResourceModel struct {
|
||||
// Base attributes
|
||||
ID types.String `tfsdk:"id"`
|
||||
NodeName types.String `tfsdk:"node_name"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Address pvetypes.IPCIDRValue `tfsdk:"address"`
|
||||
Gateway pvetypes.IPAddrValue `tfsdk:"gateway"`
|
||||
Address6 pvetypes.IPCIDRValue `tfsdk:"address6"`
|
||||
Gateway6 pvetypes.IPAddrValue `tfsdk:"gateway6"`
|
||||
Autostart types.Bool `tfsdk:"autostart"`
|
||||
MTU types.Int64 `tfsdk:"mtu"`
|
||||
Comment types.String `tfsdk:"comment"`
|
||||
// Linux VLAN attributes
|
||||
Interface types.String `tfsdk:"interface"`
|
||||
VLAN types.Int64 `tfsdk:"vlan"`
|
||||
}
|
||||
|
||||
//nolint:lll
|
||||
func (m *linuxVLANResourceModel) exportToNetworkInterfaceCreateUpdateBody() *nodes.NetworkInterfaceCreateUpdateRequestBody {
|
||||
body := &nodes.NetworkInterfaceCreateUpdateRequestBody{
|
||||
Iface: m.Name.ValueString(),
|
||||
Type: "vlan",
|
||||
Autostart: pvetypes.CustomBool(m.Autostart.ValueBool()).Pointer(),
|
||||
}
|
||||
|
||||
body.CIDR = m.Address.ValueStringPointer()
|
||||
body.Gateway = m.Gateway.ValueStringPointer()
|
||||
body.CIDR6 = m.Address6.ValueStringPointer()
|
||||
body.Gateway6 = m.Gateway6.ValueStringPointer()
|
||||
body.Comments = m.Comment.ValueStringPointer()
|
||||
|
||||
if !m.MTU.IsUnknown() {
|
||||
body.MTU = m.MTU.ValueInt64Pointer()
|
||||
}
|
||||
|
||||
if !m.Interface.IsUnknown() {
|
||||
body.VLANRawDevice = m.Interface.ValueStringPointer()
|
||||
}
|
||||
|
||||
if !m.VLAN.IsUnknown() {
|
||||
body.VLANID = m.VLAN.ValueInt64Pointer()
|
||||
}
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
func (m *linuxVLANResourceModel) importFromNetworkInterfaceList(iface *nodes.NetworkInterfaceListResponseData) {
|
||||
m.Address = pvetypes.NewIPCIDRPointerValue(iface.CIDR)
|
||||
m.Gateway = pvetypes.NewIPAddrPointerValue(iface.Gateway)
|
||||
m.Address6 = pvetypes.NewIPCIDRPointerValue(iface.CIDR6)
|
||||
m.Gateway6 = pvetypes.NewIPAddrPointerValue(iface.Gateway6)
|
||||
m.Autostart = types.BoolPointerValue(iface.Autostart.PointerBool())
|
||||
|
||||
if iface.MTU != nil {
|
||||
if v, err := strconv.Atoi(*iface.MTU); err == nil {
|
||||
m.MTU = types.Int64Value(int64(v))
|
||||
}
|
||||
} else {
|
||||
m.MTU = types.Int64Null()
|
||||
}
|
||||
|
||||
if iface.Comments != nil {
|
||||
m.Comment = types.StringValue(strings.TrimSpace(*iface.Comments))
|
||||
} else {
|
||||
m.Comment = types.StringNull()
|
||||
}
|
||||
|
||||
if iface.VLANID != nil {
|
||||
if v, err := strconv.Atoi(*iface.VLANID); err == nil {
|
||||
m.VLAN = types.Int64Value(int64(v))
|
||||
}
|
||||
} else {
|
||||
// in reality, this should never happen
|
||||
m.VLAN = types.Int64Unknown()
|
||||
}
|
||||
|
||||
if iface.VLANRawDevice != nil {
|
||||
m.Interface = types.StringValue(strings.TrimSpace(*iface.VLANRawDevice))
|
||||
} else {
|
||||
m.Interface = types.StringNull()
|
||||
}
|
||||
}
|
||||
|
||||
// NewLinuxVLANResource creates a new resource for managing Linux VLAN network interfaces.
|
||||
func NewLinuxVLANResource() resource.Resource {
|
||||
return &linuxVLANResource{}
|
||||
}
|
||||
|
||||
type linuxVLANResource struct {
|
||||
client proxmox.Client
|
||||
}
|
||||
|
||||
func (r *linuxVLANResource) Metadata(
|
||||
_ context.Context,
|
||||
req resource.MetadataRequest,
|
||||
resp *resource.MetadataResponse,
|
||||
) {
|
||||
resp.TypeName = req.ProviderTypeName + "_network_linux_vlan"
|
||||
}
|
||||
|
||||
// Schema defines the schema for the resource.
|
||||
func (r *linuxVLANResource) Schema(
|
||||
_ context.Context,
|
||||
_ resource.SchemaRequest,
|
||||
resp *resource.SchemaResponse,
|
||||
) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Manages a Linux VLAN network interface in a Proxmox VE node.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
// Base attributes
|
||||
"id": schema.StringAttribute{
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
Description: "A unique identifier with format '<node name>:<iface>'",
|
||||
},
|
||||
"node_name": schema.StringAttribute{
|
||||
Description: "The name of the node.",
|
||||
Required: true,
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: "The interface name.",
|
||||
Required: true,
|
||||
Validators: []validator.String{
|
||||
stringvalidator.LengthAtLeast(3),
|
||||
},
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"address": schema.StringAttribute{
|
||||
Description: "The interface IPv4/CIDR address.",
|
||||
CustomType: pvetypes.IPCIDRType{},
|
||||
Optional: true,
|
||||
},
|
||||
"gateway": schema.StringAttribute{
|
||||
Description: "Default gateway address.",
|
||||
CustomType: pvetypes.IPAddrType{},
|
||||
Optional: true,
|
||||
},
|
||||
"address6": schema.StringAttribute{
|
||||
Description: "The interface IPv6/CIDR address.",
|
||||
CustomType: pvetypes.IPCIDRType{},
|
||||
Optional: true,
|
||||
},
|
||||
"gateway6": schema.StringAttribute{
|
||||
Description: "Default IPv6 gateway address.",
|
||||
CustomType: pvetypes.IPAddrType{},
|
||||
Optional: true,
|
||||
},
|
||||
"autostart": schema.BoolAttribute{
|
||||
Description: "Automatically start interface on boot.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: booldefault.StaticBool(true),
|
||||
},
|
||||
"mtu": schema.Int64Attribute{
|
||||
Description: "The interface MTU.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"comment": schema.StringAttribute{
|
||||
Description: "Comment for the interface.",
|
||||
Optional: true,
|
||||
},
|
||||
// Linux VLAN attributes
|
||||
"interface": schema.StringAttribute{
|
||||
// read-only
|
||||
Description: "The VLAN raw device.",
|
||||
Computed: true,
|
||||
},
|
||||
"vlan": schema.Int64Attribute{
|
||||
// read-only
|
||||
Description: "The VLAN tag",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *linuxVLANResource) Configure(
|
||||
_ context.Context,
|
||||
req resource.ConfigureRequest,
|
||||
resp *resource.ConfigureResponse,
|
||||
) {
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
|
||||
client, ok := req.ProviderData.(proxmox.Client)
|
||||
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Resource Configure Type",
|
||||
fmt.Sprintf("Expected *proxmox.Client, got: %T. Please report this issue to the provider developers.",
|
||||
req.ProviderData),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
r.client = client
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func (r *linuxVLANResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var plan linuxVLANResourceModel
|
||||
diags := req.Plan.Get(ctx, &plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
body := plan.exportToNetworkInterfaceCreateUpdateBody()
|
||||
|
||||
err := r.client.Node(plan.NodeName.ValueString()).CreateNetworkInterface(ctx, body)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error creating Linux VLAN interface",
|
||||
"Could not create Linux VLAN, unexpected error: "+err.Error(),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
plan.ID = types.StringValue(plan.NodeName.ValueString() + ":" + plan.Name.ValueString())
|
||||
|
||||
r.read(ctx, &plan, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.State.Set(ctx, plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
err = r.client.Node(plan.NodeName.ValueString()).ReloadNetworkConfiguration(ctx)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reloading network configuration",
|
||||
fmt.Sprintf("Could not reload network configuration on node '%s', unexpected error: %s",
|
||||
plan.NodeName.ValueString(), err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *linuxVLANResource) read(ctx context.Context, model *linuxVLANResourceModel, diags *diag.Diagnostics) {
|
||||
ifaces, err := r.client.Node(model.NodeName.ValueString()).ListNetworkInterfaces(ctx)
|
||||
if err != nil {
|
||||
diags.AddError(
|
||||
"Error listing network interfaces",
|
||||
"Could not list network interfaces, unexpected error: "+err.Error(),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, iface := range ifaces {
|
||||
if iface.Iface != model.Name.ValueString() {
|
||||
continue
|
||||
}
|
||||
|
||||
model.importFromNetworkInterfaceList(iface)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Read reads a Linux VLAN interface.
|
||||
func (r *linuxVLANResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
// Get current state
|
||||
var state linuxVLANResourceModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
r.read(ctx, &state, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
diags = resp.State.Set(ctx, state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
||||
|
||||
// Update updates a Linux VLAN interface.
|
||||
func (r *linuxVLANResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var plan, state linuxVLANResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
body := plan.exportToNetworkInterfaceCreateUpdateBody()
|
||||
|
||||
var toDelete []string
|
||||
|
||||
if !plan.MTU.Equal(state.MTU) && (plan.MTU.IsUnknown() || plan.MTU.ValueInt64() == 0) {
|
||||
toDelete = append(toDelete, "mtu")
|
||||
body.MTU = nil
|
||||
}
|
||||
|
||||
if len(toDelete) > 0 {
|
||||
body.Delete = &toDelete
|
||||
}
|
||||
|
||||
err := r.client.Node(plan.NodeName.ValueString()).UpdateNetworkInterface(ctx, plan.Name.ValueString(), body)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error updating Linux VLAN interface",
|
||||
"Could not update Linux VLAN, unexpected error: "+err.Error(),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
r.read(ctx, &plan, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
|
||||
|
||||
err = r.client.Node(state.NodeName.ValueString()).ReloadNetworkConfiguration(ctx)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reloading network configuration",
|
||||
fmt.Sprintf("Could not reload network configuration on node '%s', unexpected error: %s",
|
||||
state.NodeName.ValueString(), err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete deletes a Linux VLAN interface.
|
||||
//
|
||||
//nolint:dupl
|
||||
func (r *linuxVLANResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
var state linuxVLANResourceModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
err := r.client.Node(state.NodeName.ValueString()).DeleteNetworkInterface(ctx, state.Name.ValueString())
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "interface does not exist") {
|
||||
resp.Diagnostics.AddWarning(
|
||||
"Linux VLAN interface does not exist",
|
||||
fmt.Sprintf("Could not delete Linux VLAN '%s', interface does not exist, "+
|
||||
"or has already been deleted outside of Terraform.", state.Name.ValueString()),
|
||||
)
|
||||
} else {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error deleting Linux VLAN interface",
|
||||
fmt.Sprintf("Could not delete Linux VLAN '%s', unexpected error: %s",
|
||||
state.Name.ValueString(), err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = r.client.Node(state.NodeName.ValueString()).ReloadNetworkConfiguration(ctx)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Error reloading network configuration",
|
||||
fmt.Sprintf("Could not reload network configuration on node '%s', unexpected error: %s",
|
||||
state.NodeName.ValueString(), err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *linuxVLANResource) ImportState(
|
||||
ctx context.Context,
|
||||
req resource.ImportStateRequest,
|
||||
resp *resource.ImportStateResponse,
|
||||
) {
|
||||
idParts := strings.Split(req.ID, ":")
|
||||
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Import Identifier",
|
||||
fmt.Sprintf("Expected import identifier with format: node_name:iface. Got: %q", req.ID),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nodeName := idParts[0]
|
||||
iface := idParts[1]
|
||||
|
||||
state := linuxVLANResourceModel{
|
||||
ID: types.StringValue(req.ID),
|
||||
NodeName: types.StringValue(nodeName),
|
||||
Name: types.StringValue(iface),
|
||||
}
|
||||
r.read(ctx, &state, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
diags := resp.State.Set(ctx, state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
401
internal/provider/provider.go
Normal file
401
internal/provider/provider.go
Normal file
@ -0,0 +1,401 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/provider"
|
||||
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/network"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/ssh"
|
||||
"github.com/bpg/terraform-provider-proxmox/utils"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var _ provider.Provider = &proxmoxProvider{}
|
||||
|
||||
// New is a helper function to simplify provider server and testing implementation.
|
||||
func New(version string) func() provider.Provider {
|
||||
return func() provider.Provider {
|
||||
return &proxmoxProvider{
|
||||
version: version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type proxmoxProvider struct {
|
||||
// version is set to the provider version on release, "dev" when the
|
||||
// provider is built and ran locally, and "test" when running acceptance
|
||||
// testing.
|
||||
version string
|
||||
}
|
||||
|
||||
// proxmoxProviderModel maps provider schema data.
|
||||
type proxmoxProviderModel struct {
|
||||
APIToken types.String `tfsdk:"api_token"`
|
||||
Endpoint types.String `tfsdk:"endpoint"`
|
||||
Insecure types.Bool `tfsdk:"insecure"`
|
||||
OTP types.String `tfsdk:"otp"`
|
||||
Username types.String `tfsdk:"username"`
|
||||
Password types.String `tfsdk:"password"`
|
||||
SSH []struct {
|
||||
Agent types.Bool `tfsdk:"agent"`
|
||||
AgentSocket types.String `tfsdk:"agent_socket"`
|
||||
Password types.String `tfsdk:"password"`
|
||||
Username types.String `tfsdk:"username"`
|
||||
|
||||
Nodes []struct {
|
||||
Name types.String `tfsdk:"name"`
|
||||
Address types.String `tfsdk:"address"`
|
||||
} `tfsdk:"node"`
|
||||
} `tfsdk:"ssh"`
|
||||
}
|
||||
|
||||
func (p *proxmoxProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
|
||||
// resp.TypeName = "proxmox"
|
||||
resp.TypeName = "proxmox_virtual_environment"
|
||||
resp.Version = p.version
|
||||
}
|
||||
|
||||
func (p *proxmoxProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
// Attributes specified in alphabetical order.
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"api_token": schema.StringAttribute{
|
||||
Description: "The API token for the Proxmox VE API.",
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
Validators: []validator.String{
|
||||
stringvalidator.RegexMatches(
|
||||
regexp.MustCompile(`^\S+@\w+!\S+=([a-zA-Z0-9-]+)$`),
|
||||
`must be a valid API token, e.g. 'USER@REALM!TOKENID=UUID'`,
|
||||
),
|
||||
},
|
||||
},
|
||||
"endpoint": schema.StringAttribute{
|
||||
Description: "The endpoint for the Proxmox VE API.",
|
||||
Optional: true,
|
||||
Validators: []validator.String{
|
||||
stringvalidator.LengthAtLeast(1),
|
||||
},
|
||||
},
|
||||
"insecure": schema.BoolAttribute{
|
||||
Description: "Whether to skip the TLS verification step.",
|
||||
Optional: true,
|
||||
},
|
||||
"otp": schema.StringAttribute{
|
||||
Description: "The one-time password for the Proxmox VE API.",
|
||||
Optional: true,
|
||||
DeprecationMessage: "The `otp` attribute is deprecated and will be removed in a future release. " +
|
||||
"Please use the `api_token` attribute instead.",
|
||||
},
|
||||
"password": schema.StringAttribute{
|
||||
Description: "The password for the Proxmox VE API.",
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"username": schema.StringAttribute{
|
||||
Description: "The username for the Proxmox VE API.",
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
Blocks: map[string]schema.Block{
|
||||
// have to define it as a list due to backwards compatibility
|
||||
"ssh": schema.ListNestedBlock{
|
||||
Description: "The SSH configuration for the Proxmox nodes.",
|
||||
Validators: []validator.List{
|
||||
listvalidator.SizeAtMost(1),
|
||||
},
|
||||
NestedObject: schema.NestedBlockObject{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"agent": schema.BoolAttribute{
|
||||
Description: "Whether to use the SSH agent for authentication. " +
|
||||
"Defaults to `false`.",
|
||||
Optional: true,
|
||||
},
|
||||
"agent_socket": schema.StringAttribute{
|
||||
Description: "The path to the SSH agent socket. " +
|
||||
"Defaults to the value of the `SSH_AUTH_SOCK` " +
|
||||
"environment variable.",
|
||||
Optional: true,
|
||||
},
|
||||
"password": schema.StringAttribute{
|
||||
Description: "The password used for the SSH connection. " +
|
||||
"Defaults to the value of the `password` field of the " +
|
||||
"`provider` block.",
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"username": schema.StringAttribute{
|
||||
Description: "The username used for the SSH connection. " +
|
||||
"Defaults to the value of the `username` field of the " +
|
||||
"`provider` block.",
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
Blocks: map[string]schema.Block{
|
||||
"node": schema.ListNestedBlock{
|
||||
Description: "Overrides for SSH connection configuration for a Proxmox VE node.",
|
||||
NestedObject: schema.NestedBlockObject{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"name": schema.StringAttribute{
|
||||
Description: "The name of the Proxmox VE node.",
|
||||
Required: true,
|
||||
},
|
||||
"address": schema.StringAttribute{
|
||||
Description: "The address of the Proxmox VE node.",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *proxmoxProvider) Configure(
|
||||
ctx context.Context,
|
||||
req provider.ConfigureRequest,
|
||||
resp *provider.ConfigureResponse,
|
||||
) {
|
||||
tflog.Info(ctx, "Configuring the Proxmox provider...")
|
||||
|
||||
// Retrieve provider data from configuration
|
||||
var config proxmoxProviderModel
|
||||
diags := req.Config.Get(ctx, &config)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// If practitioner provided a configuration value for any of the
|
||||
// attributes, it must be a known value.
|
||||
|
||||
if config.Endpoint.IsUnknown() {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("endpoint"),
|
||||
"Unknown Proxmox VE API Endpoint",
|
||||
"The provider cannot create the Proxmox VE API client as there is an unknown configuration value "+
|
||||
"for the API endpoint. Either target apply the source of the value first, set the value statically in "+
|
||||
"the configuration, or use the PROXMOX_VE_ENDPOINT environment variable.",
|
||||
)
|
||||
}
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Default values to environment variables, but override
|
||||
// with Terraform configuration value if set.
|
||||
|
||||
// Check environment variables
|
||||
apiToken := utils.GetAnyStringEnv("PROXMOX_VE_API_TOKEN")
|
||||
endpoint := utils.GetAnyStringEnv("PROXMOX_VE_ENDPOINT")
|
||||
insecure := utils.GetAnyBoolEnv("PROXMOX_VE_INSECURE")
|
||||
username := utils.GetAnyStringEnv("PROXMOX_VE_USERNAME")
|
||||
password := utils.GetAnyStringEnv("PROXMOX_VE_PASSWORD")
|
||||
|
||||
if !config.APIToken.IsNull() {
|
||||
apiToken = config.APIToken.ValueString()
|
||||
}
|
||||
|
||||
if !config.Endpoint.IsNull() {
|
||||
endpoint = config.Endpoint.ValueString()
|
||||
}
|
||||
|
||||
if !config.Insecure.IsNull() {
|
||||
insecure = config.Insecure.ValueBool()
|
||||
}
|
||||
|
||||
if !config.Username.IsNull() {
|
||||
username = config.Username.ValueString()
|
||||
}
|
||||
|
||||
if !config.Password.IsNull() {
|
||||
password = config.Password.ValueString()
|
||||
}
|
||||
|
||||
if endpoint == "" {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("endpoint"),
|
||||
"Missing Proxmox VE API Endpoint",
|
||||
"The provider cannot create the Proxmox VE API client as there is a missing or empty value for the API endpoint. "+
|
||||
"Set the host value in the configuration or use the PROXMOX_VE_ENDPOINT environment variable. "+
|
||||
"If either is already set, ensure the value is not empty.",
|
||||
)
|
||||
}
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Create the Proxmox VE API client
|
||||
|
||||
creds, err := api.NewCredentials(username, password, "", apiToken)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unable to create Proxmox VE API credentials",
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
conn, err := api.NewConnection(
|
||||
endpoint,
|
||||
insecure,
|
||||
)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unable to create Proxmox VE API connection",
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
apiClient, err := api.NewClient(creds, conn)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unable to create Proxmox VE API client",
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
sshUsername := utils.GetAnyStringEnv("PROXMOX_VE_SSH_USERNAME")
|
||||
sshPassword := utils.GetAnyStringEnv("PROXMOX_VE_SSH_PASSWORD")
|
||||
sshAgent := utils.GetAnyBoolEnv("PROXMOX_VE_SSH_AGENT")
|
||||
sshAgentSocket := utils.GetAnyStringEnv("SSH_AUTH_SOCK", "PROXMOX_VE_SSH_AUTH_SOCK")
|
||||
nodeOverrides := map[string]string{}
|
||||
|
||||
if len(config.SSH) > 0 {
|
||||
if !config.SSH[0].Username.IsNull() {
|
||||
sshUsername = config.SSH[0].Username.ValueString()
|
||||
}
|
||||
|
||||
if !config.SSH[0].Password.IsNull() {
|
||||
sshPassword = config.SSH[0].Password.ValueString()
|
||||
}
|
||||
|
||||
if !config.SSH[0].Agent.IsNull() {
|
||||
sshAgent = config.SSH[0].Agent.ValueBool()
|
||||
}
|
||||
|
||||
if !config.SSH[0].AgentSocket.IsNull() {
|
||||
sshAgentSocket = config.SSH[0].AgentSocket.ValueString()
|
||||
}
|
||||
|
||||
for _, n := range config.SSH[0].Nodes {
|
||||
nodeOverrides[n.Name.ValueString()] = n.Address.ValueString()
|
||||
}
|
||||
}
|
||||
|
||||
if sshUsername == "" {
|
||||
sshUsername = strings.Split(creds.Username, "@")[0]
|
||||
}
|
||||
|
||||
if sshPassword == "" {
|
||||
sshPassword = creds.Password
|
||||
}
|
||||
|
||||
sshClient, err := ssh.NewClient(
|
||||
sshUsername, sshPassword, sshAgent, sshAgentSocket,
|
||||
&apiResolverWithOverrides{
|
||||
ar: apiResolver{c: apiClient},
|
||||
overrides: nodeOverrides,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unable to create Proxmox VE SSH client",
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
client := proxmox.NewClient(apiClient, sshClient)
|
||||
|
||||
resp.ResourceData = client
|
||||
resp.DataSourceData = client
|
||||
}
|
||||
|
||||
func (p *proxmoxProvider) Resources(_ context.Context) []func() resource.Resource {
|
||||
return []func() resource.Resource{
|
||||
network.NewLinuxBridgeResource,
|
||||
network.NewLinuxVLANResource,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *proxmoxProvider) DataSources(_ context.Context) []func() datasource.DataSource {
|
||||
return []func() datasource.DataSource{}
|
||||
}
|
||||
|
||||
type apiResolver struct {
|
||||
c api.Client
|
||||
}
|
||||
|
||||
func (r *apiResolver) Resolve(ctx context.Context, nodeName string) (string, error) {
|
||||
nc := &nodes.Client{Client: r.c, NodeName: nodeName}
|
||||
|
||||
networkDevices, err := nc.ListNetworkInterfaces(ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to list network devices of node \"%s\": %w", nc.NodeName, err)
|
||||
}
|
||||
|
||||
nodeAddress := ""
|
||||
|
||||
for _, d := range networkDevices {
|
||||
if d.Address != nil {
|
||||
nodeAddress = *d.Address
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if nodeAddress == "" {
|
||||
return "", fmt.Errorf("failed to determine the IP address of node \"%s\"", nc.NodeName)
|
||||
}
|
||||
|
||||
nodeAddressParts := strings.Split(nodeAddress, "/")
|
||||
|
||||
return nodeAddressParts[0], nil
|
||||
}
|
||||
|
||||
type apiResolverWithOverrides struct {
|
||||
ar apiResolver
|
||||
overrides map[string]string
|
||||
}
|
||||
|
||||
func (r *apiResolverWithOverrides) Resolve(ctx context.Context, nodeName string) (string, error) {
|
||||
if ip, ok := r.overrides[nodeName]; ok {
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
return r.ar.Resolve(ctx, nodeName)
|
||||
}
|
41
internal/test/provider_test.go
Normal file
41
internal/test/provider_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/providerserver"
|
||||
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/provider"
|
||||
)
|
||||
|
||||
const (
|
||||
// ProviderConfig is a shared configuration to combine with the actual
|
||||
// test configuration so the Proxmox VE client is properly configured.
|
||||
// It is also possible to use the PROXMOX_VE_ environment variables instead,.
|
||||
ProviderConfig = `
|
||||
provider "proxmox" {
|
||||
username = "root@pam"
|
||||
password = "password"
|
||||
insecure = true
|
||||
ssh {
|
||||
agent = true
|
||||
}
|
||||
}
|
||||
`
|
||||
// such as updating the Makefile and running the testing through that tool.
|
||||
)
|
||||
|
||||
// AccTestProtoV6ProviderFactories are used to instantiate a provider during
|
||||
// acceptance testing. The factory function will be invoked for every Terraform
|
||||
// CLI command executed to create a provider server to which the CLI can
|
||||
// reattach.
|
||||
//
|
||||
//nolint:gochecknoglobals
|
||||
var AccTestProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServer, error){
|
||||
"proxmox": providerserver.NewProtocol6WithError(provider.New("test")()),
|
||||
}
|
74
internal/test/resource_linux_bridge_test.go
Normal file
74
internal/test/resource_linux_bridge_test.go
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
)
|
||||
|
||||
func Test_LinuxBridgeResource(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
resourceName := "proxmox_virtual_environment_network_linux_bridge.test"
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: AccTestProtoV6ProviderFactories,
|
||||
Steps: []resource.TestStep{
|
||||
// Create and Read testing
|
||||
{
|
||||
Config: ProviderConfig + `
|
||||
resource "proxmox_virtual_environment_network_linux_bridge" "test" {
|
||||
node_name = "pve"
|
||||
name = "vmbr99"
|
||||
address = "3.3.3.3/24"
|
||||
comment = "created by terraform"
|
||||
mtu = 1499
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, "name", "vmbr99"),
|
||||
resource.TestCheckResourceAttr(resourceName, "address", "3.3.3.3/24"),
|
||||
resource.TestCheckResourceAttr(resourceName, "comment", "created by terraform"),
|
||||
resource.TestCheckResourceAttr(resourceName, "vlan_aware", "true"),
|
||||
resource.TestCheckResourceAttr(resourceName, "mtu", "1499"),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "id"),
|
||||
),
|
||||
},
|
||||
// ImportState testing
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
// Update testing
|
||||
{
|
||||
Config: ProviderConfig + `
|
||||
resource "proxmox_virtual_environment_network_linux_bridge" "test" {
|
||||
node_name = "pve"
|
||||
name = "vmbr99"
|
||||
address = "1.1.1.1/24"
|
||||
address6 = "FE80:0000:0000:0000:0202:B3FF:FE1E:8329/64"
|
||||
comment = "updated by terraform"
|
||||
vlan_aware = false
|
||||
mtu = null
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, "name", "vmbr99"),
|
||||
resource.TestCheckResourceAttr(resourceName, "address", "1.1.1.1/24"),
|
||||
resource.TestCheckResourceAttr(resourceName, "address6", "FE80:0000:0000:0000:0202:B3FF:FE1E:8329/64"),
|
||||
resource.TestCheckResourceAttr(resourceName, "comment", "updated by terraform"),
|
||||
resource.TestCheckResourceAttr(resourceName, "vlan_aware", "false"),
|
||||
resource.TestCheckNoResourceAttr(resourceName, "mtu"),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "id"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
72
internal/test/resource_linux_vlan_test.go
Normal file
72
internal/test/resource_linux_vlan_test.go
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
)
|
||||
|
||||
func Test_LinuxVLANResource(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
resourceName := "proxmox_virtual_environment_network_linux_vlan.test"
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: AccTestProtoV6ProviderFactories,
|
||||
Steps: []resource.TestStep{
|
||||
// Create and Read testing
|
||||
{
|
||||
Config: ProviderConfig + `
|
||||
resource "proxmox_virtual_environment_network_linux_vlan" "test" {
|
||||
node_name = "pve"
|
||||
name = "ens18.33"
|
||||
comment = "created by terraform"
|
||||
mtu = 1499
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, "name", "ens18.33"),
|
||||
resource.TestCheckResourceAttr(resourceName, "comment", "created by terraform"),
|
||||
resource.TestCheckResourceAttr(resourceName, "vlan", "33"),
|
||||
resource.TestCheckResourceAttr(resourceName, "interface", "ens18"),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "id"),
|
||||
),
|
||||
},
|
||||
// ImportState testing
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
// Update testing
|
||||
{
|
||||
Config: ProviderConfig + `
|
||||
resource "proxmox_virtual_environment_network_linux_vlan" "test" {
|
||||
node_name = "pve"
|
||||
name = "ens18.33"
|
||||
address = "1.1.1.1/24"
|
||||
address6 = "FE80:0000:0000:0000:0202:B3FF:FE1E:8329/64"
|
||||
comment = "updated by terraform"
|
||||
mtu = null
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(resourceName, "name", "ens18.33"),
|
||||
resource.TestCheckResourceAttr(resourceName, "address", "1.1.1.1/24"),
|
||||
resource.TestCheckResourceAttr(resourceName, "address6", "FE80:0000:0000:0000:0202:B3FF:FE1E:8329/64"),
|
||||
resource.TestCheckResourceAttr(resourceName, "comment", "updated by terraform"),
|
||||
resource.TestCheckResourceAttr(resourceName, "vlan", "33"),
|
||||
resource.TestCheckResourceAttr(resourceName, "interface", "ens18"),
|
||||
resource.TestCheckNoResourceAttr(resourceName, "mtu"),
|
||||
resource.TestCheckResourceAttrSet(resourceName, "id"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
@ -53,6 +53,16 @@ func (r *CustomBool) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pointer returns a pointers.
|
||||
func (r CustomBool) Pointer() *CustomBool {
|
||||
return &r
|
||||
}
|
||||
|
||||
// PointerBool returns a pointer to a boolean.
|
||||
func (r *CustomBool) PointerBool() *bool {
|
||||
return (*bool)(r)
|
||||
}
|
||||
|
||||
// MarshalJSON converts a boolean to a JSON value.
|
||||
func (r *CustomCommaSeparatedList) MarshalJSON() ([]byte, error) {
|
||||
s := strings.Join(*r, ",")
|
118
internal/types/ip_addr.go
Normal file
118
internal/types/ip_addr.go
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var _ basetypes.StringTypable = IPAddrType{}
|
||||
|
||||
// IPAddrType is a type that represents an IP address.
|
||||
type IPAddrType struct {
|
||||
basetypes.StringType
|
||||
}
|
||||
|
||||
// Equal returns true if the two types are equal.
|
||||
func (t IPAddrType) Equal(o attr.Type) bool {
|
||||
other, ok := o.(IPAddrType)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return t.StringType.Equal(other.StringType)
|
||||
}
|
||||
|
||||
// String returns a string representation of the type.
|
||||
func (t IPAddrType) String() string {
|
||||
return "IPAddrType"
|
||||
}
|
||||
|
||||
// ValueFromString converts a string value to a StringValuable.
|
||||
func (t IPAddrType) ValueFromString(
|
||||
_ context.Context, in basetypes.StringValue,
|
||||
) (basetypes.StringValuable, diag.Diagnostics) {
|
||||
value := IPAddrValue{
|
||||
StringValue: in,
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// ValueFromTerraform converts a Terraform value to a StringValuable.
|
||||
func (t IPAddrType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
|
||||
attrValue, err := t.StringType.ValueFromTerraform(ctx, in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unexpected error converting Terraform value to StringValue: %w", err)
|
||||
}
|
||||
|
||||
stringValue, ok := attrValue.(basetypes.StringValue)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected value type of %T", attrValue)
|
||||
}
|
||||
|
||||
stringValuable, diags := t.ValueFromString(ctx, stringValue)
|
||||
if diags.HasError() {
|
||||
return nil, fmt.Errorf("unexpected error converting StringValue to StringValuable: %v", diags)
|
||||
}
|
||||
|
||||
return stringValuable, nil
|
||||
}
|
||||
|
||||
// ValueType returns the underlying value type.
|
||||
func (t IPAddrType) ValueType(_ context.Context) attr.Value {
|
||||
return IPAddrValue{}
|
||||
}
|
||||
|
||||
// Validate ensures the value is valid IP address.
|
||||
func (t IPAddrType) Validate(_ context.Context, value tftypes.Value, valuePath path.Path) diag.Diagnostics {
|
||||
if value.IsNull() || !value.IsKnown() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var diags diag.Diagnostics
|
||||
|
||||
var valueString string
|
||||
|
||||
if err := value.As(&valueString); err != nil {
|
||||
diags.AddAttributeError(
|
||||
valuePath,
|
||||
"Invalid Terraform Value",
|
||||
"An unexpected error occurred while attempting to convert a Terraform value to a string. "+
|
||||
"This generally is an issue with the provider schema implementation. "+
|
||||
"Please contact the provider developers.\n\n"+
|
||||
"Path: "+valuePath.String()+"\n"+
|
||||
"Error: "+err.Error(),
|
||||
)
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
if ip := net.ParseIP(valueString); ip == nil {
|
||||
diags.AddAttributeError(
|
||||
valuePath,
|
||||
"Invalid IP String Value",
|
||||
"An unexpected error occurred while converting a string value that was expected to be IPv4/IPv6.\n\n"+
|
||||
"Path: "+valuePath.String()+"\n"+
|
||||
"Given Value: "+valueString,
|
||||
)
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
122
internal/types/ip_addr_test.go
Normal file
122
internal/types/ip_addr_test.go
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
)
|
||||
|
||||
func Test_IPAddrTypeValueFromTerraform(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
val tftypes.Value
|
||||
expected func(val IPAddrValue) bool
|
||||
expectError bool
|
||||
}{
|
||||
"null value": {
|
||||
val: tftypes.NewValue(tftypes.String, nil),
|
||||
expected: func(val IPAddrValue) bool {
|
||||
return val.IsNull()
|
||||
},
|
||||
},
|
||||
"unknown value": {
|
||||
val: tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
|
||||
expected: func(val IPAddrValue) bool {
|
||||
return val.IsUnknown()
|
||||
},
|
||||
},
|
||||
"valid IPv4": {
|
||||
val: tftypes.NewValue(tftypes.String, "1.2.3.4"),
|
||||
expected: func(val IPAddrValue) bool {
|
||||
return val.ValueString() == "1.2.3.4"
|
||||
},
|
||||
},
|
||||
"valid IPv6": {
|
||||
val: tftypes.NewValue(tftypes.String, "2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
|
||||
expected: func(val IPAddrValue) bool {
|
||||
return val.ValueString() == "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
name, test := name, test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.TODO()
|
||||
val, err := IPAddrType{}.ValueFromTerraform(ctx, test.val)
|
||||
|
||||
if err == nil && test.expectError {
|
||||
t.Fatal("expected error, got no error")
|
||||
}
|
||||
if err != nil && !test.expectError {
|
||||
t.Fatalf("got unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !test.expected(val.(IPAddrValue)) {
|
||||
t.Errorf("unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_IPAddrTypeValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type testCase struct {
|
||||
val tftypes.Value
|
||||
expectError bool
|
||||
}
|
||||
|
||||
tests := map[string]testCase{
|
||||
"not a string": {
|
||||
val: tftypes.NewValue(tftypes.Bool, true),
|
||||
expectError: true,
|
||||
},
|
||||
"unknown string": {
|
||||
val: tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
|
||||
},
|
||||
"null string": {
|
||||
val: tftypes.NewValue(tftypes.String, nil),
|
||||
},
|
||||
"valid IPv4 string": {
|
||||
val: tftypes.NewValue(tftypes.String, "1.2.3.4"),
|
||||
},
|
||||
"valid IPv6 string": {
|
||||
val: tftypes.NewValue(tftypes.String, "2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
|
||||
},
|
||||
"invalid string": {
|
||||
val: tftypes.NewValue(tftypes.String, "not ok"),
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
name, test := name, test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
diags := IPAddrType{}.Validate(ctx, test.val, path.Root("test"))
|
||||
|
||||
if !diags.HasError() && test.expectError {
|
||||
t.Fatal("expected error, got no error")
|
||||
}
|
||||
|
||||
if diags.HasError() && !test.expectError {
|
||||
t.Fatalf("got unexpected error: %s", diags)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
46
internal/types/ip_addr_value.go
Normal file
46
internal/types/ip_addr_value.go
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var _ basetypes.StringValuable = IPAddrValue{}
|
||||
|
||||
// IPAddrValue is a type that represents an IP address value.
|
||||
type IPAddrValue struct {
|
||||
basetypes.StringValue
|
||||
}
|
||||
|
||||
// Equal returns true if the two values are equal.
|
||||
func (v IPAddrValue) Equal(o attr.Value) bool {
|
||||
other, ok := o.(IPAddrValue)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return v.StringValue.Equal(other.StringValue)
|
||||
}
|
||||
|
||||
// Type returns the type of the value.
|
||||
func (v IPAddrValue) Type(_ context.Context) attr.Type {
|
||||
return IPAddrType{}
|
||||
}
|
||||
|
||||
// NewIPAddrPointerValue returns a new IPAddrValue from a string pointer.
|
||||
func NewIPAddrPointerValue(value *string) IPAddrValue {
|
||||
return IPAddrValue{
|
||||
StringValue: types.StringPointerValue(value),
|
||||
}
|
||||
}
|
119
internal/types/ip_cidr.go
Normal file
119
internal/types/ip_cidr.go
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var _ basetypes.StringTypable = IPCIDRType{}
|
||||
|
||||
// IPCIDRType is a type that represents an IP address in CIDR notation.
|
||||
type IPCIDRType struct {
|
||||
basetypes.StringType
|
||||
}
|
||||
|
||||
// Equal returns true if the two types are equal.
|
||||
func (t IPCIDRType) Equal(o attr.Type) bool {
|
||||
other, ok := o.(IPCIDRType)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return t.StringType.Equal(other.StringType)
|
||||
}
|
||||
|
||||
// String returns a string representation of the type.
|
||||
func (t IPCIDRType) String() string {
|
||||
return "IPCIDRType"
|
||||
}
|
||||
|
||||
// ValueFromString converts a string value to a StringValuable.
|
||||
func (t IPCIDRType) ValueFromString(
|
||||
_ context.Context, in basetypes.StringValue,
|
||||
) (basetypes.StringValuable, diag.Diagnostics) {
|
||||
value := IPCIDRValue{
|
||||
StringValue: in,
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// ValueFromTerraform converts a Terraform value to a StringValuable.
|
||||
func (t IPCIDRType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
|
||||
attrValue, err := t.StringType.ValueFromTerraform(ctx, in)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unexpected error converting Terraform value to StringValue: %w", err)
|
||||
}
|
||||
|
||||
stringValue, ok := attrValue.(basetypes.StringValue)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected value type of %T", attrValue)
|
||||
}
|
||||
|
||||
stringValuable, diags := t.ValueFromString(ctx, stringValue)
|
||||
if diags.HasError() {
|
||||
return nil, fmt.Errorf("unexpected error converting StringValue to StringValuable: %v", diags)
|
||||
}
|
||||
|
||||
return stringValuable, nil
|
||||
}
|
||||
|
||||
// ValueType returns the underlying value type.
|
||||
func (t IPCIDRType) ValueType(_ context.Context) attr.Value {
|
||||
return IPCIDRValue{}
|
||||
}
|
||||
|
||||
// Validate ensures the value is valid IP address in CIDR notation.
|
||||
func (t IPCIDRType) Validate(_ context.Context, value tftypes.Value, valuePath path.Path) diag.Diagnostics {
|
||||
if value.IsNull() || !value.IsKnown() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var diags diag.Diagnostics
|
||||
|
||||
var valueString string
|
||||
|
||||
if err := value.As(&valueString); err != nil {
|
||||
diags.AddAttributeError(
|
||||
valuePath,
|
||||
"Invalid Terraform Value",
|
||||
"An unexpected error occurred while attempting to convert a Terraform value to a string. "+
|
||||
"This generally is an issue with the provider schema implementation. "+
|
||||
"Please contact the provider developers.\n\n"+
|
||||
"Path: "+valuePath.String()+"\n"+
|
||||
"Error: "+err.Error(),
|
||||
)
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
if _, _, err := net.ParseCIDR(valueString); err != nil {
|
||||
diags.AddAttributeError(
|
||||
valuePath,
|
||||
"Invalid IP/CIDR String Value",
|
||||
"An unexpected error occurred while converting a string value that was expected to be IP/CIDR.\n\n"+
|
||||
"Path: "+valuePath.String()+"\n"+
|
||||
"Given Value: "+valueString+"\n"+
|
||||
"Error: "+err.Error(),
|
||||
)
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
130
internal/types/ip_cidr_test.go
Normal file
130
internal/types/ip_cidr_test.go
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
)
|
||||
|
||||
func Test_IPCIDRTypeValueFromTerraform(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]struct {
|
||||
val tftypes.Value
|
||||
expected func(val IPCIDRValue) bool
|
||||
expectError bool
|
||||
}{
|
||||
"null value": {
|
||||
val: tftypes.NewValue(tftypes.String, nil),
|
||||
expected: func(val IPCIDRValue) bool {
|
||||
return val.IsNull()
|
||||
},
|
||||
},
|
||||
"unknown value": {
|
||||
val: tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
|
||||
expected: func(val IPCIDRValue) bool {
|
||||
return val.IsUnknown()
|
||||
},
|
||||
},
|
||||
"valid IPv4/CIDR": {
|
||||
val: tftypes.NewValue(tftypes.String, "1.2.3.4/32"),
|
||||
expected: func(val IPCIDRValue) bool {
|
||||
return val.ValueString() == "1.2.3.4/32"
|
||||
},
|
||||
},
|
||||
"valid IPv6/CIDR": {
|
||||
val: tftypes.NewValue(tftypes.String, "2001:db8::/32"),
|
||||
expected: func(val IPCIDRValue) bool {
|
||||
return val.ValueString() == "2001:db8::/32"
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
name, test := name, test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.TODO()
|
||||
val, err := IPCIDRType{}.ValueFromTerraform(ctx, test.val)
|
||||
|
||||
if err == nil && test.expectError {
|
||||
t.Fatal("expected error, got no error")
|
||||
}
|
||||
if err != nil && !test.expectError {
|
||||
t.Fatalf("got unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !test.expected(val.(IPCIDRValue)) {
|
||||
t.Errorf("unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_IPCIDRTypeValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type testCase struct {
|
||||
val tftypes.Value
|
||||
expectError bool
|
||||
}
|
||||
|
||||
tests := map[string]testCase{
|
||||
"not a string": {
|
||||
val: tftypes.NewValue(tftypes.Bool, true),
|
||||
expectError: true,
|
||||
},
|
||||
"unknown string": {
|
||||
val: tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
|
||||
},
|
||||
"null string": {
|
||||
val: tftypes.NewValue(tftypes.String, nil),
|
||||
},
|
||||
"valid IPv4 string": {
|
||||
val: tftypes.NewValue(tftypes.String, "1.2.3.4/32"),
|
||||
},
|
||||
"valid IPv6 string": {
|
||||
val: tftypes.NewValue(tftypes.String, "2001:db8::/32"),
|
||||
},
|
||||
"invalid string": {
|
||||
val: tftypes.NewValue(tftypes.String, "not ok"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid IPv4 string no CIDR": {
|
||||
val: tftypes.NewValue(tftypes.String, "1.2.3.4"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid IPv6 string no CIDR": {
|
||||
val: tftypes.NewValue(tftypes.String, "2001:db8::"),
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
name, test := name, test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
diags := IPCIDRType{}.Validate(ctx, test.val, path.Root("test"))
|
||||
|
||||
if !diags.HasError() && test.expectError {
|
||||
t.Fatal("expected error, got no error")
|
||||
}
|
||||
|
||||
if diags.HasError() && !test.expectError {
|
||||
t.Fatalf("got unexpected error: %s", diags)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
46
internal/types/ip_cidr_value.go
Normal file
46
internal/types/ip_cidr_value.go
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var _ basetypes.StringValuable = IPCIDRValue{}
|
||||
|
||||
// IPCIDRValue is a type that represents an IP address in CIDR notation.
|
||||
type IPCIDRValue struct {
|
||||
basetypes.StringValue
|
||||
}
|
||||
|
||||
// Equal returns true if the two values are equal.
|
||||
func (v IPCIDRValue) Equal(o attr.Value) bool {
|
||||
other, ok := o.(IPCIDRValue)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return v.StringValue.Equal(other.StringValue)
|
||||
}
|
||||
|
||||
// Type returns the type of the value.
|
||||
func (v IPCIDRValue) Type(_ context.Context) attr.Type {
|
||||
return IPCIDRType{}
|
||||
}
|
||||
|
||||
// NewIPCIDRPointerValue returns a new IPCIDRValue from a string pointer.
|
||||
func NewIPCIDRPointerValue(value *string) IPCIDRValue {
|
||||
return IPCIDRValue{
|
||||
StringValue: types.StringPointerValue(value),
|
||||
}
|
||||
}
|
67
main.go
67
main.go
@ -1,31 +1,80 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/providerserver"
|
||||
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
|
||||
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
|
||||
"github.com/hashicorp/terraform-plugin-go/tfprotov6/tf6server"
|
||||
"github.com/hashicorp/terraform-plugin-mux/tf5to6server"
|
||||
"github.com/hashicorp/terraform-plugin-mux/tf6muxserver"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
|
||||
|
||||
newProvider "github.com/bpg/terraform-provider-proxmox/internal/provider"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/provider"
|
||||
)
|
||||
|
||||
// If you do not have terraform installed, you can remove the formatting command, but it's suggested to
|
||||
// ensure the documentation is formatted properly.
|
||||
//go:generate terraform fmt -recursive ./example/
|
||||
|
||||
// Run the docs generation tool, check its repository for more information on how it works and how docs
|
||||
// can be customized.
|
||||
//go:generate go run -modfile=tools/go.mod github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
var debug bool
|
||||
|
||||
flag.BoolVar(&debug, "debug", false, "set to true to run the provider with support for debuggers like delve")
|
||||
flag.Parse()
|
||||
|
||||
opts := &plugin.ServeOpts{
|
||||
Debug: debug,
|
||||
ProviderAddr: "registry.terraform.io/bpg/proxmox",
|
||||
ProviderFunc: func() *schema.Provider {
|
||||
return provider.ProxmoxVirtualEnvironment()
|
||||
upgradedSdkServer, err := tf5to6server.UpgradeServer(
|
||||
ctx,
|
||||
func() tfprotov5.ProviderServer {
|
||||
return schema.NewGRPCProviderServer(
|
||||
provider.ProxmoxVirtualEnvironment(),
|
||||
)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
providers := []func() tfprotov6.ProviderServer{
|
||||
providerserver.NewProtocol6(newProvider.New("dev")()),
|
||||
func() tfprotov6.ProviderServer {
|
||||
return upgradedSdkServer
|
||||
},
|
||||
}
|
||||
|
||||
plugin.Serve(opts)
|
||||
muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var serveOpts []tf6server.ServeOpt
|
||||
|
||||
if debug {
|
||||
serveOpts = append(serveOpts, tf6server.WithManagedDebug())
|
||||
}
|
||||
|
||||
err = tf6server.Serve(
|
||||
"registry.terraform.io/bpg/proxmox",
|
||||
muxServer.ProviderServer,
|
||||
serveOpts...,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
package access
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// ACLGetResponseBody contains the body from an access control list response.
|
||||
type ACLGetResponseBody struct {
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"net/url"
|
||||
"sort"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
)
|
||||
|
||||
func (c *Client) rolesPath() string {
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
package access
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// RoleCreateRequestBody contains the data for an access group create request.
|
||||
type RoleCreateRequestBody struct {
|
||||
|
@ -14,8 +14,8 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
)
|
||||
|
||||
func (c *Client) usersPath() string {
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
package access
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// UserChangePasswordRequestBody contains the data for a user password change request.
|
||||
type UserChangePasswordRequestBody struct {
|
||||
|
@ -7,6 +7,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@ -18,5 +19,5 @@ type Authenticator interface {
|
||||
IsRoot() bool
|
||||
|
||||
// AuthenticateRequest adds authentication data to a new request.
|
||||
AuthenticateRequest(req *http.Request) error
|
||||
AuthenticateRequest(ctx context.Context, req *http.Request) error
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
@ -29,7 +30,9 @@ import (
|
||||
var ErrNoDataObjectInResponse = errors.New("the server did not include a data object in the response")
|
||||
|
||||
const (
|
||||
basePathJSONAPI = "api2/json"
|
||||
// the large timeout is to allow for large file uploads.
|
||||
httpClientTimeout = 5 * time.Minute
|
||||
basePathJSONAPI = "api2/json"
|
||||
)
|
||||
|
||||
// Client is an interface for performing requests against the Proxmox API.
|
||||
@ -83,8 +86,11 @@ func NewConnection(endpoint string, insecure bool) (*Connection, error) {
|
||||
}
|
||||
|
||||
return &Connection{
|
||||
endpoint: strings.TrimRight(u.String(), "/"),
|
||||
httpClient: &http.Client{Transport: transport},
|
||||
endpoint: strings.TrimRight(u.String(), "/"),
|
||||
httpClient: &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: httpClientTimeout,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -95,7 +101,7 @@ type client struct {
|
||||
}
|
||||
|
||||
// NewClient creates and initializes a VirtualEnvironmentClient instance.
|
||||
func NewClient(ctx context.Context, creds *Credentials, conn *Connection) (Client, error) {
|
||||
func NewClient(creds *Credentials, conn *Connection) (Client, error) {
|
||||
if creds == nil {
|
||||
return nil, errors.New("credentials must not be nil")
|
||||
}
|
||||
@ -111,7 +117,7 @@ func NewClient(ctx context.Context, creds *Credentials, conn *Connection) (Clien
|
||||
if creds.APIToken != nil {
|
||||
auth, err = NewTokenAuthenticator(*creds.APIToken)
|
||||
} else {
|
||||
auth, err = NewTicketAuthenticator(ctx, conn, creds)
|
||||
auth, err = NewTicketAuthenticator(conn, creds)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -202,7 +208,7 @@ func (c *client) DoRequest(
|
||||
req.Header.Add("Content-Type", reqBodyType)
|
||||
}
|
||||
|
||||
err = c.auth.AuthenticateRequest(req)
|
||||
err = c.auth.AuthenticateRequest(ctx, req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to authenticate HTTP %s request (path: %s) - Reason: %w",
|
||||
method,
|
||||
@ -228,6 +234,7 @@ func (c *client) DoRequest(
|
||||
return err
|
||||
}
|
||||
|
||||
//nolint:nestif
|
||||
if responseBody != nil {
|
||||
err = json.NewDecoder(res.Body).Decode(responseBody)
|
||||
if err != nil {
|
||||
@ -248,14 +255,27 @@ func (c *client) DoRequest(
|
||||
err,
|
||||
)
|
||||
}
|
||||
tflog.Warn(ctx, "unhandled HTTP response body", map[string]interface{}{
|
||||
"data": string(data),
|
||||
})
|
||||
if len(data) > 0 {
|
||||
dr := dataResponse{}
|
||||
|
||||
if err2 := json.NewDecoder(bytes.NewReader(data)).Decode(&dr); err2 == nil {
|
||||
if dr.Data == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
tflog.Warn(ctx, "unhandled HTTP response body", map[string]interface{}{
|
||||
"data": dr.Data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type dataResponse struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// ExpandPath expands the given path to an absolute path.
|
||||
func (c *client) ExpandPath(path string) string {
|
||||
return path
|
||||
|
@ -21,12 +21,14 @@ import (
|
||||
)
|
||||
|
||||
type ticketAuthenticator struct {
|
||||
authenticationData *AuthenticationResponseData
|
||||
conn *Connection
|
||||
authRequest string
|
||||
authData *AuthenticationResponseData
|
||||
}
|
||||
|
||||
// NewTicketAuthenticator returns a new ticket authenticator.
|
||||
func NewTicketAuthenticator(ctx context.Context, conn *Connection, creds *Credentials) (Authenticator, error) {
|
||||
reqStr := fmt.Sprintf(
|
||||
func NewTicketAuthenticator(conn *Connection, creds *Credentials) (Authenticator, error) {
|
||||
authRequest := fmt.Sprintf(
|
||||
"username=%s&password=%s",
|
||||
url.QueryEscape(creds.Username),
|
||||
url.QueryEscape(creds.Password),
|
||||
@ -34,14 +36,25 @@ func NewTicketAuthenticator(ctx context.Context, conn *Connection, creds *Creden
|
||||
|
||||
// OTP is optional, and probably doesn't make much sense for most provider users.
|
||||
if creds.OTP != nil {
|
||||
reqStr = fmt.Sprintf("%s&otp=%s", reqStr, url.QueryEscape(*creds.OTP))
|
||||
authRequest = fmt.Sprintf("%s&otp=%s", authRequest, url.QueryEscape(*creds.OTP))
|
||||
}
|
||||
|
||||
return &ticketAuthenticator{
|
||||
conn: conn,
|
||||
authRequest: authRequest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *ticketAuthenticator) authenticate(ctx context.Context) (*AuthenticationResponseData, error) {
|
||||
if t.authData != nil {
|
||||
return t.authData, nil
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodPost,
|
||||
fmt.Sprintf("%s/%s/access/ticket", conn.endpoint, basePathJSONAPI),
|
||||
bytes.NewBufferString(reqStr),
|
||||
fmt.Sprintf("%s/%s/access/ticket", t.conn.endpoint, basePathJSONAPI),
|
||||
bytes.NewBufferString(t.authRequest),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create authentication request: %w", err)
|
||||
@ -49,12 +62,12 @@ func NewTicketAuthenticator(ctx context.Context, conn *Connection, creds *Creden
|
||||
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
tflog.Debug(ctx, "sending authentication request", map[string]interface{}{
|
||||
tflog.Debug(ctx, "Sending authentication request", map[string]interface{}{
|
||||
"path": req.URL.Path,
|
||||
})
|
||||
|
||||
//nolint:bodyclose
|
||||
res, err := conn.httpClient.Do(req)
|
||||
res, err := t.conn.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve authentication response: %w", err)
|
||||
}
|
||||
@ -91,28 +104,29 @@ func NewTicketAuthenticator(ctx context.Context, conn *Connection, creds *Creden
|
||||
return nil, errors.New("the server did not include the username in the authentication response")
|
||||
}
|
||||
|
||||
return &ticketAuthenticator{
|
||||
authenticationData: resBody.Data,
|
||||
}, nil
|
||||
t.authData = resBody.Data
|
||||
|
||||
return resBody.Data, nil
|
||||
}
|
||||
|
||||
func (t *ticketAuthenticator) IsRoot() bool {
|
||||
return t.authenticationData.Username == rootUsername
|
||||
return t.authData != nil && t.authData.Username == rootUsername
|
||||
}
|
||||
|
||||
// AuthenticateRequest adds authentication data to a new request.
|
||||
func (t *ticketAuthenticator) AuthenticateRequest(req *http.Request) error {
|
||||
if t.authenticationData == nil {
|
||||
return errors.New("failed to authenticate: no ticket")
|
||||
func (t *ticketAuthenticator) AuthenticateRequest(ctx context.Context, req *http.Request) error {
|
||||
a, err := t.authenticate(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to authenticate: %w", err)
|
||||
}
|
||||
|
||||
req.AddCookie(&http.Cookie{
|
||||
Name: "PVEAuthCookie",
|
||||
Value: *t.authenticationData.Ticket,
|
||||
Value: *a.Ticket,
|
||||
})
|
||||
|
||||
if req.Method != http.MethodGet {
|
||||
req.Header.Add("CSRFPreventionToken", *t.authenticationData.CSRFPreventionToken)
|
||||
req.Header.Add("CSRFPreventionToken", *a.CSRFPreventionToken)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
package api
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// AuthenticationResponseBody contains the body from an authentication response.
|
||||
type AuthenticationResponseBody struct {
|
||||
|
@ -7,6 +7,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
@ -29,7 +30,7 @@ func (t *tokenAuthenticator) IsRoot() bool {
|
||||
return t.username == rootUsername
|
||||
}
|
||||
|
||||
func (t *tokenAuthenticator) AuthenticateRequest(req *http.Request) error {
|
||||
func (t *tokenAuthenticator) AuthenticateRequest(_ context.Context, req *http.Request) error {
|
||||
req.Header.Set("Authorization", "PVEAPIToken="+t.token)
|
||||
return nil
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package cluster
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// NextIDRequestBody contains the data for a cluster next id request.
|
||||
type NextIDRequestBody struct {
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// OptionsPutRequestBody is the request body for the PUT /cluster/firewall/options API call.
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
package firewall
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// IPSetListResponseBody contains the data from an IPSet get response.
|
||||
type IPSetListResponseBody struct {
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
package firewall
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// OptionsPutRequestBody is the request body for the PUT /cluster/firewall/options API call.
|
||||
type OptionsPutRequestBody struct {
|
||||
|
@ -14,8 +14,8 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
)
|
||||
|
||||
// Rule is an interface for the Proxmox firewall rule API.
|
||||
|
@ -26,9 +26,9 @@ type RuleGetResponseData struct {
|
||||
BaseRule
|
||||
|
||||
// NOTE: This is `int` in the PVE API docs, but it's actually a string in the response.
|
||||
Pos string `json:"pos" url:"pos"`
|
||||
Action string `json:"action" url:"action"`
|
||||
Type string `json:"type" url:"type"`
|
||||
Pos string `json:"pos" url:"pos"`
|
||||
Action string `json:"action" url:"action"`
|
||||
Type string `json:"type" url:"type"`
|
||||
}
|
||||
|
||||
// RuleListResponseBody contains the data from a firewall rule get response.
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
package nodes
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// CertificateDeleteRequestBody contains the data for a custom certificate delete request.
|
||||
type CertificateDeleteRequestBody struct {
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/containers"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/tasks"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms"
|
||||
)
|
||||
|
||||
@ -41,3 +42,10 @@ func (c *Client) VM(vmID int) *vms.Client {
|
||||
VMID: vmID,
|
||||
}
|
||||
}
|
||||
|
||||
// Tasks returns a client for managing VM tasks.
|
||||
func (c *Client) Tasks() *tasks.Client {
|
||||
return &tasks.Client{
|
||||
Client: c,
|
||||
}
|
||||
}
|
||||
|
@ -13,26 +13,27 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
types2 "github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
)
|
||||
|
||||
// CloneRequestBody contains the data for an container clone request.
|
||||
type CloneRequestBody struct {
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
Description *string `json:"description,omitempty" url:"description,omitempty"`
|
||||
FullCopy *types.CustomBool `json:"full,omitempty" url:"full,omitempty,int"`
|
||||
Hostname *string `json:"hostname,omitempty" url:"hostname,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
SnapshotName *string `json:"snapname,omitempty" url:"snapname,omitempty"`
|
||||
TargetNodeName *string `json:"target,omitempty" url:"target,omitempty"`
|
||||
TargetStorage *string `json:"storage,omitempty" url:"storage,omitempty"`
|
||||
VMIDNew int `json:"newid" url:"newid"`
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
Description *string `json:"description,omitempty" url:"description,omitempty"`
|
||||
FullCopy *types2.CustomBool `json:"full,omitempty" url:"full,omitempty,int"`
|
||||
Hostname *string `json:"hostname,omitempty" url:"hostname,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
SnapshotName *string `json:"snapname,omitempty" url:"snapname,omitempty"`
|
||||
TargetNodeName *string `json:"target,omitempty" url:"target,omitempty"`
|
||||
TargetStorage *string `json:"storage,omitempty" url:"storage,omitempty"`
|
||||
VMIDNew int `json:"newid" url:"newid"`
|
||||
}
|
||||
|
||||
// CreateRequestBody contains the data for a user create request.
|
||||
type CreateRequestBody struct {
|
||||
BandwidthLimit *float64 `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
ConsoleEnabled *types.CustomBool `json:"console,omitempty" url:"console,omitempty,int"`
|
||||
ConsoleEnabled *types2.CustomBool `json:"console,omitempty" url:"console,omitempty,int"`
|
||||
ConsoleMode *string `json:"cmode,omitempty" url:"cmode,omitempty"`
|
||||
CPUArchitecture *string `json:"arch,omitempty" url:"arch,omitempty"`
|
||||
CPUCores *int `json:"cores,omitempty" url:"cores,omitempty"`
|
||||
@ -45,10 +46,10 @@ type CreateRequestBody struct {
|
||||
DNSDomain *string `json:"searchdomain,omitempty" url:"searchdomain,omitempty"`
|
||||
DNSServer *string `json:"nameserver,omitempty" url:"nameserver,omitempty"`
|
||||
Features *CustomFeatures `json:"features,omitempty" url:"features,omitempty"`
|
||||
Force *types.CustomBool `json:"force,omitempty" url:"force,omitempty,int"`
|
||||
Force *types2.CustomBool `json:"force,omitempty" url:"force,omitempty,int"`
|
||||
HookScript *string `json:"hookscript,omitempty" url:"hookscript,omitempty"`
|
||||
Hostname *string `json:"hostname,omitempty" url:"hostname,omitempty"`
|
||||
IgnoreUnpackErrors *types.CustomBool `json:"ignore-unpack-errors,omitempty" url:"force,omitempty,int"`
|
||||
IgnoreUnpackErrors *types2.CustomBool `json:"ignore-unpack-errors,omitempty" url:"force,omitempty,int"`
|
||||
Lock *string `json:"lock,omitempty" url:"lock,omitempty,int"`
|
||||
MountPoints CustomMountPointArray `json:"mp,omitempty" url:"mp,omitempty,numbered"`
|
||||
NetworkInterfaces CustomNetworkInterfaceArray `json:"net,omitempty" url:"net,omitempty,numbered"`
|
||||
@ -56,43 +57,43 @@ type CreateRequestBody struct {
|
||||
OSType *string `json:"ostype,omitempty" url:"ostype,omitempty"`
|
||||
Password *string `json:"password,omitempty" url:"password,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
Protection *types.CustomBool `json:"protection,omitempty" url:"protection,omitempty,int"`
|
||||
Restore *types.CustomBool `json:"restore,omitempty" url:"restore,omitempty,int"`
|
||||
Protection *types2.CustomBool `json:"protection,omitempty" url:"protection,omitempty,int"`
|
||||
Restore *types2.CustomBool `json:"restore,omitempty" url:"restore,omitempty,int"`
|
||||
RootFS *CustomRootFS `json:"rootfs,omitempty" url:"rootfs,omitempty"`
|
||||
SSHKeys *CustomSSHKeys `json:"ssh-public-keys,omitempty" url:"ssh-public-keys,omitempty"`
|
||||
Start *types.CustomBool `json:"start,omitempty" url:"start,omitempty,int"`
|
||||
StartOnBoot *types.CustomBool `json:"onboot,omitempty" url:"onboot,omitempty,int"`
|
||||
Start *types2.CustomBool `json:"start,omitempty" url:"start,omitempty,int"`
|
||||
StartOnBoot *types2.CustomBool `json:"onboot,omitempty" url:"onboot,omitempty,int"`
|
||||
StartupBehavior *CustomStartupBehavior `json:"startup,omitempty" url:"startup,omitempty"`
|
||||
Swap *int `json:"swap,omitempty" url:"swap,omitempty"`
|
||||
Tags *string `json:"tags,omitempty" url:"tags,omitempty"`
|
||||
Template *types.CustomBool `json:"template,omitempty" url:"template,omitempty,int"`
|
||||
Template *types2.CustomBool `json:"template,omitempty" url:"template,omitempty,int"`
|
||||
TTY *int `json:"tty,omitempty" url:"tty,omitempty"`
|
||||
Unique *types.CustomBool `json:"unique,omitempty" url:"unique,omitempty,int"`
|
||||
Unprivileged *types.CustomBool `json:"unprivileged,omitempty" url:"unprivileged,omitempty,int"`
|
||||
Unique *types2.CustomBool `json:"unique,omitempty" url:"unique,omitempty,int"`
|
||||
Unprivileged *types2.CustomBool `json:"unprivileged,omitempty" url:"unprivileged,omitempty,int"`
|
||||
VMID *int `json:"vmid,omitempty" url:"vmid,omitempty"`
|
||||
}
|
||||
|
||||
// CustomFeatures contains the values for the "features" property.
|
||||
type CustomFeatures struct {
|
||||
FUSE *types.CustomBool `json:"fuse,omitempty" url:"fuse,omitempty,int"`
|
||||
KeyControl *types.CustomBool `json:"keyctl,omitempty" url:"keyctl,omitempty,int"`
|
||||
MountTypes *[]string `json:"mount,omitempty" url:"mount,omitempty"`
|
||||
Nesting *types.CustomBool `json:"nesting,omitempty" url:"nesting,omitempty,int"`
|
||||
FUSE *types2.CustomBool `json:"fuse,omitempty" url:"fuse,omitempty,int"`
|
||||
KeyControl *types2.CustomBool `json:"keyctl,omitempty" url:"keyctl,omitempty,int"`
|
||||
MountTypes *[]string `json:"mount,omitempty" url:"mount,omitempty"`
|
||||
Nesting *types2.CustomBool `json:"nesting,omitempty" url:"nesting,omitempty,int"`
|
||||
}
|
||||
|
||||
// CustomMountPoint contains the values for the "mp[n]" properties.
|
||||
type CustomMountPoint struct {
|
||||
ACL *types.CustomBool `json:"acl,omitempty" url:"acl,omitempty,int"`
|
||||
Backup *types.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
||||
DiskSize *string `json:"size,omitempty" url:"size,omitempty"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
MountOptions *[]string `json:"mountoptions,omitempty" url:"mountoptions,omitempty"`
|
||||
MountPoint string `json:"mp" url:"mp"`
|
||||
Quota *types.CustomBool `json:"quota,omitempty" url:"quota,omitempty,int"`
|
||||
ReadOnly *types.CustomBool `json:"ro,omitempty" url:"ro,omitempty,int"`
|
||||
Replicate *types.CustomBool `json:"replicate,omitempty" url:"replicate,omitempty,int"`
|
||||
Shared *types.CustomBool `json:"shared,omitempty" url:"shared,omitempty,int"`
|
||||
Volume string `json:"volume" url:"volume"`
|
||||
ACL *types2.CustomBool `json:"acl,omitempty" url:"acl,omitempty,int"`
|
||||
Backup *types2.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
||||
DiskSize *string `json:"size,omitempty" url:"size,omitempty"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
MountOptions *[]string `json:"mountoptions,omitempty" url:"mountoptions,omitempty"`
|
||||
MountPoint string `json:"mp" url:"mp"`
|
||||
Quota *types2.CustomBool `json:"quota,omitempty" url:"quota,omitempty,int"`
|
||||
ReadOnly *types2.CustomBool `json:"ro,omitempty" url:"ro,omitempty,int"`
|
||||
Replicate *types2.CustomBool `json:"replicate,omitempty" url:"replicate,omitempty,int"`
|
||||
Shared *types2.CustomBool `json:"shared,omitempty" url:"shared,omitempty,int"`
|
||||
Volume string `json:"volume" url:"volume"`
|
||||
}
|
||||
|
||||
// CustomMountPointArray is an array of CustomMountPoint.
|
||||
@ -100,20 +101,20 @@ type CustomMountPointArray []CustomMountPoint
|
||||
|
||||
// CustomNetworkInterface contains the values for the "net[n]" properties.
|
||||
type CustomNetworkInterface struct {
|
||||
Bridge *string `json:"bridge,omitempty" url:"bridge,omitempty"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
Firewall *types.CustomBool `json:"firewall,omitempty" url:"firewall,omitempty,int"`
|
||||
IPv4Address *string `json:"ip,omitempty" url:"ip,omitempty"`
|
||||
IPv4Gateway *string `json:"gw,omitempty" url:"gw,omitempty"`
|
||||
IPv6Address *string `json:"ip6,omitempty" url:"ip6,omitempty"`
|
||||
IPv6Gateway *string `json:"gw6,omitempty" url:"gw6,omitempty"`
|
||||
MACAddress *string `json:"hwaddr,omitempty" url:"hwaddr,omitempty"`
|
||||
MTU *int `json:"mtu,omitempty" url:"mtu,omitempty"`
|
||||
Name string `json:"name" url:"name"`
|
||||
RateLimit *float64 `json:"rate,omitempty" url:"rate,omitempty"`
|
||||
Tag *int `json:"tag,omitempty" url:"tag,omitempty"`
|
||||
Trunks *[]int `json:"trunks,omitempty" url:"trunks,omitempty"`
|
||||
Type *string `json:"type,omitempty" url:"type,omitempty"`
|
||||
Bridge *string `json:"bridge,omitempty" url:"bridge,omitempty"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
Firewall *types2.CustomBool `json:"firewall,omitempty" url:"firewall,omitempty,int"`
|
||||
IPv4Address *string `json:"ip,omitempty" url:"ip,omitempty"`
|
||||
IPv4Gateway *string `json:"gw,omitempty" url:"gw,omitempty"`
|
||||
IPv6Address *string `json:"ip6,omitempty" url:"ip6,omitempty"`
|
||||
IPv6Gateway *string `json:"gw6,omitempty" url:"gw6,omitempty"`
|
||||
MACAddress *string `json:"hwaddr,omitempty" url:"hwaddr,omitempty"`
|
||||
MTU *int `json:"mtu,omitempty" url:"mtu,omitempty"`
|
||||
Name string `json:"name" url:"name"`
|
||||
RateLimit *float64 `json:"rate,omitempty" url:"rate,omitempty"`
|
||||
Tag *int `json:"tag,omitempty" url:"tag,omitempty"`
|
||||
Trunks *[]int `json:"trunks,omitempty" url:"trunks,omitempty"`
|
||||
Type *string `json:"type,omitempty" url:"type,omitempty"`
|
||||
}
|
||||
|
||||
// CustomNetworkInterfaceArray is an array of CustomNetworkInterface.
|
||||
@ -121,14 +122,14 @@ type CustomNetworkInterfaceArray []CustomNetworkInterface
|
||||
|
||||
// CustomRootFS contains the values for the "rootfs" property.
|
||||
type CustomRootFS struct {
|
||||
ACL *types.CustomBool `json:"acl,omitempty" url:"acl,omitempty,int"`
|
||||
Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
|
||||
MountOptions *[]string `json:"mountoptions,omitempty" url:"mountoptions,omitempty"`
|
||||
Quota *types.CustomBool `json:"quota,omitempty" url:"quota,omitempty,int"`
|
||||
ReadOnly *types.CustomBool `json:"ro,omitempty" url:"ro,omitempty,int"`
|
||||
Replicate *types.CustomBool `json:"replicate,omitempty" url:"replicate,omitempty,int"`
|
||||
Shared *types.CustomBool `json:"shared,omitempty" url:"shared,omitempty,int"`
|
||||
Volume string `json:"volume" url:"volume"`
|
||||
ACL *types2.CustomBool `json:"acl,omitempty" url:"acl,omitempty,int"`
|
||||
Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
|
||||
MountOptions *[]string `json:"mountoptions,omitempty" url:"mountoptions,omitempty"`
|
||||
Quota *types2.CustomBool `json:"quota,omitempty" url:"quota,omitempty,int"`
|
||||
ReadOnly *types2.CustomBool `json:"ro,omitempty" url:"ro,omitempty,int"`
|
||||
Replicate *types2.CustomBool `json:"replicate,omitempty" url:"replicate,omitempty,int"`
|
||||
Shared *types2.CustomBool `json:"shared,omitempty" url:"shared,omitempty,int"`
|
||||
Volume string `json:"volume" url:"volume"`
|
||||
}
|
||||
|
||||
// CustomSSHKeys contains the values for the "ssh-public-keys" property.
|
||||
@ -148,7 +149,7 @@ type GetResponseBody struct {
|
||||
|
||||
// GetResponseData contains the data from a user get response.
|
||||
type GetResponseData struct {
|
||||
ConsoleEnabled *types.CustomBool `json:"console,omitempty"`
|
||||
ConsoleEnabled *types2.CustomBool `json:"console,omitempty"`
|
||||
ConsoleMode *string `json:"cmode,omitempty"`
|
||||
CPUArchitecture *string `json:"arch,omitempty"`
|
||||
CPUCores *int `json:"cores,omitempty"`
|
||||
@ -162,7 +163,7 @@ type GetResponseData struct {
|
||||
Features *CustomFeatures `json:"features,omitempty"`
|
||||
HookScript *string `json:"hookscript,omitempty"`
|
||||
Hostname *string `json:"hostname,omitempty"`
|
||||
Lock *types.CustomBool `json:"lock,omitempty"`
|
||||
Lock *types2.CustomBool `json:"lock,omitempty"`
|
||||
LXCConfiguration *[][2]string `json:"lxc,omitempty"`
|
||||
MountPoint0 CustomMountPoint `json:"mp0,omitempty"`
|
||||
MountPoint1 CustomMountPoint `json:"mp1,omitempty"`
|
||||
@ -177,15 +178,15 @@ type GetResponseData struct {
|
||||
NetworkInterface6 *CustomNetworkInterface `json:"net6,omitempty"`
|
||||
NetworkInterface7 *CustomNetworkInterface `json:"net7,omitempty"`
|
||||
OSType *string `json:"ostype,omitempty"`
|
||||
Protection *types.CustomBool `json:"protection,omitempty"`
|
||||
Protection *types2.CustomBool `json:"protection,omitempty"`
|
||||
RootFS *CustomRootFS `json:"rootfs,omitempty"`
|
||||
StartOnBoot *types.CustomBool `json:"onboot,omitempty"`
|
||||
StartOnBoot *types2.CustomBool `json:"onboot,omitempty"`
|
||||
StartupBehavior *CustomStartupBehavior `json:"startup,omitempty"`
|
||||
Swap *int `json:"swap,omitempty"`
|
||||
Tags *string `json:"tags,omitempty"`
|
||||
Template *types.CustomBool `json:"template,omitempty"`
|
||||
Template *types2.CustomBool `json:"template,omitempty"`
|
||||
TTY *int `json:"tty,omitempty"`
|
||||
Unprivileged *types.CustomBool `json:"unprivileged,omitempty"`
|
||||
Unprivileged *types2.CustomBool `json:"unprivileged,omitempty"`
|
||||
}
|
||||
|
||||
// GetStatusResponseBody contains the body from a container get status response.
|
||||
@ -214,8 +215,8 @@ type RebootRequestBody struct {
|
||||
|
||||
// ShutdownRequestBody contains the body for a container shutdown request.
|
||||
type ShutdownRequestBody struct {
|
||||
ForceStop *types.CustomBool `json:"forceStop,omitempty" url:"forceStop,omitempty,int"`
|
||||
Timeout *int `json:"timeout,omitempty" url:"timeout,omitempty"`
|
||||
ForceStop *types2.CustomBool `json:"forceStop,omitempty" url:"forceStop,omitempty,int"`
|
||||
Timeout *int `json:"timeout,omitempty" url:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateRequestBody contains the data for an user update request.
|
||||
@ -550,10 +551,10 @@ func (r *CustomFeatures) UnmarshalJSON(b []byte) error {
|
||||
if len(v) == 2 {
|
||||
switch v[0] {
|
||||
case "fuse":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.FUSE = &bv
|
||||
case "keyctl":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.KeyControl = &bv
|
||||
case "mount":
|
||||
if v[1] != "" {
|
||||
@ -564,7 +565,7 @@ func (r *CustomFeatures) UnmarshalJSON(b []byte) error {
|
||||
r.MountTypes = &a
|
||||
}
|
||||
case "nesting":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Nesting = &bv
|
||||
}
|
||||
}
|
||||
@ -592,10 +593,10 @@ func (r *CustomMountPoint) UnmarshalJSON(b []byte) error {
|
||||
} else if len(v) == 2 {
|
||||
switch v[0] {
|
||||
case "acl":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.ACL = &bv
|
||||
case "backup":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Backup = &bv
|
||||
case "mountoptions":
|
||||
if v[1] != "" {
|
||||
@ -608,16 +609,16 @@ func (r *CustomMountPoint) UnmarshalJSON(b []byte) error {
|
||||
case "mp":
|
||||
r.MountPoint = v[1]
|
||||
case "quota":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Quota = &bv
|
||||
case "ro":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.ReadOnly = &bv
|
||||
case "replicate":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Replicate = &bv
|
||||
case "shared":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Shared = &bv
|
||||
case "size":
|
||||
r.DiskSize = &v[1]
|
||||
@ -650,7 +651,7 @@ func (r *CustomNetworkInterface) UnmarshalJSON(b []byte) error {
|
||||
case "bridge":
|
||||
r.Bridge = &v[1]
|
||||
case "firewall":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Firewall = &bv
|
||||
case "gw":
|
||||
r.IPv4Gateway = &v[1]
|
||||
@ -731,7 +732,7 @@ func (r *CustomRootFS) UnmarshalJSON(b []byte) error {
|
||||
} else if len(v) == 2 {
|
||||
switch v[0] {
|
||||
case "acl":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.ACL = &bv
|
||||
case "mountoptions":
|
||||
if v[1] != "" {
|
||||
@ -742,16 +743,16 @@ func (r *CustomRootFS) UnmarshalJSON(b []byte) error {
|
||||
r.MountOptions = &a
|
||||
}
|
||||
case "quota":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Quota = &bv
|
||||
case "ro":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.ReadOnly = &bv
|
||||
case "replicate":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Replicate = &bv
|
||||
case "shared":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Shared = &bv
|
||||
case "size":
|
||||
r.Size = new(types.DiskSize)
|
||||
|
125
proxmox/nodes/network.go
Normal file
125
proxmox/nodes/network.go
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||
)
|
||||
|
||||
const (
|
||||
networkReloadTimeoutSec = 5
|
||||
)
|
||||
|
||||
// ListNetworkInterfaces retrieves a list of network interfaces for a specific nodes.
|
||||
func (c *Client) ListNetworkInterfaces(ctx context.Context) ([]*NetworkInterfaceListResponseData, error) {
|
||||
resBody := &NetworkInterfaceListResponseBody{}
|
||||
|
||||
err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("network"), nil, resBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network interfaces for node \"%s\": %w", c.NodeName, err)
|
||||
}
|
||||
|
||||
if resBody.Data == nil {
|
||||
return nil, api.ErrNoDataObjectInResponse
|
||||
}
|
||||
|
||||
sort.Slice(resBody.Data, func(i, j int) bool {
|
||||
return resBody.Data[i].Priority < resBody.Data[j].Priority
|
||||
})
|
||||
|
||||
return resBody.Data, nil
|
||||
}
|
||||
|
||||
// CreateNetworkInterface creates a network interface for a specific node.
|
||||
func (c *Client) CreateNetworkInterface(ctx context.Context, d *NetworkInterfaceCreateUpdateRequestBody) error {
|
||||
err := c.DoRequest(ctx, http.MethodPost, c.ExpandPath("network"), d, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"failed to create network interface \"%s\" for node \"%s\": %w",
|
||||
d.Iface, c.NodeName, err,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReloadNetworkConfiguration reloads the network configuration for a specific node.
|
||||
func (c *Client) ReloadNetworkConfiguration(ctx context.Context) error {
|
||||
resBody := &ReloadNetworkResponseBody{}
|
||||
|
||||
err := c.DoRequest(ctx, http.MethodPut, c.ExpandPath("network"), nil, resBody)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to reload network configuration for node \"%s\": %w", c.NodeName, err)
|
||||
}
|
||||
|
||||
if resBody.Data == nil {
|
||||
return api.ErrNoDataObjectInResponse
|
||||
}
|
||||
|
||||
err = c.Tasks().WaitForTask(ctx, *resBody.Data, networkReloadTimeoutSec, 1)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevertNetworkConfiguration reverts the network configuration changes for a specific node.
|
||||
func (c *Client) RevertNetworkConfiguration(ctx context.Context) error {
|
||||
err := c.DoRequest(ctx, http.MethodDelete, c.ExpandPath("network"), nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to revert network configuration for node \"%s\": %w", c.NodeName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateNetworkInterface updates a network interface for a specific node.
|
||||
func (c *Client) UpdateNetworkInterface(
|
||||
ctx context.Context,
|
||||
iface string,
|
||||
d *NetworkInterfaceCreateUpdateRequestBody,
|
||||
) error {
|
||||
err := c.DoRequest(
|
||||
ctx,
|
||||
http.MethodPut,
|
||||
c.ExpandPath(fmt.Sprintf("network/%s", url.PathEscape(iface))),
|
||||
d,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update network interface \"%s\" for node \"%s\": %w",
|
||||
d.Iface, c.NodeName, err,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteNetworkInterface deletes a network interface configuration for a specific node.
|
||||
func (c *Client) DeleteNetworkInterface(ctx context.Context, iface string) error {
|
||||
err := c.DoRequest(
|
||||
ctx,
|
||||
http.MethodDelete,
|
||||
c.ExpandPath(fmt.Sprintf("network/%s", url.PathEscape(iface))),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete network interface \"%s\" for node \"%s\": %w",
|
||||
iface, c.NodeName, err,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
83
proxmox/nodes/network_types.go
Normal file
83
proxmox/nodes/network_types.go
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// NetworkInterfaceListResponseBody contains the body from a node network interface list response.
|
||||
type NetworkInterfaceListResponseBody struct {
|
||||
Data []*NetworkInterfaceListResponseData `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkInterfaceListResponseData contains the data from a node network interface list response.
|
||||
type NetworkInterfaceListResponseData struct {
|
||||
Active *types.CustomBool `json:"active,omitempty"`
|
||||
Address *string `json:"address,omitempty"`
|
||||
Address6 *string `json:"address6,omitempty"`
|
||||
Autostart *types.CustomBool `json:"autostart,omitempty"`
|
||||
BridgeFD *string `json:"bridge_fd,omitempty"`
|
||||
BridgePorts *string `json:"bridge_ports,omitempty"`
|
||||
BridgeSTP *string `json:"bridge_stp,omitempty"`
|
||||
BridgeVIDs *string `json:"bridge_vids,omitempty"`
|
||||
BridgeVLANAware *types.CustomBool `json:"bridge_vlan_aware,omitempty"`
|
||||
CIDR *string `json:"cidr,omitempty"`
|
||||
CIDR6 *string `json:"cidr6,omitempty"`
|
||||
Comments *string `json:"comments,omitempty"`
|
||||
Exists *types.CustomBool `json:"exists,omitempty"`
|
||||
Families *[]string `json:"families,omitempty"`
|
||||
Gateway *string `json:"gateway,omitempty"`
|
||||
Gateway6 *string `json:"gateway6,omitempty"`
|
||||
Iface string `json:"iface"`
|
||||
MethodIPv4 *string `json:"method,omitempty"`
|
||||
MethodIPv6 *string `json:"method6,omitempty"`
|
||||
MTU *string `json:"mtu,omitempty"`
|
||||
Netmask *string `json:"netmask,omitempty"`
|
||||
VLANID *string `json:"vlan-id,omitempty"`
|
||||
VLANRawDevice *string `json:"vlan-raw-device,omitempty"`
|
||||
Priority int `json:"priority"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// NetworkInterfaceCreateUpdateRequestBody contains the body for a node network interface create / update request.
|
||||
type NetworkInterfaceCreateUpdateRequestBody struct {
|
||||
Iface string `json:"iface" url:"iface"`
|
||||
Type string `json:"type" url:"type"`
|
||||
|
||||
Address *string `json:"address,omitempty" url:"address,omitempty"`
|
||||
Address6 *string `json:"address6,omitempty" url:"address6,omitempty"`
|
||||
Autostart *types.CustomBool `json:"autostart,omitempty" url:"autostart,omitempty,int"`
|
||||
BondPrimary *string `json:"bond-primary,omitempty" url:"bond-primary,omitempty"`
|
||||
BondMode *string `json:"bond_mode,omitempty" url:"bond_mode,omitempty"`
|
||||
BondXmitHashPolicy *string `json:"bond_xmit_hash_policy,omitempty" url:"bond_xmit_hash_policy,omitempty"`
|
||||
BridgePorts *string `json:"bridge_ports,omitempty" url:"bridge_ports,omitempty"`
|
||||
BridgeVLANAware *types.CustomBool `json:"bridge_vlan_aware,omitempty" url:"bridge_vlan_aware,omitempty,int"`
|
||||
CIDR *string `json:"cidr,omitempty" url:"cidr,omitempty"`
|
||||
CIDR6 *string `json:"cidr6,omitempty" url:"cidr6,omitempty"`
|
||||
Comments *string `json:"comments,omitempty" url:"comments,omitempty"`
|
||||
Comments6 *string `json:"comments6,omitempty" url:"comments6,omitempty"`
|
||||
Gateway *string `json:"gateway,omitempty" url:"gateway,omitempty"`
|
||||
Gateway6 *string `json:"gateway6,omitempty" url:"gateway6,omitempty"`
|
||||
Delete *[]string `json:"delete,omitempty" url:"delete,omitempty"`
|
||||
MTU *int64 `json:"mtu,omitempty" url:"mtu,omitempty"`
|
||||
Netmask *string `json:"netmask,omitempty" url:"netmask,omitempty"`
|
||||
Netmask6 *string `json:"netmask6,omitempty" url:"netmask6,omitempty"`
|
||||
OVSBonds *string `json:"ovs_bonds,omitempty" url:"ovs_bonds,omitempty"`
|
||||
OVSBridge *string `json:"ovs_bridge,omitempty" url:"ovs_bridge,omitempty"`
|
||||
OVSOptions *string `json:"ovs_options,omitempty" url:"ovs_options,omitempty"`
|
||||
OVSPorts *string `json:"ovs_ports,omitempty" url:"ovs_ports,omitempty"`
|
||||
OVSTag *string `json:"ovs_tag,omitempty" url:"ovs_tag,omitempty"`
|
||||
Slaves *string `json:"slaves,omitempty" url:"slaves,omitempty"`
|
||||
VLANID *int64 `json:"vlan_id,omitempty" url:"vlan_id,omitempty"`
|
||||
VLANRawDevice *string `json:"vlan-raw-device,omitempty" url:"vlan-raw-device,omitempty"`
|
||||
}
|
||||
|
||||
// ReloadNetworkResponseBody contains the body from a node network reload response.
|
||||
type ReloadNetworkResponseBody struct {
|
||||
Data *string `json:"data,omitempty"`
|
||||
}
|
@ -11,72 +11,10 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||
)
|
||||
|
||||
// GetIP retrieves the IP address of a node.
|
||||
func (c *Client) GetIP(ctx context.Context) (string, error) {
|
||||
networkDevices, err := c.ListNetworkDevices(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
nodeAddress := ""
|
||||
|
||||
for _, d := range networkDevices {
|
||||
if d.Address != nil {
|
||||
nodeAddress = *d.Address
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if nodeAddress == "" {
|
||||
return "", fmt.Errorf("failed to determine the IP address of node \"%s\"", c.NodeName)
|
||||
}
|
||||
|
||||
nodeAddressParts := strings.Split(nodeAddress, "/")
|
||||
|
||||
return nodeAddressParts[0], nil
|
||||
}
|
||||
|
||||
// GetTime retrieves the time information for a node.
|
||||
func (c *Client) GetTime(ctx context.Context) (*GetTimeResponseData, error) {
|
||||
resBody := &GetTimeResponseBody{}
|
||||
|
||||
err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("time"), nil, resBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get time information for node \"%s\": %w", c.NodeName, err)
|
||||
}
|
||||
|
||||
if resBody.Data == nil {
|
||||
return nil, api.ErrNoDataObjectInResponse
|
||||
}
|
||||
|
||||
return resBody.Data, nil
|
||||
}
|
||||
|
||||
// ListNetworkDevices retrieves a list of network devices for a specific nodes.
|
||||
func (c *Client) ListNetworkDevices(ctx context.Context) ([]*NetworkDeviceListResponseData, error) {
|
||||
resBody := &NetworkDeviceListResponseBody{}
|
||||
|
||||
err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("network"), nil, resBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network devices for node \"%s\": %w", c.NodeName, err)
|
||||
}
|
||||
|
||||
if resBody.Data == nil {
|
||||
return nil, api.ErrNoDataObjectInResponse
|
||||
}
|
||||
|
||||
sort.Slice(resBody.Data, func(i, j int) bool {
|
||||
return resBody.Data[i].Priority < resBody.Data[j].Priority
|
||||
})
|
||||
|
||||
return resBody.Data, nil
|
||||
}
|
||||
|
||||
// ListNodes retrieves a list of nodes.
|
||||
func (c *Client) ListNodes(ctx context.Context) ([]*ListResponseData, error) {
|
||||
resBody := &ListResponseBody{}
|
||||
@ -97,6 +35,22 @@ func (c *Client) ListNodes(ctx context.Context) ([]*ListResponseData, error) {
|
||||
return resBody.Data, nil
|
||||
}
|
||||
|
||||
// GetTime retrieves the time information for a node.
|
||||
func (c *Client) GetTime(ctx context.Context) (*GetTimeResponseData, error) {
|
||||
resBody := &GetTimeResponseBody{}
|
||||
|
||||
err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("time"), nil, resBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get time information for node \"%s\": %w", c.NodeName, err)
|
||||
}
|
||||
|
||||
if resBody.Data == nil {
|
||||
return nil, api.ErrNoDataObjectInResponse
|
||||
}
|
||||
|
||||
return resBody.Data, nil
|
||||
}
|
||||
|
||||
// UpdateTime updates the time on a node.
|
||||
func (c *Client) UpdateTime(ctx context.Context, d *UpdateTimeRequestBody) error {
|
||||
err := c.DoRequest(ctx, http.MethodPut, c.ExpandPath("time"), d, nil)
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// CustomCommands contains an array of commands to execute.
|
||||
@ -52,31 +52,6 @@ type ListResponseData struct {
|
||||
Uptime *int `json:"uptime"`
|
||||
}
|
||||
|
||||
// NetworkDeviceListResponseBody contains the body from a node network device list response.
|
||||
type NetworkDeviceListResponseBody struct {
|
||||
Data []*NetworkDeviceListResponseData `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkDeviceListResponseData contains the data from a node network device list response.
|
||||
type NetworkDeviceListResponseData struct {
|
||||
Active *types.CustomBool `json:"active,omitempty"`
|
||||
Address *string `json:"address,omitempty"`
|
||||
Autostart *types.CustomBool `json:"autostart,omitempty"`
|
||||
BridgeFD *string `json:"bridge_fd,omitempty"`
|
||||
BridgePorts *string `json:"bridge_ports,omitempty"`
|
||||
BridgeSTP *string `json:"bridge_stp,omitempty"`
|
||||
CIDR *string `json:"cidr,omitempty"`
|
||||
Exists *types.CustomBool `json:"exists,omitempty"`
|
||||
Families *[]string `json:"families,omitempty"`
|
||||
Gateway *string `json:"gateway,omitempty"`
|
||||
Iface string `json:"iface"`
|
||||
MethodIPv4 *string `json:"method,omitempty"`
|
||||
MethodIPv6 *string `json:"method6,omitempty"`
|
||||
Netmask *string `json:"netmask,omitempty"`
|
||||
Priority int `json:"priority"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// UpdateTimeRequestBody contains the body for a node time update request.
|
||||
type UpdateTimeRequestBody struct {
|
||||
TimeZone string `json:"timezone" url:"timezone"`
|
||||
|
@ -7,7 +7,7 @@
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// DatastoreFileListResponseBody contains the body from a datastore content list response.
|
||||
|
@ -39,9 +39,9 @@ func (c *Client) GetTaskStatus(ctx context.Context, upid string) (*GetTaskStatus
|
||||
}
|
||||
|
||||
// WaitForTask waits for a specific task to complete.
|
||||
func (c *Client) WaitForTask(ctx context.Context, upid string, timeout, delay int) error {
|
||||
timeDelay := int64(delay)
|
||||
timeMax := float64(timeout)
|
||||
func (c *Client) WaitForTask(ctx context.Context, upid string, timeoutSec, delaySec int) error {
|
||||
timeDelay := int64(delaySec)
|
||||
timeMax := float64(timeoutSec)
|
||||
timeStart := time.Now()
|
||||
timeElapsed := timeStart.Sub(timeStart)
|
||||
|
||||
@ -80,7 +80,7 @@ func (c *Client) WaitForTask(ctx context.Context, upid string, timeout, delay in
|
||||
}
|
||||
|
||||
return fmt.Errorf(
|
||||
"timeout while waiting for task \"%s\" to complete",
|
||||
"timeoutSec while waiting for task \"%s\" to complete",
|
||||
upid,
|
||||
)
|
||||
}
|
||||
|
@ -15,14 +15,15 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
types2 "github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
)
|
||||
|
||||
// CustomAgent handles QEMU agent parameters.
|
||||
type CustomAgent struct {
|
||||
Enabled *types.CustomBool `json:"enabled,omitempty" url:"enabled,int"`
|
||||
TrimClonedDisks *types.CustomBool `json:"fstrim_cloned_disks" url:"fstrim_cloned_disks,int"`
|
||||
Type *string `json:"type" url:"type"`
|
||||
Enabled *types2.CustomBool `json:"enabled,omitempty" url:"enabled,int"`
|
||||
TrimClonedDisks *types2.CustomBool `json:"fstrim_cloned_disks" url:"fstrim_cloned_disks,int"`
|
||||
Type *string `json:"type" url:"type"`
|
||||
}
|
||||
|
||||
// CustomAudioDevice handles QEMU audio parameters.
|
||||
@ -73,10 +74,10 @@ type CustomCloudInitSSHKeys []string
|
||||
|
||||
// CustomCPUEmulation handles QEMU CPU emulation parameters.
|
||||
type CustomCPUEmulation struct {
|
||||
Flags *[]string `json:"flags,omitempty" url:"flags,omitempty,semicolon"`
|
||||
Hidden *types.CustomBool `json:"hidden,omitempty" url:"hidden,omitempty,int"`
|
||||
HVVendorID *string `json:"hv-vendor-id,omitempty" url:"hv-vendor-id,omitempty"`
|
||||
Type string `json:"cputype,omitempty" url:"cputype,omitempty"`
|
||||
Flags *[]string `json:"flags,omitempty" url:"flags,omitempty,semicolon"`
|
||||
Hidden *types2.CustomBool `json:"hidden,omitempty" url:"hidden,omitempty,int"`
|
||||
HVVendorID *string `json:"hv-vendor-id,omitempty" url:"hv-vendor-id,omitempty"`
|
||||
Type string `json:"cputype,omitempty" url:"cputype,omitempty"`
|
||||
}
|
||||
|
||||
// CustomEFIDisk handles QEMU EFI disk parameters.
|
||||
@ -88,17 +89,17 @@ type CustomEFIDisk struct {
|
||||
|
||||
// CustomNetworkDevice handles QEMU network device parameters.
|
||||
type CustomNetworkDevice struct {
|
||||
Model string `json:"model" url:"model"`
|
||||
Bridge *string `json:"bridge,omitempty" url:"bridge,omitempty"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
Firewall *types.CustomBool `json:"firewall,omitempty" url:"firewall,omitempty,int"`
|
||||
LinkDown *types.CustomBool `json:"link_down,omitempty" url:"link_down,omitempty,int"`
|
||||
MACAddress *string `json:"macaddr,omitempty" url:"macaddr,omitempty"`
|
||||
Queues *int `json:"queues,omitempty" url:"queues,omitempty"`
|
||||
RateLimit *float64 `json:"rate,omitempty" url:"rate,omitempty"`
|
||||
Tag *int `json:"tag,omitempty" url:"tag,omitempty"`
|
||||
MTU *int `json:"mtu,omitempty" url:"mtu,omitempty"`
|
||||
Trunks []int `json:"trunks,omitempty" url:"trunks,omitempty"`
|
||||
Model string `json:"model" url:"model"`
|
||||
Bridge *string `json:"bridge,omitempty" url:"bridge,omitempty"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
Firewall *types2.CustomBool `json:"firewall,omitempty" url:"firewall,omitempty,int"`
|
||||
LinkDown *types2.CustomBool `json:"link_down,omitempty" url:"link_down,omitempty,int"`
|
||||
MACAddress *string `json:"macaddr,omitempty" url:"macaddr,omitempty"`
|
||||
Queues *int `json:"queues,omitempty" url:"queues,omitempty"`
|
||||
RateLimit *float64 `json:"rate,omitempty" url:"rate,omitempty"`
|
||||
Tag *int `json:"tag,omitempty" url:"tag,omitempty"`
|
||||
MTU *int `json:"mtu,omitempty" url:"mtu,omitempty"`
|
||||
Trunks []int `json:"trunks,omitempty" url:"trunks,omitempty"`
|
||||
}
|
||||
|
||||
// CustomNetworkDevices handles QEMU network device parameters.
|
||||
@ -117,12 +118,12 @@ type CustomNUMADevices []CustomNUMADevice
|
||||
|
||||
// CustomPCIDevice handles QEMU host PCI device mapping parameters.
|
||||
type CustomPCIDevice struct {
|
||||
DeviceIDs []string `json:"host" url:"host,semicolon"`
|
||||
MDev *string `json:"mdev,omitempty" url:"mdev,omitempty"`
|
||||
PCIExpress *types.CustomBool `json:"pcie,omitempty" url:"pcie,omitempty,int"`
|
||||
ROMBAR *types.CustomBool `json:"rombar,omitempty" url:"rombar,omitempty,int"`
|
||||
ROMFile *string `json:"romfile,omitempty" url:"romfile,omitempty"`
|
||||
XVGA *types.CustomBool `json:"x-vga,omitempty" url:"x-vga,omitempty,int"`
|
||||
DeviceIDs []string `json:"host" url:"host,semicolon"`
|
||||
MDev *string `json:"mdev,omitempty" url:"mdev,omitempty"`
|
||||
PCIExpress *types2.CustomBool `json:"pcie,omitempty" url:"pcie,omitempty,int"`
|
||||
ROMBAR *types2.CustomBool `json:"rombar,omitempty" url:"rombar,omitempty,int"`
|
||||
ROMFile *string `json:"romfile,omitempty" url:"romfile,omitempty"`
|
||||
XVGA *types2.CustomBool `json:"x-vga,omitempty" url:"x-vga,omitempty,int"`
|
||||
}
|
||||
|
||||
// CustomPCIDevices handles QEMU host PCI device mapping parameters.
|
||||
@ -139,20 +140,20 @@ type CustomSharedMemory struct {
|
||||
|
||||
// CustomSMBIOS handles QEMU SMBIOS parameters.
|
||||
type CustomSMBIOS struct {
|
||||
Base64 *types.CustomBool `json:"base64,omitempty" url:"base64,omitempty"`
|
||||
Family *string `json:"family,omitempty" url:"family,omitempty"`
|
||||
Manufacturer *string `json:"manufacturer,omitempty" url:"manufacturer,omitempty"`
|
||||
Product *string `json:"product,omitempty" url:"product,omitempty"`
|
||||
Serial *string `json:"serial,omitempty" url:"serial,omitempty"`
|
||||
SKU *string `json:"sku,omitempty" url:"sku,omitempty"`
|
||||
UUID *string `json:"uuid,omitempty" url:"uuid,omitempty"`
|
||||
Version *string `json:"version,omitempty" url:"version,omitempty"`
|
||||
Base64 *types2.CustomBool `json:"base64,omitempty" url:"base64,omitempty"`
|
||||
Family *string `json:"family,omitempty" url:"family,omitempty"`
|
||||
Manufacturer *string `json:"manufacturer,omitempty" url:"manufacturer,omitempty"`
|
||||
Product *string `json:"product,omitempty" url:"product,omitempty"`
|
||||
Serial *string `json:"serial,omitempty" url:"serial,omitempty"`
|
||||
SKU *string `json:"sku,omitempty" url:"sku,omitempty"`
|
||||
UUID *string `json:"uuid,omitempty" url:"uuid,omitempty"`
|
||||
Version *string `json:"version,omitempty" url:"version,omitempty"`
|
||||
}
|
||||
|
||||
// CustomSpiceEnhancements handles QEMU spice enhancement parameters.
|
||||
type CustomSpiceEnhancements struct {
|
||||
FolderSharing *types.CustomBool `json:"foldersharing,omitempty" url:"foldersharing,omitempty"`
|
||||
VideoStreaming *string `json:"videostreaming,omitempty" url:"videostreaming,omitempty"`
|
||||
FolderSharing *types2.CustomBool `json:"foldersharing,omitempty" url:"foldersharing,omitempty"`
|
||||
VideoStreaming *string `json:"videostreaming,omitempty" url:"videostreaming,omitempty"`
|
||||
}
|
||||
|
||||
// CustomStartupOrder handles QEMU startup order parameters.
|
||||
@ -164,20 +165,20 @@ type CustomStartupOrder struct {
|
||||
|
||||
// CustomStorageDevice handles QEMU SATA device parameters.
|
||||
type CustomStorageDevice struct {
|
||||
AIO *string `json:"aio,omitempty" url:"aio,omitempty"`
|
||||
BackupEnabled *types.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
||||
BurstableReadSpeedMbps *int `json:"mbps_rd_max,omitempty" url:"mbps_rd_max,omitempty"`
|
||||
BurstableWriteSpeedMbps *int `json:"mbps_wr_max,omitempty" url:"mbps_wr_max,omitempty"`
|
||||
Discard *string `json:"discard,omitempty" url:"discard,omitempty"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
FileVolume string `json:"file" url:"file"`
|
||||
Format *string `json:"format,omitempty" url:"format,omitempty"`
|
||||
IOThread *types.CustomBool `json:"iothread,omitempty" url:"iothread,omitempty,int"`
|
||||
SSD *types.CustomBool `json:"ssd,omitempty" url:"ssd,omitempty,int"`
|
||||
MaxReadSpeedMbps *int `json:"mbps_rd,omitempty" url:"mbps_rd,omitempty"`
|
||||
MaxWriteSpeedMbps *int `json:"mbps_wr,omitempty" url:"mbps_wr,omitempty"`
|
||||
Media *string `json:"media,omitempty" url:"media,omitempty"`
|
||||
Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
|
||||
AIO *string `json:"aio,omitempty" url:"aio,omitempty"`
|
||||
BackupEnabled *types2.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
||||
BurstableReadSpeedMbps *int `json:"mbps_rd_max,omitempty" url:"mbps_rd_max,omitempty"`
|
||||
BurstableWriteSpeedMbps *int `json:"mbps_wr_max,omitempty" url:"mbps_wr_max,omitempty"`
|
||||
Discard *string `json:"discard,omitempty" url:"discard,omitempty"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
FileVolume string `json:"file" url:"file"`
|
||||
Format *string `json:"format,omitempty" url:"format,omitempty"`
|
||||
IOThread *types2.CustomBool `json:"iothread,omitempty" url:"iothread,omitempty,int"`
|
||||
SSD *types2.CustomBool `json:"ssd,omitempty" url:"ssd,omitempty,int"`
|
||||
MaxReadSpeedMbps *int `json:"mbps_rd,omitempty" url:"mbps_rd,omitempty"`
|
||||
MaxWriteSpeedMbps *int `json:"mbps_wr,omitempty" url:"mbps_wr,omitempty"`
|
||||
Media *string `json:"media,omitempty" url:"media,omitempty"`
|
||||
Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
|
||||
Interface *string
|
||||
ID *string
|
||||
FileID *string
|
||||
@ -189,8 +190,8 @@ type CustomStorageDevices map[string]CustomStorageDevice
|
||||
|
||||
// CustomUSBDevice handles QEMU USB device parameters.
|
||||
type CustomUSBDevice struct {
|
||||
HostDevice string `json:"host" url:"host"`
|
||||
USB3 *types.CustomBool `json:"usb3,omitempty" url:"usb3,omitempty,int"`
|
||||
HostDevice string `json:"host" url:"host"`
|
||||
USB3 *types2.CustomBool `json:"usb3,omitempty" url:"usb3,omitempty,int"`
|
||||
}
|
||||
|
||||
// CustomUSBDevices handles QEMU USB device parameters.
|
||||
@ -204,10 +205,10 @@ type CustomVGADevice struct {
|
||||
|
||||
// CustomVirtualIODevice handles QEMU VirtIO device parameters.
|
||||
type CustomVirtualIODevice struct {
|
||||
AIO *string `json:"aio,omitempty" url:"aio,omitempty"`
|
||||
BackupEnabled *types.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
FileVolume string `json:"file" url:"file"`
|
||||
AIO *string `json:"aio,omitempty" url:"aio,omitempty"`
|
||||
BackupEnabled *types2.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
||||
Enabled bool `json:"-" url:"-"`
|
||||
FileVolume string `json:"file" url:"file"`
|
||||
}
|
||||
|
||||
// CustomVirtualIODevices handles QEMU VirtIO device parameters.
|
||||
@ -221,89 +222,89 @@ type CustomWatchdogDevice struct {
|
||||
|
||||
// CloneRequestBody contains the data for an virtual machine clone request.
|
||||
type CloneRequestBody struct {
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
Description *string `json:"description,omitempty" url:"description,omitempty"`
|
||||
FullCopy *types.CustomBool `json:"full,omitempty" url:"full,omitempty,int"`
|
||||
Name *string `json:"name,omitempty" url:"name,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
SnapshotName *string `json:"snapname,omitempty" url:"snapname,omitempty"`
|
||||
TargetNodeName *string `json:"target,omitempty" url:"target,omitempty"`
|
||||
TargetStorage *string `json:"storage,omitempty" url:"storage,omitempty"`
|
||||
TargetStorageFormat *string `json:"format,omitempty" url:"format,omitempty"`
|
||||
VMIDNew int `json:"newid" url:"newid"`
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
Description *string `json:"description,omitempty" url:"description,omitempty"`
|
||||
FullCopy *types2.CustomBool `json:"full,omitempty" url:"full,omitempty,int"`
|
||||
Name *string `json:"name,omitempty" url:"name,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
SnapshotName *string `json:"snapname,omitempty" url:"snapname,omitempty"`
|
||||
TargetNodeName *string `json:"target,omitempty" url:"target,omitempty"`
|
||||
TargetStorage *string `json:"storage,omitempty" url:"storage,omitempty"`
|
||||
TargetStorageFormat *string `json:"format,omitempty" url:"format,omitempty"`
|
||||
VMIDNew int `json:"newid" url:"newid"`
|
||||
}
|
||||
|
||||
// CreateRequestBody contains the data for a virtual machine create request.
|
||||
type CreateRequestBody struct {
|
||||
ACPI *types.CustomBool `json:"acpi,omitempty" url:"acpi,omitempty,int"`
|
||||
Agent *CustomAgent `json:"agent,omitempty" url:"agent,omitempty"`
|
||||
AllowReboot *types.CustomBool `json:"reboot,omitempty" url:"reboot,omitempty,int"`
|
||||
AudioDevices CustomAudioDevices `json:"audio,omitempty" url:"audio,omitempty"`
|
||||
Autostart *types.CustomBool `json:"autostart,omitempty" url:"autostart,omitempty,int"`
|
||||
BackupFile *string `json:"archive,omitempty" url:"archive,omitempty"`
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
BIOS *string `json:"bios,omitempty" url:"bios,omitempty"`
|
||||
Boot *CustomBoot `json:"boot,omitempty" url:"boot,omitempty"`
|
||||
CDROM *string `json:"cdrom,omitempty" url:"cdrom,omitempty"`
|
||||
CloudInitConfig *CustomCloudInitConfig `json:"cloudinit,omitempty" url:"cloudinit,omitempty"`
|
||||
CPUArchitecture *string `json:"arch,omitempty" url:"arch,omitempty"`
|
||||
CPUCores *int `json:"cores,omitempty" url:"cores,omitempty"`
|
||||
CPUEmulation *CustomCPUEmulation `json:"cpu,omitempty" url:"cpu,omitempty"`
|
||||
CPULimit *int `json:"cpulimit,omitempty" url:"cpulimit,omitempty"`
|
||||
CPUSockets *int `json:"sockets,omitempty" url:"sockets,omitempty"`
|
||||
CPUUnits *int `json:"cpuunits,omitempty" url:"cpuunits,omitempty"`
|
||||
DedicatedMemory *int `json:"memory,omitempty" url:"memory,omitempty"`
|
||||
Delete []string `json:"delete,omitempty" url:"delete,omitempty,comma"`
|
||||
DeletionProtection *types.CustomBool `json:"protection,omitempty" url:"force,omitempty,int"`
|
||||
Description *string `json:"description,omitempty" url:"description,omitempty"`
|
||||
EFIDisk *CustomEFIDisk `json:"efidisk0,omitempty" url:"efidisk0,omitempty"`
|
||||
FloatingMemory *int `json:"balloon,omitempty" url:"balloon,omitempty"`
|
||||
FloatingMemoryShares *int `json:"shares,omitempty" url:"shares,omitempty"`
|
||||
Freeze *types.CustomBool `json:"freeze,omitempty" url:"freeze,omitempty,int"`
|
||||
HookScript *string `json:"hookscript,omitempty" url:"hookscript,omitempty"`
|
||||
Hotplug types.CustomCommaSeparatedList `json:"hotplug,omitempty" url:"hotplug,omitempty,comma"`
|
||||
Hugepages *string `json:"hugepages,omitempty" url:"hugepages,omitempty"`
|
||||
IDEDevices CustomStorageDevices `json:"ide,omitempty" url:",omitempty"`
|
||||
KeyboardLayout *string `json:"keyboard,omitempty" url:"keyboard,omitempty"`
|
||||
KVMArguments *string `json:"args,omitempty" url:"args,omitempty,space"`
|
||||
KVMEnabled *types.CustomBool `json:"kvm,omitempty" url:"kvm,omitempty,int"`
|
||||
LocalTime *types.CustomBool `json:"localtime,omitempty" url:"localtime,omitempty,int"`
|
||||
Lock *string `json:"lock,omitempty" url:"lock,omitempty"`
|
||||
Machine *string `json:"machine,omitempty" url:"machine,omitempty"`
|
||||
MigrateDowntime *float64 `json:"migrate_downtime,omitempty" url:"migrate_downtime,omitempty"`
|
||||
MigrateSpeed *int `json:"migrate_speed,omitempty" url:"migrate_speed,omitempty"`
|
||||
Name *string `json:"name,omitempty" url:"name,omitempty"`
|
||||
NetworkDevices CustomNetworkDevices `json:"net,omitempty" url:"net,omitempty"`
|
||||
NUMADevices CustomNUMADevices `json:"numa_devices,omitempty" url:"numa,omitempty"`
|
||||
NUMAEnabled *types.CustomBool `json:"numa,omitempty" url:"numa,omitempty,int"`
|
||||
OSType *string `json:"ostype,omitempty" url:"ostype,omitempty"`
|
||||
Overwrite *types.CustomBool `json:"force,omitempty" url:"force,omitempty,int"`
|
||||
PCIDevices CustomPCIDevices `json:"hostpci,omitempty" url:"hostpci,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
Revert *string `json:"revert,omitempty" url:"revert,omitempty"`
|
||||
SATADevices CustomStorageDevices `json:"sata,omitempty" url:"sata,omitempty"`
|
||||
SCSIDevices CustomStorageDevices `json:"scsi,omitempty" url:"scsi,omitempty"`
|
||||
SCSIHardware *string `json:"scsihw,omitempty" url:"scsihw,omitempty"`
|
||||
SerialDevices CustomSerialDevices `json:"serial,omitempty" url:"serial,omitempty"`
|
||||
SharedMemory *CustomSharedMemory `json:"ivshmem,omitempty" url:"ivshmem,omitempty"`
|
||||
SkipLock *types.CustomBool `json:"skiplock,omitempty" url:"skiplock,omitempty,int"`
|
||||
SMBIOS *CustomSMBIOS `json:"smbios1,omitempty" url:"smbios1,omitempty"`
|
||||
SpiceEnhancements *CustomSpiceEnhancements `json:"spice_enhancements,omitempty" url:"spice_enhancements,omitempty"`
|
||||
StartDate *string `json:"startdate,omitempty" url:"startdate,omitempty"`
|
||||
StartOnBoot *types.CustomBool `json:"onboot,omitempty" url:"onboot,omitempty,int"`
|
||||
StartupOrder *CustomStartupOrder `json:"startup,omitempty" url:"startup,omitempty"`
|
||||
TabletDeviceEnabled *types.CustomBool `json:"tablet,omitempty" url:"tablet,omitempty,int"`
|
||||
Tags *string `json:"tags,omitempty" url:"tags,omitempty"`
|
||||
Template *types.CustomBool `json:"template,omitempty" url:"template,omitempty,int"`
|
||||
TimeDriftFixEnabled *types.CustomBool `json:"tdf,omitempty" url:"tdf,omitempty,int"`
|
||||
USBDevices CustomUSBDevices `json:"usb,omitempty" url:"usb,omitempty"`
|
||||
VGADevice *CustomVGADevice `json:"vga,omitempty" url:"vga,omitempty"`
|
||||
VirtualCPUCount *int `json:"vcpus,omitempty" url:"vcpus,omitempty"`
|
||||
VirtualIODevices CustomStorageDevices `json:"virtio,omitempty" url:"virtio,omitempty"`
|
||||
VMGenerationID *string `json:"vmgenid,omitempty" url:"vmgenid,omitempty"`
|
||||
VMID *int `json:"vmid,omitempty" url:"vmid,omitempty"`
|
||||
VMStateDatastoreID *string `json:"vmstatestorage,omitempty" url:"vmstatestorage,omitempty"`
|
||||
WatchdogDevice *CustomWatchdogDevice `json:"watchdog,omitempty" url:"watchdog,omitempty"`
|
||||
ACPI *types2.CustomBool `json:"acpi,omitempty" url:"acpi,omitempty,int"`
|
||||
Agent *CustomAgent `json:"agent,omitempty" url:"agent,omitempty"`
|
||||
AllowReboot *types2.CustomBool `json:"reboot,omitempty" url:"reboot,omitempty,int"`
|
||||
AudioDevices CustomAudioDevices `json:"audio,omitempty" url:"audio,omitempty"`
|
||||
Autostart *types2.CustomBool `json:"autostart,omitempty" url:"autostart,omitempty,int"`
|
||||
BackupFile *string `json:"archive,omitempty" url:"archive,omitempty"`
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
BIOS *string `json:"bios,omitempty" url:"bios,omitempty"`
|
||||
Boot *CustomBoot `json:"boot,omitempty" url:"boot,omitempty"`
|
||||
CDROM *string `json:"cdrom,omitempty" url:"cdrom,omitempty"`
|
||||
CloudInitConfig *CustomCloudInitConfig `json:"cloudinit,omitempty" url:"cloudinit,omitempty"`
|
||||
CPUArchitecture *string `json:"arch,omitempty" url:"arch,omitempty"`
|
||||
CPUCores *int `json:"cores,omitempty" url:"cores,omitempty"`
|
||||
CPUEmulation *CustomCPUEmulation `json:"cpu,omitempty" url:"cpu,omitempty"`
|
||||
CPULimit *int `json:"cpulimit,omitempty" url:"cpulimit,omitempty"`
|
||||
CPUSockets *int `json:"sockets,omitempty" url:"sockets,omitempty"`
|
||||
CPUUnits *int `json:"cpuunits,omitempty" url:"cpuunits,omitempty"`
|
||||
DedicatedMemory *int `json:"memory,omitempty" url:"memory,omitempty"`
|
||||
Delete []string `json:"delete,omitempty" url:"delete,omitempty,comma"`
|
||||
DeletionProtection *types2.CustomBool `json:"protection,omitempty" url:"force,omitempty,int"`
|
||||
Description *string `json:"description,omitempty" url:"description,omitempty"`
|
||||
EFIDisk *CustomEFIDisk `json:"efidisk0,omitempty" url:"efidisk0,omitempty"`
|
||||
FloatingMemory *int `json:"balloon,omitempty" url:"balloon,omitempty"`
|
||||
FloatingMemoryShares *int `json:"shares,omitempty" url:"shares,omitempty"`
|
||||
Freeze *types2.CustomBool `json:"freeze,omitempty" url:"freeze,omitempty,int"`
|
||||
HookScript *string `json:"hookscript,omitempty" url:"hookscript,omitempty"`
|
||||
Hotplug types2.CustomCommaSeparatedList `json:"hotplug,omitempty" url:"hotplug,omitempty,comma"`
|
||||
Hugepages *string `json:"hugepages,omitempty" url:"hugepages,omitempty"`
|
||||
IDEDevices CustomStorageDevices `json:"ide,omitempty" url:",omitempty"`
|
||||
KeyboardLayout *string `json:"keyboard,omitempty" url:"keyboard,omitempty"`
|
||||
KVMArguments *string `json:"args,omitempty" url:"args,omitempty,space"`
|
||||
KVMEnabled *types2.CustomBool `json:"kvm,omitempty" url:"kvm,omitempty,int"`
|
||||
LocalTime *types2.CustomBool `json:"localtime,omitempty" url:"localtime,omitempty,int"`
|
||||
Lock *string `json:"lock,omitempty" url:"lock,omitempty"`
|
||||
Machine *string `json:"machine,omitempty" url:"machine,omitempty"`
|
||||
MigrateDowntime *float64 `json:"migrate_downtime,omitempty" url:"migrate_downtime,omitempty"`
|
||||
MigrateSpeed *int `json:"migrate_speed,omitempty" url:"migrate_speed,omitempty"`
|
||||
Name *string `json:"name,omitempty" url:"name,omitempty"`
|
||||
NetworkDevices CustomNetworkDevices `json:"net,omitempty" url:"net,omitempty"`
|
||||
NUMADevices CustomNUMADevices `json:"numa_devices,omitempty" url:"numa,omitempty"`
|
||||
NUMAEnabled *types2.CustomBool `json:"numa,omitempty" url:"numa,omitempty,int"`
|
||||
OSType *string `json:"ostype,omitempty" url:"ostype,omitempty"`
|
||||
Overwrite *types2.CustomBool `json:"force,omitempty" url:"force,omitempty,int"`
|
||||
PCIDevices CustomPCIDevices `json:"hostpci,omitempty" url:"hostpci,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
Revert *string `json:"revert,omitempty" url:"revert,omitempty"`
|
||||
SATADevices CustomStorageDevices `json:"sata,omitempty" url:"sata,omitempty"`
|
||||
SCSIDevices CustomStorageDevices `json:"scsi,omitempty" url:"scsi,omitempty"`
|
||||
SCSIHardware *string `json:"scsihw,omitempty" url:"scsihw,omitempty"`
|
||||
SerialDevices CustomSerialDevices `json:"serial,omitempty" url:"serial,omitempty"`
|
||||
SharedMemory *CustomSharedMemory `json:"ivshmem,omitempty" url:"ivshmem,omitempty"`
|
||||
SkipLock *types2.CustomBool `json:"skiplock,omitempty" url:"skiplock,omitempty,int"`
|
||||
SMBIOS *CustomSMBIOS `json:"smbios1,omitempty" url:"smbios1,omitempty"`
|
||||
SpiceEnhancements *CustomSpiceEnhancements `json:"spice_enhancements,omitempty" url:"spice_enhancements,omitempty"`
|
||||
StartDate *string `json:"startdate,omitempty" url:"startdate,omitempty"`
|
||||
StartOnBoot *types2.CustomBool `json:"onboot,omitempty" url:"onboot,omitempty,int"`
|
||||
StartupOrder *CustomStartupOrder `json:"startup,omitempty" url:"startup,omitempty"`
|
||||
TabletDeviceEnabled *types2.CustomBool `json:"tablet,omitempty" url:"tablet,omitempty,int"`
|
||||
Tags *string `json:"tags,omitempty" url:"tags,omitempty"`
|
||||
Template *types2.CustomBool `json:"template,omitempty" url:"template,omitempty,int"`
|
||||
TimeDriftFixEnabled *types2.CustomBool `json:"tdf,omitempty" url:"tdf,omitempty,int"`
|
||||
USBDevices CustomUSBDevices `json:"usb,omitempty" url:"usb,omitempty"`
|
||||
VGADevice *CustomVGADevice `json:"vga,omitempty" url:"vga,omitempty"`
|
||||
VirtualCPUCount *int `json:"vcpus,omitempty" url:"vcpus,omitempty"`
|
||||
VirtualIODevices CustomStorageDevices `json:"virtio,omitempty" url:"virtio,omitempty"`
|
||||
VMGenerationID *string `json:"vmgenid,omitempty" url:"vmgenid,omitempty"`
|
||||
VMID *int `json:"vmid,omitempty" url:"vmid,omitempty"`
|
||||
VMStateDatastoreID *string `json:"vmstatestorage,omitempty" url:"vmstatestorage,omitempty"`
|
||||
WatchdogDevice *CustomWatchdogDevice `json:"watchdog,omitempty" url:"watchdog,omitempty"`
|
||||
}
|
||||
|
||||
// CreateResponseBody contains the body from a create response.
|
||||
@ -355,137 +356,137 @@ type GetResponseBody struct {
|
||||
|
||||
// GetResponseData contains the data from an virtual machine get response.
|
||||
type GetResponseData struct {
|
||||
ACPI *types.CustomBool `json:"acpi,omitempty"`
|
||||
Agent *CustomAgent `json:"agent,omitempty"`
|
||||
AllowReboot *types.CustomBool `json:"reboot,omitempty"`
|
||||
AudioDevice *CustomAudioDevice `json:"audio0,omitempty"`
|
||||
Autostart *types.CustomBool `json:"autostart,omitempty"`
|
||||
BackupFile *string `json:"archive,omitempty"`
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty"`
|
||||
BIOS *string `json:"bios,omitempty"`
|
||||
BootDisk *string `json:"bootdisk,omitempty"`
|
||||
BootOrder *string `json:"boot,omitempty"`
|
||||
CDROM *string `json:"cdrom,omitempty"`
|
||||
CloudInitDNSDomain *string `json:"searchdomain,omitempty"`
|
||||
CloudInitDNSServer *string `json:"nameserver,omitempty"`
|
||||
CloudInitFiles *CustomCloudInitFiles `json:"cicustom,omitempty"`
|
||||
CloudInitPassword *string `json:"cipassword,omitempty"`
|
||||
CloudInitSSHKeys *CustomCloudInitSSHKeys `json:"sshkeys,omitempty"`
|
||||
CloudInitType *string `json:"citype,omitempty"`
|
||||
CloudInitUsername *string `json:"ciuser,omitempty"`
|
||||
CPUArchitecture *string `json:"arch,omitempty"`
|
||||
CPUCores *int `json:"cores,omitempty"`
|
||||
CPUEmulation *CustomCPUEmulation `json:"cpu,omitempty"`
|
||||
CPULimit *int `json:"cpulimit,omitempty"`
|
||||
CPUSockets *int `json:"sockets,omitempty"`
|
||||
CPUUnits *int `json:"cpuunits,omitempty"`
|
||||
DedicatedMemory *int `json:"memory,omitempty"`
|
||||
DeletionProtection *types.CustomBool `json:"protection,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
EFIDisk *CustomEFIDisk `json:"efidisk0,omitempty"`
|
||||
FloatingMemory *int `json:"balloon,omitempty"`
|
||||
FloatingMemoryShares *int `json:"shares,omitempty"`
|
||||
Freeze *types.CustomBool `json:"freeze,omitempty"`
|
||||
HookScript *string `json:"hookscript,omitempty"`
|
||||
Hotplug *types.CustomCommaSeparatedList `json:"hotplug,omitempty"`
|
||||
Hugepages *string `json:"hugepages,omitempty"`
|
||||
IDEDevice0 *CustomStorageDevice `json:"ide0,omitempty"`
|
||||
IDEDevice1 *CustomStorageDevice `json:"ide1,omitempty"`
|
||||
IDEDevice2 *CustomStorageDevice `json:"ide2,omitempty"`
|
||||
IDEDevice3 *CustomStorageDevice `json:"ide3,omitempty"`
|
||||
IPConfig0 *CustomCloudInitIPConfig `json:"ipconfig0,omitempty"`
|
||||
IPConfig1 *CustomCloudInitIPConfig `json:"ipconfig1,omitempty"`
|
||||
IPConfig2 *CustomCloudInitIPConfig `json:"ipconfig2,omitempty"`
|
||||
IPConfig3 *CustomCloudInitIPConfig `json:"ipconfig3,omitempty"`
|
||||
IPConfig4 *CustomCloudInitIPConfig `json:"ipconfig4,omitempty"`
|
||||
IPConfig5 *CustomCloudInitIPConfig `json:"ipconfig5,omitempty"`
|
||||
IPConfig6 *CustomCloudInitIPConfig `json:"ipconfig6,omitempty"`
|
||||
IPConfig7 *CustomCloudInitIPConfig `json:"ipconfig7,omitempty"`
|
||||
KeyboardLayout *string `json:"keyboard,omitempty"`
|
||||
KVMArguments *string `json:"args,omitempty"`
|
||||
KVMEnabled *types.CustomBool `json:"kvm,omitempty"`
|
||||
LocalTime *types.CustomBool `json:"localtime,omitempty"`
|
||||
Lock *string `json:"lock,omitempty"`
|
||||
Machine *string `json:"machine,omitempty"`
|
||||
MigrateDowntime *float64 `json:"migrate_downtime,omitempty"`
|
||||
MigrateSpeed *int `json:"migrate_speed,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
NetworkDevice0 *CustomNetworkDevice `json:"net0,omitempty"`
|
||||
NetworkDevice1 *CustomNetworkDevice `json:"net1,omitempty"`
|
||||
NetworkDevice2 *CustomNetworkDevice `json:"net2,omitempty"`
|
||||
NetworkDevice3 *CustomNetworkDevice `json:"net3,omitempty"`
|
||||
NetworkDevice4 *CustomNetworkDevice `json:"net4,omitempty"`
|
||||
NetworkDevice5 *CustomNetworkDevice `json:"net5,omitempty"`
|
||||
NetworkDevice6 *CustomNetworkDevice `json:"net6,omitempty"`
|
||||
NetworkDevice7 *CustomNetworkDevice `json:"net7,omitempty"`
|
||||
NUMADevices *CustomNUMADevices `json:"numa_devices,omitempty"`
|
||||
NUMAEnabled *types.CustomBool `json:"numa,omitempty"`
|
||||
OSType *string `json:"ostype,omitempty"`
|
||||
Overwrite *types.CustomBool `json:"force,omitempty"`
|
||||
PCIDevice0 *CustomPCIDevice `json:"hostpci0,omitempty"`
|
||||
PCIDevice1 *CustomPCIDevice `json:"hostpci1,omitempty"`
|
||||
PCIDevice2 *CustomPCIDevice `json:"hostpci2,omitempty"`
|
||||
PCIDevice3 *CustomPCIDevice `json:"hostpci3,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
Revert *string `json:"revert,omitempty"`
|
||||
SATADevice0 *CustomStorageDevice `json:"sata0,omitempty"`
|
||||
SATADevice1 *CustomStorageDevice `json:"sata1,omitempty"`
|
||||
SATADevice2 *CustomStorageDevice `json:"sata2,omitempty"`
|
||||
SATADevice3 *CustomStorageDevice `json:"sata3,omitempty"`
|
||||
SATADevice4 *CustomStorageDevice `json:"sata4,omitempty"`
|
||||
SATADevice5 *CustomStorageDevice `json:"sata5,omitempty"`
|
||||
SCSIDevice0 *CustomStorageDevice `json:"scsi0,omitempty"`
|
||||
SCSIDevice1 *CustomStorageDevice `json:"scsi1,omitempty"`
|
||||
SCSIDevice2 *CustomStorageDevice `json:"scsi2,omitempty"`
|
||||
SCSIDevice3 *CustomStorageDevice `json:"scsi3,omitempty"`
|
||||
SCSIDevice4 *CustomStorageDevice `json:"scsi4,omitempty"`
|
||||
SCSIDevice5 *CustomStorageDevice `json:"scsi5,omitempty"`
|
||||
SCSIDevice6 *CustomStorageDevice `json:"scsi6,omitempty"`
|
||||
SCSIDevice7 *CustomStorageDevice `json:"scsi7,omitempty"`
|
||||
SCSIDevice8 *CustomStorageDevice `json:"scsi8,omitempty"`
|
||||
SCSIDevice9 *CustomStorageDevice `json:"scsi9,omitempty"`
|
||||
SCSIDevice10 *CustomStorageDevice `json:"scsi10,omitempty"`
|
||||
SCSIDevice11 *CustomStorageDevice `json:"scsi11,omitempty"`
|
||||
SCSIDevice12 *CustomStorageDevice `json:"scsi12,omitempty"`
|
||||
SCSIDevice13 *CustomStorageDevice `json:"scsi13,omitempty"`
|
||||
SCSIHardware *string `json:"scsihw,omitempty"`
|
||||
SerialDevice0 *string `json:"serial0,omitempty"`
|
||||
SerialDevice1 *string `json:"serial1,omitempty"`
|
||||
SerialDevice2 *string `json:"serial2,omitempty"`
|
||||
SerialDevice3 *string `json:"serial3,omitempty"`
|
||||
SharedMemory *CustomSharedMemory `json:"ivshmem,omitempty"`
|
||||
SkipLock *types.CustomBool `json:"skiplock,omitempty"`
|
||||
SMBIOS *CustomSMBIOS `json:"smbios1,omitempty"`
|
||||
SpiceEnhancements *CustomSpiceEnhancements `json:"spice_enhancements,omitempty"`
|
||||
StartDate *string `json:"startdate,omitempty"`
|
||||
StartOnBoot *types.CustomBool `json:"onboot,omitempty"`
|
||||
StartupOrder *CustomStartupOrder `json:"startup,omitempty"`
|
||||
TabletDeviceEnabled *types.CustomBool `json:"tablet,omitempty"`
|
||||
Tags *string `json:"tags,omitempty"`
|
||||
Template *types.CustomBool `json:"template,omitempty"`
|
||||
TimeDriftFixEnabled *types.CustomBool `json:"tdf,omitempty"`
|
||||
USBDevices *CustomUSBDevices `json:"usb,omitempty"`
|
||||
VGADevice *CustomVGADevice `json:"vga,omitempty"`
|
||||
VirtualCPUCount *int `json:"vcpus,omitempty"`
|
||||
VirtualIODevice0 *CustomStorageDevice `json:"virtio0,omitempty"`
|
||||
VirtualIODevice1 *CustomStorageDevice `json:"virtio1,omitempty"`
|
||||
VirtualIODevice2 *CustomStorageDevice `json:"virtio2,omitempty"`
|
||||
VirtualIODevice3 *CustomStorageDevice `json:"virtio3,omitempty"`
|
||||
VirtualIODevice4 *CustomStorageDevice `json:"virtio4,omitempty"`
|
||||
VirtualIODevice5 *CustomStorageDevice `json:"virtio5,omitempty"`
|
||||
VirtualIODevice6 *CustomStorageDevice `json:"virtio6,omitempty"`
|
||||
VirtualIODevice7 *CustomStorageDevice `json:"virtio7,omitempty"`
|
||||
VirtualIODevice8 *CustomStorageDevice `json:"virtio8,omitempty"`
|
||||
VirtualIODevice9 *CustomStorageDevice `json:"virtio9,omitempty"`
|
||||
VirtualIODevice10 *CustomStorageDevice `json:"virtio10,omitempty"`
|
||||
VirtualIODevice11 *CustomStorageDevice `json:"virtio11,omitempty"`
|
||||
VirtualIODevice12 *CustomStorageDevice `json:"virtio12,omitempty"`
|
||||
VirtualIODevice13 *CustomStorageDevice `json:"virtio13,omitempty"`
|
||||
VirtualIODevice14 *CustomStorageDevice `json:"virtio14,omitempty"`
|
||||
VirtualIODevice15 *CustomStorageDevice `json:"virtio15,omitempty"`
|
||||
VMGenerationID *string `json:"vmgenid,omitempty"`
|
||||
VMStateDatastoreID *string `json:"vmstatestorage,omitempty"`
|
||||
WatchdogDevice *CustomWatchdogDevice `json:"watchdog,omitempty"`
|
||||
ACPI *types2.CustomBool `json:"acpi,omitempty"`
|
||||
Agent *CustomAgent `json:"agent,omitempty"`
|
||||
AllowReboot *types2.CustomBool `json:"reboot,omitempty"`
|
||||
AudioDevice *CustomAudioDevice `json:"audio0,omitempty"`
|
||||
Autostart *types2.CustomBool `json:"autostart,omitempty"`
|
||||
BackupFile *string `json:"archive,omitempty"`
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty"`
|
||||
BIOS *string `json:"bios,omitempty"`
|
||||
BootDisk *string `json:"bootdisk,omitempty"`
|
||||
BootOrder *string `json:"boot,omitempty"`
|
||||
CDROM *string `json:"cdrom,omitempty"`
|
||||
CloudInitDNSDomain *string `json:"searchdomain,omitempty"`
|
||||
CloudInitDNSServer *string `json:"nameserver,omitempty"`
|
||||
CloudInitFiles *CustomCloudInitFiles `json:"cicustom,omitempty"`
|
||||
CloudInitPassword *string `json:"cipassword,omitempty"`
|
||||
CloudInitSSHKeys *CustomCloudInitSSHKeys `json:"sshkeys,omitempty"`
|
||||
CloudInitType *string `json:"citype,omitempty"`
|
||||
CloudInitUsername *string `json:"ciuser,omitempty"`
|
||||
CPUArchitecture *string `json:"arch,omitempty"`
|
||||
CPUCores *int `json:"cores,omitempty"`
|
||||
CPUEmulation *CustomCPUEmulation `json:"cpu,omitempty"`
|
||||
CPULimit *int `json:"cpulimit,omitempty"`
|
||||
CPUSockets *int `json:"sockets,omitempty"`
|
||||
CPUUnits *int `json:"cpuunits,omitempty"`
|
||||
DedicatedMemory *int `json:"memory,omitempty"`
|
||||
DeletionProtection *types2.CustomBool `json:"protection,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
EFIDisk *CustomEFIDisk `json:"efidisk0,omitempty"`
|
||||
FloatingMemory *int `json:"balloon,omitempty"`
|
||||
FloatingMemoryShares *int `json:"shares,omitempty"`
|
||||
Freeze *types2.CustomBool `json:"freeze,omitempty"`
|
||||
HookScript *string `json:"hookscript,omitempty"`
|
||||
Hotplug *types2.CustomCommaSeparatedList `json:"hotplug,omitempty"`
|
||||
Hugepages *string `json:"hugepages,omitempty"`
|
||||
IDEDevice0 *CustomStorageDevice `json:"ide0,omitempty"`
|
||||
IDEDevice1 *CustomStorageDevice `json:"ide1,omitempty"`
|
||||
IDEDevice2 *CustomStorageDevice `json:"ide2,omitempty"`
|
||||
IDEDevice3 *CustomStorageDevice `json:"ide3,omitempty"`
|
||||
IPConfig0 *CustomCloudInitIPConfig `json:"ipconfig0,omitempty"`
|
||||
IPConfig1 *CustomCloudInitIPConfig `json:"ipconfig1,omitempty"`
|
||||
IPConfig2 *CustomCloudInitIPConfig `json:"ipconfig2,omitempty"`
|
||||
IPConfig3 *CustomCloudInitIPConfig `json:"ipconfig3,omitempty"`
|
||||
IPConfig4 *CustomCloudInitIPConfig `json:"ipconfig4,omitempty"`
|
||||
IPConfig5 *CustomCloudInitIPConfig `json:"ipconfig5,omitempty"`
|
||||
IPConfig6 *CustomCloudInitIPConfig `json:"ipconfig6,omitempty"`
|
||||
IPConfig7 *CustomCloudInitIPConfig `json:"ipconfig7,omitempty"`
|
||||
KeyboardLayout *string `json:"keyboard,omitempty"`
|
||||
KVMArguments *string `json:"args,omitempty"`
|
||||
KVMEnabled *types2.CustomBool `json:"kvm,omitempty"`
|
||||
LocalTime *types2.CustomBool `json:"localtime,omitempty"`
|
||||
Lock *string `json:"lock,omitempty"`
|
||||
Machine *string `json:"machine,omitempty"`
|
||||
MigrateDowntime *float64 `json:"migrate_downtime,omitempty"`
|
||||
MigrateSpeed *int `json:"migrate_speed,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
NetworkDevice0 *CustomNetworkDevice `json:"net0,omitempty"`
|
||||
NetworkDevice1 *CustomNetworkDevice `json:"net1,omitempty"`
|
||||
NetworkDevice2 *CustomNetworkDevice `json:"net2,omitempty"`
|
||||
NetworkDevice3 *CustomNetworkDevice `json:"net3,omitempty"`
|
||||
NetworkDevice4 *CustomNetworkDevice `json:"net4,omitempty"`
|
||||
NetworkDevice5 *CustomNetworkDevice `json:"net5,omitempty"`
|
||||
NetworkDevice6 *CustomNetworkDevice `json:"net6,omitempty"`
|
||||
NetworkDevice7 *CustomNetworkDevice `json:"net7,omitempty"`
|
||||
NUMADevices *CustomNUMADevices `json:"numa_devices,omitempty"`
|
||||
NUMAEnabled *types2.CustomBool `json:"numa,omitempty"`
|
||||
OSType *string `json:"ostype,omitempty"`
|
||||
Overwrite *types2.CustomBool `json:"force,omitempty"`
|
||||
PCIDevice0 *CustomPCIDevice `json:"hostpci0,omitempty"`
|
||||
PCIDevice1 *CustomPCIDevice `json:"hostpci1,omitempty"`
|
||||
PCIDevice2 *CustomPCIDevice `json:"hostpci2,omitempty"`
|
||||
PCIDevice3 *CustomPCIDevice `json:"hostpci3,omitempty"`
|
||||
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
|
||||
Revert *string `json:"revert,omitempty"`
|
||||
SATADevice0 *CustomStorageDevice `json:"sata0,omitempty"`
|
||||
SATADevice1 *CustomStorageDevice `json:"sata1,omitempty"`
|
||||
SATADevice2 *CustomStorageDevice `json:"sata2,omitempty"`
|
||||
SATADevice3 *CustomStorageDevice `json:"sata3,omitempty"`
|
||||
SATADevice4 *CustomStorageDevice `json:"sata4,omitempty"`
|
||||
SATADevice5 *CustomStorageDevice `json:"sata5,omitempty"`
|
||||
SCSIDevice0 *CustomStorageDevice `json:"scsi0,omitempty"`
|
||||
SCSIDevice1 *CustomStorageDevice `json:"scsi1,omitempty"`
|
||||
SCSIDevice2 *CustomStorageDevice `json:"scsi2,omitempty"`
|
||||
SCSIDevice3 *CustomStorageDevice `json:"scsi3,omitempty"`
|
||||
SCSIDevice4 *CustomStorageDevice `json:"scsi4,omitempty"`
|
||||
SCSIDevice5 *CustomStorageDevice `json:"scsi5,omitempty"`
|
||||
SCSIDevice6 *CustomStorageDevice `json:"scsi6,omitempty"`
|
||||
SCSIDevice7 *CustomStorageDevice `json:"scsi7,omitempty"`
|
||||
SCSIDevice8 *CustomStorageDevice `json:"scsi8,omitempty"`
|
||||
SCSIDevice9 *CustomStorageDevice `json:"scsi9,omitempty"`
|
||||
SCSIDevice10 *CustomStorageDevice `json:"scsi10,omitempty"`
|
||||
SCSIDevice11 *CustomStorageDevice `json:"scsi11,omitempty"`
|
||||
SCSIDevice12 *CustomStorageDevice `json:"scsi12,omitempty"`
|
||||
SCSIDevice13 *CustomStorageDevice `json:"scsi13,omitempty"`
|
||||
SCSIHardware *string `json:"scsihw,omitempty"`
|
||||
SerialDevice0 *string `json:"serial0,omitempty"`
|
||||
SerialDevice1 *string `json:"serial1,omitempty"`
|
||||
SerialDevice2 *string `json:"serial2,omitempty"`
|
||||
SerialDevice3 *string `json:"serial3,omitempty"`
|
||||
SharedMemory *CustomSharedMemory `json:"ivshmem,omitempty"`
|
||||
SkipLock *types2.CustomBool `json:"skiplock,omitempty"`
|
||||
SMBIOS *CustomSMBIOS `json:"smbios1,omitempty"`
|
||||
SpiceEnhancements *CustomSpiceEnhancements `json:"spice_enhancements,omitempty"`
|
||||
StartDate *string `json:"startdate,omitempty"`
|
||||
StartOnBoot *types2.CustomBool `json:"onboot,omitempty"`
|
||||
StartupOrder *CustomStartupOrder `json:"startup,omitempty"`
|
||||
TabletDeviceEnabled *types2.CustomBool `json:"tablet,omitempty"`
|
||||
Tags *string `json:"tags,omitempty"`
|
||||
Template *types2.CustomBool `json:"template,omitempty"`
|
||||
TimeDriftFixEnabled *types2.CustomBool `json:"tdf,omitempty"`
|
||||
USBDevices *CustomUSBDevices `json:"usb,omitempty"`
|
||||
VGADevice *CustomVGADevice `json:"vga,omitempty"`
|
||||
VirtualCPUCount *int `json:"vcpus,omitempty"`
|
||||
VirtualIODevice0 *CustomStorageDevice `json:"virtio0,omitempty"`
|
||||
VirtualIODevice1 *CustomStorageDevice `json:"virtio1,omitempty"`
|
||||
VirtualIODevice2 *CustomStorageDevice `json:"virtio2,omitempty"`
|
||||
VirtualIODevice3 *CustomStorageDevice `json:"virtio3,omitempty"`
|
||||
VirtualIODevice4 *CustomStorageDevice `json:"virtio4,omitempty"`
|
||||
VirtualIODevice5 *CustomStorageDevice `json:"virtio5,omitempty"`
|
||||
VirtualIODevice6 *CustomStorageDevice `json:"virtio6,omitempty"`
|
||||
VirtualIODevice7 *CustomStorageDevice `json:"virtio7,omitempty"`
|
||||
VirtualIODevice8 *CustomStorageDevice `json:"virtio8,omitempty"`
|
||||
VirtualIODevice9 *CustomStorageDevice `json:"virtio9,omitempty"`
|
||||
VirtualIODevice10 *CustomStorageDevice `json:"virtio10,omitempty"`
|
||||
VirtualIODevice11 *CustomStorageDevice `json:"virtio11,omitempty"`
|
||||
VirtualIODevice12 *CustomStorageDevice `json:"virtio12,omitempty"`
|
||||
VirtualIODevice13 *CustomStorageDevice `json:"virtio13,omitempty"`
|
||||
VirtualIODevice14 *CustomStorageDevice `json:"virtio14,omitempty"`
|
||||
VirtualIODevice15 *CustomStorageDevice `json:"virtio15,omitempty"`
|
||||
VMGenerationID *string `json:"vmgenid,omitempty"`
|
||||
VMStateDatastoreID *string `json:"vmstatestorage,omitempty"`
|
||||
WatchdogDevice *CustomWatchdogDevice `json:"watchdog,omitempty"`
|
||||
}
|
||||
|
||||
// GetStatusResponseBody contains the body from a VM get status response.
|
||||
@ -495,19 +496,19 @@ type GetStatusResponseBody struct {
|
||||
|
||||
// GetStatusResponseData contains the data from a VM get status response.
|
||||
type GetStatusResponseData struct {
|
||||
AgentEnabled *types.CustomBool `json:"agent,omitempty"`
|
||||
CPUCount *float64 `json:"cpus,omitempty"`
|
||||
Lock *string `json:"lock,omitempty"`
|
||||
MemoryAllocation *int `json:"maxmem,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
PID *int `json:"pid,omitempty"`
|
||||
QMPStatus *string `json:"qmpstatus,omitempty"`
|
||||
RootDiskSize *int `json:"maxdisk,omitempty"`
|
||||
SpiceSupport *types.CustomBool `json:"spice,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Tags *string `json:"tags,omitempty"`
|
||||
Uptime *int `json:"uptime,omitempty"`
|
||||
VMID *int `json:"vmid,omitempty"`
|
||||
AgentEnabled *types2.CustomBool `json:"agent,omitempty"`
|
||||
CPUCount *float64 `json:"cpus,omitempty"`
|
||||
Lock *string `json:"lock,omitempty"`
|
||||
MemoryAllocation *int `json:"maxmem,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
PID *int `json:"pid,omitempty"`
|
||||
QMPStatus *string `json:"qmpstatus,omitempty"`
|
||||
RootDiskSize *int `json:"maxdisk,omitempty"`
|
||||
SpiceSupport *types2.CustomBool `json:"spice,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Tags *string `json:"tags,omitempty"`
|
||||
Uptime *int `json:"uptime,omitempty"`
|
||||
VMID *int `json:"vmid,omitempty"`
|
||||
}
|
||||
|
||||
// ListResponseBody contains the body from a virtual machine list response.
|
||||
@ -524,10 +525,10 @@ type ListResponseData struct {
|
||||
|
||||
// MigrateRequestBody contains the body for a VM migration request.
|
||||
type MigrateRequestBody struct {
|
||||
OnlineMigration *types.CustomBool `json:"online,omitempty" url:"online,omitempty"`
|
||||
TargetNode string `json:"target" url:"target"`
|
||||
TargetStorage *string `json:"targetstorage,omitempty" url:"targetstorage,omitempty"`
|
||||
WithLocalDisks *types.CustomBool `json:"with-local-disks,omitempty" url:"with-local-disks,omitempty,int"`
|
||||
OnlineMigration *types2.CustomBool `json:"online,omitempty" url:"online,omitempty"`
|
||||
TargetNode string `json:"target" url:"target"`
|
||||
TargetStorage *string `json:"targetstorage,omitempty" url:"targetstorage,omitempty"`
|
||||
WithLocalDisks *types2.CustomBool `json:"with-local-disks,omitempty" url:"with-local-disks,omitempty,int"`
|
||||
}
|
||||
|
||||
// MigrateResponseBody contains the body from a VM migrate response.
|
||||
@ -537,12 +538,12 @@ type MigrateResponseBody struct {
|
||||
|
||||
// MoveDiskRequestBody contains the body for a VM move disk request.
|
||||
type MoveDiskRequestBody struct {
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
DeleteOriginalDisk *types.CustomBool `json:"delete,omitempty" url:"delete,omitempty,int"`
|
||||
Digest *string `json:"digest,omitempty" url:"digest,omitempty"`
|
||||
Disk string `json:"disk" url:"disk"`
|
||||
TargetStorage string `json:"storage" url:"storage"`
|
||||
TargetStorageFormat *string `json:"format,omitempty" url:"format,omitempty"`
|
||||
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
|
||||
DeleteOriginalDisk *types2.CustomBool `json:"delete,omitempty" url:"delete,omitempty,int"`
|
||||
Digest *string `json:"digest,omitempty" url:"digest,omitempty"`
|
||||
Disk string `json:"disk" url:"disk"`
|
||||
TargetStorage string `json:"storage" url:"storage"`
|
||||
TargetStorageFormat *string `json:"format,omitempty" url:"format,omitempty"`
|
||||
}
|
||||
|
||||
// MoveDiskResponseBody contains the body from a VM move disk response.
|
||||
@ -562,18 +563,18 @@ type RebootResponseBody struct {
|
||||
|
||||
// ResizeDiskRequestBody contains the body for a VM resize disk request.
|
||||
type ResizeDiskRequestBody struct {
|
||||
Digest *string `json:"digest,omitempty" url:"digest,omitempty"`
|
||||
Disk string `json:"disk" url:"disk"`
|
||||
Size types.DiskSize `json:"size" url:"size"`
|
||||
SkipLock *types.CustomBool `json:"skiplock,omitempty" url:"skiplock,omitempty,int"`
|
||||
Digest *string `json:"digest,omitempty" url:"digest,omitempty"`
|
||||
Disk string `json:"disk" url:"disk"`
|
||||
Size types.DiskSize `json:"size" url:"size"`
|
||||
SkipLock *types2.CustomBool `json:"skiplock,omitempty" url:"skiplock,omitempty,int"`
|
||||
}
|
||||
|
||||
// ShutdownRequestBody contains the body for a VM shutdown request.
|
||||
type ShutdownRequestBody struct {
|
||||
ForceStop *types.CustomBool `json:"forceStop,omitempty" url:"forceStop,omitempty,int"`
|
||||
KeepActive *types.CustomBool `json:"keepActive,omitempty" url:"keepActive,omitempty,int"`
|
||||
SkipLock *types.CustomBool `json:"skipLock,omitempty" url:"skipLock,omitempty,int"`
|
||||
Timeout *int `json:"timeout,omitempty" url:"timeout,omitempty"`
|
||||
ForceStop *types2.CustomBool `json:"forceStop,omitempty" url:"forceStop,omitempty,int"`
|
||||
KeepActive *types2.CustomBool `json:"keepActive,omitempty" url:"keepActive,omitempty,int"`
|
||||
SkipLock *types2.CustomBool `json:"skipLock,omitempty" url:"skipLock,omitempty,int"`
|
||||
Timeout *int `json:"timeout,omitempty" url:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
// ShutdownResponseBody contains the body from a VM shutdown response.
|
||||
@ -1267,15 +1268,15 @@ func (r *CustomAgent) UnmarshalJSON(b []byte) error {
|
||||
v := strings.Split(strings.TrimSpace(p), "=")
|
||||
|
||||
if len(v) == 1 {
|
||||
enabled := types.CustomBool(v[0] == "1")
|
||||
enabled := types2.CustomBool(v[0] == "1")
|
||||
r.Enabled = &enabled
|
||||
} else if len(v) == 2 {
|
||||
switch v[0] {
|
||||
case "enabled":
|
||||
enabled := types.CustomBool(v[1] == "1")
|
||||
enabled := types2.CustomBool(v[1] == "1")
|
||||
r.Enabled = &enabled
|
||||
case "fstrim_cloned_disks":
|
||||
fstrim := types.CustomBool(v[1] == "1")
|
||||
fstrim := types2.CustomBool(v[1] == "1")
|
||||
r.TrimClonedDisks = &fstrim
|
||||
case "type":
|
||||
r.Type = &v[1]
|
||||
@ -1450,7 +1451,7 @@ func (r *CustomCPUEmulation) UnmarshalJSON(b []byte) error {
|
||||
r.Flags = &f
|
||||
}
|
||||
case "hidden":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Hidden = &bv
|
||||
case "hv-vendor-id":
|
||||
r.HVVendorID = &v[1]
|
||||
@ -1513,10 +1514,10 @@ func (r *CustomNetworkDevice) UnmarshalJSON(b []byte) error {
|
||||
case "bridge":
|
||||
r.Bridge = &v[1]
|
||||
case "firewall":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.Firewall = &bv
|
||||
case "link_down":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.LinkDown = &bv
|
||||
case "macaddr":
|
||||
r.MACAddress = &v[1]
|
||||
@ -1597,15 +1598,15 @@ func (r *CustomPCIDevice) UnmarshalJSON(b []byte) error {
|
||||
case "mdev":
|
||||
r.MDev = &v[1]
|
||||
case "pcie":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.PCIExpress = &bv
|
||||
case "rombar":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.ROMBAR = &bv
|
||||
case "romfile":
|
||||
r.ROMFile = &v[1]
|
||||
case "x-vga":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.XVGA = &bv
|
||||
}
|
||||
}
|
||||
@ -1661,7 +1662,7 @@ func (r *CustomSMBIOS) UnmarshalJSON(b []byte) error {
|
||||
if len(v) == 2 {
|
||||
switch v[0] {
|
||||
case "base64":
|
||||
base64 := types.CustomBool(v[1] == "1")
|
||||
base64 := types2.CustomBool(v[1] == "1")
|
||||
r.Base64 = &base64
|
||||
case "family":
|
||||
r.Family = &v[1]
|
||||
@ -1711,7 +1712,7 @@ func (r *CustomStorageDevice) UnmarshalJSON(b []byte) error {
|
||||
case "aio":
|
||||
r.AIO = &v[1]
|
||||
case "backup":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.BackupEnabled = &bv
|
||||
case "file":
|
||||
r.FileVolume = v[1]
|
||||
@ -1754,10 +1755,10 @@ func (r *CustomStorageDevice) UnmarshalJSON(b []byte) error {
|
||||
case "format":
|
||||
r.Format = &v[1]
|
||||
case "iothread":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.IOThread = &bv
|
||||
case "ssd":
|
||||
bv := types.CustomBool(v[1] == "1")
|
||||
bv := types2.CustomBool(v[1] == "1")
|
||||
r.SSD = &bv
|
||||
case "discard":
|
||||
r.Discard = &v[1]
|
||||
|
@ -7,7 +7,7 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
)
|
||||
|
||||
// DatastoreGetResponseBody contains the body from a datastore get response.
|
||||
|
@ -6,13 +6,15 @@
|
||||
|
||||
package types
|
||||
|
||||
import "github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
|
||||
// StrPtr returns a pointer to a string.
|
||||
func StrPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// BoolPtr returns a pointer to a bool.
|
||||
func BoolPtr(s bool) *CustomBool {
|
||||
customBool := CustomBool(s)
|
||||
func BoolPtr(s bool) *types.CustomBool {
|
||||
customBool := types.CustomBool(s)
|
||||
return &customBool
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ func ProxmoxVirtualEnvironment() *schema.Provider {
|
||||
}
|
||||
}
|
||||
|
||||
func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
|
||||
func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
|
||||
var err error
|
||||
|
||||
var diags diag.Diagnostics
|
||||
@ -43,44 +43,25 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}
|
||||
|
||||
var conn *api.Connection
|
||||
|
||||
// Legacy configuration, wrapped in the deprecated `virtual_environment` block
|
||||
veConfigBlock := d.Get(mkProviderVirtualEnvironment).([]interface{})
|
||||
if len(veConfigBlock) > 0 {
|
||||
veConfig := veConfigBlock[0].(map[string]interface{})
|
||||
creds, err = api.NewCredentials(
|
||||
veConfig[mkProviderUsername].(string),
|
||||
veConfig[mkProviderPassword].(string),
|
||||
veConfig[mkProviderOTP].(string),
|
||||
"",
|
||||
)
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
creds, err = api.NewCredentials(
|
||||
d.Get(mkProviderUsername).(string),
|
||||
d.Get(mkProviderPassword).(string),
|
||||
d.Get(mkProviderOTP).(string),
|
||||
d.Get(mkProviderAPIToken).(string),
|
||||
)
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
|
||||
conn, err = api.NewConnection(
|
||||
veConfig[mkProviderEndpoint].(string),
|
||||
veConfig[mkProviderInsecure].(bool),
|
||||
)
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
} else {
|
||||
creds, err = api.NewCredentials(
|
||||
d.Get(mkProviderUsername).(string),
|
||||
d.Get(mkProviderPassword).(string),
|
||||
d.Get(mkProviderOTP).(string),
|
||||
d.Get(mkProviderAPIToken).(string),
|
||||
)
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
|
||||
conn, err = api.NewConnection(
|
||||
d.Get(mkProviderEndpoint).(string),
|
||||
d.Get(mkProviderInsecure).(bool),
|
||||
)
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
}
|
||||
conn, err = api.NewConnection(
|
||||
d.Get(mkProviderEndpoint).(string),
|
||||
d.Get(mkProviderInsecure).(bool),
|
||||
)
|
||||
diags = append(diags, diag.FromErr(err)...)
|
||||
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
apiClient, err = api.NewClient(ctx, creds, conn)
|
||||
apiClient, err = api.NewClient(creds, conn)
|
||||
if err != nil {
|
||||
return nil, diag.Errorf("error creating virtual environment client: %s", err)
|
||||
}
|
||||
@ -145,12 +126,27 @@ type apiResolver struct {
|
||||
func (r *apiResolver) Resolve(ctx context.Context, nodeName string) (string, error) {
|
||||
nc := &nodes.Client{Client: r.c, NodeName: nodeName}
|
||||
|
||||
ip, err := nc.GetIP(ctx)
|
||||
networkDevices, err := nc.ListNetworkInterfaces(ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get node IP: %w", err)
|
||||
return "", fmt.Errorf("failed to list network devices of node \"%s\": %w", nc.NodeName, err)
|
||||
}
|
||||
|
||||
return ip, nil
|
||||
nodeAddress := ""
|
||||
|
||||
for _, d := range networkDevices {
|
||||
if d.Address != nil {
|
||||
nodeAddress = *d.Address
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if nodeAddress == "" {
|
||||
return "", fmt.Errorf("failed to determine the IP address of node \"%s\"", nc.NodeName)
|
||||
}
|
||||
|
||||
nodeAddressParts := strings.Split(nodeAddress, "/")
|
||||
|
||||
return nodeAddressParts[0], nil
|
||||
}
|
||||
|
||||
type apiResolverWithOverrides struct {
|
||||
|
@ -33,7 +33,6 @@ func TestProviderSchema(t *testing.T) {
|
||||
}
|
||||
|
||||
test.AssertOptionalArguments(t, s, []string{
|
||||
mkProviderVirtualEnvironment,
|
||||
mkProviderUsername,
|
||||
mkProviderPassword,
|
||||
mkProviderEndpoint,
|
||||
@ -42,32 +41,11 @@ func TestProviderSchema(t *testing.T) {
|
||||
})
|
||||
|
||||
test.AssertValueTypes(t, s, map[string]schema.ValueType{
|
||||
mkProviderVirtualEnvironment: schema.TypeList,
|
||||
mkProviderUsername: schema.TypeString,
|
||||
mkProviderPassword: schema.TypeString,
|
||||
mkProviderEndpoint: schema.TypeString,
|
||||
mkProviderInsecure: schema.TypeBool,
|
||||
mkProviderOTP: schema.TypeString,
|
||||
})
|
||||
|
||||
veSchema := test.AssertNestedSchemaExistence(t, s, mkProviderVirtualEnvironment)
|
||||
|
||||
test.AssertOptionalArguments(t, veSchema, []string{
|
||||
mkProviderEndpoint,
|
||||
mkProviderInsecure,
|
||||
mkProviderOTP,
|
||||
mkProviderPassword,
|
||||
mkProviderUsername,
|
||||
mkProviderSSH,
|
||||
})
|
||||
|
||||
test.AssertValueTypes(t, veSchema, map[string]schema.ValueType{
|
||||
mkProviderUsername: schema.TypeString,
|
||||
mkProviderPassword: schema.TypeString,
|
||||
mkProviderEndpoint: schema.TypeString,
|
||||
mkProviderInsecure: schema.TypeBool,
|
||||
mkProviderOTP: schema.TypeString,
|
||||
mkProviderPassword: schema.TypeString,
|
||||
mkProviderUsername: schema.TypeString,
|
||||
mkProviderSSH: schema.TypeList,
|
||||
})
|
||||
|
||||
providerSSHSchema := test.AssertNestedSchemaExistence(t, s, mkProviderSSH)
|
||||
|
@ -17,21 +17,22 @@ import (
|
||||
func createResourceMap() map[string]*schema.Resource {
|
||||
return map[string]*schema.Resource{
|
||||
"proxmox_virtual_environment_certificate": resource.Certificate(),
|
||||
"proxmox_virtual_environment_firewall_alias": firewall.Alias(),
|
||||
"proxmox_virtual_environment_firewall_ipset": firewall.IPSet(),
|
||||
"proxmox_virtual_environment_firewall_rules": firewall.Rules(),
|
||||
"proxmox_virtual_environment_firewall_options": firewall.Options(),
|
||||
"proxmox_virtual_environment_cluster_firewall_security_group": clusterfirewall.SecurityGroup(),
|
||||
"proxmox_virtual_environment_cluster_firewall": clusterfirewall.Firewall(),
|
||||
"proxmox_virtual_environment_cluster_firewall_security_group": clusterfirewall.SecurityGroup(),
|
||||
"proxmox_virtual_environment_container": resource.Container(),
|
||||
"proxmox_virtual_environment_dns": resource.DNS(),
|
||||
"proxmox_virtual_environment_file": resource.File(),
|
||||
"proxmox_virtual_environment_firewall_alias": firewall.Alias(),
|
||||
"proxmox_virtual_environment_firewall_ipset": firewall.IPSet(),
|
||||
"proxmox_virtual_environment_firewall_options": firewall.Options(),
|
||||
"proxmox_virtual_environment_firewall_rules": firewall.Rules(),
|
||||
"proxmox_virtual_environment_group": resource.Group(),
|
||||
"proxmox_virtual_environment_hosts": resource.Hosts(),
|
||||
"proxmox_virtual_environment_pool": resource.Pool(),
|
||||
"proxmox_virtual_environment_role": resource.Role(),
|
||||
"proxmox_virtual_environment_time": resource.Time(),
|
||||
"proxmox_virtual_environment_user": resource.User(),
|
||||
"proxmox_virtual_environment_vm": resource.VM(),
|
||||
// "proxmox_virtual_environment_network_linux_bridge": resource.NetworkLinuxBridge(),
|
||||
"proxmox_virtual_environment_pool": resource.Pool(),
|
||||
"proxmox_virtual_environment_role": resource.Role(),
|
||||
"proxmox_virtual_environment_time": resource.Time(),
|
||||
"proxmox_virtual_environment_user": resource.User(),
|
||||
"proxmox_virtual_environment_vm": resource.VM(),
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
@ -16,19 +15,18 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
dvProviderOTP = ""
|
||||
mkProviderVirtualEnvironment = "virtual_environment"
|
||||
mkProviderEndpoint = "endpoint"
|
||||
mkProviderInsecure = "insecure"
|
||||
mkProviderOTP = "otp"
|
||||
mkProviderPassword = "password"
|
||||
mkProviderUsername = "username"
|
||||
mkProviderAPIToken = "api_token"
|
||||
mkProviderSSH = "ssh"
|
||||
mkProviderSSHUsername = "username"
|
||||
mkProviderSSHPassword = "password"
|
||||
mkProviderSSHAgent = "agent"
|
||||
mkProviderSSHAgentSocket = "agent_socket"
|
||||
dvProviderOTP = ""
|
||||
mkProviderEndpoint = "endpoint"
|
||||
mkProviderInsecure = "insecure"
|
||||
mkProviderOTP = "otp"
|
||||
mkProviderPassword = "password"
|
||||
mkProviderUsername = "username"
|
||||
mkProviderAPIToken = "api_token"
|
||||
mkProviderSSH = "ssh"
|
||||
mkProviderSSHUsername = "username"
|
||||
mkProviderSSHPassword = "password"
|
||||
mkProviderSSHAgent = "agent"
|
||||
mkProviderSSHAgentSocket = "agent_socket"
|
||||
|
||||
mkProviderSSHNode = "node"
|
||||
mkProviderSSHNodeName = "name"
|
||||
@ -36,40 +34,21 @@ const (
|
||||
)
|
||||
|
||||
func createSchema() map[string]*schema.Schema {
|
||||
providerSchema := nestedProviderSchema()
|
||||
providerSchema[mkProviderVirtualEnvironment] = &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: nestedProviderSchema(),
|
||||
},
|
||||
MaxItems: 1,
|
||||
Deprecated: "Move attributes out of virtual_environment block",
|
||||
}
|
||||
|
||||
return providerSchema
|
||||
}
|
||||
|
||||
func nestedProviderSchema() map[string]*schema.Schema {
|
||||
return map[string]*schema.Schema{
|
||||
mkProviderEndpoint: {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The endpoint for the Proxmox Virtual Environment API",
|
||||
Description: "The endpoint for the Proxmox VE API.",
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{"PROXMOX_VE_ENDPOINT", "PM_VE_ENDPOINT"},
|
||||
nil,
|
||||
),
|
||||
AtLeastOneOf: []string{
|
||||
mkProviderEndpoint,
|
||||
fmt.Sprintf("%s.0.%s", mkProviderVirtualEnvironment, mkProviderEndpoint),
|
||||
},
|
||||
ValidateFunc: validation.IsURLWithHTTPorHTTPS,
|
||||
},
|
||||
mkProviderInsecure: {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Description: "Whether to skip the TLS verification step",
|
||||
Description: "Whether to skip the TLS verification step.",
|
||||
DefaultFunc: func() (interface{}, error) {
|
||||
for _, k := range []string{"PROXMOX_VE_INSECURE", "PM_VE_INSECURE"} {
|
||||
v := os.Getenv(k)
|
||||
@ -85,24 +64,25 @@ func nestedProviderSchema() map[string]*schema.Schema {
|
||||
mkProviderOTP: {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The one-time password for the Proxmox Virtual Environment API",
|
||||
Description: "The one-time password for the Proxmox VE API.",
|
||||
Deprecated: "The `otp` attribute is deprecated and will be removed in a future release. " +
|
||||
"Please use the `api_token` attribute instead.",
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{"PROXMOX_VE_OTP", "PM_VE_OTP"},
|
||||
dvProviderOTP,
|
||||
nil,
|
||||
),
|
||||
},
|
||||
mkProviderPassword: {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
Description: "The password for the Proxmox Virtual Environment API",
|
||||
Description: "The password for the Proxmox VE API.",
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{"PROXMOX_VE_PASSWORD", "PM_VE_PASSWORD"},
|
||||
nil,
|
||||
),
|
||||
AtLeastOneOf: []string{
|
||||
mkProviderPassword,
|
||||
fmt.Sprintf("%s.0.%s", mkProviderVirtualEnvironment, mkProviderPassword),
|
||||
mkProviderAPIToken,
|
||||
},
|
||||
ValidateFunc: validation.StringIsNotEmpty,
|
||||
@ -110,14 +90,13 @@ func nestedProviderSchema() map[string]*schema.Schema {
|
||||
mkProviderUsername: {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The username for the Proxmox Virtual Environment API",
|
||||
Description: "The username for the Proxmox VE API.",
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{"PROXMOX_VE_USERNAME", "PM_VE_USERNAME"},
|
||||
nil,
|
||||
),
|
||||
AtLeastOneOf: []string{
|
||||
mkProviderUsername,
|
||||
fmt.Sprintf("%s.0.%s", mkProviderVirtualEnvironment, mkProviderUsername),
|
||||
mkProviderAPIToken,
|
||||
},
|
||||
ValidateFunc: validation.StringIsNotEmpty,
|
||||
@ -126,7 +105,7 @@ func nestedProviderSchema() map[string]*schema.Schema {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
Description: "The API token for the Proxmox Virtual Environment API",
|
||||
Description: "The API token for the Proxmox VE API.",
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{"PROXMOX_VE_API_TOKEN", "PM_VE_API_TOKEN"},
|
||||
nil,
|
||||
@ -140,14 +119,15 @@ func nestedProviderSchema() map[string]*schema.Schema {
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Description: "The SSH connection configuration to a Proxmox node",
|
||||
Description: "The SSH configuration for the Proxmox nodes.",
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
mkProviderSSHUsername: {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: fmt.Sprintf("The username used for the SSH connection, "+
|
||||
"defaults to the user specified in '%s'", mkProviderUsername),
|
||||
Description: "The username used for the SSH connection. " +
|
||||
"Defaults to the value of the `username` field of the " +
|
||||
"`provider` block.",
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{"PROXMOX_VE_SSH_USERNAME", "PM_VE_SSH_USERNAME"},
|
||||
nil,
|
||||
@ -158,8 +138,9 @@ func nestedProviderSchema() map[string]*schema.Schema {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
Description: fmt.Sprintf("The password used for the SSH connection, "+
|
||||
"defaults to the password specified in '%s'", mkProviderPassword),
|
||||
Description: "The password used for the SSH connection. " +
|
||||
"Defaults to the value of the `password` field of the " +
|
||||
"`provider` block.",
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{"PROXMOX_VE_SSH_PASSWORD", "PM_VE_SSH_PASSWORD"},
|
||||
nil,
|
||||
@ -167,9 +148,10 @@ func nestedProviderSchema() map[string]*schema.Schema {
|
||||
ValidateFunc: validation.StringIsNotEmpty,
|
||||
},
|
||||
mkProviderSSHAgent: {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Description: "Whether to use the SSH agent for the SSH authentication. Defaults to false",
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Description: "Whether to use the SSH agent for authentication. " +
|
||||
"Defaults to `false`.",
|
||||
DefaultFunc: func() (interface{}, error) {
|
||||
for _, k := range []string{"PROXMOX_VE_SSH_AGENT", "PM_VE_SSH_AGENT"} {
|
||||
v := os.Getenv(k)
|
||||
@ -186,7 +168,7 @@ func nestedProviderSchema() map[string]*schema.Schema {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The path to the SSH agent socket. Defaults to the value of the `SSH_AUTH_SOCK` " +
|
||||
"environment variable",
|
||||
"environment variable.",
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{"SSH_AUTH_SOCK", "PROXMOX_VE_SSH_AUTH_SOCK", "PM_VE_SSH_AUTH_SOCK"},
|
||||
nil,
|
||||
@ -197,19 +179,19 @@ func nestedProviderSchema() map[string]*schema.Schema {
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
MinItems: 0,
|
||||
Description: "Overrides for SSH connection configuration to a Proxmox node",
|
||||
Description: "Overrides for SSH connection configuration for a Proxmox VE node.",
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
mkProviderSSHNodeName: {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "The name of the node to connect to",
|
||||
Description: "The name of the Proxmox VE node.",
|
||||
ValidateFunc: validation.StringIsNotEmpty,
|
||||
},
|
||||
mkProviderSSHNodeAddress: {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "The address that should be used to connect to the node",
|
||||
Description: "The address of the Proxmox VE node.",
|
||||
ValidateFunc: validation.IsIPAddress,
|
||||
},
|
||||
},
|
||||
|
@ -15,8 +15,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||
)
|
||||
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/cluster/firewall"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator"
|
||||
)
|
||||
|
@ -17,8 +17,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/containers"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||
)
|
||||
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/firewall"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
||||
)
|
||||
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/firewall"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
||||
)
|
||||
|
@ -15,8 +15,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/firewall"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
||||
)
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/access"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||
)
|
||||
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/access"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||
)
|
||||
|
||||
|
@ -15,8 +15,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
|
||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/access"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||
)
|
||||
|
||||
|
@ -352,39 +352,6 @@ func getSCSIHardwareValidator() schema.SchemaValidateDiagFunc {
|
||||
}, false))
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func getVLANIDsValidator() schema.SchemaValidateDiagFunc {
|
||||
return validation.ToDiagFunc(func(i interface{}, k string) (ws []string, es []error) {
|
||||
min := 1
|
||||
max := 4094
|
||||
|
||||
list, ok := i.([]interface{})
|
||||
|
||||
if !ok {
|
||||
es = append(es, fmt.Errorf("expected type of %s to be []interface{}", k))
|
||||
return
|
||||
}
|
||||
|
||||
for li, lv := range list {
|
||||
v, ok := lv.(int)
|
||||
|
||||
if !ok {
|
||||
es = append(es, fmt.Errorf("expected type of %s[%d] to be int", k, li))
|
||||
return
|
||||
}
|
||||
|
||||
if v != -1 {
|
||||
if v < min || v > max {
|
||||
es = append(es, fmt.Errorf("expected %s[%d] to be in the range (%d - %d), got %d", k, li, min, max, v))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
func getVMIDValidator() schema.SchemaValidateDiagFunc {
|
||||
return validation.ToDiagFunc(func(i interface{}, k string) (ws []string, es []error) {
|
||||
min := 100
|
||||
|
76
proxmoxtf/resource/validator/network.go
Normal file
76
proxmoxtf/resource/validator/network.go
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package validator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
)
|
||||
|
||||
// VLANIDsValidator returns a schema validation function for VLAN IDs.
|
||||
func VLANIDsValidator() schema.SchemaValidateDiagFunc {
|
||||
return validation.ToDiagFunc(func(i interface{}, k string) ([]string, []error) {
|
||||
min := 1
|
||||
max := 4094
|
||||
|
||||
var ws []string
|
||||
var es []error
|
||||
|
||||
list, ok := i.([]interface{})
|
||||
|
||||
if !ok {
|
||||
es = append(es, fmt.Errorf("expected type of %s to be []interface{}", k))
|
||||
return ws, es
|
||||
}
|
||||
|
||||
for li, lv := range list {
|
||||
v, ok := lv.(int)
|
||||
|
||||
if !ok {
|
||||
es = append(es, fmt.Errorf("expected type of %s[%d] to be int", k, li))
|
||||
return ws, es
|
||||
}
|
||||
|
||||
if v != -1 {
|
||||
if v < min || v > max {
|
||||
es = append(es, fmt.Errorf("expected %s[%d] to be in the range (%d - %d), got %d", k, li, min, max, v))
|
||||
return ws, es
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ws, es
|
||||
})
|
||||
}
|
||||
|
||||
// NodeNetworkInterfaceBondingModes returns a schema validation function for a node network interface bonding mode.
|
||||
func NodeNetworkInterfaceBondingModes() schema.SchemaValidateDiagFunc {
|
||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||
"balance-rr",
|
||||
"active-backup",
|
||||
"balance-xor",
|
||||
"broadcast",
|
||||
"802.3ad",
|
||||
"balance-tlb",
|
||||
"balance-alb",
|
||||
"balance-slb",
|
||||
"lacp-balance-slb",
|
||||
"lacp-balance-tcp",
|
||||
}, false))
|
||||
}
|
||||
|
||||
// NodeNetworkInterfaceBondingTransmitHashPolicies returns a schema validation function for a node network interface
|
||||
// bonding transmit hash policy.
|
||||
func NodeNetworkInterfaceBondingTransmitHashPolicies() schema.SchemaValidateDiagFunc {
|
||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||
"layer2",
|
||||
"layer2+3",
|
||||
"layer3+4",
|
||||
}, false))
|
||||
}
|
@ -20,6 +20,7 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
|
||||
types2 "github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||
@ -1311,7 +1312,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
}
|
||||
}
|
||||
|
||||
fullCopy := types.CustomBool(cloneFull)
|
||||
fullCopy := types2.CustomBool(cloneFull)
|
||||
|
||||
cloneBody := &vms.CloneRequestBody{
|
||||
FullCopy: &fullCopy,
|
||||
@ -1392,7 +1393,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
}
|
||||
|
||||
// Migrate to target node
|
||||
withLocalDisks := types.CustomBool(true)
|
||||
withLocalDisks := types2.CustomBool(true)
|
||||
migrateBody := &vms.MigrateRequestBody{
|
||||
TargetNode: nodeName,
|
||||
WithLocalDisks: &withLocalDisks,
|
||||
@ -1426,7 +1427,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
}
|
||||
|
||||
// Now that the virtual machine has been cloned, we need to perform some modifications.
|
||||
acpi := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
|
||||
acpi := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
|
||||
agent := d.Get(mkResourceVirtualEnvironmentVMAgent).([]interface{})
|
||||
audioDevices := vmGetAudioDeviceList(d)
|
||||
|
||||
@ -1442,9 +1443,9 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
networkDevice := d.Get(mkResourceVirtualEnvironmentVMNetworkDevice).([]interface{})
|
||||
operatingSystem := d.Get(mkResourceVirtualEnvironmentVMOperatingSystem).([]interface{})
|
||||
serialDevice := d.Get(mkResourceVirtualEnvironmentVMSerialDevice).([]interface{})
|
||||
onBoot := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMOnBoot).(bool))
|
||||
tabletDevice := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTabletDevice).(bool))
|
||||
template := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTemplate).(bool))
|
||||
onBoot := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMOnBoot).(bool))
|
||||
tabletDevice := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTabletDevice).(bool))
|
||||
template := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTemplate).(bool))
|
||||
vga := d.Get(mkResourceVirtualEnvironmentVMVGA).([]interface{})
|
||||
|
||||
updateBody := &vms.UpdateRequestBody{
|
||||
@ -1463,10 +1464,10 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
if len(agent) > 0 {
|
||||
agentBlock := agent[0].(map[string]interface{})
|
||||
|
||||
agentEnabled := types.CustomBool(
|
||||
agentEnabled := types2.CustomBool(
|
||||
agentBlock[mkResourceVirtualEnvironmentVMAgentEnabled].(bool),
|
||||
)
|
||||
agentTrim := types.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool))
|
||||
agentTrim := types2.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool))
|
||||
agentType := agentBlock[mkResourceVirtualEnvironmentVMAgentType].(string)
|
||||
|
||||
updateBody.Agent = &vms.CustomAgent{
|
||||
@ -1753,7 +1754,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
||||
)
|
||||
}
|
||||
|
||||
deleteOriginalDisk := types.CustomBool(true)
|
||||
deleteOriginalDisk := types2.CustomBool(true)
|
||||
|
||||
diskMoveBody := &vms.MoveDiskRequestBody{
|
||||
DeleteOriginalDisk: &deleteOriginalDisk,
|
||||
@ -1806,7 +1807,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
||||
|
||||
resource := VM()
|
||||
|
||||
acpi := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
|
||||
acpi := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
|
||||
|
||||
agentBlock, err := getSchemaBlock(
|
||||
resource,
|
||||
@ -1819,10 +1820,10 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
agentEnabled := types.CustomBool(
|
||||
agentEnabled := types2.CustomBool(
|
||||
agentBlock[mkResourceVirtualEnvironmentVMAgentEnabled].(bool),
|
||||
)
|
||||
agentTrim := types.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool))
|
||||
agentTrim := types2.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool))
|
||||
agentType := agentBlock[mkResourceVirtualEnvironmentVMAgentType].(string)
|
||||
|
||||
kvmArguments := d.Get(mkResourceVirtualEnvironmentVMKVMArguments).(string)
|
||||
@ -1936,9 +1937,9 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
||||
|
||||
serialDevices := vmGetSerialDeviceList(d)
|
||||
|
||||
onBoot := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMOnBoot).(bool))
|
||||
tabletDevice := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTabletDevice).(bool))
|
||||
template := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTemplate).(bool))
|
||||
onBoot := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMOnBoot).(bool))
|
||||
tabletDevice := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTabletDevice).(bool))
|
||||
template := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTemplate).(bool))
|
||||
|
||||
vgaDevice, err := vmGetVGADeviceObject(d)
|
||||
if err != nil {
|
||||
@ -2161,8 +2162,8 @@ func vmCreateCustomDisks(ctx context.Context, d *schema.ResourceData, m interfac
|
||||
size, _ := block[mkResourceVirtualEnvironmentVMDiskSize].(int)
|
||||
speed := block[mkResourceVirtualEnvironmentVMDiskSpeed].([]interface{})
|
||||
diskInterface, _ := block[mkResourceVirtualEnvironmentVMDiskInterface].(string)
|
||||
ioThread := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskIOThread].(bool))
|
||||
ssd := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskSSD].(bool))
|
||||
ioThread := types2.CustomBool(block[mkResourceVirtualEnvironmentVMDiskIOThread].(bool))
|
||||
ssd := types2.CustomBool(block[mkResourceVirtualEnvironmentVMDiskSSD].(bool))
|
||||
discard, _ := block[mkResourceVirtualEnvironmentVMDiskDiscard].(string)
|
||||
|
||||
if fileFormat == "" {
|
||||
@ -2510,8 +2511,8 @@ func vmGetDiskDeviceObjects(
|
||||
fileID, _ := block[mkResourceVirtualEnvironmentVMDiskFileID].(string)
|
||||
size, _ := block[mkResourceVirtualEnvironmentVMDiskSize].(int)
|
||||
diskInterface, _ := block[mkResourceVirtualEnvironmentVMDiskInterface].(string)
|
||||
ioThread := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskIOThread].(bool))
|
||||
ssd := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskSSD].(bool))
|
||||
ioThread := types2.CustomBool(block[mkResourceVirtualEnvironmentVMDiskIOThread].(bool))
|
||||
ssd := types2.CustomBool(block[mkResourceVirtualEnvironmentVMDiskSSD].(bool))
|
||||
discard := block[mkResourceVirtualEnvironmentVMDiskDiscard].(string)
|
||||
|
||||
speedBlock, err := getSchemaBlock(
|
||||
@ -2601,12 +2602,12 @@ func vmGetHostPCIDeviceObjects(d *schema.ResourceData) vms.CustomPCIDevices {
|
||||
|
||||
ids, _ := block[mkResourceVirtualEnvironmentVMHostPCIDeviceID].(string)
|
||||
mdev, _ := block[mkResourceVirtualEnvironmentVMHostPCIDeviceMDev].(string)
|
||||
pcie := types.CustomBool(block[mkResourceVirtualEnvironmentVMHostPCIDevicePCIE].(bool))
|
||||
rombar := types.CustomBool(
|
||||
pcie := types2.CustomBool(block[mkResourceVirtualEnvironmentVMHostPCIDevicePCIE].(bool))
|
||||
rombar := types2.CustomBool(
|
||||
block[mkResourceVirtualEnvironmentVMHostPCIDeviceROMBAR].(bool),
|
||||
)
|
||||
romfile, _ := block[mkResourceVirtualEnvironmentVMHostPCIDeviceROMFile].(string)
|
||||
xvga := types.CustomBool(block[mkResourceVirtualEnvironmentVMHostPCIDeviceXVGA].(bool))
|
||||
xvga := types2.CustomBool(block[mkResourceVirtualEnvironmentVMHostPCIDeviceXVGA].(bool))
|
||||
|
||||
device := vms.CustomPCIDevice{
|
||||
DeviceIDs: strings.Split(ids, ";"),
|
||||
@ -2641,7 +2642,7 @@ func vmGetNetworkDeviceObjects(d *schema.ResourceData) vms.CustomNetworkDevices
|
||||
|
||||
bridge := block[mkResourceVirtualEnvironmentVMNetworkDeviceBridge].(string)
|
||||
enabled := block[mkResourceVirtualEnvironmentVMNetworkDeviceEnabled].(bool)
|
||||
firewall := types.CustomBool(block[mkResourceVirtualEnvironmentVMNetworkDeviceFirewall].(bool))
|
||||
firewall := types2.CustomBool(block[mkResourceVirtualEnvironmentVMNetworkDeviceFirewall].(bool))
|
||||
macAddress := block[mkResourceVirtualEnvironmentVMNetworkDeviceMACAddress].(string)
|
||||
model := block[mkResourceVirtualEnvironmentVMNetworkDeviceModel].(string)
|
||||
rateLimit := block[mkResourceVirtualEnvironmentVMNetworkDeviceRateLimit].(float64)
|
||||
@ -2757,7 +2758,7 @@ func vmGetVGADeviceObject(d *schema.ResourceData) (*vms.CustomVGADevice, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vgaEnabled := types.CustomBool(vgaBlock[mkResourceVirtualEnvironmentVMAgentEnabled].(bool))
|
||||
vgaEnabled := types2.CustomBool(vgaBlock[mkResourceVirtualEnvironmentVMAgentEnabled].(bool))
|
||||
vgaMemory := vgaBlock[mkResourceVirtualEnvironmentVMVGAMemory].(int)
|
||||
vgaType := vgaBlock[mkResourceVirtualEnvironmentVMVGAType].(string)
|
||||
|
||||
@ -4008,7 +4009,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
|
||||
// Prepare the new primitive configuration values.
|
||||
if d.HasChange(mkResourceVirtualEnvironmentVMACPI) {
|
||||
acpi := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
|
||||
acpi := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
|
||||
updateBody.ACPI = &acpi
|
||||
rebootRequired = true
|
||||
}
|
||||
@ -4031,7 +4032,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
}
|
||||
|
||||
if d.HasChange(mkResourceVirtualEnvironmentVMOnBoot) {
|
||||
startOnBoot := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMOnBoot).(bool))
|
||||
startOnBoot := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMOnBoot).(bool))
|
||||
updateBody.StartOnBoot = &startOnBoot
|
||||
}
|
||||
|
||||
@ -4061,12 +4062,12 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
}
|
||||
|
||||
if d.HasChange(mkResourceVirtualEnvironmentVMTabletDevice) {
|
||||
tabletDevice := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTabletDevice).(bool))
|
||||
tabletDevice := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTabletDevice).(bool))
|
||||
updateBody.TabletDeviceEnabled = &tabletDevice
|
||||
rebootRequired = true
|
||||
}
|
||||
|
||||
template := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTemplate).(bool))
|
||||
template := types2.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTemplate).(bool))
|
||||
|
||||
if d.HasChange(mkResourceVirtualEnvironmentVMTemplate) {
|
||||
updateBody.Template = &template
|
||||
@ -4086,10 +4087,10 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
agentEnabled := types.CustomBool(
|
||||
agentEnabled := types2.CustomBool(
|
||||
agentBlock[mkResourceVirtualEnvironmentVMAgentEnabled].(bool),
|
||||
)
|
||||
agentTrim := types.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool))
|
||||
agentTrim := types2.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool))
|
||||
agentType := agentBlock[mkResourceVirtualEnvironmentVMAgentType].(string)
|
||||
|
||||
updateBody.Agent = &vms.CustomAgent{
|
||||
@ -4436,7 +4437,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
return diag.FromErr(e)
|
||||
}
|
||||
} else {
|
||||
forceStop := types.CustomBool(true)
|
||||
forceStop := types2.CustomBool(true)
|
||||
shutdownTimeout := d.Get(mkResourceVirtualEnvironmentVMTimeoutShutdownVM).(int)
|
||||
|
||||
e = vmAPI.ShutdownVM(ctx, &vms.ShutdownRequestBody{
|
||||
@ -4518,7 +4519,7 @@ func vmUpdateDiskLocationAndSize(
|
||||
}
|
||||
|
||||
if *oldDisk.ID != *diskNewEntries[prefix][oldKey].ID {
|
||||
deleteOriginalDisk := types.CustomBool(true)
|
||||
deleteOriginalDisk := types2.CustomBool(true)
|
||||
|
||||
diskMoveBodies = append(
|
||||
diskMoveBodies,
|
||||
@ -4546,7 +4547,7 @@ func vmUpdateDiskLocationAndSize(
|
||||
}
|
||||
|
||||
if shutdownForDisksRequired && !template {
|
||||
forceStop := types.CustomBool(true)
|
||||
forceStop := types2.CustomBool(true)
|
||||
shutdownTimeout := d.Get(mkResourceVirtualEnvironmentVMTimeoutShutdownVM).(int)
|
||||
|
||||
err = vmAPI.ShutdownVM(
|
||||
@ -4630,7 +4631,7 @@ func vmDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
||||
}
|
||||
|
||||
if status.Status != "stopped" {
|
||||
forceStop := types.CustomBool(true)
|
||||
forceStop := types2.CustomBool(true)
|
||||
shutdownTimeout := d.Get(mkResourceVirtualEnvironmentVMTimeoutShutdownVM).(int)
|
||||
|
||||
err = vmAPI.ShutdownVM(
|
||||
|
32
tools/go.mod
32
tools/go.mod
@ -5,6 +5,7 @@ go 1.20
|
||||
require (
|
||||
github.com/golangci/golangci-lint v1.53.3
|
||||
github.com/goreleaser/goreleaser v1.18.2
|
||||
github.com/hashicorp/terraform-plugin-docs v0.15.0
|
||||
)
|
||||
|
||||
require (
|
||||
@ -46,15 +47,18 @@ require (
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/OpenPeeDeeP/depguard/v2 v2.1.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
|
||||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f // indirect
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||
github.com/alessio/shellescape v1.4.1 // indirect
|
||||
github.com/alexkohler/nakedret/v2 v2.0.2 // indirect
|
||||
github.com/alexkohler/prealloc v1.0.0 // indirect
|
||||
github.com/alingse/asasalint v0.0.11 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/ashanbrown/forbidigo v1.5.3 // indirect
|
||||
github.com/ashanbrown/makezero v1.1.1 // indirect
|
||||
@ -85,6 +89,7 @@ require (
|
||||
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220517224237-e6f29200ae04 // 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.1 // indirect
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect
|
||||
github.com/blizzy78/varnamelen v0.8.0 // indirect
|
||||
@ -106,6 +111,7 @@ require (
|
||||
github.com/charmbracelet/lipgloss v0.7.1 // indirect
|
||||
github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect
|
||||
github.com/chrismellard/docker-credential-acr-env v0.0.0-20220327082430-c57b701bfc08 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/curioswitch/go-reassign v0.2.0 // indirect
|
||||
@ -127,7 +133,7 @@ require (
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/elliotchance/orderedmap/v2 v2.2.0 // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/esimonov/ifshort v1.0.4 // indirect
|
||||
github.com/ettle/strcase v0.1.1 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
|
||||
@ -138,8 +144,8 @@ require (
|
||||
github.com/fzipp/gocyclo v0.6.0 // indirect
|
||||
github.com/go-critic/go-critic v0.8.1 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
||||
github.com/go-git/go-git/v5 v5.4.2 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.4.1 // indirect
|
||||
github.com/go-git/go-git/v5 v5.6.1 // indirect
|
||||
github.com/go-openapi/analysis v0.21.4 // indirect
|
||||
github.com/go-openapi/errors v0.20.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
@ -195,11 +201,16 @@ require (
|
||||
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
|
||||
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.5.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.18.1 // indirect
|
||||
github.com/hashicorp/terraform-json v0.16.0 // indirect
|
||||
github.com/hexops/gotextdiff v1.0.3 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/iancoleman/orderedmap v0.2.0 // indirect
|
||||
@ -213,7 +224,7 @@ require (
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/julz/importas v0.1.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.1.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/kisielk/errcheck v1.6.3 // indirect
|
||||
github.com/kisielk/gotool v1.0.0 // indirect
|
||||
github.com/kkHAIKE/contextcheck v1.1.4 // indirect
|
||||
@ -241,6 +252,7 @@ require (
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mbilski/exhaustivestruct v1.2.0 // indirect
|
||||
github.com/mgechev/revive v1.3.2 // indirect
|
||||
github.com/mitchellh/cli v1.1.5 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
@ -263,10 +275,12 @@ require (
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/polyfloyd/go-errorlint v1.4.2 // indirect
|
||||
github.com/posener/complete v1.2.3 // indirect
|
||||
github.com/prometheus/client_golang v1.15.1 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
@ -276,6 +290,7 @@ require (
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
|
||||
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
|
||||
github.com/rivo/uniseg v0.4.2 // indirect
|
||||
github.com/russross/blackfriday v1.6.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/ryancurrah/gomodguard v1.3.0 // indirect
|
||||
github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect
|
||||
@ -286,6 +301,7 @@ require (
|
||||
github.com/securego/gosec/v2 v2.16.0 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sigstore/cosign/v2 v2.0.0 // indirect
|
||||
github.com/sigstore/rekor v1.2.0 // indirect
|
||||
github.com/sigstore/sigstore v1.6.4 // indirect
|
||||
@ -293,6 +309,7 @@ require (
|
||||
github.com/sivchari/containedctx v1.0.3 // indirect
|
||||
github.com/sivchari/nosnakecase v1.7.0 // indirect
|
||||
github.com/sivchari/tenv v1.7.1 // indirect
|
||||
github.com/skeema/knownhosts v1.1.0 // indirect
|
||||
github.com/slack-go/slack v0.12.2 // indirect
|
||||
github.com/sonatard/noctx v0.0.2 // indirect
|
||||
github.com/sourcegraph/go-diff v0.7.0 // indirect
|
||||
@ -325,11 +342,12 @@ require (
|
||||
github.com/vbatts/tar-split v0.11.2 // indirect
|
||||
github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 // indirect
|
||||
github.com/xanzy/go-gitlab v0.83.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.1 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xen0n/gosmopolitan v1.2.1 // indirect
|
||||
github.com/yagipy/maintidx v1.0.0 // indirect
|
||||
github.com/yeya24/promlinter v0.2.0 // indirect
|
||||
github.com/ykadowak/zerologlint v0.1.2 // indirect
|
||||
github.com/zclconf/go-cty v1.13.2 // indirect
|
||||
gitlab.com/bosi/decorder v0.2.3 // indirect
|
||||
gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect
|
||||
go.mongodb.org/mongo-driver v1.11.3 // indirect
|
||||
|
100
tools/go.sum
100
tools/go.sum
@ -535,6 +535,9 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
||||
github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
|
||||
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
|
||||
github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
@ -543,8 +546,8 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX
|
||||
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
@ -566,9 +569,8 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenPeeDeeP/depguard/v2 v2.1.0 h1:aQl70G173h/GZYhWf36aE5H0KaujXfVMnn/f1kSDVYY=
|
||||
github.com/OpenPeeDeeP/depguard/v2 v2.1.0/go.mod h1:PUBgk35fX4i7JDmwzlJwJ+GMe6NfO1723wmJMgPThNQ=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3 h1:XcF0cTDJeiuZ5NU8w7WUDge0HRwwNRmxj/GGk6KSA6g=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f h1:CGq7OieOz3wyQJ1fO8S0eO9TCW1JyvLrf8fhzz1i8ko=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.2.2 h1:u2m7xt+CZWj88qK1UUNBoXeJCFJwJCZ/Ff4ymGoxEXs=
|
||||
@ -580,8 +582,8 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:H
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
|
||||
github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@ -600,9 +602,11 @@ github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pO
|
||||
github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE=
|
||||
github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw=
|
||||
github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
@ -610,6 +614,7 @@ github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4
|
||||
github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
@ -726,6 +731,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
@ -755,6 +761,7 @@ github.com/butuzov/ireturn v0.2.0 h1:kCHi+YzC150GE98WFuZQu9yrTn6GEydO2AuPLbTgnO4
|
||||
github.com/butuzov/ireturn v0.2.0/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc=
|
||||
github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI=
|
||||
github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/caarlos0/ctrlc v1.2.0 h1:AtbThhmbeYx1WW3WXdWrd94EHKi+0NPRGS4/4pzrjwk=
|
||||
github.com/caarlos0/ctrlc v1.2.0/go.mod h1:n3gDlSjsXZ7rbD9/RprIR040b7oaLfNStikPd4gFago=
|
||||
github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0=
|
||||
@ -816,6 +823,9 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
@ -1049,8 +1059,8 @@ github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@ -1091,7 +1101,6 @@ github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y=
|
||||
github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
@ -1118,19 +1127,19 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-critic/go-critic v0.8.1 h1:16omCF1gN3gTzt4j4J6fKI/HnRojhEp+Eks6EuKw3vw=
|
||||
github.com/go-critic/go-critic v0.8.1/go.mod h1:kpzXl09SIJX1cr9TB/g/sAG+eFEl7ZS9f9cqvZtyNl0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
|
||||
github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
|
||||
github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
|
||||
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
|
||||
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
||||
github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk=
|
||||
github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -1535,6 +1544,8 @@ github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FK
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
|
||||
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
@ -1566,6 +1577,8 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
@ -1574,6 +1587,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hc-install v0.5.2 h1:SfwMFnEXVVirpwkDuSF5kymUOhrUxrTq3udEseZdOD0=
|
||||
github.com/hashicorp/hc-install v0.5.2/go.mod h1:9QISwe6newMWIfEiXpzuu1k9HAGtQYgnSH8H9T8wmoI=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
@ -1591,6 +1606,12 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN
|
||||
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
|
||||
github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
|
||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||
github.com/hashicorp/terraform-exec v0.18.1 h1:LAbfDvNQU1l0NOQlTuudjczVhHj061fNX5H8XZxHlH4=
|
||||
github.com/hashicorp/terraform-exec v0.18.1/go.mod h1:58wg4IeuAJ6LVsLUeD2DWZZoc/bYi6dzhLHzxM41980=
|
||||
github.com/hashicorp/terraform-json v0.16.0 h1:UKkeWRWb23do5LNAFlh/K3N0ymn1qTOO8c+85Albo3s=
|
||||
github.com/hashicorp/terraform-json v0.16.0/go.mod h1:v0Ufk9jJnk6tcIZvScHvetlKfiNTC+WS21mnXIlc0B0=
|
||||
github.com/hashicorp/terraform-plugin-docs v0.15.0 h1:W5xYB5kCUBqO7lyjE2UMmUBh95c0aAf4jwO0Xuuw2Ec=
|
||||
github.com/hashicorp/terraform-plugin-docs v0.15.0/go.mod h1:K5Taof1Y7sL4dw6Ie0qMFyQnHN0W+RSVMD0iIyFDFJc=
|
||||
github.com/hetznercloud/hcloud-go v1.33.1/go.mod h1:XX/TQub3ge0yWR2yHWmnDVIrB+MQbda1pHxkUmDlUME=
|
||||
github.com/hetznercloud/hcloud-go v1.39.0/go.mod h1:mepQwR6va27S3UQthaEPGS86jtzSY9xWL1e9dyxXpgA=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
@ -1598,6 +1619,7 @@ github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSo
|
||||
github.com/honeycombio/beeline-go v1.10.0 h1:cUDe555oqvw8oD76BQJ8alk7FP0JZ/M/zXpNvOEDLDc=
|
||||
github.com/honeycombio/libhoney-go v1.16.0 h1:kPpqoz6vbOzgp7jC6SR7SkNj7rua7rgxvznI6M3KdHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
|
||||
@ -1615,6 +1637,7 @@ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
|
||||
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
@ -1713,9 +1736,8 @@ github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSX
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o=
|
||||
github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
@ -1865,6 +1887,9 @@ github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLT
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
|
||||
github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng=
|
||||
github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
@ -1884,8 +1909,10 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
@ -2052,6 +2079,8 @@ github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha
|
||||
github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
@ -2069,6 +2098,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/polyfloyd/go-errorlint v1.4.2 h1:CU+O4181IxFDdPH6t/HT7IiDj1I7zxNi1RIUxYwn8d0=
|
||||
github.com/polyfloyd/go-errorlint v1.4.2/go.mod h1:k6fU/+fQe38ednoZS51T7gSIGQW1y94d6TkSr35OzH8=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
@ -2163,6 +2193,8 @@ github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@ -2201,6 +2233,8 @@ github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAx
|
||||
github.com/shoenig/test v0.6.0/go.mod h1:xYtyGBC5Q3kzCNyJg/SjgNpfAa2kvmgA0i5+lQso8x0=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
@ -2229,6 +2263,8 @@ github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt
|
||||
github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY=
|
||||
github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak=
|
||||
github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg=
|
||||
github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
|
||||
github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
|
||||
github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ=
|
||||
github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
@ -2386,9 +2422,8 @@ github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 h1:+dBg5k7nuTE38
|
||||
github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1/go.mod h1:nmuySobZb4kFgFy6BptpXp/BBw+xFSyvVPP6auoJB4k=
|
||||
github.com/xanzy/go-gitlab v0.83.0 h1:37p0MpTPNbsTMKX/JnmJtY8Ch1sFiJzVF342+RvZEGw=
|
||||
github.com/xanzy/go-gitlab v0.83.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw=
|
||||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
|
||||
github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo=
|
||||
github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
@ -2423,6 +2458,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0=
|
||||
github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0=
|
||||
gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE=
|
||||
@ -2546,11 +2583,11 @@ go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||
gocloud.dev v0.29.0 h1:fBy0jwJSmxs0IjT0fE32MO+Mj+307VZQwyHaTyFZbC4=
|
||||
gocloud.dev v0.29.0/go.mod h1:E3dAjji80g+lIkq4CQeF/BTWqv1CBeTftmOb+gpyapQ=
|
||||
golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
@ -2563,8 +2600,10 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
@ -2584,8 +2623,10 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0
|
||||
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
@ -2699,7 +2740,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
@ -2727,6 +2767,7 @@ golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20220921155015-db77216a4ee9/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
@ -2738,6 +2779,7 @@ golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmL
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -2890,7 +2932,6 @@ golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -2940,6 +2981,7 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -2954,6 +2996,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
@ -3436,6 +3479,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
|
@ -1,6 +1,12 @@
|
||||
//go:build tools
|
||||
// +build tools
|
||||
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package tools
|
||||
|
||||
// Manage tool dependencies via go.mod.
|
||||
@ -10,4 +16,5 @@ package tools
|
||||
import (
|
||||
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
|
||||
_ "github.com/goreleaser/goreleaser"
|
||||
_ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs"
|
||||
)
|
||||
|
34
utils/env.go
Normal file
34
utils/env.go
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import "os"
|
||||
|
||||
// GetAnyStringEnv returns the first non-empty string value from the environment variables.
|
||||
func GetAnyStringEnv(ks ...string) string {
|
||||
for _, k := range ks {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetAnyBoolEnv returns the first non-empty boolean value from the environment variables.
|
||||
func GetAnyBoolEnv(ks ...string) bool {
|
||||
val := ""
|
||||
|
||||
for _, k := range ks {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
val = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return val == "true" || val == "1"
|
||||
}
|
Loading…
Reference in New Issue
Block a user