-
Notifications
You must be signed in to change notification settings - Fork 3
/
list.go
179 lines (146 loc) · 4.02 KB
/
list.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package cmd
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"time"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
"github.com/capeprivacy/cli/entities"
)
type ErrorMsg struct {
ErrorMsg string `json:"error"`
}
func (e ErrorMsg) Error() string {
return e.ErrorMsg
}
type ErrServerForList struct {
statusCode int
message string
}
func (e ErrServerForList) Error() string {
return fmt.Sprintf("expected 200, got server response code when listing functions %d: %s", e.statusCode, e.message)
}
var ErrUnauthorized = errors.New("unauthorized: authentication required")
// listCmd represents the list command
var listCmd = &cobra.Command{
Use: "list",
Short: "List all deployed functions",
Long: "List all deployed functions for your user.\n",
RunE: func(cmd *cobra.Command, args []string) error {
err := list(cmd, args)
if _, ok := err.(UserError); !ok {
cmd.SilenceUsage = true
}
return err
},
}
func init() {
rootCmd.AddCommand(listCmd)
listCmd.PersistentFlags().IntP("limit", "", 50, "Limit the number of functions returned.")
listCmd.PersistentFlags().IntP("offset", "", 0, "Number of functions to skip before listing.")
}
func list(cmd *cobra.Command, args []string) error {
u := C.EnclaveHost
insecure := C.Insecure
limit, err := cmd.Flags().GetInt("limit")
if err != nil {
return err
}
offset, err := cmd.Flags().GetInt("offset")
if err != nil {
return err
}
format, err := cmd.Flags().GetString("output")
if err != nil {
return err
}
if len(args) > 0 {
return UserError{Msg: "list does not take any arguments", Err: fmt.Errorf("invalid number of input arguments")}
}
t, err := authToken()
if err != nil {
return err
}
auth := entities.FunctionAuth{Type: entities.AuthenticationTypeUserToken, Token: t}
err = doList(u, insecure, auth, limit, offset, format)
if err != nil {
if errors.Is(err, ErrUnauthorized) {
return err
}
return fmt.Errorf("list failed: %w", err)
}
return nil
}
func doList(url string, insecure bool, auth entities.FunctionAuth, limit int, offset int, format string) error { //nolint:gocognit
endpoint := fmt.Sprintf("%s/v1/functions?limit=%d&offset=%d", url, limit, offset)
req, err := http.NewRequest("GET", endpoint, nil)
if err != nil {
return err
}
var bearer = "Bearer " + auth.Token
req.Header.Add("Authorization", bearer)
res, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("cannot complete http request: %s", err)
}
if res.StatusCode != 200 {
var e ErrorMsg
if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
return ErrServerForList{statusCode: res.StatusCode}
}
res.Body.Close()
if res.StatusCode == 401 {
return ErrUnauthorized
}
return ErrServerForList{res.StatusCode, e.ErrorMsg}
}
body, err := io.ReadAll(res.Body)
if err != nil {
return errors.New("could not read response body")
}
var deploymentNames []entities.Deployment
err = json.Unmarshal(body, &deploymentNames)
if err != nil {
return errors.New("malformed body in response")
}
if len(deploymentNames) == 0 {
fmt.Println("No functions deployed.")
return nil
}
if f, ok := listFormatters[format]; ok {
return f(deploymentNames)
}
return printTable(deploymentNames)
}
var listFormatters = map[string]func([]entities.Deployment) error{
"plain": printTable,
"json": printJSON,
}
func printTable(deps []entities.Deployment) error {
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"#", "Name", "ID", "Created At"})
localTime, err := time.LoadLocation("Local")
if err != nil {
return err
}
for i, deployment := range deps {
t.AppendRow([]interface{}{i, deployment.Name, deployment.ID, deployment.CreatedAt.In(localTime).Format("Jan 02 2006 15:04")})
}
t.SetStyle(table.StyleLight)
t.Render()
return nil
}
func printJSON(deps []entities.Deployment) error {
return json.NewEncoder(os.Stdout).Encode(struct {
Deps []entities.Deployment `json:"deployments"`
Count int `json:"count"`
}{
Deps: deps,
Count: len(deps),
})
}