forked from aliyun/aliyun-cli
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwaiter.go
114 lines (103 loc) · 3.25 KB
/
waiter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright (c) 2009-present, Alibaba Cloud All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package openapi
import (
"fmt"
"strconv"
"time"
"github.com/aliyun/aliyun-cli/cli"
"github.com/aliyun/aliyun-cli/i18n"
)
var WaiterFlag = &cli.Flag{Category: "helper",
Name: "waiter",
AssignedMode: cli.AssignedRepeatable,
Short: i18n.T(
"use `--waiter expr=<jmesPath> to=<value>` to pull api until result equal to expected value",
"使用 `--waiter expr=<jmesPath> to=<value>` 来轮询调用OpenAPI,直到返回期望的值"),
Long: i18n.T(
"",
""),
Fields: []cli.Field{
{Key: "expr", Required: true, Short: i18n.T("", "")},
{Key: "to", Required: true, Short: i18n.T("", "")},
{Key: "timeout", DefaultValue: "180", Short: i18n.T("", "")},
{Key: "interval", DefaultValue: "5", Short: i18n.T("", "")},
},
ExcludeWith: []string{"pager"},
}
type Waiter struct {
expr string
to string
// timeout time.Duration TODO use Flag.Field to validate
// interval time.Duration TODO use Flag.Field to validate
}
func GetWaiter() *Waiter {
if !WaiterFlag.IsAssigned() {
return nil
}
waiter := &Waiter{}
waiter.expr, _ = WaiterFlag.GetFieldValue("expr")
waiter.to, _ = WaiterFlag.GetFieldValue("to")
//waiter.timeout = time.Duration(time.Second * 180)
//waiter.interval = time.Duration(time.Second * 5)
return waiter
}
func (a *Waiter) CallWith(invoker Invoker) (string, error) {
//
// timeout is 1-600 seconds, default is 180
timeout := time.Duration(time.Second * 180)
if s, ok := WaiterFlag.GetFieldValue("timeout"); ok {
if n, err := strconv.Atoi(s); err == nil {
if n <= 0 && n > 600 {
return "", fmt.Errorf("--waiter timeout=%s must between 1-600 (seconds)", s)
}
timeout = time.Duration(time.Second * time.Duration(n))
} else {
return "", fmt.Errorf("--waiter timeout=%s must be integer", s)
}
}
//
// interval is 2-10 seconds, default is 5
interval := time.Duration(time.Second * 5)
if s, ok := WaiterFlag.GetFieldValue("interval"); ok {
if n, err := strconv.Atoi(s); err == nil {
if n <= 1 && n > 10 {
return "", fmt.Errorf("--waiter interval=%s must between 2-10 (seconds)", s)
}
interval = time.Duration(time.Second * time.Duration(n))
} else {
return "", fmt.Errorf("--waiter interval=%s must be integer", s)
}
}
begin := time.Now()
for {
resp, err := invoker.Call()
if err != nil {
return "", err
}
v, err := evaluateExpr(resp.GetHttpContentBytes(), a.expr)
if err != nil {
return "", err
}
if v == a.to {
return resp.GetHttpContentString(), nil
}
duration := time.Now().Sub(begin)
if duration > timeout {
return "", fmt.Errorf("wait '%s' to '%s' timeout(%dseconds), last='%s'",
a.expr, a.to, timeout/time.Second, v)
}
time.Sleep(interval)
}
}