-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathapi_utils.go
More file actions
207 lines (183 loc) · 5.15 KB
/
api_utils.go
File metadata and controls
207 lines (183 loc) · 5.15 KB
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
package util
import (
"errors"
"strings"
"time"
pb "github.com/runconduit/conduit/controller/gen/public"
"github.com/runconduit/conduit/pkg/k8s"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
/*
Shared utilities for interacting with the controller public api
*/
var (
defaultMetricTimeWindow = "1m"
// ValidTargets specifies resource types allowed as a target:
// target resource on an inbound query
// target resource on an outbound 'to' query
// destination resource on an outbound 'from' query
ValidTargets = []string{
k8s.Deployments,
k8s.Namespaces,
k8s.Pods,
k8s.ReplicationControllers,
}
// ValidDestinations specifies resource types allowed as a destination:
// destination resource on an outbound 'to' query
// target resource on an outbound 'from' query
ValidDestinations = []string{
k8s.Deployments,
k8s.Namespaces,
k8s.Pods,
k8s.ReplicationControllers,
k8s.Services,
}
)
type StatSummaryRequestParams struct {
TimeWindow string
Namespace string
ResourceType string
ResourceName string
ToNamespace string
ToType string
ToName string
FromNamespace string
FromType string
FromName string
}
// GRPCError generates a gRPC error code, as defined in
// google.golang.org/grpc/status.
// If the error is nil or already a gRPC error, return the error.
// If the error is of type k8s.io/apimachinery/pkg/apis/meta/v1#StatusReason,
// attempt to map the reason to a gRPC error.
func GRPCError(err error) error {
if err != nil && status.Code(err) == codes.Unknown {
code := codes.Internal
switch k8sErrors.ReasonForError(err) {
case metav1.StatusReasonUnknown:
code = codes.Unknown
case metav1.StatusReasonUnauthorized, metav1.StatusReasonForbidden:
code = codes.PermissionDenied
case metav1.StatusReasonNotFound:
code = codes.NotFound
case metav1.StatusReasonAlreadyExists:
code = codes.AlreadyExists
case metav1.StatusReasonInvalid:
code = codes.InvalidArgument
case metav1.StatusReasonExpired:
code = codes.DeadlineExceeded
case metav1.StatusReasonServiceUnavailable:
code = codes.Unavailable
}
err = status.Error(code, err.Error())
}
return err
}
func BuildStatSummaryRequest(p StatSummaryRequestParams) (*pb.StatSummaryRequest, error) {
window := defaultMetricTimeWindow
if p.TimeWindow != "" {
_, err := time.ParseDuration(p.TimeWindow)
if err != nil {
return nil, err
}
window = p.TimeWindow
}
resourceType, err := k8s.CanonicalKubernetesNameFromFriendlyName(p.ResourceType)
if err != nil {
return nil, err
}
statRequest := &pb.StatSummaryRequest{
Selector: &pb.ResourceSelection{
Resource: &pb.Resource{
Namespace: p.Namespace,
Name: p.ResourceName,
Type: resourceType,
},
},
TimeWindow: window,
}
if p.ToName != "" || p.ToType != "" || p.ToNamespace != "" {
if p.ToNamespace == "" {
p.ToNamespace = p.Namespace
}
if p.ToType == "" {
p.ToType = resourceType
}
toType, err := k8s.CanonicalKubernetesNameFromFriendlyName(p.ToType)
if err != nil {
return nil, err
}
toResource := pb.StatSummaryRequest_ToResource{
ToResource: &pb.Resource{
Namespace: p.ToNamespace,
Type: toType,
Name: p.ToName,
},
}
statRequest.Outbound = &toResource
}
if p.FromName != "" || p.FromType != "" || p.FromNamespace != "" {
if p.FromNamespace == "" {
p.FromNamespace = p.Namespace
}
if p.FromType == "" {
p.FromType = resourceType
}
fromType, err := k8s.CanonicalKubernetesNameFromFriendlyName(p.FromType)
if err != nil {
return nil, err
}
fromResource := pb.StatSummaryRequest_FromResource{
FromResource: &pb.Resource{
Namespace: p.FromNamespace,
Type: fromType,
Name: p.FromName,
},
}
statRequest.Outbound = &fromResource
}
return statRequest, nil
}
// BuildResource parses input strings, typically from CLI flags, to build a
// Resource object for use in the Conduit Public API.
func BuildResource(namespace string, args ...string) (pb.Resource, error) {
switch len(args) {
case 0:
return pb.Resource{}, errors.New("No resource arguments provided")
case 1:
elems := strings.Split(args[0], "/")
switch len(elems) {
case 1:
// --namespace my-ns deploy
return buildResource(namespace, elems[0], "")
case 2:
// --namespace my-ns deploy/foo
return buildResource(namespace, elems[0], elems[1])
default:
return pb.Resource{}, errors.New("Invalid resource string: " + args[0])
}
case 2:
// --namespace my-ns deploy foo
return buildResource(namespace, args[0], args[1])
default:
return pb.Resource{}, errors.New("Too many arguments provided for resource: " + strings.Join(args, "/"))
}
}
func buildResource(namespace string, resType string, name string) (pb.Resource, error) {
canonicalType, err := k8s.CanonicalKubernetesNameFromFriendlyName(resType)
if err != nil {
return pb.Resource{}, err
}
if canonicalType == k8s.Namespaces {
// ignore --namespace flags if type is namespace
namespace = ""
}
return pb.Resource{
Namespace: namespace,
Type: canonicalType,
Name: name,
}, nil
}