func Run()

in internal/diag.go [62:259]


func Run(params Params) error {
	logger.Printf("ECK diagnostics with parameters: %+v", params)
	stopCh := make(chan struct{})
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt)
	go func() {
		s := <-sigCh
		logger.Printf("Aborting: %v received", s)
		close(stopCh)
	}()

	kubectl, err := NewKubectl(params.Kubeconfig, params.Verbose)
	if err != nil {
		return err
	}

	if err := kubectl.CheckNamespaces(context.Background(), params.AllNamespaces()); err != nil {
		return err
	}

	clientSet, err := kubectl.factory.KubernetesClientSet()
	if err != nil {
		return err
	}

	zipFileName := filepath.Join(params.OutputDir, params.OutputName)
	zipFile, err := archive.NewZipFile(zipFileName, about().Version, logger)
	if err != nil {
		return err
	}

	// Filters is intentionally empty in many of these, as Elastic labels
	// are not applied to these resources.
	zipFile.Add(map[string]func(io.Writer) error{
		"version.json": func(writer io.Writer) error {
			return kubectl.Version(writer)
		},
		"nodes.json": func(writer io.Writer) error {
			return kubectl.GetByLabel("nodes", "", filters.Empty, writer)
		},
		"podsecuritypolicies.json": func(writer io.Writer) error {
			return kubectl.GetByLabel("podsecuritypolicies", "", filters.Empty, writer)
		},
		"storageclasses.json": func(writer io.Writer) error {
			return kubectl.GetByLabel("storageclasses", "", filters.Empty, writer)
		},
		"clusterroles.txt": func(writer io.Writer) error {
			return kubectl.Describe("clusterroles", "elastic", "", writer)
		},
		"clusterrolebindings.txt": func(writer io.Writer) error {
			return kubectl.Describe("clusterrolebindings", "elastic", "", writer)
		},
	})

	var operatorLabels []labels.Set
	operatorVersions := make([]*version.Version, 0, len(params.OperatorNamespaces))
	for _, ns := range params.OperatorNamespaces {
		// Find the label in use by operator in this namespace and add this to
		// the set of filters to ensure we always retrieve the objects
		// associated with the ECK operator.
		operatorLabel, err := getOperatorLabel(kubectl, ns)
		if err != nil || operatorLabel == nil {
			logger.Printf("Could not find label corresponding to ECK Operator in namespace %s: potentially not including operator data in diagnostics", ns)
		} else {
			operatorLabels = append(operatorLabels, operatorLabel)
		}

		operatorVersions = append(operatorVersions, detectECKVersion(clientSet, ns, params.ECKVersion))
	}

	maxOperatorVersion := maxVersion(operatorVersions)
	logVersion(maxOperatorVersion)

	allNamespaces := sets.New(params.ResourcesNamespaces...)
	allNamespaces.Insert(params.OperatorNamespaces...)

	logsLabels := []string{
		"common.k8s.elastic.co/type=elasticsearch",
		"common.k8s.elastic.co/type=kibana",
		"common.k8s.elastic.co/type=apm-server",
		// the below were introduced in later version but label selector will just return no result:
		"common.k8s.elastic.co/type=enterprise-search", // 1.2.0
		"common.k8s.elastic.co/type=beat",              // 1.2.0
		"common.k8s.elastic.co/type=agent",             // 1.4.0
		"common.k8s.elastic.co/type=maps",              // 1.6.0
		"common.k8s.elastic.co/type=logstash",          // 2.8.0
	}

	operatorSelectors := make([]labels.Selector, len(operatorLabels))
	for i, label := range operatorLabels {
		operatorSelectors[i] = label.AsSelector()
		logsLabels = append(logsLabels, label.AsSelector().String())
	}
	// always collect operator information even in the presence of filters
	operatorFilters := filters.LabelFilter(operatorSelectors)
	// user defined type filters or any resource related to the operator
	namespaceFilters := filters.Or(params.Filters, operatorFilters)
	// for logs respect user defined log filters but add the operator filters here too so that the AND works out and we always have the operator logs
	logsFilters := filters.And(filters.Or(params.LogFilters, operatorFilters), namespaceFilters)

LOOP:
	for ns := range allNamespaces {
		select {
		case <-stopCh:
			break LOOP
		default:
		}

		logger.Printf("Extracting Kubernetes diagnostics from %s\n", ns)
		zipFile.Add(getResources(kubectl.GetByLabel, ns, namespaceFilters, []string{
			"statefulsets",
			"replicasets",
			"deployments",
			"daemonsets",
			"pods",
			"persistentvolumeclaims",
			"services",
			"endpoints",
			"configmaps",
			"controllerrevisions",
		}))

		zipFile.Add(getResources(kubectl.GetByName, ns, namespaceFilters, []string{
			"kibana",
			"elasticsearch",
			"apmserver",
		}))

		// Filters is intentionally empty here, as Elastic labels
		// are not applied to these resources.
		zipFile.Add(getResources(kubectl.GetByLabel, ns, filters.Empty, []string{
			"persistentvolumes",
			"events",
			"networkpolicies",
			"serviceaccount",
		}))

		if maxOperatorVersion.AtLeast(version.MustParseSemantic("1.2.0")) {
			zipFile.Add(getResources(kubectl.GetByName, ns, namespaceFilters, []string{
				"enterprisesearch",
				"beat",
			}))
		}

		if maxOperatorVersion.AtLeast(version.MustParseSemantic("1.4.0")) {
			zipFile.Add(getResources(kubectl.GetByName, ns, namespaceFilters, []string{
				"agent",
			}))
		}

		if maxOperatorVersion.AtLeast(version.MustParseSemantic("1.6.0")) {
			zipFile.Add(getResources(kubectl.GetByName, ns, namespaceFilters, []string{
				"elasticmapsserver",
			}))
		}
		if maxOperatorVersion.AtLeast(logstashMinVersion) {
			zipFile.Add(getResources(kubectl.GetByName, ns, namespaceFilters, []string{
				"logstash",
			}))
		}

		zipFile.Add(map[string]func(io.Writer) error{
			archive.Path(ns, "secrets.json"): func(writer io.Writer) error {
				return kubectl.GetMeta("secrets", ns, writer)
			},
		})

		getLogs(kubectl, zipFile, ns, logsFilters, logsLabels...)

		if params.RunStackDiagnostics {
			runStackDiagnostics(
				kubectl,
				ns,
				zipFile,
				params.Verbose,
				params.DiagnosticImage,
				params.StackDiagnosticsTimeout,
				stopCh,
				namespaceFilters,
				maxOperatorVersion,
			)
		}

		if params.RunAgentDiagnostics {
			runAgentDiagnostics(kubectl, ns, zipFile, params.Verbose, stopCh, namespaceFilters)
		}
	}

	addDiagnosticLogToArchive(zipFile, &log.Buffer)

	if err := zipFile.Close(); err != nil {
		// log the errors here and don't return them to the invoking command as we don't want usage help to be
		// printed in this case
		logger.Println(err.Error())
	}
	logger.Printf("ECK diagnostics written to %s\n", zipFileName)
	return nil
}