Skip to content

feat: add IP firewall (Edge Firewall) management commands#159

Open
pablotoledo wants to merge 1 commit intoovh:mainfrom
pablotoledo:main
Open

feat: add IP firewall (Edge Firewall) management commands#159
pablotoledo wants to merge 1 commit intoovh:mainfrom
pablotoledo:main

Conversation

@pablotoledo
Copy link

Summary

  • Implement full lifecycle management for OVHcloud IP Edge Firewall under ovhcloud ip firewall
  • Commands: firewall list/add/get/enable/disable/delete and firewall rule list/get/create/delete
  • Supports --from-file, --init-file, and --editor for rule create (>5 params requirement)

Changes

  • internal/services/ip/firewall.go — service layer (10 functions, FirewallRuleCreateExample, --from-file/pipe support)
  • internal/services/ip/templates/firewall.tmpl — display template for firewall get
  • internal/services/ip/templates/firewall_rule.tmpl — display template for rule get
  • internal/cmd/ip.go — firewall+rule command tree with all required flags
  • internal/cmd/ip_firewall_test.go — 13 unit tests using RFC 5737 documentation IPs
  • README.md — added ip firewall to Available Products table
  • doc/ — 12 generated doc pages via make doc

Checklist

  • Service code isolated in internal/services
  • Command code in internal/cmd
  • rule create (>5 params) supports --editor, --from-file, --init-file
  • --from-file and --editor are mutually exclusive
  • Docs regenerated via make doc
  • Tests added and passing (go test ./...)
  • make build succeeds
  • Signed-off-by trailer present (DCO)
  • Test IPs use RFC 5737 documentation ranges

Signed-off-by: pablotoledo jptgjuanpablo@gmail.com

Implement full lifecycle management for OVHcloud IP firewall (AntiDDoS/
Edge Firewall) under the `ovhcloud ip firewall` command tree:

- ip firewall list/add/get/enable/disable/delete
- ip firewall rule list/get/create/delete

Includes service layer, display templates, command registration,
tests with RFC 5737 documentation IPs, and generated doc pages.

Signed-off-by: pablotoledo <jptgjuanpablo@gmail.com>
@pablotoledo pablotoledo requested a review from a team as a code owner March 4, 2026 09:34
@pablotoledo
Copy link
Author

Hi everyone!

This is a small contribution to solve a use case I need to automate some port firewall rules in VPS I have deployed, it would be nice to avoid the ovh portal or the API scripts for some support activities I have to do.

@pablotoledo
Copy link
Author

@amstuta ?

@amstuta
Copy link
Collaborator

amstuta commented Mar 13, 2026

Yes sorry for the lag @pablotoledo and thanks for your contribution, I'll review quickly !

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds ovhcloud ip firewall command group to manage OVHcloud IP Edge Firewall resources and rules, including service-layer API calls, CLI wiring, display templates, docs, and tests.

Changes:

  • Introduces IP firewall and firewall rule service functions (list/add/get/enable/disable/delete + rule list/get/create/delete).
  • Adds CLI command tree and flags for firewall/rule management (including parameter file/editor modes for rule creation).
  • Adds display templates, unit tests, and regenerates documentation/README product listing.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
internal/services/ip/firewall.go Implements firewall + rule lifecycle API calls and rule creation input handling.
internal/services/ip/templates/firewall.tmpl Adds human-readable output template for ip firewall get.
internal/services/ip/templates/firewall_rule.tmpl Adds human-readable output template for ip firewall rule get.
internal/cmd/ip.go Registers ip firewall / ip firewall rule commands and flags.
internal/cmd/ip_firewall_test.go Adds unit tests covering firewall and rule commands (notably --from-file).
README.md Marks ip firewall as available in the products table.
doc/ovhcloud_ip_firewall.md Generated docs for ovhcloud ip firewall.
doc/ovhcloud_ip_firewall_add.md Generated docs for ovhcloud ip firewall add.
doc/ovhcloud_ip_firewall_delete.md Generated docs for ovhcloud ip firewall delete.
doc/ovhcloud_ip_firewall_disable.md Generated docs for ovhcloud ip firewall disable.
doc/ovhcloud_ip_firewall_enable.md Generated docs for ovhcloud ip firewall enable.
doc/ovhcloud_ip_firewall_get.md Generated docs for ovhcloud ip firewall get.
doc/ovhcloud_ip_firewall_list.md Generated docs for ovhcloud ip firewall list.
doc/ovhcloud_ip_firewall_rule.md Generated docs for ovhcloud ip firewall rule.
doc/ovhcloud_ip_firewall_rule_create.md Generated docs for ovhcloud ip firewall rule create.
doc/ovhcloud_ip_firewall_rule_delete.md Generated docs for ovhcloud ip firewall rule delete.
doc/ovhcloud_ip_firewall_rule_get.md Generated docs for ovhcloud ip firewall rule get.
doc/ovhcloud_ip_firewall_rule_list.md Generated docs for ovhcloud ip firewall rule list.
doc/ovhcloud_ip.md Links the new firewall command in the IP command index.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +257 to +274
if cmd.Flags().Changed("destination-port") {
body["destinationPort"] = FirewallRuleSpec.DestinationPort
}
if cmd.Flags().Changed("destination-port-from") || cmd.Flags().Changed("destination-port-to") {
body["destinationPortRange"] = map[string]int{
"from": FirewallRuleSpec.DestinationPortFrom,
"to": FirewallRuleSpec.DestinationPortTo,
}
}
if cmd.Flags().Changed("source-port") {
body["sourcePort"] = FirewallRuleSpec.SourcePort
}
if cmd.Flags().Changed("source-port-from") || cmd.Flags().Changed("source-port-to") {
body["sourcePortRange"] = map[string]int{
"from": FirewallRuleSpec.SourcePortFrom,
"to": FirewallRuleSpec.SourcePortTo,
}
}
Comment on lines +360 to +372
body["destinationPortRange"] = map[string]int{
"from": FirewallRuleSpec.DestinationPortFrom,
"to": FirewallRuleSpec.DestinationPortTo,
}
}

if cmd.Flags().Changed("source-port") {
body["sourcePort"] = FirewallRuleSpec.SourcePort
} else if cmd.Flags().Changed("source-port-from") || cmd.Flags().Changed("source-port-to") {
body["sourcePortRange"] = map[string]int{
"from": FirewallRuleSpec.SourcePortFrom,
"to": FirewallRuleSpec.SourcePortTo,
}
Comment on lines +185 to +193
ipFirewallRuleCreateCmd.Flags().IntVar(&ip.FirewallRuleSpec.DestinationPortFrom, "destination-port-from", 0, "Destination port range start (mutually exclusive with --destination-port)")
ipFirewallRuleCreateCmd.Flags().IntVar(&ip.FirewallRuleSpec.DestinationPortTo, "destination-port-to", 0, "Destination port range end")
ipFirewallRuleCreateCmd.Flags().IntVar(&ip.FirewallRuleSpec.SourcePort, "source-port", 0, "Source port (TCP/UDP only)")
ipFirewallRuleCreateCmd.Flags().IntVar(&ip.FirewallRuleSpec.SourcePortFrom, "source-port-from", 0, "Source port range start (mutually exclusive with --source-port)")
ipFirewallRuleCreateCmd.Flags().IntVar(&ip.FirewallRuleSpec.SourcePortTo, "source-port-to", 0, "Source port range end")
ipFirewallRuleCreateCmd.Flags().BoolVar(&ip.FirewallRuleSpec.TCPFragments, "tcp-fragments", false, "TCP fragments option")
ipFirewallRuleCreateCmd.Flags().StringVar(&ip.FirewallRuleSpec.TCPOption, "tcp-option", "", "TCP option: established or syn (TCP only)")
ipFirewallRuleCreateCmd.MarkFlagsMutuallyExclusive("destination-port", "destination-port-from")
ipFirewallRuleCreateCmd.MarkFlagsMutuallyExclusive("source-port", "source-port-from")
Comment on lines +219 to +223
// If --from-file or pipe: load base params, merge explicit CLI flags on top, POST directly
usingFile := flags.ParametersFile != "" || utils.IsInputFromPipe()
if usingFile {
var fileData []byte
var err error
Comment on lines +4 to +8
| Key | Value |
| -------------- | ------------------------------------- |
| IP on Firewall | {{index .Result "ipOnFirewall"}} |
| Enabled | {{index .Result "enabled"}} |
| State | {{index .Result "state"}} |
Comment on lines +4 to +18
| Key | Value |
| ---------------- | ------------------------------------------ |
| Sequence | {{index .Result "sequence"}} |
| Action | {{index .Result "action"}} |
| Protocol | {{index .Result "protocol"}} |
| Source | {{index .Result "source"}} |
| Destination | {{index .Result "destination"}} |
| Destination Port | {{index .Result "destinationPort"}} |
| Source Port | {{index .Result "sourcePort"}} |
| Rule | {{index .Result "rule"}} |
| State | {{index .Result "state"}} |
| Creation Date | {{index .Result "creationDate"}} |
| TCP Option | {{index .Result "tcpOption"}} |
| Fragments | {{index .Result "fragments"}} |
| L3 Packet Length | {{index .Result "l3PacketLength"}} |
Comment on lines +219 to +223
// If --from-file or pipe: load base params, merge explicit CLI flags on top, POST directly
usingFile := flags.ParametersFile != "" || utils.IsInputFromPipe()
if usingFile {
var fileData []byte
var err error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants