diff --git a/config/crds/troubleshoot.replicated.com_preflightjobs.yaml b/config/crds/troubleshoot.replicated.com_preflightjobs.yaml index e22a213f..727ede36 100644 --- a/config/crds/troubleshoot.replicated.com_preflightjobs.yaml +++ b/config/crds/troubleshoot.replicated.com_preflightjobs.yaml @@ -390,12 +390,84 @@ spec: type: string type: object spec: + properties: + analyzerImage: + type: string + analyzerImagePullPolicy: + type: string + collectorImage: + type: string + collectorImagePullPolicy: + type: string + preflight: + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + required: + - preflight type: object status: + properties: + analyzersFailed: + items: + type: string + type: array + analyzersRunning: + items: + type: string + type: array + analyzersSuccessful: + items: + type: string + type: array + collectorsFailed: + items: + type: string + type: array + collectorsRunning: + items: + type: string + type: array + collectorsSuccessful: + items: + type: string + type: array + isAnalyzersComplete: + type: boolean + isCollectorsComplete: + type: boolean + isServerReady: + type: boolean + serverPodName: + type: string + serverPodNamespace: + type: string + serverPodPort: + type: integer + required: + - isServerReady + - serverPodName + - serverPodNamespace + - serverPodPort + - isCollectorsComplete + - collectorsRunning + - collectorsSuccessful + - collectorsFailed + - isAnalyzersComplete + - analyzersRunning + - analyzersSuccessful + - analyzersFailed type: object type: object served: true storage: true + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/config/crds/troubleshoot.replicated.com_preflights.yaml b/config/crds/troubleshoot.replicated.com_preflights.yaml index 8a6e65b0..b9c81bcf 100644 --- a/config/crds/troubleshoot.replicated.com_preflights.yaml +++ b/config/crds/troubleshoot.replicated.com_preflights.yaml @@ -390,6 +390,20 @@ spec: type: string type: object spec: + properties: + analyzers: + items: + type: object + type: array + collectors: + items: + properties: + cluster-info: + type: object + cluster-resources: + type: object + type: object + type: array type: object status: type: object diff --git a/config/crds/zz_generated.deepcopy.go b/config/crds/zz_generated.deepcopy.go index 552e0a5a..b9b60e31 100644 --- a/config/crds/zz_generated.deepcopy.go +++ b/config/crds/zz_generated.deepcopy.go @@ -8,6 +8,21 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Analyze) DeepCopyInto(out *Analyze) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Analyze. +func (in *Analyze) DeepCopy() *Analyze { + if in == nil { + return nil + } + out := new(Analyze) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Analyzer) DeepCopyInto(out *Analyzer) { *out = *in @@ -450,7 +465,7 @@ func (in *Preflight) DeepCopyInto(out *Preflight) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) out.Status = in.Status } @@ -478,7 +493,7 @@ func (in *PreflightJob) DeepCopyInto(out *PreflightJob) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightJob. @@ -534,6 +549,7 @@ func (in *PreflightJobList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreflightJobSpec) DeepCopyInto(out *PreflightJobSpec) { *out = *in + out.Preflight = in.Preflight } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightJobSpec. @@ -549,6 +565,36 @@ func (in *PreflightJobSpec) DeepCopy() *PreflightJobSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreflightJobStatus) DeepCopyInto(out *PreflightJobStatus) { *out = *in + if in.CollectorsRunning != nil { + in, out := &in.CollectorsRunning, &out.CollectorsRunning + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.CollectorsSuccessful != nil { + in, out := &in.CollectorsSuccessful, &out.CollectorsSuccessful + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.CollectorsFailed != nil { + in, out := &in.CollectorsFailed, &out.CollectorsFailed + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AnalyzersRunning != nil { + in, out := &in.AnalyzersRunning, &out.AnalyzersRunning + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AnalyzersSuccessful != nil { + in, out := &in.AnalyzersSuccessful, &out.AnalyzersSuccessful + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AnakyzersFailed != nil { + in, out := &in.AnakyzersFailed, &out.AnakyzersFailed + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightJobStatus. @@ -593,9 +639,46 @@ func (in *PreflightList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PreflightRef) DeepCopyInto(out *PreflightRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightRef. +func (in *PreflightRef) DeepCopy() *PreflightRef { + if in == nil { + return nil + } + out := new(PreflightRef) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreflightSpec) DeepCopyInto(out *PreflightSpec) { *out = *in + if in.Collectors != nil { + in, out := &in.Collectors, &out.Collectors + *out = make([]*Collect, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Collect) + (*in).DeepCopyInto(*out) + } + } + } + if in.Analyzers != nil { + in, out := &in.Analyzers, &out.Analyzers + *out = make([]*Analyze, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Analyze) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightSpec. diff --git a/config/samples/troubleshoot_v1beta1_preflight.yaml b/config/samples/troubleshoot_v1beta1_preflight.yaml index ba9a825a..f73616ae 100644 --- a/config/samples/troubleshoot_v1beta1_preflight.yaml +++ b/config/samples/troubleshoot_v1beta1_preflight.yaml @@ -1,9 +1,9 @@ apiVersion: troubleshoot.replicated.com/v1beta1 kind: Preflight metadata: - labels: - controller-tools.k8s.io: "1.0" name: preflight-sample spec: - # Add fields here - foo: bar + collectors: + - cluster-info: {} + - cluster-resources: {} + analyzers: [] diff --git a/config/samples/troubleshoot_v1beta1_preflightjob.yaml b/config/samples/troubleshoot_v1beta1_preflightjob.yaml index 61f005c6..b7626a69 100644 --- a/config/samples/troubleshoot_v1beta1_preflightjob.yaml +++ b/config/samples/troubleshoot_v1beta1_preflightjob.yaml @@ -1,9 +1,10 @@ apiVersion: troubleshoot.replicated.com/v1beta1 kind: PreflightJob metadata: - labels: - controller-tools.k8s.io: "1.0" name: preflightjob-sample spec: - # Add fields here - foo: bar + image: localhost:32000/troubleshoot:alpha + imagePullPolicy: Always + preflight: + name: preflight-sample + namespace: default diff --git a/pkg/apis/troubleshoot/v1beta1/analyzer_shared.go b/pkg/apis/troubleshoot/v1beta1/analyzer_shared.go new file mode 100644 index 00000000..a91e607b --- /dev/null +++ b/pkg/apis/troubleshoot/v1beta1/analyzer_shared.go @@ -0,0 +1,4 @@ +package v1beta1 + +type Analyze struct { +} diff --git a/pkg/apis/troubleshoot/v1beta1/preflight_types.go b/pkg/apis/troubleshoot/v1beta1/preflight_types.go index b64a2f53..34c20f97 100644 --- a/pkg/apis/troubleshoot/v1beta1/preflight_types.go +++ b/pkg/apis/troubleshoot/v1beta1/preflight_types.go @@ -20,13 +20,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - // PreflightSpec defines the desired state of Preflight type PreflightSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file + Collectors []*Collect `json:"collectors,omitempty"` + Analyzers []*Analyze `json:"analyzers,omitempty"` } // PreflightStatus defines the observed state of Preflight diff --git a/pkg/apis/troubleshoot/v1beta1/preflightjob_types.go b/pkg/apis/troubleshoot/v1beta1/preflightjob_types.go index fad4fcf1..c17ee669 100644 --- a/pkg/apis/troubleshoot/v1beta1/preflightjob_types.go +++ b/pkg/apis/troubleshoot/v1beta1/preflightjob_types.go @@ -20,26 +20,45 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. +type PreflightRef struct { + Name string `json:"name"` + Namespace string `json:"namespace,omitempty"` +} // PreflightJobSpec defines the desired state of PreflightJob type PreflightJobSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file + Preflight PreflightRef `json:"preflight"` + + CollectorImage string `json:"collectorImage,omitempty"` + CollectorImagePullPolicy string `json:"collectorImagePullPolicy,omitempty"` + + AnalyzerImage string `json:"analyzerImage,omitempty"` + AnalyzerImagePullPolicy string `json:"analyzerImagePullPolicy,omitempty"` } // PreflightJobStatus defines the observed state of PreflightJob type PreflightJobStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file + IsServerReady bool `json:"isServerReady"` + ServerPodName string `json:"serverPodName"` + ServerPodNamespace string `json:"serverPodNamespace"` + ServerPodPort int `json:"serverPodPort"` + + IsCollectorsComplete bool `json:"isCollectorsComplete"` + CollectorsRunning []string `json:"collectorsRunning"` + CollectorsSuccessful []string `json:"collectorsSuccessful"` + CollectorsFailed []string `json:"collectorsFailed"` + + IsAnalyzersComplete bool `json:"isAnalyzersComplete"` + AnalyzersRunning []string `json:"analyzersRunning"` + AnalyzersSuccessful []string `json:"analyzersSuccessful"` + AnakyzersFailed []string `json:"analyzersFailed"` } // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - // PreflightJob is the Schema for the preflightjobs API // +k8s:openapi-gen=true +// +kubebuilder:subresource:status type PreflightJob struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go b/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go index 6ae2bb14..13fcb571 100644 --- a/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go @@ -24,6 +24,21 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Analyze) DeepCopyInto(out *Analyze) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Analyze. +func (in *Analyze) DeepCopy() *Analyze { + if in == nil { + return nil + } + out := new(Analyze) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Analyzer) DeepCopyInto(out *Analyzer) { *out = *in @@ -466,7 +481,7 @@ func (in *Preflight) DeepCopyInto(out *Preflight) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) out.Status = in.Status } @@ -494,7 +509,7 @@ func (in *PreflightJob) DeepCopyInto(out *PreflightJob) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightJob. @@ -550,6 +565,7 @@ func (in *PreflightJobList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreflightJobSpec) DeepCopyInto(out *PreflightJobSpec) { *out = *in + out.Preflight = in.Preflight } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightJobSpec. @@ -565,6 +581,36 @@ func (in *PreflightJobSpec) DeepCopy() *PreflightJobSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreflightJobStatus) DeepCopyInto(out *PreflightJobStatus) { *out = *in + if in.CollectorsRunning != nil { + in, out := &in.CollectorsRunning, &out.CollectorsRunning + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.CollectorsSuccessful != nil { + in, out := &in.CollectorsSuccessful, &out.CollectorsSuccessful + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.CollectorsFailed != nil { + in, out := &in.CollectorsFailed, &out.CollectorsFailed + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AnalyzersRunning != nil { + in, out := &in.AnalyzersRunning, &out.AnalyzersRunning + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AnalyzersSuccessful != nil { + in, out := &in.AnalyzersSuccessful, &out.AnalyzersSuccessful + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AnakyzersFailed != nil { + in, out := &in.AnakyzersFailed, &out.AnakyzersFailed + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightJobStatus. @@ -609,9 +655,46 @@ func (in *PreflightList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PreflightRef) DeepCopyInto(out *PreflightRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightRef. +func (in *PreflightRef) DeepCopy() *PreflightRef { + if in == nil { + return nil + } + out := new(PreflightRef) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreflightSpec) DeepCopyInto(out *PreflightSpec) { *out = *in + if in.Collectors != nil { + in, out := &in.Collectors, &out.Collectors + *out = make([]*Collect, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Collect) + (*in).DeepCopyInto(*out) + } + } + } + if in.Analyzers != nil { + in, out := &in.Analyzers, &out.Analyzers + *out = make([]*Analyze, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Analyze) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreflightSpec. diff --git a/pkg/controller/collectorjob/collector_server.go b/pkg/controller/collectorjob/collector_server.go new file mode 100644 index 00000000..29cbc29a --- /dev/null +++ b/pkg/controller/collectorjob/collector_server.go @@ -0,0 +1,127 @@ +package collectorjob + +import ( + "context" + "fmt" + "time" + + troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" + corev1 "k8s.io/api/core/v1" + kuberneteserrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +func (r *ReconcileCollectorJob) createCollectorServer(instance *troubleshootv1beta1.CollectorJob) error { + name := fmt.Sprintf("%s-%s", instance.Name, "collector") + + namespacedName := types.NamespacedName{ + Name: name, + Namespace: instance.Namespace, + } + + found := &corev1.Pod{} + err := r.Get(context.Background(), namespacedName, found) + if err == nil || !kuberneteserrors.IsNotFound(err) { + return err + } + + imageName := "replicatedhq/troubleshoot:latest" + imagePullPolicy := corev1.PullAlways + + if instance.Spec.Image != "" { + imageName = instance.Spec.Image + } + if instance.Spec.ImagePullPolicy != "" { + imagePullPolicy = corev1.PullPolicy(instance.Spec.ImagePullPolicy) + } + + podLabels := make(map[string]string) + podLabels["collector"] = instance.Name + podLabels["troubleshoot-role"] = "collector" + + pod := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: instance.Namespace, + Labels: podLabels, + }, + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Pod", + }, + Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyNever, + Containers: []corev1.Container{ + { + Image: imageName, + ImagePullPolicy: imagePullPolicy, + Name: "collector", + Command: []string{"collector"}, + Args: []string{"server"}, + Ports: []corev1.ContainerPort{ + { + Name: "http", + ContainerPort: 8000, + }, + }, + }, + }, + }, + } + + if err := controllerutil.SetControllerReference(instance, &pod, r.scheme); err != nil { + return err + } + + if err := r.Create(context.Background(), &pod); err != nil { + return err + } + + service := corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: instance.Namespace, + }, + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Service", + }, + Spec: corev1.ServiceSpec{ + Selector: podLabels, + Type: corev1.ServiceTypeClusterIP, + Ports: []corev1.ServicePort{ + { + Name: "http", + Port: 8000, + TargetPort: intstr.FromInt(8000), + }, + }, + }, + } + + if err := controllerutil.SetControllerReference(instance, &service, r.scheme); err != nil { + return err + } + + if err := r.Create(context.Background(), &service); err != nil { + return err + } + + instance.Status.ServerPodName = name + instance.Status.ServerPodNamespace = instance.Namespace + instance.Status.ServerPodPort = 8000 + instance.Status.IsServerReady = true + + // wait for the server to be ready + // TODO + time.Sleep(time.Second * 5) + + if err := r.Update(context.Background(), instance); err != nil { + return err + } + + return nil +} diff --git a/pkg/controller/collectorjob/collectorjob_controller.go b/pkg/controller/collectorjob/collectorjob_controller.go index 0d93b0a9..4a0b6bb3 100644 --- a/pkg/controller/collectorjob/collectorjob_controller.go +++ b/pkg/controller/collectorjob/collectorjob_controller.go @@ -37,7 +37,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" @@ -145,118 +144,6 @@ func (r *ReconcileCollectorJob) Reconcile(request reconcile.Request) (reconcile. return reconcile.Result{}, nil } -func (r *ReconcileCollectorJob) createCollectorServer(instance *troubleshootv1beta1.CollectorJob) error { - name := fmt.Sprintf("%s-%s", instance.Name, "collector") - - namespacedName := types.NamespacedName{ - Name: name, - Namespace: instance.Namespace, - } - - found := &corev1.Pod{} - err := r.Get(context.Background(), namespacedName, found) - if err == nil || !kuberneteserrors.IsNotFound(err) { - return err - } - - imageName := "replicatedhq/troubleshoot:latest" - imagePullPolicy := corev1.PullAlways - - if instance.Spec.Image != "" { - imageName = instance.Spec.Image - } - if instance.Spec.ImagePullPolicy != "" { - imagePullPolicy = corev1.PullPolicy(instance.Spec.ImagePullPolicy) - } - - podLabels := make(map[string]string) - podLabels["collector"] = instance.Name - podLabels["troubleshoot-role"] = "collector" - - pod := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: instance.Namespace, - Labels: podLabels, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - Containers: []corev1.Container{ - { - Image: imageName, - ImagePullPolicy: imagePullPolicy, - Name: "collector", - Command: []string{"collector"}, - Args: []string{"server"}, - Ports: []corev1.ContainerPort{ - { - Name: "http", - ContainerPort: 8000, - }, - }, - }, - }, - }, - } - - if err := controllerutil.SetControllerReference(instance, &pod, r.scheme); err != nil { - return err - } - - if err := r.Create(context.Background(), &pod); err != nil { - return err - } - - service := corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: instance.Namespace, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Service", - }, - Spec: corev1.ServiceSpec{ - Selector: podLabels, - Type: corev1.ServiceTypeClusterIP, - Ports: []corev1.ServicePort{ - { - Name: "http", - Port: 8000, - TargetPort: intstr.FromInt(8000), - }, - }, - }, - } - - if err := controllerutil.SetControllerReference(instance, &service, r.scheme); err != nil { - return err - } - - if err := r.Create(context.Background(), &service); err != nil { - return err - } - - instance.Status.ServerPodName = name - instance.Status.ServerPodNamespace = instance.Namespace - instance.Status.ServerPodPort = 8000 - instance.Status.IsServerReady = true - - // wait for the server to be ready - // TODO - time.Sleep(time.Second * 5) - - if err := r.Update(context.Background(), instance); err != nil { - return err - } - - return nil -} - func (r *ReconcileCollectorJob) getCollectorSpec(namespace string, name string) (*troubleshootv1beta1.Collector, error) { cfg, err := config.GetConfig() if err != nil { diff --git a/pkg/controller/preflightjob/analyzers.go b/pkg/controller/preflightjob/analyzers.go new file mode 100644 index 00000000..590dcd56 --- /dev/null +++ b/pkg/controller/preflightjob/analyzers.go @@ -0,0 +1,5 @@ +package preflightjob + +func (r *ReconcilePreflightJob) reconcileAnalyzers() error { + return nil +} diff --git a/pkg/controller/preflightjob/collectors.go b/pkg/controller/preflightjob/collectors.go new file mode 100644 index 00000000..884afb92 --- /dev/null +++ b/pkg/controller/preflightjob/collectors.go @@ -0,0 +1,5 @@ +package preflightjob + +func (r *ReconcilePreflightJob) reconcileCollectors() error { + return nil +} diff --git a/pkg/controller/preflightjob/preflight_server.go b/pkg/controller/preflightjob/preflight_server.go new file mode 100644 index 00000000..6891eb1e --- /dev/null +++ b/pkg/controller/preflightjob/preflight_server.go @@ -0,0 +1,119 @@ +package preflightjob + +import ( + "fmt" + + troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" +) + +func (r *ReconcilePreflightJob) createPreflightServer(instance *troubleshootv1beta1.PreflightJob) error { + name := fmt.Sprintf("%s-%s", instance.Name, "preflight") + fmt.Printf("name = %s\n", name) + // namespacedName := types.NamespacedName{ + // Name: name, + // Namespace: instance.Namespace, + // } + + // found := &corev1.Pod{} + // err := r.Get(context.Background(), namespacedName, found) + // if err == nil || !kuberneteserrors.IsNotFound(err) { + // return err + // } + + // imageName := "replicatedhq/troubleshoot:latest" + // imagePullPolicy := corev1.PullAlways + + // if instance.Spec.Image != "" { + // imageName = instance.Spec.Image + // } + // if instance.Spec.ImagePullPolicy != "" { + // imagePullPolicy = corev1.PullPolicy(instance.Spec.ImagePullPolicy) + // } + + // podLabels := make(map[string]string) + // podLabels["collector"] = instance.Name + // podLabels["troubleshoot-role"] = "collector" + + // pod := corev1.Pod{ + // ObjectMeta: metav1.ObjectMeta{ + // Name: name, + // Namespace: instance.Namespace, + // Labels: podLabels, + // }, + // TypeMeta: metav1.TypeMeta{ + // APIVersion: "v1", + // Kind: "Pod", + // }, + // Spec: corev1.PodSpec{ + // RestartPolicy: corev1.RestartPolicyNever, + // Containers: []corev1.Container{ + // { + // Image: imageName, + // ImagePullPolicy: imagePullPolicy, + // Name: "collector", + // Command: []string{"collector"}, + // Args: []string{"server"}, + // Ports: []corev1.ContainerPort{ + // { + // Name: "http", + // ContainerPort: 8000, + // }, + // }, + // }, + // }, + // }, + // } + + // if err := controllerutil.SetControllerReference(instance, &pod, r.scheme); err != nil { + // return err + // } + + // if err := r.Create(context.Background(), &pod); err != nil { + // return err + // } + + // service := corev1.Service{ + // ObjectMeta: metav1.ObjectMeta{ + // Name: name, + // Namespace: instance.Namespace, + // }, + // TypeMeta: metav1.TypeMeta{ + // APIVersion: "v1", + // Kind: "Service", + // }, + // Spec: corev1.ServiceSpec{ + // Selector: podLabels, + // Type: corev1.ServiceTypeClusterIP, + // Ports: []corev1.ServicePort{ + // { + // Name: "http", + // Port: 8000, + // TargetPort: intstr.FromInt(8000), + // }, + // }, + // }, + // } + + // if err := controllerutil.SetControllerReference(instance, &service, r.scheme); err != nil { + // return err + // } + + // if err := r.Create(context.Background(), &service); err != nil { + // return err + // } + + // instance.Status.ServerPodName = name + // instance.Status.ServerPodNamespace = instance.Namespace + // instance.Status.ServerPodPort = 8000 + // instance.Status.IsServerReady = true + + // // wait for the server to be ready + // // TODO + // time.Sleep(time.Second * 5) + + // if err := r.Update(context.Background(), instance); err != nil { + // return err + // } + + return nil +} diff --git a/pkg/controller/preflightjob/preflightjob_controller.go b/pkg/controller/preflightjob/preflightjob_controller.go index d68b6f85..0b293159 100644 --- a/pkg/controller/preflightjob/preflightjob_controller.go +++ b/pkg/controller/preflightjob/preflightjob_controller.go @@ -18,18 +18,16 @@ package preflightjob import ( "context" - "reflect" + "fmt" troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" + troubleshootclientv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1" + kuberneteserrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/controller" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -39,11 +37,6 @@ import ( var log = logf.Log.WithName("controller") -/** -* USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller -* business logic. Delete these comments after modifying this file.* - */ - // Add creates a new PreflightJob Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller // and Start it when the Manager is Started. func Add(mgr manager.Manager) error { @@ -69,16 +62,6 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error { return err } - // TODO(user): Modify this to be the types you create - // Uncomment watch a Deployment created by PreflightJob - change this for objects you create - err = c.Watch(&source.Kind{Type: &appsv1.Deployment{}}, &handler.EnqueueRequestForOwner{ - IsController: true, - OwnerType: &troubleshootv1beta1.PreflightJob{}, - }) - if err != nil { - return err - } - return nil } @@ -104,7 +87,7 @@ func (r *ReconcilePreflightJob) Reconcile(request reconcile.Request) (reconcile. instance := &troubleshootv1beta1.PreflightJob{} err := r.Get(context.TODO(), request.NamespacedName, instance) if err != nil { - if errors.IsNotFound(err) { + if kuberneteserrors.IsNotFound(err) { // Object not found, return. Created objects are automatically garbage collected. // For additional cleanup logic use finalizers. return reconcile.Result{}, nil @@ -113,55 +96,45 @@ func (r *ReconcilePreflightJob) Reconcile(request reconcile.Request) (reconcile. return reconcile.Result{}, err } - // TODO(user): Change this to be the object type created by your controller - // Define the desired Deployment object - deploy := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: instance.Name + "-deployment", - Namespace: instance.Namespace, - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"deployment": instance.Name + "-deployment"}, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"deployment": instance.Name + "-deployment"}}, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "nginx", - Image: "nginx", - }, - }, - }, - }, - }, - } - if err := controllerutil.SetControllerReference(instance, deploy, r.scheme); err != nil { - return reconcile.Result{}, err - } - - // TODO(user): Change this for the object type created by your controller - // Check if the Deployment already exists - found := &appsv1.Deployment{} - err = r.Get(context.TODO(), types.NamespacedName{Name: deploy.Name, Namespace: deploy.Namespace}, found) - if err != nil && errors.IsNotFound(err) { - log.Info("Creating Deployment", "namespace", deploy.Namespace, "name", deploy.Name) - err = r.Create(context.TODO(), deploy) - return reconcile.Result{}, err - } else if err != nil { - return reconcile.Result{}, err - } - - // TODO(user): Change this for the object type created by your controller - // Update the found object and write the result back if there are any changes - if !reflect.DeepEqual(deploy.Spec, found.Spec) { - found.Spec = deploy.Spec - log.Info("Updating Deployment", "namespace", deploy.Namespace, "name", deploy.Name) - err = r.Update(context.TODO(), found) - if err != nil { + if !instance.Status.IsServerReady { + if err := r.createPreflightServer(instance); err != nil { return reconcile.Result{}, err } } + + namespace := instance.Namespace + if instance.Spec.Preflight.Namespace != "" { + namespace = instance.Spec.Preflight.Namespace + } + + preflightSpec, err := r.getPreflightSpec(namespace, instance.Spec.Preflight.Name) + if err != nil { + return reconcile.Result{}, err + } + + fmt.Printf("preflightSpec = %#v\n", preflightSpec) return reconcile.Result{}, nil } + +func (r *ReconcilePreflightJob) getPreflightSpec(namespace string, name string) (*troubleshootv1beta1.Preflight, error) { + cfg, err := config.GetConfig() + if err != nil { + return nil, err + } + + troubleshootClient, err := troubleshootclientv1beta1.NewForConfig(cfg) + if err != nil { + return nil, err + } + + preflight, err := troubleshootClient.Preflights(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + if kuberneteserrors.IsNotFound(err) { + return nil, nil + } + + return nil, err + } + + return preflight, nil +}