/
runtimes.go
222 lines (186 loc) · 6.6 KB
/
runtimes.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
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// Copyright 2017-2018 Authors of Cilium
//
// 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 workloads
import (
"context"
"fmt"
"sort"
"strings"
"github.com/cilium/cilium/api/v1/models"
"github.com/cilium/cilium/pkg/endpoint"
"github.com/cilium/cilium/pkg/endpoint/regeneration"
)
// WorkloadOwner is the interface that the owner of workloads must implement.
type WorkloadOwner interface {
regeneration.Owner
// DeleteEndpoint is called when the underlying workload has died
DeleteEndpoint(id string) (int, error)
}
var (
owner WorkloadOwner
)
// Owner returns the owner instance of all workloads
func Owner() WorkloadOwner {
return owner
}
// Init initializes the workloads package
func Init(o WorkloadOwner) {
owner = o
}
const (
None WorkloadRuntimeType = "none"
Auto WorkloadRuntimeType = "auto"
)
const (
// EpOpt is the option name for path to endpoint
EpOpt = "endpoint"
// DatapathModeOpt is the option name for datapath mode
DatapathModeOpt = "datapath-mode"
)
type workloadRuntimeOpt struct {
// description is the description of the option
description string
// value is the value the option has been configured to
value string
// validate, if set, is called to validate the value before assignment
validate func(value string) error
}
type workloadRuntimeOpts map[string]*workloadRuntimeOpt
// workloadModule is the interface that each workload module has to implement.
type workloadModule interface {
// getName must return the name of the workload
getName() string
// setConfig must configure the workload with the specified options.
// This function is called once before newClient().
setConfig(opts map[string]string) error
// setConfigDummy must configure the workload with dummy configuration
// for testing purposes. This is a replacement for setConfig().
setConfigDummy()
// getConfig must return the workload configuration.
getConfig() map[string]string
// newClient must initializes the workload and create a new kvstore
// client which implements the WorkloadRuntime interface
newClient() (WorkloadRuntime, error)
}
// WorkloadRuntimeType is the type of a container runtime
type WorkloadRuntimeType string
var (
// registeredWorkloads is a slice of all workloads that have registered
// itself via registerWorkload()
registeredWorkloads = map[WorkloadRuntimeType]workloadModule{}
)
func unregisterWorkloads() {
registeredWorkloads = map[WorkloadRuntimeType]workloadModule{}
}
func parseRuntimeType(str string) (WorkloadRuntimeType, error) {
switch crt := WorkloadRuntimeType(strings.ToLower(str)); crt {
case None, Auto:
return crt, nil
default:
_, ok := registeredWorkloads[crt]
if !ok {
return None, fmt.Errorf("runtime '%s' is not available", crt)
}
return crt, nil
}
}
// registerWorkload must be called by container runtimes to register themselves
func registerWorkload(name WorkloadRuntimeType, module workloadModule) {
if _, ok := registeredWorkloads[name]; ok {
log.Panicf("workload with name '%s' already registered", name)
}
registeredWorkloads[name] = module
}
// getWorkload finds a registered workload by name
func getWorkload(name WorkloadRuntimeType) workloadModule {
if workload, ok := registeredWorkloads[name]; ok {
return workload
}
return nil
}
// GetRuntimeDefaultOpt returns the default options for the given container
// runtime.
func GetRuntimeDefaultOpt(crt WorkloadRuntimeType, opt string) string {
opts, ok := registeredWorkloads[crt]
if !ok {
return ""
}
return opts.getConfig()[opt]
}
// GetRuntimeOptions returns a string representation of the container runtimes
// stored and the list of options for each container runtime.
func GetRuntimeOptions() string {
var crtStr []string
crs := make([]string, 0, len(registeredWorkloads))
for k := range registeredWorkloads {
crs = append(crs, string(k))
}
sort.Strings(crs)
for _, cr := range crs {
rb := registeredWorkloads[WorkloadRuntimeType(cr)]
cfg := rb.getConfig()
keys := make([]string, 0, len(cfg))
for k := range cfg {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
crtStr = append(crtStr, fmt.Sprintf("%s=%s", k, cfg[k]))
}
}
return strings.Join(crtStr, ",")
}
// GetDefaultEPOptsStringWithPrefix returns the defaults options for each
// runtime with the given prefix.
func GetDefaultEPOptsStringWithPrefix(prefix string) string {
strs := make([]string, 0, len(registeredWorkloads))
crs := make([]string, 0, len(registeredWorkloads))
for k := range registeredWorkloads {
crs = append(crs, string(k))
}
sort.Strings(crs)
for _, cr := range crs {
v := registeredWorkloads[WorkloadRuntimeType(cr)].getConfig()
strs = append(strs, fmt.Sprintf("%s%s=%s", prefix, cr, v[EpOpt]))
}
return strings.Join(strs, ", ")
}
// WorkloadRuntime are the individual workload runtime operations that each
// workload must implement.
type WorkloadRuntime interface {
// EnableEventListener enables the event listener of the workload runtime
// If the workload runtime does not support events, it will return a
// events channel where the caller will be in charge of sending the
// create and stop events.
EnableEventListener() (eventsCh chan<- *EventMessage, err error)
// Status returns the status of the workload runtime.
Status() *models.Status
// IsRunning returns true if the endpoint is available and in a running
// state in the respective workload runtime.
IsRunning(ep *endpoint.Endpoint) bool
// IgnoreRunningWorkloads sets the runtime to ignore all running workloads.
IgnoreRunningWorkloads()
// processEvents processes events from the given event channel.
processEvents(events chan EventMessage)
// handleCreateWorkload handles the creation of the given workload, if
// retry is set, it keeps retrying until the workload is found running or
// until the workload runtime stops retrying.
handleCreateWorkload(id string, retry bool)
// workloadIDsList returns a list of workload IDs running in the workload
// runtime.
workloadIDsList(ctx context.Context) ([]string, error)
// GetAllInfraContainersPID returns a list of workload IDs running in the
// workload that represent a infra container.
GetAllInfraContainersPID() (map[string]int, error)
}