diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 06c9cab3f..f44a9a603 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -13,16 +13,8 @@ jobs: name: Analyze (${{ matrix.language }}) runs-on: ubuntu-latest permissions: - # required for all workflows security-events: write - # required to fetch internal or private CodeQL packs - packages: read - - # only required for workflows in private repositories - actions: read - contents: read - strategy: fail-fast: false matrix: diff --git a/go.work b/go.work index 9f6d7df5e..ae3c9f159 100644 --- a/go.work +++ b/go.work @@ -1,4 +1,4 @@ -go 1.22 +go 1.22.0 use ( . diff --git a/go.work.sum b/go.work.sum index 2f19f081f..5cc18d7e6 100644 --- a/go.work.sum +++ b/go.work.sum @@ -51,6 +51,8 @@ golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ug golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= @@ -60,11 +62,9 @@ golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= diff --git a/instances.go b/instances.go index d996bef70..6903fa766 100644 --- a/instances.go +++ b/instances.go @@ -72,11 +72,12 @@ type Instance struct { // InstanceSpec represents a linode spec type InstanceSpec struct { - Disk int `json:"disk"` - Memory int `json:"memory"` - VCPUs int `json:"vcpus"` - Transfer int `json:"transfer"` - GPUs int `json:"gpus"` + Disk int `json:"disk"` + Memory int `json:"memory"` + VCPUs int `json:"vcpus"` + Transfer int `json:"transfer"` + GPUs int `json:"gpus"` + AcceleratedDevices int `json:"accelerated_devices"` } // InstanceAlert represents a metric alert diff --git a/k8s/go.mod b/k8s/go.mod index e7af6a53d..0256c2a81 100644 --- a/k8s/go.mod +++ b/k8s/go.mod @@ -37,7 +37,7 @@ require ( golang.org/x/time v0.6.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.66.6 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.110.1 // indirect @@ -51,3 +51,5 @@ require ( replace github.com/linode/linodego => ../ go 1.22 + +toolchain go1.22.1 diff --git a/k8s/go.sum b/k8s/go.sum index c2635ca37..f34753976 100644 --- a/k8s/go.sum +++ b/k8s/go.sum @@ -128,8 +128,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/regions.go b/regions.go index 744355cdb..2aad42189 100644 --- a/regions.go +++ b/regions.go @@ -22,6 +22,7 @@ const ( CapabilityVlans string = "Vlans" CapabilityVPCs string = "VPCs" CapabilityVPCsExtra string = "VPCs Extra" + CapabilityQuadraT1UVPU string = "NETINT Quadra T1U" CapabilityMachineImages string = "Machine Images" CapabilityBareMetal string = "Bare Metal" CapabilityDBAAS string = "Managed Databases" diff --git a/test/go.mod b/test/go.mod index 2191b9b80..e63ae22d0 100644 --- a/test/go.mod +++ b/test/go.mod @@ -7,6 +7,7 @@ require ( github.com/linode/linodego v1.33.0 github.com/linode/linodego/k8s v0.0.0-00010101000000-000000000000 github.com/stretchr/testify v1.10.0 + golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 golang.org/x/net v0.34.0 golang.org/x/oauth2 v0.25.0 k8s.io/client-go v0.29.4 @@ -42,7 +43,7 @@ require ( golang.org/x/time v0.6.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.66.6 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.29.4 // indirect @@ -55,7 +56,9 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) -go 1.22 +go 1.22.0 + +toolchain go1.22.1 replace github.com/linode/linodego => ../ diff --git a/test/go.sum b/test/go.sum index 5c6b959a2..77986261b 100644 --- a/test/go.sum +++ b/test/go.sum @@ -92,6 +92,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -122,8 +124,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -135,8 +137,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/test/integration/fixtures/TestInstance_withVPU.yaml b/test/integration/fixtures/TestInstance_withVPU.yaml new file mode 100644 index 000000000..72b52adb1 --- /dev/null +++ b/test/integration/fixtures/TestInstance_withVPU.yaml @@ -0,0 +1,433 @@ +--- +version: 1 +interactions: +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/regions?page=1 + method: GET + response: + body: '{"data": [{"id": "ap-west", "label": "Mumbai, IN", "country": "in", "capabilities": + ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", "Block Storage", + "GPU Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "172.105.34.5,172.105.35.5,172.105.36.5,172.105.37.5,172.105.38.5,172.105.39.5,172.105.40.5,172.105.41.5,172.105.42.5,172.105.43.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "ca-central", "label": "Toronto, CA", "country": + "ca", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "172.105.0.5,172.105.3.5,172.105.4.5,172.105.5.5,172.105.6.5,172.105.7.5,172.105.8.5,172.105.9.5,172.105.10.5,172.105.11.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "ap-southeast", "label": "Sydney, AU", "country": + "au", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "172.105.166.5,172.105.169.5,172.105.168.5,172.105.172.5,172.105.162.5,172.105.170.5,172.105.167.5,172.105.171.5,172.105.181.5,172.105.161.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-iad", "label": "Washington, DC", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": + "139.144.192.62,139.144.192.60,139.144.192.61,139.144.192.53,139.144.192.54,139.144.192.67,139.144.192.69,139.144.192.66,139.144.192.52,139.144.192.68", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-ord", "label": "Chicago, IL", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", + "Premium Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": + {"ipv4": "172.232.0.17,172.232.0.16,172.232.0.21,172.232.0.13,172.232.0.22,172.232.0.9,172.232.0.19,172.232.0.20,172.232.0.15,172.232.0.18", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "fr-par", "label": "Paris, FR", "country": + "fr", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", + "Premium Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": + {"ipv4": "172.232.32.21,172.232.32.23,172.232.32.17,172.232.32.18,172.232.32.16,172.232.32.22,172.232.32.20,172.232.32.14,172.232.32.11,172.232.32.12", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-sea", "label": "Seattle, WA", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", + "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.232.160.19,172.232.160.21,172.232.160.17,172.232.160.15,172.232.160.18,172.232.160.8,172.232.160.12,172.232.160.11,172.232.160.14,172.232.160.16", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "br-gru", "label": "Sao Paulo, BR", "country": + "br", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.233.0.4,172.233.0.9,172.233.0.7,172.233.0.12,172.233.0.5,172.233.0.13,172.233.0.10,172.233.0.6,172.233.0.8,172.233.0.11", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "nl-ams", "label": "Amsterdam, NL", "country": + "nl", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": + "172.233.33.36,172.233.33.38,172.233.33.35,172.233.33.39,172.233.33.34,172.233.33.33,172.233.33.31,172.233.33.30,172.233.33.37,172.233.33.32", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "se-sto", "label": "Stockholm, SE", "country": + "se", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": + "172.232.128.24,172.232.128.26,172.232.128.20,172.232.128.22,172.232.128.25,172.232.128.19,172.232.128.23,172.232.128.18,172.232.128.21,172.232.128.27", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "es-mad", "label": "Madrid, ES", "country": + "es", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.233.111.6,172.233.111.17,172.233.111.21,172.233.111.25,172.233.111.19,172.233.111.12,172.233.111.26,172.233.111.16,172.233.111.18,172.233.111.9", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "in-maa", "label": "Chennai, IN", "country": + "in", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts", "NETINT Quadra T1U"], "status": "ok", + "resolvers": {"ipv4": "172.232.96.17,172.232.96.26,172.232.96.19,172.232.96.20,172.232.96.25,172.232.96.21,172.232.96.18,172.232.96.22,172.232.96.23,172.232.96.24", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "jp-osa", "label": "Osaka, JP", "country": + "jp", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", + "Premium Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": + {"ipv4": "172.233.64.44,172.233.64.43,172.233.64.37,172.233.64.40,172.233.64.46,172.233.64.41,172.233.64.39,172.233.64.42,172.233.64.45,172.233.64.38", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "it-mil", "label": "Milan, IT", "country": + "it", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.232.192.19,172.232.192.18,172.232.192.16,172.232.192.20,172.232.192.24,172.232.192.21,172.232.192.22,172.232.192.17,172.232.192.15,172.232.192.23", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-mia", "label": "Miami, FL", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts", "NETINT Quadra T1U"], "status": "ok", + "resolvers": {"ipv4": "172.233.160.34,172.233.160.27,172.233.160.30,172.233.160.29,172.233.160.32,172.233.160.28,172.233.160.33,172.233.160.26,172.233.160.25,172.233.160.31", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "id-cgk", "label": "Jakarta, ID", "country": + "id", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.232.224.23,172.232.224.32,172.232.224.26,172.232.224.27,172.232.224.21,172.232.224.24,172.232.224.22,172.232.224.20,172.232.224.31,172.232.224.28", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-lax", "label": "Los Angeles, CA", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts", "NETINT Quadra T1U"], "status": "ok", "resolvers": {"ipv4": + "172.233.128.45,172.233.128.38,172.233.128.53,172.233.128.37,172.233.128.34,172.233.128.36,172.233.128.33,172.233.128.39,172.233.128.43,172.233.128.44", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "gb-lon", "label": "London 2, UK", "country": + "gb", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": + "172.236.0.46,172.236.0.50,172.236.0.47,172.236.0.53,172.236.0.52,172.236.0.45,172.236.0.49,172.236.0.51,172.236.0.54,172.236.0.48", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "au-mel", "label": "Melbourne, AU", "country": + "au", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts", "NETINT Quadra T1U"], "status": "ok", + "resolvers": {"ipv4": "172.236.32.23,172.236.32.35,172.236.32.30,172.236.32.28,172.236.32.32,172.236.32.33,172.236.32.27,172.236.32.37,172.236.32.29,172.236.32.34", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "in-bom-2", "label": "Mumbai 2, IN", "country": + "in", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.236.171.41,172.236.171.42,172.236.171.25,172.236.171.44,172.236.171.26,172.236.171.45,172.236.171.24,172.236.171.43,172.236.171.27,172.236.171.28", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "de-fra-2", "label": "Frankfurt 2, DE", "country": + "de", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", + "Placement Group", "StackScripts", "NETINT Quadra T1U"], "status": "ok", "resolvers": + {"ipv4": "172.236.203.9,172.236.203.16,172.236.203.19,172.236.203.15,172.236.203.17,172.236.203.11,172.236.203.18,172.236.203.14,172.236.203.13,172.236.203.12", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "sg-sin-2", "label": "Singapore 2, SG", "country": + "sg", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", + "Premium Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": + {"ipv4": "172.236.129.8,172.236.129.42,172.236.129.41,172.236.129.19,172.236.129.46,172.236.129.23,172.236.129.48,172.236.129.20,172.236.129.21,172.236.129.47", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "jp-tyo-3", "label": "Tokyo 3, JP", "country": + "jp", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Kubernetes", "Cloud Firewall", + "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", "StackScripts"], + "status": "ok", "resolvers": {"ipv4": "172.237.4.15,172.237.4.19,172.237.4.17,172.237.4.21,172.237.4.16,172.237.4.18,172.237.4.23,172.237.4.24,172.237.4.20,172.237.4.14", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-central", "label": "Dallas, TX", "country": + "us", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "72.14.179.5,72.14.188.5,173.255.199.5,66.228.53.5,96.126.122.5,96.126.124.5,96.126.127.5,198.58.107.5,198.58.111.5,23.239.24.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-west", "label": "Fremont, CA", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Kubernetes", "Cloud Firewall", + "Vlans", "Block Storage Migrations", "Managed Databases", "Metadata", "Placement + Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "173.230.145.5, + 173.230.147.5, 173.230.155.5, 173.255.212.5, 173.255.219.5, 173.255.241.5, 173.255.243.5, + 173.255.244.5, 74.207.241.5, 74.207.242.5", "ipv6": "1234::5678, 1234::5678, + 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, + 1234::5678, 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": + null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-southeast", + "label": "Atlanta, GA", "country": "us", "capabilities": ["Linodes", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", "Managed + Databases", "Metadata", "Placement Group", "StackScripts"], "status": "ok", + "resolvers": {"ipv4": "74.207.231.5,173.230.128.5,173.230.129.5,173.230.136.5,173.230.140.5,66.228.59.5,66.228.62.5,50.116.35.5,50.116.41.5,23.239.18.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-east", "label": "Newark, NJ", "country": + "us", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", + "Vlans", "Block Storage Migrations", "Managed Databases", "Metadata", "Placement + Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "66.228.42.5, + 96.126.106.5, 50.116.53.5, 50.116.58.5, 50.116.61.5, 50.116.62.5, 66.175.211.5, + 97.107.133.4, 207.192.69.4, 207.192.69.5", "ipv6": "1234::5678, 1234::5678, + 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, + 1234::5678, 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": + null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "eu-west", + "label": "London, UK", "country": "gb", "capabilities": ["Linodes", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Kubernetes", "Cloud Firewall", + "Vlans", "Block Storage Migrations", "Metadata", "Placement Group", "StackScripts"], + "status": "ok", "resolvers": {"ipv4": "178.79.182.5, 176.58.107.5, 176.58.116.5, + 176.58.121.5, 151.236.220.5, 212.71.252.5, 212.71.253.5, 109.74.192.20, 109.74.193.20, + 109.74.194.20", "ipv6": "1234::5678, 1234::5678, 1234::5678, 1234::5678, + 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "ap-south", "label": "Singapore, SG", "country": + "sg", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", + "Vlans", "Block Storage Migrations", "Metadata", "Placement Group", "StackScripts"], + "status": "ok", "resolvers": {"ipv4": "139.162.11.5,139.162.13.5,139.162.14.5,139.162.15.5,139.162.16.5,139.162.21.5,139.162.27.5,103.3.60.18,103.3.60.19,103.3.60.20", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "eu-central", "label": "Frankfurt, DE", "country": + "de", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", + "Vlans", "Block Storage Migrations", "Managed Databases", "Metadata", "Placement + Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "139.162.130.5,139.162.131.5,139.162.132.5,139.162.133.5,139.162.134.5,139.162.135.5,139.162.136.5,139.162.137.5,139.162.138.5,139.162.139.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "ap-northeast", "label": "Tokyo 2, JP", "country": + "jp", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "139.162.66.5,139.162.67.5,139.162.68.5,139.162.69.5,139.162.70.5,139.162.71.5,139.162.72.5,139.162.73.5,139.162.74.5,139.162.75.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}], "page": 1, "pages": 1, "results": 31}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Tue, 17 Dec 2024 21:17:55 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - '*' + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - '*' + X-Ratelimit-Limit: + - "1600" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"region":"us-lax","type":"g1-accelerated-netint-vpu-t1u1-s","label":"go-inst-test-create-vpu","root_pass":"*;m69FwMc01;1xhofX*Hh[S?G$zO678in4I\u0026d)w9k5E!7^80ZK2B`JkV\u003e\u003e5I;Fi-","image":"linode/debian12","firewall_id":1384634,"booted":false}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/linode/instances + method: POST + response: + body: '{"id": 68664304, "label": "go-inst-test-create-vpu", "group": "", "status": + "provisioning", "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", + "type": "g1-accelerated-netint-vpu-t1u1-s", "ipv4": ["172.235.54.133"], "ipv6": + "1234::5678/128", "image": "linode/debian12", "region": + "us-lax", "site_type": "core", "specs": {"disk": 204800, "memory": 16384, "vcpus": + 8, "gpus": 0, "transfer": 0, "accelerated_devices": 1}, "alerts": {"cpu": 720, + "network_in": 10, "network_out": 10, "transfer_quota": 80, "io": 10000}, "backups": + {"enabled": true, "available": false, "schedule": {"day": null, "window": null}, + "last_successful": null}, "hypervisor": "kvm", "watchdog_enabled": true, "tags": + [], "host_uuid": "c7ddd1b17f8d9fe4b82fa29a2ae05811a400fae2", "has_user_data": + false, "placement_group": null, "disk_encryption": "enabled", "lke_cluster_id": + null, "capabilities": ["Block Storage Encryption"]}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Tue, 17 Dec 2024 21:17:56 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - linodes:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - '*' + X-Ratelimit-Limit: + - "8" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/linode/instances/68664304 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Tue, 17 Dec 2024 21:17:57 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - linodes:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - '*' + X-Ratelimit-Limit: + - "1600" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/instances_test.go b/test/integration/instances_test.go index ac3ec828a..395e25817 100644 --- a/test/integration/instances_test.go +++ b/test/integration/instances_test.go @@ -869,6 +869,24 @@ func TestInstance_withBlockStorageEncryption(t *testing.T) { require.True(t, slices.Contains(inst.Capabilities, "Block Storage Encryption")) } +func TestInstance_withVPU(t *testing.T) { + client, clientTeardown := createTestClient(t, "fixtures/TestInstance_withVPU") + + inst, err := createInstance(t, client, true, func(client *linodego.Client, options *linodego.InstanceCreateOptions) { + options.Region = "us-lax" + options.Type = "g1-accelerated-netint-vpu-t1u1-s" + options.Label = "go-inst-test-create-vpu" + }) + require.NoError(t, err) + + defer func() { + client.DeleteInstance(context.Background(), inst.ID) + clientTeardown() + }() + + require.NotNil(t, inst.Specs.AcceleratedDevices) +} + func TestInstance_withPG(t *testing.T) { client, clientTeardown := createTestClient(t, "fixtures/TestInstance_withPG") diff --git a/test/unit/fixtures/linode_type_get.json b/test/unit/fixtures/linode_type_get.json new file mode 100644 index 000000000..040207e0a --- /dev/null +++ b/test/unit/fixtures/linode_type_get.json @@ -0,0 +1,26 @@ +{ + "id": "g6-standard-2", + "disk": 4000, + "class": "standard", + "price": { + "hourly": 0.015, + "monthly": 10 + }, + "label": "Linode 2GB", + "addons": { + "backups": { + "price": { + "hourly": 0.003, + "monthly": 2 + }, + "region_prices": [] + } + }, + "region_prices": [], + "network_out": 2000, + "memory": 4000, + "transfer": 500, + "vcpus": 2, + "gpus": 0, + "successor": null +} diff --git a/test/unit/fixtures/linode_types_list.json b/test/unit/fixtures/linode_types_list.json new file mode 100644 index 000000000..67eec4707 --- /dev/null +++ b/test/unit/fixtures/linode_types_list.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "id": "g6-nanode-1", + "disk": 25600, + "class": "nanode", + "price": { + "hourly": 0.0075, + "monthly": 5 + }, + "label": "Nanode 1GB", + "addons": null, + "region_prices": [], + "network_out": 1000, + "memory": 1024, + "transfer": 250, + "vcpus": 1, + "gpus": 0, + "successor": null + }, + { + "id": "g6-standard-2", + "disk": 51200, + "class": "standard", + "price": { + "hourly": 0.015, + "monthly": 10 + }, + "label": "Linode 2GB", + "addons": null, + "region_prices": [], + "network_out": 2000, + "memory": 2048, + "transfer": 500, + "vcpus": 2, + "gpus": 0, + "successor": null + } + ], + "page": 1, + "pages": 1, + "results": 2 + } + \ No newline at end of file diff --git a/test/unit/fixtures/tag_create.json b/test/unit/fixtures/tag_create.json new file mode 100644 index 000000000..fa35f0e97 --- /dev/null +++ b/test/unit/fixtures/tag_create.json @@ -0,0 +1,3 @@ +{ + "label": "new-tag" +} diff --git a/test/unit/fixtures/tagged_objects_list.json b/test/unit/fixtures/tagged_objects_list.json new file mode 100644 index 000000000..5a1abd60a --- /dev/null +++ b/test/unit/fixtures/tagged_objects_list.json @@ -0,0 +1,15 @@ +{ + "data": [ + { + "type": "linode", + "data": { + "id": 12345, + "label": "example-instance", + "region": "us-east" + } + } + ], + "page": 1, + "pages": 1, + "results": 1 + } \ No newline at end of file diff --git a/test/unit/fixtures/tags_list.json b/test/unit/fixtures/tags_list.json new file mode 100644 index 000000000..3d7318819 --- /dev/null +++ b/test/unit/fixtures/tags_list.json @@ -0,0 +1,10 @@ +{ + "data": [ + { + "label": "example-tag" + } + ], + "page": 1, + "pages": 1, + "results": 1 + } \ No newline at end of file diff --git a/test/unit/fixtures/vlan_get_ipam_address.json b/test/unit/fixtures/vlan_get_ipam_address.json new file mode 100644 index 000000000..d294d9f8f --- /dev/null +++ b/test/unit/fixtures/vlan_get_ipam_address.json @@ -0,0 +1,15 @@ +{ + "data": [ + { + "interfaces": [ + { + "label": "test-vlan", + "ipam_address": "10.0.0.1/24" + } + ] + } + ], + "page": 1, + "pages": 1, + "results": 1 +} diff --git a/test/unit/fixtures/vlans_list.json b/test/unit/fixtures/vlans_list.json new file mode 100644 index 000000000..5572e8074 --- /dev/null +++ b/test/unit/fixtures/vlans_list.json @@ -0,0 +1,13 @@ +{ + "data": [ + { + "label": "test-vlan", + "linodes": [12345], + "region": "us-east", + "created": "2024-12-01T12:00:00" + } + ], + "page": 1, + "pages": 1, + "results": 1 +} diff --git a/test/unit/tag_test.go b/test/unit/tag_test.go new file mode 100644 index 000000000..3cfaef762 --- /dev/null +++ b/test/unit/tag_test.go @@ -0,0 +1,122 @@ +package unit + +import ( + "context" + "fmt" + "testing" + + "github.com/linode/linodego" + "github.com/stretchr/testify/assert" + "golang.org/x/exp/slices" +) + +func TestListTags(t *testing.T) { + // Load the fixture data for tags + fixtureData, err := fixtures.GetFixture("tags_list") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("tags", fixtureData) + + tags, err := base.Client.ListTags(context.Background(), &linodego.ListOptions{}) + assert.NoError(t, err) + + assert.NotEmpty(t, tags, "Expected non-empty tag list") + + // Check if a specific tag exists using slices.ContainsFunc + exists := slices.ContainsFunc(tags, func(tag linodego.Tag) bool { + return tag.Label == "example-tag" + }) + + assert.True(t, exists, "Expected tag list to contain 'example-tag'") +} + + +func TestCreateTag(t *testing.T) { + // Load the fixture data for tag creation + fixtureData, err := fixtures.GetFixture("tag_create") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockPost("tags", fixtureData) + + opts := linodego.TagCreateOptions{ + Label: "new-tag", + } + + tag, err := base.Client.CreateTag(context.Background(), opts) + assert.NoError(t, err, "Expected no error when creating tag") + + // Verify the created tag's label + assert.Equal(t, "new-tag", tag.Label, "Expected created tag label to match input") +} + + +func TestDeleteTag(t *testing.T) { + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + tagLabel := "delete-tag" + base.MockDelete(fmt.Sprintf("tags/%s", tagLabel), nil) + + err := base.Client.DeleteTag(context.Background(), tagLabel) + assert.NoError(t, err, "Expected no error when deleting tag") +} + +func TestListTaggedObjects(t *testing.T) { + // Load the fixture data for tagged objects + fixtureData, err := fixtures.GetFixture("tagged_objects_list") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + tagLabel := "example-tag" + base.MockGet(fmt.Sprintf("tags/%s", tagLabel), fixtureData) + + taggedObjects, err := base.Client.ListTaggedObjects(context.Background(), tagLabel, &linodego.ListOptions{}) + assert.NoError(t, err) + + assert.NotEmpty(t, taggedObjects, "Expected non-empty tagged objects list") + + // Find the specific tagged object using slices.IndexFunc + index := slices.IndexFunc(taggedObjects, func(obj linodego.TaggedObject) bool { + return obj.Type == "linode" + }) + + assert.NotEqual(t, -1, index, "Expected to find a tagged object of type 'linode'") + if index != -1 { + assert.Equal(t, "linode", taggedObjects[index].Type, "Expected tagged object type to be 'linode'") + } +} + + +func TestSortedObjects(t *testing.T) { + // Load the fixture data for tagged objects + fixtureData, err := fixtures.GetFixture("tagged_objects_list") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + tagLabel := "example-tag" + base.MockGet(fmt.Sprintf("tags/%s", tagLabel), fixtureData) + + taggedObjects, err := base.Client.ListTaggedObjects(context.Background(), tagLabel, &linodego.ListOptions{}) + assert.NoError(t, err) + + sortedObjects, err := taggedObjects.SortedObjects() + assert.NoError(t, err) + + assert.NotEmpty(t, sortedObjects.Instances, "Expected non-empty instances list in sorted objects") + assert.Equal(t, "example-instance", sortedObjects.Instances[0].Label, "Expected instance label to be 'example-instance'") +} diff --git a/test/unit/types_test.go b/test/unit/types_test.go new file mode 100644 index 000000000..25e1623cf --- /dev/null +++ b/test/unit/types_test.go @@ -0,0 +1,75 @@ +package unit + +import ( + "context" + "fmt" + "github.com/linode/linodego" + "github.com/stretchr/testify/assert" + "testing" + "golang.org/x/exp/slices" + +) + +func TestLinodeTypes_List(t *testing.T) { + // Load the fixture data for types + fixtureData, err := fixtures.GetFixture("linode_types_list") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("linode/types", fixtureData) + + types, err := base.Client.ListTypes(context.Background(), &linodego.ListOptions{}) + assert.NoError(t, err) + + // Use slices.IndexFunc to find the index of the specific type + index := slices.IndexFunc(types, func(t linodego.LinodeType) bool { + return t.ID == "g6-nanode-1" + }) + + if index == -1 { + t.Errorf("Expected type 'g6-nanode-1' to be in the response, but it was not found") + } else { + nanodeType := types[index] + assert.Equal(t, "nanode", string(nanodeType.Class), "Expected class to be 'nanode'") + assert.Equal(t, 1, nanodeType.VCPUs, "Expected VCPUs for 'g6-nanode-1' to be 1") + assert.Equal(t, 250, nanodeType.Transfer, "Expected transfer for 'g6-nanode-1' to be 250GB") + assert.NotNil(t, nanodeType.Price, "Expected 'g6-nanode-1' to have a price object") + if nanodeType.Price != nil { + assert.Equal(t, float32(5), nanodeType.Price.Monthly, "Expected monthly price for 'g6-nanode-1' to be $5") + } + } +} + +func TestLinodeType_Get(t *testing.T) { + // Load the fixture data for a specific type + fixtureData, err := fixtures.GetFixture("linode_type_get") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + typeID := "g6-standard-2" + base.MockGet(fmt.Sprintf("linode/types/%s", typeID), fixtureData) + + typeObj, err := base.Client.GetType(context.Background(), typeID) + assert.NoError(t, err) + + assert.Equal(t, typeID, typeObj.ID, "Expected type ID to match") + assert.Equal(t, "standard", string(typeObj.Class), "Expected class to be 'standard'") + assert.Equal(t, 2, typeObj.VCPUs, "Expected VCPUs to be 2") + assert.Equal(t, 4000, typeObj.Disk, "Expected disk to be 4000MB") + assert.Equal(t, 4000, typeObj.Memory, "Expected memory to be 4000MB") + assert.NotNil(t, typeObj.Price, "Expected type to have a price object") + if typeObj.Price != nil { + assert.Equal(t, float32(10), typeObj.Price.Monthly, "Expected monthly price to be $10") + } + + assert.NotNil(t, typeObj.Addons, "Expected type to have addons") + if typeObj.Addons != nil && typeObj.Addons.Backups != nil { + assert.NotNil(t, typeObj.Addons.Backups.Price, "Expected backups to have a price object") + } +} diff --git a/test/unit/vlan_test.go b/test/unit/vlan_test.go new file mode 100644 index 000000000..8fcfd680e --- /dev/null +++ b/test/unit/vlan_test.go @@ -0,0 +1,63 @@ +package unit + +import ( + "context" + "fmt" + "github.com/linode/linodego" + "github.com/stretchr/testify/assert" + "golang.org/x/exp/slices" + "testing" +) + +func TestVLAN_List(t *testing.T) { + // Load the fixture data for VLANs + fixtureData, err := fixtures.GetFixture("vlans_list") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + // Mock the GET request + base.MockGet("networking/vlans", fixtureData) + + vlans, err := base.Client.ListVLANs(context.Background(), &linodego.ListOptions{}) + assert.NoError(t, err) + assert.NotEmpty(t, vlans, "Expected non-empty VLAN list") + + // Use slices.IndexFunc to find the index of the specific VLAN + index := slices.IndexFunc(vlans, func(v linodego.VLAN) bool { + return v.Label == "test-vlan" + }) + + if index == -1 { + t.Errorf("Expected VLAN 'test-vlan' to be in the response, but it was not found") + } else { + testVLAN := vlans[index] + assert.Equal(t, "us-east", testVLAN.Region, "Expected region to be 'us-east'") + assert.Contains(t, testVLAN.Linodes, 12345, "Expected Linodes to include 12345") + assert.NotNil(t, testVLAN.Created, "Expected 'test-vlan' to have a created timestamp") + } +} + +func TestVLAN_GetIPAMAddress(t *testing.T) { + // Load the fixture data for VLAN IPAM address + fixtureData, err := fixtures.GetFixture("vlan_get_ipam_address") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + linodeID := 12345 + vlanLabel := "test-vlan" + // Mock the GET request + base.MockGet(fmt.Sprintf("linode/instances/%d/configs", linodeID), fixtureData) + + ipamAddress, err := base.Client.GetVLANIPAMAddress(context.Background(), linodeID, vlanLabel) + assert.NoError(t, err) + assert.NotEmpty(t, ipamAddress, "Expected non-empty IPAM address") + + // Verify the returned IPAM address + assert.Equal(t, "10.0.0.1/24", ipamAddress, "Expected IPAM address to be '10.0.0.1/24'") +} diff --git a/types.go b/types.go index bd9b801c9..06b9b8cd0 100644 --- a/types.go +++ b/types.go @@ -7,19 +7,20 @@ import ( // LinodeType represents a linode type object type LinodeType struct { - ID string `json:"id"` - Disk int `json:"disk"` - Class LinodeTypeClass `json:"class"` // enum: nanode, standard, highmem, dedicated, gpu - Price *LinodePrice `json:"price"` - Label string `json:"label"` - Addons *LinodeAddons `json:"addons"` - RegionPrices []LinodeRegionPrice `json:"region_prices"` - NetworkOut int `json:"network_out"` - Memory int `json:"memory"` - Transfer int `json:"transfer"` - VCPUs int `json:"vcpus"` - GPUs int `json:"gpus"` - Successor string `json:"successor"` + ID string `json:"id"` + Disk int `json:"disk"` + Class LinodeTypeClass `json:"class"` // enum: nanode, standard, highmem, dedicated, gpu + Price *LinodePrice `json:"price"` + Label string `json:"label"` + Addons *LinodeAddons `json:"addons"` + RegionPrices []LinodeRegionPrice `json:"region_prices"` + NetworkOut int `json:"network_out"` + Memory int `json:"memory"` + Transfer int `json:"transfer"` + VCPUs int `json:"vcpus"` + GPUs int `json:"gpus"` + Successor string `json:"successor"` + AcceleratedDevices int `json:"accelerated_devices"` } // LinodePrice represents a linode type price object