...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/dashboard/collector/schedule_collector.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/dashboard/collector

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package collector
    17  
    18  import (
    19  	"context"
    20  	"encoding/json"
    21  
    22  	"github.com/go-logr/logr"
    23  	"github.com/jinzhu/gorm"
    24  	"github.com/pkg/errors"
    25  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    26  	"k8s.io/apimachinery/pkg/runtime"
    27  	ctrl "sigs.k8s.io/controller-runtime"
    28  	"sigs.k8s.io/controller-runtime/pkg/client"
    29  
    30  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    31  	"github.com/chaos-mesh/chaos-mesh/pkg/dashboard/core"
    32  )
    33  
    34  // ScheduleCollector represents a collector for Schedule Object.
    35  type ScheduleCollector struct {
    36  	client.Client
    37  	Log     logr.Logger
    38  	apiType runtime.Object
    39  	archive core.ScheduleStore
    40  }
    41  
    42  // Reconcile reconciles a Schedule collector.
    43  func (r *ScheduleCollector) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    44  	if r.apiType == nil {
    45  		r.Log.Error(nil, "apiType has not been initialized")
    46  		return ctrl.Result{}, nil
    47  	}
    48  
    49  	schedule := &v1alpha1.Schedule{}
    50  	err := r.Get(ctx, req.NamespacedName, schedule)
    51  	if apierrors.IsNotFound(err) {
    52  		if err = r.archiveSchedule(req.Namespace, req.Name); err != nil {
    53  			r.Log.Error(err, "failed to archive schedule")
    54  		}
    55  		return ctrl.Result{}, nil
    56  	}
    57  	if err != nil {
    58  		r.Log.Error(err, "failed to get schedule object", "request", req.NamespacedName)
    59  		return ctrl.Result{}, nil
    60  	}
    61  
    62  	if err := r.setUnarchivedSchedule(req, *schedule); err != nil {
    63  		r.Log.Error(err, "failed to archive schedule")
    64  		// ignore error here
    65  	}
    66  
    67  	return ctrl.Result{}, nil
    68  }
    69  
    70  // Setup setups collectors by Manager.
    71  func (r *ScheduleCollector) Setup(mgr ctrl.Manager, apiType client.Object) error {
    72  	r.apiType = apiType
    73  
    74  	return ctrl.NewControllerManagedBy(mgr).
    75  		For(apiType).
    76  		Complete(r)
    77  }
    78  
    79  func (r *ScheduleCollector) setUnarchivedSchedule(req ctrl.Request, schedule v1alpha1.Schedule) error {
    80  	archive := &core.Schedule{
    81  		ScheduleMeta: core.ScheduleMeta{
    82  			Namespace: req.Namespace,
    83  			Name:      req.Name,
    84  			Kind:      schedule.Kind,
    85  			UID:       string(schedule.UID),
    86  			Archived:  false,
    87  		},
    88  	}
    89  
    90  	switch schedule.Spec.Type {
    91  	case v1alpha1.ScheduleTypePodChaos:
    92  		archive.Action = string(schedule.Spec.ScheduleItem.PodChaos.Action)
    93  	case v1alpha1.ScheduleTypeNetworkChaos:
    94  		archive.Action = string(schedule.Spec.ScheduleItem.NetworkChaos.Action)
    95  	case v1alpha1.ScheduleTypeIOChaos:
    96  		archive.Action = string(schedule.Spec.ScheduleItem.IOChaos.Action)
    97  	case v1alpha1.ScheduleTypeTimeChaos, v1alpha1.ScheduleTypeKernelChaos, v1alpha1.ScheduleTypeStressChaos, v1alpha1.ScheduleTypeHTTPChaos:
    98  		archive.Action = ""
    99  	case v1alpha1.ScheduleTypeDNSChaos:
   100  		archive.Action = string(schedule.Spec.ScheduleItem.DNSChaos.Action)
   101  	case v1alpha1.ScheduleTypeAWSChaos:
   102  		archive.Action = string(schedule.Spec.ScheduleItem.AWSChaos.Action)
   103  	case v1alpha1.ScheduleTypeGCPChaos:
   104  		archive.Action = string(schedule.Spec.ScheduleItem.GCPChaos.Action)
   105  	case v1alpha1.ScheduleTypeJVMChaos:
   106  		archive.Action = string(schedule.Spec.ScheduleItem.JVMChaos.Action)
   107  	case v1alpha1.ScheduleTypePhysicalMachineChaos:
   108  		archive.Action = string(schedule.Spec.ScheduleItem.PhysicalMachineChaos.Action)
   109  	default:
   110  		return errors.New("unsupported chaos type " + string(schedule.Spec.Type))
   111  	}
   112  
   113  	archive.StartTime = schedule.GetCreationTimestamp().Time
   114  	if schedule.GetDeletionTimestamp() != nil {
   115  		archive.FinishTime = &schedule.GetDeletionTimestamp().Time
   116  	}
   117  
   118  	data, err := json.Marshal(schedule)
   119  	if err != nil {
   120  		r.Log.Error(err, "failed to marshal schedule", "kind", archive.Kind,
   121  			"namespace", archive.Namespace, "name", archive.Name)
   122  		return err
   123  	}
   124  
   125  	archive.Schedule = string(data)
   126  
   127  	find, err := r.archive.FindByUID(context.Background(), string(schedule.UID))
   128  	if err != nil && !gorm.IsRecordNotFoundError(err) {
   129  		r.Log.Error(err, "failed to find schedule", "UID", schedule.UID)
   130  		return err
   131  	}
   132  
   133  	if find != nil {
   134  		archive.ID = find.ID
   135  		archive.CreatedAt = find.CreatedAt
   136  		archive.UpdatedAt = find.UpdatedAt
   137  	}
   138  
   139  	if err := r.archive.Set(context.Background(), archive); err != nil {
   140  		r.Log.Error(err, "failed to update schedule", "archive", archive)
   141  		return err
   142  	}
   143  
   144  	return nil
   145  }
   146  
   147  func (r *ScheduleCollector) archiveSchedule(ns, name string) error {
   148  	if err := r.archive.Archive(context.Background(), ns, name); err != nil {
   149  		r.Log.Error(err, "failed to archive schedule", "namespace", ns, "name", name)
   150  		return err
   151  	}
   152  
   153  	return nil
   154  }
   155