diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-add-rules-usage.cassette.yaml b/cmd/scw/testdata/test-all-usage-instance-security-group-add-rules-usage.cassette.yaml new file mode 100644 index 0000000000..2797c38e00 --- /dev/null +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-add-rules-usage.cassette.yaml @@ -0,0 +1,3 @@ +--- +version: 2 +interactions: [] diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-add-rules-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-add-rules-usage.golden new file mode 100644 index 0000000000..3a4794fda0 --- /dev/null +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-add-rules-usage.golden @@ -0,0 +1,33 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +Add one or more rules to a security group. + +USAGE: + scw instance security-group add-rules [arg=value ...] + +ARGS: + security-group-id ID of the security group to add rules to + [rules.{index}.protocol] Protocol for the rule (unknown_protocol | tcp | udp | icmp | any) + [rules.{index}.direction] Direction of traffic for the rule (unknown_direction | inbound | outbound | both) + [rules.{index}.action] Action to take when the rule matches (unknown_action | accept | drop) + [rules.{index}.source-ip-range] Source IP range for the rule + [rules.{index}.destination-ip-range] Destination IP range for the rule + [rules.{index}.source-ports.start] Start of the port range + [rules.{index}.source-ports.end] End of the port range + [rules.{index}.destination-ports.start] Start of the port range + [rules.{index}.destination-ports.end] End of the port range + [rules.{index}.position] Position of this rule in the rule list, starting at 1 + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) + +FLAGS: + -h, --help help for add-rules + --list-sub-commands List all subcommands + +GLOBAL FLAGS: + -B, --beta Enable beta mode + -c, --config string The path to the config file + -D, --debug Enable debug mode + -H, --no-headers Skip headers in human output + -o, --output string Output format: json or human, see 'scw help output' for more info (default "human") + -p, --profile string The config profile to use + --web open console page for the current resource diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-clear-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-clear-usage.golden index 6e26297bc2..c1c0f271fc 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-clear-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-clear-usage.golden @@ -3,15 +3,15 @@ Remove all rules of a security group USAGE: - scw instance security-group clear [arg=value ...] + scw instance security-group clear [arg=value ...] EXAMPLES: Remove all rules of the given security group - scw instance security-group clear security-group-id=11111111-1111-1111-1111-111111111111 + scw instance security-group clear 11111111-1111-1111-1111-111111111111 ARGS: security-group-id ID of the security group to reset. - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1) + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for clear diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-create-rule-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-create-rule-usage.golden index ffe3d50db2..e129af2eca 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-create-rule-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-create-rule-usage.golden @@ -1,5 +1,6 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +Command "create-rule" is deprecated, it is not available in v2 of the API and will be removed when v1 reaches end of support. Rules can be created using "scw instance security-group add-rules [arg=value ...]". Create a rule in the specified security group ID. USAGE: diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-create-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-create-usage.golden index 9ca5345b29..09111d970b 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-create-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-create-usage.golden @@ -7,35 +7,31 @@ USAGE: EXAMPLES: Create a security group with a specified name and description - scw instance security-group create name=foobar description=foobar foobar + scw instance security-group create name=foobar description="foobar foobar" Create a security group that will be applied as default on all Instances of this Project scw instance security-group create project-default=true Create a security group that will have a default drop inbound policy (traffic your Instance receives) - scw instance security-group create inbound-default-policy=drop + scw instance security-group create inbound-default-action=drop Create a security group that will have a default drop outbound policy (traffic your Instance transmits) - scw instance security-group create outbound-default-policy=drop + scw instance security-group create outbound-default-action=drop Create a stateless security group - scw instance security-group create + scw instance security-group create stateless=true ARGS: name= Name of the security group [description] Description of the security group + [disable-default-rules=false] Whether to disable default rules [project-id] Project ID to use. If none is passed the default project ID will be used - [tags.{index}] Tags of the security group - [project-default] Whether this security group becomes the default security group for new Instances - [stateful=true] Whether the security group is stateful or not - [inbound-default-policy=accept] Default policy for inbound rules (unknown_policy | accept | drop) - [outbound-default-policy=accept] Default policy for outbound rules (unknown_policy | accept | drop) - [enable-default-security] True to block SMTP on IPv4 and IPv6. This feature is read only, please open a support ticket if you need to make it configurable - [organization-id] Organization ID to use. If none is passed the default organization ID will be used - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1) - -DEPRECATED ARGS: - [organization-default] Defines whether this security group becomes the default security group for new Instances + [tags.{index}] Tags for the security group + [project-default] Whether this should be the default security group for the project + [inbound-default-action=accept] Default action for inbound rules (unknown_action | accept | drop) + [outbound-default-action=accept] Default action for outbound rules (unknown_action | accept | drop) + [stateless=false] Whether the security group should be stateless + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for create diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rule-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rule-usage.golden index 126a824855..916d651a2f 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rule-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rule-usage.golden @@ -1,5 +1,6 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +Command "delete-rule" is deprecated, it is not available in v2 of the API and will be removed when v1 reaches end of support. Rules can be deleted using "scw instance security-group delete-rules security-group-rule-ids.0=". Delete a security group rule with the specified ID. USAGE: diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rules-usage.cassette.yaml b/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rules-usage.cassette.yaml new file mode 100644 index 0000000000..2797c38e00 --- /dev/null +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rules-usage.cassette.yaml @@ -0,0 +1,3 @@ +--- +version: 2 +interactions: [] diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rules-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rules-usage.golden new file mode 100644 index 0000000000..d56d277c4b --- /dev/null +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-delete-rules-usage.golden @@ -0,0 +1,23 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +Delete specified security groups. + +USAGE: + scw instance security-group delete-rules [arg=value ...] + +ARGS: + [security-group-rule-ids.{index}] List of rule IDs to delete + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) + +FLAGS: + -h, --help help for delete-rules + --list-sub-commands List all subcommands + +GLOBAL FLAGS: + -B, --beta Enable beta mode + -c, --config string The path to the config file + -D, --debug Enable debug mode + -H, --no-headers Skip headers in human output + -o, --output string Output format: json or human, see 'scw help output' for more info (default "human") + -p, --profile string The config profile to use + --web open console page for the current resource diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-delete-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-delete-usage.golden index 0d959440e9..29abdf0992 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-delete-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-delete-usage.golden @@ -1,6 +1,6 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ -Delete a security group with the specified ID. +Delete a specified security group. USAGE: scw instance security-group delete [arg=value ...] @@ -10,8 +10,8 @@ EXAMPLES: scw instance security-group delete 11111111-1111-1111-1111-111111111111 ARGS: - security-group-id UUID of the security group you want to delete - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1) + security-group-id ID of the security group to delete + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for delete diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-edit-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-edit-usage.golden index 42ef0ba999..e652697496 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-edit-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-edit-usage.golden @@ -9,7 +9,7 @@ USAGE: ARGS: security-group-id ID of the security group to reset. [mode=yaml] marshaling used when editing data (yaml | json) - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1) + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for edit diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-get-rule-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-get-rule-usage.golden index 929bd62bc6..446be8ac8a 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-get-rule-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-get-rule-usage.golden @@ -1,5 +1,6 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +Command "get-rule" is deprecated, it is not available in v2 of the API and will be removed when v1 reaches end of support. Rules can be listed using "scw instance security-group get ". Get details of a security group rule with the specified ID. USAGE: diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-get-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-get-usage.golden index 6ca939337d..124be391b5 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-get-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-get-usage.golden @@ -1,6 +1,6 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ -Get the details of a security group with the specified ID. +Get the details of a specified security group. USAGE: scw instance security-group get [arg=value ...] @@ -10,8 +10,8 @@ EXAMPLES: scw instance security-group get 11111111-1111-1111-1111-111111111111 ARGS: - security-group-id UUID of the security group you want to get - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1) + security-group-id ID of the security group to retrieve + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for get diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-list-default-rules-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-list-default-rules-usage.golden index 2dfdc098e7..b02a5c60f6 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-list-default-rules-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-list-default-rules-usage.golden @@ -1,5 +1,6 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +Command "list-default-rules" is deprecated, it is not available in v2 of the API and will be removed when v1 reaches end of support. Default rules can be listed using "scw instance security-group get ". Lists the default rules applied to all the security groups. USAGE: diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-list-rules-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-list-rules-usage.golden index d048abda50..d5a5d820bd 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-list-rules-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-list-rules-usage.golden @@ -1,5 +1,6 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +Command "list-rules" is deprecated, it is not available in v2 of the API and will be removed when v1 reaches end of support. Rules can be listed using "scw instance security-group get ". List the rules of the a specified security group ID. USAGE: diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-list-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-list-usage.golden index 2e3eccce92..b09e1f06c4 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-list-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-list-usage.golden @@ -1,6 +1,6 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ -List all existing security groups. +List all security groups. USAGE: scw instance security-group list [arg=value ...] @@ -10,12 +10,14 @@ EXAMPLES: scw instance security-group list name=foobar ARGS: - [name] Name of the security group - [project-id] Security group Project ID - [tags] List security groups with these exact tags (to filter with several tags, use commas to separate them) - [project-default] Filter security groups with this value for project_default - [organization-id] Security group Organization ID - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | all) + [page-token] Token for pagination + [page-size] Number of items to return per page + [order-by] Field and direction to sort by (created_at_desc | created_at_asc | updated_at_desc | updated_at_asc) + [project-id] Project ID to use. If none is passed the default project ID will be used + [name] Filter by name + [tags.{index}] Filter by tags + [security-group-ids.{index}] Filter by specific security group IDs + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for list diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-set-rules-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-set-rules-usage.golden index e8aa67bf4c..0a04b3a3b5 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-set-rules-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-set-rules-usage.golden @@ -1,23 +1,23 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ -Replaces the existing rules of the security group with the rules provided. This endpoint supports the update of existing rules, creation of new rules and deletion of existing rules when they are not passed in the request. +Replace all rules of a specified security group with the provided rules. USAGE: - scw instance security-group set-rules [arg=value ...] + scw instance security-group set-rules [arg=value ...] ARGS: - security-group-id UUID of the security group to update the rules on - [rules.{index}.id] UUID of the security rule to update. If no value is provided, a new rule will be created - [rules.{index}.action] Action to apply when the rule matches a packet (unknown_action | accept | drop) - [rules.{index}.protocol] Protocol family this rule applies to (unknown_protocol | TCP | UDP | ICMP | ANY) - [rules.{index}.direction] Direction the rule applies to (unknown_direction | inbound | outbound) - [rules.{index}.ip-range] Range of IP addresses these rules apply to - [rules.{index}.dest-port-from] Beginning of the range of ports this rule applies to (inclusive). This value will be set to null if protocol is ICMP or ANY - [rules.{index}.dest-port-to] End of the range of ports this rule applies to (inclusive). This value will be set to null if protocol is ICMP or ANY, or if it is equal to dest_port_from - [rules.{index}.position] Position of this rule in the security group rules list. If several rules are passed with the same position, the resulting order is undefined - [rules.{index}.editable] Indicates if this rule is editable. Rules with the value false will be ignored - [rules.{index}.zone] Zone of the rule. This field is ignored - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1) + security-group-id ID of the security group to set rules for + [rules.{index}.protocol] Protocol for the rule (unknown_protocol | tcp | udp | icmp | any) + [rules.{index}.direction] Direction of traffic for the rule (unknown_direction | inbound | outbound | both) + [rules.{index}.action] Action to take when the rule matches (unknown_action | accept | drop) + [rules.{index}.source-ip-range] Source IP range for the rule + [rules.{index}.destination-ip-range] Destination IP range for the rule + [rules.{index}.source-ports.start] Start of the port range + [rules.{index}.source-ports.end] End of the port range + [rules.{index}.destination-ports.start] Start of the port range + [rules.{index}.destination-ports.end] End of the port range + [rules.{index}.position] Position of this rule in the rule list, starting at 1 + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for set-rules diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-update-rule-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-update-rule-usage.golden index ea227436a6..5207de7a90 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-update-rule-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-update-rule-usage.golden @@ -6,16 +6,18 @@ USAGE: scw instance security-group update-rule [arg=value ...] ARGS: - security-group-id UUID of the security group - security-group-rule-id UUID of the rule - [protocol] Protocol family this rule applies to (unknown_protocol | TCP | UDP | ICMP | ANY) - [direction] Direction the rule applies to (unknown_direction | inbound | outbound) - [action] Action to apply when the rule matches a packet (unknown_action | accept | drop) - [ip-range] Range of IP addresses these rules apply to - [dest-port-from] Beginning of the range of ports this rule applies to (inclusive). If 0 is provided, unset the parameter. - [dest-port-to] End of the range of ports this rule applies to (inclusive). If 0 is provided, unset the parameter. - [position] Position of this rule in the security group rules list - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1) + security-group-rule-id ID of the rule to update + [protocol] New protocol for the rule (unknown_protocol | tcp | udp | icmp | any) + [direction] New direction for the rule (unknown_direction | inbound | outbound | both) + [action] New action for the rule (unknown_action | accept | drop) + [source-ip-range] New source IP range for the rule + [destination-ip-range] New destination IP range for the rule + [source-ports.start] Start of the port range + [source-ports.end] End of the port range + [destination-ports.start] Start of the port range + [destination-ports.end] End of the port range + [position] New position for the rule + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for update-rule diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-update-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-update-usage.golden index a706f2bcc6..a6720053b8 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-update-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-update-usage.golden @@ -1,24 +1,21 @@ 🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 🟩🟩🟩 STDOUT️ 🟩🟩🟩️ -Update the properties of security group. +Update the properties of a security group. USAGE: scw instance security-group update [arg=value ...] ARGS: - security-group-id UUID of the security group - [name] Name of the security group - [description] Description of the security group - [enable-default-security] True to block SMTP on IPv4 and IPv6. This feature is read only, please open a support ticket if you need to make it configurable - [inbound-default-policy] Default inbound policy (unknown_policy | accept | drop) - [tags.{index}] Tags of the security group - [project-default] True use this security group for future Instances created in this project - [outbound-default-policy] Default outbound policy (unknown_policy | accept | drop) - [stateful] True to set the security group as stateful - [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1) - -DEPRECATED ARGS: - [organization-default] Please use project_default instead + security-group-id ID of the security group to update + [name] New name for the security group + [description] New description for the security group + [disable-default-rules] Whether to disable default rules + [tags.{index}] New tags for the security group + [project-default] Whether this should be the default security group for the project + [inbound-default-action] New default action for inbound rules (unknown_action | accept | drop) + [outbound-default-action] New default action for outbound rules (unknown_action | accept | drop) + [stateless] Whether the security group should be stateless + [zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | fr-par-3 | nl-ams-1 | nl-ams-2 | nl-ams-3 | pl-waw-1 | pl-waw-2 | pl-waw-3 | it-mil-1 | it-mil-2 | it-mil-3) FLAGS: -h, --help help for update diff --git a/cmd/scw/testdata/test-all-usage-instance-security-group-usage.golden b/cmd/scw/testdata/test-all-usage-instance-security-group-usage.golden index c751faa9e8..4c89df6be3 100644 --- a/cmd/scw/testdata/test-all-usage-instance-security-group-usage.golden +++ b/cmd/scw/testdata/test-all-usage-instance-security-group-usage.golden @@ -3,27 +3,29 @@ A security group is a set of firewall rules on a set of Instances. Security groups enable you to create rules that either drop or allow incoming traffic from certain ports of your Instances. -Security groups are stateful by default which means return traffic is automatically allowed, regardless of any rules. -As a contrary, you have to switch in a stateless mode to define explicitly allowed. +Security groups are stateful by default, which means that return traffic is automatically allowed, regardless of any rules. +You can switch to a stateless mode if you want to only allow explicitly defined traffic. That mode may be difficult to use when filtering outgoing flows. USAGE: scw instance security-group AVAILABLE COMMANDS: + add-rules Add rules to a security group clear Remove all rules of a security group create Create a security group - create-rule Create rule delete Delete a security group - delete-rule Delete rule + delete-rules Delete rules from a security group edit Edit all rules of a security group get Get a security group - get-rule Get rule list List security groups - list-default-rules Get default rules - list-rules List rules - set-rules Update all the rules of a security group + set-rules Set all rules of a security group update Update a security group - update-rule Update security group rule + update-rule Update a security group rule + create-rule Create rule (Deprecated) + delete-rule Delete rule (Deprecated) + get-rule Get rule (Deprecated) + list-default-rules Get default rules (Deprecated) + list-rules List rules (Deprecated) FLAGS: -h, --help help for security-group diff --git a/docs/commands/instance.md b/docs/commands/instance.md index 39cf1c2c77..0421bfde1b 100644 --- a/docs/commands/instance.md +++ b/docs/commands/instance.md @@ -934,8 +934,38 @@ scw instance private-network-interface update A security group is a set of firewall rules on a set of Instances. Security groups enable you to create rules that either drop or allow incoming traffic from certain ports of your Instances. -Security groups are stateful by default which means return traffic is automatically allowed, regardless of any rules. -As a contrary, you have to switch in a stateless mode to define explicitly allowed. +Security groups are stateful by default, which means that return traffic is automatically allowed, regardless of any rules. +You can switch to a stateless mode if you want to only allow explicitly defined traffic. That mode may be difficult to use when filtering outgoing flows. + + +### Add rules to a security group + +Add one or more rules to a security group. + +**Usage:** + +```shell +scw instance security-group add-rules [arg=value ...] +``` + + +**Arguments:** + +| Name | Description | Argument Specifications | +|---------------------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| security-group-id | ID of the security group to add rules to | Required | +| rules.{index}.protocol | Protocol for the rule | One of: `unknown_protocol`, `tcp`, `udp`, `icmp`, `any` | +| rules.{index}.direction | Direction of traffic for the rule | One of: `unknown_direction`, `inbound`, `outbound`, `both` | +| rules.{index}.action | Action to take when the rule matches | One of: `unknown_action`, `accept`, `drop` | +| rules.{index}.source-ip-range | Source IP range for the rule | | +| rules.{index}.destination-ip-range | Destination IP range for the rule | | +| rules.{index}.source-ports.start | Start of the port range | | +| rules.{index}.source-ports.end | End of the port range | | +| rules.{index}.destination-ports.start | Start of the port range | | +| rules.{index}.destination-ports.end | End of the port range | | +| rules.{index}.position | Position of this rule in the rule list, starting at 1 | | +| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | + ### Remove all rules of a security group @@ -945,7 +975,7 @@ As a contrary, you have to switch in a stateless mode to define explicitly allow **Usage:** ```shell -scw instance security-group clear [arg=value ...] +scw instance security-group clear [arg=value ...] ``` @@ -962,7 +992,7 @@ scw instance security-group clear [arg=value ...] Remove all rules of the given security group ```shell -scw instance security-group clear security-group-id=11111111-1111-1111-1111-111111111111 +scw instance security-group clear 11111111-1111-1111-1111-111111111111 ``` @@ -981,50 +1011,18 @@ scw instance security-group create [arg=value ...] **Arguments:** -| Name | Description | Argument Specifications | -|--------------------------|----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| -| name | Name of the security group | Required
Default: `` | -| description | Description of the security group | | -| project-id | Project ID to use. If none is passed the default project ID will be used | | -| tags.{index} | Tags of the security group | | -| ~~organization-default~~ | Defines whether this security group becomes the default security group for new Instances | Deprecated | -| project-default | Whether this security group becomes the default security group for new Instances | | -| stateful | Whether the security group is stateful or not | Default: `true` | -| inbound-default-policy | Default policy for inbound rules | Default: `accept`
One of: `unknown_policy`, `accept`, `drop` | -| outbound-default-policy | Default policy for outbound rules | Default: `accept`
One of: `unknown_policy`, `accept`, `drop` | -| enable-default-security | True to block SMTP on IPv4 and IPv6. This feature is read only, please open a support ticket if you need to make it configurable | | -| organization-id | Organization ID to use. If none is passed the default organization ID will be used | | -| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | - - -**Examples:** - - -Create a security group with a specified name and description -```shell -scw instance security-group create name=foobar description=foobar foobar -``` - -Create a security group that will be applied as default on all Instances of this Project -```shell -scw instance security-group create project-default=true -``` - -Create a security group that will have a default drop inbound policy (traffic your Instance receives) -```shell -scw instance security-group create inbound-default-policy=drop -``` - -Create a security group that will have a default drop outbound policy (traffic your Instance transmits) -```shell -scw instance security-group create outbound-default-policy=drop -``` - -Create a stateless security group -```shell -scw instance security-group create -``` - +| Name | Description | Argument Specifications | +|-------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| name | Name of the security group | Required
Default: `` | +| description | Description of the security group | | +| disable-default-rules | Whether to disable default rules | Default: `false` | +| project-id | Project ID to use. If none is passed the default project ID will be used | | +| tags.{index} | Tags for the security group | | +| project-default | Whether this should be the default security group for the project | | +| inbound-default-action | Default action for inbound rules | Default: `accept`
One of: `unknown_action`, `accept`, `drop` | +| outbound-default-action | Default action for outbound rules | Default: `accept`
One of: `unknown_action`, `accept`, `drop` | +| stateless | Whether the security group should be stateless | Default: `false` | +| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | @@ -1088,7 +1086,7 @@ scw instance security-group create-rule security-group-id=9c46df03-83c2-46fb-936 ### Delete a security group -Delete a security group with the specified ID. +Delete a specified security group. **Usage:** @@ -1101,20 +1099,10 @@ scw instance security-group delete [arg=value ...] | Name | Description | Argument Specifications | |-------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| -| security-group-id | UUID of the security group you want to delete | Required | +| security-group-id | ID of the security group to delete | Required | | zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | -**Examples:** - - -Delete the security group with the specified ID -```shell -scw instance security-group delete 69e17c83-9945-47ac-8b29-8c1ad050ee83 -``` - - - ### Delete rule @@ -1147,6 +1135,26 @@ scw instance security-group delete-rule security-group-id=a01a36e5-5c0c-42c1-ae0 +### Delete rules from a security group + +Delete specified security groups. + +**Usage:** + +```shell +scw instance security-group delete-rules [arg=value ...] +``` + + +**Arguments:** + +| Name | Description | Argument Specifications | +|---------------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| security-group-rule-ids.{index} | List of rule IDs to delete | | +| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | + + + ### Edit all rules of a security group This command starts your default editor to edit a marshaled version of your resource @@ -1171,7 +1179,7 @@ scw instance security-group edit [arg=value ...] ### Get a security group -Get the details of a security group with the specified ID. +Get the details of a specified security group. **Usage:** @@ -1184,20 +1192,10 @@ scw instance security-group get [arg=value ...] | Name | Description | Argument Specifications | |-------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| -| security-group-id | UUID of the security group you want to get | Required | +| security-group-id | ID of the security group to retrieve | Required | | zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | -**Examples:** - - -Get a security group with the specified ID -```shell -scw instance security-group get a3244331-5d32-4e36-9bf9-b60233e201c7 -``` - - - ### Get rule @@ -1232,7 +1230,7 @@ scw instance security-group get-rule security-group-id=d900fa38-2f0d-4b09-b6d7-f ### List security groups -List all existing security groups. +List all security groups. **Usage:** @@ -1243,24 +1241,16 @@ scw instance security-group list [arg=value ...] **Arguments:** -| Name | Description | Argument Specifications | -|-----------------|-------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| name | Name of the security group | | -| project-id | Security group Project ID | | -| tags | List security groups with these exact tags (to filter with several tags, use commas to separate them) | | -| project-default | Filter security groups with this value for project_default | | -| organization-id | Security group Organization ID | | -| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1`, `all` | - - -**Examples:** - - -List all security groups that match the specified name -```shell -scw instance security-group list name=foobar -``` - +| Name | Description | Argument Specifications | +|----------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| page-token | Token for pagination | | +| page-size | Number of items to return per page | | +| order-by | Field and direction to sort by | One of: `created_at_desc`, `created_at_asc`, `updated_at_desc`, `updated_at_asc` | +| project-id | Project ID to use. If none is passed the default project ID will be used | | +| name | Filter by name | | +| tags.{index} | Filter by tags | | +| security-group-ids.{index} | Filter by specific security group IDs | | +| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | @@ -1303,39 +1293,39 @@ scw instance security-group list-rules [arg=value ...] -### Update all the rules of a security group +### Set all rules of a security group -Replaces the existing rules of the security group with the rules provided. This endpoint supports the update of existing rules, creation of new rules and deletion of existing rules when they are not passed in the request. +Replace all rules of a specified security group with the provided rules. **Usage:** ```shell -scw instance security-group set-rules [arg=value ...] +scw instance security-group set-rules [arg=value ...] ``` **Arguments:** -| Name | Description | Argument Specifications | -|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| -| security-group-id | UUID of the security group to update the rules on | Required | -| rules.{index}.id | UUID of the security rule to update. If no value is provided, a new rule will be created | | -| rules.{index}.action | Action to apply when the rule matches a packet | One of: `unknown_action`, `accept`, `drop` | -| rules.{index}.protocol | Protocol family this rule applies to | One of: `unknown_protocol`, `TCP`, `UDP`, `ICMP`, `ANY` | -| rules.{index}.direction | Direction the rule applies to | One of: `unknown_direction`, `inbound`, `outbound` | -| rules.{index}.ip-range | Range of IP addresses these rules apply to | | -| rules.{index}.dest-port-from | Beginning of the range of ports this rule applies to (inclusive). This value will be set to null if protocol is ICMP or ANY | | -| rules.{index}.dest-port-to | End of the range of ports this rule applies to (inclusive). This value will be set to null if protocol is ICMP or ANY, or if it is equal to dest_port_from | | -| rules.{index}.position | Position of this rule in the security group rules list. If several rules are passed with the same position, the resulting order is undefined | | -| rules.{index}.editable | Indicates if this rule is editable. Rules with the value false will be ignored | | -| rules.{index}.zone | Zone of the rule. This field is ignored | | -| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | +| Name | Description | Argument Specifications | +|---------------------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| security-group-id | ID of the security group to set rules for | Required | +| rules.{index}.protocol | Protocol for the rule | One of: `unknown_protocol`, `tcp`, `udp`, `icmp`, `any` | +| rules.{index}.direction | Direction of traffic for the rule | One of: `unknown_direction`, `inbound`, `outbound`, `both` | +| rules.{index}.action | Action to take when the rule matches | One of: `unknown_action`, `accept`, `drop` | +| rules.{index}.source-ip-range | Source IP range for the rule | | +| rules.{index}.destination-ip-range | Destination IP range for the rule | | +| rules.{index}.source-ports.start | Start of the port range | | +| rules.{index}.source-ports.end | End of the port range | | +| rules.{index}.destination-ports.start | Start of the port range | | +| rules.{index}.destination-ports.end | End of the port range | | +| rules.{index}.position | Position of this rule in the rule list, starting at 1 | | +| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | ### Update a security group -Update the properties of security group. +Update the properties of a security group. **Usage:** @@ -1346,23 +1336,22 @@ scw instance security-group update [arg=value ...] **Arguments:** -| Name | Description | Argument Specifications | -|--------------------------|----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| -| security-group-id | UUID of the security group | Required | -| name | Name of the security group | | -| description | Description of the security group | | -| enable-default-security | True to block SMTP on IPv4 and IPv6. This feature is read only, please open a support ticket if you need to make it configurable | | -| inbound-default-policy | Default inbound policy | One of: `unknown_policy`, `accept`, `drop` | -| tags.{index} | Tags of the security group | | -| ~~organization-default~~ | Please use project_default instead | Deprecated | -| project-default | True use this security group for future Instances created in this project | | -| outbound-default-policy | Default outbound policy | One of: `unknown_policy`, `accept`, `drop` | -| stateful | True to set the security group as stateful | | -| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | +| Name | Description | Argument Specifications | +|-------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| security-group-id | ID of the security group to update | Required | +| name | New name for the security group | | +| description | New description for the security group | | +| disable-default-rules | Whether to disable default rules | | +| tags.{index} | New tags for the security group | | +| project-default | Whether this should be the default security group for the project | | +| inbound-default-action | New default action for inbound rules | One of: `unknown_action`, `accept`, `drop` | +| outbound-default-action | New default action for outbound rules | One of: `unknown_action`, `accept`, `drop` | +| stateless | Whether the security group should be stateless | | +| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | -### Update security group rule +### Update a security group rule Update the properties of a rule from a specified security group. @@ -1375,18 +1364,20 @@ scw instance security-group update-rule [arg=value ...] **Arguments:** -| Name | Description | Argument Specifications | -|------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| -| security-group-id | UUID of the security group | Required | -| security-group-rule-id | UUID of the rule | Required | -| protocol | Protocol family this rule applies to | One of: `unknown_protocol`, `TCP`, `UDP`, `ICMP`, `ANY` | -| direction | Direction the rule applies to | One of: `unknown_direction`, `inbound`, `outbound` | -| action | Action to apply when the rule matches a packet | One of: `unknown_action`, `accept`, `drop` | -| ip-range | Range of IP addresses these rules apply to | | -| dest-port-from | Beginning of the range of ports this rule applies to (inclusive). If 0 is provided, unset the parameter. | | -| dest-port-to | End of the range of ports this rule applies to (inclusive). If 0 is provided, unset the parameter. | | -| position | Position of this rule in the security group rules list | | -| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | +| Name | Description | Argument Specifications | +|-------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| security-group-rule-id | ID of the rule to update | Required | +| protocol | New protocol for the rule | One of: `unknown_protocol`, `tcp`, `udp`, `icmp`, `any` | +| direction | New direction for the rule | One of: `unknown_direction`, `inbound`, `outbound`, `both` | +| action | New action for the rule | One of: `unknown_action`, `accept`, `drop` | +| source-ip-range | New source IP range for the rule | | +| destination-ip-range | New destination IP range for the rule | | +| source-ports.start | Start of the port range | | +| source-ports.end | End of the port range | | +| destination-ports.start | Start of the port range | | +| destination-ports.end | End of the port range | | +| position | New position for the rule | | +| zone | Zone to target. If none is passed will use default zone from the config | Default: `fr-par-1`
One of: `fr-par-1`, `fr-par-2`, `fr-par-3`, `nl-ams-1`, `nl-ams-2`, `nl-ams-3`, `pl-waw-1`, `pl-waw-2`, `pl-waw-3`, `it-mil-1` | diff --git a/internal/namespaces/instance/v1/custom.go b/internal/namespaces/instance/v1/custom.go index 349f07ec68..dce8508cd8 100644 --- a/internal/namespaces/instance/v1/custom.go +++ b/internal/namespaces/instance/v1/custom.go @@ -37,7 +37,6 @@ func GetCommands() *core.Commands { instanceRoot(), instanceImage(), instanceIP(), - instanceSecurityGroup(), instanceServer(), instanceVolumeType(), instanceSnapshot(), @@ -74,18 +73,6 @@ func GetCommands() *core.Commands { instanceVolumeDelete(), instanceVolumePlanMigration(), instanceVolumeApplyMigration(), - instanceSecurityGroupList(), - instanceSecurityGroupCreate(), - instanceSecurityGroupGet(), - instanceSecurityGroupDelete(), - instanceSecurityGroupUpdate(), - instanceSecurityGroupListDefaultRules(), - instanceSecurityGroupListRules(), - instanceSecurityGroupCreateRule(), - instanceSecurityGroupSetRules(), - instanceSecurityGroupDeleteRule(), - instanceSecurityGroupGetRule(), - instanceSecurityGroupUpdateRule(), instanceIPList(), instanceIPCreate(), instanceIPGet(), @@ -103,6 +90,12 @@ func GetCommands() *core.Commands { instancePrivateNicGet(), instancePrivateNicUpdate(), instancePrivateNicDelete(), + // SecurityGroup commands exclusive to v1 + instanceSecurityGroupListDefaultRules(), + instanceSecurityGroupListRules(), + instanceSecurityGroupCreateRule(), + instanceSecurityGroupDeleteRule(), + instanceSecurityGroupGetRule(), // ServerType commands exclusive to v1 instanceServerTypeGet(), ) @@ -218,32 +211,6 @@ func GetCommands() *core.Commands { // cmds.MustFind("instance", "volume-type", "list").Override(volumeTypeListBuilder) - // - // Security Group - // - human.RegisterMarshalerFunc( - instance.CreateSecurityGroupResponse{}, - marshallNestedField("SecurityGroup"), - ) - human.RegisterMarshalerFunc( - instance.SecurityGroupPolicy(""), - human.EnumMarshalFunc(securityGroupPolicyMarshalSpecs), - ) - human.RegisterMarshalerFunc( - instance.SecurityGroupState(""), - human.EnumMarshalFunc(securityGroupStateMarshalSpecs), - ) - - cmds.MustFind("instance", "security-group", "create").Override(securityGroupCreateBuilder) - cmds.MustFind("instance", "security-group", "get").Override(securityGroupGetBuilder) - cmds.MustFind("instance", "security-group", "list").Override(securityGroupListBuilder) - cmds.MustFind("instance", "security-group", "delete").Override(securityGroupDeleteBuilder) - - cmds.Merge(core.NewCommands( - securityGroupClearCommand(), - securityGroupEditCommand(), - )) - // // Security Group Rule // @@ -257,6 +224,17 @@ func GetCommands() *core.Commands { ) human.RegisterMarshalerFunc([]*instance.SecurityGroupRule{}, marshalSecurityGroupRules) + cmds.MustFind("instance", "security-group", "list-default-rules"). + Override(securityGroupListDefaultRulesBuilder) + cmds.MustFind("instance", "security-group", "list-rules"). + Override(securityGroupListRulesBuilder) + cmds.MustFind("instance", "security-group", "create-rule"). + Override(securityGroupCreateRuleBuilder) + cmds.MustFind("instance", "security-group", "delete-rule"). + Override(securityGroupDeleteRuleBuilder) + cmds.MustFind("instance", "security-group", "get-rule"). + Override(securityGroupGetRuleBuilder) + // // Placement Group // diff --git a/internal/namespaces/instance/v1/custom_security_group.go b/internal/namespaces/instance/v1/custom_security_group.go index efb27ee0b3..69ec5202b9 100644 --- a/internal/namespaces/instance/v1/custom_security_group.go +++ b/internal/namespaces/instance/v1/custom_security_group.go @@ -1,45 +1,22 @@ package instance import ( - "context" - "errors" - "fmt" - "reflect" "strconv" - "strings" - "time" "github.com/fatih/color" "github.com/scaleway/scaleway-cli/v2/core" "github.com/scaleway/scaleway-cli/v2/core/human" - "github.com/scaleway/scaleway-cli/v2/internal/editor" - "github.com/scaleway/scaleway-cli/v2/internal/terminal" "github.com/scaleway/scaleway-sdk-go/api/instance/v1" - "github.com/scaleway/scaleway-sdk-go/logger" - "github.com/scaleway/scaleway-sdk-go/scw" ) // // Marshalers // -var ( - securityGroupPolicyMarshalSpecs = human.EnumMarshalSpecs{ - instance.SecurityGroupPolicyDrop: &human.EnumMarshalSpec{Attribute: color.FgRed}, - instance.SecurityGroupPolicyAccept: &human.EnumMarshalSpec{Attribute: color.FgGreen}, - } - - securityGroupRuleActionMarshalSpecs = human.EnumMarshalSpecs{ - instance.SecurityGroupRuleActionDrop: &human.EnumMarshalSpec{Attribute: color.FgRed}, - instance.SecurityGroupRuleActionAccept: &human.EnumMarshalSpec{Attribute: color.FgGreen}, - } - - securityGroupStateMarshalSpecs = human.EnumMarshalSpecs{ - instance.SecurityGroupStateAvailable: &human.EnumMarshalSpec{Attribute: color.FgGreen}, - instance.SecurityGroupStateSyncing: &human.EnumMarshalSpec{Attribute: color.FgBlue}, - instance.SecurityGroupStateSyncingError: &human.EnumMarshalSpec{Attribute: color.FgRed}, - } -) +var securityGroupRuleActionMarshalSpecs = human.EnumMarshalSpecs{ + instance.SecurityGroupRuleActionDrop: &human.EnumMarshalSpec{Attribute: color.FgRed}, + instance.SecurityGroupRuleActionAccept: &human.EnumMarshalSpec{Attribute: color.FgGreen}, +} func marshalSecurityGroupRules(i any, _ *human.MarshalOpt) (out string, err error) { rules := i.([]*instance.SecurityGroupRule) @@ -80,415 +57,41 @@ func marshalSecurityGroupRules(i any, _ *human.MarshalOpt) (out string, err erro return human.Marshal(humanRules, nil) } -// MarshalHuman marshals a customSecurityGroupResponse. -func (sg *customSecurityGroupResponse) MarshalHuman() (out string, err error) { - humanSecurityGroup := struct { - ID string - Name string - State instance.SecurityGroupState - Description string - EnableDefaultSecurity bool - OrganizationID string - ProjectID string - OrganizationDefault *bool - ProjectDefault bool - CreationDate *time.Time - ModificationDate *time.Time - Stateful bool - }{ - ID: sg.ID, - Name: sg.Name, - State: sg.State, - Description: sg.Description, - EnableDefaultSecurity: sg.EnableDefaultSecurity, - OrganizationID: sg.Organization, - ProjectID: sg.Project, - OrganizationDefault: sg.OrganizationDefault, - ProjectDefault: sg.ProjectDefault, - CreationDate: sg.CreationDate, - ModificationDate: sg.ModificationDate, - Stateful: sg.Stateful, - } - - securityGroupView, err := human.Marshal(humanSecurityGroup, nil) - if err != nil { - return "", err - } - securityGroupView = terminal.Style("Security Group:\n", color.Bold) + securityGroupView - - inboundRules := []*instance.SecurityGroupRule(nil) - outboundRules := []*instance.SecurityGroupRule(nil) - for _, rule := range sg.Rules { - switch rule.Direction { - case instance.SecurityGroupRuleDirectionInbound: - inboundRules = append(inboundRules, rule) - case instance.SecurityGroupRuleDirectionOutbound: - outboundRules = append(outboundRules, rule) - default: - logger.Warningf("invalid security group rule direction: %v", rule.Direction) - } - } - - // defaultInboundPolicy will already be colored in green or red by the marshaler. - defaultInboundPolicy, err := human.Marshal(sg.InboundDefaultPolicy, nil) - if err != nil { - return "", err - } - - // defaultOutboundPolicy will already be colored in green or red by the marshaler. - defaultOutboundPolicy, err := human.Marshal(sg.OutboundDefaultPolicy, nil) - if err != nil { - return "", err - } - - // b returns the given string in bold. - // For inboundRulesView and outboundRulesView, this function must be called for every - // concatenated part of the string because of the color package escaping at the end of - // a color resulting in a non-bold format after the default{In|Out}boundPolicy. - b := color.New(color.Bold).SprintFunc() - - inboundRulesContent, err := human.Marshal(inboundRules, nil) - if err != nil { - return "", err - } - inboundRulesView := b( - "Inbound Rules (default policy ", - ) + b( - defaultInboundPolicy, - ) + b( - "):\n", - ) + inboundRulesContent - - outboundRulesContent, err := human.Marshal(outboundRules, nil) - if err != nil { - return "", err - } - outboundRulesView := b( - "Outbound Rules (default policy ", - ) + b( - defaultOutboundPolicy, - ) + b( - "):\n", - ) + outboundRulesContent - - serversContent, err := human.Marshal(sg.Servers, nil) - if err != nil { - return "", err - } - serversView := terminal.Style("Servers:\n", color.Bold) + serversContent - - return strings.Join([]string{ - securityGroupView, - inboundRulesView, - outboundRulesView, - serversView, - }, "\n\n"), nil -} - // // Builders // -type customSecurityGroupResponse struct { - instance.SecurityGroup - - Rules []*instance.SecurityGroupRule -} - -func securityGroupCreateBuilder(c *core.Command) *core.Command { - type customCreateSecurityGroupRequest struct { - *instance.CreateSecurityGroupRequest - OrganizationID *string - ProjectID *string - } - - renameOrganizationIDArgSpec(c.ArgSpecs) - renameProjectIDArgSpec(c.ArgSpecs) - - c.ArgsType = reflect.TypeFor[customCreateSecurityGroupRequest]() - - c.AddInterceptors( - func(ctx context.Context, argsI any, runner core.CommandRunner) (i any, err error) { - args := argsI.(*customCreateSecurityGroupRequest) - - if args.CreateSecurityGroupRequest == nil { - args.CreateSecurityGroupRequest = &instance.CreateSecurityGroupRequest{} - } - - request := args.CreateSecurityGroupRequest - request.Organization = args.OrganizationID - request.Project = args.ProjectID - - return runner(ctx, request) - }, - ) +func securityGroupListDefaultRulesBuilder(c *core.Command) *core.Command { + deprecateV1OnlyCommand(c) + c.DeprecationMessage += " Default rules can be listed using \"scw instance security-group get \"." return c } -func securityGroupGetBuilder(c *core.Command) *core.Command { - c.Run = func(ctx context.Context, argsI any) (any, error) { - req := argsI.(*instance.GetSecurityGroupRequest) - - client := core.ExtractClient(ctx) - api := instance.NewAPI(client) - securityGroup, err := api.GetSecurityGroup(req) - if err != nil { - return nil, err - } - - securityGroupRules, err := api.ListSecurityGroupRules( - &instance.ListSecurityGroupRulesRequest{ - Zone: req.Zone, - SecurityGroupID: securityGroup.SecurityGroup.ID, - }, - scw.WithAllPages(), - ) - if err != nil { - return nil, err - } - - return &customSecurityGroupResponse{ - SecurityGroup: *securityGroup.SecurityGroup, - Rules: securityGroupRules.Rules, - }, nil - } +func securityGroupListRulesBuilder(c *core.Command) *core.Command { + deprecateV1OnlyCommand(c) + c.DeprecationMessage += " Rules can be listed using \"scw instance security-group get \"." return c } -func securityGroupListBuilder(c *core.Command) *core.Command { - type customListSecurityGroupsRequest struct { - *instance.ListSecurityGroupsRequest - OrganizationID *string - ProjectID *string - } - - renameOrganizationIDArgSpec(c.ArgSpecs) - renameProjectIDArgSpec(c.ArgSpecs) - - c.ArgsType = reflect.TypeFor[customListSecurityGroupsRequest]() - - c.AddInterceptors( - func(ctx context.Context, argsI any, runner core.CommandRunner) (i any, err error) { - args := argsI.(*customListSecurityGroupsRequest) - - if args.ListSecurityGroupsRequest == nil { - args.ListSecurityGroupsRequest = &instance.ListSecurityGroupsRequest{} - } - - request := args.ListSecurityGroupsRequest - request.Organization = args.OrganizationID - request.Project = args.ProjectID - - return runner(ctx, request) - }, - ) +func securityGroupCreateRuleBuilder(c *core.Command) *core.Command { + deprecateV1OnlyCommand(c) + c.DeprecationMessage += " Rules can be created using \"scw instance security-group add-rules [arg=value ...]\"." // check usage return c } -func securityGroupDeleteBuilder(c *core.Command) *core.Command { - c.AddInterceptors( - func(ctx context.Context, argsI any, runner core.CommandRunner) (any, error) { - res, originalErr := runner(ctx, argsI) - if originalErr == nil { - return res, nil - } - - if strings.HasSuffix(originalErr.Error(), "group is in use. you cannot delete it.") { - req := argsI.(*instance.DeleteSecurityGroupRequest) - api := instance.NewAPI(core.ExtractClient(ctx)) - - newError := &core.CliError{ - Err: errors.New("cannot delete security-group currently in use"), - } - - // Get security-group. - sg, err := api.GetSecurityGroup(&instance.GetSecurityGroupRequest{ - SecurityGroupID: req.SecurityGroupID, - }) - if err != nil { - // Ignore API error and return a minimal error. - return nil, newError - } - - // Create detail message. - var hintBuilder strings.Builder - hintBuilder.WriteString( - "Attach all these instances to another security-group before deleting this one:", - ) - for _, s := range sg.SecurityGroup.Servers { - fmt.Fprintf( - &hintBuilder, - "\nscw instance server update %s security-group.id=$NEW_SECURITY_GROUP_ID", - s.ID, - ) - } - - newError.Hint = hintBuilder.String() - - return nil, newError - } - - return nil, originalErr - }, - ) +func securityGroupDeleteRuleBuilder(c *core.Command) *core.Command { + deprecateV1OnlyCommand(c) + c.DeprecationMessage += " Rules can be deleted using \"scw instance security-group delete-rules security-group-rule-ids.0=\"." // check usage return c } -// -// Commands -// - -type instanceResetSecurityGroupArgs struct { - Zone scw.Zone - SecurityGroupID string -} - -func securityGroupClearCommand() *core.Command { - return &core.Command{ - Short: `Remove all rules of a security group`, - Namespace: "instance", - Resource: "security-group", - Verb: "clear", - ArgsType: reflect.TypeFor[instanceResetSecurityGroupArgs](), - Examples: []*core.Example{ - { - Short: "Remove all rules of the given security group", - ArgsJSON: `{"security_group_id": "11111111-1111-1111-1111-111111111111"}`, - }, - }, - Run: func(ctx context.Context, argsI any) (i any, e error) { - args := argsI.(*instanceResetSecurityGroupArgs) - - client := core.ExtractClient(ctx) - api := instance.NewAPI(client) - - rules, err := api.ListSecurityGroupRules(&instance.ListSecurityGroupRulesRequest{ - Zone: args.Zone, - SecurityGroupID: args.SecurityGroupID, - }, scw.WithAllPages()) - if err != nil { - return nil, err - } - - for _, rule := range rules.Rules { - if !rule.Editable { - continue - } - err = api.DeleteSecurityGroupRule(&instance.DeleteSecurityGroupRuleRequest{ - Zone: args.Zone, - SecurityGroupID: args.SecurityGroupID, - SecurityGroupRuleID: rule.ID, - }) - if err != nil { - return nil, err - } - } - - return &core.SuccessResult{Message: "Successful reset of the security group rules"}, err - }, - ArgSpecs: core.ArgSpecs{ - { - Name: "security-group-id", - Short: `ID of the security group to reset.`, - Required: true, - }, - core.ZoneArgSpec((*instance.API)(nil).Zones()...), - }, - } -} - -var instanceSecurityGroupEditYamlExample = `rules: -- action: drop - dest_port_from: 1200 - dest_port_to: 1300 - direction: inbound - ip_range: 192.168.0.0/24 - protocol: TCP -- action: drop - direction: inbound - protocol: ICMP - ip_range: 0.0.0.0/0 -- action: accept - dest_port_from: 25565 - direction: outbound - ip_range: 0.0.0.0/0 - protocol: UDP -` - -type instanceSecurityGroupEditArgs struct { - Zone scw.Zone - SecurityGroupID string - Mode editor.MarshalMode -} - -func securityGroupEditCommand() *core.Command { - return &core.Command{ - Short: `Edit all rules of a security group`, - Long: editor.LongDescription, - Namespace: "instance", - Resource: "security-group", - Verb: "edit", - ArgsType: reflect.TypeFor[instanceSecurityGroupEditArgs](), - ArgSpecs: core.ArgSpecs{ - { - Name: "security-group-id", - Short: `ID of the security group to reset.`, - Required: true, - Positional: true, - }, - editor.MarshalModeArgSpec(), - core.ZoneArgSpec((*instance.API)(nil).Zones()...), - }, - Run: func(ctx context.Context, argsI any) (i any, e error) { - args := argsI.(*instanceSecurityGroupEditArgs) - - client := core.ExtractClient(ctx) - api := instance.NewAPI(client) - - rules, err := api.ListSecurityGroupRules(&instance.ListSecurityGroupRulesRequest{ - Zone: args.Zone, - SecurityGroupID: args.SecurityGroupID, - }, scw.WithAllPages(), scw.WithContext(ctx)) - if err != nil { - return nil, fmt.Errorf("failed to list security-group rules: %w", err) - } - - // Get only rules that can be edited - editableRules := []*instance.SecurityGroupRule(nil) - for _, rule := range rules.Rules { - if rule.Editable { - editableRules = append(editableRules, rule) - } - } - rules.Rules = editableRules - - setRequest := &instance.SetSecurityGroupRulesRequest{ - Zone: args.Zone, - SecurityGroupID: args.SecurityGroupID, - } +func securityGroupGetRuleBuilder(c *core.Command) *core.Command { + deprecateV1OnlyCommand(c) + c.DeprecationMessage += " Rules can be listed using \"scw instance security-group get \"." - editedSetRequest, err := editor.UpdateResourceEditor(rules, setRequest, &editor.Config{ - PutRequest: true, - MarshalMode: args.Mode, - Template: instanceSecurityGroupEditYamlExample, - IgnoreFields: []string{"editable"}, - }) - if err != nil { - return nil, err - } - - setRequest = editedSetRequest.(*instance.SetSecurityGroupRulesRequest) - - resp, err := api.SetSecurityGroupRules(setRequest, scw.WithContext(ctx)) - if err != nil { - return nil, err - } - - return resp.Rules, nil - }, - } + return c } diff --git a/internal/namespaces/instance/v1/custom_security_group_test.go b/internal/namespaces/instance/v1/custom_security_group_test.go deleted file mode 100644 index ec90e8d075..0000000000 --- a/internal/namespaces/instance/v1/custom_security_group_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package instance_test - -import ( - "testing" - - "github.com/scaleway/scaleway-cli/v2/core" - "github.com/scaleway/scaleway-cli/v2/internal/namespaces/instance/v1" -) - -const securityGroupCreateCommand = "scw instance security-group create name=cli-sg-charming-rubin -o json" - -func Test_SecurityGroupCreate(t *testing.T) { - // Keep the existing JSON response shape covered as an output contract. - t.Run("Create", core.Test(&core.TestConfig{ - Commands: instance.GetCommands(), - Cmd: securityGroupCreateCommand, - Check: core.TestCheckCombine( - core.TestCheckGolden(), - core.TestCheckExitCode(0), - ), - AfterFunc: core.ExecAfterCmd( - "scw instance security-group delete {{ .CmdResult.SecurityGroup.ID }}", - ), - })) - - // The API error must be surfaced when the create call fails. - t.Run("Error", core.Test(&core.TestConfig{ - Commands: instance.GetCommands(), - Cmd: securityGroupCreateCommand, - Check: core.TestCheckCombine( - core.TestCheckGolden(), - core.TestCheckExitCode(1), - ), - })) -} - -func Test_SecurityGroupGet(t *testing.T) { - t.Run("Get", core.Test(&core.TestConfig{ - Commands: instance.GetCommands(), - BeforeFunc: core.BeforeFuncCombine( - createSecurityGroup("SecurityGroup"), - ), - Cmd: "scw instance security-group get {{ .SecurityGroup.ID }}", - Check: core.TestCheckCombine( - core.TestCheckGolden(), - core.TestCheckExitCode(0), - ), - AfterFunc: deleteSecurityGroup("SecurityGroup"), - })) -} diff --git a/internal/namespaces/instance/v1/custom_server_test.go b/internal/namespaces/instance/v1/custom_server_test.go index 8b8cff3497..56de9605ed 100644 --- a/internal/namespaces/instance/v1/custom_server_test.go +++ b/internal/namespaces/instance/v1/custom_server_test.go @@ -250,10 +250,10 @@ func Test_ServerUpdateCustom(t *testing.T) { t.Run( "Update server security-group-id from server with security-group-id", core.Test(&core.TestConfig{ - Commands: instance.GetCommands(), + Commands: cmds, BeforeFunc: core.BeforeFuncCombine( - createSecurityGroup("SecurityGroup1"), - createSecurityGroup("SecurityGroup2"), + instanceV2.CreateSecurityGroup("SecurityGroup1"), + instanceV2.CreateSecurityGroup("SecurityGroup2"), core.ExecStoreBeforeCmd( "Server", testServerCommand( @@ -267,14 +267,14 @@ func Test_ServerUpdateCustom(t *testing.T) { func(t *testing.T, ctx *core.CheckFuncCtx) { t.Helper() assert.Equal(t, - ctx.Meta["SecurityGroup2"].(*instanceSDK.SecurityGroup).ID, + ctx.Meta["SecurityGroup2"].(*instanceSDKV2.SecurityGroup).ID, ctx.Result.(*instance.ServerWithWarningsResponse).Server.SecurityGroup.ID) }, ), AfterFunc: core.AfterFuncCombine( deleteServer("Server"), - deleteSecurityGroup("SecurityGroup1"), - deleteSecurityGroup("SecurityGroup2"), + instanceV2.DeleteSecurityGroup("SecurityGroup1"), + instanceV2.DeleteSecurityGroup("SecurityGroup2"), ), }), ) diff --git a/internal/namespaces/instance/v1/custom_web.go b/internal/namespaces/instance/v1/custom_web.go index 68b14f1348..800d982597 100644 --- a/internal/namespaces/instance/v1/custom_web.go +++ b/internal/namespaces/instance/v1/custom_web.go @@ -17,7 +17,6 @@ func addWebUrls(cmds *core.Commands) { cmds.MustFind("instance", "private-nic", "list").WebURL = "https://console.scaleway.com/instance/servers/{{ .Zone }}/{{ .ServerID }}/private-networks" - cmds.MustFind("instance", "security-group").WebURL = "https://console.scaleway.com/instance/security-groups" cmds.MustFind("instance", "snapshot").WebURL = "https://console.scaleway.com/instance/snapshots" cmds.MustFind("instance", "volume").WebURL = "https://console.scaleway.com/instance/volumes" diff --git a/internal/namespaces/instance/v1/helpers_test.go b/internal/namespaces/instance/v1/helpers_test.go index b75315ba34..06399f727e 100644 --- a/internal/namespaces/instance/v1/helpers_test.go +++ b/internal/namespaces/instance/v1/helpers_test.go @@ -202,28 +202,6 @@ func deletePlacementGroup(metaKey string) core.AfterFunc { return core.ExecAfterCmd("scw instance placement-group delete {{ ." + metaKey + ".ID }}") } -// -// Security Group -// - -// createSecurityGroup creates a security group and -// register it in the context Meta at metaKey. -func createSecurityGroup(metaKey string) core.BeforeFunc { - return func(ctx *core.BeforeFuncCtx) error { - res := ctx.ExecuteCmd([]string{"scw", "instance", "security-group", "create"}) - createSecurityGroupResponse := res.(*instanceSDK.CreateSecurityGroupResponse) - ctx.Meta[metaKey] = createSecurityGroupResponse.SecurityGroup - - return nil - } -} - -// deleteSecurityGroup deletes a security group -// previously registered in the context Meta at metaKey. -func deleteSecurityGroup(metaKey string) core.AfterFunc { - return core.ExecAfterCmd("scw instance security-group delete {{ ." + metaKey + ".ID }}") -} - // // Snapshot // diff --git a/internal/namespaces/instance/v1/testdata/test-security-group-create-create.cassette.yaml b/internal/namespaces/instance/v1/testdata/test-security-group-create-create.cassette.yaml deleted file mode 100644 index 8b2727052f..0000000000 --- a/internal/namespaces/instance/v1/testdata/test-security-group-create-create.cassette.yaml +++ /dev/null @@ -1,70 +0,0 @@ ---- -version: 2 -interactions: -- id: 0 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 166 - host: api.scaleway.com - body: "{\"name\":\"cli-sg-charming-rubin\",\"project\":\"fa1e3217-dc80-42ac-85c3-3f034b78b552\",\"stateful\":true,\"inbound_default_policy\":\"accept\",\"outbound_default_policy\":\"accept\"}" - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups - method: POST - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 587 - body: "{\"security_group\": {\"id\": \"6bbed5ce-6b01-4841-9adb-c18fc2b80774\", \"creation_date\": \"2025-11-04T10:12:59.006303+00:00\", \"modification_date\": \"2025-11-04T10:12:59.006303+00:00\", \"name\": \"cli-sg-charming-rubin\", \"description\": null, \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"servers\": [], \"stateful\": true, \"inbound_default_policy\": \"accept\", \"outbound_default_policy\": \"accept\", \"organization_default\": false, \"project_default\": false, \"enable_default_security\": true, \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}}" - headers: - Content-Length: - - "587" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:12:59 GMT - Location: - - https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/6bbed5ce-6b01-4841-9adb-c18fc2b80774 - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - db548b67-958f-4e26-94c7-b9e6f25f3cb9 - status: 201 Created - code: 201 - duration: 174.14533ms -- id: 1 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/6bbed5ce-6b01-4841-9adb-c18fc2b80774 - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 0 - body: "" - headers: - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:12:59 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 16d5dd10-8b0b-48d5-a0a3-2e89c03d3bb0 - status: 204 No Content - code: 204 - duration: 110.833429ms diff --git a/internal/namespaces/instance/v1/testdata/test-security-group-create-create.golden b/internal/namespaces/instance/v1/testdata/test-security-group-create-create.golden deleted file mode 100644 index cfe23853c8..0000000000 --- a/internal/namespaces/instance/v1/testdata/test-security-group-create-create.golden +++ /dev/null @@ -1,25 +0,0 @@ -🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 -🟩🟩🟩 STDOUT️ 🟩🟩🟩️ -{"security_group":{"id":"6bbed5ce-6b01-4841-9adb-c18fc2b80774","name":"cli-sg-charming-rubin","description":"","enable_default_security":true,"inbound_default_policy":"accept","outbound_default_policy":"accept","organization":"fa1e3217-dc80-42ac-85c3-3f034b78b552","project":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"organization_default":false,"project_default":false,"creation_date":"1970-01-01T00:00:00.0Z","modification_date":"1970-01-01T00:00:00.0Z","servers":[],"stateful":true,"state":"available","zone":"fr-par-1"}} -🟩🟩🟩 JSON STDOUT 🟩🟩🟩 -{ - "security_group": { - "id": "6bbed5ce-6b01-4841-9adb-c18fc2b80774", - "name": "cli-sg-charming-rubin", - "description": "", - "enable_default_security": true, - "inbound_default_policy": "accept", - "outbound_default_policy": "accept", - "organization": "fa1e3217-dc80-42ac-85c3-3f034b78b552", - "project": "fa1e3217-dc80-42ac-85c3-3f034b78b552", - "tags": [], - "organization_default": false, - "project_default": false, - "creation_date": "1970-01-01T00:00:00.0Z", - "modification_date": "1970-01-01T00:00:00.0Z", - "servers": [], - "stateful": true, - "state": "available", - "zone": "fr-par-1" - } -} diff --git a/internal/namespaces/instance/v1/testdata/test-security-group-create-error.cassette.yaml b/internal/namespaces/instance/v1/testdata/test-security-group-create-error.cassette.yaml deleted file mode 100644 index 837226cf77..0000000000 --- a/internal/namespaces/instance/v1/testdata/test-security-group-create-error.cassette.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -version: 2 -interactions: -- id: 0 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 166 - host: api.scaleway.com - body: "{\"name\":\"cli-sg-charming-rubin\",\"project\":\"fa1e3217-dc80-42ac-85c3-3f034b78b552\",\"stateful\":true,\"inbound_default_policy\":\"accept\",\"outbound_default_policy\":\"accept\"}" - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups - method: POST - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 71 - body: "{\"message\": \"insufficient permissions\", \"type\": \"permissions_denied\"}" - headers: - Content-Length: - - "71" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:12:59 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - db548b67-958f-4e26-94c7-b9e6f25f3cb0 - status: 403 Forbidden - code: 403 - duration: 12.14533ms diff --git a/internal/namespaces/instance/v1/testdata/test-security-group-create-error.golden b/internal/namespaces/instance/v1/testdata/test-security-group-create-error.golden deleted file mode 100644 index 32930ee94a..0000000000 --- a/internal/namespaces/instance/v1/testdata/test-security-group-create-error.golden +++ /dev/null @@ -1,7 +0,0 @@ -🎲🎲🎲 EXIT CODE: 1 🎲🎲🎲 -πŸŸ₯πŸŸ₯πŸŸ₯ STDERR️️ πŸŸ₯πŸŸ₯πŸŸ₯️ -{"error":"scaleway-sdk-go: insufficient permissions: "} -πŸŸ₯πŸŸ₯πŸŸ₯ JSON STDERR πŸŸ₯πŸŸ₯πŸŸ₯ -{ - "error": "scaleway-sdk-go: insufficient permissions: " -} diff --git a/internal/namespaces/instance/v1/testdata/test-security-group-get-get.cassette.yaml b/internal/namespaces/instance/v1/testdata/test-security-group-get-get.cassette.yaml deleted file mode 100644 index 0b585a0ab9..0000000000 --- a/internal/namespaces/instance/v1/testdata/test-security-group-get-get.cassette.yaml +++ /dev/null @@ -1,137 +0,0 @@ ---- -version: 2 -interactions: -- id: 0 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 166 - host: api.scaleway.com - body: "{\"name\":\"cli-sg-charming-rubin\",\"project\":\"fa1e3217-dc80-42ac-85c3-3f034b78b552\",\"stateful\":true,\"inbound_default_policy\":\"accept\",\"outbound_default_policy\":\"accept\"}" - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups - method: POST - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 587 - body: "{\"security_group\": {\"id\": \"6bbed5ce-6b01-4841-9adb-c18fc2b80774\", \"creation_date\": \"2025-11-04T10:12:59.006303+00:00\", \"modification_date\": \"2025-11-04T10:12:59.006303+00:00\", \"name\": \"cli-sg-charming-rubin\", \"description\": null, \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"servers\": [], \"stateful\": true, \"inbound_default_policy\": \"accept\", \"outbound_default_policy\": \"accept\", \"organization_default\": false, \"project_default\": false, \"enable_default_security\": true, \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}}" - headers: - Content-Length: - - "587" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:12:59 GMT - Location: - - https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/6bbed5ce-6b01-4841-9adb-c18fc2b80774 - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - db548b67-958f-4e26-94c7-b9e6f25f3cb9 - status: 201 Created - code: 201 - duration: 174.14533ms -- id: 1 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/6bbed5ce-6b01-4841-9adb-c18fc2b80774 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 587 - body: "{\"security_group\": {\"id\": \"6bbed5ce-6b01-4841-9adb-c18fc2b80774\", \"creation_date\": \"2025-11-04T10:12:59.006303+00:00\", \"modification_date\": \"2025-11-04T10:12:59.006303+00:00\", \"name\": \"cli-sg-charming-rubin\", \"description\": null, \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"servers\": [], \"stateful\": true, \"inbound_default_policy\": \"accept\", \"outbound_default_policy\": \"accept\", \"organization_default\": false, \"project_default\": false, \"enable_default_security\": true, \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}}" - headers: - Content-Length: - - "587" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:12:59 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - be6ead0d-389b-4d8d-9a37-cfea9fc0b18d - status: 200 OK - code: 200 - duration: 55.698506ms -- id: 2 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - form: - page: - - "1" - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/6bbed5ce-6b01-4841-9adb-c18fc2b80774/rules?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 1536 - body: "{\"rules\": [{\"id\": \"11111111-2222-4333-8444-000000000001\", \"protocol\": \"TCP\", \"direction\": \"outbound\", \"ip_range\": \"0.0.0.0/0\", \"dest_ip_range\": null, \"dest_port_from\": 25, \"dest_port_to\": null, \"position\": 1, \"editable\": false, \"action\": \"drop\", \"zone\": \"fr-par-1\"}, {\"id\": \"11111111-2222-4333-8444-000000000002\", \"protocol\": \"TCP\", \"direction\": \"outbound\", \"ip_range\": \"0.0.0.0/0\", \"dest_ip_range\": null, \"dest_port_from\": 465, \"dest_port_to\": null, \"position\": 2, \"editable\": false, \"action\": \"drop\", \"zone\": \"fr-par-1\"}, {\"id\": \"11111111-2222-4333-8444-000000000003\", \"protocol\": \"TCP\", \"direction\": \"outbound\", \"ip_range\": \"0.0.0.0/0\", \"dest_ip_range\": null, \"dest_port_from\": 587, \"dest_port_to\": null, \"position\": 3, \"editable\": false, \"action\": \"drop\", \"zone\": \"fr-par-1\"}, {\"id\": \"11111111-2222-4333-8444-000000000004\", \"protocol\": \"TCP\", \"direction\": \"outbound\", \"ip_range\": \"::/0\", \"dest_ip_range\": null, \"dest_port_from\": 25, \"dest_port_to\": null, \"position\": 4, \"editable\": false, \"action\": \"drop\", \"zone\": \"fr-par-1\"}, {\"id\": \"11111111-2222-4333-8444-000000000005\", \"protocol\": \"TCP\", \"direction\": \"outbound\", \"ip_range\": \"::/0\", \"dest_ip_range\": null, \"dest_port_from\": 465, \"dest_port_to\": null, \"position\": 5, \"editable\": false, \"action\": \"drop\", \"zone\": \"fr-par-1\"}, {\"id\": \"11111111-2222-4333-8444-000000000006\", \"protocol\": \"TCP\", \"direction\": \"outbound\", \"ip_range\": \"::/0\", \"dest_ip_range\": null, \"dest_port_from\": 587, \"dest_port_to\": null, \"position\": 6, \"editable\": false, \"action\": \"drop\", \"zone\": \"fr-par-1\"}]}" - headers: - Content-Length: - - "1536" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:12:59 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - dc007331-e008-487c-8690-69c36bfb4c28 - status: 200 OK - code: 200 - duration: 72.568131ms -- id: 3 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/6bbed5ce-6b01-4841-9adb-c18fc2b80774 - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 0 - body: "" - headers: - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:12:59 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 16d5dd10-8b0b-48d5-a0a3-2e89c03d3bb0 - status: 204 No Content - code: 204 - duration: 110.833429ms diff --git a/internal/namespaces/instance/v1/testdata/test-security-group-get-get.golden b/internal/namespaces/instance/v1/testdata/test-security-group-get-get.golden deleted file mode 100644 index 6fed4df594..0000000000 --- a/internal/namespaces/instance/v1/testdata/test-security-group-get-get.golden +++ /dev/null @@ -1,124 +0,0 @@ -🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 -🟩🟩🟩 STDOUT️ 🟩🟩🟩️ -Security Group: -ID 6bbed5ce-6b01-4841-9adb-c18fc2b80774 -Name cli-sg-charming-rubin -State available -Description - -EnableDefaultSecurity true -OrganizationID fa1e3217-dc80-42ac-85c3-3f034b78b552 -ProjectID fa1e3217-dc80-42ac-85c3-3f034b78b552 -OrganizationDefault false -ProjectDefault false -CreationDate few seconds ago -ModificationDate few seconds ago -Stateful true - -Inbound Rules (default policy accept): -ID DIRECTION PROTOCOL ACTION IP RANGE DEST - -Outbound Rules (default policy accept): -ID DIRECTION PROTOCOL ACTION IP RANGE DEST -11111111-2222-4333-8444-000000000001 outbound TCP drop 0.0.0.0/0 25 -11111111-2222-4333-8444-000000000002 outbound TCP drop 0.0.0.0/0 465 -11111111-2222-4333-8444-000000000003 outbound TCP drop 0.0.0.0/0 587 -11111111-2222-4333-8444-000000000004 outbound TCP drop ::/0 25 -11111111-2222-4333-8444-000000000005 outbound TCP drop ::/0 465 -11111111-2222-4333-8444-000000000006 outbound TCP drop ::/0 587 - -Servers: -ID NAME -🟩🟩🟩 JSON STDOUT 🟩🟩🟩 -{ - "id": "6bbed5ce-6b01-4841-9adb-c18fc2b80774", - "name": "cli-sg-charming-rubin", - "description": "", - "enable_default_security": true, - "inbound_default_policy": "accept", - "outbound_default_policy": "accept", - "organization": "fa1e3217-dc80-42ac-85c3-3f034b78b552", - "project": "fa1e3217-dc80-42ac-85c3-3f034b78b552", - "tags": [], - "organization_default": false, - "project_default": false, - "creation_date": "1970-01-01T00:00:00.0Z", - "modification_date": "1970-01-01T00:00:00.0Z", - "servers": [], - "stateful": true, - "state": "available", - "zone": "fr-par-1", - "Rules": [ - { - "id": "11111111-2222-4333-8444-000000000001", - "protocol": "TCP", - "direction": "outbound", - "action": "drop", - "ip_range": "0.0.0.0/0", - "dest_port_from": 25, - "dest_port_to": null, - "position": 1, - "editable": false, - "zone": "fr-par-1" - }, - { - "id": "11111111-2222-4333-8444-000000000002", - "protocol": "TCP", - "direction": "outbound", - "action": "drop", - "ip_range": "0.0.0.0/0", - "dest_port_from": 465, - "dest_port_to": null, - "position": 2, - "editable": false, - "zone": "fr-par-1" - }, - { - "id": "11111111-2222-4333-8444-000000000003", - "protocol": "TCP", - "direction": "outbound", - "action": "drop", - "ip_range": "0.0.0.0/0", - "dest_port_from": 587, - "dest_port_to": null, - "position": 3, - "editable": false, - "zone": "fr-par-1" - }, - { - "id": "11111111-2222-4333-8444-000000000004", - "protocol": "TCP", - "direction": "outbound", - "action": "drop", - "ip_range": "::/0", - "dest_port_from": 25, - "dest_port_to": null, - "position": 4, - "editable": false, - "zone": "fr-par-1" - }, - { - "id": "11111111-2222-4333-8444-000000000005", - "protocol": "TCP", - "direction": "outbound", - "action": "drop", - "ip_range": "::/0", - "dest_port_from": 465, - "dest_port_to": null, - "position": 5, - "editable": false, - "zone": "fr-par-1" - }, - { - "id": "11111111-2222-4333-8444-000000000006", - "protocol": "TCP", - "direction": "outbound", - "action": "drop", - "ip_range": "::/0", - "dest_port_from": 587, - "dest_port_to": null, - "position": 6, - "editable": false, - "zone": "fr-par-1" - } - ] -} diff --git a/internal/namespaces/instance/v1/testdata/test-server-update-custom-update-server-security-group-id-from-server-with-security-group-id.cassette.yaml b/internal/namespaces/instance/v1/testdata/test-server-update-custom-update-server-security-group-id-from-server-with-security-group-id.cassette.yaml index 19f1146cae..43948babe7 100644 --- a/internal/namespaces/instance/v1/testdata/test-server-update-custom-update-server-security-group-id-from-server-with-security-group-id.cassette.yaml +++ b/internal/namespaces/instance/v1/testdata/test-server-update-custom-update-server-security-group-id-from-server-with-security-group-id.cassette.yaml @@ -1,548 +1,685 @@ --- version: 2 interactions: -- id: 0 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 164 - host: api.scaleway.com - body: "{\"name\":\"cli-sg-sweet-jepsen\",\"project\":\"fa1e3217-dc80-42ac-85c3-3f034b78b552\",\"stateful\":true,\"inbound_default_policy\":\"accept\",\"outbound_default_policy\":\"accept\"}" - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups - method: POST - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 585 - body: "{\"security_group\": {\"id\": \"7e1d0ec9-7984-4d72-bac2-9b98865b1644\", \"creation_date\": \"2025-11-04T10:24:40.121662+00:00\", \"modification_date\": \"2025-11-04T10:24:40.121662+00:00\", \"name\": \"cli-sg-sweet-jepsen\", \"description\": null, \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"servers\": [], \"stateful\": true, \"inbound_default_policy\": \"accept\", \"outbound_default_policy\": \"accept\", \"organization_default\": false, \"project_default\": false, \"enable_default_security\": true, \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}}" - headers: - Content-Length: - - "585" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:40 GMT - Location: - - https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/7e1d0ec9-7984-4d72-bac2-9b98865b1644 - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 3522b52e-d50f-43ac-8468-2e84ab2ca10c - status: 201 Created - code: 201 - duration: 132.201229ms -- id: 1 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 169 - host: api.scaleway.com - body: "{\"name\":\"cli-sg-epic-visvesvaraya\",\"project\":\"fa1e3217-dc80-42ac-85c3-3f034b78b552\",\"stateful\":true,\"inbound_default_policy\":\"accept\",\"outbound_default_policy\":\"accept\"}" - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups - method: POST - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 590 - body: "{\"security_group\": {\"id\": \"9104a94f-692c-4880-96b6-8f4600b87200\", \"creation_date\": \"2025-11-04T10:24:40.249298+00:00\", \"modification_date\": \"2025-11-04T10:24:40.249298+00:00\", \"name\": \"cli-sg-epic-visvesvaraya\", \"description\": null, \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"servers\": [], \"stateful\": true, \"inbound_default_policy\": \"accept\", \"outbound_default_policy\": \"accept\", \"organization_default\": false, \"project_default\": false, \"enable_default_security\": true, \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}}" - headers: - Content-Length: - - "590" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:40 GMT - Location: - - https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/9104a94f-692c-4880-96b6-8f4600b87200 - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 8c87104c-f74f-4d22-8133-e6b5bad14ec7 - status: 201 Created - code: 201 - duration: 137.408538ms -- id: 2 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - form: - page: - - "1" - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/products/servers?page=1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 39264 - body: "{\"servers\": {\"COPARM1-16C-64G\": {\"alt_names\": [], \"arch\": \"arm64\", \"ncpus\": 16, \"ram\": 68719476736, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 252.14, \"hourly_price\": 0.3454, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1600000000, \"sum_internet_bandwidth\": 1600000000, \"interfaces\": [{\"internal_bandwidth\": 1600000000, \"internet_bandwidth\": 1600000000}]}, \"block_bandwidth\": 671088640, \"end_of_service\": false}, \"COPARM1-2C-8G\": {\"alt_names\": [], \"arch\": \"arm64\", \"ncpus\": 2, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 31.1, \"hourly_price\": 0.0426, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 200000000, \"sum_internet_bandwidth\": 200000000, \"interfaces\": [{\"internal_bandwidth\": 200000000, \"internet_bandwidth\": 200000000}]}, \"block_bandwidth\": 83886080, \"end_of_service\": false}, \"COPARM1-32C-128G\": {\"alt_names\": [], \"arch\": \"arm64\", \"ncpus\": 32, \"ram\": 137438953472, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 506.26, \"hourly_price\": 0.6935, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 3200000000, \"sum_internet_bandwidth\": 3200000000, \"interfaces\": [{\"internal_bandwidth\": 3200000000, \"internet_bandwidth\": 3200000000}]}, \"block_bandwidth\": 1342177280, \"end_of_service\": false}, \"COPARM1-4C-16G\": {\"alt_names\": [], \"arch\": \"arm64\", \"ncpus\": 4, \"ram\": 17179869184, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 62.56, \"hourly_price\": 0.0857, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 400000000, \"sum_internet_bandwidth\": 400000000, \"interfaces\": [{\"internal_bandwidth\": 400000000, \"internet_bandwidth\": 400000000}]}, \"block_bandwidth\": 167772160, \"end_of_service\": false}, \"COPARM1-8C-32G\": {\"alt_names\": [], \"arch\": \"arm64\", \"ncpus\": 8, \"ram\": 34359738368, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 125.85, \"hourly_price\": 0.1724, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 800000000, \"sum_internet_bandwidth\": 800000000, \"interfaces\": [{\"internal_bandwidth\": 800000000, \"internet_bandwidth\": 800000000}]}, \"block_bandwidth\": 335544320, \"end_of_service\": false}, \"DEV1-L\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 80000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 36.1496, \"hourly_price\": 0.04952, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 400000000, \"sum_internet_bandwidth\": 400000000, \"interfaces\": [{\"internal_bandwidth\": 400000000, \"internet_bandwidth\": 400000000}]}, \"block_bandwidth\": 209715200, \"end_of_service\": false}, \"DEV1-M\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 3, \"ram\": 4294967296, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 40000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 18.6588, \"hourly_price\": 0.02556, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 300000000, \"sum_internet_bandwidth\": 300000000, \"interfaces\": [{\"internal_bandwidth\": 300000000, \"internet_bandwidth\": 300000000}]}, \"block_bandwidth\": 157286400, \"end_of_service\": false}, \"DEV1-S\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 2147483648, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 20000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 9.9864, \"hourly_price\": 0.01368, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 200000000, \"sum_internet_bandwidth\": 200000000, \"interfaces\": [{\"internal_bandwidth\": 200000000, \"internet_bandwidth\": 200000000}]}, \"block_bandwidth\": 104857600, \"end_of_service\": false}, \"DEV1-XL\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 12884901888, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 120000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 53.3484, \"hourly_price\": 0.07308, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 500000000, \"sum_internet_bandwidth\": 500000000, \"interfaces\": [{\"internal_bandwidth\": 500000000, \"internet_bandwidth\": 500000000}]}, \"block_bandwidth\": 262144000, \"end_of_service\": false}, \"GP1-L\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 32, \"ram\": 137438953472, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 600000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 576.262, \"hourly_price\": 0.7894, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 5000000000, \"sum_internet_bandwidth\": 5000000000, \"interfaces\": [{\"internal_bandwidth\": 5000000000, \"internet_bandwidth\": 5000000000}]}, \"block_bandwidth\": 1073741824, \"end_of_service\": false}, \"GP1-M\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 16, \"ram\": 68719476736, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 600000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 296.672, \"hourly_price\": 0.4064, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1500000000, \"sum_internet_bandwidth\": 1500000000, \"interfaces\": [{\"internal_bandwidth\": 1500000000, \"internet_bandwidth\": 1500000000}]}, \"block_bandwidth\": 838860800, \"end_of_service\": false}, \"GP1-S\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 34359738368, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 300000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 149.066, \"hourly_price\": 0.2042, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 800000000, \"sum_internet_bandwidth\": 800000000, \"interfaces\": [{\"internal_bandwidth\": 800000000, \"internet_bandwidth\": 800000000}]}, \"block_bandwidth\": 524288000, \"end_of_service\": false}, \"GP1-XL\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 48, \"ram\": 274877906944, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 600000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 1220.122, \"hourly_price\": 1.6714, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 10000000000, \"sum_internet_bandwidth\": 10000000000, \"interfaces\": [{\"internal_bandwidth\": 10000000000, \"internet_bandwidth\": 10000000000}]}, \"block_bandwidth\": 2147483648, \"end_of_service\": false}, \"GP1-XS\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 17179869184, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 150000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 74.168, \"hourly_price\": 0.1016, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 500000000, \"sum_internet_bandwidth\": 500000000, \"interfaces\": [{\"internal_bandwidth\": 500000000, \"internet_bandwidth\": 500000000}]}, \"block_bandwidth\": 314572800, \"end_of_service\": false}, \"L4-1-24G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 51539607552, \"gpu\": 1, \"gpu_info\": {\"gpu_manufacturer\": \"NVIDIA\", \"gpu_name\": \"L4\", \"gpu_memory\": 25769803776}, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 547.5, \"hourly_price\": 0.75, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 2}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 2500000000, \"sum_internet_bandwidth\": 2500000000, \"interfaces\": [{\"internal_bandwidth\": 2500000000, \"internet_bandwidth\": 2500000000}]}, \"block_bandwidth\": 1048576000, \"end_of_service\": false}, \"L4-2-24G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 16, \"ram\": 103079215104, \"gpu\": 2, \"gpu_info\": {\"gpu_manufacturer\": \"NVIDIA\", \"gpu_name\": \"L4\", \"gpu_memory\": 25769803776}, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 1095.0, \"hourly_price\": 1.5, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 4}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 5000000000, \"sum_internet_bandwidth\": 5000000000, \"interfaces\": [{\"internal_bandwidth\": 5000000000, \"internet_bandwidth\": 5000000000}]}, \"block_bandwidth\": 1572864000, \"end_of_service\": false}, \"L4-4-24G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 32, \"ram\": 206158430208, \"gpu\": 4, \"gpu_info\": {\"gpu_manufacturer\": \"NVIDIA\", \"gpu_name\": \"L4\", \"gpu_memory\": 25769803776}, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 2190.0, \"hourly_price\": 3.0, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 8}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 10000000000, \"sum_internet_bandwidth\": 10000000000, \"interfaces\": [{\"internal_bandwidth\": 10000000000, \"internet_bandwidth\": 10000000000}]}, \"block_bandwidth\": 2621440000, \"end_of_service\": false}, \"L4-8-24G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 64, \"ram\": 412316860416, \"gpu\": 8, \"gpu_info\": {\"gpu_manufacturer\": \"NVIDIA\", \"gpu_name\": \"L4\", \"gpu_memory\": 25769803776}, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 4380.0, \"hourly_price\": 6.0, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 16}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 20000000000, \"sum_internet_bandwidth\": 20000000000, \"interfaces\": [{\"internal_bandwidth\": 20000000000, \"internet_bandwidth\": 20000000000}]}, \"block_bandwidth\": 5242880000, \"end_of_service\": false}, \"PLAY2-MICRO\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 39.42, \"hourly_price\": 0.054, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 400000000, \"sum_internet_bandwidth\": 400000000, \"interfaces\": [{\"internal_bandwidth\": 400000000, \"internet_bandwidth\": 400000000}]}, \"block_bandwidth\": 167772160, \"end_of_service\": false}, \"PLAY2-NANO\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 4294967296, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 19.71, \"hourly_price\": 0.027, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 200000000, \"sum_internet_bandwidth\": 200000000, \"interfaces\": [{\"internal_bandwidth\": 200000000, \"internet_bandwidth\": 200000000}]}, \"block_bandwidth\": 83886080, \"end_of_service\": false}, \"PLAY2-PICO\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 1, \"ram\": 2147483648, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 10.22, \"hourly_price\": 0.014, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 100000000, \"sum_internet_bandwidth\": 100000000, \"interfaces\": [{\"internal_bandwidth\": 100000000, \"internet_bandwidth\": 100000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": false}, \"POP2-16C-64G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 16, \"ram\": 68719476736, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 430.7, \"hourly_price\": 0.59, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 4}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 3200000000, \"sum_internet_bandwidth\": 3200000000, \"interfaces\": [{\"internal_bandwidth\": 3200000000, \"internet_bandwidth\": 3200000000}]}, \"block_bandwidth\": 3355443200, \"end_of_service\": false}, \"POP2-16C-64G-WIN\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 16, \"ram\": 68719476736, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 1063.391, \"hourly_price\": 1.4567, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 3200000000, \"sum_internet_bandwidth\": 3200000000, \"interfaces\": [{\"internal_bandwidth\": 3200000000, \"internet_bandwidth\": 3200000000}]}, \"block_bandwidth\": 3355443200, \"end_of_service\": false}, \"POP2-2C-8G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 53.66, \"hourly_price\": 0.0735, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 1}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 400000000, \"sum_internet_bandwidth\": 400000000, \"interfaces\": [{\"internal_bandwidth\": 400000000, \"internet_bandwidth\": 400000000}]}, \"block_bandwidth\": 419430400, \"end_of_service\": false}, \"POP2-2C-8G-WIN\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 133.079, \"hourly_price\": 0.1823, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 400000000, \"sum_internet_bandwidth\": 400000000, \"interfaces\": [{\"internal_bandwidth\": 400000000, \"internet_bandwidth\": 400000000}]}, \"block_bandwidth\": 419430400, \"end_of_service\": false}, \"POP2-32C-128G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 32, \"ram\": 137438953472, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 861.4, \"hourly_price\": 1.18, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 8}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 6400000000, \"sum_internet_bandwidth\": 6400000000, \"interfaces\": [{\"internal_bandwidth\": 6400000000, \"internet_bandwidth\": 6400000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-32C-128G-WIN\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 32, \"ram\": 137438953472, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 2126.709, \"hourly_price\": 2.9133, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 6400000000, \"sum_internet_bandwidth\": 6400000000, \"interfaces\": [{\"internal_bandwidth\": 6400000000, \"internet_bandwidth\": 6400000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-48C-192G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 48, \"ram\": 206158430208, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 1274.4, \"hourly_price\": 1.77, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 12}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 9600000000, \"sum_internet_bandwidth\": 9600000000, \"interfaces\": [{\"internal_bandwidth\": 9600000000, \"internet_bandwidth\": 9600000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-4C-16G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 17179869184, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 107.31, \"hourly_price\": 0.147, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 1}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 800000000, \"sum_internet_bandwidth\": 800000000, \"interfaces\": [{\"internal_bandwidth\": 800000000, \"internet_bandwidth\": 800000000}]}, \"block_bandwidth\": 838860800, \"end_of_service\": false}, \"POP2-4C-16G-WIN\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 17179869184, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 265.501, \"hourly_price\": 0.3637, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 800000000, \"sum_internet_bandwidth\": 800000000, \"interfaces\": [{\"internal_bandwidth\": 800000000, \"internet_bandwidth\": 800000000}]}, \"block_bandwidth\": 838860800, \"end_of_service\": false}, \"POP2-64C-256G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 64, \"ram\": 274877906944, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 1715.5, \"hourly_price\": 2.35, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 16}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 12800000000, \"sum_internet_bandwidth\": 12800000000, \"interfaces\": [{\"internal_bandwidth\": 12800000000, \"internet_bandwidth\": 12800000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-8C-32G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 34359738368, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 211.7, \"hourly_price\": 0.29, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 2}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1600000000, \"sum_internet_bandwidth\": 1600000000, \"interfaces\": [{\"internal_bandwidth\": 1600000000, \"internet_bandwidth\": 1600000000}]}, \"block_bandwidth\": 1677721600, \"end_of_service\": false}, \"POP2-8C-32G-WIN\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 34359738368, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 528.009, \"hourly_price\": 0.7233, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1600000000, \"sum_internet_bandwidth\": 1600000000, \"interfaces\": [{\"internal_bandwidth\": 1600000000, \"internet_bandwidth\": 1600000000}]}, \"block_bandwidth\": 1677721600, \"end_of_service\": false}, \"POP2-HC-16C-32G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 16, \"ram\": 34359738368, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 310.69, \"hourly_price\": 0.4256, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 4}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 3200000000, \"sum_internet_bandwidth\": 3200000000, \"interfaces\": [{\"internal_bandwidth\": 3200000000, \"internet_bandwidth\": 3200000000}]}, \"block_bandwidth\": 3355443200, \"end_of_service\": false}, \"POP2-HC-2C-4G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 4294967296, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 38.84, \"hourly_price\": 0.0532, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 1}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 400000000, \"sum_internet_bandwidth\": 400000000, \"interfaces\": [{\"internal_bandwidth\": 400000000, \"internet_bandwidth\": 400000000}]}, \"block_bandwidth\": 419430400, \"end_of_service\": false}, \"POP2-HC-32C-64G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 32, \"ram\": 68719476736, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 621.38, \"hourly_price\": 0.8512, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 8}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 6400000000, \"sum_internet_bandwidth\": 6400000000, \"interfaces\": [{\"internal_bandwidth\": 6400000000, \"internet_bandwidth\": 6400000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-HC-48C-96G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 48, \"ram\": 103079215104, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 914.4, \"hourly_price\": 1.27, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 12}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 9600000000, \"sum_internet_bandwidth\": 9600000000, \"interfaces\": [{\"internal_bandwidth\": 9600000000, \"internet_bandwidth\": 9600000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-HC-4C-8G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 77.67, \"hourly_price\": 0.1064, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 1}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 800000000, \"sum_internet_bandwidth\": 800000000, \"interfaces\": [{\"internal_bandwidth\": 800000000, \"internet_bandwidth\": 800000000}]}, \"block_bandwidth\": 838860800, \"end_of_service\": false}, \"POP2-HC-64C-128G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 64, \"ram\": 137438953472, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 1242.75, \"hourly_price\": 1.7024, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 16}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 12800000000, \"sum_internet_bandwidth\": 12800000000, \"interfaces\": [{\"internal_bandwidth\": 12800000000, \"internet_bandwidth\": 12800000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-HC-8C-16G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 17179869184, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 155.34, \"hourly_price\": 0.2128, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 2}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1600000000, \"sum_internet_bandwidth\": 1600000000, \"interfaces\": [{\"internal_bandwidth\": 1600000000, \"internet_bandwidth\": 1600000000}]}, \"block_bandwidth\": 1677721600, \"end_of_service\": false}, \"POP2-HM-16C-128G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 16, \"ram\": 137438953472, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 601.52, \"hourly_price\": 0.824, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 4}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 3200000000, \"sum_internet_bandwidth\": 3200000000, \"interfaces\": [{\"internal_bandwidth\": 3200000000, \"internet_bandwidth\": 3200000000}]}, \"block_bandwidth\": 3355443200, \"end_of_service\": false}, \"POP2-HM-2C-16G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 17179869184, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 75.19, \"hourly_price\": 0.103, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 2}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 400000000, \"sum_internet_bandwidth\": 400000000, \"interfaces\": [{\"internal_bandwidth\": 400000000, \"internet_bandwidth\": 400000000}]}, \"block_bandwidth\": 419430400, \"end_of_service\": false}, \"POP2-HM-32C-256G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 32, \"ram\": 274877906944, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 1203.04, \"hourly_price\": 1.648, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 8}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 6400000000, \"sum_internet_bandwidth\": 6400000000, \"interfaces\": [{\"internal_bandwidth\": 6400000000, \"internet_bandwidth\": 6400000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-HM-48C-384G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 48, \"ram\": 412316860416, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 1778.4, \"hourly_price\": 2.47, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 12}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 9600000000, \"sum_internet_bandwidth\": 9600000000, \"interfaces\": [{\"internal_bandwidth\": 9600000000, \"internet_bandwidth\": 9600000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-HM-4C-32G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 34359738368, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 150.38, \"hourly_price\": 0.206, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 1}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 800000000, \"sum_internet_bandwidth\": 800000000, \"interfaces\": [{\"internal_bandwidth\": 800000000, \"internet_bandwidth\": 800000000}]}, \"block_bandwidth\": 838860800, \"end_of_service\": false}, \"POP2-HM-64C-512G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 64, \"ram\": 549755813888, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 2406.08, \"hourly_price\": 3.296, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 16}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 12800000000, \"sum_internet_bandwidth\": 12800000000, \"interfaces\": [{\"internal_bandwidth\": 12800000000, \"internet_bandwidth\": 12800000000}]}, \"block_bandwidth\": 5905580032, \"end_of_service\": false}, \"POP2-HM-8C-64G\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 68719476736, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 300.76, \"hourly_price\": 0.412, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 2}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1600000000, \"sum_internet_bandwidth\": 1600000000, \"interfaces\": [{\"internal_bandwidth\": 1600000000, \"internet_bandwidth\": 1600000000}]}, \"block_bandwidth\": 1677721600, \"end_of_service\": false}, \"POP2-HN-10\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 530.29, \"hourly_price\": 0.7264, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 1}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 10000000000, \"sum_internet_bandwidth\": 10000000000, \"interfaces\": [{\"internal_bandwidth\": 10000000000, \"internet_bandwidth\": 10000000000}]}, \"block_bandwidth\": 838860800, \"end_of_service\": false}, \"POP2-HN-3\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 4294967296, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 186.49, \"hourly_price\": 0.2554, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 1}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 3000000000, \"sum_internet_bandwidth\": 3000000000, \"interfaces\": [{\"internal_bandwidth\": 3000000000, \"internet_bandwidth\": 3000000000}]}, \"block_bandwidth\": 419430400, \"end_of_service\": false}, \"POP2-HN-5\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 330.29, \"hourly_price\": 0.4524, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 1}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 5000000000, \"sum_internet_bandwidth\": 5000000000, \"interfaces\": [{\"internal_bandwidth\": 5000000000, \"internet_bandwidth\": 5000000000}]}, \"block_bandwidth\": 838860800, \"end_of_service\": false}}}" - headers: - Content-Length: - - "39264" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:40 GMT - Link: - - ; rel="next",; rel="last" - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - e087c1ab-4b55-4670-b1c0-873d02351c17 - X-Total-Count: - - "68" - status: 200 OK - code: 200 - duration: 53.500821ms -- id: 3 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - form: - page: - - "2" - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/products/servers?page=2 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 14295 - body: "{\"servers\": {\"PRO2-L\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 32, \"ram\": 137438953472, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 640.21, \"hourly_price\": 0.877, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 6000000000, \"sum_internet_bandwidth\": 6000000000, \"interfaces\": [{\"internal_bandwidth\": 6000000000, \"internet_bandwidth\": 6000000000}]}, \"block_bandwidth\": 2097152000, \"end_of_service\": false}, \"PRO2-M\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 16, \"ram\": 68719476736, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 319.74, \"hourly_price\": 0.438, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 3000000000, \"sum_internet_bandwidth\": 3000000000, \"interfaces\": [{\"internal_bandwidth\": 3000000000, \"internet_bandwidth\": 3000000000}]}, \"block_bandwidth\": 1048576000, \"end_of_service\": false}, \"PRO2-S\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 34359738368, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 159.87, \"hourly_price\": 0.219, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1500000000, \"sum_internet_bandwidth\": 1500000000, \"interfaces\": [{\"internal_bandwidth\": 1500000000, \"internet_bandwidth\": 1500000000}]}, \"block_bandwidth\": 524288000, \"end_of_service\": false}, \"PRO2-XS\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 17179869184, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 80.3, \"hourly_price\": 0.11, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 700000000, \"sum_internet_bandwidth\": 700000000, \"interfaces\": [{\"internal_bandwidth\": 700000000, \"internet_bandwidth\": 700000000}]}, \"block_bandwidth\": 262144000, \"end_of_service\": false}, \"PRO2-XXS\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 0}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 0, \"max_size\": 0}}, \"scratch_storage_max_size\": null, \"monthly_price\": 40.15, \"hourly_price\": 0.055, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": false, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 350000000, \"sum_internet_bandwidth\": 350000000, \"interfaces\": [{\"internal_bandwidth\": 350000000, \"internet_bandwidth\": 350000000}]}, \"block_bandwidth\": 131072000, \"end_of_service\": false}, \"RENDER-S\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 10, \"ram\": 45097156608, \"gpu\": 1, \"gpu_info\": {\"gpu_manufacturer\": \"NVIDIA\", \"gpu_name\": \"P100\", \"gpu_memory\": 17179869184}, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 400000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 907.098, \"hourly_price\": 1.2426, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 2000000000, \"sum_internet_bandwidth\": 2000000000, \"interfaces\": [{\"internal_bandwidth\": 2000000000, \"internet_bandwidth\": 2000000000}]}, \"block_bandwidth\": 2147483648, \"end_of_service\": false}, \"STARDUST1-S\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 1, \"ram\": 1073741824, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 10000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 3.3507, \"hourly_price\": 0.00459, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 100000000, \"sum_internet_bandwidth\": 100000000, \"interfaces\": [{\"internal_bandwidth\": 100000000, \"internet_bandwidth\": 100000000}]}, \"block_bandwidth\": 52428800, \"end_of_service\": false}, \"START1-L\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 200000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 26.864, \"hourly_price\": 0.0368, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 400000000, \"sum_internet_bandwidth\": 400000000, \"interfaces\": [{\"internal_bandwidth\": 400000000, \"internet_bandwidth\": 400000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"START1-M\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 4294967296, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 100000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 14.162, \"hourly_price\": 0.0194, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 300000000, \"sum_internet_bandwidth\": 300000000, \"interfaces\": [{\"internal_bandwidth\": 300000000, \"internet_bandwidth\": 300000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"START1-S\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 2147483648, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 50000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 7.738, \"hourly_price\": 0.0106, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 200000000, \"sum_internet_bandwidth\": 200000000, \"interfaces\": [{\"internal_bandwidth\": 200000000, \"internet_bandwidth\": 200000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"START1-XS\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 1, \"ram\": 1073741824, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 25000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 4.526, \"hourly_price\": 0.0062, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 100000000, \"sum_internet_bandwidth\": 100000000, \"interfaces\": [{\"internal_bandwidth\": 100000000, \"internet_bandwidth\": 100000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"VC1L\": {\"alt_names\": [\"X64-8GB\"], \"arch\": \"x86_64\", \"ncpus\": 6, \"ram\": 8589934592, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 200000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 18.0164, \"hourly_price\": 0.02468, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 200000000, \"sum_internet_bandwidth\": 200000000, \"interfaces\": [{\"internal_bandwidth\": 200000000, \"internet_bandwidth\": 200000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"VC1M\": {\"alt_names\": [\"X64-4GB\"], \"arch\": \"x86_64\", \"ncpus\": 4, \"ram\": 4294967296, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 100000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 11.3515, \"hourly_price\": 0.01555, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 200000000, \"sum_internet_bandwidth\": 200000000, \"interfaces\": [{\"internal_bandwidth\": 200000000, \"internet_bandwidth\": 200000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"VC1S\": {\"alt_names\": [\"X64-2GB\"], \"arch\": \"x86_64\", \"ncpus\": 2, \"ram\": 2147483648, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 50000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 6.2926, \"hourly_price\": 0.00862, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 200000000, \"sum_internet_bandwidth\": 200000000, \"interfaces\": [{\"internal_bandwidth\": 200000000, \"internet_bandwidth\": 200000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"X64-120GB\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 12, \"ram\": 128849018880, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 800000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 310.7902, \"hourly_price\": 0.42574, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1000000000, \"sum_internet_bandwidth\": 1000000000, \"interfaces\": [{\"internal_bandwidth\": 1000000000, \"internet_bandwidth\": 1000000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"X64-15GB\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 6, \"ram\": 16106127360, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 200000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 44.0336, \"hourly_price\": 0.06032, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 250000000, \"sum_internet_bandwidth\": 250000000, \"interfaces\": [{\"internal_bandwidth\": 250000000, \"internet_bandwidth\": 250000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"X64-30GB\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 8, \"ram\": 32212254720, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 400000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 86.9138, \"hourly_price\": 0.11906, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 500000000, \"sum_internet_bandwidth\": 500000000, \"interfaces\": [{\"internal_bandwidth\": 500000000, \"internet_bandwidth\": 500000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}, \"X64-60GB\": {\"alt_names\": [], \"arch\": \"x86_64\", \"ncpus\": 10, \"ram\": 64424509440, \"gpu\": 0, \"gpu_info\": null, \"mig_profile\": null, \"volumes_constraint\": {\"min_size\": 0, \"max_size\": 700000000000}, \"per_volume_constraint\": {\"l_ssd\": {\"min_size\": 1000000000, \"max_size\": 800000000000}}, \"scratch_storage_max_size\": null, \"monthly_price\": 155.49, \"hourly_price\": 0.213, \"capabilities\": {\"boot_types\": [\"local\", \"rescue\"], \"placement_groups\": true, \"block_storage\": true, \"hot_snapshots_local_volume\": true, \"private_network\": 8, \"max_file_systems\": 0}, \"network\": {\"ipv6_support\": true, \"sum_internal_bandwidth\": 1000000000, \"sum_internet_bandwidth\": 1000000000, \"interfaces\": [{\"internal_bandwidth\": 1000000000, \"internet_bandwidth\": 1000000000}]}, \"block_bandwidth\": 41943040, \"end_of_service\": true}}}" - headers: - Content-Length: - - "14295" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:40 GMT - Link: - - ; rel="first",; rel="previous",; rel="last" - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 37572bbc-45c7-4adf-905e-f7b6bf149454 - X-Total-Count: - - "68" - status: 200 OK - code: 200 - duration: 50.332419ms -- id: 4 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - form: - image_label: - - ubuntu_jammy - order_by: - - type_asc - type: - - instance_sbs - zone: - - fr-par-1 - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/marketplace/v2/local-images?image_label=ubuntu_jammy&order_by=type_asc&type=instance_sbs&zone=fr-par-1 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 1403 - body: "{\"local_images\":[{\"id\":\"65ce6135-f6d5-4e90-82ec-ef09d29d1cff\", \"arch\":\"arm64\", \"zone\":\"fr-par-1\", \"compatible_commercial_types\":[\"COPARM1-2C-8G\", \"COPARM1-4C-16G\", \"COPARM1-8C-32G\", \"COPARM1-16C-64G\", \"COPARM1-32C-128G\", \"BASIC2-A2C-4G\", \"BASIC2-A2C-8G\", \"BASIC2-A4C-8G\", \"BASIC2-A4C-16G\", \"BASIC2-A8C-16G\", \"BASIC2-A8C-32G\", \"BASIC2-A16C-32G\", \"BASIC2-A16C-64G\"], \"label\":\"ubuntu_jammy\", \"type\":\"instance_sbs\"}, {\"id\":\"6d3c053e-c728-4294-b23a-560b62a4d592\", \"arch\":\"x86_64\", \"zone\":\"fr-par-1\", \"compatible_commercial_types\":[\"DEV1-L\", \"DEV1-M\", \"DEV1-S\", \"DEV1-XL\", \"GP1-L\", \"GP1-M\", \"GP1-S\", \"GP1-XL\", \"GP1-XS\", \"START1-L\", \"START1-M\", \"START1-S\", \"START1-XS\", \"VC1L\", \"VC1M\", \"VC1S\", \"X64-120GB\", \"X64-15GB\", \"X64-30GB\", \"X64-60GB\", \"ENT1-XXS\", \"ENT1-XS\", \"ENT1-S\", \"ENT1-M\", \"ENT1-L\", \"ENT1-XL\", \"ENT1-2XL\", \"PRO2-XXS\", \"PRO2-XS\", \"PRO2-S\", \"PRO2-M\", \"PRO2-L\", \"STARDUST1-S\", \"PLAY2-MICRO\", \"PLAY2-NANO\", \"PLAY2-PICO\", \"POP2-2C-8G\", \"POP2-4C-16G\", \"POP2-8C-32G\", \"POP2-16C-64G\", \"POP2-32C-128G\", \"POP2-48C-192G\", \"POP2-64C-256G\", \"POP2-HM-2C-16G\", \"POP2-HM-4C-32G\", \"POP2-HM-8C-64G\", \"POP2-HM-16C-128G\", \"POP2-HM-32C-256G\", \"POP2-HM-48C-384G\", \"POP2-HM-64C-512G\", \"POP2-HC-2C-4G\", \"POP2-HC-4C-8G\", \"POP2-HC-8C-16G\", \"POP2-HC-16C-32G\", \"POP2-HC-32C-64G\", \"POP2-HC-48C-96G\", \"POP2-HC-64C-128G\", \"POP2-HN-3\", \"POP2-HN-5\", \"POP2-HN-10\"], \"label\":\"ubuntu_jammy\", \"type\":\"instance_sbs\"}], \"total_count\":2}" - headers: - Content-Length: - - "1403" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:40 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - ca7f5359-a5a2-428c-81fc-1488ddf0a01d - status: 200 OK - code: 200 - duration: 71.633277ms -- id: 5 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/images/6d3c053e-c728-4294-b23a-560b62a4d592 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 587 - body: "{\"image\": {\"id\": \"6d3c053e-c728-4294-b23a-560b62a4d592\", \"name\": \"Ubuntu 22.04 Jammy Jellyfish\", \"organization\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"project\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"root_volume\": {\"volume_type\": \"sbs_snapshot\", \"id\": \"36b4ce54-c67a-4f68-ab74-839515834352\", \"size\": 0, \"name\": \"\"}, \"extra_volumes\": {}, \"public\": true, \"arch\": \"x86_64\", \"creation_date\": \"2025-09-12T09:11:41.420846+00:00\", \"modification_date\": \"2025-09-12T09:11:41.420846+00:00\", \"default_bootscript\": null, \"from_server\": \"\", \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}}" - headers: - Content-Length: - - "587" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:40 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 769166c4-6c37-46ea-b3a7-339b95f23f79 - status: 200 OK - code: 200 - duration: 45.788261ms -- id: 6 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 283 - host: api.scaleway.com - body: "{\"name\":\"cli-srv-dazzling-elbakyan\",\"dynamic_ip_required\":false,\"commercial_type\":\"DEV1-S\",\"image\":\"6d3c053e-c728-4294-b23a-560b62a4d592\",\"enable_ipv6\":false,\"boot_type\":\"local\",\"project\":\"fa1e3217-dc80-42ac-85c3-3f034b78b552\",\"security_group\":\"7e1d0ec9-7984-4d72-bac2-9b98865b1644\"}" - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers - method: POST - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 1747 - body: "{\"server\": {\"id\": \"ffb648f8-8385-4e71-914a-28c89c155416\", \"name\": \"cli-srv-dazzling-elbakyan\", \"arch\": \"x86_64\", \"commercial_type\": \"DEV1-S\", \"boot_type\": \"local\", \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"hostname\": \"cli-srv-dazzling-elbakyan\", \"image\": {\"id\": \"6d3c053e-c728-4294-b23a-560b62a4d592\", \"name\": \"Ubuntu 22.04 Jammy Jellyfish\", \"organization\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"project\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"root_volume\": {\"volume_type\": \"sbs_snapshot\", \"id\": \"36b4ce54-c67a-4f68-ab74-839515834352\", \"size\": 0, \"name\": \"\"}, \"extra_volumes\": {}, \"public\": true, \"arch\": \"x86_64\", \"creation_date\": \"2025-09-12T09:11:41.420846+00:00\", \"modification_date\": \"2025-09-12T09:11:41.420846+00:00\", \"default_bootscript\": null, \"from_server\": \"\", \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}, \"volumes\": {\"0\": {\"boot\": false, \"volume_type\": \"sbs_volume\", \"id\": \"e42f76cd-4caa-4258-860f-5c286a783f8b\", \"state\": \"available\", \"zone\": \"fr-par-1\"}}, \"tags\": [], \"state\": \"stopped\", \"protected\": false, \"state_detail\": \"\", \"public_ip\": null, \"public_ips\": [], \"mac_address\": \"de:00:00:d1:45:f7\", \"routed_ip_enabled\": true, \"ipv6\": null, \"extra_networks\": [], \"dynamic_ip_required\": false, \"enable_ipv6\": false, \"private_ip\": null, \"creation_date\": \"2025-11-04T10:24:40.668974+00:00\", \"modification_date\": \"2025-11-04T10:24:40.668974+00:00\", \"bootscript\": null, \"security_group\": {\"id\": \"7e1d0ec9-7984-4d72-bac2-9b98865b1644\", \"name\": \"cli-sg-sweet-jepsen\"}, \"location\": null, \"maintenances\": [], \"allowed_actions\": [\"poweron\", \"backup\"], \"placement_group\": null, \"private_nics\": [], \"zone\": \"fr-par-1\", \"filesystems\": [], \"end_of_service\": false}}" - headers: - Content-Length: - - "1747" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:41 GMT - Location: - - https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ffb648f8-8385-4e71-914a-28c89c155416 - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - d49cc1a3-9a9e-4775-9c9a-4e68df1f8926 - status: 201 Created - code: 201 - duration: 493.150958ms -- id: 7 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ffb648f8-8385-4e71-914a-28c89c155416 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 1747 - body: "{\"server\": {\"id\": \"ffb648f8-8385-4e71-914a-28c89c155416\", \"name\": \"cli-srv-dazzling-elbakyan\", \"arch\": \"x86_64\", \"commercial_type\": \"DEV1-S\", \"boot_type\": \"local\", \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"hostname\": \"cli-srv-dazzling-elbakyan\", \"image\": {\"id\": \"6d3c053e-c728-4294-b23a-560b62a4d592\", \"name\": \"Ubuntu 22.04 Jammy Jellyfish\", \"organization\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"project\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"root_volume\": {\"volume_type\": \"sbs_snapshot\", \"id\": \"36b4ce54-c67a-4f68-ab74-839515834352\", \"size\": 0, \"name\": \"\"}, \"extra_volumes\": {}, \"public\": true, \"arch\": \"x86_64\", \"creation_date\": \"2025-09-12T09:11:41.420846+00:00\", \"modification_date\": \"2025-09-12T09:11:41.420846+00:00\", \"default_bootscript\": null, \"from_server\": \"\", \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}, \"volumes\": {\"0\": {\"boot\": false, \"volume_type\": \"sbs_volume\", \"id\": \"e42f76cd-4caa-4258-860f-5c286a783f8b\", \"state\": \"available\", \"zone\": \"fr-par-1\"}}, \"tags\": [], \"state\": \"stopped\", \"protected\": false, \"state_detail\": \"\", \"public_ip\": null, \"public_ips\": [], \"mac_address\": \"de:00:00:d1:45:f7\", \"routed_ip_enabled\": true, \"ipv6\": null, \"extra_networks\": [], \"dynamic_ip_required\": false, \"enable_ipv6\": false, \"private_ip\": null, \"creation_date\": \"2025-11-04T10:24:40.668974+00:00\", \"modification_date\": \"2025-11-04T10:24:40.668974+00:00\", \"bootscript\": null, \"security_group\": {\"id\": \"7e1d0ec9-7984-4d72-bac2-9b98865b1644\", \"name\": \"cli-sg-sweet-jepsen\"}, \"location\": null, \"maintenances\": [], \"allowed_actions\": [\"poweron\", \"backup\"], \"placement_group\": null, \"private_nics\": [], \"zone\": \"fr-par-1\", \"filesystems\": [], \"end_of_service\": false}}" - headers: - Content-Length: - - "1747" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:41 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 55ebc922-7184-43df-b0e7-7b8e590f8ee9 - status: 200 OK - code: 200 - duration: 100.066378ms -- id: 8 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 64 - host: api.scaleway.com - body: "{\"security_group\":{\"id\":\"9104a94f-692c-4880-96b6-8f4600b87200\"}}" - headers: - Content-Type: - - application/json - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ffb648f8-8385-4e71-914a-28c89c155416 - method: PATCH - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 1752 - body: "{\"server\": {\"id\": \"ffb648f8-8385-4e71-914a-28c89c155416\", \"name\": \"cli-srv-dazzling-elbakyan\", \"arch\": \"x86_64\", \"commercial_type\": \"DEV1-S\", \"boot_type\": \"local\", \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"hostname\": \"cli-srv-dazzling-elbakyan\", \"image\": {\"id\": \"6d3c053e-c728-4294-b23a-560b62a4d592\", \"name\": \"Ubuntu 22.04 Jammy Jellyfish\", \"organization\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"project\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"root_volume\": {\"volume_type\": \"sbs_snapshot\", \"id\": \"36b4ce54-c67a-4f68-ab74-839515834352\", \"size\": 0, \"name\": \"\"}, \"extra_volumes\": {}, \"public\": true, \"arch\": \"x86_64\", \"creation_date\": \"2025-09-12T09:11:41.420846+00:00\", \"modification_date\": \"2025-09-12T09:11:41.420846+00:00\", \"default_bootscript\": null, \"from_server\": \"\", \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}, \"volumes\": {\"0\": {\"boot\": false, \"volume_type\": \"sbs_volume\", \"id\": \"e42f76cd-4caa-4258-860f-5c286a783f8b\", \"state\": \"available\", \"zone\": \"fr-par-1\"}}, \"tags\": [], \"state\": \"stopped\", \"protected\": false, \"state_detail\": \"\", \"public_ip\": null, \"public_ips\": [], \"mac_address\": \"de:00:00:d1:45:f7\", \"routed_ip_enabled\": true, \"ipv6\": null, \"extra_networks\": [], \"dynamic_ip_required\": false, \"enable_ipv6\": false, \"private_ip\": null, \"creation_date\": \"2025-11-04T10:24:40.668974+00:00\", \"modification_date\": \"2025-11-04T10:24:41.179443+00:00\", \"bootscript\": null, \"security_group\": {\"id\": \"9104a94f-692c-4880-96b6-8f4600b87200\", \"name\": \"cli-sg-epic-visvesvaraya\"}, \"location\": null, \"maintenances\": [], \"allowed_actions\": [\"poweron\", \"backup\"], \"placement_group\": null, \"private_nics\": [], \"zone\": \"fr-par-1\", \"filesystems\": [], \"end_of_service\": false}}" - headers: - Content-Length: - - "1752" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:41 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - a2525cd7-eab0-446e-affa-517b3e79a799 - status: 200 OK - code: 200 - duration: 203.992882ms -- id: 9 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ffb648f8-8385-4e71-914a-28c89c155416 - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 1752 - body: "{\"server\": {\"id\": \"ffb648f8-8385-4e71-914a-28c89c155416\", \"name\": \"cli-srv-dazzling-elbakyan\", \"arch\": \"x86_64\", \"commercial_type\": \"DEV1-S\", \"boot_type\": \"local\", \"organization\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"project\": \"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"hostname\": \"cli-srv-dazzling-elbakyan\", \"image\": {\"id\": \"6d3c053e-c728-4294-b23a-560b62a4d592\", \"name\": \"Ubuntu 22.04 Jammy Jellyfish\", \"organization\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"project\": \"51b656e3-4865-41e8-adbc-0c45bdd780db\", \"root_volume\": {\"volume_type\": \"sbs_snapshot\", \"id\": \"36b4ce54-c67a-4f68-ab74-839515834352\", \"size\": 0, \"name\": \"\"}, \"extra_volumes\": {}, \"public\": true, \"arch\": \"x86_64\", \"creation_date\": \"2025-09-12T09:11:41.420846+00:00\", \"modification_date\": \"2025-09-12T09:11:41.420846+00:00\", \"default_bootscript\": null, \"from_server\": \"\", \"state\": \"available\", \"tags\": [], \"zone\": \"fr-par-1\"}, \"volumes\": {\"0\": {\"boot\": false, \"volume_type\": \"sbs_volume\", \"id\": \"e42f76cd-4caa-4258-860f-5c286a783f8b\", \"state\": \"available\", \"zone\": \"fr-par-1\"}}, \"tags\": [], \"state\": \"stopped\", \"protected\": false, \"state_detail\": \"\", \"public_ip\": null, \"public_ips\": [], \"mac_address\": \"de:00:00:d1:45:f7\", \"routed_ip_enabled\": true, \"ipv6\": null, \"extra_networks\": [], \"dynamic_ip_required\": false, \"enable_ipv6\": false, \"private_ip\": null, \"creation_date\": \"2025-11-04T10:24:40.668974+00:00\", \"modification_date\": \"2025-11-04T10:24:41.179443+00:00\", \"bootscript\": null, \"security_group\": {\"id\": \"9104a94f-692c-4880-96b6-8f4600b87200\", \"name\": \"cli-sg-epic-visvesvaraya\"}, \"location\": null, \"maintenances\": [], \"allowed_actions\": [\"poweron\", \"backup\"], \"placement_group\": null, \"private_nics\": [], \"zone\": \"fr-par-1\", \"filesystems\": [], \"end_of_service\": false}}" - headers: - Content-Length: - - "1752" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:41 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 72819b69-83fa-4bbf-b71a-748e2955bdfe - status: 200 OK - code: 200 - duration: 104.676088ms -- id: 10 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ffb648f8-8385-4e71-914a-28c89c155416 - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 0 - body: "" - headers: - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:41 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - fb50c1ec-224c-4f2c-9eb5-e95d31ab262b - status: 204 No Content - code: 204 - duration: 197.97164ms -- id: 11 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/block/v1alpha1/zones/fr-par-1/volumes/e42f76cd-4caa-4258-860f-5c286a783f8b - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 706 - body: "{\"id\":\"e42f76cd-4caa-4258-860f-5c286a783f8b\", \"name\":\"Ubuntu 22.04 Jammy Jellyfish_sbs_volume_0\", \"type\":\"sbs_5k\", \"size\":10000000000, \"project_id\":\"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"created_at\":\"2025-11-04T10:24:40.757537Z\", \"updated_at\":\"2025-11-04T10:24:40.757537Z\", \"references\":[{\"id\":\"78690022-22fa-4734-b179-78120b0bcd0a\", \"product_resource_type\":\"instance_server\", \"product_resource_id\":\"ffb648f8-8385-4e71-914a-28c89c155416\", \"created_at\":\"2025-11-04T10:24:40.757537Z\", \"type\":\"exclusive\", \"status\":\"detaching\"}], \"parent_snapshot_id\":\"36b4ce54-c67a-4f68-ab74-839515834352\", \"status\":\"in_use\", \"tags\":[], \"specs\":{\"perf_iops\":5000, \"class\":\"sbs\"}, \"last_detached_at\":null, \"zone\":\"fr-par-1\"}" - headers: - Content-Length: - - "706" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:41 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 9b9c3d3f-4953-42c6-a156-00875fb701ee - status: 200 OK - code: 200 - duration: 49.812777ms -- id: 12 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/block/v1alpha1/zones/fr-par-1/volumes/e42f76cd-4caa-4258-860f-5c286a783f8b - method: GET - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 498 - body: "{\"id\":\"e42f76cd-4caa-4258-860f-5c286a783f8b\", \"name\":\"Ubuntu 22.04 Jammy Jellyfish_sbs_volume_0\", \"type\":\"sbs_5k\", \"size\":10000000000, \"project_id\":\"fa1e3217-dc80-42ac-85c3-3f034b78b552\", \"created_at\":\"2025-11-04T10:24:40.757537Z\", \"updated_at\":\"2025-11-04T10:24:41.687544Z\", \"references\":[], \"parent_snapshot_id\":\"36b4ce54-c67a-4f68-ab74-839515834352\", \"status\":\"available\", \"tags\":[], \"specs\":{\"perf_iops\":5000, \"class\":\"sbs\"}, \"last_detached_at\":\"2025-11-04T10:24:41.687544Z\", \"zone\":\"fr-par-1\"}" - headers: - Content-Length: - - "498" - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:46 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - c61980cf-3e5d-4e9f-8230-77403042de33 - status: 200 OK - code: 200 - duration: 50.405766ms -- id: 13 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/block/v1alpha1/zones/fr-par-1/volumes/e42f76cd-4caa-4258-860f-5c286a783f8b - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 0 - body: "" - headers: - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:46 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 2cc94785-782e-4f3e-ad88-aa7cc298814a - status: 204 No Content - code: 204 - duration: 76.762759ms -- id: 14 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/7e1d0ec9-7984-4d72-bac2-9b98865b1644 - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 0 - body: "" - headers: - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:46 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - 553b61f9-eb74-4d2a-a051-e8a2369a7327 - status: 204 No Content - code: 204 - duration: 98.288307ms -- id: 15 - request: - proto: HTTP/1.1 - proto_major: 1 - proto_minor: 1 - content_length: 0 - host: api.scaleway.com - headers: - User-Agent: - - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.25.1; linux; amd64) cli-e2e-test - url: https://api.scaleway.com/instance/v1/zones/fr-par-1/security_groups/9104a94f-692c-4880-96b6-8f4600b87200 - method: DELETE - response: - proto: HTTP/2.0 - proto_major: 2 - proto_minor: 0 - content_length: 0 - body: "" - headers: - Content-Type: - - application/json - Date: - - Tue, 04 Nov 2025 10:24:47 GMT - Server: - - Scaleway API Gateway (fr-par-3;edge02) - X-Request-Id: - - cd0fd0c3-3aec-45f2-8fad-718eea890df4 - status: 204 No Content - code: 204 - duration: 97.831442ms + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 252 + host: api.scaleway.com + body: '{"name":"cli-sg-dreamy-moser","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":null,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2021 + body: '{"srn":"", "id":"5080afc5-b32a-44bf-95e3-30530f32850a", "name":"cli-sg-dreamy-moser", "description":"", "project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552", "tags":[], "disable_default_rules":false, "project_default":false, "inbound_default_action":"accept", "outbound_default_action":"accept", "stateless":false, "created_at":"2026-10-13T12:51:31.116176Z", "updated_at":"2026-10-13T12:51:31.116176Z", "default_rules":[{"id":"11111111-2222-4333-8444-000000000001", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"0.0.0.0/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":25, "end":25}, "position":1}, {"id":"11111111-2222-4333-8444-000000000002", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"0.0.0.0/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":465, "end":465}, "position":2}, {"id":"11111111-2222-4333-8444-000000000003", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"0.0.0.0/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":587, "end":587}, "position":3}, {"id":"11111111-2222-4333-8444-000000000004", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"::/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":25, "end":25}, "position":4}, {"id":"11111111-2222-4333-8444-000000000005", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"::/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":465, "end":465}, "position":5}, {"id":"11111111-2222-4333-8444-000000000006", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"::/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":587, "end":587}, "position":6}], "rules":[], "zone":"fr-par-1"}' + headers: + Content-Length: + - "2021" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - eb24b69b-6dd1-424e-b62b-d0b029bc160f + status: 200 OK + code: 200 + duration: 209.143249ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 6b516670-bc6e-4912-8b6b-72cfbbf62157 + status: 200 OK + code: 200 + duration: 10.850061ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 254 + host: api.scaleway.com + body: '{"name":"cli-sg-admiring-bassi","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":null,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2023 + body: '{"srn":"", "id":"c5260a58-af26-4fe9-9a69-c44b3e31bda1", "name":"cli-sg-admiring-bassi", "description":"", "project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552", "tags":[], "disable_default_rules":false, "project_default":false, "inbound_default_action":"accept", "outbound_default_action":"accept", "stateless":false, "created_at":"2026-10-13T12:51:31.261806Z", "updated_at":"2026-10-13T12:51:31.261806Z", "default_rules":[{"id":"11111111-2222-4333-8444-000000000001", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"0.0.0.0/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":25, "end":25}, "position":1}, {"id":"11111111-2222-4333-8444-000000000002", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"0.0.0.0/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":465, "end":465}, "position":2}, {"id":"11111111-2222-4333-8444-000000000003", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"0.0.0.0/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":587, "end":587}, "position":3}, {"id":"11111111-2222-4333-8444-000000000004", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"::/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":25, "end":25}, "position":4}, {"id":"11111111-2222-4333-8444-000000000005", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"::/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":465, "end":465}, "position":5}, {"id":"11111111-2222-4333-8444-000000000006", "protocol":"tcp", "direction":"outbound", "action":"drop", "source_ip_range":"::/0", "destination_ip_range":"", "source_ports":{"start":1, "end":65536}, "destination_ports":{"start":587, "end":587}, "position":6}], "rules":[], "zone":"fr-par-1"}' + headers: + Content-Length: + - "2023" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - f1cb1d0a-b3f4-40e7-bc3a-600b41303449 + status: 200 OK + code: 200 + duration: 142.94113ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + form: + page: + - "1" + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/products/servers?page=1 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 43874 + body: '{"servers": {"BASIC2-A12C-24G": {"alt_names": [], "arch": "arm64", "ncpus": 12, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 115.194, "hourly_price": 0.1578, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1200000000, "sum_internet_bandwidth": 1200000000, "interfaces": [{"internal_bandwidth": 1200000000, "internet_bandwidth": 1200000000}]}, "block_bandwidth": 335544320, "end_of_service": false, "sku": "/instance/server/basic2_a12c_24g/fr-par-1"}, "BASIC2-A12C-48G": {"alt_names": [], "arch": "arm64", "ncpus": 12, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 131.911, "hourly_price": 0.1807, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1200000000, "sum_internet_bandwidth": 1200000000, "interfaces": [{"internal_bandwidth": 1200000000, "internet_bandwidth": 1200000000}]}, "block_bandwidth": 335544320, "end_of_service": false, "sku": "/instance/server/basic2_a12c_48g/fr-par-1"}, "BASIC2-A16C-32G": {"alt_names": [], "arch": "arm64", "ncpus": 16, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 150.891, "hourly_price": 0.2067, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1600000000, "sum_internet_bandwidth": 1600000000, "interfaces": [{"internal_bandwidth": 1600000000, "internet_bandwidth": 1600000000}]}, "block_bandwidth": 503316480, "end_of_service": false, "sku": "/instance/server/basic2_a16c_32g/fr-par-1"}, "BASIC2-A16C-64G": {"alt_names": [], "arch": "arm64", "ncpus": 16, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 201.188, "hourly_price": 0.2756, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1600000000, "sum_internet_bandwidth": 1600000000, "interfaces": [{"internal_bandwidth": 1600000000, "internet_bandwidth": 1600000000}]}, "block_bandwidth": 503316480, "end_of_service": false, "sku": "/instance/server/basic2_a16c_64g/fr-par-1"}, "BASIC2-A2C-4G": {"alt_names": [], "arch": "arm64", "ncpus": 2, "ram": 4294967296, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 16.79, "hourly_price": 0.023, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 200000000, "sum_internet_bandwidth": 200000000, "interfaces": [{"internal_bandwidth": 200000000, "internet_bandwidth": 200000000}]}, "block_bandwidth": 83886080, "end_of_service": false, "sku": "/instance/server/basic2_a2c_4g/fr-par-1"}, "BASIC2-A2C-8G": {"alt_names": [], "arch": "arm64", "ncpus": 2, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 25.185, "hourly_price": 0.0345, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 200000000, "sum_internet_bandwidth": 200000000, "interfaces": [{"internal_bandwidth": 200000000, "internet_bandwidth": 200000000}]}, "block_bandwidth": 83886080, "end_of_service": false, "sku": "/instance/server/basic2_a2c_8g/fr-par-1"}, "BASIC2-A4C-16G": {"alt_names": [], "arch": "arm64", "ncpus": 4, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 50.297, "hourly_price": 0.0689, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 125829120, "end_of_service": false, "sku": "/instance/server/basic2_a4c_16g/fr-par-1"}, "BASIC2-A4C-8G": {"alt_names": [], "arch": "arm64", "ncpus": 4, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 37.741, "hourly_price": 0.0517, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 125829120, "end_of_service": false, "sku": "/instance/server/basic2_a4c_8g/fr-par-1"}, "BASIC2-A6C-12G": {"alt_names": [], "arch": "arm64", "ncpus": 6, "ram": 12884901888, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 57.597, "hourly_price": 0.0789, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 600000000, "sum_internet_bandwidth": 600000000, "interfaces": [{"internal_bandwidth": 600000000, "internet_bandwidth": 600000000}]}, "block_bandwidth": 188743680, "end_of_service": false, "sku": "/instance/server/basic2_a6c_12g/fr-par-1"}, "BASIC2-A6C-24G": {"alt_names": [], "arch": "arm64", "ncpus": 6, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 65.919, "hourly_price": 0.0903, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 600000000, "sum_internet_bandwidth": 600000000, "interfaces": [{"internal_bandwidth": 600000000, "internet_bandwidth": 600000000}]}, "block_bandwidth": 188743680, "end_of_service": false, "sku": "/instance/server/basic2_a6c_24g/fr-par-1"}, "BASIC2-A8C-16G": {"alt_names": [], "arch": "arm64", "ncpus": 8, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 75.482, "hourly_price": 0.1034, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 800000000, "sum_internet_bandwidth": 800000000, "interfaces": [{"internal_bandwidth": 800000000, "internet_bandwidth": 800000000}]}, "block_bandwidth": 251658240, "end_of_service": false, "sku": "/instance/server/basic2_a8c_16g/fr-par-1"}, "BASIC2-A8C-32G": {"alt_names": [], "arch": "arm64", "ncpus": 8, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 100.594, "hourly_price": 0.1378, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 800000000, "sum_internet_bandwidth": 800000000, "interfaces": [{"internal_bandwidth": 800000000, "internet_bandwidth": 800000000}]}, "block_bandwidth": 251658240, "end_of_service": false, "sku": "/instance/server/basic2_a8c_32g/fr-par-1"}, "BASIC3-X12C-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 12, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 197.903, "hourly_price": 0.2711, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 2250000000, "sum_internet_bandwidth": 2250000000, "interfaces": [{"internal_bandwidth": 2250000000, "internet_bandwidth": 2250000000}]}, "block_bandwidth": 786432000, "end_of_service": false, "sku": "/instance/server/basic3_x12c_24g/fr-par-1"}, "BASIC3-X12C-48G": {"alt_names": [], "arch": "x86_64", "ncpus": 12, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 226.592, "hourly_price": 0.3104, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 2250000000, "sum_internet_bandwidth": 2250000000, "interfaces": [{"internal_bandwidth": 2250000000, "internet_bandwidth": 2250000000}]}, "block_bandwidth": 786432000, "end_of_service": false, "sku": "/instance/server/basic3_x12c_48g/fr-par-1"}, "BASIC3-X16C-32G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 259.33031, "hourly_price": 0.355247, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3000000000, "sum_internet_bandwidth": 3000000000, "interfaces": [{"internal_bandwidth": 3000000000, "internet_bandwidth": 3000000000}]}, "block_bandwidth": 1048576000, "end_of_service": false, "sku": "/instance/server/basic3_x16c_32g/fr-par-1"}, "BASIC3-X16C-64G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 345.49805, "hourly_price": 0.473285, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3000000000, "sum_internet_bandwidth": 3000000000, "interfaces": [{"internal_bandwidth": 3000000000, "internet_bandwidth": 3000000000}]}, "block_bandwidth": 1048576000, "end_of_service": false, "sku": "/instance/server/basic3_x16c_64g/fr-par-1"}, "BASIC3-X2C-4G": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 4294967296, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 28.79777, "hourly_price": 0.039449, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 350000000, "sum_internet_bandwidth": 350000000, "interfaces": [{"internal_bandwidth": 350000000, "internet_bandwidth": 350000000}]}, "block_bandwidth": 131072000, "end_of_service": false, "sku": "/instance/server/basic3_x2c_4g/fr-par-1"}, "BASIC3-X2C-8G": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 43.23425, "hourly_price": 0.059225, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 350000000, "sum_internet_bandwidth": 350000000, "interfaces": [{"internal_bandwidth": 350000000, "internet_bandwidth": 350000000}]}, "block_bandwidth": 131072000, "end_of_service": false, "sku": "/instance/server/basic3_x2c_8g/fr-par-1"}, "BASIC3-X4C-16G": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 86.4685, "hourly_price": 0.11845, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 700000000, "sum_internet_bandwidth": 700000000, "interfaces": [{"internal_bandwidth": 700000000, "internet_bandwidth": 700000000}]}, "block_bandwidth": 262144000, "end_of_service": false, "sku": "/instance/server/basic3_x4c_16g/fr-par-1"}, "BASIC3-X4C-8G": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 57.67073, "hourly_price": 0.079001, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 700000000, "sum_internet_bandwidth": 700000000, "interfaces": [{"internal_bandwidth": 700000000, "internet_bandwidth": 700000000}]}, "block_bandwidth": 262144000, "end_of_service": false, "sku": "/instance/server/basic3_x4c_8g/fr-par-1"}, "BASIC3-X6C-12G": {"alt_names": [], "arch": "x86_64", "ncpus": 6, "ram": 12884901888, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 98.988, "hourly_price": 0.1356, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1050000000, "sum_internet_bandwidth": 1050000000, "interfaces": [{"internal_bandwidth": 1050000000, "internet_bandwidth": 1050000000}]}, "block_bandwidth": 393216000, "end_of_service": false, "sku": "/instance/server/basic3_x6c_12g/fr-par-1"}, "BASIC3-X6C-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 6, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 113.369, "hourly_price": 0.1553, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1050000000, "sum_internet_bandwidth": 1050000000, "interfaces": [{"internal_bandwidth": 1050000000, "internet_bandwidth": 1050000000}]}, "block_bandwidth": 393216000, "end_of_service": false, "sku": "/instance/server/basic3_x6c_24g/fr-par-1"}, "BASIC3-X8C-16G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 129.70275, "hourly_price": 0.177675, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1500000000, "sum_internet_bandwidth": 1500000000, "interfaces": [{"internal_bandwidth": 1500000000, "internet_bandwidth": 1500000000}]}, "block_bandwidth": 524288000, "end_of_service": false, "sku": "/instance/server/basic3_x8c_16g/fr-par-1"}, "BASIC3-X8C-32G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 172.86181, "hourly_price": 0.236797, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1500000000, "sum_internet_bandwidth": 1500000000, "interfaces": [{"internal_bandwidth": 1500000000, "internet_bandwidth": 1500000000}]}, "block_bandwidth": 524288000, "end_of_service": false, "sku": "/instance/server/basic3_x8c_32g/fr-par-1"}, "COMPUTE3-X12C-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 12, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 240000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 256.317, "hourly_price": 0.3511, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 4000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 4000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/compute3_x12c_24g/fr-par-1"}, "COMPUTE3-X16C-32G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 320000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 341.786, "hourly_price": 0.4682, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 4000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 4000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/compute3_x16c_32g/fr-par-1"}, "COMPUTE3-X24C-48G": {"alt_names": [], "arch": "x86_64", "ncpus": 24, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 480000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 512.3176, "hourly_price": 0.7022, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6000000000, "sum_internet_bandwidth": 6000000000, "interfaces": [{"internal_bandwidth": 6000000000, "internet_bandwidth": 6000000000}]}, "block_bandwidth": 749731840, "end_of_service": false, "sku": "/instance/server/compute3_x24c_48g/fr-par-1"}, "COMPUTE3-X2C-4G": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 4294967296, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 40000000000, "scratch_storage_max_volumes_count": 1, "monthly_price": 42.705, "hourly_price": 0.0585, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 500000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 500000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/compute3_x2c_4g/fr-par-1"}, "COMPUTE3-X32C-64G": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 640000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 683.499, "hourly_price": 0.9363, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 8000000000, "sum_internet_bandwidth": 8000000000, "interfaces": [{"internal_bandwidth": 8000000000, "internet_bandwidth": 8000000000}]}, "block_bandwidth": 1000341504, "end_of_service": false, "sku": "/instance/server/compute3_x32c_64g/fr-par-1"}, "COMPUTE3-X48C-96G": {"alt_names": [], "arch": "x86_64", "ncpus": 48, "ram": 103079215104, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 960000000000, "scratch_storage_max_volumes_count": 8, "monthly_price": 1019.81, "hourly_price": 1.397, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 16000000000, "sum_internet_bandwidth": 16000000000, "interfaces": [{"internal_bandwidth": 16000000000, "internet_bandwidth": 16000000000}]}, "block_bandwidth": 1999634432, "end_of_service": false, "sku": "/instance/server/compute3_x48c_96g/fr-par-1"}, "COMPUTE3-X4C-8G": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 80000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 85.41, "hourly_price": 0.117, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 1000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 1000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/compute3_x4c_8g/fr-par-1"}, "COMPUTE3-X64C-128G": {"alt_names": [], "arch": "x86_64", "ncpus": 64, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 1280000000000, "scratch_storage_max_volumes_count": 8, "monthly_price": 1366.998, "hourly_price": 1.8726, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 16000000000, "sum_internet_bandwidth": 16000000000, "interfaces": [{"internal_bandwidth": 16000000000, "internet_bandwidth": 16000000000}]}, "block_bandwidth": 1999634432, "end_of_service": false, "sku": "/instance/server/compute3_x64c_128g/fr-par-1"}, "COMPUTE3-X6C-12G": {"alt_names": [], "arch": "x86_64", "ncpus": 6, "ram": 12884901888, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 120000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 128.1588, "hourly_price": 0.1756, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 3}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 1500000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 1500000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/compute3_x6c_12g/fr-par-1"}, "COMPUTE3-X8C-16G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 160000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 170.893, "hourly_price": 0.2341, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 2000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 2000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/compute3_x8c_16g/fr-par-1"}, "COMPUTE3-X96C-192G": {"alt_names": [], "arch": "x86_64", "ncpus": 96, "ram": 206158430208, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 1280000000000, "scratch_storage_max_volumes_count": 8, "monthly_price": 2039.62, "hourly_price": 2.794, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 16000000000, "sum_internet_bandwidth": 16000000000, "interfaces": [{"internal_bandwidth": 16000000000, "internet_bandwidth": 16000000000}]}, "block_bandwidth": 1999634432, "end_of_service": false, "sku": "/instance/server/compute3_x96c_192g/fr-par-1"}, "DEV1-L": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 80000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 31.2732, "hourly_price": 0.04284, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 209715200, "end_of_service": false, "sku": "/instance/server/dev1_l/fr-par-1"}, "DEV1-M": {"alt_names": [], "arch": "x86_64", "ncpus": 3, "ram": 4294967296, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 40000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 14.74308, "hourly_price": 0.020196, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 300000000, "sum_internet_bandwidth": 300000000, "interfaces": [{"internal_bandwidth": 300000000, "internet_bandwidth": 300000000}]}, "block_bandwidth": 157286400, "end_of_service": false, "sku": "/instance/server/dev1_m/fr-par-1"}, "STARDUST1-S": {"alt_names": [], "arch": "x86_64", "ncpus": 1, "ram": 1073741824, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 10000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 0.438, "hourly_price": 0.0006, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 100000000, "sum_internet_bandwidth": 100000000, "interfaces": [{"internal_bandwidth": 100000000, "internet_bandwidth": 100000000}]}, "block_bandwidth": 52428800, "end_of_service": false, "sku": "/instance/server/stardust1_s/fr-par-1"}, "DEV1-S": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 2147483648, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 20000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 6.55248, "hourly_price": 0.008976, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 200000000, "sum_internet_bandwidth": 200000000, "interfaces": [{"internal_bandwidth": 200000000, "internet_bandwidth": 200000000}]}, "block_bandwidth": 104857600, "end_of_service": false, "sku": "/instance/server/dev1_s/fr-par-1"}, "DEV1-XL": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 12884901888, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 120000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 47.50548, "hourly_price": 0.065076, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 500000000, "sum_internet_bandwidth": 500000000, "interfaces": [{"internal_bandwidth": 500000000, "internet_bandwidth": 500000000}]}, "block_bandwidth": 262144000, "end_of_service": false, "sku": "/instance/server/dev1_xl/fr-par-1"}, "GP1-L": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 600000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 565.1514, "hourly_price": 0.77418, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 5000000000, "sum_internet_bandwidth": 5000000000, "interfaces": [{"internal_bandwidth": 5000000000, "internet_bandwidth": 5000000000}]}, "block_bandwidth": 1073741824, "end_of_service": false, "sku": "/instance/server/gp1_l/fr-par-1"}, "GP1-M": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 600000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 279.9696, "hourly_price": 0.38352, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1500000000, "sum_internet_bandwidth": 1500000000, "interfaces": [{"internal_bandwidth": 1500000000, "internet_bandwidth": 1500000000}]}, "block_bandwidth": 838860800, "end_of_service": false, "sku": "/instance/server/gp1_m/fr-par-1"}, "GP1-S": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 300000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 139.2402, "hourly_price": 0.19074, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 800000000, "sum_internet_bandwidth": 800000000, "interfaces": [{"internal_bandwidth": 800000000, "internet_bandwidth": 800000000}]}, "block_bandwidth": 524288000, "end_of_service": false, "sku": "/instance/server/gp1_s/fr-par-1"}, "GP1-XL": {"alt_names": [], "arch": "x86_64", "ncpus": 48, "ram": 274877906944, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 600000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1221.8886, "hourly_price": 1.67382, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 10000000000, "sum_internet_bandwidth": 10000000000, "interfaces": [{"internal_bandwidth": 10000000000, "internet_bandwidth": 10000000000}]}, "block_bandwidth": 2147483648, "end_of_service": false, "sku": "/instance/server/gp1_xl/fr-par-1"}, "GP1-XS": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 150000000000}, "per_volume_constraint": {"l_ssd": {"min_size": 1000000000, "max_size": 800000000000}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 67.7586, "hourly_price": 0.09282, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": true, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 500000000, "sum_internet_bandwidth": 500000000, "interfaces": [{"internal_bandwidth": 500000000, "internet_bandwidth": 500000000}]}, "block_bandwidth": 314572800, "end_of_service": false, "sku": "/instance/server/gp1_xs/fr-par-1"}, "L4-1-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 51539607552, "gpu": 1, "gpu_info": {"gpu_manufacturer": "NVIDIA", "gpu_name": "L4", "gpu_memory": 25769803776}, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 574.875, "hourly_price": 0.7875, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 2500000000, "sum_internet_bandwidth": 2500000000, "interfaces": [{"internal_bandwidth": 2500000000, "internet_bandwidth": 2500000000}]}, "block_bandwidth": 1048576000, "end_of_service": false, "sku": "/instance/server/l4_1_24g/fr-par-1"}, "L4-2-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 103079215104, "gpu": 2, "gpu_info": {"gpu_manufacturer": "NVIDIA", "gpu_name": "L4", "gpu_memory": 25769803776}, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1149.75, "hourly_price": 1.575, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 5000000000, "sum_internet_bandwidth": 5000000000, "interfaces": [{"internal_bandwidth": 5000000000, "internet_bandwidth": 5000000000}]}, "block_bandwidth": 1572864000, "end_of_service": false, "sku": "/instance/server/l4_2_24g/fr-par-1"}, "L4-4-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 206158430208, "gpu": 4, "gpu_info": {"gpu_manufacturer": "NVIDIA", "gpu_name": "L4", "gpu_memory": 25769803776}, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 2299.5, "hourly_price": 3.15, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 10000000000, "sum_internet_bandwidth": 10000000000, "interfaces": [{"internal_bandwidth": 10000000000, "internet_bandwidth": 10000000000}]}, "block_bandwidth": 2621440000, "end_of_service": false, "sku": "/instance/server/l4_4_24g/fr-par-1"}, "L4-8-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 64, "ram": 412316860416, "gpu": 8, "gpu_info": {"gpu_manufacturer": "NVIDIA", "gpu_name": "L4", "gpu_memory": 25769803776}, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 4599.0, "hourly_price": 6.3, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 16}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 20000000000, "sum_internet_bandwidth": 20000000000, "interfaces": [{"internal_bandwidth": 20000000000, "internet_bandwidth": 20000000000}]}, "block_bandwidth": 5242880000, "end_of_service": false, "sku": "/instance/server/l4_8_24g/fr-par-1"}, "MEMORY3-X12C-96G": {"alt_names": [], "arch": "x86_64", "ncpus": 12, "ram": 103079215104, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 240000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 496.254, "hourly_price": 0.6798, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 4000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 4000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/memory3_x12c_96g/fr-par-1"}}}' + headers: + Content-Length: + - "43874" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Link: + - ; rel="next",; rel="last" + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 4c22baa3-2dcf-43b5-814a-80f40df97a10 + X-Total-Count: + - "124" + status: 200 OK + code: 200 + duration: 32.319069ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + form: + page: + - "2" + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/products/servers?page=2 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 43363 + body: '{"servers": {"MEMORY3-X16C-128G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 320000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 661.672, "hourly_price": 0.9064, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 4000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 4000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/memory3_x16c_128g/fr-par-1"}, "MEMORY3-X24C-192G": {"alt_names": [], "arch": "x86_64", "ncpus": 24, "ram": 206158430208, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 480000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 992.508, "hourly_price": 1.3596, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 6}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6000000000, "sum_internet_bandwidth": 6000000000, "interfaces": [{"internal_bandwidth": 6000000000, "internet_bandwidth": 6000000000}]}, "block_bandwidth": 749731840, "end_of_service": false, "sku": "/instance/server/memory3_x24c_192g/fr-par-1"}, "MEMORY3-X2C-16G": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 40000000000, "scratch_storage_max_volumes_count": 1, "monthly_price": 82.709, "hourly_price": 0.1133, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 500000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 500000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/memory3_x2c_16g/fr-par-1"}, "MEMORY3-X32C-256G": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 274877906944, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 640000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 1323.344, "hourly_price": 1.8128, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 8000000000, "sum_internet_bandwidth": 8000000000, "interfaces": [{"internal_bandwidth": 8000000000, "internet_bandwidth": 8000000000}]}, "block_bandwidth": 1000341504, "end_of_service": false, "sku": "/instance/server/memory3_x32c_256g/fr-par-1"}, "MEMORY3-X48C-384G": {"alt_names": [], "arch": "x86_64", "ncpus": 48, "ram": 412316860416, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 960000000000, "scratch_storage_max_volumes_count": 8, "monthly_price": 1983.41, "hourly_price": 2.717, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 16000000000, "sum_internet_bandwidth": 16000000000, "interfaces": [{"internal_bandwidth": 16000000000, "internet_bandwidth": 16000000000}]}, "block_bandwidth": 1999634432, "end_of_service": false, "sku": "/instance/server/memory3_x48c_384g/fr-par-1"}, "MEMORY3-X4C-32G": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 80000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 165.418, "hourly_price": 0.2266, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 1000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 1000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/memory3_x4c_32g/fr-par-1"}, "MEMORY3-X6C-48G": {"alt_names": [], "arch": "x86_64", "ncpus": 6, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 120000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 248.127, "hourly_price": 0.3399, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 3}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 1500000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 1500000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/memory3_x6c_48g/fr-par-1"}, "MEMORY3-X8C-64G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 160000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 330.836, "hourly_price": 0.4532, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 2000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 2000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/memory3_x8c_64g/fr-par-1"}, "PLAY2-MICRO": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 40.2084, "hourly_price": 0.05508, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 167772160, "end_of_service": false, "sku": "/instance/server/play2_micro/fr-par-1"}, "PLAY2-NANO": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 4294967296, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 20.1042, "hourly_price": 0.02754, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 200000000, "sum_internet_bandwidth": 200000000, "interfaces": [{"internal_bandwidth": 200000000, "internet_bandwidth": 200000000}]}, "block_bandwidth": 83886080, "end_of_service": false, "sku": "/instance/server/play2_nano/fr-par-1"}, "PLAY2-PICO": {"alt_names": [], "arch": "x86_64", "ncpus": 1, "ram": 2147483648, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 10.4244, "hourly_price": 0.01428, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 100000000, "sum_internet_bandwidth": 100000000, "interfaces": [{"internal_bandwidth": 100000000, "internet_bandwidth": 100000000}]}, "block_bandwidth": 41943040, "end_of_service": false, "sku": "/instance/server/play2_pico/fr-par-1"}, "POP2-12C-48G": {"alt_names": [], "arch": "x86_64", "ncpus": 12, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 317.55, "hourly_price": 0.435, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 3}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 2400000000, "sum_internet_bandwidth": 2400000000, "interfaces": [{"internal_bandwidth": 2400000000, "internet_bandwidth": 2400000000}]}, "block_bandwidth": 2516582400, "end_of_service": false, "sku": "/instance/server/pop2_12c_48g/fr-par-1"}, "POP2-16C-64G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 430.7, "hourly_price": 0.59, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3200000000, "sum_internet_bandwidth": 3200000000, "interfaces": [{"internal_bandwidth": 3200000000, "internet_bandwidth": 3200000000}]}, "block_bandwidth": 3355443200, "end_of_service": false, "sku": "/instance/server/pop2_16c_64g/fr-par-1"}, "POP2-16C-64G-WIN": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1063.391, "hourly_price": 1.4567, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3200000000, "sum_internet_bandwidth": 3200000000, "interfaces": [{"internal_bandwidth": 3200000000, "internet_bandwidth": 3200000000}]}, "block_bandwidth": 3355443200, "end_of_service": false, "sku": "/instance/server/pop2_16c_64g_win/fr-par-1"}, "POP2-24C-96G": {"alt_names": [], "arch": "x86_64", "ncpus": 24, "ram": 103079215104, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 643.05, "hourly_price": 0.885, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 6}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4800000000, "sum_internet_bandwidth": 4800000000, "interfaces": [{"internal_bandwidth": 4800000000, "internet_bandwidth": 4800000000}]}, "block_bandwidth": 3355443200, "end_of_service": false, "sku": "/instance/server/pop2_24c_96g/fr-par-1"}, "POP2-2C-8G": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 53.655, "hourly_price": 0.0735, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 419430400, "end_of_service": false, "sku": "/instance/server/pop2_2c_8g/fr-par-1"}, "POP2-2C-8G-WIN": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 133.079, "hourly_price": 0.1823, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 419430400, "end_of_service": false, "sku": "/instance/server/pop2_2c_8g_win/fr-par-1"}, "POP2-32C-128G": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 861.4, "hourly_price": 1.18, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6400000000, "sum_internet_bandwidth": 6400000000, "interfaces": [{"internal_bandwidth": 6400000000, "internet_bandwidth": 6400000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_32c_128g/fr-par-1"}, "POP2-32C-128G-WIN": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 2126.709, "hourly_price": 2.9133, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6400000000, "sum_internet_bandwidth": 6400000000, "interfaces": [{"internal_bandwidth": 6400000000, "internet_bandwidth": 6400000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_32c_128g_win/fr-par-1"}, "POP2-48C-192G": {"alt_names": [], "arch": "x86_64", "ncpus": 48, "ram": 206158430208, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1292.1, "hourly_price": 1.77, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 12}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 9600000000, "sum_internet_bandwidth": 9600000000, "interfaces": [{"internal_bandwidth": 9600000000, "internet_bandwidth": 9600000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_48c_192g/fr-par-1"}, "POP2-4C-16G": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 107.31, "hourly_price": 0.147, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 800000000, "sum_internet_bandwidth": 800000000, "interfaces": [{"internal_bandwidth": 800000000, "internet_bandwidth": 800000000}]}, "block_bandwidth": 838860800, "end_of_service": false, "sku": "/instance/server/pop2_4c_16g/fr-par-1"}, "POP2-4C-16G-WIN": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 265.501, "hourly_price": 0.3637, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 800000000, "sum_internet_bandwidth": 800000000, "interfaces": [{"internal_bandwidth": 800000000, "internet_bandwidth": 800000000}]}, "block_bandwidth": 838860800, "end_of_service": false, "sku": "/instance/server/pop2_4c_16g_win/fr-par-1"}, "POP2-64C-256G": {"alt_names": [], "arch": "x86_64", "ncpus": 64, "ram": 274877906944, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1715.5, "hourly_price": 2.35, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 16}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 12800000000, "sum_internet_bandwidth": 12800000000, "interfaces": [{"internal_bandwidth": 12800000000, "internet_bandwidth": 12800000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_64c_256g/fr-par-1"}, "POP2-6C-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 6, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 160.965, "hourly_price": 0.225, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1200000000, "sum_internet_bandwidth": 1200000000, "interfaces": [{"internal_bandwidth": 1200000000, "internet_bandwidth": 1200000000}]}, "block_bandwidth": 1258291200, "end_of_service": false, "sku": "/instance/server/pop2_6c_24g/fr-par-1"}, "POP2-8C-32G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 211.7, "hourly_price": 0.29, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1600000000, "sum_internet_bandwidth": 1600000000, "interfaces": [{"internal_bandwidth": 1600000000, "internet_bandwidth": 1600000000}]}, "block_bandwidth": 1677721600, "end_of_service": false, "sku": "/instance/server/pop2_8c_32g/fr-par-1"}, "POP2-8C-32G-WIN": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 528.009, "hourly_price": 0.7233, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1600000000, "sum_internet_bandwidth": 1600000000, "interfaces": [{"internal_bandwidth": 1600000000, "internet_bandwidth": 1600000000}]}, "block_bandwidth": 1677721600, "end_of_service": false, "sku": "/instance/server/pop2_8c_32g_win/fr-par-1"}, "POP2-HC-12C-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 12, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 233.016, "hourly_price": 0.3192, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 3}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 2400000000, "sum_internet_bandwidth": 2400000000, "interfaces": [{"internal_bandwidth": 2400000000, "internet_bandwidth": 2400000000}]}, "block_bandwidth": 2516582400, "end_of_service": false, "sku": "/instance/server/pop2_hc_12c_24g/fr-par-1"}, "POP2-HC-16C-32G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 310.688, "hourly_price": 0.4256, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3200000000, "sum_internet_bandwidth": 3200000000, "interfaces": [{"internal_bandwidth": 3200000000, "internet_bandwidth": 3200000000}]}, "block_bandwidth": 3355443200, "end_of_service": false, "sku": "/instance/server/pop2_hc_16c_32g/fr-par-1"}, "POP2-HC-24C-48G": {"alt_names": [], "arch": "x86_64", "ncpus": 24, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 466.032, "hourly_price": 0.6384, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 6}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4800000000, "sum_internet_bandwidth": 4800000000, "interfaces": [{"internal_bandwidth": 4800000000, "internet_bandwidth": 4800000000}]}, "block_bandwidth": 3355443200, "end_of_service": false, "sku": "/instance/server/pop2_hc_24c_48g/fr-par-1"}, "POP2-HC-2C-4G": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 4294967296, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 38.836, "hourly_price": 0.0532, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 419430400, "end_of_service": false, "sku": "/instance/server/pop2_hc_2c_4g/fr-par-1"}, "POP2-HC-32C-64G": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 621.376, "hourly_price": 0.8512, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6400000000, "sum_internet_bandwidth": 6400000000, "interfaces": [{"internal_bandwidth": 6400000000, "internet_bandwidth": 6400000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_hc_32c_64g/fr-par-1"}, "POP2-HC-48C-96G": {"alt_names": [], "arch": "x86_64", "ncpus": 48, "ram": 103079215104, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 927.1, "hourly_price": 1.27, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 12}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 9600000000, "sum_internet_bandwidth": 9600000000, "interfaces": [{"internal_bandwidth": 9600000000, "internet_bandwidth": 9600000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_hc_48c_96g/fr-par-1"}, "POP2-HC-4C-8G": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 77.672, "hourly_price": 0.1064, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 800000000, "sum_internet_bandwidth": 800000000, "interfaces": [{"internal_bandwidth": 800000000, "internet_bandwidth": 800000000}]}, "block_bandwidth": 838860800, "end_of_service": false, "sku": "/instance/server/pop2_hc_4c_8g/fr-par-1"}, "POP2-HC-64C-128G": {"alt_names": [], "arch": "x86_64", "ncpus": 64, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1242.752, "hourly_price": 1.7024, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 16}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 12800000000, "sum_internet_bandwidth": 12800000000, "interfaces": [{"internal_bandwidth": 12800000000, "internet_bandwidth": 12800000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_hc_64c_128g/fr-par-1"}, "POP2-HC-6C-12G": {"alt_names": [], "arch": "x86_64", "ncpus": 6, "ram": 12884901888, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 116.508, "hourly_price": 0.1596, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1200000000, "sum_internet_bandwidth": 1200000000, "interfaces": [{"internal_bandwidth": 1200000000, "internet_bandwidth": 1200000000}]}, "block_bandwidth": 1258291200, "end_of_service": false, "sku": "/instance/server/pop2_hc_6c_12g/fr-par-1"}, "POP2-HC-8C-16G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 155.344, "hourly_price": 0.2128, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1600000000, "sum_internet_bandwidth": 1600000000, "interfaces": [{"internal_bandwidth": 1600000000, "internet_bandwidth": 1600000000}]}, "block_bandwidth": 1677721600, "end_of_service": false, "sku": "/instance/server/pop2_hc_8c_16g/fr-par-1"}, "POP2-HM-12C-96G": {"alt_names": [], "arch": "x86_64", "ncpus": 12, "ram": 103079215104, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 451.14, "hourly_price": 0.618, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 3}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 2400000000, "sum_internet_bandwidth": 2400000000, "interfaces": [{"internal_bandwidth": 2400000000, "internet_bandwidth": 2400000000}]}, "block_bandwidth": 2516582400, "end_of_service": false, "sku": "/instance/server/pop2_hm_12c_96g/fr-par-1"}, "POP2-HM-16C-128G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 601.52, "hourly_price": 0.824, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3200000000, "sum_internet_bandwidth": 3200000000, "interfaces": [{"internal_bandwidth": 3200000000, "internet_bandwidth": 3200000000}]}, "block_bandwidth": 3355443200, "end_of_service": false, "sku": "/instance/server/pop2_hm_16c_128g/fr-par-1"}, "POP2-HM-24C-192G": {"alt_names": [], "arch": "x86_64", "ncpus": 24, "ram": 206158430208, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 902.28, "hourly_price": 1.236, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 6}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4800000000, "sum_internet_bandwidth": 4800000000, "interfaces": [{"internal_bandwidth": 4800000000, "internet_bandwidth": 4800000000}]}, "block_bandwidth": 3355443200, "end_of_service": false, "sku": "/instance/server/pop2_hm_24c_192g/fr-par-1"}, "POP2-HM-2C-16G": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 75.19, "hourly_price": 0.103, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 419430400, "end_of_service": false, "sku": "/instance/server/pop2_hm_2c_16g/fr-par-1"}, "POP2-HM-32C-256G": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 274877906944, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1203.04, "hourly_price": 1.648, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6400000000, "sum_internet_bandwidth": 6400000000, "interfaces": [{"internal_bandwidth": 6400000000, "internet_bandwidth": 6400000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_hm_32c_256g/fr-par-1"}, "POP2-HM-48C-384G": {"alt_names": [], "arch": "x86_64", "ncpus": 48, "ram": 412316860416, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1803.1, "hourly_price": 2.47, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 12}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 9600000000, "sum_internet_bandwidth": 9600000000, "interfaces": [{"internal_bandwidth": 9600000000, "internet_bandwidth": 9600000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_hm_48c_384g/fr-par-1"}, "POP2-HM-4C-32G": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 150.38, "hourly_price": 0.206, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 800000000, "sum_internet_bandwidth": 800000000, "interfaces": [{"internal_bandwidth": 800000000, "internet_bandwidth": 800000000}]}, "block_bandwidth": 838860800, "end_of_service": false, "sku": "/instance/server/pop2_hm_4c_32g/fr-par-1"}, "POP2-HM-64C-512G": {"alt_names": [], "arch": "x86_64", "ncpus": 64, "ram": 549755813888, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 2406.08, "hourly_price": 3.296, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 16}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 12800000000, "sum_internet_bandwidth": 12800000000, "interfaces": [{"internal_bandwidth": 12800000000, "internet_bandwidth": 12800000000}]}, "block_bandwidth": 5905580032, "end_of_service": false, "sku": "/instance/server/pop2_hm_64c_512g/fr-par-1"}, "POP2-HM-6C-48G": {"alt_names": [], "arch": "x86_64", "ncpus": 6, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 225.57, "hourly_price": 0.309, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1200000000, "sum_internet_bandwidth": 1200000000, "interfaces": [{"internal_bandwidth": 1200000000, "internet_bandwidth": 1200000000}]}, "block_bandwidth": 1258291200, "end_of_service": false, "sku": "/instance/server/pop2_hm_6c_48g/fr-par-1"}, "POP2-HM-8C-64G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 300.76, "hourly_price": 0.412, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1600000000, "sum_internet_bandwidth": 1600000000, "interfaces": [{"internal_bandwidth": 1600000000, "internet_bandwidth": 1600000000}]}, "block_bandwidth": 1677721600, "end_of_service": false, "sku": "/instance/server/pop2_hm_8c_64g/fr-par-1"}, "POP2-HN-10": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 530.272, "hourly_price": 0.7264, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 10000000000, "sum_internet_bandwidth": 10000000000, "interfaces": [{"internal_bandwidth": 10000000000, "internet_bandwidth": 10000000000}]}, "block_bandwidth": 838860800, "end_of_service": false, "sku": "/instance/server/pop2_hn_10/fr-par-1"}, "POP2-HN-3": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 4294967296, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 186.442, "hourly_price": 0.2554, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3000000000, "sum_internet_bandwidth": 3000000000, "interfaces": [{"internal_bandwidth": 3000000000, "internet_bandwidth": 3000000000}]}, "block_bandwidth": 419430400, "end_of_service": false, "sku": "/instance/server/pop2_hn_3/fr-par-1"}, "POP2-HN-5": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 330.252, "hourly_price": 0.4524, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 5000000000, "sum_internet_bandwidth": 5000000000, "interfaces": [{"internal_bandwidth": 5000000000, "internet_bandwidth": 5000000000}]}, "block_bandwidth": 838860800, "end_of_service": false, "sku": "/instance/server/pop2_hn_5/fr-par-1"}, "PRO2-L": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 653.0142, "hourly_price": 0.89454, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6000000000, "sum_internet_bandwidth": 6000000000, "interfaces": [{"internal_bandwidth": 6000000000, "internet_bandwidth": 6000000000}]}, "block_bandwidth": 2097152000, "end_of_service": false, "sku": "/instance/server/pro2_l/fr-par-1"}}}' + headers: + Content-Length: + - "43363" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Link: + - ; rel="first",; rel="previous",; rel="next",; rel="last" + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "47" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - dba007e3-6132-47c4-90fa-f19599b001e5 + X-Total-Count: + - "124" + status: 200 OK + code: 200 + duration: 31.062968ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + form: + page: + - "3" + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/products/servers?page=3 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 21007 + body: '{"servers": {"PRO2-M": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 326.1348, "hourly_price": 0.44676, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3000000000, "sum_internet_bandwidth": 3000000000, "interfaces": [{"internal_bandwidth": 3000000000, "internet_bandwidth": 3000000000}]}, "block_bandwidth": 1048576000, "end_of_service": false, "sku": "/instance/server/pro2_m/fr-par-1"}, "PRO2-S": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 163.0674, "hourly_price": 0.22338, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1500000000, "sum_internet_bandwidth": 1500000000, "interfaces": [{"internal_bandwidth": 1500000000, "internet_bandwidth": 1500000000}]}, "block_bandwidth": 524288000, "end_of_service": false, "sku": "/instance/server/pro2_s/fr-par-1"}, "PRO2-XS": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 81.906, "hourly_price": 0.1122, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 700000000, "sum_internet_bandwidth": 700000000, "interfaces": [{"internal_bandwidth": 700000000, "internet_bandwidth": 700000000}]}, "block_bandwidth": 262144000, "end_of_service": false, "sku": "/instance/server/pro2_xs/fr-par-1"}, "PRO2-XXS": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 40.953, "hourly_price": 0.0561, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 0}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 350000000, "sum_internet_bandwidth": 350000000, "interfaces": [{"internal_bandwidth": 350000000, "internet_bandwidth": 350000000}]}, "block_bandwidth": 131072000, "end_of_service": false, "sku": "/instance/server/pro2_xxs/fr-par-1"}, "STANDARD2-A12C-48G": {"alt_names": [], "arch": "arm64", "ncpus": 12, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 223.964, "hourly_price": 0.3068, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 2400000000, "sum_internet_bandwidth": 2400000000, "interfaces": [{"internal_bandwidth": 2400000000, "internet_bandwidth": 2400000000}]}, "block_bandwidth": 2516582400, "end_of_service": false, "sku": "/instance/server/standard2_a12c_48g/fr-par-1"}, "STANDARD2-A16C-64G": {"alt_names": [], "arch": "arm64", "ncpus": 16, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 367.847, "hourly_price": 0.5039, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 3200000000, "sum_internet_bandwidth": 3200000000, "interfaces": [{"internal_bandwidth": 3200000000, "internet_bandwidth": 3200000000}]}, "block_bandwidth": 3355443200, "end_of_service": false, "sku": "/instance/server/standard2_a16c_64g/fr-par-1"}, "STANDARD2-A24C-96G": {"alt_names": [], "arch": "arm64", "ncpus": 24, "ram": 103079215104, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 478.223, "hourly_price": 0.6551, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 6}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4800000000, "sum_internet_bandwidth": 4800000000, "interfaces": [{"internal_bandwidth": 4800000000, "internet_bandwidth": 4800000000}]}, "block_bandwidth": 5033164800, "end_of_service": false, "sku": "/instance/server/standard2_a24c_96g/fr-par-1"}, "STANDARD2-A2C-8G": {"alt_names": [], "arch": "arm64", "ncpus": 2, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 42.778, "hourly_price": 0.0586, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 400000000, "sum_internet_bandwidth": 400000000, "interfaces": [{"internal_bandwidth": 400000000, "internet_bandwidth": 400000000}]}, "block_bandwidth": 419430400, "end_of_service": false, "sku": "/instance/server/standard2_a2c_8g/fr-par-1"}, "STANDARD2-A32C-128G": {"alt_names": [], "arch": "arm64", "ncpus": 32, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 874.394, "hourly_price": 1.1978, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6400000000, "sum_internet_bandwidth": 6400000000, "interfaces": [{"internal_bandwidth": 6400000000, "internet_bandwidth": 6400000000}]}, "block_bandwidth": 5033164800, "end_of_service": false, "sku": "/instance/server/standard2_a32c_128g/fr-par-1"}, "STANDARD2-A48C-192G": {"alt_names": [], "arch": "arm64", "ncpus": 48, "ram": 206158430208, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1103.541, "hourly_price": 1.5117, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 9600000000, "sum_internet_bandwidth": 9600000000, "interfaces": [{"internal_bandwidth": 9600000000, "internet_bandwidth": 9600000000}]}, "block_bandwidth": 5033164800, "end_of_service": false, "sku": "/instance/server/standard2_a48c_192g/fr-par-1"}, "STANDARD2-A4C-16G": {"alt_names": [], "arch": "arm64", "ncpus": 4, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 85.483, "hourly_price": 0.1171, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 800000000, "sum_internet_bandwidth": 800000000, "interfaces": [{"internal_bandwidth": 800000000, "internet_bandwidth": 800000000}]}, "block_bandwidth": 838860800, "end_of_service": false, "sku": "/instance/server/standard2_a4c_16g/fr-par-1"}, "STANDARD2-A64C-256G": {"alt_names": [], "arch": "arm64", "ncpus": 64, "ram": 274877906944, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 1470.366, "hourly_price": 2.0142, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 12800000000, "sum_internet_bandwidth": 12800000000, "interfaces": [{"internal_bandwidth": 12800000000, "internet_bandwidth": 12800000000}]}, "block_bandwidth": 5033164800, "end_of_service": false, "sku": "/instance/server/standard2_a64c_256g/fr-par-1"}, "STANDARD2-A6C-24G": {"alt_names": [], "arch": "arm64", "ncpus": 6, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 111.909, "hourly_price": 0.1533, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 3}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1200000000, "sum_internet_bandwidth": 1200000000, "interfaces": [{"internal_bandwidth": 1200000000, "internet_bandwidth": 1200000000}]}, "block_bandwidth": 1258291200, "end_of_service": false, "sku": "/instance/server/standard2_a6c_24g/fr-par-1"}, "STANDARD2-A8C-32G": {"alt_names": [], "arch": "arm64", "ncpus": 8, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 0, "scratch_storage_max_volumes_count": 0, "monthly_price": 171.039, "hourly_price": 0.2343, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 1600000000, "sum_internet_bandwidth": 1600000000, "interfaces": [{"internal_bandwidth": 1600000000, "internet_bandwidth": 1600000000}]}, "block_bandwidth": 1677721600, "end_of_service": false, "sku": "/instance/server/standard2_a8c_32g/fr-par-1"}, "STANDARD3-X12C-48G": {"alt_names": [], "arch": "x86_64", "ncpus": 12, "ram": 51539607552, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 240000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 337.698, "hourly_price": 0.4626, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 4000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 4000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/standard3_x12c_48g/fr-par-1"}, "STANDARD3-X16C-64G": {"alt_names": [], "arch": "x86_64", "ncpus": 16, "ram": 68719476736, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 320000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 473.77, "hourly_price": 0.649, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 4000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 4000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/standard3_x16c_64g/fr-par-1"}, "STANDARD3-X24C-96G": {"alt_names": [], "arch": "x86_64", "ncpus": 24, "ram": 103079215104, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 480000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 687.003, "hourly_price": 0.9411, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 6}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 6000000000, "sum_internet_bandwidth": 6000000000, "interfaces": [{"internal_bandwidth": 6000000000, "internet_bandwidth": 6000000000}]}, "block_bandwidth": 749731840, "end_of_service": false, "sku": "/instance/server/standard3_x24c_96g/fr-par-1"}, "STANDARD3-X2C-8G": {"alt_names": [], "arch": "x86_64", "ncpus": 2, "ram": 8589934592, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 40000000000, "scratch_storage_max_volumes_count": 1, "monthly_price": 59.057, "hourly_price": 0.0809, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 1}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 500000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 500000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/standard3_x2c_8g/fr-par-1"}, "STANDARD3-X32C-128G": {"alt_names": [], "arch": "x86_64", "ncpus": 32, "ram": 137438953472, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 640000000000, "scratch_storage_max_volumes_count": 4, "monthly_price": 947.54, "hourly_price": 1.298, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 8000000000, "sum_internet_bandwidth": 8000000000, "interfaces": [{"internal_bandwidth": 8000000000, "internet_bandwidth": 8000000000}]}, "block_bandwidth": 1000341504, "end_of_service": false, "sku": "/instance/server/standard3_x32c_128g/fr-par-1"}, "STANDARD3-X48C-192G": {"alt_names": [], "arch": "x86_64", "ncpus": 48, "ram": 206158430208, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 960000000000, "scratch_storage_max_volumes_count": 8, "monthly_price": 1421.31, "hourly_price": 1.947, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 16000000000, "sum_internet_bandwidth": 16000000000, "interfaces": [{"internal_bandwidth": 16000000000, "internet_bandwidth": 16000000000}]}, "block_bandwidth": 1999634432, "end_of_service": false, "sku": "/instance/server/standard3_x48c_192g/fr-par-1"}, "STANDARD3-X4C-16G": {"alt_names": [], "arch": "x86_64", "ncpus": 4, "ram": 17179869184, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 80000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 118.041, "hourly_price": 0.1617, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 2}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 1000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 1000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/standard3_x4c_16g/fr-par-1"}, "STANDARD3-X64C-256G": {"alt_names": [], "arch": "x86_64", "ncpus": 64, "ram": 274877906944, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 1280000000000, "scratch_storage_max_volumes_count": 8, "monthly_price": 1887.05, "hourly_price": 2.585, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 8}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 16000000000, "sum_internet_bandwidth": 16000000000, "interfaces": [{"internal_bandwidth": 16000000000, "internet_bandwidth": 16000000000}]}, "block_bandwidth": 1999634432, "end_of_service": false, "sku": "/instance/server/standard3_x64c_256g/fr-par-1"}, "STANDARD3-X6C-24G": {"alt_names": [], "arch": "x86_64", "ncpus": 6, "ram": 25769803776, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 120000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 177.185, "hourly_price": 0.2425, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 3}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 1500000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 1500000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/standard3_x6c_24g/fr-par-1"}, "STANDARD3-X8C-32G": {"alt_names": [], "arch": "x86_64", "ncpus": 8, "ram": 34359738368, "gpu": 0, "gpu_info": null, "mig_profile": null, "volumes_constraint": {"min_size": 0, "max_size": 0}, "per_volume_constraint": {"l_ssd": {"min_size": 0, "max_size": 0}}, "scratch_storage_max_size": 160000000000, "scratch_storage_max_volumes_count": 2, "monthly_price": 232.87, "hourly_price": 0.319, "capabilities": {"boot_types": ["local", "rescue"], "placement_groups": true, "block_storage": true, "hot_snapshots_local_volume": false, "private_network": 8, "max_file_systems": 4}, "network": {"ipv6_support": true, "sum_internal_bandwidth": 4000000000, "sum_internet_bandwidth": 2000000000, "interfaces": [{"internal_bandwidth": 4000000000, "internet_bandwidth": 2000000000}]}, "block_bandwidth": 500170752, "end_of_service": false, "sku": "/instance/server/standard3_x8c_32g/fr-par-1"}}}' + headers: + Content-Length: + - "21007" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Link: + - ; rel="first",; rel="previous",; rel="last" + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "46" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 9c58bb4b-c8fa-4e2f-9535-9918032deb47 + X-Total-Count: + - "124" + status: 200 OK + code: 200 + duration: 32.528593ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + form: + image_label: + - ubuntu_jammy + order_by: + - type_asc + type: + - instance_sbs + zone: + - fr-par-1 + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/marketplace/v2/local-images?image_label=ubuntu_jammy&order_by=type_asc&type=instance_sbs&zone=fr-par-1 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2850 + body: '{"local_images":[{"id":"8a5729a3-94fc-4a95-93bd-2c00bfd8344b", "arch":"x86_64", "zone":"fr-par-1", "compatible_commercial_types":["DEV1-L", "DEV1-M", "DEV1-S", "DEV1-XL", "GP1-L", "GP1-M", "GP1-S", "GP1-XL", "GP1-XS", "START1-L", "START1-M", "START1-S", "START1-XS", "VC1L", "VC1M", "VC1S", "X64-120GB", "X64-15GB", "X64-30GB", "X64-60GB", "PRO2-XXS", "PRO2-XS", "PRO2-S", "PRO2-M", "PRO2-L", "STARDUST1-S", "PLAY2-MICRO", "PLAY2-NANO", "PLAY2-PICO", "POP2-2C-8G", "POP2-4C-16G", "POP2-8C-32G", "POP2-16C-64G", "POP2-32C-128G", "POP2-48C-192G", "POP2-64C-256G", "POP2-HM-2C-16G", "POP2-HM-4C-32G", "POP2-HM-8C-64G", "POP2-HM-16C-128G", "POP2-HM-32C-256G", "POP2-HM-48C-384G", "POP2-HM-64C-512G", "POP2-HC-2C-4G", "POP2-HC-4C-8G", "POP2-HC-8C-16G", "POP2-HC-16C-32G", "POP2-HC-32C-64G", "POP2-HC-48C-96G", "POP2-HC-64C-128G", "POP2-HN-3", "POP2-HN-5", "POP2-HN-10", "POP2-6C-24G", "POP2-12C-48G", "POP2-24C-96G", "POP2-HM-6C-48G", "POP2-HM-12C-96G", "POP2-HM-24C-192G", "POP2-HC-6C-12G", "POP2-HC-12C-24G", "POP2-HC-24C-48G", "BASIC1-X1C-2G", "BASIC1-X2C-2G", "BASIC1-X2C-4G", "BASIC1-X2C-8G", "BASIC1-X4C-8G", "BASIC1-X4C-16G", "BASIC1-X6C-12G", "BASIC1-X6C-48G", "BASIC1-X8C-16G", "BASIC1-X8C-32G", "BASIC1-X12C-24G", "BASIC1-X12C-48G", "BASIC1-X16C-32G", "BASIC1-X16C-64G", "BASIC3-X2C-4G", "BASIC3-X2C-8G", "BASIC3-X4C-8G", "BASIC3-X4C-16G", "BASIC3-X8C-16G", "BASIC3-X8C-32G", "BASIC3-X16C-32G", "BASIC3-X16C-64G", "BASIC3-X6C-12G", "BASIC3-X6C-24G", "BASIC3-X12C-24G", "BASIC3-X12C-48G", "STANDARD3-X2C-8G", "STANDARD3-X4C-16G", "STANDARD3-X8C-32G", "STANDARD3-X16C-64G", "STANDARD3-X32C-128G", "STANDARD3-X48C-192G", "STANDARD3-X64C-256G", "STANDARD3-X6C-24G", "STANDARD3-X12C-48G", "STANDARD3-X24C-96G", "MEMORY3-X2C-16G", "MEMORY3-X4C-32G", "MEMORY3-X8C-64G", "MEMORY3-X16C-128G", "MEMORY3-X32C-256G", "MEMORY3-X48C-384G", "MEMORY3-X6C-48G", "MEMORY3-X12C-96G", "MEMORY3-X24C-192G", "COMPUTE3-X2C-4G", "COMPUTE3-X4C-8G", "COMPUTE3-X8C-16G", "COMPUTE3-X16C-32G", "COMPUTE3-X32C-64G", "COMPUTE3-X48C-96G", "COMPUTE3-X64C-128G", "COMPUTE3-X6C-12G", "COMPUTE3-X12C-24G", "COMPUTE3-X24C-48G", "COMPUTE3-X96C-192G"], "label":"ubuntu_jammy", "type":"instance_sbs"}, {"id":"e417327b-c427-40b6-908f-bc416609eaff", "arch":"arm64", "zone":"fr-par-1", "compatible_commercial_types":["COPARM1-2C-8G", "COPARM1-4C-16G", "COPARM1-8C-32G", "COPARM1-16C-64G", "COPARM1-32C-128G", "BASIC2-A2C-4G", "BASIC2-A2C-8G", "BASIC2-A4C-8G", "BASIC2-A4C-16G", "BASIC2-A8C-16G", "BASIC2-A8C-32G", "BASIC2-A16C-32G", "BASIC2-A16C-64G", "BASIC2-A6C-12G", "BASIC2-A6C-24G", "BASIC2-A12C-24G", "BASIC2-A12C-48G", "STANDARD2-A6C-24G", "STANDARD2-A12C-48G", "STANDARD2-A2C-8G", "STANDARD2-A4C-16G", "STANDARD2-A8C-32G", "STANDARD2-A16C-64G", "STANDARD2-A32C-128G", "STANDARD2-A48C-192G", "STANDARD2-A64C-256G"], "label":"ubuntu_jammy", "type":"instance_sbs"}], "total_count":2}' + headers: + Content-Length: + - "2850" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 13045ca5-7dd6-4788-97a3-62bcd5001c7b + status: 200 OK + code: 200 + duration: 61.327844ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/images/8a5729a3-94fc-4a95-93bd-2c00bfd8344b + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 587 + body: '{"image": {"id": "8a5729a3-94fc-4a95-93bd-2c00bfd8344b", "name": "Ubuntu 22.04 Jammy Jellyfish", "organization": "51b656e3-4865-41e8-adbc-0c45bdd780db", "project": "51b656e3-4865-41e8-adbc-0c45bdd780db", "root_volume": {"volume_type": "sbs_snapshot", "id": "ae4ddd7b-dc23-448b-b033-5a9b30c7e31b", "size": 0, "name": ""}, "extra_volumes": {}, "public": true, "arch": "x86_64", "creation_date": "2026-10-06T06:58:13.768602+00:00", "modification_date": "2026-10-06T06:58:13.768602+00:00", "default_bootscript": null, "from_server": "", "state": "available", "tags": [], "zone": "fr-par-1"}}' + headers: + Content-Length: + - "587" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 580a8657-6e1b-41a8-b02d-c5c8ffca6cce + status: 200 OK + code: 200 + duration: 46.305448ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 287 + host: api.scaleway.com + body: '{"name":"cli-srv-awesome-chandrasekhar","dynamic_ip_required":false,"commercial_type":"DEV1-S","image":"8a5729a3-94fc-4a95-93bd-2c00bfd8344b","enable_ipv6":false,"boot_type":"local","project":"fa1e3217-dc80-42ac-85c3-3f034b78b552","security_group":"5080afc5-b32a-44bf-95e3-30530f32850a"}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 1826 + body: '{"server": {"id": "ea4291ae-506a-40b0-87a8-671926c7c232", "name": "cli-srv-awesome-chandrasekhar", "arch": "x86_64", "commercial_type": "DEV1-S", "boot_type": "local", "organization": "fa1e3217-dc80-42ac-85c3-3f034b78b552", "project": "fa1e3217-dc80-42ac-85c3-3f034b78b552", "hostname": "cli-srv-awesome-chandrasekhar", "image": {"id": "8a5729a3-94fc-4a95-93bd-2c00bfd8344b", "name": "Ubuntu 22.04 Jammy Jellyfish", "organization": "51b656e3-4865-41e8-adbc-0c45bdd780db", "project": "51b656e3-4865-41e8-adbc-0c45bdd780db", "root_volume": {"volume_type": "sbs_snapshot", "id": "ae4ddd7b-dc23-448b-b033-5a9b30c7e31b", "size": 0, "name": ""}, "extra_volumes": {}, "public": true, "arch": "x86_64", "creation_date": "2026-10-06T06:58:13.768602+00:00", "modification_date": "2026-10-06T06:58:13.768602+00:00", "default_bootscript": null, "from_server": "", "state": "available", "tags": [], "zone": "fr-par-1"}, "volumes": {"0": {"boot": false, "volume_type": "sbs_volume", "id": "576b56fc-dadf-45f3-a1d5-51b9c549fcaa", "state": "available", "zone": "fr-par-1"}}, "tags": [], "state": "stopped", "protected": false, "state_detail": "", "public_ip": null, "public_ips": [], "mac_address": "de:00:00:2d:0e:3e", "routed_ip_enabled": true, "ipv6": null, "extra_networks": [], "dynamic_ip_required": false, "enable_ipv6": false, "private_ip": null, "creation_date": "2026-10-13T12:51:31.555613+00:00", "modification_date": "2026-10-13T12:51:31.555613+00:00", "bootscript": null, "security_group": {"id": "5080afc5-b32a-44bf-95e3-30530f32850a", "name": "cli-sg-dreamy-moser"}, "location": null, "maintenances": [], "allowed_actions": ["poweron", "backup"], "placement_group": null, "private_nics": [], "zone": "fr-par-1", "filesystems": [], "end_of_service": false, "dns": "ea4291ae-506a-40b0-87a8-671926c7c232.pub.instances.scw.cloud"}}' + headers: + Content-Length: + - "1826" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:31 GMT + Location: + - https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ea4291ae-506a-40b0-87a8-671926c7c232 + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "47" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - a8fbff20-2e66-4663-b844-d9b17fbf0d8b + status: 201 Created + code: 201 + duration: 417.238729ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ea4291ae-506a-40b0-87a8-671926c7c232 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 1826 + body: '{"server": {"id": "ea4291ae-506a-40b0-87a8-671926c7c232", "name": "cli-srv-awesome-chandrasekhar", "arch": "x86_64", "commercial_type": "DEV1-S", "boot_type": "local", "organization": "fa1e3217-dc80-42ac-85c3-3f034b78b552", "project": "fa1e3217-dc80-42ac-85c3-3f034b78b552", "hostname": "cli-srv-awesome-chandrasekhar", "image": {"id": "8a5729a3-94fc-4a95-93bd-2c00bfd8344b", "name": "Ubuntu 22.04 Jammy Jellyfish", "organization": "51b656e3-4865-41e8-adbc-0c45bdd780db", "project": "51b656e3-4865-41e8-adbc-0c45bdd780db", "root_volume": {"volume_type": "sbs_snapshot", "id": "ae4ddd7b-dc23-448b-b033-5a9b30c7e31b", "size": 0, "name": ""}, "extra_volumes": {}, "public": true, "arch": "x86_64", "creation_date": "2026-10-06T06:58:13.768602+00:00", "modification_date": "2026-10-06T06:58:13.768602+00:00", "default_bootscript": null, "from_server": "", "state": "available", "tags": [], "zone": "fr-par-1"}, "volumes": {"0": {"boot": false, "volume_type": "sbs_volume", "id": "576b56fc-dadf-45f3-a1d5-51b9c549fcaa", "state": "available", "zone": "fr-par-1"}}, "tags": [], "state": "stopped", "protected": false, "state_detail": "", "public_ip": null, "public_ips": [], "mac_address": "de:00:00:2d:0e:3e", "routed_ip_enabled": true, "ipv6": null, "extra_networks": [], "dynamic_ip_required": false, "enable_ipv6": false, "private_ip": null, "creation_date": "2026-10-13T12:51:31.555613+00:00", "modification_date": "2026-10-13T12:51:31.555613+00:00", "bootscript": null, "security_group": {"id": "5080afc5-b32a-44bf-95e3-30530f32850a", "name": "cli-sg-dreamy-moser"}, "location": null, "maintenances": [], "allowed_actions": ["poweron", "backup"], "placement_group": null, "private_nics": [], "zone": "fr-par-1", "filesystems": [], "end_of_service": false, "dns": "ea4291ae-506a-40b0-87a8-671926c7c232.pub.instances.scw.cloud"}}' + headers: + Content-Length: + - "1826" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:32 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "46" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - ba7a9577-165a-473c-85a9-c7ad0ad878a4 + status: 200 OK + code: 200 + duration: 87.323824ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 64 + host: api.scaleway.com + body: '{"security_group":{"id":"c5260a58-af26-4fe9-9a69-c44b3e31bda1"}}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ea4291ae-506a-40b0-87a8-671926c7c232 + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 1828 + body: '{"server": {"id": "ea4291ae-506a-40b0-87a8-671926c7c232", "name": "cli-srv-awesome-chandrasekhar", "arch": "x86_64", "commercial_type": "DEV1-S", "boot_type": "local", "organization": "fa1e3217-dc80-42ac-85c3-3f034b78b552", "project": "fa1e3217-dc80-42ac-85c3-3f034b78b552", "hostname": "cli-srv-awesome-chandrasekhar", "image": {"id": "8a5729a3-94fc-4a95-93bd-2c00bfd8344b", "name": "Ubuntu 22.04 Jammy Jellyfish", "organization": "51b656e3-4865-41e8-adbc-0c45bdd780db", "project": "51b656e3-4865-41e8-adbc-0c45bdd780db", "root_volume": {"volume_type": "sbs_snapshot", "id": "ae4ddd7b-dc23-448b-b033-5a9b30c7e31b", "size": 0, "name": ""}, "extra_volumes": {}, "public": true, "arch": "x86_64", "creation_date": "2026-10-06T06:58:13.768602+00:00", "modification_date": "2026-10-06T06:58:13.768602+00:00", "default_bootscript": null, "from_server": "", "state": "available", "tags": [], "zone": "fr-par-1"}, "volumes": {"0": {"boot": false, "volume_type": "sbs_volume", "id": "576b56fc-dadf-45f3-a1d5-51b9c549fcaa", "state": "available", "zone": "fr-par-1"}}, "tags": [], "state": "stopped", "protected": false, "state_detail": "", "public_ip": null, "public_ips": [], "mac_address": "de:00:00:2d:0e:3e", "routed_ip_enabled": true, "ipv6": null, "extra_networks": [], "dynamic_ip_required": false, "enable_ipv6": false, "private_ip": null, "creation_date": "2026-10-13T12:51:31.555613+00:00", "modification_date": "2026-10-13T12:51:32.116488+00:00", "bootscript": null, "security_group": {"id": "c5260a58-af26-4fe9-9a69-c44b3e31bda1", "name": "cli-sg-admiring-bassi"}, "location": null, "maintenances": [], "allowed_actions": ["poweron", "backup"], "placement_group": null, "private_nics": [], "zone": "fr-par-1", "filesystems": [], "end_of_service": false, "dns": "ea4291ae-506a-40b0-87a8-671926c7c232.pub.instances.scw.cloud"}}' + headers: + Content-Length: + - "1828" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:32 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "45" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - d431f355-c3f7-43e7-9b07-ddbaca32b57e + status: 200 OK + code: 200 + duration: 373.541254ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ea4291ae-506a-40b0-87a8-671926c7c232 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 1914 + body: '{"server": {"id": "ea4291ae-506a-40b0-87a8-671926c7c232", "name": "cli-srv-awesome-chandrasekhar", "arch": "x86_64", "commercial_type": "DEV1-S", "boot_type": "local", "organization": "fa1e3217-dc80-42ac-85c3-3f034b78b552", "project": "fa1e3217-dc80-42ac-85c3-3f034b78b552", "hostname": "cli-srv-awesome-chandrasekhar", "image": {"id": "8a5729a3-94fc-4a95-93bd-2c00bfd8344b", "name": "Ubuntu 22.04 Jammy Jellyfish", "organization": "51b656e3-4865-41e8-adbc-0c45bdd780db", "project": "51b656e3-4865-41e8-adbc-0c45bdd780db", "root_volume": {"volume_type": "sbs_snapshot", "id": "ae4ddd7b-dc23-448b-b033-5a9b30c7e31b", "size": 0, "name": ""}, "extra_volumes": {}, "public": true, "arch": "x86_64", "creation_date": "2026-10-06T06:58:13.768602+00:00", "modification_date": "2026-10-06T06:58:13.768602+00:00", "default_bootscript": null, "from_server": "", "state": "available", "tags": [], "zone": "fr-par-1"}, "volumes": {"0": {"boot": false, "volume_type": "sbs_volume", "id": "576b56fc-dadf-45f3-a1d5-51b9c549fcaa", "state": "available", "zone": "fr-par-1"}}, "tags": [], "state": "stopped", "protected": false, "state_detail": "", "public_ip": null, "public_ips": [], "mac_address": "de:00:00:2d:0e:3e", "routed_ip_enabled": true, "ipv6": null, "extra_networks": [], "dynamic_ip_required": false, "enable_ipv6": false, "private_ip": null, "creation_date": "2026-10-13T12:51:31.555613+00:00", "modification_date": "2026-10-13T12:51:32.116488+00:00", "bootscript": null, "security_group": {"id": "c5260a58-af26-4fe9-9a69-c44b3e31bda1", "name": "cli-sg-admiring-bassi"}, "location": null, "maintenances": [], "allowed_actions": ["poweron", "backup"], "placement_group": null, "private_nics": [], "zone": "fr-par-1", "filesystems": [], "end_of_service": false, "dns": "ea4291ae-506a-40b0-87a8-671926c7c232.pub.instances.scw.cloud", "admin_password_encryption_ssh_key_id": null, "admin_password_encrypted_value": null}}' + headers: + Content-Length: + - "1914" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:32 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 876940cd-f05e-48a9-8657-0f75aacc3aee + status: 200 OK + code: 200 + duration: 89.045501ms + - id: 12 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v1/zones/fr-par-1/servers/ea4291ae-506a-40b0-87a8-671926c7c232 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:32 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 1b07d45a-977f-44cd-b2d4-3d31f4bd4a2e + status: 204 No Content + code: 204 + duration: 283.578148ms + - id: 13 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/block/v1alpha1/zones/fr-par-1/volumes/576b56fc-dadf-45f3-a1d5-51b9c549fcaa + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 498 + body: '{"id":"576b56fc-dadf-45f3-a1d5-51b9c549fcaa", "name":"Ubuntu 22.04 Jammy Jellyfish_sbs_volume_0", "type":"sbs_5k", "size":10000000000, "project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552", "created_at":"2026-10-13T12:51:31.738234Z", "updated_at":"2026-10-13T12:51:32.633654Z", "references":[], "parent_snapshot_id":"ae4ddd7b-dc23-448b-b033-5a9b30c7e31b", "status":"available", "tags":[], "specs":{"perf_iops":5000, "class":"sbs"}, "last_detached_at":"2026-10-13T12:51:32.633654Z", "zone":"fr-par-1"}' + headers: + Content-Length: + - "498" + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:32 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 15e771a4-2422-4980-a4b6-eda5011d480d + status: 200 OK + code: 200 + duration: 48.134707ms + - id: 14 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/block/v1alpha1/zones/fr-par-1/volumes/576b56fc-dadf-45f3-a1d5-51b9c549fcaa + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:32 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - c58fd070-db6e-45c0-b7b1-0b72124ecd14 + status: 204 No Content + code: 204 + duration: 79.589571ms + - id: 15 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/5080afc5-b32a-44bf-95e3-30530f32850a + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:33 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 7a2e82ba-45b7-4c99-b1d5-b17570c151d2 + status: 204 No Content + code: 204 + duration: 132.298689ms + - id: 16 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/c5260a58-af26-4fe9-9a69-c44b3e31bda1 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Tue, 13 Oct 2026 12:51:33 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "47" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 6d6d61a6-bd84-4932-96cd-f6679406df30 + status: 204 No Content + code: 204 + duration: 116.006345ms diff --git a/internal/namespaces/instance/v2alpha1/custom.go b/internal/namespaces/instance/v2alpha1/custom.go index ada6d1e6e3..c4e3b16f1b 100644 --- a/internal/namespaces/instance/v2alpha1/custom.go +++ b/internal/namespaces/instance/v2alpha1/custom.go @@ -17,6 +17,7 @@ func GetCommands() *core.Commands { cmds := core.NewCommands( instancePlacementGroup(), instancePrivateNetworkInterface(), + instanceSecurityGroup(), instanceServerType(), instanceTemplate(), instancePlacementGroupList(), @@ -29,6 +30,15 @@ func GetCommands() *core.Commands { instancePrivateNetworkInterfaceGet(), instancePrivateNetworkInterfaceUpdate(), instancePrivateNetworkInterfaceDelete(), + instanceSecurityGroupList(), + instanceSecurityGroupCreate(), + instanceSecurityGroupGet(), + instanceSecurityGroupUpdate(), + instanceSecurityGroupDelete(), + instanceSecurityGroupAddRules(), + instanceSecurityGroupSetRules(), + instanceSecurityGroupUpdateRule(), + instanceSecurityGroupDeleteRules(), instanceServerGetCompatibleTypes(), instanceServerTypeList(), instanceTemplateList(), @@ -73,6 +83,37 @@ func GetCommands() *core.Commands { cmds.MustFind("instance", "private-network-interface", "delete"). Override(privateNetworkInterfaceDeleteBuilder) + // + // Security Group + // + human.RegisterMarshalerFunc(instanceSDK.SecurityGroup{}, securityGroupMarshalerFunc) + human.RegisterMarshalerFunc([]*instanceSDK.SecurityGroupRule{}, securityGroupRulesMarshalerFunc) + human.RegisterMarshalerFunc( + instanceSDK.SecurityGroupRulePortRange{}, + securityGroupRulePortRangeMarshalerFunc, + ) + human.RegisterMarshalerFunc( + instanceSDK.SecurityGroupAction(""), + human.EnumMarshalFunc(securityGroupActionMarshalSpecs), + ) + human.RegisterMarshalerFunc( + instanceSDK.SecurityGroupRuleAction(""), + human.EnumMarshalFunc(securityGroupRuleActionMarshalSpecs), + ) + + cmds.MustFind("instance", "security-group", "create").Override(securityGroupCreateBuilder) + cmds.MustFind("instance", "security-group", "get").Override(securityGroupGetBuilder) + cmds.MustFind("instance", "security-group", "list").Override(securityGroupListBuilder) + cmds.MustFind("instance", "security-group", "update").Override(securityGroupUpdateBuilder) + cmds.MustFind("instance", "security-group", "delete").Override(securityGroupDeleteBuilder) + cmds.MustFind("instance", "security-group", "add-rules").Override(securityGroupAddRulesBuilder) + cmds.MustFind("instance", "security-group", "set-rules").Override(securityGroupSetRulesBuilder) + + cmds.Merge(core.NewCommands( + securityGroupClearCommand(), + securityGroupEditCommand(), + )) + // // Server-Type // diff --git a/internal/namespaces/instance/v2alpha1/custom_placement_group_test.go b/internal/namespaces/instance/v2alpha1/custom_placement_group_test.go index 88643da13e..104ffe0b9b 100644 --- a/internal/namespaces/instance/v2alpha1/custom_placement_group_test.go +++ b/internal/namespaces/instance/v2alpha1/custom_placement_group_test.go @@ -14,11 +14,9 @@ func Test_PlacementGroup_Get(t *testing.T) { cmds := instance.GetCommands() t.Run("Without servers", core.Test(&core.TestConfig{ - BeforeFunc: core.BeforeFuncCombine( - core.ExecStoreBeforeCmd( - "PlacementGroup", - "scw instance placement-group create", - ), + BeforeFunc: core.ExecStoreBeforeCmd( + "PlacementGroup", + "scw instance placement-group create", ), Commands: cmds, Cmd: "scw instance placement-group get {{ .PlacementGroup.ID }}", @@ -26,10 +24,8 @@ func Test_PlacementGroup_Get(t *testing.T) { core.TestCheckExitCode(0), core.TestCheckGolden(), ), - AfterFunc: core.AfterFuncCombine( - core.ExecAfterCmd( - "scw instance placement-group delete {{ .PlacementGroup.ID }}", - ), + AfterFunc: core.ExecAfterCmd( + "scw instance placement-group delete {{ .PlacementGroup.ID }}", ), })) @@ -87,11 +83,9 @@ func Test_PlacementGroup_List(t *testing.T) { func Test_PlacementGroup_Update(t *testing.T) { t.Run("simple", core.Test(&core.TestConfig{ - BeforeFunc: core.BeforeFuncCombine( - core.ExecStoreBeforeCmd( - "PlacementGroup", - "scw instance placement-group create policy-type=max_availability tags.0=test", - ), + BeforeFunc: core.ExecStoreBeforeCmd( + "PlacementGroup", + "scw instance placement-group create policy-type=max_availability tags.0=test", ), Commands: instance.GetCommands(), Cmd: "scw instance placement-group update {{ .PlacementGroup.ID }} name=cli-test-pg-update" + @@ -109,10 +103,8 @@ func Test_PlacementGroup_Update(t *testing.T) { core.TestCheckExitCode(0), core.TestCheckGolden(), ), - AfterFunc: core.AfterFuncCombine( - core.ExecAfterCmd( - "scw instance placement-group delete {{ .PlacementGroup.ID }}", - ), + AfterFunc: core.ExecAfterCmd( + "scw instance placement-group delete {{ .PlacementGroup.ID }}", ), })) } diff --git a/internal/namespaces/instance/v2alpha1/custom_security_group.go b/internal/namespaces/instance/v2alpha1/custom_security_group.go new file mode 100644 index 0000000000..5f5861e9b9 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/custom_security_group.go @@ -0,0 +1,541 @@ +package instance + +import ( + "context" + "fmt" + "reflect" + "strconv" + "strings" + + "github.com/fatih/color" + "github.com/scaleway/scaleway-cli/v2/core" + "github.com/scaleway/scaleway-cli/v2/core/human" + "github.com/scaleway/scaleway-cli/v2/internal/editor" + instance "github.com/scaleway/scaleway-sdk-go/api/instance/v2alpha1" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +const ( + SecurityGroupRulePortMin = 1 + SecurityGroupRulePortMax = 65536 +) + +// +// Marshalers +// + +var ( + securityGroupActionMarshalSpecs = human.EnumMarshalSpecs{ + instance.SecurityGroupActionDrop: &human.EnumMarshalSpec{Attribute: color.FgRed}, + instance.SecurityGroupActionAccept: &human.EnumMarshalSpec{Attribute: color.FgGreen}, + } + + securityGroupRuleActionMarshalSpecs = human.EnumMarshalSpecs{ + instance.SecurityGroupRuleActionDrop: &human.EnumMarshalSpec{Attribute: color.FgRed}, + instance.SecurityGroupRuleActionAccept: &human.EnumMarshalSpec{Attribute: color.FgGreen}, + } +) + +func securityGroupMarshalerFunc(i any, opt *human.MarshalOpt) (string, error) { + type tmpSecurityGroup instance.SecurityGroup + securityGroup := tmpSecurityGroup(i.(instance.SecurityGroup)) + + // Sections + opt.Sections = []*human.MarshalSection{ + { + FieldName: "Tags", + Title: "Tags", + HideIfEmpty: true, + }, + { + FieldName: "Rules", + Title: "Rules", + }, + { + FieldName: "DefaultRules", + Title: "Default Rules", + }, + } + + str, err := human.Marshal(securityGroup, opt) + if err != nil { + return "", err + } + + return str, nil +} + +func securityGroupRulesMarshalerFunc(i any, opt *human.MarshalOpt) (string, error) { + type tmpSecurityGroupRules []*instance.SecurityGroupRule + securityGroupRules := tmpSecurityGroupRules(i.([]*instance.SecurityGroupRule)) + + opt.Fields = []*human.MarshalFieldOpt{ + { + Label: "ID", + FieldName: "ID", + }, + { + Label: "PROTOCOL", + FieldName: "Protocol", + }, + { + Label: "DIRECTION", + FieldName: "Direction", + }, + { + Label: "ACTION", + FieldName: "Action", + }, + { + Label: "SOURCE IP RANGE", + FieldName: "SourceIPRange", + }, + { + Label: "SOURCE PORTS", + FieldName: "SourcePorts", + }, + { + Label: "DEST IP RANGE", + FieldName: "DestinationIPRange", + }, + { + Label: "DEST PORTS", + FieldName: "DestinationPorts", + }, + } + + str, err := human.Marshal(securityGroupRules, opt) + if err != nil { + return "", err + } + + return str, nil +} + +func securityGroupRulePortRangeMarshalerFunc(i any, opt *human.MarshalOpt) (string, error) { + type tmpSecurityGroupRulePortRange instance.SecurityGroupRulePortRange + securityGroupRulePortRange := tmpSecurityGroupRulePortRange( + i.(instance.SecurityGroupRulePortRange), + ) + + humanReadablePortRange := fmt.Sprintf( + "%d-%d", + securityGroupRulePortRange.Start, + securityGroupRulePortRange.End, + ) + + if securityGroupRulePortRange.Start == SecurityGroupRulePortMin && + securityGroupRulePortRange.End == SecurityGroupRulePortMax { + humanReadablePortRange = "ALL" + } + + if securityGroupRulePortRange.Start == securityGroupRulePortRange.End { + humanReadablePortRange = strconv.Itoa(int(securityGroupRulePortRange.Start)) + } + + str, err := human.Marshal(humanReadablePortRange, opt) + if err != nil { + return "", err + } + + return str, nil +} + +// +// Builders +// + +func securityGroupCreateBuilder(c *core.Command) *core.Command { + c.ArgSpecs.GetByName("name").Required = true + c.ArgSpecs.GetByName("name").Default = core.RandomValueGenerator("sg") + c.ArgSpecs.GetByName("inbound-default-action").Default = core.DefaultValueSetter( + instance.SecurityGroupActionAccept.String(), + ) + c.ArgSpecs.GetByName("outbound-default-action").Default = core.DefaultValueSetter( + instance.SecurityGroupActionAccept.String(), + ) + c.ArgSpecs.GetByName("stateless").Default = core.DefaultValueSetter("false") + c.ArgSpecs.GetByName("disable-default-rules").Default = core.DefaultValueSetter("false") + + examples := []*core.Example{ + { + Short: "Create a security group with a specified name and description", + Raw: `scw instance security-group create name=foobar description="foobar foobar"`, + }, + { + Short: "Create a security group that will be applied as default on all Instances of this Project", + Raw: `scw instance security-group create project-default=true`, + }, + { + Short: "Create a security group that will have a default drop inbound policy (traffic your Instance receives)", + Raw: "scw instance security-group create inbound-default-action=drop", + }, + { + Short: "Create a security group that will have a default drop outbound policy (traffic your Instance transmits)", + Raw: "scw instance security-group create outbound-default-action=drop", + }, + { + Short: "Create a stateless security group", + Raw: "scw instance security-group create stateless=true", + }, + } + + c.Examples = append(c.Examples, examples...) + + return c +} + +func securityGroupGetBuilder(c *core.Command) *core.Command { + c.ArgSpecs.GetByName("security-group-id").Positional = true + + c.Examples = append(c.Examples, &core.Example{ + Short: "Get a security group with the specified ID", + Raw: "scw instance security-group get 11111111-1111-1111-1111-111111111111", + }) + + return c +} + +func securityGroupUpdateBuilder(c *core.Command) *core.Command { + c.ArgSpecs.GetByName("security-group-id").Positional = true + + return c +} + +func securityGroupDeleteBuilder(c *core.Command) *core.Command { + c.ArgSpecs.GetByName("security-group-id").Positional = true + + c.Examples = append(c.Examples, &core.Example{ + Short: "Delete the security group with the specified ID", + Raw: "scw instance security-group delete 11111111-1111-1111-1111-111111111111", + }) + + return c +} + +func securityGroupListBuilder(c *core.Command) *core.Command { + c.Interceptor = func(ctx context.Context, argsI any, runner core.CommandRunner) (i any, err error) { + rawResp, err := runner(ctx, argsI) + if err != nil { + return rawResp, err + } + + sgList, ok := rawResp.(*instance.ListSecurityGroupsResponse) + if !ok { + return rawResp, fmt.Errorf( + "expected response of type *instance.ListSecurityGroupsResponse, got %T", + rawResp, + ) + } + + return sgList.SecurityGroups, nil + } + + c.View = &core.View{ + Fields: []*core.ViewField{ + { + Label: "ID", + FieldName: "ID", + }, + { + Label: "NAME", + FieldName: "Name", + }, + { + Label: "DESCRIPTION", + FieldName: "Description", + }, + { + Label: "TAGS", + FieldName: "Tags", + }, + { + Label: "INBOUND DEF. ACT.", + FieldName: "InboundDefaultAction", + }, + { + Label: "OUTBOUND DEF. ACT.", + FieldName: "OutboundDefaultAction", + }, + { + Label: "STATELESS", + FieldName: "Stateless", + }, + { + Label: "PROJECT DEFAULT", + FieldName: "ProjectDefault", + }, + { + Label: "PROJECT ID", + FieldName: "ProjectID", + }, + { + Label: "ZONE", + FieldName: "Zone", + }, + { + Label: "CREATED AT", + FieldName: "CreatedAt", + }, + { + Label: "UPDATED AT", + FieldName: "UpdatedAt", + }, + }, + } + + c.Examples = append(c.Examples, &core.Example{ + Short: "List all security groups that match the specified name", + Raw: "scw instance security-group list name=foobar", + }) + + return c +} + +func securityGroupAddRulesBuilder(c *core.Command) *core.Command { + c.ArgSpecs.GetByName("security-group-id").Positional = true + c.ArgSpecs.GetByName("security-group-id").Required = true + c.ArgSpecs.GetByName("security-group-rules.{index}.protocol").Name = "rules.{index}.protocol" + c.ArgSpecs.GetByName("security-group-rules.{index}.direction").Name = "rules.{index}.direction" + c.ArgSpecs.GetByName("security-group-rules.{index}.action").Name = "rules.{index}.action" + c.ArgSpecs.GetByName("security-group-rules.{index}.source-ip-range").Name = "rules.{index}.source-ip-range" + c.ArgSpecs.GetByName("security-group-rules.{index}.destination-ip-range").Name = "rules.{index}.destination-ip-range" + c.ArgSpecs.GetByName("security-group-rules.{index}.source-ports.start").Name = "rules.{index}.source-ports.start" + c.ArgSpecs.GetByName("security-group-rules.{index}.source-ports.end").Name = "rules.{index}.source-ports.end" + c.ArgSpecs.GetByName("security-group-rules.{index}.destination-ports.start").Name = "rules.{index}.destination-ports.start" + c.ArgSpecs.GetByName("security-group-rules.{index}.destination-ports.end").Name = "rules.{index}.destination-ports.end" + c.ArgSpecs.GetByName("security-group-rules.{index}.position").Name = "rules.{index}.position" + + type customSecurityGroupAddRulesRequest struct { + instance.AddSecurityGroupRulesRequest + Rules []*instance.SecurityGroupRuleConfig + } + + c.ArgsType = reflect.TypeFor[customSecurityGroupAddRulesRequest]() + + c.Interceptor = func(ctx context.Context, argsI any, runner core.CommandRunner) (any, error) { + args := argsI.(*customSecurityGroupAddRulesRequest) + req := args.AddSecurityGroupRulesRequest + req.SecurityGroupRules = args.Rules + + resp, err := runner(ctx, &req) + if err != nil { + return nil, err + } + + return resp.(*instance.AddSecurityGroupRulesResponse).SecurityGroup, nil + } + + return c +} + +func securityGroupSetRulesBuilder(c *core.Command) *core.Command { + c.ArgSpecs.GetByName("security-group-id").Positional = true + c.ArgSpecs.GetByName("security-group-id").Required = true + c.ArgSpecs.GetByName("security-group-rules.{index}.protocol").Name = "rules.{index}.protocol" + c.ArgSpecs.GetByName("security-group-rules.{index}.direction").Name = "rules.{index}.direction" + c.ArgSpecs.GetByName("security-group-rules.{index}.action").Name = "rules.{index}.action" + c.ArgSpecs.GetByName("security-group-rules.{index}.source-ip-range").Name = "rules.{index}.source-ip-range" + c.ArgSpecs.GetByName("security-group-rules.{index}.destination-ip-range").Name = "rules.{index}.destination-ip-range" + c.ArgSpecs.GetByName("security-group-rules.{index}.source-ports.start").Name = "rules.{index}.source-ports.start" + c.ArgSpecs.GetByName("security-group-rules.{index}.source-ports.end").Name = "rules.{index}.source-ports.end" + c.ArgSpecs.GetByName("security-group-rules.{index}.destination-ports.start").Name = "rules.{index}.destination-ports.start" + c.ArgSpecs.GetByName("security-group-rules.{index}.destination-ports.end").Name = "rules.{index}.destination-ports.end" + c.ArgSpecs.GetByName("security-group-rules.{index}.position").Name = "rules.{index}.position" + + type customSecurityGroupSetRulesRequest struct { + instance.SetSecurityGroupRulesRequest + Rules []*instance.SecurityGroupRuleConfig + } + + c.ArgsType = reflect.TypeFor[customSecurityGroupSetRulesRequest]() + + c.Interceptor = func(ctx context.Context, argsI any, runner core.CommandRunner) (any, error) { + args := argsI.(*customSecurityGroupSetRulesRequest) + req := args.SetSecurityGroupRulesRequest + req.SecurityGroupRules = args.Rules + + return runner(ctx, &req) + } + + return c +} + +// +// Commands +// + +type instanceResetSecurityGroupArgs struct { + Zone scw.Zone + SecurityGroupID string +} + +func securityGroupClearCommand() *core.Command { + return &core.Command{ + Short: `Remove all rules of a security group`, + Namespace: "instance", + Resource: "security-group", + Verb: "clear", + ArgsType: reflect.TypeFor[instanceResetSecurityGroupArgs](), + Examples: []*core.Example{ + { + Short: "Remove all rules of the given security group", + ArgsJSON: `{"security_group_id": "11111111-1111-1111-1111-111111111111"}`, + }, + }, + Run: func(ctx context.Context, argsI any) (i any, e error) { + args := argsI.(*instanceResetSecurityGroupArgs) + + client := core.ExtractClient(ctx) + api := instance.NewAPI(client) + + _, err := api.SetSecurityGroupRules(&instance.SetSecurityGroupRulesRequest{ + Zone: args.Zone, + SecurityGroupID: args.SecurityGroupID, + SecurityGroupRules: []*instance.SecurityGroupRuleConfig{}, + }, scw.WithContext(ctx)) + if err != nil { + return nil, err + } + + return &core.SuccessResult{Message: "Successful reset of the security group rules"}, err + }, + ArgSpecs: core.ArgSpecs{ + { + Name: "security-group-id", + Short: `ID of the security group to reset.`, + Required: true, + Positional: true, + }, + core.ZoneArgSpec((*instance.API)(nil).Zones()...), + }, + } +} + +var instanceSecurityGroupEditYamlExample = `security_group_rules: +- action: drop + destination_ports: + start: 1200 + end: 1300 + direction: inbound + source_ip_range: 192.168.0.0/24 + protocol: TCP +- action: drop + direction: inbound + protocol: ICMP + source_ip_range: 0.0.0.0/0 +- action: accept + destination_ports: + start: 25565 + direction: outbound + source_ip_range: 0.0.0.0/0 + protocol: UDP +` + +type instanceSecurityGroupEditArgs struct { + Zone scw.Zone + SecurityGroupID string + Mode editor.MarshalMode +} + +func securityGroupEditCommand() *core.Command { + return &core.Command{ + Short: `Edit all rules of a security group`, + Long: editor.LongDescription, + Namespace: "instance", + Resource: "security-group", + Verb: "edit", + ArgsType: reflect.TypeFor[instanceSecurityGroupEditArgs](), + ArgSpecs: core.ArgSpecs{ + { + Name: "security-group-id", + Short: `ID of the security group to reset.`, + Required: true, + Positional: true, + }, + editor.MarshalModeArgSpec(), + core.ZoneArgSpec((*instance.API)(nil).Zones()...), + }, + Run: func(ctx context.Context, argsI any) (i any, e error) { + args := argsI.(*instanceSecurityGroupEditArgs) + + client := core.ExtractClient(ctx) + api := instance.NewAPI(client) + + sg, err := api.GetSecurityGroup(&instance.GetSecurityGroupRequest{ + Zone: args.Zone, + SecurityGroupID: args.SecurityGroupID, + }, scw.WithContext(ctx)) + if err != nil { + return nil, fmt.Errorf("failed to get security group: %w", err) + } + + // Build resource with matching field names for editor + type securityGroupRulesResource struct { + SecurityGroupRules []*instance.SecurityGroupRule + } + resource := &securityGroupRulesResource{ + SecurityGroupRules: sg.Rules, + } + + setRequest := &instance.SetSecurityGroupRulesRequest{ + Zone: args.Zone, + SecurityGroupID: args.SecurityGroupID, + } + + editedSetRequest, err := editor.UpdateResourceEditor( + resource, + setRequest, + &editor.Config{ + PutRequest: true, + MarshalMode: args.Mode, + Template: instanceSecurityGroupEditYamlExample, + IgnoreFields: []string{"security_group_id", "zone", "id", "position"}, + }, + ) + if err != nil { + return nil, err + } + + setRequest = editedSetRequest.(*instance.SetSecurityGroupRulesRequest) + + // Preserve path parameters that were filtered out by IgnoreFields + setRequest.Zone = args.Zone + setRequest.SecurityGroupID = args.SecurityGroupID + + for _, rule := range setRequest.SecurityGroupRules { + rule.Protocol = instance.SecurityGroupRuleProtocol( + strings.ToLower(rule.Protocol.String()), + ) + + removePortRangeDefaultValues(rule.SourcePorts) + removePortRangeDefaultValues(rule.DestinationPorts) + } + + resp, err := api.SetSecurityGroupRules(setRequest, scw.WithContext(ctx)) + if err != nil { + return nil, err + } + + return resp.Rules, nil + }, + } +} + +// removePortRangeDefaultValues makes sure the ports are not 1-65536, which: +// - are the default values returned from the API +// - mean "no ports specified" +// - are not accepted back by the API +func removePortRangeDefaultValues(ports *instance.SecurityGroupRulePortRange) { + if ports == nil || ports.End != SecurityGroupRulePortMax { + return + } + + if ports.Start == SecurityGroupRulePortMin { + // Case 1-65536, return empty ports + *ports = instance.SecurityGroupRulePortRange{} + } else { + // Start is OK, it's a single port (not a range) + ports.End = ports.Start + } +} diff --git a/internal/namespaces/instance/v2alpha1/custom_security_group_test.go b/internal/namespaces/instance/v2alpha1/custom_security_group_test.go new file mode 100644 index 0000000000..1b1055d8ba --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/custom_security_group_test.go @@ -0,0 +1,276 @@ +package instance_test + +import ( + "testing" + + "github.com/scaleway/scaleway-cli/v2/core" + "github.com/scaleway/scaleway-cli/v2/internal/namespaces/instance/v2alpha1" + "github.com/scaleway/scaleway-cli/v2/internal/testhelpers" + instanceSDK "github.com/scaleway/scaleway-sdk-go/api/instance/v2alpha1" + "github.com/scaleway/scaleway-sdk-go/scw" + "github.com/stretchr/testify/assert" +) + +func Test_SecurityGroup(t *testing.T) { + t.Run("Create", core.Test(&core.TestConfig{ + Commands: instance.GetCommands(), + Cmd: "scw instance security-group create name=cli-test-sg-create outbound-default-action=drop " + + "stateless=true tags.0=cli-test tags.1=instance-sg tags.2=create description=\"Add desc here.\"", + Check: core.TestCheckCombine( + func(t *testing.T, ctx *core.CheckFuncCtx) { + t.Helper() + + res := ctx.Result.(*instanceSDK.SecurityGroup) + assert.Equal(t, "cli-test-sg-create", res.Name) + assert.Equal(t, "drop", res.OutboundDefaultAction.String()) + assert.Equal(t, "accept", res.InboundDefaultAction.String()) + assert.True(t, res.Stateless) + assert.Equal(t, "cli-test", res.Tags[0]) + assert.Equal(t, "instance-sg", res.Tags[1]) + assert.Equal(t, "create", res.Tags[2]) + assert.Equal(t, "Add desc here.", res.Description) + }, + core.TestCheckGolden(), + core.TestCheckExitCode(0), + ), + AfterFunc: instance.DeleteSecurityGroup("CmdResult"), + })) + + t.Run("List", core.Test(&core.TestConfig{ + Commands: instance.GetCommands(), + BeforeFunc: core.BeforeFuncCombine( + core.ExecStoreBeforeCmd("SG0", "scw instance security-group create tags.0=foo "), + core.ExecStoreBeforeCmd("SG1", "scw instance security-group create"), + core.ExecStoreBeforeCmd("SG2", "scw instance security-group create name=named-sg "+ + "inbound-default-action=drop outbound-default-action=drop stateless=true tags.0=foo"), + core.ExecStoreBeforeCmd( + "SG3", + "scw instance security-group create tags.0=foo tags.1=bar "+ + "inbound-default-action=drop description=\"Descriptive text.\"", + ), + ), + Cmd: "scw instance security-group list tags.0=foo", + Check: core.TestCheckCombine( + func(t *testing.T, ctx *core.CheckFuncCtx) { + t.Helper() + + res := ctx.Result.([]*instanceSDK.SecurityGroupSummary) + assert.Len(t, res, 3) + }, + core.TestCheckGolden(), + core.TestCheckExitCode(0), + ), + AfterFunc: core.AfterFuncCombine( + core.ExecAfterCmd("scw instance security-group delete {{ .SG0.ID }}"), + core.ExecAfterCmd("scw instance security-group delete {{ .SG1.ID }}"), + core.ExecAfterCmd("scw instance security-group delete {{ .SG2.ID }}"), + core.ExecAfterCmd("scw instance security-group delete {{ .SG3.ID }}"), + ), + })) + + t.Run("Update", core.Test(&core.TestConfig{ + Commands: instance.GetCommands(), + BeforeFunc: core.ExecStoreBeforeCmd("SecurityGroup", "scw instance security-group create "+ + "outbound-default-action=drop tags.0=cli-test tags.1=instance-sg tags.2=update description=tmp disable-default-rules=true"), + Cmd: "scw instance security-group update {{ .SecurityGroup.ID }} name=cli-test-sg-update stateless=true " + + "outbound-default-action=accept inbound-default-action=drop disable-default-rules=false " + + "tags.0=cli-test tags.1=instance-sg tags.2=update description=updated", + Check: core.TestCheckCombine( + func(t *testing.T, ctx *core.CheckFuncCtx) { + t.Helper() + + res := ctx.Result.(*instanceSDK.SecurityGroup) + assert.Equal(t, "cli-test-sg-update", res.Name) + assert.True(t, res.Stateless) + assert.Equal(t, "accept", res.OutboundDefaultAction.String()) + assert.Equal(t, "drop", res.InboundDefaultAction.String()) + assert.False(t, res.DisableDefaultRules) + assert.Len(t, res.DefaultRules, 6) + assert.Equal(t, "cli-test", res.Tags[0]) + assert.Equal(t, "instance-sg", res.Tags[1]) + assert.Equal(t, "update", res.Tags[2]) + assert.Equal(t, "updated", res.Description) + }, + core.TestCheckGolden(), + core.TestCheckExitCode(0), + ), + AfterFunc: instance.DeleteSecurityGroup("SecurityGroup"), + })) + + t.Run("AddRules", core.Test(&core.TestConfig{ + Commands: instance.GetCommands(), + BeforeFunc: instance.CreateSecurityGroup("SecurityGroup"), + Cmd: "scw instance security-group add-rules {{ .SecurityGroup.ID }} " + + "rules.0.protocol=any rules.0.direction=inbound rules.0.action=accept rules.0.source-ip-range=1.1.1.1/32 " + + "rules.1.protocol=udp rules.1.direction=outbound rules.1.action=drop rules.1.source-ip-range=2.2.2.2/32", + Check: core.TestCheckCombine( + func(t *testing.T, ctx *core.CheckFuncCtx) { + t.Helper() + + sg := ctx.Result.(*instanceSDK.SecurityGroup) + assert.Len(t, sg.Rules, 2) + assert.Equal(t, "any", sg.Rules[0].Protocol.String()) + assert.Equal(t, "udp", sg.Rules[1].Protocol.String()) + assert.Equal(t, "inbound", sg.Rules[0].Direction.String()) + assert.Equal(t, "outbound", sg.Rules[1].Direction.String()) + assert.Equal(t, "accept", sg.Rules[0].Action.String()) + assert.Equal(t, "drop", sg.Rules[1].Action.String()) + assert.Equal(t, "1.1.1.1/32", sg.Rules[0].SourceIPRange.String()) + assert.Equal(t, "2.2.2.2/32", sg.Rules[1].SourceIPRange.String()) + }, + core.TestCheckGolden(), + core.TestCheckExitCode(0), + ), + AfterFunc: instance.DeleteSecurityGroup("SecurityGroup"), + })) + + t.Run("SetRules", core.Test(&core.TestConfig{ + Commands: instance.GetCommands(), + BeforeFunc: core.ExecStoreBeforeCmd( + "SecurityGroup", + "scw instance security-group create zone=fr-par-2", + ), + Cmd: "scw instance security-group set-rules {{ .SecurityGroup.ID }} zone=fr-par-2 " + + "rules.0.protocol=tcp rules.0.direction=inbound rules.0.action=drop rules.0.source-ip-range=1.1.1.1/32 " + + "rules.1.protocol=udp rules.1.direction=outbound rules.1.action=drop rules.1.source-ip-range=2.2.2.2/32 " + + "rules.2.protocol=icmp rules.2.direction=inbound rules.2.action=accept rules.2.source-ip-range=3.3.3.3/32", + Check: core.TestCheckCombine( + func(t *testing.T, ctx *core.CheckFuncCtx) { + t.Helper() + + sg := ctx.Result.(*instanceSDK.SecurityGroup) + assert.Len(t, sg.Rules, 3) + assert.Equal(t, "tcp", sg.Rules[0].Protocol.String()) + assert.Equal(t, "udp", sg.Rules[1].Protocol.String()) + assert.Equal(t, "icmp", sg.Rules[2].Protocol.String()) + assert.Equal(t, "inbound", sg.Rules[0].Direction.String()) + assert.Equal(t, "outbound", sg.Rules[1].Direction.String()) + assert.Equal(t, "inbound", sg.Rules[2].Direction.String()) + assert.Equal(t, "drop", sg.Rules[0].Action.String()) + assert.Equal(t, "drop", sg.Rules[1].Action.String()) + assert.Equal(t, "accept", sg.Rules[2].Action.String()) + assert.Equal(t, "1.1.1.1/32", sg.Rules[0].SourceIPRange.String()) + assert.Equal(t, "2.2.2.2/32", sg.Rules[1].SourceIPRange.String()) + assert.Equal(t, "3.3.3.3/32", sg.Rules[2].SourceIPRange.String()) + }, + core.TestCheckGolden(), + core.TestCheckExitCode(0), + ), + AfterFunc: core.ExecAfterCmd( + "scw instance security-group delete {{ .SecurityGroup.ID }} zone=fr-par-2", + ), + })) + + t.Run("UpdateRule", core.Test(&core.TestConfig{ + Commands: instance.GetCommands(), + BeforeFunc: core.BeforeFuncCombine( + instance.CreateSecurityGroup("SecurityGroup"), + core.ExecStoreBeforeCmd( + "SecurityGroupWithRules", + "scw instance security-group add-rules {{ .SecurityGroup.ID }} "+ + "rules.0.protocol=udp rules.0.direction=inbound rules.0.action=drop rules.0.source-ip-range=1.1.1.1/32", + ), + ), + Cmd: "scw instance security-group update-rule security-group-rule-id={{ (index .SecurityGroupWithRules.Rules 0).ID }} " + + "protocol=icmp direction=outbound action=drop source-ip-range=2.2.2.2/32", + Check: core.TestCheckCombine( + func(t *testing.T, ctx *core.CheckFuncCtx) { + t.Helper() + + sg := ctx.Result.(*instanceSDK.SecurityGroup) + assert.Len(t, sg.Rules, 1) + assert.Equal(t, "icmp", sg.Rules[0].Protocol.String()) + assert.Equal(t, "outbound", sg.Rules[0].Direction.String()) + assert.Equal(t, "drop", sg.Rules[0].Action.String()) + assert.Equal(t, "2.2.2.2/32", sg.Rules[0].SourceIPRange.String()) + }, + core.TestCheckGolden(), + core.TestCheckExitCode(0), + ), + AfterFunc: instance.DeleteSecurityGroup("SecurityGroup"), + })) + + t.Run("DeleteRules", core.Test(&core.TestConfig{ + Commands: instance.GetCommands(), + BeforeFunc: core.BeforeFuncCombine( + instance.CreateSecurityGroup("SecurityGroup"), + core.ExecStoreBeforeCmd( + "SecurityGroupWithRules", + "scw instance security-group set-rules {{ .SecurityGroup.ID }} "+ + "rules.0.protocol=tcp rules.0.direction=inbound rules.0.action=drop rules.0.source-ip-range=1.1.1.1/32 "+ + "rules.1.protocol=udp rules.1.direction=outbound rules.1.action=drop rules.1.source-ip-range=2.2.2.2/32 "+ + "rules.2.protocol=icmp rules.2.direction=inbound rules.2.action=accept rules.2.source-ip-range=3.3.3.3/32 "+ + "rules.3.protocol=any rules.3.direction=outbound rules.3.action=accept rules.3.source-ip-range=4.4.4.4/32", + ), + ), + Cmd: "scw instance security-group delete-rules security-group-rule-ids.0={{ (index .SecurityGroupWithRules.Rules 0).ID }} " + + "security-group-rule-ids.1={{ (index .SecurityGroupWithRules.Rules 1).ID }} " + + "security-group-rule-ids.2={{ (index .SecurityGroupWithRules.Rules 3).ID }}", + Check: core.TestCheckCombine( + func(t *testing.T, ctx *core.CheckFuncCtx) { + t.Helper() + sg, err := refreshSecurityGroupInfo(t, ctx, "SecurityGroup") + if err != nil { + t.Errorf("could not get security group: %v", err) + } + + assert.Len(t, sg.Rules, 1) + assert.Equal(t, "icmp", sg.Rules[0].Protocol.String()) + assert.Equal(t, "inbound", sg.Rules[0].Direction.String()) + assert.Equal(t, "accept", sg.Rules[0].Action.String()) + assert.Equal(t, "3.3.3.3/32", sg.Rules[0].SourceIPRange.String()) + }, + core.TestCheckGolden(), + core.TestCheckExitCode(0), + ), + AfterFunc: instance.DeleteSecurityGroup("SecurityGroup"), + })) + + t.Run("Clear", core.Test(&core.TestConfig{ + Commands: instance.GetCommands(), + BeforeFunc: core.BeforeFuncCombine( + instance.CreateSecurityGroup("SecurityGroup"), + core.ExecBeforeCmd( + "scw instance security-group set-rules {{ .SecurityGroup.ID }} "+ + "rules.0.protocol=tcp rules.0.direction=inbound rules.0.action=drop rules.0.source-ip-range=1.1.1.1/32 "+ + "rules.1.protocol=udp rules.1.direction=outbound rules.1.action=drop rules.1.source-ip-range=2.2.2.2/32 "+ + "rules.2.protocol=icmp rules.2.direction=inbound rules.2.action=accept rules.2.source-ip-range=3.3.3.3/32 "+ + "rules.3.protocol=any rules.3.direction=outbound rules.3.action=accept rules.3.source-ip-range=4.4.4.4/32", + ), + ), + Cmd: "scw instance security-group clear {{ .SecurityGroup.ID }}", + Check: core.TestCheckCombine( + func(t *testing.T, ctx *core.CheckFuncCtx) { + t.Helper() + sg, err := refreshSecurityGroupInfo(t, ctx, "SecurityGroup") + if err != nil { + t.Errorf("could not get security group: %v", err) + } + + assert.Empty(t, sg.Rules) + }, + core.TestCheckGolden(), + core.TestCheckExitCode(0), + ), + AfterFunc: instance.DeleteSecurityGroup("SecurityGroup"), + })) +} + +func refreshSecurityGroupInfo( + t *testing.T, + ctx *core.CheckFuncCtx, + metaKey string, +) (*instanceSDK.SecurityGroup, error) { + t.Helper() + api := instanceSDK.NewAPI(ctx.Client) + sgMeta := testhelpers.MapValue[*instanceSDK.SecurityGroup]( + t, + ctx.Meta, + metaKey, + ) + + return api.GetSecurityGroup(&instanceSDK.GetSecurityGroupRequest{ + Zone: "fr-par-1", + SecurityGroupID: sgMeta.ID, + }, scw.WithContext(t.Context())) +} diff --git a/internal/namespaces/instance/v2alpha1/custom_web.go b/internal/namespaces/instance/v2alpha1/custom_web.go index d204ae6ac2..a6b7d02476 100644 --- a/internal/namespaces/instance/v2alpha1/custom_web.go +++ b/internal/namespaces/instance/v2alpha1/custom_web.go @@ -7,4 +7,6 @@ func addWebUrls(cmds *core.Commands) { cmds.MustFind("instance", "placement-group", "get").WebURL = "https://console.scaleway.com/instance/{{ .Zone }}/placement-groups/{{ .PlacementGroupID }}/overview" cmds.MustFind("instance", "private-network-interface", "list").WebURL = "https://console.scaleway.com/instance/{{ .Zone }}/servers/{{ index .ServerIDs 0 }}/network" + + cmds.MustFind("instance", "security-group").WebURL = "https://console.scaleway.com/instance/security-groups" } diff --git a/internal/namespaces/instance/v2alpha1/test_helpers.go b/internal/namespaces/instance/v2alpha1/test_helpers.go new file mode 100644 index 0000000000..e88f18f5eb --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/test_helpers.go @@ -0,0 +1,11 @@ +package instance + +import "github.com/scaleway/scaleway-cli/v2/core" + +func CreateSecurityGroup(metaKey string) core.BeforeFunc { + return core.ExecStoreBeforeCmd(metaKey, "scw instance security-group create") +} + +func DeleteSecurityGroup(metaKey string) core.AfterFunc { + return core.ExecAfterCmd("scw instance security-group delete {{ ." + metaKey + ".ID }}") +} diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-add-rules.cassette.yaml b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-add-rules.cassette.yaml new file mode 100644 index 0000000000..7b50171bcb --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-add-rules.cassette.yaml @@ -0,0 +1,159 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 265 + host: api.scaleway.com + body: '{"name":"cli-sg-xenodochial-proskuriakova","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":null,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2043 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/a0f34b8b-1344-4150-b2d5-b415e3912e27","id":"a0f34b8b-1344-4150-b2d5-b415e3912e27","name":"cli-sg-xenodochial-proskuriakova","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:44.277861Z","updated_at":"2026-10-15T11:34:44.277861Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2043" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:44 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge02) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 0f309d6e-3566-48a6-bd5a-65631e697411 + status: 200 OK + code: 200 + duration: 137.860423ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:44 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge02) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 88efceff-9889-4d02-9f7c-ae1e5364adfb + status: 200 OK + code: 200 + duration: 11.727309ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 432 + host: api.scaleway.com + body: '{"security_group_id":"a0f34b8b-1344-4150-b2d5-b415e3912e27","security_group_rules":[{"protocol":"any","direction":"inbound","action":"accept","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0}]}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-group-rules + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 3099 + body: '{"security_group":{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/a0f34b8b-1344-4150-b2d5-b415e3912e27","id":"a0f34b8b-1344-4150-b2d5-b415e3912e27","name":"cli-sg-xenodochial-proskuriakova","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:44.277861Z","updated_at":"2026-10-15T11:34:44.353611Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[{"id":"c6b10e55-0522-41f2-aff5-1c7692858690","protocol":"any","direction":"inbound","action":"accept","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1},{"id":"23d7c8d6-65b9-4fee-8625-1dd299ee92ae","protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":2}],"zone":"fr-par-1"},"added_rules":[{"id":"c6b10e55-0522-41f2-aff5-1c7692858690","protocol":"any","direction":"inbound","action":"accept","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1},{"id":"23d7c8d6-65b9-4fee-8625-1dd299ee92ae","protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":2}]}' + headers: + Content-Length: + - "3099" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:44 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge02) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 3caab4e8-c12a-4500-adcd-dc90f6892fe7 + status: 200 OK + code: 200 + duration: 133.755021ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/a0f34b8b-1344-4150-b2d5-b415e3912e27 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:44 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge02) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 2d4c6133-870b-49d1-bc6d-6b40fc7dc170 + status: 204 No Content + code: 204 + duration: 105.58816ms diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-add-rules.golden b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-add-rules.golden new file mode 100644 index 0000000000..ec72f35131 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-add-rules.golden @@ -0,0 +1,189 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +ID a0f34b8b-1344-4150-b2d5-b415e3912e27 +Srn srn://instance.scw.eu/zones/fr-par-1/security-groups/a0f34b8b-1344-4150-b2d5-b415e3912e27 +Name cli-sg-xenodochial-proskuriakova +Description - +ProjectID fa1e3217-dc80-42ac-85c3-3f034b78b552 +DisableDefaultRules false +ProjectDefault false +InboundDefaultAction accept +OutboundDefaultAction accept +Stateless false +CreatedAt few seconds ago +UpdatedAt few seconds ago +Zone fr-par-1 + +Tags: +[] + +Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS +c6b10e55-0522-41f2-aff5-1c7692858690 any inbound accept 1.1.1.1/32 ALL - ALL +23d7c8d6-65b9-4fee-8625-1dd299ee92ae udp outbound drop 2.2.2.2/32 ALL - ALL + +Default Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS +11111111-2222-4333-8444-000000000001 tcp outbound drop 0.0.0.0/0 ALL - 25 +11111111-2222-4333-8444-000000000002 tcp outbound drop 0.0.0.0/0 ALL - 465 +11111111-2222-4333-8444-000000000003 tcp outbound drop 0.0.0.0/0 ALL - 587 +11111111-2222-4333-8444-000000000004 tcp outbound drop ::/0 ALL - 25 +11111111-2222-4333-8444-000000000005 tcp outbound drop ::/0 ALL - 465 +11111111-2222-4333-8444-000000000006 tcp outbound drop ::/0 ALL - 587 +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +{ + "id": "a0f34b8b-1344-4150-b2d5-b415e3912e27", + "srn": "srn://instance.scw.eu/zones/fr-par-1/security-groups/a0f34b8b-1344-4150-b2d5-b415e3912e27", + "name": "cli-sg-xenodochial-proskuriakova", + "description": "", + "project_id": "fa1e3217-dc80-42ac-85c3-3f034b78b552", + "tags": [], + "disable_default_rules": false, + "project_default": false, + "inbound_default_action": "accept", + "outbound_default_action": "accept", + "stateless": false, + "created_at": "1970-01-01T00:00:00.0Z", + "updated_at": "1970-01-01T00:00:00.0Z", + "default_rules": [ + { + "id": "11111111-2222-4333-8444-000000000001", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 1 + }, + { + "id": "11111111-2222-4333-8444-000000000002", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 2 + }, + { + "id": "11111111-2222-4333-8444-000000000003", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 3 + }, + { + "id": "11111111-2222-4333-8444-000000000004", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 4 + }, + { + "id": "11111111-2222-4333-8444-000000000005", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 5 + }, + { + "id": "11111111-2222-4333-8444-000000000006", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 6 + } + ], + "rules": [ + { + "id": "c6b10e55-0522-41f2-aff5-1c7692858690", + "protocol": "any", + "direction": "inbound", + "action": "accept", + "source_ip_range": "1.1.1.1/32", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 1, + "end": 65536 + }, + "position": 1 + }, + { + "id": "23d7c8d6-65b9-4fee-8625-1dd299ee92ae", + "protocol": "udp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "2.2.2.2/32", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 1, + "end": 65536 + }, + "position": 2 + } + ], + "zone": "fr-par-1" +} diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-clear.cassette.yaml b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-clear.cassette.yaml new file mode 100644 index 0000000000..b805414ffd --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-clear.cassette.yaml @@ -0,0 +1,238 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 250 + host: api.scaleway.com + body: '{"name":"cli-sg-happy-bohr","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":null,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2028 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","id":"4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","name":"cli-sg-happy-bohr","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.864174Z","updated_at":"2026-10-15T11:34:30.864174Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2028" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 2e518b8a-7b65-45fe-94cf-bbdaaa1d438a + status: 200 OK + code: 200 + duration: 219.57184ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "45" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 6abe7e69-c0b1-44b1-8fda-878c528b2545 + status: 200 OK + code: 200 + duration: 9.587694ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 780 + host: api.scaleway.com + body: '{"security_group_id":"4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","security_group_rules":[{"protocol":"tcp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"icmp","direction":"inbound","action":"accept","source_ip_range":"3.3.3.3/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"any","direction":"outbound","action":"accept","source_ip_range":"4.4.4.4/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0}]}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-group-rules + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 3050 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","id":"4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","name":"cli-sg-happy-bohr","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.864174Z","updated_at":"2026-10-15T11:34:30.935331Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[{"id":"be7a2e73-2c58-4dc4-a292-18981ffb16d2","protocol":"tcp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1},{"id":"cb6721b4-b094-46cc-a775-6e24d51260e2","protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":2},{"id":"d7083564-d83e-460c-a971-edf4760a1aae","protocol":"icmp","direction":"inbound","action":"accept","source_ip_range":"3.3.3.3/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":3},{"id":"2ce12b55-b881-4c9a-90ab-aedab8c807cf","protocol":"any","direction":"outbound","action":"accept","source_ip_range":"4.4.4.4/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":4}],"zone":"fr-par-1"}' + headers: + Content-Length: + - "3050" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "46" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - cf00e06e-2f68-449e-8295-a8d18e4c6a19 + status: 200 OK + code: 200 + duration: 203.119915ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 86 + host: api.scaleway.com + body: '{"security_group_id":"4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","security_group_rules":[]}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-group-rules + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2028 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","id":"4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","name":"cli-sg-happy-bohr","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.864174Z","updated_at":"2026-10-15T11:34:31.156715Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2028" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "40" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 1a1a6a6f-dc1e-44e1-a489-81f046b093fa + status: 200 OK + code: 200 + duration: 182.657986ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/4a7eb0f9-b535-4f3a-84a0-b141079b9d9a + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2028 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","id":"4a7eb0f9-b535-4f3a-84a0-b141079b9d9a","name":"cli-sg-happy-bohr","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.864174Z","updated_at":"2026-10-15T11:34:31.281976Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2028" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "40" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - b9d0bc7d-3799-4db3-bc99-2ac26a138fdf + status: 200 OK + code: 200 + duration: 49.457258ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/4a7eb0f9-b535-4f3a-84a0-b141079b9d9a + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "34" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - c358804d-e812-4bb2-a4be-65649c132a95 + status: 204 No Content + code: 204 + duration: 136.792625ms diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-clear.golden b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-clear.golden new file mode 100644 index 0000000000..078163d6c9 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-clear.golden @@ -0,0 +1,8 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +βœ… Successful reset of the security group rules. +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +{ + "message": "Successful reset of the security group rules", + "details": "" +} diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-create.cassette.yaml b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-create.cassette.yaml new file mode 100644 index 0000000000..b5cca1139e --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-create.cassette.yaml @@ -0,0 +1,118 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 293 + host: api.scaleway.com + body: '{"name":"cli-test-sg-create","description":"Add desc here.","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["cli-test","instance-sg","create"],"project_default":false,"inbound_default_action":"accept","outbound_default_action":"drop","stateless":true}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.39.1-0.20261012134007-9effca27d734 (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2073 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/b29bc86a-525d-4876-bdad-adae3aef4360","id":"b29bc86a-525d-4876-bdad-adae3aef4360","name":"cli-test-sg-create","description":"Add desc here.","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["cli-test","instance-sg","create"],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"drop","stateless":true,"created_at":"2026-10-15T12:34:27.935723Z","updated_at":"2026-10-15T12:34:27.935723Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2073" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 12:34:27 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 77d0f55f-4138-4f3d-a6b0-d55c69ea3540 + status: 200 OK + code: 200 + duration: 225.490354ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.39.1-0.20261012134007-9effca27d734 (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 12:34:28 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 102662ad-da41-4a47-ae9f-12b104032f8e + status: 200 OK + code: 200 + duration: 7.781867ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.39.1-0.20261012134007-9effca27d734 (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/b29bc86a-525d-4876-bdad-adae3aef4360 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 12:34:28 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - bbb02da1-654f-4cfd-bf62-49d444bb3055 + status: 204 No Content + code: 204 + duration: 182.817082ms diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-create.golden b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-create.golden new file mode 100644 index 0000000000..fe3278ab84 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-create.golden @@ -0,0 +1,156 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +ID b29bc86a-525d-4876-bdad-adae3aef4360 +Srn srn://instance.scw.eu/zones/fr-par-1/security-groups/b29bc86a-525d-4876-bdad-adae3aef4360 +Name cli-test-sg-create +Description Add desc here. +ProjectID fa1e3217-dc80-42ac-85c3-3f034b78b552 +DisableDefaultRules false +ProjectDefault false +InboundDefaultAction accept +OutboundDefaultAction drop +Stateless true +CreatedAt few seconds ago +UpdatedAt few seconds ago +Zone fr-par-1 + +Tags: +[cli-test instance-sg create] + +Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS + +Default Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS +11111111-2222-4333-8444-000000000001 tcp outbound drop 0.0.0.0/0 ALL - 25 +11111111-2222-4333-8444-000000000002 tcp outbound drop 0.0.0.0/0 ALL - 465 +11111111-2222-4333-8444-000000000003 tcp outbound drop 0.0.0.0/0 ALL - 587 +11111111-2222-4333-8444-000000000004 tcp outbound drop ::/0 ALL - 25 +11111111-2222-4333-8444-000000000005 tcp outbound drop ::/0 ALL - 465 +11111111-2222-4333-8444-000000000006 tcp outbound drop ::/0 ALL - 587 +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +{ + "id": "b29bc86a-525d-4876-bdad-adae3aef4360", + "srn": "srn://instance.scw.eu/zones/fr-par-1/security-groups/b29bc86a-525d-4876-bdad-adae3aef4360", + "name": "cli-test-sg-create", + "description": "Add desc here.", + "project_id": "fa1e3217-dc80-42ac-85c3-3f034b78b552", + "tags": [ + "cli-test", + "instance-sg", + "create" + ], + "disable_default_rules": false, + "project_default": false, + "inbound_default_action": "accept", + "outbound_default_action": "drop", + "stateless": true, + "created_at": "1970-01-01T00:00:00.0Z", + "updated_at": "1970-01-01T00:00:00.0Z", + "default_rules": [ + { + "id": "11111111-2222-4333-8444-000000000001", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 1 + }, + { + "id": "11111111-2222-4333-8444-000000000002", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 2 + }, + { + "id": "11111111-2222-4333-8444-000000000003", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 3 + }, + { + "id": "11111111-2222-4333-8444-000000000004", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 4 + }, + { + "id": "11111111-2222-4333-8444-000000000005", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 5 + }, + { + "id": "11111111-2222-4333-8444-000000000006", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 6 + } + ], + "rules": [], + "zone": "fr-par-1" +} diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-delete-rules.cassette.yaml b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-delete-rules.cassette.yaml new file mode 100644 index 0000000000..6de4418a4e --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-delete-rules.cassette.yaml @@ -0,0 +1,236 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 253 + host: api.scaleway.com + body: '{"name":"cli-sg-adoring-rubin","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":null,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2031 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/4ecf3270-0bb9-489f-b9d3-33213e94bae3","id":"4ecf3270-0bb9-489f-b9d3-33213e94bae3","name":"cli-sg-adoring-rubin","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.871128Z","updated_at":"2026-10-15T11:34:30.871128Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2031" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 67e0a555-eaf2-404a-99d5-590c6a473614 + status: 200 OK + code: 200 + duration: 293.912162ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "43" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - f170e11a-feaa-4056-a6d6-f4381c955322 + status: 200 OK + code: 200 + duration: 12.449307ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 780 + host: api.scaleway.com + body: '{"security_group_id":"4ecf3270-0bb9-489f-b9d3-33213e94bae3","security_group_rules":[{"protocol":"tcp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"icmp","direction":"inbound","action":"accept","source_ip_range":"3.3.3.3/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"any","direction":"outbound","action":"accept","source_ip_range":"4.4.4.4/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0}]}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-group-rules + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 3053 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/4ecf3270-0bb9-489f-b9d3-33213e94bae3","id":"4ecf3270-0bb9-489f-b9d3-33213e94bae3","name":"cli-sg-adoring-rubin","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.871128Z","updated_at":"2026-10-15T11:34:31.015114Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[{"id":"9a770b28-9367-4b82-a4d2-5080d089ed10","protocol":"tcp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1},{"id":"a25b6531-8725-4434-a923-45c2b61e4130","protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":2},{"id":"d340d3b8-5d01-4bab-8fb5-9d521ba6e85b","protocol":"icmp","direction":"inbound","action":"accept","source_ip_range":"3.3.3.3/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":3},{"id":"758e556d-2e6b-441e-ab0c-f3aab508dde7","protocol":"any","direction":"outbound","action":"accept","source_ip_range":"4.4.4.4/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":4}],"zone":"fr-par-1"}' + headers: + Content-Length: + - "3053" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "42" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - a14a37a9-dcfd-4bb6-b7c2-233d6a465535 + status: 200 OK + code: 200 + duration: 276.990784ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 146 + host: api.scaleway.com + body: '{"security_group_rule_ids":["9a770b28-9367-4b82-a4d2-5080d089ed10","a25b6531-8725-4434-a923-45c2b61e4130","758e556d-2e6b-441e-ab0c-f3aab508dde7"]}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-group-rules + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "38" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - c8c60c16-51b5-45e4-a58a-1dee2390a040 + status: 204 No Content + code: 204 + duration: 127.823654ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/4ecf3270-0bb9-489f-b9d3-33213e94bae3 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2287 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/4ecf3270-0bb9-489f-b9d3-33213e94bae3","id":"4ecf3270-0bb9-489f-b9d3-33213e94bae3","name":"cli-sg-adoring-rubin","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.871128Z","updated_at":"2026-10-15T11:34:31.373049Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[{"id":"d340d3b8-5d01-4bab-8fb5-9d521ba6e85b","protocol":"icmp","direction":"inbound","action":"accept","source_ip_range":"3.3.3.3/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1}],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2287" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "35" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 3fddee6c-7a59-4281-a23d-2dc996b76d72 + status: 200 OK + code: 200 + duration: 78.536766ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/4ecf3270-0bb9-489f-b9d3-33213e94bae3 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "38" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - b892a6d8-da29-4491-884c-4ac0b8337db0 + status: 204 No Content + code: 204 + duration: 153.904942ms diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-delete-rules.golden b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-delete-rules.golden new file mode 100644 index 0000000000..87818d7a08 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-delete-rules.golden @@ -0,0 +1,8 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +βœ… Success. +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +{ + "message": "Success", + "details": "" +} diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-list.cassette.yaml b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-list.cassette.yaml new file mode 100644 index 0000000000..821d27a358 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-list.cassette.yaml @@ -0,0 +1,394 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 258 + host: api.scaleway.com + body: '{"name":"cli-sg-beautiful-kalam","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo"],"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2038 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/03c20b93-6635-4c0b-8fd1-b3d8b7c71a32","id":"03c20b93-6635-4c0b-8fd1-b3d8b7c71a32","name":"cli-sg-beautiful-kalam","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo"],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.886767Z","updated_at":"2026-10-15T11:34:30.886767Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2038" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 773b8604-975f-4e34-8fa4-afd84f4d07ce + status: 200 OK + code: 200 + duration: 289.3918ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "41" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - e5430648-27c7-4d8d-8179-1f3366f5c5d9 + status: 200 OK + code: 200 + duration: 13.071999ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 259 + host: api.scaleway.com + body: '{"name":"cli-sg-sharp-chandrasekhar","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":null,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2037 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/89b336c0-35bf-4a9e-a749-edd2e190d6e7","id":"89b336c0-35bf-4a9e-a749-edd2e190d6e7","name":"cli-sg-sharp-chandrasekhar","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:31.081209Z","updated_at":"2026-10-15T11:34:31.081209Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2037" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "42" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 3a13fde2-85f3-4c81-991c-fc609ebcfdb4 + status: 200 OK + code: 200 + duration: 142.141565ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 239 + host: api.scaleway.com + body: '{"name":"named-sg","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo"],"project_default":false,"inbound_default_action":"drop","outbound_default_action":"drop","stateless":true}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2019 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/63975a9e-1b88-4c2b-939f-df1b97bb32c0","id":"63975a9e-1b88-4c2b-939f-df1b97bb32c0","name":"named-sg","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo"],"disable_default_rules":false,"project_default":false,"inbound_default_action":"drop","outbound_default_action":"drop","stateless":true,"created_at":"2026-10-15T11:34:31.252631Z","updated_at":"2026-10-15T11:34:31.252631Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2019" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "37" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 7dcf1847-45f4-4fb6-8f73-4f4ff45e64b1 + status: 200 OK + code: 200 + duration: 205.816827ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 278 + host: api.scaleway.com + body: '{"name":"cli-sg-modest-jackson","description":"Descriptive text.","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo","bar"],"project_default":false,"inbound_default_action":"drop","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2058 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/27059e57-2834-4b0a-bfef-66f378bb1430","id":"27059e57-2834-4b0a-bfef-66f378bb1430","name":"cli-sg-modest-jackson","description":"Descriptive text.","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo","bar"],"disable_default_rules":false,"project_default":false,"inbound_default_action":"drop","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:31.412630Z","updated_at":"2026-10-15T11:34:31.412630Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2058" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "36" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 8fd27b15-6389-4f4c-899b-e82f152baf23 + status: 200 OK + code: 200 + duration: 107.275433ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + form: + order_by: + - created_at_desc + project_id: + - fa1e3217-dc80-42ac-85c3-3f034b78b552 + tags: + - foo + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups?order_by=created_at_desc&project_id=fa1e3217-dc80-42ac-85c3-3f034b78b552&tags=foo + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 1553 + body: '{"security_groups":[{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/27059e57-2834-4b0a-bfef-66f378bb1430","id":"27059e57-2834-4b0a-bfef-66f378bb1430","name":"cli-sg-modest-jackson","description":"Descriptive text.","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo","bar"],"disable_default_rules":false,"project_default":false,"inbound_default_action":"drop","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:31.412630Z","updated_at":"2026-10-15T11:34:31.412630Z","zone":"fr-par-1"},{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/63975a9e-1b88-4c2b-939f-df1b97bb32c0","id":"63975a9e-1b88-4c2b-939f-df1b97bb32c0","name":"named-sg","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo"],"disable_default_rules":false,"project_default":false,"inbound_default_action":"drop","outbound_default_action":"drop","stateless":true,"created_at":"2026-10-15T11:34:31.252631Z","updated_at":"2026-10-15T11:34:31.252631Z","zone":"fr-par-1"},{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/03c20b93-6635-4c0b-8fd1-b3d8b7c71a32","id":"03c20b93-6635-4c0b-8fd1-b3d8b7c71a32","name":"cli-sg-beautiful-kalam","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["foo"],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.886767Z","updated_at":"2026-10-15T11:34:30.886767Z","zone":"fr-par-1"}],"total_count":3}' + headers: + Content-Length: + - "1553" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "33" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 18fcb369-67c9-4937-bfe7-3da33bff18cb + status: 200 OK + code: 200 + duration: 91.244589ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/03c20b93-6635-4c0b-8fd1-b3d8b7c71a32 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "32" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 01f2e1e1-f795-4eac-b851-2a4a7652a2ec + status: 204 No Content + code: 204 + duration: 106.559957ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/89b336c0-35bf-4a9e-a749-edd2e190d6e7 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "34" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - bb9e9a18-79d0-405f-ac68-c1ba6df261a7 + status: 204 No Content + code: 204 + duration: 100.784193ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/63975a9e-1b88-4c2b-939f-df1b97bb32c0 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - e2df6f9d-d3f2-45ac-b49a-c5c921f7af0c + status: 204 No Content + code: 204 + duration: 117.574796ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/27059e57-2834-4b0a-bfef-66f378bb1430 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "48" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 524767d9-6b5d-4312-9601-54d830cca6ab + status: 204 No Content + code: 204 + duration: 105.950231ms diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-list.golden b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-list.golden new file mode 100644 index 0000000000..52a8f4991f --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-list.golden @@ -0,0 +1,64 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +ID NAME DESCRIPTION TAGS INBOUND DEF. ACT. OUTBOUND DEF. ACT. STATELESS PROJECT DEFAULT PROJECT ID ZONE CREATED AT UPDATED AT +27059e57-2834-4b0a-bfef-66f378bb1430 cli-sg-modest-jackson Descriptive text. [foo bar] drop accept false false fa1e3217-dc80-42ac-85c3-3f034b78b552 fr-par-1 few seconds ago few seconds ago +63975a9e-1b88-4c2b-939f-df1b97bb32c0 named-sg - [foo] drop drop true false fa1e3217-dc80-42ac-85c3-3f034b78b552 fr-par-1 few seconds ago few seconds ago +03c20b93-6635-4c0b-8fd1-b3d8b7c71a32 cli-sg-beautiful-kalam - [foo] accept accept false false fa1e3217-dc80-42ac-85c3-3f034b78b552 fr-par-1 few seconds ago few seconds ago +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +[ + { + "id": "27059e57-2834-4b0a-bfef-66f378bb1430", + "srn": "srn://instance.scw.eu/zones/fr-par-1/security-groups/27059e57-2834-4b0a-bfef-66f378bb1430", + "name": "cli-sg-modest-jackson", + "description": "Descriptive text.", + "project_id": "fa1e3217-dc80-42ac-85c3-3f034b78b552", + "tags": [ + "foo", + "bar" + ], + "disable_default_rules": false, + "project_default": false, + "inbound_default_action": "drop", + "outbound_default_action": "accept", + "stateless": false, + "created_at": "1970-01-01T00:00:00.0Z", + "updated_at": "1970-01-01T00:00:00.0Z", + "zone": "fr-par-1" + }, + { + "id": "63975a9e-1b88-4c2b-939f-df1b97bb32c0", + "srn": "srn://instance.scw.eu/zones/fr-par-1/security-groups/63975a9e-1b88-4c2b-939f-df1b97bb32c0", + "name": "named-sg", + "description": "", + "project_id": "fa1e3217-dc80-42ac-85c3-3f034b78b552", + "tags": [ + "foo" + ], + "disable_default_rules": false, + "project_default": false, + "inbound_default_action": "drop", + "outbound_default_action": "drop", + "stateless": true, + "created_at": "1970-01-01T00:00:00.0Z", + "updated_at": "1970-01-01T00:00:00.0Z", + "zone": "fr-par-1" + }, + { + "id": "03c20b93-6635-4c0b-8fd1-b3d8b7c71a32", + "srn": "srn://instance.scw.eu/zones/fr-par-1/security-groups/03c20b93-6635-4c0b-8fd1-b3d8b7c71a32", + "name": "cli-sg-beautiful-kalam", + "description": "", + "project_id": "fa1e3217-dc80-42ac-85c3-3f034b78b552", + "tags": [ + "foo" + ], + "disable_default_rules": false, + "project_default": false, + "inbound_default_action": "accept", + "outbound_default_action": "accept", + "stateless": false, + "created_at": "1970-01-01T00:00:00.0Z", + "updated_at": "1970-01-01T00:00:00.0Z", + "zone": "fr-par-1" + } +] diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-set-rules.cassette.yaml b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-set-rules.cassette.yaml new file mode 100644 index 0000000000..a4d176ea48 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-set-rules.cassette.yaml @@ -0,0 +1,159 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 255 + host: api.scaleway.com + body: '{"name":"cli-sg-youthful-diffie","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":null,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-2/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2033 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-2/security-groups/3abd2cee-5545-4439-a9d2-018790d26af9","id":"3abd2cee-5545-4439-a9d2-018790d26af9","name":"cli-sg-youthful-diffie","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.915603Z","updated_at":"2026-10-15T11:34:30.915603Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-2"}' + headers: + Content-Length: + - "2033" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "49" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 778be265-f717-4729-9ffd-fde8a016a8b6 + status: 200 OK + code: 200 + duration: 264.93683ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "46" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - c9f6fdc3-cc71-47ef-896f-6bf33f26161a + status: 200 OK + code: 200 + duration: 12.871441ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 605 + host: api.scaleway.com + body: '{"security_group_id":"3abd2cee-5545-4439-a9d2-018790d26af9","security_group_rules":[{"protocol":"tcp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0},{"protocol":"icmp","direction":"inbound","action":"accept","source_ip_range":"3.3.3.3/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0}]}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-2/security-group-rules + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2798 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-2/security-groups/3abd2cee-5545-4439-a9d2-018790d26af9","id":"3abd2cee-5545-4439-a9d2-018790d26af9","name":"cli-sg-youthful-diffie","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.915603Z","updated_at":"2026-10-15T11:34:30.988198Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[{"id":"6f5da7cd-2223-4715-8843-8b98b79dbc09","protocol":"tcp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1},{"id":"707744f2-9eb9-46f5-85f2-e57546d6265b","protocol":"udp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":2},{"id":"f425fc83-566e-407d-b2dc-311126c11b73","protocol":"icmp","direction":"inbound","action":"accept","source_ip_range":"3.3.3.3/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":3}],"zone":"fr-par-2"}' + headers: + Content-Length: + - "2798" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "45" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 94123bea-15cf-4463-a4e1-35377e74ab69 + status: 200 OK + code: 200 + duration: 143.477669ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-2/security-groups/3abd2cee-5545-4439-a9d2-018790d26af9 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "41" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 73575dca-9caf-4b6a-98c3-b31fe73a641d + status: 204 No Content + code: 204 + duration: 132.089077ms diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-set-rules.golden b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-set-rules.golden new file mode 100644 index 0000000000..1213e13c86 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-set-rules.golden @@ -0,0 +1,207 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +ID 3abd2cee-5545-4439-a9d2-018790d26af9 +Srn srn://instance.scw.eu/zones/fr-par-2/security-groups/3abd2cee-5545-4439-a9d2-018790d26af9 +Name cli-sg-youthful-diffie +Description - +ProjectID fa1e3217-dc80-42ac-85c3-3f034b78b552 +DisableDefaultRules false +ProjectDefault false +InboundDefaultAction accept +OutboundDefaultAction accept +Stateless false +CreatedAt few seconds ago +UpdatedAt few seconds ago +Zone fr-par-2 + +Tags: +[] + +Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS +6f5da7cd-2223-4715-8843-8b98b79dbc09 tcp inbound drop 1.1.1.1/32 ALL - ALL +707744f2-9eb9-46f5-85f2-e57546d6265b udp outbound drop 2.2.2.2/32 ALL - ALL +f425fc83-566e-407d-b2dc-311126c11b73 icmp inbound accept 3.3.3.3/32 ALL - ALL + +Default Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS +11111111-2222-4333-8444-000000000001 tcp outbound drop 0.0.0.0/0 ALL - 25 +11111111-2222-4333-8444-000000000002 tcp outbound drop 0.0.0.0/0 ALL - 465 +11111111-2222-4333-8444-000000000003 tcp outbound drop 0.0.0.0/0 ALL - 587 +11111111-2222-4333-8444-000000000004 tcp outbound drop ::/0 ALL - 25 +11111111-2222-4333-8444-000000000005 tcp outbound drop ::/0 ALL - 465 +11111111-2222-4333-8444-000000000006 tcp outbound drop ::/0 ALL - 587 +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +{ + "id": "3abd2cee-5545-4439-a9d2-018790d26af9", + "srn": "srn://instance.scw.eu/zones/fr-par-2/security-groups/3abd2cee-5545-4439-a9d2-018790d26af9", + "name": "cli-sg-youthful-diffie", + "description": "", + "project_id": "fa1e3217-dc80-42ac-85c3-3f034b78b552", + "tags": [], + "disable_default_rules": false, + "project_default": false, + "inbound_default_action": "accept", + "outbound_default_action": "accept", + "stateless": false, + "created_at": "1970-01-01T00:00:00.0Z", + "updated_at": "1970-01-01T00:00:00.0Z", + "default_rules": [ + { + "id": "11111111-2222-4333-8444-000000000001", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 1 + }, + { + "id": "11111111-2222-4333-8444-000000000002", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 2 + }, + { + "id": "11111111-2222-4333-8444-000000000003", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 3 + }, + { + "id": "11111111-2222-4333-8444-000000000004", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 4 + }, + { + "id": "11111111-2222-4333-8444-000000000005", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 5 + }, + { + "id": "11111111-2222-4333-8444-000000000006", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 6 + } + ], + "rules": [ + { + "id": "6f5da7cd-2223-4715-8843-8b98b79dbc09", + "protocol": "tcp", + "direction": "inbound", + "action": "drop", + "source_ip_range": "1.1.1.1/32", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 1, + "end": 65536 + }, + "position": 1 + }, + { + "id": "707744f2-9eb9-46f5-85f2-e57546d6265b", + "protocol": "udp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "2.2.2.2/32", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 1, + "end": 65536 + }, + "position": 2 + }, + { + "id": "f425fc83-566e-407d-b2dc-311126c11b73", + "protocol": "icmp", + "direction": "inbound", + "action": "accept", + "source_ip_range": "3.3.3.3/32", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 1, + "end": 65536 + }, + "position": 3 + } + ], + "zone": "fr-par-2" +} diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update-rule.cassette.yaml b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update-rule.cassette.yaml new file mode 100644 index 0000000000..0091f194b8 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update-rule.cassette.yaml @@ -0,0 +1,200 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 261 + host: api.scaleway.com + body: '{"name":"cli-sg-affectionate-jennings","description":"","disable_default_rules":false,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":null,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2039 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/c778cb06-3629-4f55-b1c6-f7acd82c4088","id":"c778cb06-3629-4f55-b1c6-f7acd82c4088","name":"cli-sg-affectionate-jennings","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.893198Z","updated_at":"2026-10-15T11:34:30.893198Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2039" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "47" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 58f5a71a-9e0b-42a6-b945-a6866c8a1972 + status: 200 OK + code: 200 + duration: 267.984513ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "43" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 76bf6302-fb16-424d-9f96-22dfc40bb281 + status: 200 OK + code: 200 + duration: 10.560074ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 257 + host: api.scaleway.com + body: '{"security_group_id":"c778cb06-3629-4f55-b1c6-f7acd82c4088","security_group_rules":[{"protocol":"udp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":null,"destination_ports":null,"position":0}]}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-group-rules + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2581 + body: '{"security_group":{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/c778cb06-3629-4f55-b1c6-f7acd82c4088","id":"c778cb06-3629-4f55-b1c6-f7acd82c4088","name":"cli-sg-affectionate-jennings","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.893198Z","updated_at":"2026-10-15T11:34:30.985776Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[{"id":"94db220a-4e45-4a6c-a152-2c8b23e9b4fb","protocol":"udp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1}],"zone":"fr-par-1"},"added_rules":[{"id":"94db220a-4e45-4a6c-a152-2c8b23e9b4fb","protocol":"udp","direction":"inbound","action":"drop","source_ip_range":"1.1.1.1/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1}]}' + headers: + Content-Length: + - "2581" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "44" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 761a9176-c005-47ad-836a-1a01ff04ad40 + status: 200 OK + code: 200 + duration: 186.463834ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 89 + host: api.scaleway.com + body: '{"protocol":"icmp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32"}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-group-rules/94db220a-4e45-4a6c-a152-2c8b23e9b4fb + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2294 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/c778cb06-3629-4f55-b1c6-f7acd82c4088","id":"c778cb06-3629-4f55-b1c6-f7acd82c4088","name":"cli-sg-affectionate-jennings","description":"","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":[],"disable_default_rules":false,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"accept","stateless":false,"created_at":"2026-10-15T11:34:30.893198Z","updated_at":"2026-10-15T11:34:31.192133Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[{"id":"94db220a-4e45-4a6c-a152-2c8b23e9b4fb","protocol":"icmp","direction":"outbound","action":"drop","source_ip_range":"2.2.2.2/32","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":1,"end":65536},"position":1}],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2294" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "41" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 271c1abf-aa40-4d2e-97bb-9525ce435286 + status: 200 OK + code: 200 + duration: 129.769594ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/c778cb06-3629-4f55-b1c6-f7acd82c4088 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "35" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - ad882450-0788-44e6-85ca-3e6cb42e82e3 + status: 204 No Content + code: 204 + duration: 105.820817ms diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update-rule.golden b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update-rule.golden new file mode 100644 index 0000000000..be8f746cf0 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update-rule.golden @@ -0,0 +1,171 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +ID c778cb06-3629-4f55-b1c6-f7acd82c4088 +Srn srn://instance.scw.eu/zones/fr-par-1/security-groups/c778cb06-3629-4f55-b1c6-f7acd82c4088 +Name cli-sg-affectionate-jennings +Description - +ProjectID fa1e3217-dc80-42ac-85c3-3f034b78b552 +DisableDefaultRules false +ProjectDefault false +InboundDefaultAction accept +OutboundDefaultAction accept +Stateless false +CreatedAt few seconds ago +UpdatedAt few seconds ago +Zone fr-par-1 + +Tags: +[] + +Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS +94db220a-4e45-4a6c-a152-2c8b23e9b4fb icmp outbound drop 2.2.2.2/32 ALL - ALL + +Default Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS +11111111-2222-4333-8444-000000000001 tcp outbound drop 0.0.0.0/0 ALL - 25 +11111111-2222-4333-8444-000000000002 tcp outbound drop 0.0.0.0/0 ALL - 465 +11111111-2222-4333-8444-000000000003 tcp outbound drop 0.0.0.0/0 ALL - 587 +11111111-2222-4333-8444-000000000004 tcp outbound drop ::/0 ALL - 25 +11111111-2222-4333-8444-000000000005 tcp outbound drop ::/0 ALL - 465 +11111111-2222-4333-8444-000000000006 tcp outbound drop ::/0 ALL - 587 +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +{ + "id": "c778cb06-3629-4f55-b1c6-f7acd82c4088", + "srn": "srn://instance.scw.eu/zones/fr-par-1/security-groups/c778cb06-3629-4f55-b1c6-f7acd82c4088", + "name": "cli-sg-affectionate-jennings", + "description": "", + "project_id": "fa1e3217-dc80-42ac-85c3-3f034b78b552", + "tags": [], + "disable_default_rules": false, + "project_default": false, + "inbound_default_action": "accept", + "outbound_default_action": "accept", + "stateless": false, + "created_at": "1970-01-01T00:00:00.0Z", + "updated_at": "1970-01-01T00:00:00.0Z", + "default_rules": [ + { + "id": "11111111-2222-4333-8444-000000000001", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 1 + }, + { + "id": "11111111-2222-4333-8444-000000000002", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 2 + }, + { + "id": "11111111-2222-4333-8444-000000000003", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 3 + }, + { + "id": "11111111-2222-4333-8444-000000000004", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 4 + }, + { + "id": "11111111-2222-4333-8444-000000000005", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 5 + }, + { + "id": "11111111-2222-4333-8444-000000000006", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 6 + } + ], + "rules": [ + { + "id": "94db220a-4e45-4a6c-a152-2c8b23e9b4fb", + "protocol": "icmp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "2.2.2.2/32", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 1, + "end": 65536 + }, + "position": 1 + } + ], + "zone": "fr-par-1" +} diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update.cassette.yaml b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update.cassette.yaml new file mode 100644 index 0000000000..9413d03665 --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update.cassette.yaml @@ -0,0 +1,159 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 290 + host: api.scaleway.com + body: '{"name":"cli-sg-infallible-hamilton","description":"tmp","disable_default_rules":true,"project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["cli-test","instance-sg","update"],"project_default":false,"inbound_default_action":"accept","outbound_default_action":"drop","stateless":false}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2070 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/0007d941-ed06-42d3-8381-934b316e1543","id":"0007d941-ed06-42d3-8381-934b316e1543","name":"cli-sg-infallible-hamilton","description":"tmp","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["cli-test","instance-sg","update"],"disable_default_rules":true,"project_default":false,"inbound_default_action":"accept","outbound_default_action":"drop","stateless":false,"created_at":"2026-10-15T11:34:30.860476Z","updated_at":"2026-10-15T11:34:30.860476Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2070" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "46" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 18c482b8-76b2-4d0b-aa5e-f13a1d470f23 + status: 200 OK + code: 200 + duration: 212.733187ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/metadata + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 59 + body: '{"platform":"external","partition":"scw","domain":"scw.eu"}' + headers: + Content-Length: + - "59" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:30 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "47" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 99426045-acfc-40a6-a709-49cd5702e09e + status: 200 OK + code: 200 + duration: 8.050743ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 210 + host: api.scaleway.com + body: '{"name":"cli-test-sg-update","description":"updated","disable_default_rules":false,"tags":["cli-test","instance-sg","update"],"inbound_default_action":"drop","outbound_default_action":"accept","stateless":true}' + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/0007d941-ed06-42d3-8381-934b316e1543 + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 2066 + body: '{"srn":"srn://instance.scw.eu/zones/fr-par-1/security-groups/0007d941-ed06-42d3-8381-934b316e1543","id":"0007d941-ed06-42d3-8381-934b316e1543","name":"cli-test-sg-update","description":"updated","project_id":"fa1e3217-dc80-42ac-85c3-3f034b78b552","tags":["cli-test","instance-sg","update"],"disable_default_rules":false,"project_default":false,"inbound_default_action":"drop","outbound_default_action":"accept","stateless":true,"created_at":"2026-10-15T11:34:30.860476Z","updated_at":"2026-10-15T11:34:30.939190Z","default_rules":[{"id":"11111111-2222-4333-8444-000000000001","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":1},{"id":"11111111-2222-4333-8444-000000000002","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":2},{"id":"11111111-2222-4333-8444-000000000003","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"0.0.0.0/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":3},{"id":"11111111-2222-4333-8444-000000000004","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":25,"end":25},"position":4},{"id":"11111111-2222-4333-8444-000000000005","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":465,"end":465},"position":5},{"id":"11111111-2222-4333-8444-000000000006","protocol":"tcp","direction":"outbound","action":"drop","source_ip_range":"::/0","destination_ip_range":"","source_ports":{"start":1,"end":65536},"destination_ports":{"start":587,"end":587},"position":6}],"rules":[],"zone":"fr-par-1"}' + headers: + Content-Length: + - "2066" + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "44" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - 1e1d307d-83fc-4e15-94ef-0a2b55715db9 + status: 200 OK + code: 200 + duration: 166.276222ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + host: api.scaleway.com + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.37.0.20261005125851-bba713c8ec7e (go1.27.1; linux; amd64) cli-e2e-test + url: https://api.scaleway.com/instance/v2alpha1/zones/fr-par-1/security-groups/0007d941-ed06-42d3-8381-934b316e1543 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: 0 + body: "" + headers: + Content-Type: + - application/json + Date: + - Thu, 15 Oct 2026 11:34:31 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + X-Ratelimit-Limit: + - 50, 50;w=1 + X-Ratelimit-Remaining: + - "38" + X-Ratelimit-Reset: + - "1" + X-Request-Id: + - c4c89edb-326a-422c-a4ff-434a65a60d5e + status: 204 No Content + code: 204 + duration: 198.099702ms diff --git a/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update.golden b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update.golden new file mode 100644 index 0000000000..313262573b --- /dev/null +++ b/internal/namespaces/instance/v2alpha1/testdata/test-security-group-update.golden @@ -0,0 +1,156 @@ +🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲 +🟩🟩🟩 STDOUT️ 🟩🟩🟩️ +ID 0007d941-ed06-42d3-8381-934b316e1543 +Srn srn://instance.scw.eu/zones/fr-par-1/security-groups/0007d941-ed06-42d3-8381-934b316e1543 +Name cli-test-sg-update +Description updated +ProjectID fa1e3217-dc80-42ac-85c3-3f034b78b552 +DisableDefaultRules false +ProjectDefault false +InboundDefaultAction drop +OutboundDefaultAction accept +Stateless true +CreatedAt few seconds ago +UpdatedAt few seconds ago +Zone fr-par-1 + +Tags: +[cli-test instance-sg update] + +Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS + +Default Rules: +ID PROTOCOL DIRECTION ACTION SOURCE IP RANGE SOURCE PORTS DEST IP RANGE DEST PORTS +11111111-2222-4333-8444-000000000001 tcp outbound drop 0.0.0.0/0 ALL - 25 +11111111-2222-4333-8444-000000000002 tcp outbound drop 0.0.0.0/0 ALL - 465 +11111111-2222-4333-8444-000000000003 tcp outbound drop 0.0.0.0/0 ALL - 587 +11111111-2222-4333-8444-000000000004 tcp outbound drop ::/0 ALL - 25 +11111111-2222-4333-8444-000000000005 tcp outbound drop ::/0 ALL - 465 +11111111-2222-4333-8444-000000000006 tcp outbound drop ::/0 ALL - 587 +🟩🟩🟩 JSON STDOUT 🟩🟩🟩 +{ + "id": "0007d941-ed06-42d3-8381-934b316e1543", + "srn": "srn://instance.scw.eu/zones/fr-par-1/security-groups/0007d941-ed06-42d3-8381-934b316e1543", + "name": "cli-test-sg-update", + "description": "updated", + "project_id": "fa1e3217-dc80-42ac-85c3-3f034b78b552", + "tags": [ + "cli-test", + "instance-sg", + "update" + ], + "disable_default_rules": false, + "project_default": false, + "inbound_default_action": "drop", + "outbound_default_action": "accept", + "stateless": true, + "created_at": "1970-01-01T00:00:00.0Z", + "updated_at": "1970-01-01T00:00:00.0Z", + "default_rules": [ + { + "id": "11111111-2222-4333-8444-000000000001", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 1 + }, + { + "id": "11111111-2222-4333-8444-000000000002", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 2 + }, + { + "id": "11111111-2222-4333-8444-000000000003", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "0.0.0.0/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 3 + }, + { + "id": "11111111-2222-4333-8444-000000000004", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 25, + "end": 25 + }, + "position": 4 + }, + { + "id": "11111111-2222-4333-8444-000000000005", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 465, + "end": 465 + }, + "position": 5 + }, + { + "id": "11111111-2222-4333-8444-000000000006", + "protocol": "tcp", + "direction": "outbound", + "action": "drop", + "source_ip_range": "::/0", + "destination_ip_range": "", + "source_ports": { + "start": 1, + "end": 65536 + }, + "destination_ports": { + "start": 587, + "end": 587 + }, + "position": 6 + } + ], + "rules": [], + "zone": "fr-par-1" +}