From 09780bdc8c8d76a06b3399b8b464f9f299940d60 Mon Sep 17 00:00:00 2001 From: mikolaj-krzyzanowski-f3 Date: Tue, 7 Jan 2025 11:14:21 +0000 Subject: [PATCH] feat: Add NodeSelectorChaos --- api/v1alpha1/nodeselectorchaos_types.go | 58 +++ api/v1alpha1/selector.go | 9 + api/v1alpha1/zz_generated.chaosmesh.go | 149 ++++++ api/v1alpha1/zz_generated.chaosmesh_test.go | 63 +++ api/v1alpha1/zz_generated.deepcopy.go | 148 ++++++ .../zz_generated.schedule.chaosmesh.go | 9 + .../zz_generated.workflow.chaosmesh.go | 22 + .../zz_generated.workflow.chaosmesh_test.go | 8 + .../chaos-mesh.org_nodeselectorchaos.yaml | 153 ++++++ .../crd/bases/chaos-mesh.org_schedules.yaml | 100 ++++ .../bases/chaos-mesh.org_workflownodes.yaml | 133 +++++ .../crd/bases/chaos-mesh.org_workflows.yaml | 67 +++ config/crd/kustomization.yaml | 1 + controllers/chaosimpl/fx.go | 2 + controllers/chaosimpl/k8schaos/impl.go | 3 +- .../chaosimpl/nodeselectorchaos/impl.go | 122 +++++ controllers/types/types.go | 8 + .../chaos-mesh.org_nodeselectorchaos.yaml | 153 ++++++ .../crds/chaos-mesh.org_schedules.yaml | 100 ++++ .../crds/chaos-mesh.org_workflownodes.yaml | 133 +++++ .../crds/chaos-mesh.org_workflows.yaml | 67 +++ manifests/crd.yaml | 453 ++++++++++++++++++ pkg/annotation/utils.go | 3 +- pkg/ctrl/server/generated/generated.go | 7 +- pkg/ctrl/server/model/models_gen.go | 3 +- pkg/ctrl/server/schema.resolvers.go | 9 +- pkg/dashboard/swaggerdocs/docs.go | 43 ++ pkg/dashboard/swaggerdocs/swagger.json | 43 ++ pkg/dashboard/swaggerdocs/swagger.yaml | 36 ++ pkg/selector/deployment/selector.go | 93 ++++ pkg/selector/selector.go | 3 + .../api/zz_generated.frontend.chaos-mesh.ts | 1 + ui/app/src/components/NewExperiment/types.ts | 1 + .../NewExperimentNext/data/types.ts | 1 + 34 files changed, 2191 insertions(+), 13 deletions(-) create mode 100644 api/v1alpha1/nodeselectorchaos_types.go create mode 100644 config/crd/bases/chaos-mesh.org_nodeselectorchaos.yaml create mode 100644 controllers/chaosimpl/nodeselectorchaos/impl.go create mode 100644 helm/chaos-mesh/crds/chaos-mesh.org_nodeselectorchaos.yaml create mode 100644 pkg/selector/deployment/selector.go diff --git a/api/v1alpha1/nodeselectorchaos_types.go b/api/v1alpha1/nodeselectorchaos_types.go new file mode 100644 index 0000000000..5279c9e9b1 --- /dev/null +++ b/api/v1alpha1/nodeselectorchaos_types.go @@ -0,0 +1,58 @@ +// Copyright 2021 Chaos Mesh Authors.PodPVCChaos +// +// 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var ( + _ InnerObject = (*NodeSelectorChaos)(nil) + _ InnerObjectWithSelector = (*NodeSelectorChaos)(nil) +) + +// +kubebuilder:object:root=true +// +chaos-mesh:experiment +type NodeSelectorChaos struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec NodeSelectorChaosSpec `json:"spec"` + Status NodeSelectorChaosStatus `json:"status"` +} + +type NodeSelectorChaosSpec struct { + DeploymentSelectorSpec `json:"selector"` + // Key is the name of the key that will be applied to the deployment's nodeSelector field. + Key string `json:"key"` + // Value is the value assigned to the provided key. + Value string `json:"value"` + // Duration represents the duration of the chaos + // +optional + Duration *string `json:"duration,omitempty"` + // RemoteCluster represents the remote cluster where the chaos will be deployed + // +optional + RemoteCluster string `json:"remoteCluster,omitempty"` +} +type NodeSelectorChaosStatus struct { + ChaosStatus `json:",inline"` +} + +func (obj *NodeSelectorChaos) GetSelectorSpecs() map[string]interface{} { + return map[string]interface{}{ + ".": &obj.Spec.DeploymentSelector, + } +} diff --git a/api/v1alpha1/selector.go b/api/v1alpha1/selector.go index 315bde4573..d71a0b0459 100644 --- a/api/v1alpha1/selector.go +++ b/api/v1alpha1/selector.go @@ -164,3 +164,12 @@ type NodeSelectorSpec struct { // +optional ExpressionSelectors LabelSelectorRequirements `json:"expressionSelectors,omitempty" swaggerignore:"true"` } + +type DeploymentSelector struct { + // Map of namespace names to a list of deployments in that namespace. + Deployments map[string][]string `json:"deployments,omitempty"` +} + +type DeploymentSelectorSpec struct { + DeploymentSelector `json:",inline"` +} diff --git a/api/v1alpha1/zz_generated.chaosmesh.go b/api/v1alpha1/zz_generated.chaosmesh.go index 87d947c290..42573991c0 100644 --- a/api/v1alpha1/zz_generated.chaosmesh.go +++ b/api/v1alpha1/zz_generated.chaosmesh.go @@ -2125,6 +2125,144 @@ func (in *NetworkChaos) Default() { gw.Default(in) } +const KindNodeSelectorChaos = "NodeSelectorChaos" + +// IsDeleted returns whether this resource has been deleted +func (in *NodeSelectorChaos) IsDeleted() bool { + return !in.DeletionTimestamp.IsZero() +} + +// IsPaused returns whether this resource has been paused +func (in *NodeSelectorChaos) IsPaused() bool { + if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" { + return false + } + return true +} + +// GetObjectMeta would return the ObjectMeta for chaos +func (in *NodeSelectorChaos) GetObjectMeta() *metav1.ObjectMeta { + return &in.ObjectMeta +} + +// GetDuration would return the duration for chaos +func (in *NodeSelectorChaosSpec) GetDuration() (*time.Duration, error) { + if in.Duration == nil { + return nil, nil + } + duration, err := time.ParseDuration(string(*in.Duration)) + if err != nil { + return nil, err + } + return &duration, nil +} + +// GetStatus returns the status +func (in *NodeSelectorChaos) GetStatus() *ChaosStatus { + return &in.Status.ChaosStatus +} + +// GetRemoteCluster returns the remoteCluster +func (in *NodeSelectorChaos) GetRemoteCluster() string { + return in.Spec.RemoteCluster +} + +// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object. +func (in *NodeSelectorChaos) GetSpecAndMetaString() (string, error) { + spec, err := json.Marshal(in.Spec) + if err != nil { + return "", err + } + + meta := in.ObjectMeta.DeepCopy() + meta.SetResourceVersion("") + meta.SetGeneration(0) + + return string(spec) + meta.String(), nil +} + +// +kubebuilder:object:root=true + +// NodeSelectorChaosList contains a list of NodeSelectorChaos +type NodeSelectorChaosList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NodeSelectorChaos `json:"items"` +} + +func (in *NodeSelectorChaosList) DeepCopyList() GenericChaosList { + return in.DeepCopy() +} + +// ListChaos returns a list of chaos +func (in *NodeSelectorChaosList) ListChaos() []GenericChaos { + var result []GenericChaos + for _, item := range in.Items { + item := item + result = append(result, &item) + } + return result +} + +func (in *NodeSelectorChaos) DurationExceeded(now time.Time) (bool, time.Duration, error) { + duration, err := in.Spec.GetDuration() + if err != nil { + return false, 0, err + } + + if duration != nil { + stopTime := in.GetCreationTimestamp().Add(*duration) + if stopTime.Before(now) { + return true, 0, nil + } + + return false, stopTime.Sub(now), nil + } + + return false, 0, nil +} + +func (in *NodeSelectorChaos) IsOneShot() bool { + return false +} + +var NodeSelectorChaosWebhookLog = logf.Log.WithName("NodeSelectorChaos-resource") + +func (in *NodeSelectorChaos) ValidateCreate() (admission.Warnings, error) { + NodeSelectorChaosWebhookLog.V(1).Info("validate create", "name", in.Name) + return in.Validate() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (in *NodeSelectorChaos) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + NodeSelectorChaosWebhookLog.V(1).Info("validate update", "name", in.Name) + if !reflect.DeepEqual(in.Spec, old.(*NodeSelectorChaos).Spec) { + return nil, ErrCanNotUpdateChaos + } + return in.Validate() +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (in *NodeSelectorChaos) ValidateDelete() (admission.Warnings, error) { + NodeSelectorChaosWebhookLog.V(1).Info("validate delete", "name", in.Name) + + // Nothing to do? + return nil, nil +} + +var _ webhook.Validator = &NodeSelectorChaos{} + +func (in *NodeSelectorChaos) Validate() ([]string, error) { + errs := gw.Validate(in) + return nil, gw.Aggregate(errs) +} + +var _ webhook.Defaulter = &NodeSelectorChaos{} + +func (in *NodeSelectorChaos) Default() { + gw.Default(in) +} + const KindPhysicalMachineChaos = "PhysicalMachineChaos" // IsDeleted returns whether this resource has been deleted @@ -3416,6 +3554,12 @@ func init() { list: &NetworkChaosList{}, }) + SchemeBuilder.Register(&NodeSelectorChaos{}, &NodeSelectorChaosList{}) + all.register(KindNodeSelectorChaos, &ChaosKind{ + chaos: &NodeSelectorChaos{}, + list: &NodeSelectorChaosList{}, + }) + SchemeBuilder.Register(&PhysicalMachineChaos{}, &PhysicalMachineChaosList{}) all.register(KindPhysicalMachineChaos, &ChaosKind{ chaos: &PhysicalMachineChaos{}, @@ -3546,6 +3690,11 @@ func init() { list: &NetworkChaosList{}, }) + allScheduleItem.register(KindNodeSelectorChaos, &ChaosKind{ + chaos: &NodeSelectorChaos{}, + list: &NodeSelectorChaosList{}, + }) + allScheduleItem.register(KindPhysicalMachineChaos, &ChaosKind{ chaos: &PhysicalMachineChaos{}, list: &PhysicalMachineChaosList{}, diff --git a/api/v1alpha1/zz_generated.chaosmesh_test.go b/api/v1alpha1/zz_generated.chaosmesh_test.go index 66f0fe86b3..52f6971753 100644 --- a/api/v1alpha1/zz_generated.chaosmesh_test.go +++ b/api/v1alpha1/zz_generated.chaosmesh_test.go @@ -970,6 +970,69 @@ func TestNetworkChaosListChaos(t *testing.T) { chaos.ListChaos() } +func TestNodeSelectorChaosIsDeleted(t *testing.T) { + g := NewGomegaWithT(t) + + chaos := &NodeSelectorChaos{} + err := faker.FakeData(chaos) + + g.Expect(err).To(BeNil()) + + chaos.IsDeleted() +} + +func TestNodeSelectorChaosIsIsPaused(t *testing.T) { + g := NewGomegaWithT(t) + + chaos := &NodeSelectorChaos{} + err := faker.FakeData(chaos) + + g.Expect(err).To(BeNil()) + + chaos.IsPaused() +} + +func TestNodeSelectorChaosGetDuration(t *testing.T) { + g := NewGomegaWithT(t) + + chaos := &NodeSelectorChaos{} + err := faker.FakeData(chaos) + + g.Expect(err).To(BeNil()) + + chaos.Spec.GetDuration() +} + +func TestNodeSelectorChaosGetStatus(t *testing.T) { + g := NewGomegaWithT(t) + + chaos := &NodeSelectorChaos{} + err := faker.FakeData(chaos) + + g.Expect(err).To(BeNil()) + + chaos.GetStatus() +} + +func TestNodeSelectorChaosGetSpecAndMetaString(t *testing.T) { + g := NewGomegaWithT(t) + chaos := &NodeSelectorChaos{} + err := faker.FakeData(chaos) + g.Expect(err).To(BeNil()) + chaos.GetSpecAndMetaString() +} + +func TestNodeSelectorChaosListChaos(t *testing.T) { + g := NewGomegaWithT(t) + + chaos := &NodeSelectorChaosList{} + err := faker.FakeData(chaos) + + g.Expect(err).To(BeNil()) + + chaos.ListChaos() +} + func TestPhysicalMachineChaosIsDeleted(t *testing.T) { g := NewGomegaWithT(t) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 2c53cf6dc5..447c04117f 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1558,6 +1558,53 @@ func (in *DelaySpec) DeepCopy() *DelaySpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentSelector) DeepCopyInto(out *DeploymentSelector) { + *out = *in + if in.Deployments != nil { + in, out := &in.Deployments, &out.Deployments + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSelector. +func (in *DeploymentSelector) DeepCopy() *DeploymentSelector { + if in == nil { + return nil + } + out := new(DeploymentSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentSelectorSpec) DeepCopyInto(out *DeploymentSelectorSpec) { + *out = *in + in.DeploymentSelector.DeepCopyInto(&out.DeploymentSelector) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSelectorSpec. +func (in *DeploymentSelectorSpec) DeepCopy() *DeploymentSelectorSpec { + if in == nil { + return nil + } + out := new(DeploymentSelectorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskFileSpec) DeepCopyInto(out *DiskFileSpec) { *out = *in @@ -1698,6 +1745,11 @@ func (in *EmbedChaos) DeepCopyInto(out *EmbedChaos) { *out = new(NetworkChaosSpec) (*in).DeepCopyInto(*out) } + if in.NodeSelectorChaos != nil { + in, out := &in.NodeSelectorChaos, &out.NodeSelectorChaos + *out = new(NodeSelectorChaosSpec) + (*in).DeepCopyInto(*out) + } if in.PhysicalMachineChaos != nil { in, out := &in.PhysicalMachineChaos, &out.PhysicalMachineChaos *out = new(PhysicalMachineChaosSpec) @@ -3755,6 +3807,102 @@ func (in *NodeSelector) DeepCopy() *NodeSelector { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSelectorChaos) DeepCopyInto(out *NodeSelectorChaos) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSelectorChaos. +func (in *NodeSelectorChaos) DeepCopy() *NodeSelectorChaos { + if in == nil { + return nil + } + out := new(NodeSelectorChaos) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeSelectorChaos) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSelectorChaosList) DeepCopyInto(out *NodeSelectorChaosList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NodeSelectorChaos, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSelectorChaosList. +func (in *NodeSelectorChaosList) DeepCopy() *NodeSelectorChaosList { + if in == nil { + return nil + } + out := new(NodeSelectorChaosList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeSelectorChaosList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSelectorChaosSpec) DeepCopyInto(out *NodeSelectorChaosSpec) { + *out = *in + in.DeploymentSelectorSpec.DeepCopyInto(&out.DeploymentSelectorSpec) + if in.Duration != nil { + in, out := &in.Duration, &out.Duration + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSelectorChaosSpec. +func (in *NodeSelectorChaosSpec) DeepCopy() *NodeSelectorChaosSpec { + if in == nil { + return nil + } + out := new(NodeSelectorChaosSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSelectorChaosStatus) DeepCopyInto(out *NodeSelectorChaosStatus) { + *out = *in + in.ChaosStatus.DeepCopyInto(&out.ChaosStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSelectorChaosStatus. +func (in *NodeSelectorChaosStatus) DeepCopy() *NodeSelectorChaosStatus { + if in == nil { + return nil + } + out := new(NodeSelectorChaosStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeSelectorSpec) DeepCopyInto(out *NodeSelectorSpec) { *out = *in diff --git a/api/v1alpha1/zz_generated.schedule.chaosmesh.go b/api/v1alpha1/zz_generated.schedule.chaosmesh.go index 114e77d5e1..c68016c830 100644 --- a/api/v1alpha1/zz_generated.schedule.chaosmesh.go +++ b/api/v1alpha1/zz_generated.schedule.chaosmesh.go @@ -39,6 +39,7 @@ const ( ScheduleTypeK8SChaos ScheduleTemplateType = "K8SChaos" ScheduleTypeKernelChaos ScheduleTemplateType = "KernelChaos" ScheduleTypeNetworkChaos ScheduleTemplateType = "NetworkChaos" + ScheduleTypeNodeSelectorChaos ScheduleTemplateType = "NodeSelectorChaos" ScheduleTypePhysicalMachineChaos ScheduleTemplateType = "PhysicalMachineChaos" ScheduleTypePodChaos ScheduleTemplateType = "PodChaos" ScheduleTypePodPVCChaos ScheduleTemplateType = "PodPVCChaos" @@ -66,6 +67,7 @@ var allScheduleTemplateType = []ScheduleTemplateType{ ScheduleTypeK8SChaos, ScheduleTypeKernelChaos, ScheduleTypeNetworkChaos, + ScheduleTypeNodeSelectorChaos, ScheduleTypePhysicalMachineChaos, ScheduleTypePodChaos, ScheduleTypePodPVCChaos, @@ -139,6 +141,10 @@ func (it *ScheduleItem) SpawnNewObject(templateType ScheduleTemplateType) (Gener result := NetworkChaos{} result.Spec = *it.NetworkChaos return &result, nil + case ScheduleTypeNodeSelectorChaos: + result := NodeSelectorChaos{} + result.Spec = *it.NodeSelectorChaos + return &result, nil case ScheduleTypePhysicalMachineChaos: result := PhysicalMachineChaos{} result.Spec = *it.PhysicalMachineChaos @@ -224,6 +230,9 @@ func (it *ScheduleItem) RestoreChaosSpec(root interface{}) error { case *NetworkChaos: *it.NetworkChaos = chaos.Spec return nil + case *NodeSelectorChaos: + *it.NodeSelectorChaos = chaos.Spec + return nil case *PhysicalMachineChaos: *it.PhysicalMachineChaos = chaos.Spec return nil diff --git a/api/v1alpha1/zz_generated.workflow.chaosmesh.go b/api/v1alpha1/zz_generated.workflow.chaosmesh.go index 37d54b71da..9ec26cd66e 100644 --- a/api/v1alpha1/zz_generated.workflow.chaosmesh.go +++ b/api/v1alpha1/zz_generated.workflow.chaosmesh.go @@ -39,6 +39,7 @@ const ( TypeK8SChaos TemplateType = "K8SChaos" TypeKernelChaos TemplateType = "KernelChaos" TypeNetworkChaos TemplateType = "NetworkChaos" + TypeNodeSelectorChaos TemplateType = "NodeSelectorChaos" TypePhysicalMachineChaos TemplateType = "PhysicalMachineChaos" TypePodChaos TemplateType = "PodChaos" TypePodPVCChaos TemplateType = "PodPVCChaos" @@ -66,6 +67,7 @@ var allChaosTemplateType = []TemplateType{ TypeK8SChaos, TypeKernelChaos, TypeNetworkChaos, + TypeNodeSelectorChaos, TypePhysicalMachineChaos, TypePodChaos, TypePodPVCChaos, @@ -108,6 +110,8 @@ type EmbedChaos struct { // +optional NetworkChaos *NetworkChaosSpec `json:"networkChaos,omitempty"` // +optional + NodeSelectorChaos *NodeSelectorChaosSpec `json:"nodeselectorChaos,omitempty"` + // +optional PhysicalMachineChaos *PhysicalMachineChaosSpec `json:"physicalmachineChaos,omitempty"` // +optional PodChaos *PodChaosSpec `json:"podChaos,omitempty"` @@ -186,6 +190,10 @@ func (it *EmbedChaos) SpawnNewObject(templateType TemplateType) (GenericChaos, e result := NetworkChaos{} result.Spec = *it.NetworkChaos return &result, nil + case TypeNodeSelectorChaos: + result := NodeSelectorChaos{} + result.Spec = *it.NodeSelectorChaos + return &result, nil case TypePhysicalMachineChaos: result := PhysicalMachineChaos{} result.Spec = *it.PhysicalMachineChaos @@ -267,6 +275,9 @@ func (it *EmbedChaos) RestoreChaosSpec(root interface{}) error { case *NetworkChaos: *it.NetworkChaos = chaos.Spec return nil + case *NodeSelectorChaos: + *it.NodeSelectorChaos = chaos.Spec + return nil case *PhysicalMachineChaos: *it.PhysicalMachineChaos = chaos.Spec return nil @@ -341,6 +352,9 @@ func (it *EmbedChaos) SpawnNewList(templateType TemplateType) (GenericChaosList, case TypeNetworkChaos: result := NetworkChaosList{} return &result, nil + case TypeNodeSelectorChaos: + result := NodeSelectorChaosList{} + return &result, nil case TypePhysicalMachineChaos: result := PhysicalMachineChaosList{} return &result, nil @@ -488,6 +502,14 @@ func (in *NetworkChaosList) GetItems() []GenericChaos { } return result } +func (in *NodeSelectorChaosList) GetItems() []GenericChaos { + var result []GenericChaos + for _, item := range in.Items { + item := item + result = append(result, &item) + } + return result +} func (in *PhysicalMachineChaosList) GetItems() []GenericChaos { var result []GenericChaos for _, item := range in.Items { diff --git a/api/v1alpha1/zz_generated.workflow.chaosmesh_test.go b/api/v1alpha1/zz_generated.workflow.chaosmesh_test.go index ac84c8a8b8..74dd38f3f0 100644 --- a/api/v1alpha1/zz_generated.workflow.chaosmesh_test.go +++ b/api/v1alpha1/zz_generated.workflow.chaosmesh_test.go @@ -143,6 +143,14 @@ func TestChaosKindMapShouldContainsNetworkChaos(t *testing.T) { _, ok := all.kinds[string(requiredType)] g.Expect(ok).To(Equal(true), "all kinds map should contains this type", requiredType) } +func TestChaosKindMapShouldContainsNodeSelectorChaos(t *testing.T) { + g := NewGomegaWithT(t) + var requiredType TemplateType + requiredType = TypeNodeSelectorChaos + + _, ok := all.kinds[string(requiredType)] + g.Expect(ok).To(Equal(true), "all kinds map should contains this type", requiredType) +} func TestChaosKindMapShouldContainsPhysicalMachineChaos(t *testing.T) { g := NewGomegaWithT(t) var requiredType TemplateType diff --git a/config/crd/bases/chaos-mesh.org_nodeselectorchaos.yaml b/config/crd/bases/chaos-mesh.org_nodeselectorchaos.yaml new file mode 100644 index 0000000000..9efba320a9 --- /dev/null +++ b/config/crd/bases/chaos-mesh.org_nodeselectorchaos.yaml @@ -0,0 +1,153 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: nodeselectorchaos.chaos-mesh.org +spec: + group: chaos-mesh.org + names: + kind: NodeSelectorChaos + listKind: NodeSelectorChaosList + plural: nodeselectorchaos + singular: nodeselectorchaos + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to the + deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where the + chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments in + that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object + status: + properties: + conditions: + description: Conditions represents the current global condition of + the chaos + items: + properties: + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + experiment: + description: Experiment records the last experiment state. + properties: + containerRecords: + description: Records are used to track the running status + items: + properties: + events: + description: Events are the essential details about the + injections and recoveries + items: + properties: + message: + description: Message is the detail message, e.g. the + reason why we failed to inject the chaos + type: string + operation: + description: Operation represents the operation we + are doing, when we crate this event + type: string + timestamp: + description: Timestamp is time when we create this + event + format: date-time + type: string + type: + description: Type means the stage of this event + type: string + required: + - operation + - timestamp + - type + type: object + type: array + id: + type: string + injectedCount: + description: InjectedCount is a counter to record the sum + of successful injections + type: integer + phase: + type: string + recoveredCount: + description: RecoveredCount is a counter to record the sum + of successful recoveries + type: integer + selectorKey: + type: string + required: + - id + - injectedCount + - phase + - recoveredCount + - selectorKey + type: object + type: array + desiredPhase: + enum: + - Run + - Stop + type: string + type: object + required: + - experiment + type: object + required: + - spec + - status + type: object + served: true + storage: true diff --git a/config/crd/bases/chaos-mesh.org_schedules.yaml b/config/crd/bases/chaos-mesh.org_schedules.yaml index d1c6d60e1b..a216dcdf1c 100644 --- a/config/crd/bases/chaos-mesh.org_schedules.yaml +++ b/config/crd/bases/chaos-mesh.org_schedules.yaml @@ -2273,6 +2273,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to + the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -6373,6 +6405,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the + chaos + type: string + key: + description: Key is the name of the key that will be + applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of + deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -10240,6 +10306,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of + the chaos + type: string + key: + description: Key is the name of the key that will + be applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list + of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the + provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos diff --git a/config/crd/bases/chaos-mesh.org_workflownodes.yaml b/config/crd/bases/chaos-mesh.org_workflownodes.yaml index 86c8a1f84c..e0f8dd7686 100644 --- a/config/crd/bases/chaos-mesh.org_workflownodes.yaml +++ b/config/crd/bases/chaos-mesh.org_workflownodes.yaml @@ -2294,6 +2294,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to + the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -5917,6 +5949,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied + to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -10116,6 +10180,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of + the chaos + type: string + key: + description: Key is the name of the key that will + be applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list + of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the + provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -14112,6 +14210,41 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration + of the chaos + type: string + key: + description: Key is the name of the key that + will be applied to the deployment's nodeSelector + field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a + list of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to + the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos diff --git a/config/crd/bases/chaos-mesh.org_workflows.yaml b/config/crd/bases/chaos-mesh.org_workflows.yaml index 9144cef58b..87250c8018 100644 --- a/config/crd/bases/chaos-mesh.org_workflows.yaml +++ b/config/crd/bases/chaos-mesh.org_workflows.yaml @@ -2382,6 +2382,39 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied + to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -6146,6 +6179,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the + chaos + type: string + key: + description: Key is the name of the key that will be + applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of + deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 3d3ecc1990..78d2ea40b1 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -34,6 +34,7 @@ resources: - bases/chaos-mesh.org_resourcescalechaos.yaml - bases/chaos-mesh.org_podpvcchaos.yaml - bases/chaos-mesh.org_certificatechaos.yaml +- bases/chaos-mesh.org_nodeselectorchaos.yaml # +kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: diff --git a/controllers/chaosimpl/fx.go b/controllers/chaosimpl/fx.go index 44cc6b9b5e..c53d857013 100644 --- a/controllers/chaosimpl/fx.go +++ b/controllers/chaosimpl/fx.go @@ -33,6 +33,7 @@ import ( "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/k8schaos" "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/kernelchaos" "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/networkchaos" + "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/nodeselectorchaos" "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/physicalmachinechaos" "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/podchaos" "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/podpvcchaos" @@ -66,5 +67,6 @@ var AllImpl = fx.Options( rollingrestartchaos.Module, podpvcchaos.Module, certificatechaos.Module, + nodeselectorchaos.Module, utils.Module) diff --git a/controllers/chaosimpl/k8schaos/impl.go b/controllers/chaosimpl/k8schaos/impl.go index ad1eea2878..a1e9113eb8 100644 --- a/controllers/chaosimpl/k8schaos/impl.go +++ b/controllers/chaosimpl/k8schaos/impl.go @@ -23,7 +23,7 @@ import ( "github.com/go-logr/logr" "go.uber.org/fx" - "gopkg.in/yaml.v3" + "gopkg.in/yaml.v2" apiErrors "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -32,6 +32,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" + impltypes "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/types" ) diff --git a/controllers/chaosimpl/nodeselectorchaos/impl.go b/controllers/chaosimpl/nodeselectorchaos/impl.go new file mode 100644 index 0000000000..2449a2dbf7 --- /dev/null +++ b/controllers/chaosimpl/nodeselectorchaos/impl.go @@ -0,0 +1,122 @@ +// Copyright 2021 Chaos Mesh Authors.PodPVCChaos +// +// 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 nodeselectorchaos + +import ( + "context" + "errors" + "fmt" + "strings" + + "github.com/go-logr/logr" + "go.uber.org/fx" + v1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" + + chaosimpltypes "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/types" + "github.com/chaos-mesh/chaos-mesh/controllers/utils/controller" +) + +type Impl struct { + client.Client + Log logr.Logger +} + +func (i *Impl) Apply(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) { + chaos, ok := obj.(*v1alpha1.NodeSelectorChaos) + + if !ok { + err := errors.New("not NodeSelectorChaos") + i.Log.Error(err, "casting InnerObject to NodeSelectorChaos") + return v1alpha1.NotInjected, err + } + + name, err := controller.ParseNamespacedName(records[index].Id) + if err != nil { + i.Log.Error(err, "parsing record name") + return v1alpha1.NotInjected, err + } + + var deployment v1.Deployment + err = i.Client.Get(ctx, name, &deployment) + if err != nil { + i.Log.Error(err, "getting deployment") + return v1alpha1.NotInjected, err + } + + data := []byte(fmt.Sprintf(`{"spec": {"template": {"spec": {"nodeSelector": {"%s" :"%s"}}}}}`, chaos.Spec.Key, chaos.Spec.Value)) + patch := client.RawPatch(types.MergePatchType, data) + err = i.Client.Patch(ctx, &deployment, patch) + if err != nil { + i.Log.Error(err, "patching deployment") + return v1alpha1.NotInjected, err + } + + return v1alpha1.Injected, nil +} + +func (i *Impl) Recover(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) { + chaos, ok := obj.(*v1alpha1.NodeSelectorChaos) + + if !ok { + err := errors.New("not NodeSelectorChaos") + i.Log.Error(err, "casting InnerObject to NodeSelectorChaos") + return v1alpha1.NotInjected, err + } + + name, err := controller.ParseNamespacedName(records[index].Id) + if err != nil { + i.Log.Error(err, "parsing record name") + return v1alpha1.Injected, err + } + + var deployment v1.Deployment + err = i.Client.Get(ctx, name, &deployment) + if err != nil { + i.Log.Error(err, "getting deployment") + return v1alpha1.Injected, err + } + + escapedKey := strings.ReplaceAll(chaos.Spec.Key, "/", "~1") + data := []byte(fmt.Sprintf(`[{"op": "remove", "path": "/spec/template/spec/nodeSelector/%s"}]`, escapedKey)) + patch := client.RawPatch(types.JSONPatchType, data) + err = i.Client.Patch(ctx, &deployment, patch) + if err != nil { + i.Log.Error(err, "patching deployment") + return v1alpha1.Injected, err + } + + return v1alpha1.NotInjected, nil +} + +func NewImpl(c client.Client, log logr.Logger) *chaosimpltypes.ChaosImplPair { + return &chaosimpltypes.ChaosImplPair{ + Name: "nodeselectorchaos", + Object: &v1alpha1.NodeSelectorChaos{}, + Impl: &Impl{c, log.WithName("nodeselectorchaos")}, + ObjectList: &v1alpha1.NodeSelectorChaosList{}, + } +} + +var Module = fx.Provide( + fx.Annotated{ + Group: "impl", + Target: NewImpl, + }, +) diff --git a/controllers/types/types.go b/controllers/types/types.go index 49eb2753b9..a929fc3065 100644 --- a/controllers/types/types.go +++ b/controllers/types/types.go @@ -156,6 +156,14 @@ var ChaosObjects = fx.Supply( Object: &v1alpha1.CiliumChaos{}, }, }, + + fx.Annotated{ + Group: "objs", + Target: Object{ + Name: "nodeselectorchaos", + Object: &v1alpha1.NodeSelectorChaos{}, + }, + }, ) // WebhookObject only used for registration the diff --git a/helm/chaos-mesh/crds/chaos-mesh.org_nodeselectorchaos.yaml b/helm/chaos-mesh/crds/chaos-mesh.org_nodeselectorchaos.yaml new file mode 100644 index 0000000000..9efba320a9 --- /dev/null +++ b/helm/chaos-mesh/crds/chaos-mesh.org_nodeselectorchaos.yaml @@ -0,0 +1,153 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: nodeselectorchaos.chaos-mesh.org +spec: + group: chaos-mesh.org + names: + kind: NodeSelectorChaos + listKind: NodeSelectorChaosList + plural: nodeselectorchaos + singular: nodeselectorchaos + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to the + deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where the + chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments in + that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object + status: + properties: + conditions: + description: Conditions represents the current global condition of + the chaos + items: + properties: + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + experiment: + description: Experiment records the last experiment state. + properties: + containerRecords: + description: Records are used to track the running status + items: + properties: + events: + description: Events are the essential details about the + injections and recoveries + items: + properties: + message: + description: Message is the detail message, e.g. the + reason why we failed to inject the chaos + type: string + operation: + description: Operation represents the operation we + are doing, when we crate this event + type: string + timestamp: + description: Timestamp is time when we create this + event + format: date-time + type: string + type: + description: Type means the stage of this event + type: string + required: + - operation + - timestamp + - type + type: object + type: array + id: + type: string + injectedCount: + description: InjectedCount is a counter to record the sum + of successful injections + type: integer + phase: + type: string + recoveredCount: + description: RecoveredCount is a counter to record the sum + of successful recoveries + type: integer + selectorKey: + type: string + required: + - id + - injectedCount + - phase + - recoveredCount + - selectorKey + type: object + type: array + desiredPhase: + enum: + - Run + - Stop + type: string + type: object + required: + - experiment + type: object + required: + - spec + - status + type: object + served: true + storage: true diff --git a/helm/chaos-mesh/crds/chaos-mesh.org_schedules.yaml b/helm/chaos-mesh/crds/chaos-mesh.org_schedules.yaml index d1c6d60e1b..a216dcdf1c 100644 --- a/helm/chaos-mesh/crds/chaos-mesh.org_schedules.yaml +++ b/helm/chaos-mesh/crds/chaos-mesh.org_schedules.yaml @@ -2273,6 +2273,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to + the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -6373,6 +6405,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the + chaos + type: string + key: + description: Key is the name of the key that will be + applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of + deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -10240,6 +10306,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of + the chaos + type: string + key: + description: Key is the name of the key that will + be applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list + of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the + provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos diff --git a/helm/chaos-mesh/crds/chaos-mesh.org_workflownodes.yaml b/helm/chaos-mesh/crds/chaos-mesh.org_workflownodes.yaml index 86c8a1f84c..e0f8dd7686 100644 --- a/helm/chaos-mesh/crds/chaos-mesh.org_workflownodes.yaml +++ b/helm/chaos-mesh/crds/chaos-mesh.org_workflownodes.yaml @@ -2294,6 +2294,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to + the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -5917,6 +5949,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied + to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -10116,6 +10180,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of + the chaos + type: string + key: + description: Key is the name of the key that will + be applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list + of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the + provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -14112,6 +14210,41 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration + of the chaos + type: string + key: + description: Key is the name of the key that + will be applied to the deployment's nodeSelector + field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a + list of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to + the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos diff --git a/helm/chaos-mesh/crds/chaos-mesh.org_workflows.yaml b/helm/chaos-mesh/crds/chaos-mesh.org_workflows.yaml index 9144cef58b..87250c8018 100644 --- a/helm/chaos-mesh/crds/chaos-mesh.org_workflows.yaml +++ b/helm/chaos-mesh/crds/chaos-mesh.org_workflows.yaml @@ -2382,6 +2382,39 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied + to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -6146,6 +6179,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the + chaos + type: string + key: + description: Key is the name of the key that will be + applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of + deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos diff --git a/manifests/crd.yaml b/manifests/crd.yaml index 98c0717302..0a24076173 100644 --- a/manifests/crd.yaml +++ b/manifests/crd.yaml @@ -4203,6 +4203,159 @@ spec: --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: nodeselectorchaos.chaos-mesh.org +spec: + group: chaos-mesh.org + names: + kind: NodeSelectorChaos + listKind: NodeSelectorChaosList + plural: nodeselectorchaos + singular: nodeselectorchaos + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to the + deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where the + chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments in + that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object + status: + properties: + conditions: + description: Conditions represents the current global condition of + the chaos + items: + properties: + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + experiment: + description: Experiment records the last experiment state. + properties: + containerRecords: + description: Records are used to track the running status + items: + properties: + events: + description: Events are the essential details about the + injections and recoveries + items: + properties: + message: + description: Message is the detail message, e.g. the + reason why we failed to inject the chaos + type: string + operation: + description: Operation represents the operation we + are doing, when we crate this event + type: string + timestamp: + description: Timestamp is time when we create this + event + format: date-time + type: string + type: + description: Type means the stage of this event + type: string + required: + - operation + - timestamp + - type + type: object + type: array + id: + type: string + injectedCount: + description: InjectedCount is a counter to record the sum + of successful injections + type: integer + phase: + type: string + recoveredCount: + description: RecoveredCount is a counter to record the sum + of successful recoveries + type: integer + selectorKey: + type: string + required: + - id + - injectedCount + - phase + - recoveredCount + - selectorKey + type: object + type: array + desiredPhase: + enum: + - Run + - Stop + type: string + type: object + required: + - experiment + type: object + required: + - spec + - status + type: object + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.13.0 @@ -9254,6 +9407,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to + the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -13354,6 +13539,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the + chaos + type: string + key: + description: Key is the name of the key that will be + applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of + deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -17221,6 +17440,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of + the chaos + type: string + key: + description: Key is the name of the key that will + be applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list + of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the + provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -27459,6 +27712,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied to + the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -31082,6 +31367,38 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied + to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster where + the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -35281,6 +35598,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of + the chaos + type: string + key: + description: Key is the name of the key that will + be applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list + of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the + provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -39277,6 +39628,41 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration + of the chaos + type: string + key: + description: Key is the name of the key that + will be applied to the deployment's nodeSelector + field. + type: string + remoteCluster: + description: RemoteCluster represents the remote + cluster where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a + list of deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to + the provided key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -53892,6 +54278,39 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the chaos + type: string + key: + description: Key is the name of the key that will be applied + to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments + in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos @@ -57656,6 +58075,40 @@ spec: - mode - selector type: object + nodeselectorChaos: + properties: + duration: + description: Duration represents the duration of the + chaos + type: string + key: + description: Key is the name of the key that will be + applied to the deployment's nodeSelector field. + type: string + remoteCluster: + description: RemoteCluster represents the remote cluster + where the chaos will be deployed + type: string + selector: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of + deployments in that namespace. + type: object + type: object + value: + description: Value is the value assigned to the provided + key. + type: string + required: + - key + - selector + - value + type: object physicalmachineChaos: description: PhysicalMachineChaosSpec defines the desired state of PhysicalMachineChaos diff --git a/pkg/annotation/utils.go b/pkg/annotation/utils.go index 1894f978f4..d6072866c6 100644 --- a/pkg/annotation/utils.go +++ b/pkg/annotation/utils.go @@ -32,7 +32,8 @@ func GenKeyForImage(pc *v1alpha1.PodChaos, containerName string, isInit bool) st } else { containerName += "-normal" } - imageKey := fmt.Sprintf("%s-%s-%s-%s-image", AnnotationPrefix, pc.Name, pc.Spec.Action, containerName) + imageKey := fmt.Sprintf("%s-%s-%s-%s-image", + AnnotationPrefix, pc.Name, pc.Spec.Action, containerName) // name part of annotation must be no more than 63 characters. // If the key is too long, we just use containerName as the key of annotation. diff --git a/pkg/ctrl/server/generated/generated.go b/pkg/ctrl/server/generated/generated.go index 5c858abc1f..f090020243 100644 --- a/pkg/ctrl/server/generated/generated.go +++ b/pkg/ctrl/server/generated/generated.go @@ -14,13 +14,12 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/introspection" + "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" + "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/server/model" gqlparser "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" - v1 "k8s.io/api/core/v1" + "k8s.io/api/core/v1" v11 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" - "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/server/model" ) // region ************************** generated!.gotpl ************************** diff --git a/pkg/ctrl/server/model/models_gen.go b/pkg/ctrl/server/model/models_gen.go index deeb57aebd..24fbd67f5a 100644 --- a/pkg/ctrl/server/model/models_gen.go +++ b/pkg/ctrl/server/model/models_gen.go @@ -7,9 +7,8 @@ import ( "io" "strconv" - v1 "k8s.io/api/core/v1" - "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" + "k8s.io/api/core/v1" ) type Cgroups struct { diff --git a/pkg/ctrl/server/schema.resolvers.go b/pkg/ctrl/server/schema.resolvers.go index 3bd2f6d4ef..94a35178b3 100644 --- a/pkg/ctrl/server/schema.resolvers.go +++ b/pkg/ctrl/server/schema.resolvers.go @@ -12,15 +12,14 @@ import ( "io" "time" - v1 "k8s.io/api/core/v1" - v11 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/server/generated" "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/server/model" podSelector "github.com/chaos-mesh/chaos-mesh/pkg/selector/pod" + "k8s.io/api/core/v1" + v11 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" ) func (r *attrOverrideSpecResolver) Ino(ctx context.Context, obj *v1alpha1.AttrOverrideSpec) (*int, error) { diff --git a/pkg/dashboard/swaggerdocs/docs.go b/pkg/dashboard/swaggerdocs/docs.go index b39ee18c32..fbd098db4d 100644 --- a/pkg/dashboard/swaggerdocs/docs.go +++ b/pkg/dashboard/swaggerdocs/docs.go @@ -5584,6 +5584,10 @@ const docTemplate = `{ "description": "+optional", "$ref": "#/definitions/v1alpha1.NetworkChaosSpec" }, + "nodeselectorChaos": { + "description": "+optional", + "$ref": "#/definitions/v1alpha1.NodeSelectorChaosSpec" + }, "physicalmachineChaos": { "description": "+optional", "$ref": "#/definitions/v1alpha1.PhysicalMachineChaosSpec" @@ -7272,6 +7276,37 @@ const docTemplate = `{ } } }, + "v1alpha1.NodeSelectorChaosSpec": { + "type": "object", + "properties": { + "deployments": { + "description": "Map of namespace names to a list of deployments in that namespace.", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "duration": { + "description": "Duration represents the duration of the chaos\n+optional", + "type": "string" + }, + "key": { + "description": "Key is the name of the key that will be applied to the deployment's nodeSelector field.", + "type": "string" + }, + "remoteCluster": { + "description": "RemoteCluster represents the remote cluster where the chaos will be deployed\n+optional", + "type": "string" + }, + "value": { + "description": "Value is the value assigned to the provided key.", + "type": "string" + } + } + }, "v1alpha1.NodeSelectorSpec": { "type": "object", "properties": { @@ -8201,6 +8236,10 @@ const docTemplate = `{ "description": "+optional", "$ref": "#/definitions/v1alpha1.NetworkChaosSpec" }, + "nodeselectorChaos": { + "description": "+optional", + "$ref": "#/definitions/v1alpha1.NodeSelectorChaosSpec" + }, "physicalmachineChaos": { "description": "+optional", "$ref": "#/definitions/v1alpha1.PhysicalMachineChaosSpec" @@ -8588,6 +8627,10 @@ const docTemplate = `{ "description": "+optional", "$ref": "#/definitions/v1alpha1.NetworkChaosSpec" }, + "nodeselectorChaos": { + "description": "+optional", + "$ref": "#/definitions/v1alpha1.NodeSelectorChaosSpec" + }, "physicalmachineChaos": { "description": "+optional", "$ref": "#/definitions/v1alpha1.PhysicalMachineChaosSpec" diff --git a/pkg/dashboard/swaggerdocs/swagger.json b/pkg/dashboard/swaggerdocs/swagger.json index f7c625587c..e822b56c59 100644 --- a/pkg/dashboard/swaggerdocs/swagger.json +++ b/pkg/dashboard/swaggerdocs/swagger.json @@ -5576,6 +5576,10 @@ "description": "+optional", "$ref": "#/definitions/v1alpha1.NetworkChaosSpec" }, + "nodeselectorChaos": { + "description": "+optional", + "$ref": "#/definitions/v1alpha1.NodeSelectorChaosSpec" + }, "physicalmachineChaos": { "description": "+optional", "$ref": "#/definitions/v1alpha1.PhysicalMachineChaosSpec" @@ -7264,6 +7268,37 @@ } } }, + "v1alpha1.NodeSelectorChaosSpec": { + "type": "object", + "properties": { + "deployments": { + "description": "Map of namespace names to a list of deployments in that namespace.", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "duration": { + "description": "Duration represents the duration of the chaos\n+optional", + "type": "string" + }, + "key": { + "description": "Key is the name of the key that will be applied to the deployment's nodeSelector field.", + "type": "string" + }, + "remoteCluster": { + "description": "RemoteCluster represents the remote cluster where the chaos will be deployed\n+optional", + "type": "string" + }, + "value": { + "description": "Value is the value assigned to the provided key.", + "type": "string" + } + } + }, "v1alpha1.NodeSelectorSpec": { "type": "object", "properties": { @@ -8193,6 +8228,10 @@ "description": "+optional", "$ref": "#/definitions/v1alpha1.NetworkChaosSpec" }, + "nodeselectorChaos": { + "description": "+optional", + "$ref": "#/definitions/v1alpha1.NodeSelectorChaosSpec" + }, "physicalmachineChaos": { "description": "+optional", "$ref": "#/definitions/v1alpha1.PhysicalMachineChaosSpec" @@ -8580,6 +8619,10 @@ "description": "+optional", "$ref": "#/definitions/v1alpha1.NetworkChaosSpec" }, + "nodeselectorChaos": { + "description": "+optional", + "$ref": "#/definitions/v1alpha1.NodeSelectorChaosSpec" + }, "physicalmachineChaos": { "description": "+optional", "$ref": "#/definitions/v1alpha1.PhysicalMachineChaosSpec" diff --git a/pkg/dashboard/swaggerdocs/swagger.yaml b/pkg/dashboard/swaggerdocs/swagger.yaml index e0e5f107a1..fcdd22e992 100644 --- a/pkg/dashboard/swaggerdocs/swagger.yaml +++ b/pkg/dashboard/swaggerdocs/swagger.yaml @@ -4025,6 +4025,9 @@ definitions: networkChaos: $ref: '#/definitions/v1alpha1.NetworkChaosSpec' description: +optional + nodeselectorChaos: + $ref: '#/definitions/v1alpha1.NodeSelectorChaosSpec' + description: +optional physicalmachineChaos: $ref: '#/definitions/v1alpha1.PhysicalMachineChaosSpec' description: +optional @@ -5735,6 +5738,33 @@ definitions: description: only impact egress traffic to these IP addresses type: string type: object + v1alpha1.NodeSelectorChaosSpec: + properties: + deployments: + additionalProperties: + items: + type: string + type: array + description: Map of namespace names to a list of deployments in that namespace. + type: object + duration: + description: |- + Duration represents the duration of the chaos + +optional + type: string + key: + description: Key is the name of the key that will be applied to the deployment's + nodeSelector field. + type: string + remoteCluster: + description: |- + RemoteCluster represents the remote cluster where the chaos will be deployed + +optional + type: string + value: + description: Value is the value assigned to the provided key. + type: string + type: object v1alpha1.NodeSelectorSpec: properties: labelSelectors: @@ -6811,6 +6841,9 @@ definitions: networkChaos: $ref: '#/definitions/v1alpha1.NetworkChaosSpec' description: +optional + nodeselectorChaos: + $ref: '#/definitions/v1alpha1.NodeSelectorChaosSpec' + description: +optional physicalmachineChaos: $ref: '#/definitions/v1alpha1.PhysicalMachineChaosSpec' description: +optional @@ -7236,6 +7269,9 @@ definitions: networkChaos: $ref: '#/definitions/v1alpha1.NetworkChaosSpec' description: +optional + nodeselectorChaos: + $ref: '#/definitions/v1alpha1.NodeSelectorChaosSpec' + description: +optional physicalmachineChaos: $ref: '#/definitions/v1alpha1.PhysicalMachineChaosSpec' description: +optional diff --git a/pkg/selector/deployment/selector.go b/pkg/selector/deployment/selector.go new file mode 100644 index 0000000000..2553eb6aae --- /dev/null +++ b/pkg/selector/deployment/selector.go @@ -0,0 +1,93 @@ +// Copyright 2021 Chaos Mesh Authors.PodPVCChaos +// +// 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 deployment + +import ( + "context" + + v1 "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + ctrl "sigs.k8s.io/controller-runtime" + + "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" +) + +type Deployment struct { + v1.Deployment +} + +func (d *Deployment) Id() string { + return (types.NamespacedName{ + Name: d.Name, + Namespace: d.Namespace, + }).String() +} + +type SelectImpl struct{} + +func (impl *SelectImpl) Select(ctx context.Context, selector *v1alpha1.DeploymentSelector) ([]*Deployment, error) { + if selector == nil { + return []*Deployment{}, nil + } + + client, err := kubernetesClient() + if err != nil { + return []*Deployment{}, err + } + + var deployments []*Deployment + for namespace, names := range selector.Deployments { + deploymentList, err := client.AppsV1().Deployments(namespace).List(ctx, metav1.ListOptions{}) + if err != nil { + return []*Deployment{}, err + } + + matched := match(deploymentList, names) + deployments = append(deployments, matched...) + + } + + return deployments, nil +} + +func match(list *v1.DeploymentList, names []string) []*Deployment { + var deployments []*Deployment + for _, selectorName := range names { + for _, deployment := range list.Items { + if selectorName == deployment.Name { + deployments = append(deployments, &Deployment{ + Deployment: deployment, + }) + } + } + } + + return deployments +} + +func kubernetesClient() (*kubernetes.Clientset, error) { + config, err := ctrl.GetConfig() + if err != nil { + return nil, err + } + return kubernetes.NewForConfig(config) +} + +func New() *SelectImpl { + return &SelectImpl{} +} diff --git a/pkg/selector/selector.go b/pkg/selector/selector.go index 2b81ad26a3..03282d5fac 100644 --- a/pkg/selector/selector.go +++ b/pkg/selector/selector.go @@ -28,6 +28,7 @@ import ( "github.com/chaos-mesh/chaos-mesh/pkg/selector/cloudstackhost" "github.com/chaos-mesh/chaos-mesh/pkg/selector/cloudstackvm" "github.com/chaos-mesh/chaos-mesh/pkg/selector/container" + "github.com/chaos-mesh/chaos-mesh/pkg/selector/deployment" "github.com/chaos-mesh/chaos-mesh/pkg/selector/gcp" "github.com/chaos-mesh/chaos-mesh/pkg/selector/k8schaos" "github.com/chaos-mesh/chaos-mesh/pkg/selector/node" @@ -91,6 +92,7 @@ type SelectorParams struct { RollingRestartSelector *rollingrestart.SelectImpl PodPVCSelector *podpvc.SelectImpl CertificateSelector *certificate.SelectImpl + DeploymentSelector *deployment.SelectImpl } func New(p SelectorParams) *Selector { @@ -128,4 +130,5 @@ var Module = fx.Provide( rollingrestart.New, podpvc.New, certificate.New, + deployment.New, ) diff --git a/ui/app/src/api/zz_generated.frontend.chaos-mesh.ts b/ui/app/src/api/zz_generated.frontend.chaos-mesh.ts index 4d6b2db87b..710b63576a 100644 --- a/ui/app/src/api/zz_generated.frontend.chaos-mesh.ts +++ b/ui/app/src/api/zz_generated.frontend.chaos-mesh.ts @@ -16,6 +16,7 @@ const mapping = new Map([ ['K8SChaos', 'k8sChaos'], ['KernelChaos', 'kernelChaos'], ['NetworkChaos', 'networkChaos'], + ['NodeSelectorChaos', 'nodeselectorChaos'], ['PhysicalMachineChaos', 'physicalmachineChaos'], ['PodChaos', 'podChaos'], ['PodPVCChaos', 'podpvcChaos'], diff --git a/ui/app/src/components/NewExperiment/types.ts b/ui/app/src/components/NewExperiment/types.ts index 6a7ac1856a..03502748e3 100644 --- a/ui/app/src/components/NewExperiment/types.ts +++ b/ui/app/src/components/NewExperiment/types.ts @@ -191,6 +191,7 @@ export interface ExperimentType { K8SChaos?: unknown KernelChaos: Kernel NetworkChaos: Network + NodeSelectorChaos?: unknown PodChaos: Pod PodPVCChaos: PodPVC ResourceScaleChaos: ResourceScale diff --git a/ui/app/src/components/NewExperimentNext/data/types.ts b/ui/app/src/components/NewExperimentNext/data/types.ts index 5905a8fd54..67b8f29ef8 100644 --- a/ui/app/src/components/NewExperimentNext/data/types.ts +++ b/ui/app/src/components/NewExperimentNext/data/types.ts @@ -729,6 +729,7 @@ const data: Record = { }, ], }, + NodeSelectorChaos: {}, CiliumChaos: {}, // Pod Fault PodChaos: {