...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package nodevolumepath
17
18 import (
19 "context"
20
21 "github.com/pkg/errors"
22 "go.uber.org/fx"
23 v1 "k8s.io/api/core/v1"
24 "k8s.io/apimachinery/pkg/types"
25 "sigs.k8s.io/controller-runtime/pkg/client"
26
27 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
28 "github.com/chaos-mesh/chaos-mesh/controllers/config"
29 "github.com/chaos-mesh/chaos-mesh/pkg/selector/container"
30 "github.com/chaos-mesh/chaos-mesh/pkg/selector/generic"
31 )
32
33 var errNotSupported = errors.New("not supported")
34
35 type SelectImpl struct {
36 c client.Client
37 r client.Reader
38
39 containerSelector *container.SelectImpl
40 generic.Option
41 }
42
43 type NodeVolumePath struct {
44 *container.Container
45
46
47 volumePath string
48 }
49
50 func (n *NodeVolumePath) Id() string {
51
52 return n.Container.Id() + "/" + n.volumePath
53 }
54
55 func (impl *SelectImpl) Select(ctx context.Context, selector *v1alpha1.ContainerNodeVolumePathSelector) ([]*NodeVolumePath, error) {
56 containers, err := impl.containerSelector.Select(ctx, &selector.ContainerSelector)
57 if err != nil {
58 return nil, err
59 }
60
61 var result []*NodeVolumePath
62 for _, container := range containers {
63 for _, volume := range container.Spec.Volumes {
64 if volume.Name == selector.VolumeName {
65
66
67
68 if volume.HostPath != nil {
69 result = append(result, &NodeVolumePath{
70 Container: container,
71 volumePath: volume.HostPath.Path,
72 })
73 } else if volume.PersistentVolumeClaim != nil {
74 var pvc v1.PersistentVolumeClaim
75 impl.c.Get(ctx, types.NamespacedName{
76 Namespace: container.Namespace,
77 Name: volume.PersistentVolumeClaim.ClaimName,
78 }, &pvc)
79 if pvc.Status.Phase == v1.ClaimBound {
80 var pv v1.PersistentVolume
81 impl.c.Get(ctx, types.NamespacedName{
82 Name: pvc.Spec.VolumeName,
83 }, &pv)
84
85
86
87 if pv.Spec.HostPath != nil {
88 result = append(result, &NodeVolumePath{
89 Container: container,
90 volumePath: pv.Spec.HostPath.Path,
91 })
92 } else if pv.Spec.Local != nil {
93 result = append(result, &NodeVolumePath{
94 Container: container,
95 volumePath: pv.Spec.Local.Path,
96 })
97 } else {
98 return nil, errors.Wrap(errNotSupported, "unsupported PersistentVolume source")
99 }
100 } else {
101 return nil, errors.Wrapf(errNotSupported, "PVC is not bounded yet: pvc phase: %s", pvc.Status.Phase)
102 }
103 } else {
104 return nil, errors.Wrapf(errNotSupported, "volume source is not supported")
105 }
106 }
107 }
108 }
109
110 return result, nil
111 }
112
113 type Params struct {
114 fx.In
115
116 ContainerSelector *container.SelectImpl
117 Client client.Client
118 Reader client.Reader `name:"no-cache"`
119 }
120
121 func New(params Params) *SelectImpl {
122 return &SelectImpl{
123 params.Client,
124 params.Reader,
125 params.ContainerSelector,
126 generic.Option{
127 ClusterScoped: config.ControllerCfg.ClusterScoped,
128 TargetNamespace: config.ControllerCfg.TargetNamespace,
129 EnableFilterNamespace: config.ControllerCfg.EnableFilterNamespace,
130 },
131 }
132 }
133