forked from juju/juju
-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup.go
143 lines (125 loc) · 3.66 KB
/
setup.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
// Copyright 2021 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package proxy
import (
"context"
"encoding/json"
"fmt"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
core "k8s.io/client-go/kubernetes/typed/core/v1"
rbac "k8s.io/client-go/kubernetes/typed/rbac/v1"
)
// ControllerProxyConfig is used to configure the kubernetes resources made for
// the controller proxy objects.
type ControllerProxyConfig struct {
// Name to apply to kubernetes resources created for the controller
// proxy. This name is also used later on for discovery of the proxy config.
Name string `json:"name"`
// Namespace to create the proxy kubernetes resources in. This is ultimately
// used for discovery of the proxy settings.
Namespace string `json:"namespace"`
// RemotePort the remote port of the service to use when proxying
RemotePort string `json:"remote-port"`
// TargetService the service to target for proxying
TargetService string `json:"target-service"`
}
const (
// ProxyConfigMapKey the key to use in the configmap made for the proxy to
// describe the config key
ProxyConfigMapKey = "config"
)
// CreateControllerProxy establishes the Kubernetes resources needed for
// proxying to a Juju controller. The end result of this function is a service
// account with a set of permissions that the Juju client can use for proxying
// to a controller.
func CreateControllerProxy(
config ControllerProxyConfig,
labels labels.Set,
configI core.ConfigMapInterface,
roleI rbac.RoleInterface,
roleBindingI rbac.RoleBindingInterface,
saI core.ServiceAccountInterface,
) error {
role := &rbacv1.Role{
ObjectMeta: meta.ObjectMeta{
Labels: labels,
Name: config.Name,
},
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{""},
Resources: []string{"pods"},
Verbs: []string{"list", "get", "watch"},
},
{
APIGroups: []string{""},
Resources: []string{"services"},
Verbs: []string{"get"},
},
// The get verb below is not used directly by juju but is for
// the python lib
{
APIGroups: []string{""},
Resources: []string{"pods/portforward"},
Verbs: []string{"create", "get"},
},
},
}
role, err := roleI.Create(context.TODO(), role, meta.CreateOptions{})
if err != nil {
return fmt.Errorf("creating proxy service account role: %w", err)
}
sa := &corev1.ServiceAccount{
ObjectMeta: meta.ObjectMeta{
Labels: labels,
Name: config.Name,
},
}
sa, err = saI.Create(context.TODO(), sa, meta.CreateOptions{})
if err != nil {
return fmt.Errorf("creating proxy service account: %w", err)
}
roleBinding := &rbacv1.RoleBinding{
ObjectMeta: meta.ObjectMeta{
Labels: labels,
Name: config.Name,
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: sa.Name,
Namespace: sa.Namespace,
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Role",
Name: role.Name,
},
}
_, err = roleBindingI.Create(context.TODO(), roleBinding, meta.CreateOptions{})
if err != nil {
return fmt.Errorf("creating proxy service account role binding: %w", err)
}
configJSON, err := json.Marshal(config)
if err != nil {
return fmt.Errorf("marshalling proxy configmap data to json: %w", err)
}
cm := &corev1.ConfigMap{
ObjectMeta: meta.ObjectMeta{
Labels: labels,
Name: config.Name,
},
Data: map[string]string{
ProxyConfigMapKey: string(configJSON),
},
}
_, err = configI.Create(context.TODO(), cm, meta.CreateOptions{})
if err != nil {
return fmt.Errorf("creating proxy config map: %w", err)
}
return nil
}