-
Notifications
You must be signed in to change notification settings - Fork 6
/
storage.go
99 lines (86 loc) · 2.98 KB
/
storage.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
package storage
import (
"context"
"fmt"
"time"
"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands"
"github.com/UpCloudLtd/progress/messages"
"github.com/UpCloudLtd/upcloud-go-api/v8/upcloud"
"github.com/UpCloudLtd/upcloud-go-api/v8/upcloud/request"
)
var (
maxStorageActions = 10
// CachedStorages stores the cached list of storages in order to not hit the service more than once
// TODO: refactor
CachedStorages []upcloud.Storage
)
// BaseStorageCommand creates the base "storage" command
func BaseStorageCommand() commands.Command {
return &storageCommand{
commands.New("storage", "Manage storages"),
}
}
type storageCommand struct {
*commands.BaseCommand
}
func matchStorages(storages []upcloud.Storage, searchVal string) []*upcloud.Storage {
var r []*upcloud.Storage
for _, storage := range storages {
storage := storage
if storage.Title == searchVal || storage.UUID == searchVal {
r = append(r, &storage)
}
}
return r
}
func searchStorage(storagesPtr *[]upcloud.Storage, exec commands.Executor, uuidOrTitle string, unique bool) ([]*upcloud.Storage, error) {
if storagesPtr == nil || exec == nil {
return nil, fmt.Errorf("no storages or executor passed")
}
storages := *storagesPtr
if len(CachedStorages) == 0 {
res, err := exec.All().GetStorages(exec.Context(), &request.GetStoragesRequest{})
if err != nil {
return nil, err
}
storages = res.Storages
*storagesPtr = storages
}
matched := matchStorages(storages, uuidOrTitle)
if len(matched) == 0 {
return nil, fmt.Errorf("no storage with uuid, name or title %q was found", uuidOrTitle)
}
if len(matched) > 1 && unique {
return nil, fmt.Errorf("multiple storages matched to query %q, use UUID to specify", uuidOrTitle)
}
return matched, nil
}
// SearchSingleStorage returns exactly one storage where title or uuid matches uuidOrTitle
// TODO: remove the cross-command dependencies
func SearchSingleStorage(uuidOrTitle string, exec commands.Executor) (*upcloud.Storage, error) {
matchedResults, err := searchStorage(&CachedStorages, exec, uuidOrTitle, true)
if err != nil {
return nil, err
}
return matchedResults[0], nil
}
// waitForStorageState waits for storage to reach given state and updates progress message with key matching given msg. Finally, progress message is updated back to given msg and either done state or timeout warning.
func waitForStorageState(uuid, state string, exec commands.Executor, msg string) {
exec.PushProgressUpdateMessage(msg, fmt.Sprintf("Waiting for storage %s to be in %s state", uuid, state))
ctx, cancel := context.WithTimeout(exec.Context(), 15*time.Minute)
defer cancel()
if _, err := exec.All().WaitForStorageState(ctx, &request.WaitForStorageStateRequest{
UUID: uuid,
DesiredState: state,
}); err != nil {
exec.PushProgressUpdate(messages.Update{
Key: msg,
Message: msg,
Status: messages.MessageStatusWarning,
Details: "Error: " + err.Error(),
})
return
}
exec.PushProgressUpdateMessage(msg, msg)
exec.PushProgressSuccess(msg)
}