5
5
package smc
6
6
7
7
import (
8
- "encoding/json"
8
+ "net/http"
9
+ "net/http/httptest"
10
+ "strings"
9
11
"testing"
10
12
11
- "github.com/stmcginnis/gofish/redfish"
13
+ "github.com/stmcginnis/gofish"
14
+ "github.com/stmcginnis/gofish/common"
12
15
)
13
16
17
+ const serviceRootBody = `{
18
+ "@odata.type": "#ServiceRoot.v1_9_0.ServiceRoot",
19
+ "@odata.id": "/redfish/v1",
20
+ "Id": "ServiceRoot",
21
+ "Name": "Root Service",
22
+ "RedfishVersion": "1.11.0",
23
+ "UUID": "00000000-0000-0000-0000-3CECEFE32D23",
24
+ "Systems": {
25
+ "@odata.id": "/redfish/v1/Systems"
26
+ },
27
+ "Chassis": {
28
+ "@odata.id": "/redfish/v1/Chassis"
29
+ },
30
+ "Managers": {
31
+ "@odata.id": "/redfish/v1/Managers"
32
+ },
33
+ "Tasks": {
34
+ "@odata.id": "/redfish/v1/TaskService"
35
+ },
36
+ "SessionService": {
37
+ "@odata.id": "/redfish/v1/SessionService"
38
+ },
39
+ "AccountService": {
40
+ "@odata.id": "/redfish/v1/AccountService"
41
+ },
42
+ "EventService": {
43
+ "@odata.id": "/redfish/v1/EventService"
44
+ },
45
+ "UpdateService": {
46
+ "@odata.id": "/redfish/v1/UpdateService"
47
+ },
48
+ "CertificateService": {
49
+ "@odata.id": "/redfish/v1/CertificateService"
50
+ },
51
+ "Registries": {
52
+ "@odata.id": "/redfish/v1/Registries"
53
+ },
54
+ "JsonSchemas": {
55
+ "@odata.id": "/redfish/v1/JsonSchemas"
56
+ },
57
+ "TelemetryService": {
58
+ "@odata.id": "/redfish/v1/TelemetryService"
59
+ },
60
+ "Product": null,
61
+ "Links": {
62
+ "Sessions": {
63
+ "@odata.id": "/redfish/v1/SessionService/Sessions"
64
+ }
65
+ },
66
+ "Oem": {
67
+ "Supermicro": {
68
+ "DumpService": {
69
+ "@odata.id": "/redfish/v1/Oem/Supermicro/DumpService"
70
+ }
71
+ }
72
+ },
73
+ "ProtocolFeaturesSupported": {
74
+ "FilterQuery": true,
75
+ "SelectQuery": true,
76
+ "ExcerptQuery": false,
77
+ "OnlyMemberQuery": false,
78
+ "DeepOperations": {
79
+ "DeepPATCH": false,
80
+ "DeepPOST": false,
81
+ "MaxLevels": 1
82
+ },
83
+ "ExpandQuery": {
84
+ "Links": true,
85
+ "NoLinks": true,
86
+ "ExpandAll": true,
87
+ "Levels": true,
88
+ "MaxLevels": 2
89
+ }
90
+ },
91
+ "@odata.etag": "\"1a10733cff76c5506e6903b25ab88e55\""
92
+ }`
93
+
14
94
var updateServiceBody = `{
15
95
"@odata.type": "#UpdateService.v1_8_4.UpdateService",
16
96
"@odata.id": "/redfish/v1/UpdateService",
@@ -56,16 +136,123 @@ var updateServiceBody = `{
56
136
"@odata.etag": "\"e9b94401dae9992fef2e71ef30cbcfdc\""
57
137
}`
58
138
139
+ const smcSSLCertBody = `{
140
+ "@odata.type": "#SSLCert.v1_0_0.SSLCert",
141
+ "@odata.id": "/redfish/v1/UpdateService/Oem/Supermicro/SSLCert",
142
+ "Id": "SSLCert",
143
+ "Name": "SSLCert",
144
+ "VaildFrom": "Oct 9 11:15:00 2024 GMT",
145
+ "GoodTHRU": "Oct 9 11:15:00 2025 GMT",
146
+ "Actions": {
147
+ "#SmcSSLCert.Upload": {
148
+ "target": "/redfish/v1/UpdateService/Oem/Supermicro/SSLCert/Actions/SmcSSLCert.Upload",
149
+
150
+ "cert_file",
151
+ "key_file"
152
+ ]
153
+ }
154
+ },
155
+ "@odata.etag": "\"e4be24decdd8b293984fb26e1a78e62a\""
156
+ }`
157
+
158
+ const smcSSLCertUploadResponse = `{
159
+ "Success": {
160
+ "code": "Base.v1_10_3.Success",
161
+ "message": "Successfully Completed Request. See ExtendedInfo for more information.",
162
+ "@Message.ExtendedInfo": [
163
+ {
164
+ "MessageId": "SMC.1.0.OemSslcertUploaded",
165
+ "Severity": "OK",
166
+ "Resolution": "No resolution was required.",
167
+ "Message": "SSL certificate and private key were successfully uploaded.",
168
+ "MessageArgs": [
169
+ ""
170
+ ],
171
+ "RelatedProperties": [
172
+ ""
173
+ ]
174
+ }
175
+ ]
176
+ }
177
+ }`
178
+
179
+ const sslCertFile = `-----BEGIN CERTIFICATE-----
180
+ MIIDpDCCAoygAwIBAgIUIf
181
+ -----END CERTIFICATE-----`
182
+
183
+ //nolint:gosec
184
+ const sslKeyFile = `-----BEGIN RSA PRIVATE KEY-----
185
+ MIIEpAIBAAKCAQEAz
186
+ -----END RSA PRIVATE KEY-----`
187
+
59
188
// TestSmcUpdateService tests the parsing of the UpdateService oem field
60
189
func TestSmcUpdateService (t * testing.T ) {
61
- us := & redfish.UpdateService {}
62
- if err := json .Unmarshal ([]byte (updateServiceBody ), us ); err != nil {
63
- t .Fatalf ("error decoding json: %v" , err )
190
+ const redfishBaseURL = "/redfish/v1/"
191
+ var (
192
+ c common.Client
193
+ err error
194
+ requestCounter int // this counter is used to verify that the received requests are in the expected order
195
+ )
196
+
197
+ // Start a local HTTP server
198
+ server := httptest .NewServer (http .HandlerFunc (func (rw http.ResponseWriter , req * http.Request ) {
199
+ if req .Method == http .MethodGet &&
200
+ req .URL .String () == redfishBaseURL &&
201
+ requestCounter < 2 { // ServiceRoot
202
+ contentType := req .Header .Get ("Content-Type" )
203
+ if contentType != "application/json" {
204
+ t .Errorf ("gofish connect sent wrong header. Content-Type:" +
205
+ " is %v and not expected application/json" , contentType )
206
+ }
207
+
208
+ requestCounter ++
209
+
210
+ // Send response to be tested
211
+ rw .WriteHeader (http .StatusOK )
212
+ rw .Header ().Set ("Content-Type" , "application/json" )
213
+
214
+ rw .Write ([]byte (serviceRootBody )) //nolint:errcheck
215
+ } else if req .Method == http .MethodGet && // Get event service
216
+ req .URL .String () == "/redfish/v1/UpdateService" &&
217
+ requestCounter == 2 {
218
+ requestCounter ++
219
+ rw .Write ([]byte (updateServiceBody )) //nolint:errcheck
220
+ } else if req .Method == http .MethodGet &&
221
+ req .URL .String () == "/redfish/v1/UpdateService/Oem/Supermicro/SSLCert" &&
222
+ requestCounter == 3 {
223
+ requestCounter ++
224
+ rw .Write ([]byte (smcSSLCertBody )) //nolint:errcheck
225
+ } else if req .Method == http .MethodPost && // SubmitTestEvent
226
+ req .URL .String () == "/redfish/v1/UpdateService/Oem/Supermicro/SSLCert/Actions/SmcSSLCert.Upload" &&
227
+ requestCounter == 4 {
228
+ // TODO: Actually check if the request body is correct
229
+ requestCounter ++
230
+ rw .Write ([]byte (smcSSLCertUploadResponse )) //nolint:errcheck
231
+ } else {
232
+ t .Errorf ("mock got unexpected %v request to path %v while request counter is %v" ,
233
+ req .Method , req .URL .String (), requestCounter )
234
+ }
235
+ }))
236
+
237
+ // Close the server when test finishes
238
+ defer server .Close ()
239
+
240
+ c , err = gofish .Connect (gofish.ClientConfig {Endpoint : server .URL , HTTPClient : server .Client ()})
241
+ if err != nil {
242
+ t .Errorf ("failed to establish client to mock http server due to: %v" , err )
64
243
}
65
244
66
- updateService , err := FromUpdateService (us )
245
+ serviceRoot , err := gofish .ServiceRoot (c )
246
+ if err != nil {
247
+ t .Errorf ("failed to get redfish service root due to: %v" , err )
248
+ }
249
+ origUpdateService , err := serviceRoot .UpdateService ()
250
+ if err != nil {
251
+ t .Errorf ("failed to get update service due to: %v" , err )
252
+ }
253
+ updateService , err := FromUpdateService (origUpdateService )
67
254
if err != nil {
68
- t .Fatalf ("error getting oem object: %v" , err )
255
+ t .Errorf ("error getting OEM object: %v" , err )
69
256
}
70
257
71
258
if updateService .ID != "UpdateService" {
@@ -83,4 +270,14 @@ func TestSmcUpdateService(t *testing.T) {
83
270
if updateService .ipmiConfig != "/redfish/v1/UpdateService/Oem/Supermicro/IPMIConfig" {
84
271
t .Errorf ("unexpected ipmi config link: %s" , updateService .installTarget )
85
272
}
273
+
274
+ cert , err := updateService .SSLCert ()
275
+ if err != nil {
276
+ t .Errorf ("Failed to get SSL certificate due to: %v" , err )
277
+ }
278
+
279
+ err = cert .Upload (strings .NewReader (sslCertFile ), strings .NewReader (sslKeyFile ))
280
+ if err != nil {
281
+ t .Errorf ("Failed to upload SSL certificate due to: %v" , err )
282
+ }
86
283
}
0 commit comments