Skip to content

Commit 0f0201a

Browse files
committed
fix: vapi - special param encoding for edge cluster lookup
1 parent fd21c74 commit 0f0201a

File tree

5 files changed

+61
-4
lines changed

5 files changed

+61
-4
lines changed

govc/USAGE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3721,6 +3721,7 @@ Examples:
37213721
-cluster "Workload-Cluster" \
37223722
-service-cidr 10.96.0.0/23 \
37233723
-pod-cidrs 10.244.0.0/20 \
3724+
-control-plane-dns 10.10.10.10 \
37243725
-control-plane-dns-names wcp.example.com \
37253726
-workload-network.egress-cidrs 10.0.0.128/26 \
37263727
-workload-network.ingress-cidrs "10.0.0.64/26" \

govc/namespace/cluster/enable.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ Examples:
154154
-cluster "Workload-Cluster" \
155155
-service-cidr 10.96.0.0/23 \
156156
-pod-cidrs 10.244.0.0/20 \
157+
-control-plane-dns 10.10.10.10 \
157158
-control-plane-dns-names wcp.example.com \
158159
-workload-network.egress-cidrs 10.0.0.128/26 \
159160
-workload-network.ingress-cidrs "10.0.0.64/26" \
@@ -243,7 +244,7 @@ func (cmd *enableCluster) Run(ctx context.Context, f *flag.FlagSet) error {
243244
edgeClusterDisplayName := cmd.NcpClusterNetworkSpec.NsxEdgeCluster
244245
edgeClusters, err := m.ListCompatibleEdgeClusters(ctx, clusterId, switchId)
245246
if err != nil {
246-
return fmt.Errorf("error in compatible switch lookup: %s", err)
247+
return fmt.Errorf("error in compatible edge cluster lookup: %s", err)
247248
}
248249

249250
matchingEdgeClusters := make([]string, 0)

vapi/namespace/namespace.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ type EdgeClusterCompatibilitySummary struct {
188188
func (c *Manager) ListCompatibleEdgeClusters(ctx context.Context, clusterId string, switchId string) (result []EdgeClusterCompatibilitySummary, err error) {
189189
listUrl := c.Resource(internal.NamespaceEdgeClusterCompatibility).
190190
WithParam("cluster", clusterId).
191-
WithParam("distributed_switch", switchId).
192-
WithParam("compatible", "true")
191+
WithParam("compatible", "true").
192+
WithPathEncodedParam("distributed_switch", switchId)
193193
return result, c.Do(ctx, listUrl.Request(http.MethodGet), &result)
194194
}

vapi/rest/resource.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,36 @@ func (r *Resource) WithAction(action string) *Resource {
5151
// WithParam adds one parameter on the URL.RawQuery
5252
func (r *Resource) WithParam(name string, value string) *Resource {
5353
// ParseQuery handles empty case, and we control access to query string so shouldn't encounter an error case
54-
params, _ := url.ParseQuery(r.u.RawQuery)
54+
params, err := url.ParseQuery(r.u.RawQuery)
55+
if err != nil {
56+
panic(err)
57+
}
5558
params[name] = append(params[name], value)
5659
r.u.RawQuery = params.Encode()
5760
return r
5861
}
5962

63+
// WithPathEncodedParam appends a parameter on the URL.RawQuery,
64+
// For special cases where URL Path-style encoding is needed
65+
func (r *Resource) WithPathEncodedParam(name string, value string) *Resource {
66+
t := &url.URL{Path: value}
67+
encodedValue := t.String()
68+
t = &url.URL{Path: name}
69+
encodedName := t.String()
70+
// ParseQuery handles empty case, and we control access to query string so shouldn't encounter an error case
71+
params, err := url.ParseQuery(r.u.RawQuery)
72+
if err != nil {
73+
panic(err)
74+
}
75+
// Values.Encode() doesn't escape exactly how we want, so we need to build the query string ourselves
76+
if len(params) >= 1 {
77+
r.u.RawQuery = r.u.RawQuery + "&" + encodedName + "=" + encodedValue
78+
} else {
79+
r.u.RawQuery = r.u.RawQuery + encodedName + "=" + encodedValue
80+
}
81+
return r
82+
}
83+
6084
// Request returns a new http.Request for the given method.
6185
// An optional body can be provided for POST and PATCH methods.
6286
func (r *Resource) Request(method string, body ...interface{}) *http.Request {

vapi/rest/resource_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,34 @@ func TestResource_WithParam(t *testing.T) {
5151
}
5252
})
5353
}
54+
55+
func TestResource_WithPathEncodedParam(t *testing.T) {
56+
simulator.Test(func(ctx context.Context, vc *vim25.Client) {
57+
c := rest.NewClient(vc)
58+
59+
// path is correctly formatted when Path-Encoded param is first
60+
url := c.Resource("api/some/resource").
61+
WithPathEncodedParam("key1", "value 1")
62+
expectedPath := "api/some/resource?key1=value%201"
63+
if !strings.Contains(url.String(), expectedPath) {
64+
t.Errorf("First path-encoded param incorrectly added to resource, URL %q, expected path %q", url.String(), expectedPath)
65+
}
66+
67+
// path is correctly formatted when Path-Encoded param is last
68+
url = c.Resource("api/some/resource").
69+
WithParam("key1", "value 1").
70+
WithPathEncodedParam("key2", "value 2")
71+
expectedPath = "api/some/resource?key1=value+1&key2=value%202"
72+
if !strings.Contains(url.String(), expectedPath) {
73+
t.Errorf("Last path-encoded param incorrectly added to resource, URL %q, expected path %q", url.String(), expectedPath)
74+
}
75+
76+
// if WithParam is used again, it will re-encode the Path-Encoded value
77+
url = url.WithParam("key3", "value 3")
78+
expectedPath = "api/some/resource?key1=value+1&key2=value+2&key3=value+3"
79+
if !strings.Contains(url.String(), expectedPath) {
80+
t.Errorf("Middle path-encoded param not endcoded as expected, URL %q, expected path %q", url.String(), expectedPath)
81+
}
82+
83+
})
84+
}

0 commit comments

Comments
 (0)