github.phpd.cn/cilium/cilium@v1.6.12/pkg/workloads/runtimes.go (about) 1 // Copyright 2017-2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package workloads 16 17 import ( 18 "context" 19 "fmt" 20 "sort" 21 "strings" 22 23 "github.com/cilium/cilium/api/v1/models" 24 "github.com/cilium/cilium/pkg/endpoint" 25 "github.com/cilium/cilium/pkg/endpoint/regeneration" 26 ) 27 28 // WorkloadOwner is the interface that the owner of workloads must implement. 29 type WorkloadOwner interface { 30 regeneration.Owner 31 32 // DeleteEndpoint is called when the underlying workload has died 33 DeleteEndpoint(id string) (int, error) 34 } 35 36 var ( 37 owner WorkloadOwner 38 ) 39 40 // Owner returns the owner instance of all workloads 41 func Owner() WorkloadOwner { 42 return owner 43 } 44 45 // Init initializes the workloads package 46 func Init(o WorkloadOwner) { 47 owner = o 48 } 49 50 const ( 51 None WorkloadRuntimeType = "none" 52 Auto WorkloadRuntimeType = "auto" 53 ) 54 55 const ( 56 // EpOpt is the option name for path to endpoint 57 EpOpt = "endpoint" 58 // DatapathModeOpt is the option name for datapath mode 59 DatapathModeOpt = "datapath-mode" 60 ) 61 62 type workloadRuntimeOpt struct { 63 // description is the description of the option 64 description string 65 66 // value is the value the option has been configured to 67 value string 68 69 // validate, if set, is called to validate the value before assignment 70 validate func(value string) error 71 } 72 73 type workloadRuntimeOpts map[string]*workloadRuntimeOpt 74 75 // workloadModule is the interface that each workload module has to implement. 76 type workloadModule interface { 77 // getName must return the name of the workload 78 getName() string 79 80 // setConfig must configure the workload with the specified options. 81 // This function is called once before newClient(). 82 setConfig(opts map[string]string) error 83 84 // setConfigDummy must configure the workload with dummy configuration 85 // for testing purposes. This is a replacement for setConfig(). 86 setConfigDummy() 87 88 // getConfig must return the workload configuration. 89 getConfig() map[string]string 90 91 // newClient must initializes the workload and create a new kvstore 92 // client which implements the WorkloadRuntime interface 93 newClient() (WorkloadRuntime, error) 94 } 95 96 // WorkloadRuntimeType is the type of a container runtime 97 type WorkloadRuntimeType string 98 99 var ( 100 // registeredWorkloads is a slice of all workloads that have registered 101 // itself via registerWorkload() 102 registeredWorkloads = map[WorkloadRuntimeType]workloadModule{} 103 ) 104 105 func unregisterWorkloads() { 106 registeredWorkloads = map[WorkloadRuntimeType]workloadModule{} 107 } 108 109 func parseRuntimeType(str string) (WorkloadRuntimeType, error) { 110 switch crt := WorkloadRuntimeType(strings.ToLower(str)); crt { 111 case None, Auto: 112 return crt, nil 113 default: 114 _, ok := registeredWorkloads[crt] 115 if !ok { 116 return None, fmt.Errorf("runtime '%s' is not available", crt) 117 } 118 return crt, nil 119 } 120 } 121 122 // registerWorkload must be called by container runtimes to register themselves 123 func registerWorkload(name WorkloadRuntimeType, module workloadModule) { 124 if _, ok := registeredWorkloads[name]; ok { 125 log.Panicf("workload with name '%s' already registered", name) 126 } 127 128 registeredWorkloads[name] = module 129 } 130 131 // getWorkload finds a registered workload by name 132 func getWorkload(name WorkloadRuntimeType) workloadModule { 133 if workload, ok := registeredWorkloads[name]; ok { 134 return workload 135 } 136 137 return nil 138 } 139 140 // GetRuntimeDefaultOpt returns the default options for the given container 141 // runtime. 142 func GetRuntimeDefaultOpt(crt WorkloadRuntimeType, opt string) string { 143 opts, ok := registeredWorkloads[crt] 144 if !ok { 145 return "" 146 } 147 return opts.getConfig()[opt] 148 } 149 150 // GetRuntimeOptions returns a string representation of the container runtimes 151 // stored and the list of options for each container runtime. 152 func GetRuntimeOptions() string { 153 var crtStr []string 154 155 crs := make([]string, 0, len(registeredWorkloads)) 156 for k := range registeredWorkloads { 157 crs = append(crs, string(k)) 158 } 159 sort.Strings(crs) 160 161 for _, cr := range crs { 162 rb := registeredWorkloads[WorkloadRuntimeType(cr)] 163 cfg := rb.getConfig() 164 keys := make([]string, 0, len(cfg)) 165 for k := range cfg { 166 keys = append(keys, k) 167 } 168 sort.Strings(keys) 169 for _, k := range keys { 170 crtStr = append(crtStr, fmt.Sprintf("%s=%s", k, cfg[k])) 171 } 172 } 173 return strings.Join(crtStr, ",") 174 } 175 176 // GetDefaultEPOptsStringWithPrefix returns the defaults options for each 177 // runtime with the given prefix. 178 func GetDefaultEPOptsStringWithPrefix(prefix string) string { 179 strs := make([]string, 0, len(registeredWorkloads)) 180 crs := make([]string, 0, len(registeredWorkloads)) 181 182 for k := range registeredWorkloads { 183 crs = append(crs, string(k)) 184 } 185 sort.Strings(crs) 186 187 for _, cr := range crs { 188 v := registeredWorkloads[WorkloadRuntimeType(cr)].getConfig() 189 strs = append(strs, fmt.Sprintf("%s%s=%s", prefix, cr, v[EpOpt])) 190 } 191 192 return strings.Join(strs, ", ") 193 } 194 195 // WorkloadRuntime are the individual workload runtime operations that each 196 // workload must implement. 197 type WorkloadRuntime interface { 198 // EnableEventListener enables the event listener of the workload runtime 199 // If the workload runtime does not support events, it will return a 200 // events channel where the caller will be in charge of sending the 201 // create and stop events. 202 EnableEventListener() (eventsCh chan<- *EventMessage, err error) 203 // Status returns the status of the workload runtime. 204 Status() *models.Status 205 // IsRunning returns true if the endpoint is available and in a running 206 // state in the respective workload runtime. 207 IsRunning(ep *endpoint.Endpoint) bool 208 // IgnoreRunningWorkloads sets the runtime to ignore all running workloads. 209 IgnoreRunningWorkloads() 210 // processEvents processes events from the given event channel. 211 processEvents(events chan EventMessage) 212 // handleCreateWorkload handles the creation of the given workload, if 213 // retry is set, it keeps retrying until the workload is found running or 214 // until the workload runtime stops retrying. 215 handleCreateWorkload(id string, retry bool) 216 // workloadIDsList returns a list of workload IDs running in the workload 217 // runtime. 218 workloadIDsList(ctx context.Context) ([]string, error) 219 // GetAllInfraContainersPID returns a list of workload IDs running in the 220 // workload that represent a infra container. 221 GetAllInfraContainersPID() (map[string]int, error) 222 }