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  }