diff --git a/Makefile b/Makefile index f260cf75..8a61e475 100644 --- a/Makefile +++ b/Makefile @@ -79,9 +79,9 @@ snapshot-release: .PHONY: local-release local-release: snapshot-release - docker tag replicatedhq/troubleshoot:alpha localhost:32000/troubleshoot:alpha - docker tag replicatedhq/preflight:alpha localhost:32000/preflight:alpha - docker tag replicatedhq/troubleshoot-manager:alpha localhost:32000/troubleshoot-manager:alpha + docker tag replicated/troubleshoot:alpha localhost:32000/troubleshoot:alpha + docker tag replicated/preflight:alpha localhost:32000/preflight:alpha + docker tag replicated/troubleshoot-manager:alpha localhost:32000/troubleshoot-manager:alpha docker push localhost:32000/troubleshoot:alpha docker push localhost:32000/preflight:alpha docker push localhost:32000/troubleshoot-manager:alpha diff --git a/cmd/collector/cli/server.go b/cmd/collector/cli/server.go index 0186dcd4..09037078 100644 --- a/cmd/collector/cli/server.go +++ b/cmd/collector/cli/server.go @@ -13,16 +13,17 @@ import ( func Server() *cobra.Command { cmd := &cobra.Command{ - Use: "server", - Short: "run the http server", - Long: `...`, + Use: "server", + Short: "run the http server", + Hidden: true, + Long: `...`, PreRun: func(cmd *cobra.Command, args []string) { viper.BindPFlag("port", cmd.Flags().Lookup("port")) }, RunE: func(cmd *cobra.Command, args []string) error { v := viper.GetViper() - server.Serve(context.Background(), fmt.Sprintf(":%d", v.GetInt("port"))) + server.ServeCollector(context.Background(), fmt.Sprintf(":%d", v.GetInt("port"))) c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) diff --git a/cmd/preflight/cli/root.go b/cmd/preflight/cli/root.go index 5a9d22fe..c95bb28c 100644 --- a/cmd/preflight/cli/root.go +++ b/cmd/preflight/cli/root.go @@ -11,15 +11,18 @@ import ( func RootCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "troubleshoot", - Short: "Generate and manage support bundles", - Long: `A support bundle is an archive of files, output, metrics and state -from a server that can be used to assist when troubleshooting a server.`, + Use: "preflight", + Short: "Run and retrieve preflight checks in a cluster", + Long: `A preflight check is a set of validations that can and should be run to ensure +that a cluster meets the requirements to run an application.`, SilenceUsage: true, } cobra.OnInitialize(initConfig) + cmd.AddCommand(Run()) + cmd.AddCommand(Server()) + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) return cmd } @@ -32,6 +35,6 @@ func InitAndExecute() { } func initConfig() { - viper.SetEnvPrefix("TROUBLESHOOT") + viper.SetEnvPrefix("PREFLIGHT") viper.AutomaticEnv() } diff --git a/cmd/preflight/cli/run.go b/cmd/preflight/cli/run.go new file mode 100644 index 00000000..adf50304 --- /dev/null +++ b/cmd/preflight/cli/run.go @@ -0,0 +1,141 @@ +package cli + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "time" + + troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" + "github.com/replicatedhq/troubleshoot/pkg/k8sutil" + "github.com/spf13/cobra" + "github.com/spf13/viper" + kuberneteserrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Run() *cobra.Command { + cmd := &cobra.Command{ + Use: "run", + Short: "run a set of preflight checks in a cluster", + Long: `run preflight checks and return the results`, + PreRun: func(cmd *cobra.Command, args []string) { + viper.BindPFlags(cmd.Flags()) + }, + RunE: func(cmd *cobra.Command, args []string) error { + v := viper.GetViper() + + troubleshootClient, err := createTroubleshootK8sClient() + if err != nil { + return err + } + + preflightName := v.GetString("preflight") + if preflightName == "" { + preflights, err := troubleshootClient.Preflights(v.GetString("namespace")).List(metav1.ListOptions{}) + if err != nil { + return err + } + + if len(preflights.Items) == 1 { + preflightName = preflights.Items[0].Name + } + } + + if preflightName == "" { + return errors.New("unable to fly, try using the --preflight flags") + } + + // generate a unique name + now := time.Now() + suffix := fmt.Sprintf("%d", now.Unix()) + + preflightJobName := fmt.Sprintf("%s-job-%s", preflightName, suffix[len(suffix)-4:]) + preflightJob := troubleshootv1beta1.PreflightJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: preflightJobName, + Namespace: v.GetString("namespace"), + }, + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "preflightjob.troubleshoot.replicated.com", + }, + Spec: troubleshootv1beta1.PreflightJobSpec{ + Preflight: troubleshootv1beta1.PreflightRef{ + Name: preflightName, + Namespace: v.GetString("namespace"), + }, + Image: v.GetString("image"), + ImagePullPolicy: v.GetString("pullpolicy"), + CollectorImage: v.GetString("collector-image"), + CollectorImagePullPolicy: v.GetString("collector-pullpolicy"), + }, + } + if _, err := troubleshootClient.PreflightJobs(v.GetString("namespace")).Create(&preflightJob); err != nil { + return err + } + + // Poll the status of the Custom Resource for it to include a callback + var found *troubleshootv1beta1.PreflightJob + start := time.Now() + for { + current, err := troubleshootClient.PreflightJobs(v.GetString("namespace")).Get(preflightJobName, metav1.GetOptions{}) + if err != nil && kuberneteserrors.IsNotFound(err) { + continue + } else if err != nil { + return err + } + + if current.Status.IsServerReady { + found = current + break + } + + if time.Now().Sub(start) > time.Duration(time.Second*10) { + return errors.New("preflightjob failed to start") + } + + time.Sleep(time.Millisecond * 200) + } + + // Connect to the callback + stopChan, err := k8sutil.PortForward(v.GetString("kubecontext"), 8000, 8000, found.Status.ServerPodNamespace, found.Status.ServerPodName) + if err != nil { + return err + } + + // if err := receiveSupportBundle(found.Namespace, found.Name); err != nil { + // return err + // } + + // Write + + close(stopChan) + return nil + }, + } + + cmd.Flags().String("preflight", "", "name of the preflight to use") + cmd.Flags().String("namespace", "default", "namespace the preflight can be found in") + + cmd.Flags().String("kubecontext", filepath.Join(homeDir(), ".kube", "config"), "the kubecontext to use when connecting") + + cmd.Flags().String("image", "", "the full name of the preflight image to use") + cmd.Flags().String("pullpolicy", "", "the pull policy of the preflight image") + cmd.Flags().String("collector-image", "", "the full name of the collector image to use") + cmd.Flags().String("collector-pullpolicy", "", "the pull policy of the collector image") + cmd.Flags().String("analyzer-image", "", "the full name of the analyzer image to use") + cmd.Flags().String("analyzer-pullpolicy", "", "the pull policy of the analyzer image") + + viper.BindPFlags(cmd.Flags()) + + return cmd +} + +func homeDir() string { + if h := os.Getenv("HOME"); h != "" { + return h + } + return os.Getenv("USERPROFILE") // windows +} diff --git a/cmd/preflight/cli/server.go b/cmd/preflight/cli/server.go new file mode 100644 index 00000000..bb0f75e3 --- /dev/null +++ b/cmd/preflight/cli/server.go @@ -0,0 +1,43 @@ +package cli + +import ( + "context" + "fmt" + "os" + "os/signal" + + "github.com/replicatedhq/troubleshoot/pkg/server" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func Server() *cobra.Command { + cmd := &cobra.Command{ + Use: "server", + Short: "run the http server", + Hidden: true, + Long: `...`, + PreRun: func(cmd *cobra.Command, args []string) { + viper.BindPFlag("port", cmd.Flags().Lookup("port")) + }, + RunE: func(cmd *cobra.Command, args []string) error { + v := viper.GetViper() + + server.ServePreflight(context.Background(), fmt.Sprintf(":%d", v.GetInt("port"))) + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + + select { + case <-c: + return nil + } + }, + } + + cmd.Flags().Int("port", 8000, "port to listen on") + + viper.BindPFlags(cmd.Flags()) + + return cmd +} diff --git a/cmd/preflight/cli/troubleshoot.go b/cmd/preflight/cli/troubleshoot.go new file mode 100644 index 00000000..6f25c40c --- /dev/null +++ b/cmd/preflight/cli/troubleshoot.go @@ -0,0 +1,22 @@ +package cli + +import ( + troubleshootclientv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1" + "github.com/spf13/viper" + "k8s.io/client-go/tools/clientcmd" +) + +func createTroubleshootK8sClient() (*troubleshootclientv1beta1.TroubleshootV1beta1Client, error) { + v := viper.GetViper() + + config, err := clientcmd.BuildConfigFromFlags("", v.GetString("kubecontext")) + if err != nil { + return nil, err + } + troubleshootClient, err := troubleshootclientv1beta1.NewForConfig(config) + if err != nil { + return nil, err + } + + return troubleshootClient, nil +} diff --git a/config/crds/troubleshoot.replicated.com_preflightjobs.yaml b/config/crds/troubleshoot.replicated.com_preflightjobs.yaml index 727ede36..7eb94fe9 100644 --- a/config/crds/troubleshoot.replicated.com_preflightjobs.yaml +++ b/config/crds/troubleshoot.replicated.com_preflightjobs.yaml @@ -399,6 +399,8 @@ spec: type: string collectorImagePullPolicy: type: string + imagePullPolicy: + type: string preflight: properties: name: @@ -408,6 +410,8 @@ spec: required: - name type: object + preflightImage: + type: string required: - preflight type: object diff --git a/config/crds/zz_generated.deepcopy.go b/config/crds/zz_generated.deepcopy.go index b9b60e31..662be0a8 100644 --- a/config/crds/zz_generated.deepcopy.go +++ b/config/crds/zz_generated.deepcopy.go @@ -590,8 +590,8 @@ func (in *PreflightJobStatus) DeepCopyInto(out *PreflightJobStatus) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.AnakyzersFailed != nil { - in, out := &in.AnakyzersFailed, &out.AnakyzersFailed + if in.AnalyzersFailed != nil { + in, out := &in.AnalyzersFailed, &out.AnalyzersFailed *out = make([]string, len(*in)) copy(*out, *in) } diff --git a/deploy/.goreleaser.snapshot.yml b/deploy/.goreleaser.snapshot.yml index b2186b02..3ced0aa2 100644 --- a/deploy/.goreleaser.snapshot.yml +++ b/deploy/.goreleaser.snapshot.yml @@ -84,19 +84,21 @@ archives: dockers: - dockerfile: ./deploy/Dockerfile.troubleshoot image_templates: - - "replicatedhq/troubleshoot:alpha" + - "replicated/troubleshoot:alpha" binaries: - collector - troubleshoot - - dockerfile: ./deploy/Dockerfile.preflight + - preflight + - dockerfile: ./deploy/Dockerfile.troubleshoot image_templates: - - "replicatedhq/preflight:alpha" + - "replicated/preflight:alpha" binaries: - collector + - troubleshoot - preflight - dockerfile: ./deploy/Dockerfile.manager image_templates: - - "replicatedhq/troubleshoot-manager:alpha" + - "replicated/troubleshoot-manager:alpha" binaries: - manager snapshot: diff --git a/deploy/Dockerfile.preflight b/deploy/Dockerfile.preflight deleted file mode 100644 index 10ccc288..00000000 --- a/deploy/Dockerfile.preflight +++ /dev/null @@ -1,12 +0,0 @@ -FROM debian:buster -WORKDIR / - -RUN apt-get -qq update \ - && apt-get -qq -y install \ - ca-certificates - -COPY preflight /preflight/preflight -COPY collector /preflight/collector - -ENV PATH="/preflight:${PATH}" - diff --git a/deploy/Dockerfile.troubleshoot b/deploy/Dockerfile.troubleshoot index bb2ebd36..0d50b1ac 100644 --- a/deploy/Dockerfile.troubleshoot +++ b/deploy/Dockerfile.troubleshoot @@ -7,6 +7,7 @@ RUN apt-get -qq update \ COPY troubleshoot /troubleshoot/troubleshoot COPY collector /troubleshoot/collector +COPY preflight /troubleshoot/preflight ENV PATH="/troubleshoot:${PATH}" diff --git a/pkg/apis/troubleshoot/v1beta1/preflightjob_types.go b/pkg/apis/troubleshoot/v1beta1/preflightjob_types.go index c17ee669..aba700f8 100644 --- a/pkg/apis/troubleshoot/v1beta1/preflightjob_types.go +++ b/pkg/apis/troubleshoot/v1beta1/preflightjob_types.go @@ -29,6 +29,8 @@ type PreflightRef struct { type PreflightJobSpec struct { Preflight PreflightRef `json:"preflight"` + Image string `json:"preflightImage,omitempty"` + ImagePullPolicy string `json:"imagePullPolicy,omitempty"` CollectorImage string `json:"collectorImage,omitempty"` CollectorImagePullPolicy string `json:"collectorImagePullPolicy,omitempty"` @@ -51,7 +53,7 @@ type PreflightJobStatus struct { IsAnalyzersComplete bool `json:"isAnalyzersComplete"` AnalyzersRunning []string `json:"analyzersRunning"` AnalyzersSuccessful []string `json:"analyzersSuccessful"` - AnakyzersFailed []string `json:"analyzersFailed"` + AnalyzersFailed []string `json:"analyzersFailed"` } // +genclient diff --git a/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go b/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go index 13fcb571..1188ccd7 100644 --- a/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go @@ -606,8 +606,8 @@ func (in *PreflightJobStatus) DeepCopyInto(out *PreflightJobStatus) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.AnakyzersFailed != nil { - in, out := &in.AnakyzersFailed, &out.AnakyzersFailed + if in.AnalyzersFailed != nil { + in, out := &in.AnalyzersFailed, &out.AnalyzersFailed *out = make([]string, len(*in)) copy(*out, *in) } diff --git a/pkg/controller/collector/collector_controller.go b/pkg/controller/collector/collector_controller.go index ee2b9169..3f2cfcfa 100644 --- a/pkg/controller/collector/collector_controller.go +++ b/pkg/controller/collector/collector_controller.go @@ -34,11 +34,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 Collector 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 { diff --git a/pkg/controller/preflight/preflight_controller.go b/pkg/controller/preflight/preflight_controller.go index cc775c41..04968d63 100644 --- a/pkg/controller/preflight/preflight_controller.go +++ b/pkg/controller/preflight/preflight_controller.go @@ -18,18 +18,12 @@ package preflight import ( "context" - "reflect" 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" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kuberneteserrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "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 +33,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 Preflight 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 +58,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 Preflight - change this for objects you create - err = c.Watch(&source.Kind{Type: &appsv1.Deployment{}}, &handler.EnqueueRequestForOwner{ - IsController: true, - OwnerType: &troubleshootv1beta1.Preflight{}, - }) - if err != nil { - return err - } - return nil } @@ -104,7 +83,7 @@ func (r *ReconcilePreflight) Reconcile(request reconcile.Request) (reconcile.Res instance := &troubleshootv1beta1.Preflight{} 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 +92,5 @@ func (r *ReconcilePreflight) Reconcile(request reconcile.Request) (reconcile.Res 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 { - return reconcile.Result{}, err - } - } return reconcile.Result{}, nil } diff --git a/pkg/controller/preflightjob/analyzers.go b/pkg/controller/preflightjob/analyzers.go index 590dcd56..8dd1356c 100644 --- a/pkg/controller/preflightjob/analyzers.go +++ b/pkg/controller/preflightjob/analyzers.go @@ -1,5 +1,5 @@ package preflightjob -func (r *ReconcilePreflightJob) reconcileAnalyzers() error { +func (r *ReconcilePreflightJob) reconcilePreflightAnalyzers() error { return nil } diff --git a/pkg/controller/preflightjob/collectors.go b/pkg/controller/preflightjob/collectors.go index 884afb92..8443a814 100644 --- a/pkg/controller/preflightjob/collectors.go +++ b/pkg/controller/preflightjob/collectors.go @@ -1,5 +1,19 @@ package preflightjob -func (r *ReconcilePreflightJob) reconcileCollectors() error { +import ( + "fmt" + + troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" + // 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" + // "sigs.k8s.io/controller-runtime/pkg/client/config" +) + +func (r *ReconcilePreflightJob) reconcilePreflightCollectors(instance *troubleshootv1beta1.PreflightJob, preflight *troubleshootv1beta1.Preflight) error { + for _, collector := range preflight.Spec.Collectors { + fmt.Printf("collector = %#v\n", collector) + } + return nil } diff --git a/pkg/controller/preflightjob/preflight_server.go b/pkg/controller/preflightjob/preflight_server.go index 6891eb1e..c6152bff 100644 --- a/pkg/controller/preflightjob/preflight_server.go +++ b/pkg/controller/preflightjob/preflight_server.go @@ -1,119 +1,126 @@ package preflightjob 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 *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, - // } + 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 - // } + 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 + 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) - // } + 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" + podLabels := make(map[string]string) + podLabels["preflight"] = instance.Name + podLabels["troubleshoot-role"] = "preflight" - // 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, - // }, - // }, - // }, - // }, - // }, - // } + 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: "preflight", + Command: []string{"preflight"}, + Args: []string{"server"}, + Ports: []corev1.ContainerPort{ + { + Name: "http", + ContainerPort: 8000, + }, + }, + }, + }, + }, + } - // if err := controllerutil.SetControllerReference(instance, &pod, r.scheme); err != nil { - // return err - // } + if err := controllerutil.SetControllerReference(instance, &pod, r.scheme); err != nil { + return err + } - // if err := r.Create(context.Background(), &pod); 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), - // }, - // }, - // }, - // } + 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 := controllerutil.SetControllerReference(instance, &service, r.scheme); err != nil { + return err + } - // if err := r.Create(context.Background(), &service); 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 + 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) + // wait for the server to be ready + // TODO + time.Sleep(time.Second * 5) - // if err := r.Update(context.Background(), instance); err != nil { - // return err - // } + 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 0b293159..43a3ce4d 100644 --- a/pkg/controller/preflightjob/preflightjob_controller.go +++ b/pkg/controller/preflightjob/preflightjob_controller.go @@ -18,7 +18,6 @@ package preflightjob import ( "context" - "fmt" troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" troubleshootclientv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1" @@ -112,7 +111,18 @@ func (r *ReconcilePreflightJob) Reconcile(request reconcile.Request) (reconcile. return reconcile.Result{}, err } - fmt.Printf("preflightSpec = %#v\n", preflightSpec) + // the preflight job will be in collector mode or analyzer mode + if !instance.Status.IsCollectorsComplete { + if err := r.reconcilePreflightCollectors(instance, preflightSpec); err != nil { + return reconcile.Result{}, err + } + } else if !instance.Status.IsAnalyzersComplete { + if err := r.reconcilePreflightAnalyzers(); err != nil { + return reconcile.Result{}, err + } + } + + // just finished, nothing to do return reconcile.Result{}, nil } diff --git a/pkg/server/server.go b/pkg/server/collector.go similarity index 68% rename from pkg/server/server.go rename to pkg/server/collector.go index 527b397a..572fe707 100644 --- a/pkg/server/server.go +++ b/pkg/server/collector.go @@ -10,9 +10,9 @@ import ( "github.com/gin-gonic/gin" ) -var queue = make(map[string][]byte) +var collectorQueue = make(map[string][]byte) -func Serve(ctx context.Context, address string) { +func ServeCollector(ctx context.Context, address string) { g := gin.New() root := g.Group("/") @@ -35,20 +35,20 @@ func putCollectorOutput(c *gin.Context) { return } - queue[collectorID] = body + collectorQueue[collectorID] = body - fmt.Printf("queue = %#v\n", queue) + fmt.Printf("collectorQueue = %#v\n", collectorQueue) c.Status(201) } func getCollectorOutput(c *gin.Context) { - encoded := base64.StdEncoding.EncodeToString(queue[c.Param("id")]) + encoded := base64.StdEncoding.EncodeToString(collectorQueue[c.Param("id")]) c.String(200, encoded) } func getQueuedCollectors(c *gin.Context) { - keys := make([]string, 0, len(queue)) - for k := range queue { + keys := make([]string, 0, len(collectorQueue)) + for k := range collectorQueue { keys = append(keys, k) } diff --git a/pkg/server/preflight.go b/pkg/server/preflight.go new file mode 100644 index 00000000..e43d8314 --- /dev/null +++ b/pkg/server/preflight.go @@ -0,0 +1,56 @@ +package server + +import ( + "context" + "encoding/base64" + "fmt" + "io/ioutil" + "net/http" + + "github.com/gin-gonic/gin" +) + +var preflightQueue = make(map[string][]byte) + +func ServePreflight(ctx context.Context, address string) { + g := gin.New() + + root := g.Group("/") + root.PUT("/", putPreflightOutput) + root.GET("/", getQueuedPreflights) + root.GET("/preflight/:id", getPreflightOutput) + + srvr := http.Server{Addr: address, Handler: g} + go func() { + srvr.ListenAndServe() + }() +} + +func putPreflightOutput(c *gin.Context) { + preflightID := c.Request.Header.Get("collector-id") + + body, err := ioutil.ReadAll(c.Request.Body) + if err != nil { + c.AbortWithStatus(500) + return + } + + preflightQueue[preflightID] = body + + fmt.Printf("preflightQueue = %#v\n", preflightQueue) + c.Status(201) +} + +func getPreflightOutput(c *gin.Context) { + encoded := base64.StdEncoding.EncodeToString(preflightQueue[c.Param("id")]) + c.String(200, encoded) +} + +func getQueuedPreflights(c *gin.Context) { + keys := make([]string, 0, len(preflightQueue)) + for k := range preflightQueue { + keys = append(keys, k) + } + + c.JSON(200, keys) +}