|
| 1 | +# Unified Selector |
| 2 | + |
| 3 | +## Summary |
| 4 | + |
| 5 | +The whole controller framework should do more things for the implementation of |
| 6 | +chaos. Now, every implementation of chaos selects pods by themselves. However, |
| 7 | +in order to track the running status, the controller framework should know the |
| 8 | +concrete status of every selected targets, which would be a disaster to record |
| 9 | +these status inside the implementation of every chaos :(. An unified selector |
| 10 | +framework in the controller framework could solve this problem. This RFC will |
| 11 | +talk about the design of this unified selector. |
| 12 | + |
| 13 | +## Motivation |
| 14 | + |
| 15 | +There have been a lot of problems about current selector. For example, the |
| 16 | +IOChaos should select volumes, but it selects container now (and at first, it |
| 17 | +selects pods). Some chaos use `containerName string` to select a container while |
| 18 | +some use `containerNames []string` to select several containers at one time. If |
| 19 | +we can abstract selectors into one place, these errors won't happen. The |
| 20 | +developer of every chaos will not need to consider "select" or these platform |
| 21 | +dependent things. |
| 22 | + |
| 23 | +Another benifit is that it could help the controller to track the status. With |
| 24 | +it, the controller would know which target (pod/container) has been injected and |
| 25 | +which has not. It's the first step towards the target of a standalone `Schedule` |
| 26 | +CRD. |
| 27 | + |
| 28 | +## Detailed Design |
| 29 | + |
| 30 | +Every chaos specification would define a function to get the specification of |
| 31 | +selectors: |
| 32 | + |
| 33 | +```go |
| 34 | +type StatefulObjectWithSelector interface { |
| 35 | + v1alpha1.StatefulObject |
| 36 | + |
| 37 | + GetSelectorSpecs() map[string]interface{} |
| 38 | +} |
| 39 | +``` |
| 40 | + |
| 41 | +The method `GetSelectorSpecs` will return a map from `string` to selector |
| 42 | +specification (like `struct {v1alpha1.PodSelectorSpec, v1alpha1.PodMode, |
| 43 | +v1alpha1.Value}`). The key would be the identifier of the selector, as there |
| 44 | +will be multiple selectors in one chaos specification, for example the `.` and |
| 45 | +`.Target` selectors in `NetworkChaos`. The controller will iterate this map to |
| 46 | +select every `SelectSpec`. It will construct a unified selector first, and then |
| 47 | +use this selector to `Select` targets. The unified selector may contain a lot of |
| 48 | +implementation inside. The construction would be like: |
| 49 | + |
| 50 | +```go |
| 51 | +selector := selector.New(selector.SelectorParams{ |
| 52 | + PodSelector: pod.New(r.Client, r.Reader, config.ControllerCfg.ClusterScoped, config.ControllerCfg.TargetNamespace, config.ControllerCfg.AllowedNamespaces, config.ControllerCfg.IgnoredNamespaces), |
| 53 | + ContainerSelector: container.New(r.Client, r.Reader, config.ControllerCfg.ClusterScoped, config.ControllerCfg.TargetNamespace, config.ControllerCfg.AllowedNamespaces, config.ControllerCfg.IgnoredNamespaces), |
| 54 | +}) |
| 55 | +``` |
| 56 | + |
| 57 | +With the help of dependency injection, it would be constructed easier. The |
| 58 | +`Selector` method of `PodSelector` would be like: |
| 59 | + |
| 60 | +```go |
| 61 | +func (impl *PodSelector) Select(ctx context.Context, ps *v1alpha1.PodSelector) ([]interface{}, error) |
| 62 | +``` |
| 63 | + |
| 64 | +The type of second parameter will decide which selector to use. For example, if |
| 65 | +you want to select with `*v1alpha1.PodSelector`, then the unified selector will |
| 66 | +use `*PodSelector`, and if you want to select with |
| 67 | +`*v1alpha1.ContainerSelector`, then the unified selector will use |
| 68 | +`*ContainerSelector` to select. |
| 69 | + |
| 70 | +The definition of the unified selector would be: |
| 71 | + |
| 72 | +```go |
| 73 | +func (s *Selector) Select(ctx context.Context, spec interface{}) ([]interface{}, error) |
| 74 | +``` |
| 75 | + |
| 76 | +The controller would construct the `Selector` first, and then use the `Selector` |
| 77 | +to select the chaos targets. However, as the target may have multiple type (it |
| 78 | +could be a pod, a container, a volume or an AWS machine), we can only return an |
| 79 | +`interface{}`, and the implementation of chaos would assert the type by |
| 80 | +themselves. |
| 81 | + |
| 82 | +After selecting every `selectSpecs`, the controller will iterate over selected |
| 83 | +items, and call `Apply`/`Recover` for them. All selected items, current item and |
| 84 | +the identifier of the `selectorSpec` of current item will be passed into the |
| 85 | +`Apply`/`Recover` function. |
| 86 | + |
| 87 | +## Alternatives |
| 88 | + |
| 89 | +This is a RFC about internal design, and there is little choice. If you have |
| 90 | +better idea, please comment. |
0 commit comments