// Copyright Chaos Mesh Authors.
//
// 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.
//

// Code generated by chaos-builder. DO NOT EDIT.

package v1alpha1

import (
	"context"
	"encoding/json"
	"reflect"
	"time"

	"github.com/pkg/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	logf "sigs.k8s.io/controller-runtime/pkg/log"
	"sigs.k8s.io/controller-runtime/pkg/webhook"
	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

	gw "github.com/chaos-mesh/chaos-mesh/api/genericwebhook"
)

// updating spec of a chaos will have no effect, we'd better reject it
var ErrCanNotUpdateChaos = errors.New("Cannot update chaos spec")

const KindAWSChaos = "AWSChaos"

// IsDeleted returns whether this resource has been deleted
func (in *AWSChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *AWSChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *AWSChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *AWSChaosSpec) 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 *AWSChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *AWSChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *AWSChaos) 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

// AWSChaosList contains a list of AWSChaos
type AWSChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []AWSChaos `json:"items"`
}

func (in *AWSChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *AWSChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *AWSChaos) 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 *AWSChaos) IsOneShot() bool {
	if in.Spec.Action==Ec2Restart {
		return true
	}

	return false
}

var AWSChaosWebhookLog = logf.Log.WithName("AWSChaos-resource")

func (in *AWSChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*AWSChaos)
	if !ok {
		return nil, errors.Errorf("expected type *AWSChaos, got %T", obj)
	}
	AWSChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *AWSChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*AWSChaos)
	if !ok {
		return nil, errors.Errorf("expected type *AWSChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*AWSChaos)
	if !ok {
		return nil, errors.Errorf("expected type *AWSChaos, got %T", newObj)
	}

	AWSChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *AWSChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*AWSChaos)
	if !ok {
		return nil, errors.Errorf("expected type *AWSChaos, got %T", obj)
	}

	AWSChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &AWSChaos{}

func (in *AWSChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &AWSChaos{}

func (in *AWSChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindAzureChaos = "AzureChaos"

// IsDeleted returns whether this resource has been deleted
func (in *AzureChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *AzureChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *AzureChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *AzureChaosSpec) 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 *AzureChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *AzureChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *AzureChaos) 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

// AzureChaosList contains a list of AzureChaos
type AzureChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []AzureChaos `json:"items"`
}

func (in *AzureChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *AzureChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *AzureChaos) 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 *AzureChaos) IsOneShot() bool {
	if in.Spec.Action==AzureVmRestart {
		return true
	}

	return false
}

var AzureChaosWebhookLog = logf.Log.WithName("AzureChaos-resource")

func (in *AzureChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*AzureChaos)
	if !ok {
		return nil, errors.Errorf("expected type *AzureChaos, got %T", obj)
	}
	AzureChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *AzureChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*AzureChaos)
	if !ok {
		return nil, errors.Errorf("expected type *AzureChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*AzureChaos)
	if !ok {
		return nil, errors.Errorf("expected type *AzureChaos, got %T", newObj)
	}

	AzureChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *AzureChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*AzureChaos)
	if !ok {
		return nil, errors.Errorf("expected type *AzureChaos, got %T", obj)
	}

	AzureChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &AzureChaos{}

func (in *AzureChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &AzureChaos{}

func (in *AzureChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindBlockChaos = "BlockChaos"

// IsDeleted returns whether this resource has been deleted
func (in *BlockChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *BlockChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *BlockChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *BlockChaosSpec) 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 *BlockChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *BlockChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *BlockChaos) 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

// BlockChaosList contains a list of BlockChaos
type BlockChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []BlockChaos `json:"items"`
}

func (in *BlockChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *BlockChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *BlockChaos) 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 *BlockChaos) IsOneShot() bool {
	return false
}

var BlockChaosWebhookLog = logf.Log.WithName("BlockChaos-resource")

func (in *BlockChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*BlockChaos)
	if !ok {
		return nil, errors.Errorf("expected type *BlockChaos, got %T", obj)
	}
	BlockChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *BlockChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*BlockChaos)
	if !ok {
		return nil, errors.Errorf("expected type *BlockChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*BlockChaos)
	if !ok {
		return nil, errors.Errorf("expected type *BlockChaos, got %T", newObj)
	}

	BlockChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *BlockChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*BlockChaos)
	if !ok {
		return nil, errors.Errorf("expected type *BlockChaos, got %T", obj)
	}

	BlockChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &BlockChaos{}

func (in *BlockChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &BlockChaos{}

func (in *BlockChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindDNSChaos = "DNSChaos"

// IsDeleted returns whether this resource has been deleted
func (in *DNSChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *DNSChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *DNSChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *DNSChaosSpec) 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 *DNSChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *DNSChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *DNSChaos) 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

// DNSChaosList contains a list of DNSChaos
type DNSChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []DNSChaos `json:"items"`
}

func (in *DNSChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *DNSChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *DNSChaos) 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 *DNSChaos) IsOneShot() bool {
	return false
}

var DNSChaosWebhookLog = logf.Log.WithName("DNSChaos-resource")

func (in *DNSChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*DNSChaos)
	if !ok {
		return nil, errors.Errorf("expected type *DNSChaos, got %T", obj)
	}
	DNSChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *DNSChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*DNSChaos)
	if !ok {
		return nil, errors.Errorf("expected type *DNSChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*DNSChaos)
	if !ok {
		return nil, errors.Errorf("expected type *DNSChaos, got %T", newObj)
	}

	DNSChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *DNSChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*DNSChaos)
	if !ok {
		return nil, errors.Errorf("expected type *DNSChaos, got %T", obj)
	}

	DNSChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &DNSChaos{}

func (in *DNSChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &DNSChaos{}

func (in *DNSChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindGCPChaos = "GCPChaos"

// IsDeleted returns whether this resource has been deleted
func (in *GCPChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *GCPChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *GCPChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *GCPChaosSpec) 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 *GCPChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *GCPChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *GCPChaos) 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

// GCPChaosList contains a list of GCPChaos
type GCPChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []GCPChaos `json:"items"`
}

func (in *GCPChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *GCPChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *GCPChaos) 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 *GCPChaos) IsOneShot() bool {
	if in.Spec.Action==NodeReset {
		return true
	}

	return false
}

var GCPChaosWebhookLog = logf.Log.WithName("GCPChaos-resource")

func (in *GCPChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*GCPChaos)
	if !ok {
		return nil, errors.Errorf("expected type *GCPChaos, got %T", obj)
	}
	GCPChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *GCPChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*GCPChaos)
	if !ok {
		return nil, errors.Errorf("expected type *GCPChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*GCPChaos)
	if !ok {
		return nil, errors.Errorf("expected type *GCPChaos, got %T", newObj)
	}

	GCPChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *GCPChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*GCPChaos)
	if !ok {
		return nil, errors.Errorf("expected type *GCPChaos, got %T", obj)
	}

	GCPChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &GCPChaos{}

func (in *GCPChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &GCPChaos{}

func (in *GCPChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindHTTPChaos = "HTTPChaos"

// IsDeleted returns whether this resource has been deleted
func (in *HTTPChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *HTTPChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *HTTPChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *HTTPChaosSpec) 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 *HTTPChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *HTTPChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *HTTPChaos) 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

// HTTPChaosList contains a list of HTTPChaos
type HTTPChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []HTTPChaos `json:"items"`
}

func (in *HTTPChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *HTTPChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *HTTPChaos) 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 *HTTPChaos) IsOneShot() bool {
	return false
}

var HTTPChaosWebhookLog = logf.Log.WithName("HTTPChaos-resource")

func (in *HTTPChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*HTTPChaos)
	if !ok {
		return nil, errors.Errorf("expected type *HTTPChaos, got %T", obj)
	}
	HTTPChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *HTTPChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*HTTPChaos)
	if !ok {
		return nil, errors.Errorf("expected type *HTTPChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*HTTPChaos)
	if !ok {
		return nil, errors.Errorf("expected type *HTTPChaos, got %T", newObj)
	}

	HTTPChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *HTTPChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*HTTPChaos)
	if !ok {
		return nil, errors.Errorf("expected type *HTTPChaos, got %T", obj)
	}

	HTTPChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &HTTPChaos{}

func (in *HTTPChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &HTTPChaos{}

func (in *HTTPChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindIOChaos = "IOChaos"

// IsDeleted returns whether this resource has been deleted
func (in *IOChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *IOChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *IOChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *IOChaosSpec) 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 *IOChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *IOChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *IOChaos) 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

// IOChaosList contains a list of IOChaos
type IOChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []IOChaos `json:"items"`
}

func (in *IOChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *IOChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *IOChaos) 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 *IOChaos) IsOneShot() bool {
	return false
}

var IOChaosWebhookLog = logf.Log.WithName("IOChaos-resource")

func (in *IOChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*IOChaos)
	if !ok {
		return nil, errors.Errorf("expected type *IOChaos, got %T", obj)
	}
	IOChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *IOChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*IOChaos)
	if !ok {
		return nil, errors.Errorf("expected type *IOChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*IOChaos)
	if !ok {
		return nil, errors.Errorf("expected type *IOChaos, got %T", newObj)
	}

	IOChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *IOChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*IOChaos)
	if !ok {
		return nil, errors.Errorf("expected type *IOChaos, got %T", obj)
	}

	IOChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &IOChaos{}

func (in *IOChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &IOChaos{}

func (in *IOChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindJVMChaos = "JVMChaos"

// IsDeleted returns whether this resource has been deleted
func (in *JVMChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *JVMChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *JVMChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *JVMChaosSpec) 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 *JVMChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *JVMChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *JVMChaos) 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

// JVMChaosList contains a list of JVMChaos
type JVMChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []JVMChaos `json:"items"`
}

func (in *JVMChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *JVMChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *JVMChaos) 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 *JVMChaos) IsOneShot() bool {
	return false
}

var JVMChaosWebhookLog = logf.Log.WithName("JVMChaos-resource")

func (in *JVMChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*JVMChaos)
	if !ok {
		return nil, errors.Errorf("expected type *JVMChaos, got %T", obj)
	}
	JVMChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *JVMChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*JVMChaos)
	if !ok {
		return nil, errors.Errorf("expected type *JVMChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*JVMChaos)
	if !ok {
		return nil, errors.Errorf("expected type *JVMChaos, got %T", newObj)
	}

	JVMChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *JVMChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*JVMChaos)
	if !ok {
		return nil, errors.Errorf("expected type *JVMChaos, got %T", obj)
	}

	JVMChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &JVMChaos{}

func (in *JVMChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &JVMChaos{}

func (in *JVMChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindKernelChaos = "KernelChaos"

// IsDeleted returns whether this resource has been deleted
func (in *KernelChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *KernelChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *KernelChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *KernelChaosSpec) 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 *KernelChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *KernelChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *KernelChaos) 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

// KernelChaosList contains a list of KernelChaos
type KernelChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []KernelChaos `json:"items"`
}

func (in *KernelChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *KernelChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *KernelChaos) 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 *KernelChaos) IsOneShot() bool {
	return false
}

var KernelChaosWebhookLog = logf.Log.WithName("KernelChaos-resource")

func (in *KernelChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*KernelChaos)
	if !ok {
		return nil, errors.Errorf("expected type *KernelChaos, got %T", obj)
	}
	KernelChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *KernelChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*KernelChaos)
	if !ok {
		return nil, errors.Errorf("expected type *KernelChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*KernelChaos)
	if !ok {
		return nil, errors.Errorf("expected type *KernelChaos, got %T", newObj)
	}

	KernelChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *KernelChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*KernelChaos)
	if !ok {
		return nil, errors.Errorf("expected type *KernelChaos, got %T", obj)
	}

	KernelChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &KernelChaos{}

func (in *KernelChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &KernelChaos{}

func (in *KernelChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindNetworkChaos = "NetworkChaos"

// IsDeleted returns whether this resource has been deleted
func (in *NetworkChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *NetworkChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *NetworkChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *NetworkChaosSpec) 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 *NetworkChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *NetworkChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *NetworkChaos) 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

// NetworkChaosList contains a list of NetworkChaos
type NetworkChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []NetworkChaos `json:"items"`
}

func (in *NetworkChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *NetworkChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *NetworkChaos) 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 *NetworkChaos) IsOneShot() bool {
	return false
}

var NetworkChaosWebhookLog = logf.Log.WithName("NetworkChaos-resource")

func (in *NetworkChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*NetworkChaos)
	if !ok {
		return nil, errors.Errorf("expected type *NetworkChaos, got %T", obj)
	}
	NetworkChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *NetworkChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*NetworkChaos)
	if !ok {
		return nil, errors.Errorf("expected type *NetworkChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*NetworkChaos)
	if !ok {
		return nil, errors.Errorf("expected type *NetworkChaos, got %T", newObj)
	}

	NetworkChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *NetworkChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*NetworkChaos)
	if !ok {
		return nil, errors.Errorf("expected type *NetworkChaos, got %T", obj)
	}

	NetworkChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &NetworkChaos{}

func (in *NetworkChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &NetworkChaos{}

func (in *NetworkChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindPhysicalMachineChaos = "PhysicalMachineChaos"

// IsDeleted returns whether this resource has been deleted
func (in *PhysicalMachineChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *PhysicalMachineChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *PhysicalMachineChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *PhysicalMachineChaosSpec) 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 *PhysicalMachineChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *PhysicalMachineChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *PhysicalMachineChaos) 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

// PhysicalMachineChaosList contains a list of PhysicalMachineChaos
type PhysicalMachineChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []PhysicalMachineChaos `json:"items"`
}

func (in *PhysicalMachineChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *PhysicalMachineChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *PhysicalMachineChaos) 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 *PhysicalMachineChaos) IsOneShot() bool {
	return false
}

var PhysicalMachineChaosWebhookLog = logf.Log.WithName("PhysicalMachineChaos-resource")

func (in *PhysicalMachineChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PhysicalMachineChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PhysicalMachineChaos, got %T", obj)
	}
	PhysicalMachineChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PhysicalMachineChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*PhysicalMachineChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PhysicalMachineChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*PhysicalMachineChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PhysicalMachineChaos, got %T", newObj)
	}

	PhysicalMachineChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PhysicalMachineChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PhysicalMachineChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PhysicalMachineChaos, got %T", obj)
	}

	PhysicalMachineChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &PhysicalMachineChaos{}

func (in *PhysicalMachineChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &PhysicalMachineChaos{}

func (in *PhysicalMachineChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindPhysicalMachine = "PhysicalMachine"

var PhysicalMachineWebhookLog = logf.Log.WithName("PhysicalMachine-resource")

func (in *PhysicalMachine) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PhysicalMachine)
	if !ok {
		return nil, errors.Errorf("expected type *PhysicalMachine, got %T", obj)
	}
	PhysicalMachineWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PhysicalMachine) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*PhysicalMachine)
	if !ok {
		return nil, errors.Errorf("expected type *PhysicalMachine, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*PhysicalMachine)
	if !ok {
		return nil, errors.Errorf("expected type *PhysicalMachine, got %T", newObj)
	}

	PhysicalMachineWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PhysicalMachine) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PhysicalMachine)
	if !ok {
		return nil, errors.Errorf("expected type *PhysicalMachine, got %T", obj)
	}

	PhysicalMachineWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &PhysicalMachine{}

func (in *PhysicalMachine) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &PhysicalMachine{}

func (in *PhysicalMachine) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindPodChaos = "PodChaos"

// IsDeleted returns whether this resource has been deleted
func (in *PodChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *PodChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *PodChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *PodChaosSpec) 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 *PodChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *PodChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *PodChaos) 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

// PodChaosList contains a list of PodChaos
type PodChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []PodChaos `json:"items"`
}

func (in *PodChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *PodChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *PodChaos) 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 *PodChaos) IsOneShot() bool {
	if in.Spec.Action==PodKillAction || in.Spec.Action==ContainerKillAction {
		return true
	}

	return false
}

var PodChaosWebhookLog = logf.Log.WithName("PodChaos-resource")

func (in *PodChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PodChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodChaos, got %T", obj)
	}
	PodChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PodChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*PodChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*PodChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodChaos, got %T", newObj)
	}

	PodChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PodChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PodChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodChaos, got %T", obj)
	}

	PodChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &PodChaos{}

func (in *PodChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &PodChaos{}

func (in *PodChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindPodHttpChaos = "PodHttpChaos"

var PodHttpChaosWebhookLog = logf.Log.WithName("PodHttpChaos-resource")

func (in *PodHttpChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PodHttpChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodHttpChaos, got %T", obj)
	}
	PodHttpChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PodHttpChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*PodHttpChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodHttpChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*PodHttpChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodHttpChaos, got %T", newObj)
	}

	PodHttpChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PodHttpChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PodHttpChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodHttpChaos, got %T", obj)
	}

	PodHttpChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &PodHttpChaos{}

func (in *PodHttpChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &PodHttpChaos{}

func (in *PodHttpChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindPodIOChaos = "PodIOChaos"

var PodIOChaosWebhookLog = logf.Log.WithName("PodIOChaos-resource")

func (in *PodIOChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PodIOChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodIOChaos, got %T", obj)
	}
	PodIOChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PodIOChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*PodIOChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodIOChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*PodIOChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodIOChaos, got %T", newObj)
	}

	PodIOChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PodIOChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PodIOChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodIOChaos, got %T", obj)
	}

	PodIOChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &PodIOChaos{}

func (in *PodIOChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &PodIOChaos{}

func (in *PodIOChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindPodNetworkChaos = "PodNetworkChaos"

var PodNetworkChaosWebhookLog = logf.Log.WithName("PodNetworkChaos-resource")

func (in *PodNetworkChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PodNetworkChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodNetworkChaos, got %T", obj)
	}
	PodNetworkChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PodNetworkChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*PodNetworkChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodNetworkChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*PodNetworkChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodNetworkChaos, got %T", newObj)
	}

	PodNetworkChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *PodNetworkChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*PodNetworkChaos)
	if !ok {
		return nil, errors.Errorf("expected type *PodNetworkChaos, got %T", obj)
	}

	PodNetworkChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &PodNetworkChaos{}

func (in *PodNetworkChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &PodNetworkChaos{}

func (in *PodNetworkChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindRemoteCluster = "RemoteCluster"

var RemoteClusterWebhookLog = logf.Log.WithName("RemoteCluster-resource")

func (in *RemoteCluster) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*RemoteCluster)
	if !ok {
		return nil, errors.Errorf("expected type *RemoteCluster, got %T", obj)
	}
	RemoteClusterWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *RemoteCluster) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*RemoteCluster)
	if !ok {
		return nil, errors.Errorf("expected type *RemoteCluster, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*RemoteCluster)
	if !ok {
		return nil, errors.Errorf("expected type *RemoteCluster, got %T", newObj)
	}

	RemoteClusterWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *RemoteCluster) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*RemoteCluster)
	if !ok {
		return nil, errors.Errorf("expected type *RemoteCluster, got %T", obj)
	}

	RemoteClusterWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &RemoteCluster{}

func (in *RemoteCluster) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &RemoteCluster{}

func (in *RemoteCluster) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindStatusCheck = "StatusCheck"

var StatusCheckWebhookLog = logf.Log.WithName("StatusCheck-resource")

func (in *StatusCheck) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*StatusCheck)
	if !ok {
		return nil, errors.Errorf("expected type *StatusCheck, got %T", obj)
	}
	StatusCheckWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *StatusCheck) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*StatusCheck)
	if !ok {
		return nil, errors.Errorf("expected type *StatusCheck, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*StatusCheck)
	if !ok {
		return nil, errors.Errorf("expected type *StatusCheck, got %T", newObj)
	}

	StatusCheckWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *StatusCheck) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*StatusCheck)
	if !ok {
		return nil, errors.Errorf("expected type *StatusCheck, got %T", obj)
	}

	StatusCheckWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &StatusCheck{}

func (in *StatusCheck) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &StatusCheck{}

func (in *StatusCheck) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindStressChaos = "StressChaos"

// IsDeleted returns whether this resource has been deleted
func (in *StressChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *StressChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *StressChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *StressChaosSpec) 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 *StressChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *StressChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *StressChaos) 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

// StressChaosList contains a list of StressChaos
type StressChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []StressChaos `json:"items"`
}

func (in *StressChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *StressChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *StressChaos) 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 *StressChaos) IsOneShot() bool {
	return false
}

var StressChaosWebhookLog = logf.Log.WithName("StressChaos-resource")

func (in *StressChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*StressChaos)
	if !ok {
		return nil, errors.Errorf("expected type *StressChaos, got %T", obj)
	}
	StressChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *StressChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*StressChaos)
	if !ok {
		return nil, errors.Errorf("expected type *StressChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*StressChaos)
	if !ok {
		return nil, errors.Errorf("expected type *StressChaos, got %T", newObj)
	}

	StressChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *StressChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*StressChaos)
	if !ok {
		return nil, errors.Errorf("expected type *StressChaos, got %T", obj)
	}

	StressChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &StressChaos{}

func (in *StressChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &StressChaos{}

func (in *StressChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

const KindTimeChaos = "TimeChaos"

// IsDeleted returns whether this resource has been deleted
func (in *TimeChaos) IsDeleted() bool {
	return !in.DeletionTimestamp.IsZero()
}

// IsPaused returns whether this resource has been paused
func (in *TimeChaos) IsPaused() bool {
	if in.Annotations == nil || in.Annotations[PauseAnnotationKey] != "true" {
		return false
	}
	return true
}

// GetObjectMeta would return the ObjectMeta for chaos
func (in *TimeChaos) GetObjectMeta() *metav1.ObjectMeta {
	return &in.ObjectMeta
}

// GetDuration would return the duration for chaos
func (in *TimeChaosSpec) 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 *TimeChaos) GetStatus() *ChaosStatus {
	return &in.Status.ChaosStatus
}

// GetRemoteCluster returns the remoteCluster
func (in *TimeChaos) GetRemoteCluster() string {
	return in.Spec.RemoteCluster
}

// GetSpecAndMetaString returns a string including the meta and spec field of this chaos object.
func (in *TimeChaos) 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

// TimeChaosList contains a list of TimeChaos
type TimeChaosList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []TimeChaos `json:"items"`
}

func (in *TimeChaosList) DeepCopyList() GenericChaosList {
	return in.DeepCopy()
}

// ListChaos returns a list of chaos
func (in *TimeChaosList) ListChaos() []GenericChaos {
	var result []GenericChaos
	for _, item := range in.Items {
		item := item
		result = append(result, &item)
	}
	return result
}

func (in *TimeChaos) 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 *TimeChaos) IsOneShot() bool {
	return false
}

var TimeChaosWebhookLog = logf.Log.WithName("TimeChaos-resource")

func (in *TimeChaos) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*TimeChaos)
	if !ok {
		return nil, errors.Errorf("expected type *TimeChaos, got %T", obj)
	}
	TimeChaosWebhookLog.Info("validate create", "name", typedObj.GetName())

	return typedObj.Validate()
}

// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
func (in *TimeChaos) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
	typedOldObj, ok := oldObj.(*TimeChaos)
	if !ok {
		return nil, errors.Errorf("expected type *TimeChaos, got %T", oldObj)
	}

	typedNewObj, ok := newObj.(*TimeChaos)
	if !ok {
		return nil, errors.Errorf("expected type *TimeChaos, got %T", newObj)
	}

	TimeChaosWebhookLog.Info("validate update", "name", typedOldObj.GetName())
	if !reflect.DeepEqual(typedOldObj.Spec, typedNewObj.Spec) {
		return nil, ErrCanNotUpdateChaos
	}
	return typedNewObj.Validate()
}

// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
func (in *TimeChaos) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
	typedObj, ok := obj.(*TimeChaos)
	if !ok {
		return nil, errors.Errorf("expected type *TimeChaos, got %T", obj)
	}

	TimeChaosWebhookLog.Info("validate delete", "name", typedObj.GetName())

	return nil, nil
}

var _ webhook.CustomValidator = &TimeChaos{}

func (in *TimeChaos) Validate() ([]string, error) {
	errs := gw.Validate(in)
	return nil, gw.Aggregate(errs)
}

var _ webhook.CustomDefaulter = &TimeChaos{}

func (in *TimeChaos) Default(_ context.Context, obj runtime.Object) error {
	gw.Default(obj)
	return nil
}

func init() {

	SchemeBuilder.Register(&AWSChaos{}, &AWSChaosList{})
	all.register(KindAWSChaos, &ChaosKind{
		chaos: &AWSChaos{},
		list:  &AWSChaosList{},
	})

	SchemeBuilder.Register(&AzureChaos{}, &AzureChaosList{})
	all.register(KindAzureChaos, &ChaosKind{
		chaos: &AzureChaos{},
		list:  &AzureChaosList{},
	})

	SchemeBuilder.Register(&BlockChaos{}, &BlockChaosList{})
	all.register(KindBlockChaos, &ChaosKind{
		chaos: &BlockChaos{},
		list:  &BlockChaosList{},
	})

	SchemeBuilder.Register(&DNSChaos{}, &DNSChaosList{})
	all.register(KindDNSChaos, &ChaosKind{
		chaos: &DNSChaos{},
		list:  &DNSChaosList{},
	})

	SchemeBuilder.Register(&GCPChaos{}, &GCPChaosList{})
	all.register(KindGCPChaos, &ChaosKind{
		chaos: &GCPChaos{},
		list:  &GCPChaosList{},
	})

	SchemeBuilder.Register(&HTTPChaos{}, &HTTPChaosList{})
	all.register(KindHTTPChaos, &ChaosKind{
		chaos: &HTTPChaos{},
		list:  &HTTPChaosList{},
	})

	SchemeBuilder.Register(&IOChaos{}, &IOChaosList{})
	all.register(KindIOChaos, &ChaosKind{
		chaos: &IOChaos{},
		list:  &IOChaosList{},
	})

	SchemeBuilder.Register(&JVMChaos{}, &JVMChaosList{})
	all.register(KindJVMChaos, &ChaosKind{
		chaos: &JVMChaos{},
		list:  &JVMChaosList{},
	})

	SchemeBuilder.Register(&KernelChaos{}, &KernelChaosList{})
	all.register(KindKernelChaos, &ChaosKind{
		chaos: &KernelChaos{},
		list:  &KernelChaosList{},
	})

	SchemeBuilder.Register(&NetworkChaos{}, &NetworkChaosList{})
	all.register(KindNetworkChaos, &ChaosKind{
		chaos: &NetworkChaos{},
		list:  &NetworkChaosList{},
	})

	SchemeBuilder.Register(&PhysicalMachineChaos{}, &PhysicalMachineChaosList{})
	all.register(KindPhysicalMachineChaos, &ChaosKind{
		chaos: &PhysicalMachineChaos{},
		list:  &PhysicalMachineChaosList{},
	})

	SchemeBuilder.Register(&PhysicalMachine{}, &PhysicalMachineList{})

	SchemeBuilder.Register(&PodChaos{}, &PodChaosList{})
	all.register(KindPodChaos, &ChaosKind{
		chaos: &PodChaos{},
		list:  &PodChaosList{},
	})

	SchemeBuilder.Register(&PodHttpChaos{}, &PodHttpChaosList{})

	SchemeBuilder.Register(&PodIOChaos{}, &PodIOChaosList{})

	SchemeBuilder.Register(&PodNetworkChaos{}, &PodNetworkChaosList{})

	SchemeBuilder.Register(&RemoteCluster{}, &RemoteClusterList{})

	SchemeBuilder.Register(&StatusCheck{}, &StatusCheckList{})

	SchemeBuilder.Register(&StressChaos{}, &StressChaosList{})
	all.register(KindStressChaos, &ChaosKind{
		chaos: &StressChaos{},
		list:  &StressChaosList{},
	})

	SchemeBuilder.Register(&TimeChaos{}, &TimeChaosList{})
	all.register(KindTimeChaos, &ChaosKind{
		chaos: &TimeChaos{},
		list:  &TimeChaosList{},
	})


	allScheduleItem.register(KindAWSChaos, &ChaosKind{
		chaos: &AWSChaos{},
		list:  &AWSChaosList{},
	})

	allScheduleItem.register(KindAzureChaos, &ChaosKind{
		chaos: &AzureChaos{},
		list:  &AzureChaosList{},
	})

	allScheduleItem.register(KindBlockChaos, &ChaosKind{
		chaos: &BlockChaos{},
		list:  &BlockChaosList{},
	})

	allScheduleItem.register(KindDNSChaos, &ChaosKind{
		chaos: &DNSChaos{},
		list:  &DNSChaosList{},
	})

	allScheduleItem.register(KindGCPChaos, &ChaosKind{
		chaos: &GCPChaos{},
		list:  &GCPChaosList{},
	})

	allScheduleItem.register(KindHTTPChaos, &ChaosKind{
		chaos: &HTTPChaos{},
		list:  &HTTPChaosList{},
	})

	allScheduleItem.register(KindIOChaos, &ChaosKind{
		chaos: &IOChaos{},
		list:  &IOChaosList{},
	})

	allScheduleItem.register(KindJVMChaos, &ChaosKind{
		chaos: &JVMChaos{},
		list:  &JVMChaosList{},
	})

	allScheduleItem.register(KindKernelChaos, &ChaosKind{
		chaos: &KernelChaos{},
		list:  &KernelChaosList{},
	})

	allScheduleItem.register(KindNetworkChaos, &ChaosKind{
		chaos: &NetworkChaos{},
		list:  &NetworkChaosList{},
	})

	allScheduleItem.register(KindPhysicalMachineChaos, &ChaosKind{
		chaos: &PhysicalMachineChaos{},
		list:  &PhysicalMachineChaosList{},
	})

	allScheduleItem.register(KindPodChaos, &ChaosKind{
		chaos: &PodChaos{},
		list:  &PodChaosList{},
	})

	allScheduleItem.register(KindStressChaos, &ChaosKind{
		chaos: &StressChaos{},
		list:  &StressChaosList{},
	})

	allScheduleItem.register(KindTimeChaos, &ChaosKind{
		chaos: &TimeChaos{},
		list:  &TimeChaosList{},
	})

	allScheduleItem.register(KindWorkflow, &ChaosKind{
		chaos: &Workflow{},
		list:  &WorkflowList{},
	})

}
