Skip to content

Commit 1e2b87a

Browse files
authored
Merge pull request #44 from lixiaojun629/develop
ucloud 0.1.27
2 parents 9c765d5 + 91b207a commit 1e2b87a

5 files changed

Lines changed: 218 additions & 8 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export VERSION=0.1.26
1+
export VERSION=0.1.27
22

33
.PHONY : install
44
install:

base/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const DefaultBaseURL = "https://api.ucloud.cn/"
3636
const DefaultProfile = "default"
3737

3838
//Version 版本号
39-
const Version = "0.1.26"
39+
const Version = "0.1.27"
4040

4141
//ConfigIns 配置实例, 程序加载时生成
4242
var ConfigIns = &AggConfig{

base/log.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,42 @@ func LogInfo(logs ...string) {
9494
}
9595
}
9696

97+
//LogPrint 记录日志
98+
func LogPrint(logs ...string) {
99+
_, ok := os.LookupEnv("COMP_LINE")
100+
if ok {
101+
return
102+
}
103+
mu.Lock()
104+
defer mu.Unlock()
105+
goID := curGoroutineID()
106+
for _, line := range logs {
107+
logger.WithField("goroutine_id", goID).Print(line)
108+
fmt.Fprintln(out, line)
109+
}
110+
if ConfigIns.AgreeUploadLog {
111+
UploadLogs(logs, "print", goID)
112+
}
113+
}
114+
115+
//LogWarn 记录日志
116+
func LogWarn(logs ...string) {
117+
_, ok := os.LookupEnv("COMP_LINE")
118+
if ok {
119+
return
120+
}
121+
mu.Lock()
122+
defer mu.Unlock()
123+
goID := curGoroutineID()
124+
for _, line := range logs {
125+
logger.WithField("goroutine_id", goID).Warn(line)
126+
fmt.Fprintln(out, line)
127+
}
128+
if ConfigIns.AgreeUploadLog {
129+
UploadLogs(logs, "warn", goID)
130+
}
131+
}
132+
97133
//LogError 记录日志
98134
func LogError(logs ...string) {
99135
_, ok := os.LookupEnv("COMP_LINE")

cmd/uhost.go

Lines changed: 178 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"encoding/base64"
1919
"fmt"
2020
"io"
21+
"regexp"
2122
"strings"
2223
"sync"
2324
"time"
@@ -59,6 +60,7 @@ func NewCmdUHost() *cobra.Command {
5960
cmd.AddCommand(NewCmdUhostReinstallOS(out))
6061
cmd.AddCommand(NewCmdUhostCreateImage(out))
6162
cmd.AddCommand(NewCmdIsolation(out))
63+
cmd.AddCommand(NewCmdUhostLeaveIsolationGroup(out))
6264

6365
return cmd
6466
}
@@ -211,12 +213,20 @@ func getAllUHosts(req *uhost.DescribeUHostInstanceRequest, pageOff bool, allRegi
211213
func NewCmdUHostList(out io.Writer) *cobra.Command {
212214
var allRegion, pageOff, idOnly bool
213215
var output string
216+
var uhostIds []string
214217
req := base.BizClient.NewDescribeUHostInstanceRequest()
215218
cmd := &cobra.Command{
216219
Use: "list",
217220
Short: "List all UHost Instances",
218221
Long: `List all UHost Instances`,
219222
Run: func(cmd *cobra.Command, args []string) {
223+
*req.VPCId = base.PickResourceID(*req.VPCId)
224+
*req.SubnetId = base.PickResourceID(*req.SubnetId)
225+
*req.IsolationGroup = base.PickResourceID(*req.IsolationGroup)
226+
for _, uhost := range uhostIds {
227+
req.UHostIds = append(req.UHostIds, base.PickResourceID(uhost))
228+
}
229+
220230
uhosts, err := getAllUHosts(req, pageOff, allRegion)
221231
if err != nil {
222232
base.HandleError(err)
@@ -233,9 +243,12 @@ func NewCmdUHostList(out io.Writer) *cobra.Command {
233243
req.ProjectId = cmd.Flags().String("project-id", base.ConfigIns.ProjectID, "Optional. Assign project-id")
234244
req.Region = cmd.Flags().String("region", base.ConfigIns.Region, "Optional. Assign region.")
235245
req.Zone = cmd.Flags().String("zone", "", "Optional. Assign availability zone")
236-
cmd.Flags().StringSliceVar(&req.UHostIds, "uhost-id", make([]string, 0), "Optional. Resource ID of uhost instances, multiple values separated by comma(without space)")
237246
req.Offset = cmd.Flags().Int("offset", 0, "Optional. Offset default 0")
238247
req.Limit = cmd.Flags().Int("limit", 50, "Optional. Limit default 50, max value 100")
248+
req.VPCId = cmd.Flags().String("vpc-id", "", "Optional. Resource ID of VPC. List uhost instances of the specified VPC")
249+
req.SubnetId = cmd.Flags().String("subnet-id", "", "Optional. Resource ID of Subnet. List uhost instances of the specified Subnet")
250+
req.IsolationGroup = cmd.Flags().String("isolation-group", "", "Optional. Resource ID of isolation group. List uhost instances of the specified isolation group")
251+
cmd.Flags().StringSliceVar(&uhostIds, "uhost-id", make([]string, 0), "Optional. Resource ID of uhost instances, multiple values separated by comma(without space)")
239252
cmd.Flags().BoolVar(&allRegion, "all-region", false, "Optional. Accpet values: true or false. List uhost instances of all regions when assigned true")
240253
cmd.Flags().BoolVar(&pageOff, "page-off", false, "Optional. Paging or not. If all-region is specified this flag will be true. Accept values: true or false. If assigned, the limit flag will be disabled and list all uhost instances")
241254
cmd.Flags().BoolVar(&idOnly, "uhost-id-only", false, "Optional. Just display resource id of uhost")
@@ -251,6 +264,20 @@ func NewCmdUHostList(out io.Writer) *cobra.Command {
251264
return getZoneList(req.GetRegion())
252265
})
253266

267+
flags := cmd.Flags()
268+
flags.SetFlagValuesFunc("vpc-id", func() []string {
269+
return getAllVPCIdNames(*req.ProjectId, *req.Region)
270+
})
271+
flags.SetFlagValuesFunc("subnet-id", func() []string {
272+
return getAllSubnetIDNames(*req.VPCId, *req.ProjectId, *req.Region)
273+
})
274+
flags.SetFlagValuesFunc("isolation-group", func() []string {
275+
return getIsolationGroupList(*req.ProjectId, *req.Region)
276+
})
277+
flags.SetFlagValuesFunc("uhost-id", func() []string {
278+
return getUhostList(nil, *req.ProjectId, *req.Region, *req.Zone)
279+
})
280+
254281
return cmd
255282
}
256283

@@ -260,6 +287,7 @@ func NewCmdUHostCreate() *cobra.Command {
260287
var hotPlug string
261288
var async bool
262289
var count int
290+
var hotPlugImageFlag bool
263291

264292
req := base.BizClient.NewCreateUHostInstanceRequest()
265293
eipReq := base.BizClient.NewAllocateEIPRequest()
@@ -277,6 +305,24 @@ func NewCmdUHostCreate() *cobra.Command {
277305
req.IsolationGroup = sdk.String(base.PickResourceID(*req.IsolationGroup))
278306
if hotPlug == "true" {
279307
req.HotplugFeature = sdk.Bool(true)
308+
any, err := describeImageByID(*req.ImageId, *req.ProjectId, *req.Region, *req.Zone)
309+
if err != nil {
310+
base.LogError(fmt.Sprintf("check image support hot-plug failed: %v", err))
311+
} else {
312+
image, ok := any.(*uhost.UHostImageSet)
313+
if !ok {
314+
base.LogError(fmt.Sprintf("check image support hot-plug failed, image %s may not exist", *req.ImageId))
315+
}
316+
for _, feature := range image.Features {
317+
if feature == "HotPlug" {
318+
hotPlugImageFlag = true
319+
}
320+
}
321+
}
322+
if !hotPlugImageFlag {
323+
base.LogWarn(fmt.Sprintf("warning. image %s does not support hot-plug", *req.ImageId))
324+
req.HotplugFeature = sdk.Bool(false)
325+
}
280326
}
281327

282328
wg := &sync.WaitGroup{}
@@ -359,7 +405,7 @@ func NewCmdUHostCreate() *cobra.Command {
359405
req.UHostType = flags.String("type", "", "Optional. Accept values: N1, N2, N3, G1, G2, G3, I1, I2, C1. Forward to https://docs.ucloud.cn/api/uhost-api/uhost_type for details")
360406
req.GPU = flags.Int("gpu", 0, "Optional. The count of GPU cores.")
361407
req.NetCapability = flags.String("net-capability", "Normal", "Optional. Default is 'Normal', also support 'Super' which will enhance multiple times network capability as before")
362-
flags.StringVar(&hotPlug, "hot-plug", "false", "Optional. Enable hot plug feature or not. Accept values: true or false")
408+
flags.StringVar(&hotPlug, "hot-plug", "true", "Optional. Enable hot plug feature or not. Accept values: true or false")
363409
req.Disks[0].Type = flags.String("os-disk-type", "CLOUD_SSD", "Optional. Enumeration value. 'LOCAL_NORMAL', Ordinary local disk; 'CLOUD_NORMAL', Ordinary cloud disk; 'LOCAL_SSD',local ssd disk; 'CLOUD_SSD',cloud ssd disk; 'EXCLUSIVE_LOCAL_DISK',big data. The disk only supports a limited combination.")
364410
req.Disks[0].Size = flags.Int("os-disk-size-gb", 20, "Optional. Default 20G. Windows should be bigger than 40G Unit GB")
365411
req.Disks[0].BackupType = flags.String("os-disk-backup-type", "NONE", "Optional. Enumeration value, 'NONE' or 'DATAARK'. DataArk supports real-time backup, which can restore the disk back to any moment within the last 12 hours. (Normal Local Disk and Normal Cloud Disk Only)")
@@ -938,10 +984,14 @@ func getUhostList(states []string, project, region, zone string) []string {
938984
}
939985
list := []string{}
940986
for _, host := range resp.UHostSet {
941-
for _, s := range states {
942-
if host.State == s {
943-
list = append(list, host.UHostId+"/"+strings.Replace(host.Name, " ", "-", -1))
987+
if states != nil {
988+
for _, s := range states {
989+
if host.State == s {
990+
list = append(list, host.UHostId+"/"+strings.Replace(host.Name, " ", "-", -1))
991+
}
944992
}
993+
} else {
994+
list = append(list, host.UHostId+"/"+strings.Replace(host.Name, " ", "-", -1))
945995
}
946996
}
947997
return list
@@ -1271,6 +1321,54 @@ func NewCmdUhostReinstallOS(out io.Writer) *cobra.Command {
12711321
return cmd
12721322
}
12731323

1324+
//NewCmdUhostLeaveIsolationGroup ucloud uhost leave-isolation-group
1325+
func NewCmdUhostLeaveIsolationGroup(out io.Writer) *cobra.Command {
1326+
var uhostIds []string
1327+
req := base.BizClient.NewLeaveIsolationGroupRequest()
1328+
cmd := &cobra.Command{
1329+
Use: "leave-isolation-group",
1330+
Short: "Detach uhost from its isolation group",
1331+
Run: func(c *cobra.Command, args []string) {
1332+
for _, idname := range uhostIds {
1333+
id := base.PickResourceID(idname)
1334+
any, err := describeUHostByID(id, *req.ProjectId, *req.Region, *req.Zone)
1335+
if err != nil {
1336+
base.LogError(fmt.Sprintf("fetch uhost %s failed: %v", idname, err))
1337+
continue
1338+
}
1339+
ins, ok := any.(*uhost.UHostInstanceSet)
1340+
if !ok {
1341+
base.LogError(fmt.Sprintf("uhost %s may not exist", idname))
1342+
continue
1343+
}
1344+
if ins.IsolationGroup == "" {
1345+
base.LogPrint(fmt.Sprintf("uhost %s doesn't attached any isolation group", idname))
1346+
continue
1347+
}
1348+
req.GroupId = sdk.String(ins.IsolationGroup)
1349+
req.UHostId = &id
1350+
_, err = base.BizClient.LeaveIsolationGroup(req)
1351+
if err != nil {
1352+
base.HandleError(err)
1353+
continue
1354+
}
1355+
base.LogPrint(fmt.Sprintf("uhost %s detached from isolation group %s", idname, ins.IsolationGroup))
1356+
}
1357+
},
1358+
}
1359+
flags := cmd.Flags()
1360+
flags.SortFlags = false
1361+
flags.StringSliceVar(&uhostIds, "uhost-id", nil, "Required. Resource ID of uhosts to be detech from its isolation group")
1362+
bindRegion(req, flags)
1363+
bindProjectID(req, flags)
1364+
bindZone(req, flags)
1365+
cmd.MarkFlagRequired("uhost-id")
1366+
flags.SetFlagValuesFunc("uhost-id", func() []string {
1367+
return getUhostList(nil, *req.ProjectId, *req.Region, *req.Zone)
1368+
})
1369+
return cmd
1370+
}
1371+
12741372
//NewCmdIsolation ucloud uhost isolation-gorup
12751373
func NewCmdIsolation(out io.Writer) *cobra.Command {
12761374
cmd := &cobra.Command{
@@ -1279,6 +1377,76 @@ func NewCmdIsolation(out io.Writer) *cobra.Command {
12791377
Long: "List and manipulate isolation group of uhost",
12801378
}
12811379
cmd.AddCommand(NewCmdIsolationList(out))
1380+
cmd.AddCommand(NewCmdIsolationCreate(out))
1381+
cmd.AddCommand(NewCmdIsolationDelete(out))
1382+
return cmd
1383+
}
1384+
1385+
//NewCmdIsolationCreate ucloud uhost isolation-group create
1386+
func NewCmdIsolationCreate(out io.Writer) *cobra.Command {
1387+
req := base.BizClient.NewCreateIsolationGroupRequest()
1388+
cmd := &cobra.Command{
1389+
Use: "create",
1390+
Short: "Create isolation group instance",
1391+
Long: "Create isolation group instance",
1392+
Run: func(c *cobra.Command, args []string) {
1393+
re := regexp.MustCompile(cli.REGEXP_NAME)
1394+
if !re.Match([]byte(*req.GroupName)) {
1395+
base.LogError(fmt.Sprintf("group-name %s is invalid! Length 1~63, only English,Chinese,number and '-_.' are allowed", *req.GroupName))
1396+
return
1397+
}
1398+
resp, err := base.BizClient.CreateIsolationGroup(req)
1399+
if err != nil {
1400+
base.HandleError(err)
1401+
return
1402+
}
1403+
base.LogPrint(fmt.Sprintf("isolation group %s created", resp.GroupId))
1404+
},
1405+
}
1406+
flags := cmd.Flags()
1407+
flags.SortFlags = false
1408+
1409+
req.GroupName = flags.String("group-name", "", "Required. Name of isolation group. Length 1~63, only English,Chinese,number and '-_.' are allowed")
1410+
bindRegion(req, flags)
1411+
bindProjectID(req, flags)
1412+
req.Remark = flags.String("remark", "", "Optional. Remark ok isolation group")
1413+
1414+
cmd.MarkFlagRequired("group-name")
1415+
return cmd
1416+
}
1417+
1418+
//NewCmdIsolationDelete ucloud uhost
1419+
func NewCmdIsolationDelete(out io.Writer) *cobra.Command {
1420+
var ids []string
1421+
req := base.BizClient.NewDeleteIsolationGroupRequest()
1422+
cmd := &cobra.Command{
1423+
Use: "delete",
1424+
Short: "Delete isolation group instances",
1425+
Run: func(c *cobra.Command, args []string) {
1426+
for _, idname := range ids {
1427+
id := base.PickResourceID(idname)
1428+
req.GroupId = &id
1429+
_, err := base.BizClient.DeleteIsolationGroup(req)
1430+
if err != nil {
1431+
base.HandleError(err)
1432+
continue
1433+
}
1434+
base.LogPrint(fmt.Sprintf("isolation group %s deleted", idname))
1435+
}
1436+
},
1437+
}
1438+
1439+
flags := cmd.Flags()
1440+
flags.SortFlags = false
1441+
flags.StringSliceVar(&ids, "group-id", nil, "Required. Resource ID of isolation groups to be deleted")
1442+
bindRegion(req, flags)
1443+
bindProjectID(req, flags)
1444+
1445+
cmd.MarkFlagRequired("group-id")
1446+
flags.SetFlagValuesFunc("group-id", func() []string {
1447+
return getIsolationGroupList(*req.ProjectId, *req.Region)
1448+
})
1449+
12821450
return cmd
12831451
}
12841452

@@ -1321,12 +1489,16 @@ func NewCmdIsolationList(out io.Writer) *cobra.Command {
13211489
flags := cmd.Flags()
13221490
flags.SortFlags = false
13231491

1324-
flags.String("group-id", "", "Optional. Resource ID of isolation group to describe")
1492+
req.GroupId = flags.String("group-id", "", "Optional. Resource ID of isolation group to describe")
13251493
bindRegion(req, flags)
13261494
bindProjectID(req, flags)
13271495
bindLimit(req, flags)
13281496
bindOffset(req, flags)
13291497

1498+
flags.SetFlagValuesFunc("group-id", func() []string {
1499+
return getIsolationGroupList(*req.ProjectId, *req.Region)
1500+
})
1501+
13301502
return cmd
13311503
}
13321504

model/cli/cli_const.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ const IMAGE_BASE = "Base"
44
const IMAGE_BUSINESS = "Business"
55
const IAMGE_CUSTOM = "Custom"
66
const IMAGE_ALL = "*"
7+
8+
const REGEXP_NAME = "^[A-Za-z0-9-_.\u4e00-\u9fa5]{1,63}$"

0 commit comments

Comments
 (0)