github.com/sacloud/iaas-api-go@v1.12.0/test/server_op_test.go (about) 1 // Copyright 2022-2023 The sacloud/iaas-api-go Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package test 16 17 import ( 18 "errors" 19 "testing" 20 21 "github.com/sacloud/iaas-api-go" 22 "github.com/sacloud/iaas-api-go/helper/power" 23 "github.com/sacloud/iaas-api-go/search" 24 "github.com/sacloud/iaas-api-go/search/keys" 25 "github.com/sacloud/iaas-api-go/testutil" 26 "github.com/sacloud/iaas-api-go/types" 27 "github.com/sacloud/packages-go/size" 28 "github.com/stretchr/testify/assert" 29 ) 30 31 func TestServerOp_CRUD(t *testing.T) { 32 testutil.RunCRUD(t, &testutil.CRUDTestCase{ 33 Parallel: true, 34 35 SetupAPICallerFunc: singletonAPICaller, 36 37 Create: &testutil.CRUDTestFunc{ 38 Func: testServerCreate, 39 CheckFunc: testutil.AssertEqualWithExpected(&testutil.CRUDTestExpect{ 40 ExpectValue: createServerExpected, 41 IgnoreFields: ignoreServerFields, 42 }), 43 }, 44 45 Read: &testutil.CRUDTestFunc{ 46 Func: testServerRead, 47 CheckFunc: testutil.AssertEqualWithExpected(&testutil.CRUDTestExpect{ 48 ExpectValue: createServerExpected, 49 IgnoreFields: ignoreServerFields, 50 }), 51 }, 52 53 Updates: []*testutil.CRUDTestFunc{ 54 { 55 Func: testServerUpdate, 56 CheckFunc: testutil.AssertEqualWithExpected(&testutil.CRUDTestExpect{ 57 ExpectValue: updateServerExpected, 58 IgnoreFields: ignoreServerFields, 59 }), 60 }, 61 { 62 Func: testServerUpdateToMin, 63 CheckFunc: testutil.AssertEqualWithExpected(&testutil.CRUDTestExpect{ 64 ExpectValue: updateServerToMinExpected, 65 IgnoreFields: ignoreServerFields, 66 }), 67 }, 68 // Insert CDROM 69 { 70 Func: func(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 71 cdOp := iaas.NewCDROMOp(caller) 72 serverOp := iaas.NewServerOp(caller) 73 74 // find cdrom 75 searched, err := cdOp.Find(ctx, testZone, &iaas.FindCondition{ 76 Filter: search.Filter{ 77 search.Key(keys.Scope): types.Scopes.Shared.String(), 78 }, 79 Count: 1, 80 }) 81 if err != nil { 82 return nil, err 83 } 84 cdromID := searched.CDROMs[0].ID 85 ctx.Values["server/cdrom"] = cdromID 86 87 // insert 88 if err := serverOp.InsertCDROM(ctx, testZone, ctx.ID, &iaas.InsertCDROMRequest{ID: cdromID}); err != nil { 89 return nil, err 90 } 91 return serverOp.Read(ctx, testZone, ctx.ID) 92 }, 93 CheckFunc: func(t testutil.TestT, ctx *testutil.CRUDTestContext, v interface{}) error { 94 server := v.(*iaas.Server) 95 return testutil.AssertFalse(t, server.CDROMID.IsEmpty(), "Server.CDROMID") 96 }, 97 SkipExtractID: true, 98 }, 99 // Eject CDROM 100 { 101 Func: func(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 102 serverOp := iaas.NewServerOp(caller) 103 cdromID := ctx.Values["server/cdrom"].(types.ID) 104 105 if err := serverOp.EjectCDROM(ctx, testZone, ctx.ID, &iaas.EjectCDROMRequest{ID: cdromID}); err != nil { 106 return nil, err 107 } 108 return serverOp.Read(ctx, testZone, ctx.ID) 109 }, 110 CheckFunc: func(t testutil.TestT, ctx *testutil.CRUDTestContext, v interface{}) error { 111 server := v.(*iaas.Server) 112 return testutil.AssertTrue(t, server.CDROMID.IsEmpty(), "Server.CDROMID") 113 }, 114 SkipExtractID: true, 115 }, 116 // VNC Info 117 { 118 Func: func(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 119 serverOp := iaas.NewServerOp(caller) 120 return serverOp.GetVNCProxy(ctx, testZone, ctx.ID) 121 }, 122 CheckFunc: func(t testutil.TestT, ctx *testutil.CRUDTestContext, v interface{}) error { 123 vnc := v.(*iaas.VNCProxyInfo) 124 return testutil.DoAsserts( 125 testutil.AssertNotNilFunc(t, vnc, "VNCProxyInfo"), 126 testutil.AssertNotEmptyFunc(t, vnc.Status, "VNCProxyInfo.Status"), 127 testutil.AssertNotEmptyFunc(t, vnc.Host, "VNCProxyInfo.Host"), 128 testutil.AssertNotEmptyFunc(t, vnc.IOServerHost, "VNCProxyInfo.IOServerHost"), 129 testutil.AssertNotEmptyFunc(t, vnc.Port, "VNCProxyInfo.Port"), 130 testutil.AssertNotEmptyFunc(t, vnc.Password, "VNCProxyInfo.Password"), 131 testutil.AssertNotEmptyFunc(t, vnc.VNCFile, "VNCProxyInfo.VNCFile"), 132 ) 133 }, 134 SkipExtractID: true, 135 }, 136 }, 137 138 Shutdown: func(ctx *testutil.CRUDTestContext, caller iaas.APICaller) error { 139 client := iaas.NewServerOp(caller) 140 return power.ShutdownServer(ctx, client, testZone, ctx.ID, true) 141 }, 142 143 Delete: &testutil.CRUDTestDeleteFunc{ 144 Func: testServerDelete, 145 }, 146 }) 147 } 148 149 var ( 150 ignoreServerFields = []string{ 151 "ID", 152 "Availability", 153 "ServerPlanID", 154 "ServerPlanName", 155 "ServerPlanCPUModel", 156 "ServerPlanGeneration", 157 "ServerPlanCommitment", 158 "Zone", 159 "HostName", 160 "InstanceHostName", 161 "InstanceHostInfoURL", 162 "InstanceStatus", 163 "InstanceBeforeStatus", 164 "InstanceStatusChangedAt", 165 "InstanceWarnings", 166 "InstanceWarningsValue", 167 "Disks", 168 "Interfaces", 169 "PrivateHostID", 170 "PrivateHostName", 171 "BundleInfo", 172 "CreatedAt", 173 "ModifiedAt", 174 } 175 createServerParam = &iaas.ServerCreateRequest{ 176 CPU: 1, 177 MemoryMB: 1 * size.GiB, 178 ConnectedSwitches: []*iaas.ConnectedSwitch{ 179 { 180 Scope: types.Scopes.Shared, 181 }, 182 }, 183 InterfaceDriver: types.InterfaceDrivers.VirtIO, 184 Name: testutil.ResourceName("server"), 185 Description: "desc", 186 Tags: []string{"tag1", "tag2"}, 187 WaitDiskMigration: false, 188 } 189 createServerExpected = &iaas.Server{ 190 Name: createServerParam.Name, 191 Description: createServerParam.Description, 192 Tags: createServerParam.Tags, 193 InterfaceDriver: createServerParam.InterfaceDriver, 194 CPU: createServerParam.CPU, 195 MemoryMB: createServerParam.MemoryMB, 196 } 197 updateServerParam = &iaas.ServerUpdateRequest{ 198 Name: testutil.ResourceName("server-upd"), 199 Tags: []string{"tag1-upd", "tag2-upd"}, 200 Description: "desc-upd", 201 IconID: testIconID, 202 InterfaceDriver: types.InterfaceDrivers.VirtIO, 203 } 204 updateServerExpected = &iaas.Server{ 205 Name: updateServerParam.Name, 206 Description: updateServerParam.Description, 207 Tags: updateServerParam.Tags, 208 InterfaceDriver: updateServerParam.InterfaceDriver, 209 CPU: createServerParam.CPU, 210 MemoryMB: createServerParam.MemoryMB, 211 IconID: testIconID, 212 } 213 updateServerToMinParam = &iaas.ServerUpdateRequest{ 214 Name: testutil.ResourceName("server-to-min"), 215 InterfaceDriver: types.InterfaceDrivers.VirtIO, 216 } 217 updateServerToMinExpected = &iaas.Server{ 218 Name: updateServerToMinParam.Name, 219 InterfaceDriver: updateServerToMinParam.InterfaceDriver, 220 CPU: createServerParam.CPU, 221 MemoryMB: createServerParam.MemoryMB, 222 } 223 ) 224 225 func testServerCreate(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 226 client := iaas.NewServerOp(caller) 227 server, err := client.Create(ctx, testZone, createServerParam) 228 if err != nil { 229 return nil, err 230 } 231 if err := client.Boot(ctx, testZone, server.ID); err != nil { 232 return nil, err 233 } 234 return server, nil 235 } 236 237 func testServerRead(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 238 client := iaas.NewServerOp(caller) 239 return client.Read(ctx, testZone, ctx.ID) 240 } 241 242 func testServerUpdate(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 243 client := iaas.NewServerOp(caller) 244 return client.Update(ctx, testZone, ctx.ID, updateServerParam) 245 } 246 247 func testServerUpdateToMin(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 248 client := iaas.NewServerOp(caller) 249 return client.Update(ctx, testZone, ctx.ID, updateServerToMinParam) 250 } 251 252 func testServerDelete(ctx *testutil.CRUDTestContext, caller iaas.APICaller) error { 253 client := iaas.NewServerOp(caller) 254 return client.Delete(ctx, testZone, ctx.ID) 255 } 256 257 func TestServerOp_ChangePlan(t *testing.T) { 258 client := iaas.NewServerOp(singletonAPICaller()) 259 testutil.RunCRUD(t, &testutil.CRUDTestCase{ 260 Parallel: true, 261 SetupAPICallerFunc: singletonAPICaller, 262 IgnoreStartupWait: true, 263 Create: &testutil.CRUDTestFunc{ 264 Func: func(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 265 return client.Create(ctx, testZone, &iaas.ServerCreateRequest{ 266 CPU: 1, 267 MemoryMB: 1 * size.GiB, 268 ConnectedSwitches: []*iaas.ConnectedSwitch{ 269 { 270 Scope: types.Scopes.Shared, 271 }, 272 }, 273 InterfaceDriver: types.InterfaceDrivers.VirtIO, 274 Name: testutil.ResourceName("server"), 275 Description: "desc", 276 Tags: []string{"tag1", "tag2"}, 277 WaitDiskMigration: false, 278 }) 279 }, 280 CheckFunc: func(t testutil.TestT, _ *testutil.CRUDTestContext, v interface{}) error { 281 server := v.(*iaas.Server) 282 283 if !assert.Equal(t, server.CPU, 1) { 284 return errors.New("unexpected state: Server.CPU") 285 } 286 if !assert.Equal(t, server.GetMemoryGB(), 1) { 287 return errors.New("unexpected state: Server.GerMemoryGB()") 288 } 289 return nil 290 }, 291 }, 292 Read: &testutil.CRUDTestFunc{ 293 Func: testServerRead, 294 }, 295 Updates: []*testutil.CRUDTestFunc{ 296 // change plan 297 { 298 Func: func(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 299 return client.ChangePlan(ctx, testZone, ctx.ID, &iaas.ServerChangePlanRequest{ 300 CPU: 2, 301 MemoryMB: 4 * size.GiB, 302 }) 303 }, 304 CheckFunc: func(t testutil.TestT, ctx *testutil.CRUDTestContext, v interface{}) error { 305 newServer := v.(*iaas.Server) 306 if !assert.Equal(t, newServer.CPU, 2) { 307 return errors.New("unexpected state: Server.CPU") 308 } 309 if !assert.Equal(t, newServer.GetMemoryGB(), 4) { 310 return errors.New("unexpected state: Server.GerMemoryGB()") 311 } 312 if !assert.NotEqual(t, ctx.ID, newServer.ID) { 313 return errors.New("unexpected state: Server.ID(renew)") 314 } 315 return nil 316 }, 317 }, 318 }, 319 Delete: &testutil.CRUDTestDeleteFunc{ 320 Func: testServerDelete, 321 }, 322 }) 323 } 324 325 func TestServerOp_Interfaces(t *testing.T) { 326 var serverID, switchID types.ID 327 328 testutil.RunCRUD(t, &testutil.CRUDTestCase{ 329 Parallel: true, 330 SetupAPICallerFunc: singletonAPICaller, 331 IgnoreStartupWait: true, 332 333 Create: &testutil.CRUDTestFunc{ 334 Func: func(ctx *testutil.CRUDTestContext, caller iaas.APICaller) (interface{}, error) { 335 // create server with interfaces[ disconnected, disconnected, switch ] 336 switchOp := iaas.NewSwitchOp(caller) 337 sw, err := switchOp.Create(ctx, testZone, &iaas.SwitchCreateRequest{Name: "libsacloud-switch-for-server"}) 338 if err != nil { 339 return nil, err 340 } 341 342 serverOp := iaas.NewServerOp(caller) 343 server, err := serverOp.Create(ctx, testZone, &iaas.ServerCreateRequest{ 344 Name: testutil.ResourceName("server-disconnected-nics"), 345 CPU: 1, 346 MemoryMB: 1 * size.GiB, 347 ConnectedSwitches: []*iaas.ConnectedSwitch{ 348 nil, 349 nil, 350 {ID: sw.ID}, 351 }, 352 }) 353 if err != nil { 354 return nil, err 355 } 356 357 serverID = server.ID 358 switchID = sw.ID 359 360 return server, err 361 }, 362 CheckFunc: func(t testutil.TestT, ctx *testutil.CRUDTestContext, v interface{}) error { 363 server := v.(*iaas.Server) 364 return testutil.DoAsserts( 365 testutil.AssertLenFunc(t, server.Interfaces, 3, "Server.Interfaces"), 366 ) 367 }, 368 }, 369 370 Read: &testutil.CRUDTestFunc{ 371 Func: testServerRead, 372 }, 373 374 Delete: &testutil.CRUDTestDeleteFunc{ 375 Func: func(ctx *testutil.CRUDTestContext, caller iaas.APICaller) error { 376 switchOp := iaas.NewSwitchOp(caller) 377 serverOp := iaas.NewServerOp(caller) 378 379 server, _ := serverOp.Read(ctx, testZone, serverID) 380 if server != nil && server.InstanceStatus.IsUp() { 381 if err := serverOp.Shutdown(ctx, testZone, server.ID, &iaas.ShutdownOption{Force: true}); err != nil { 382 return err 383 } 384 _, err := iaas.WaiterForDown(func() (interface{}, error) { 385 return serverOp.Read(ctx, testZone, server.ID) 386 }).WaitForState(ctx) 387 if err != nil { 388 return err 389 } 390 } 391 if err := serverOp.Delete(ctx, testZone, server.ID); err != nil { 392 return err 393 } 394 sw, err := switchOp.Read(ctx, testZone, switchID) 395 if sw != nil { 396 return switchOp.Delete(ctx, testZone, sw.ID) 397 } 398 return err 399 }, 400 }, 401 }) 402 }