Skip to content

Commit

Permalink
Merge pull request #50 from replicatedhq/run-in-cli
Browse files Browse the repository at this point in the history
Run in cli
  • Loading branch information
marccampbell authored Aug 15, 2019
2 parents 91b33b0 + 3b1428a commit ff81cac
Show file tree
Hide file tree
Showing 15 changed files with 171 additions and 460 deletions.
15 changes: 12 additions & 3 deletions cmd/collector/cli/run.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cli

import (
"fmt"
"io/ioutil"

"github.com/replicatedhq/troubleshoot/pkg/collect"
Expand All @@ -25,14 +26,22 @@ func Run() *cobra.Command {
return err
}

c, err := collect.ParseSpec(string(specContents))
if err != nil {
return err
}

collector := collect.Collector{
Spec: string(specContents),
Redact: v.GetBool("redact"),
Collect: c,
Redact: v.GetBool("redact"),
}
if err := collector.RunCollectorSync(); err != nil {
b, err := collector.RunCollectorSync()
if err != nil {
return err
}

fmt.Printf("%s", b)

return nil
},
}
Expand Down
180 changes: 14 additions & 166 deletions cmd/preflight/cli/run_nocrd.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package cli

import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
Expand All @@ -18,22 +15,11 @@ import (
"github.com/pkg/errors"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
collectrunner "github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/logger"
"github.com/spf13/viper"
"github.com/tj/go-spin"
"gopkg.in/yaml.v2"
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/fields"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)

func runPreflightsNoCRD(v *viper.Viper, arg string) error {
Expand Down Expand Up @@ -143,174 +129,36 @@ func runPreflightsNoCRD(v *viper.Viper, arg string) error {
}

func runCollectors(v *viper.Viper, preflight troubleshootv1beta1.Preflight) (map[string][]byte, error) {
cfg, err := config.GetConfig()
if err != nil {
return nil, err
}

client, err := client.New(cfg, client.Options{})
if err != nil {
return nil, err
}
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, err
}
restClient := clientset.CoreV1().RESTClient()

serviceAccountName := v.GetString("serviceaccount")
if serviceAccountName == "" {
generatedServiceAccountName, err := createServiceAccount(preflight, v.GetString("namespace"), clientset)
if err != nil {
return nil, err
}
defer removeServiceAccount(generatedServiceAccountName, v.GetString("namespace"), clientset)

serviceAccountName = generatedServiceAccountName
}

// deploy an object that "owns" everything to aid in cleanup
configMapNamespacedName := types.NamespacedName{
Name: fmt.Sprintf("preflight-%s-owner", preflight.Name),
Namespace: v.GetString("namespace"),
}

foundConfigMap := &corev1.ConfigMap{}
err = client.Get(context.Background(), configMapNamespacedName, foundConfigMap)
if err == nil || !kuberneteserrors.IsNotFound(err) {
return nil, errors.Wrap(err, "failed to get existing config map")
}
owner := corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: configMapNamespacedName.Name,
Namespace: configMapNamespacedName.Namespace,
},
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
Data: make(map[string]string),
}
if err := client.Create(context.Background(), &owner); err != nil {
return nil, errors.Wrap(err, "failed to create config map")
}
defer func() {
if err := client.Delete(context.Background(), &owner); err != nil {
fmt.Println("failed to clean up preflight.")
}
}()

// deploy all collectors
desiredCollectors := make([]*troubleshootv1beta1.Collect, 0, 0)
for _, definedCollector := range preflight.Spec.Collectors {
desiredCollectors = append(desiredCollectors, definedCollector)
}
desiredCollectors = ensureCollectorInList(desiredCollectors, troubleshootv1beta1.Collect{ClusterInfo: &troubleshootv1beta1.ClusterInfo{}})
desiredCollectors = ensureCollectorInList(desiredCollectors, troubleshootv1beta1.Collect{ClusterResources: &troubleshootv1beta1.ClusterResources{}})

podsCreated := make([]*corev1.Pod, 0, 0)
podsDeleted := make([]*corev1.Pod, 0, 0)
allCollectedData := make(map[string][]byte)

resyncPeriod := time.Second
ctx := context.Background()
watchList := cache.NewListWatchFromClient(restClient, "pods", "", fields.Everything())
_, controller := cache.NewInformer(watchList, &corev1.Pod{}, resyncPeriod,
cache.ResourceEventHandlerFuncs{
UpdateFunc: func(oldObj interface{}, newObj interface{}) {
newPod, ok := newObj.(*corev1.Pod)
if !ok {
return
}
oldPod, ok := oldObj.(*corev1.Pod)
if !ok {
return
}
labels := newPod.Labels
troubleshootRole, ok := labels["troubleshoot-role"]
if !ok || troubleshootRole != "preflight" {
return
}
preflightName, ok := labels["preflight"]
if !ok || preflightName != preflight.Name {
return
}

if oldPod.Status.Phase == newPod.Status.Phase {
return
}

if newPod.Status.Phase == corev1.PodFailed {
podsDeleted = append(podsDeleted, newPod)
return
}

if newPod.Status.Phase != corev1.PodSucceeded {
return
}

podLogOpts := corev1.PodLogOptions{}

req := clientset.CoreV1().Pods(newPod.Namespace).GetLogs(newPod.Name, &podLogOpts)
podLogs, err := req.Stream()
if err != nil {
fmt.Println("get stream")
return
}
defer podLogs.Close()

buf := new(bytes.Buffer)
_, err = io.Copy(buf, podLogs)
if err != nil {
fmt.Println("copy logs")
return
}

collectedData, err := parseCollectorOutput(buf.String())
if err != nil {
logger.Printf("parse collected data: %v\n", err)
return
}
for k, v := range collectedData {
allCollectedData[k] = v
}

if err := client.Delete(context.Background(), newPod); err != nil {
fmt.Println("delete pod")
}
podsDeleted = append(podsDeleted, newPod)
},
})
go func() {
controller.Run(ctx.Done())
}()
// Run preflights collectors synchronously
for _, desiredCollector := range desiredCollectors {
collector := collect.Collector{
Redact: true,
Collect: desiredCollector,
}

s := runtime.NewScheme()
s.AddKnownTypes(schema.GroupVersion{Group: "", Version: "v1"}, &corev1.ConfigMap{})
for _, collector := range desiredCollectors {
_, pod, err := collectrunner.CreateCollector(client, s, &owner, preflight.Name, v.GetString("namespace"), serviceAccountName, "preflight", collector, v.GetString("image"), v.GetString("pullpolicy"))
result, err := collector.RunCollectorSync()
if err != nil {
return nil, errors.Wrap(err, "failed to create collector")
return nil, errors.Wrap(err, "failed to run collector")
}
podsCreated = append(podsCreated, pod)
}

start := time.Now()
for {
if start.Add(time.Second * 30).Before(time.Now()) {
fmt.Println("timeout running preflight")
return nil, err
output, err := parseCollectorOutput(string(result))
if err != nil {
return nil, errors.Wrap(err, "failed to parse collector output")
}

if len(podsDeleted) == len(podsCreated) {
break
for k, v := range output {
allCollectedData[k] = v
}

time.Sleep(time.Millisecond * 200)
}

ctx.Done()

return allCollectedData, nil
}

Expand Down
5 changes: 4 additions & 1 deletion cmd/preflight/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package main

import "github.com/replicatedhq/troubleshoot/cmd/preflight/cli"
import (
"github.com/replicatedhq/troubleshoot/cmd/preflight/cli"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
)

func main() {
cli.InitAndExecute()
Expand Down
Loading

0 comments on commit ff81cac

Please sign in to comment.