Skip to content

Commit 18a8bcc

Browse files
Merge pull request #1504 from eggfoobar/fix-fencing-redfish-parsing
OCPBUGS-63543: fix: update redfish url validation
2 parents f93a306 + 219c11f commit 18a8bcc

File tree

2 files changed

+109
-10
lines changed

2 files changed

+109
-10
lines changed

pkg/tnf/pkg/pcs/fencing.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package pcs
33
import (
44
"context"
55
"fmt"
6-
"regexp"
6+
"net/url"
77
"strings"
88

99
corev1 "k8s.io/api/core/v1"
@@ -15,10 +15,6 @@ import (
1515
"github.com/openshift/cluster-etcd-operator/pkg/tnf/pkg/tools"
1616
)
1717

18-
var (
19-
addressRegEx = regexp.MustCompile(`.*//(.*):(.*)(/redfish.*)`)
20-
)
21-
2218
const (
2319
// defaultPcmkDelayBase is the delay applied to the first fence device to prevent simultaneous fencing
2420
defaultPcmkDelayBase = "10s"
@@ -130,12 +126,28 @@ func getFencingConfig(nodeName string, secret *corev1.Secret) (*fencingConfig, e
130126

131127
// we need to parse ip, port and systems uri from the address like this:
132128
// redfish+https://192.168.111.1:8000/redfish/v1/Systems/af2167e4-c13b-4941-b606-f912e9a86f4b
133-
matches := addressRegEx.FindStringSubmatch(address)
134-
if len(matches) != 4 {
129+
parsedUrl, err := url.Parse(address)
130+
if err != nil {
135131
klog.Errorf("Failed to parse redfish address %s", address)
136132
return nil, fmt.Errorf("failed to parse redfish address %s", address)
137133
}
138134

135+
redfishHostname := parsedUrl.Hostname()
136+
redfishPath := parsedUrl.Path
137+
redfishPort := parsedUrl.Port()
138+
// Try to infer standard schema ports for https/http, otherwise notify user port is needed.
139+
if redfishPort == "" {
140+
switch {
141+
case strings.Contains(parsedUrl.Scheme, "https"):
142+
redfishPort = "443"
143+
case strings.Contains(parsedUrl.Scheme, "http"):
144+
redfishPort = "80"
145+
default:
146+
klog.Errorf("Failed to parse redfish address, no port number found %s", address)
147+
return nil, fmt.Errorf("failed to parse redfish address, no port number found %s", address)
148+
}
149+
}
150+
139151
username := string(secret.Data["username"])
140152
if username == "" {
141153
klog.Errorf("Secret %s does not contain username", secret.Name)
@@ -159,9 +171,9 @@ func getFencingConfig(nodeName string, secret *corev1.Secret) (*fencingConfig, e
159171
FencingID: fmt.Sprintf("%s_%s", nodeName, "redfish"),
160172
FencingDeviceType: "fence_redfish",
161173
FencingDeviceOptions: map[fencingOption]string{
162-
Ip: matches[1],
163-
IpPort: matches[2],
164-
SystemsUri: matches[3],
174+
Ip: redfishHostname,
175+
IpPort: redfishPort,
176+
SystemsUri: redfishPath,
165177
Username: username,
166178
Password: password,
167179
},

pkg/tnf/pkg/pcs/fencing_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,81 @@ func TestGetFencingConfig(t *testing.T) {
6565
},
6666
},
6767
},
68+
{
69+
name: "valid redfish config without port number on https",
70+
nodeName: "node1",
71+
secret: &corev1.Secret{
72+
Data: map[string][]byte{
73+
"address": []byte("redfish+https://192.168.111.1/redfish/v1/Systems/abc"),
74+
"username": []byte("admin"),
75+
"password": []byte("pass123"),
76+
"certificateVerification": []byte("Enabled"),
77+
},
78+
},
79+
wantErr: false,
80+
expectedCfg: &fencingConfig{
81+
NodeName: "node1",
82+
FencingID: "node1_redfish",
83+
FencingDeviceType: "fence_redfish",
84+
FencingDeviceOptions: map[fencingOption]string{
85+
Ip: "192.168.111.1",
86+
IpPort: "443",
87+
SystemsUri: "/redfish/v1/Systems/abc",
88+
Username: "admin",
89+
Password: "pass123",
90+
},
91+
},
92+
},
93+
{
94+
name: "valid redfish config without port number on http",
95+
nodeName: "node1",
96+
secret: &corev1.Secret{
97+
Data: map[string][]byte{
98+
"address": []byte("redfish+http://192.168.111.1/redfish/v1/Systems/abc"),
99+
"username": []byte("admin"),
100+
"password": []byte("pass123"),
101+
"certificateVerification": []byte("Enabled"),
102+
},
103+
},
104+
wantErr: false,
105+
expectedCfg: &fencingConfig{
106+
NodeName: "node1",
107+
FencingID: "node1_redfish",
108+
FencingDeviceType: "fence_redfish",
109+
FencingDeviceOptions: map[fencingOption]string{
110+
Ip: "192.168.111.1",
111+
IpPort: "80",
112+
SystemsUri: "/redfish/v1/Systems/abc",
113+
Username: "admin",
114+
Password: "pass123",
115+
},
116+
},
117+
},
118+
{
119+
name: "valid redfish config without port number on http ipv6",
120+
nodeName: "node1",
121+
secret: &corev1.Secret{
122+
Data: map[string][]byte{
123+
"address": []byte("redfish+http://[0000:0000:0000::0000]/redfish/v1/Systems/abc"),
124+
"username": []byte("admin"),
125+
"password": []byte("pass123"),
126+
"certificateVerification": []byte("Enabled"),
127+
},
128+
},
129+
wantErr: false,
130+
expectedCfg: &fencingConfig{
131+
NodeName: "node1",
132+
FencingID: "node1_redfish",
133+
FencingDeviceType: "fence_redfish",
134+
FencingDeviceOptions: map[fencingOption]string{
135+
Ip: "0000:0000:0000::0000",
136+
IpPort: "80",
137+
SystemsUri: "/redfish/v1/Systems/abc",
138+
Username: "admin",
139+
Password: "pass123",
140+
},
141+
},
142+
},
68143
{
69144
name: "invalid address format",
70145
nodeName: "node1",
@@ -102,6 +177,18 @@ func TestGetFencingConfig(t *testing.T) {
102177
},
103178
wantErr: true,
104179
},
180+
{
181+
name: "missing port and no schema provided",
182+
nodeName: "node1",
183+
secret: &corev1.Secret{
184+
Data: map[string][]byte{
185+
"address": []byte("192.168.111.1/redfish/v1/Systems/abc"),
186+
"username": []byte("admin"),
187+
"certificateVerification": []byte("Disabled"),
188+
},
189+
},
190+
wantErr: true,
191+
},
105192
}
106193

107194
for _, tt := range tests {

0 commit comments

Comments
 (0)