github.com/sacloud/libsacloud/v2@v2.32.3/helper/plans/change_plan.go (about)

     1  // Copyright 2016-2022 The Libsacloud 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 plans
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"strings"
    21  
    22  	"github.com/sacloud/libsacloud/v2/pkg/size"
    23  	"github.com/sacloud/libsacloud/v2/sacloud"
    24  	"github.com/sacloud/libsacloud/v2/sacloud/types"
    25  )
    26  
    27  var (
    28  	PreviousIDTagName = "@previous-id"
    29  	maxTags           = 10 // タグ上限数
    30  )
    31  
    32  // ChangeServerPlan 現在のIDをタグとして保持しつつプランを変更する
    33  //
    34  // もしすでにタグが上限(10)まで付与されている場合はプラン変更だけ行う
    35  func ChangeServerPlan(
    36  	ctx context.Context,
    37  	caller sacloud.APICaller,
    38  	zone string,
    39  	id types.ID,
    40  	cpu int,
    41  	memoryGB int,
    42  	commitment types.ECommitment,
    43  	generation types.EPlanGeneration,
    44  ) (*sacloud.Server, error) {
    45  	serverOp := sacloud.NewServerOp(caller)
    46  	server, err := serverOp.Read(ctx, zone, id)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	if len(server.Tags) < maxTags {
    52  		server.Tags = AppendPreviousIDTagIfAbsent(server.Tags, server.ID)
    53  
    54  		updated, err := serverOp.Update(ctx, zone, server.ID, &sacloud.ServerUpdateRequest{
    55  			Name:            server.Name,
    56  			Description:     server.Description,
    57  			Tags:            server.Tags,
    58  			IconID:          server.IconID,
    59  			PrivateHostID:   server.PrivateHostID,
    60  			InterfaceDriver: server.InterfaceDriver,
    61  		})
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		server = updated
    66  	}
    67  
    68  	return serverOp.ChangePlan(ctx, zone, server.ID, &sacloud.ServerChangePlanRequest{
    69  		CPU:                  cpu,
    70  		MemoryMB:             memoryGB * size.GiB,
    71  		ServerPlanGeneration: generation,
    72  		ServerPlanCommitment: commitment,
    73  	})
    74  }
    75  
    76  // ChangeRouterPlan 現在のIDをタグとして保持しつつプランを変更する
    77  //
    78  // もしすでにタグが上限(10)まで付与されている場合はプラン変更だけ行う
    79  func ChangeRouterPlan(
    80  	ctx context.Context,
    81  	caller sacloud.APICaller,
    82  	zone string,
    83  	id types.ID,
    84  	bandWidth int,
    85  ) (*sacloud.Internet, error) {
    86  	internetOp := sacloud.NewInternetOp(caller)
    87  	router, err := internetOp.Read(ctx, zone, id)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	if len(router.Tags) < maxTags {
    93  		router.Tags = AppendPreviousIDTagIfAbsent(router.Tags, router.ID)
    94  
    95  		updated, err := internetOp.Update(ctx, zone, router.ID, &sacloud.InternetUpdateRequest{
    96  			Name:        router.Name,
    97  			Description: router.Description,
    98  			Tags:        router.Tags,
    99  			IconID:      router.IconID,
   100  		})
   101  		if err != nil {
   102  			return nil, err
   103  		}
   104  		router = updated
   105  	}
   106  
   107  	return internetOp.UpdateBandWidth(ctx, zone, router.ID, &sacloud.InternetUpdateBandWidthRequest{
   108  		BandWidthMbps: bandWidth,
   109  	})
   110  }
   111  
   112  // ChangeProxyLBPlan 現在のIDをタグとして保持しつつプランを変更する
   113  //
   114  // もしすでにタグが上限(10)まで付与されている場合はプラン変更だけ行う
   115  func ChangeProxyLBPlan(
   116  	ctx context.Context,
   117  	caller sacloud.APICaller,
   118  	id types.ID,
   119  	cps int,
   120  ) (*sacloud.ProxyLB, error) {
   121  	elbOp := sacloud.NewProxyLBOp(caller)
   122  	elb, err := elbOp.Read(ctx, id)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	if len(elb.Tags) < maxTags {
   128  		elb.Tags = AppendPreviousIDTagIfAbsent(elb.Tags, elb.ID)
   129  
   130  		updated, err := elbOp.Update(ctx, elb.ID, &sacloud.ProxyLBUpdateRequest{
   131  			HealthCheck:   elb.HealthCheck,
   132  			SorryServer:   elb.SorryServer,
   133  			BindPorts:     elb.BindPorts,
   134  			Servers:       elb.Servers,
   135  			Rules:         elb.Rules,
   136  			LetsEncrypt:   elb.LetsEncrypt,
   137  			StickySession: elb.StickySession,
   138  			Timeout:       elb.Timeout,
   139  			Gzip:          elb.Gzip,
   140  			ProxyProtocol: elb.ProxyProtocol,
   141  			Syslog:        elb.Syslog,
   142  			SettingsHash:  elb.SettingsHash,
   143  			Name:          elb.Name,
   144  			Description:   elb.Description,
   145  			Tags:          elb.Tags,
   146  			IconID:        elb.IconID,
   147  		})
   148  		if err != nil {
   149  			return nil, err
   150  		}
   151  		elb = updated
   152  	}
   153  
   154  	return elbOp.ChangePlan(ctx, elb.ID, &sacloud.ProxyLBChangePlanRequest{
   155  		ServiceClass: types.ProxyLBServiceClass(types.EProxyLBPlan(cps), elb.Region),
   156  	})
   157  }
   158  
   159  func AppendPreviousIDTagIfAbsent(tags types.Tags, currentID types.ID) types.Tags {
   160  	if len(tags) > maxTags {
   161  		return tags
   162  	}
   163  	// すでに付けられたPreviousIDタグを消す
   164  	updated := types.Tags{}
   165  	for _, t := range tags {
   166  		if !strings.HasPrefix(t, PreviousIDTagName) {
   167  			updated = append(updated, t)
   168  		}
   169  	}
   170  	updated = append(updated, fmt.Sprintf("%s=%s", PreviousIDTagName, currentID))
   171  	updated.Sort()
   172  	return updated
   173  }