Skip to content

feat(vpc): add edit mode for acls #4655

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions cmd/scw/testdata/test-all-usage-vpc-rule-edit-usage.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲
🟥🟥🟥 STDERR️️ 🟥🟥🟥️
This command starts your default editor to edit a marshaled version of your resource
Default editor will be taken from $VISUAL, then $EDITOR or an editor based on your system

USAGE:
scw vpc rule edit [arg=value ...]

ARGS:
vpc-id ID of the Network ACL's VPC
[is-ipv6] Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type
[default-policy] Action to take for packets which do not match any rules
[mode=yaml] marshaling used when editing data (yaml | json)
[region=fr-par] Region to target. If none is passed will use default region from the config

FLAGS:
-h, --help help for edit

GLOBAL FLAGS:
-c, --config string The path to the config file
-D, --debug Enable debug mode
-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
1 change: 1 addition & 0 deletions cmd/scw/testdata/test-all-usage-vpc-rule-usage.golden
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ USAGE:
scw vpc rule <command>

AVAILABLE COMMANDS:
edit Edit all ACL rules of a VPC
get Get ACL Rules for VPC
set Set VPC ACL rules

Expand Down
25 changes: 25 additions & 0 deletions docs/commands/vpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ This API allows you to manage your Virtual Private Clouds (VPCs) and Private Net
- [Return routes with associated next hop data](#return-routes-with-associated-next-hop-data)
- [Update Route](#update-route)
- [Rule management command](#rule-management-command)
- [Edit all ACL rules of a VPC](#edit-all-acl-rules-of-a-vpc)
- [Get ACL Rules for VPC](#get-acl-rules-for-vpc)
- [Set VPC ACL rules](#set-vpc-acl-rules)
- [Subnet management command](#subnet-management-command)
Expand Down Expand Up @@ -316,6 +317,30 @@ scw vpc route update <route-id ...> [arg=value ...]
ACL Rules.


### Edit all ACL rules of a VPC

This command starts your default editor to edit a marshaled version of your resource
Default editor will be taken from $VISUAL, then $EDITOR or an editor based on your system

**Usage:**

```
scw vpc rule edit [arg=value ...]
```


**Args:**

| Name | | Description |
|------|---|-------------|
| vpc-id | Required | ID of the Network ACL's VPC |
| is-ipv6 | | Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type |
| default-policy | | Action to take for packets which do not match any rules |
| mode | Default: `yaml`<br />One of: `yaml`, `json` | marshaling used when editing data |
| region | Default: `fr-par` | Region to target. If none is passed will use default region from the config |



### Get ACL Rules for VPC

Retrieve a list of ACL rules for a VPC, specified by its VPC ID.
Expand Down
4 changes: 4 additions & 0 deletions internal/namespaces/vpc/v2/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@ func GetCommands() *core.Commands {
cmds.MustFind("vpc", "private-network", "get").Override(privateNetworkGetBuilder)
human.RegisterMarshalerFunc(vpc.PrivateNetwork{}, privateNetworkMarshalerFunc)

cmds.Merge(core.NewCommands(
vpcACLEditCommand(),
))

return cmds
}
117 changes: 117 additions & 0 deletions internal/namespaces/vpc/v2/custom_acl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package vpc

import (
"context"
"fmt"
"reflect"

"github.com/scaleway/scaleway-cli/v2/core"
"github.com/scaleway/scaleway-cli/v2/internal/editor"
"github.com/scaleway/scaleway-sdk-go/api/vpc/v2"
"github.com/scaleway/scaleway-sdk-go/scw"
)

var vpcACLEditYamlExample = `default_policy: drop
is_ipv6: false
rules: [
- protocol: TCP
src_port_low: 0
src_port_high: 0
dst_port_low: 80
dst_port_high: 80
source: 0.0.0.0/0
destination: 0.0.0.0/0
description: Allow HTTP traffic from any source
action: accept
- protocol: TCP
src_port_low: 0
src_port_high: 0
dst_port_low: 443
dst_port_high: 443
source: 0.0.0.0/0
destination: 0.0.0.0/0
description: Allow HTTPS traffic from any source
action: accept
]
`

type vpcACLEditArgs struct {
Region scw.Region
VpcID string
IsIPv6 bool
DefaultPolicy vpc.Action
Mode editor.MarshalMode
}

func vpcACLEditCommand() *core.Command {
return &core.Command{
Short: "Edit all ACL rules of a VPC",
Long: editor.LongDescription,
Namespace: "vpc",
Resource: "rule",
Verb: "edit",
ArgsType: reflect.TypeOf(vpcACLEditArgs{}),
ArgSpecs: core.ArgSpecs{
{
Name: "vpc-id",
Short: "ID of the Network ACL's VPC",
Required: true,
Positional: false,
},
{
Name: "is-ipv6",
Short: "Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type",
Required: false,
Positional: false,
},
{
Name: "default-policy",
Short: "Action to take for packets which do not match any rules",
Required: false,
Positional: false,
},
editor.MarshalModeArgSpec(),
core.RegionArgSpec(),
},
Run: func(ctx context.Context, argsI interface{}) (i interface{}, e error) {
args := argsI.(*vpcACLEditArgs)

client := core.ExtractClient(ctx)
api := vpc.NewAPI(client)

setRequest := &vpc.SetACLRequest{
Region: args.Region,
VpcID: args.VpcID,
IsIPv6: args.IsIPv6,
DefaultPolicy: args.DefaultPolicy,
}

rules, err := api.GetACL(&vpc.GetACLRequest{
Region: args.Region,
VpcID: args.VpcID,
IsIPv6: args.IsIPv6,
}, scw.WithContext(ctx))
if err != nil {
return nil, fmt.Errorf("failed to list ACL rules: %w", err)
}

editedSetRequest, err := editor.UpdateResourceEditor(rules, setRequest, &editor.Config{
PutRequest: true,
MarshalMode: args.Mode,
Template: vpcACLEditYamlExample,
})
if err != nil {
return nil, err
}

setRequest = editedSetRequest.(*vpc.SetACLRequest)

resp, err := api.SetACL(setRequest, scw.WithContext(ctx))
if err != nil {
return nil, fmt.Errorf("failed to set ACL rules: %w", err)
}

return resp.Rules, nil
},
}
}
Loading