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  }