Skip to content

Commit 1ccedd3

Browse files
committed
Ensure config element in edit-config exists
1 parent bfd8288 commit 1ccedd3

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

client.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,15 @@ func (c *Client) executeRPC(ctx context.Context, req *Req) (Res, error) {
14051405
rpcXML := c.buildEditConfigXML(req)
14061406
scrapligoRes, err = c.driver.RPC(opoptions.WithFilter(rpcXML))
14071407
} else {
1408-
scrapligoRes, err = c.driver.EditConfig(req.Target, req.Config)
1408+
// For standard edit-config, ensure config has <config> wrapper
1409+
// scrapligo's EditConfig expects the caller to provide the config element
1410+
configContent := req.Config
1411+
result := xmldot.Get(req.Config, "config")
1412+
if !result.Exists() {
1413+
// Config doesn't have <config> wrapper, add it
1414+
configContent = "<config>" + req.Config + "</config>"
1415+
}
1416+
scrapligoRes, err = c.driver.EditConfig(req.Target, configContent)
14091417
}
14101418

14111419
case "copy-config":
@@ -1636,6 +1644,11 @@ func (c *Client) parseRPCErrors(responseXML string) []ErrorModel {
16361644
// This method constructs the full edit-config RPC according to RFC 6241 Section 7.2,
16371645
// including optional default-operation, test-option, and error-option elements.
16381646
//
1647+
// Per RFC 6241, the <config> element in edit-config should contain the configuration
1648+
// data directly, not wrapped in another <config> element. If the caller provides
1649+
// configuration with an outer <config> wrapper (e.g., from Body builder), this method
1650+
// extracts the inner content automatically.
1651+
//
16391652
// Uses xmldot for safe XML building with automatic escaping.
16401653
//
16411654
// Returns the complete RPC XML string.
@@ -1661,8 +1674,24 @@ func (c *Client) buildEditConfigXML(req *Req) string {
16611674
xml, _ = xmldot.Set(xml, "edit-config.error-option", req.ErrorOption) //nolint:errcheck // XML building errors caught during validation
16621675
}
16631676

1664-
// Config data (raw XML content)
1665-
xml, _ = xmldot.SetRaw(xml, "edit-config.config", req.Config) //nolint:errcheck // XML building errors caught during validation
1677+
// Extract config content - strip outer <config> wrapper if present
1678+
// Per RFC 6241, edit-config's <config> element should contain the configuration
1679+
// data directly, not wrapped in another <config> element
1680+
configContent := req.Config
1681+
1682+
// Check if user provided <config>...</config> wrapper and extract inner content
1683+
result := xmldot.Get(req.Config, "config")
1684+
if result.Exists() {
1685+
// User provided <config> wrapper (e.g., from Body builder), extract inner XML content
1686+
// Use |@raw modifier to get the raw inner XML without the <config> wrapper
1687+
innerContent := xmldot.Get(req.Config, "config|@raw").String()
1688+
if innerContent != "" {
1689+
configContent = innerContent
1690+
}
1691+
}
1692+
1693+
// Config data (raw XML content without outer <config> wrapper)
1694+
xml, _ = xmldot.SetRaw(xml, "edit-config.config", configContent) //nolint:errcheck // XML building errors caught during validation
16661695

16671696
return xml
16681697
}

client_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ func TestBuildEditConfigXML(t *testing.T) {
483483
expected: []string{
484484
"<edit-config>",
485485
"<target><candidate/></target>",
486-
"<config><config><hostname>router1</hostname></config></config>",
486+
"<config><hostname>router1</hostname></config>",
487487
"</edit-config>",
488488
},
489489
},
@@ -498,7 +498,7 @@ func TestBuildEditConfigXML(t *testing.T) {
498498
"<edit-config>",
499499
"<target><candidate/></target>",
500500
"<default-operation>merge</default-operation>",
501-
"<config><config><hostname>router1</hostname></config></config>",
501+
"<config><hostname>router1</hostname></config>",
502502
"</edit-config>",
503503
},
504504
},
@@ -513,7 +513,7 @@ func TestBuildEditConfigXML(t *testing.T) {
513513
"<edit-config>",
514514
"<target><candidate/></target>",
515515
"<test-option>test-then-set</test-option>",
516-
"<config><config><hostname>router1</hostname></config></config>",
516+
"<config><hostname>router1</hostname></config>",
517517
"</edit-config>",
518518
},
519519
},
@@ -528,7 +528,7 @@ func TestBuildEditConfigXML(t *testing.T) {
528528
"<edit-config>",
529529
"<target><candidate/></target>",
530530
"<error-option>rollback-on-error</error-option>",
531-
"<config><config><hostname>router1</hostname></config></config>",
531+
"<config><hostname>router1</hostname></config>",
532532
"</edit-config>",
533533
},
534534
},
@@ -547,7 +547,7 @@ func TestBuildEditConfigXML(t *testing.T) {
547547
"<default-operation>replace</default-operation>",
548548
"<test-option>test-only</test-option>",
549549
"<error-option>continue-on-error</error-option>",
550-
"<config><config><interface>eth0</interface></config></config>",
550+
"<config><interface>eth0</interface></config>",
551551
"</edit-config>",
552552
},
553553
},

0 commit comments

Comments
 (0)