mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
Preflight server and CLI
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -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}"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package preflightjob
|
||||
|
||||
func (r *ReconcilePreflightJob) reconcileAnalyzers() error {
|
||||
func (r *ReconcilePreflightJob) reconcilePreflightAnalyzers() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user