feat: add loader APIs to load specs from raw troubleshoot spec (#1202)

* feat: add loader APIs to load specs from a list of yaml docs

The change introduces a loader package that will contain loader
public APIs. The aim of these APIs will be to, given any source of
troubleshoot specs, the loaders will fetch the specs and parse out
all troubleshoot objects that can be extracted.

* Some refactoring

* Some more changes

* More changes caught when testing vendor portal

* Add tests and rename Troubleshoot kinds struct

* Additional test

* Handle ConfigMap and Secrets with multiple specs in them

* Fix failing test

* Revert multidoc split implementation

* Fix merge conflict

* Change LoadFromXXX functions to a single LoadSpecs function
This commit is contained in:
Evans Mungai
2023-06-06 21:48:29 +01:00
committed by GitHub
parent 145bad7e8e
commit 401dfe2c57
22 changed files with 1313 additions and 140 deletions

View File

@@ -7,7 +7,7 @@ import (
"os"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/spf13/viper"
)

View File

@@ -10,10 +10,9 @@ import (
"time"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
@@ -88,7 +87,6 @@ func runCollect(v *viper.Viper, arg string) error {
multidocs := strings.Split(string(collectorContent), "\n---\n")
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
redactors, err := supportbundle.GetRedactorsFromURIs(v.GetStringSlice("redactors"))

View File

@@ -7,7 +7,7 @@ import (
"net/http"
"os"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/replicatedhq/troubleshoot/pkg/convert"
"github.com/spf13/cobra"

View File

@@ -10,7 +10,7 @@ import (
"github.com/pkg/errors"
ui "github.com/replicatedhq/termui/v3"
"github.com/replicatedhq/termui/v3/widgets"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
)

View File

@@ -19,8 +19,6 @@ import (
"github.com/pkg/errors"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/convert"
"github.com/replicatedhq/troubleshoot/pkg/httputil"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
@@ -79,7 +77,6 @@ func runTroubleshoot(v *viper.Viper, arg []string) error {
var mainBundle *troubleshootv1beta2.SupportBundle
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
additionalRedactors := &troubleshootv1beta2.Redactor{}
// Defining `v` below will render using `v` in reference to Viper unusable.

View File

@@ -40,3 +40,7 @@ func AppName(name string) string {
return strings.Join(casedWords, " ")
}
func SplitYAML(doc string) []string {
return strings.Split(doc, "\n---\n")
}

View File

@@ -4,20 +4,23 @@ import (
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"k8s.io/apimachinery/pkg/runtime"
)
var decoder runtime.Decoder
func init() {
decoder = scheme.Codecs.UniversalDeserializer()
}
func ParseCollectorFromDoc(doc []byte) (*troubleshootv1beta2.Collector, error) {
doc, err := docrewrite.ConvertToV1Beta2(doc)
if err != nil {
return nil, errors.Wrap(err, "failed to convert to v1beta2")
}
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode(doc, nil, nil)
obj, _, err := decoder.Decode(doc, nil, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to parse document")
}
@@ -36,10 +39,7 @@ func ParseHostCollectorFromDoc(doc []byte) (*troubleshootv1beta2.HostCollector,
return nil, errors.Wrap(err, "failed to convert to v1beta2")
}
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode(doc, nil, nil)
obj, _, err := decoder.Decode(doc, nil, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to parse document")
}
@@ -58,10 +58,7 @@ func ParseRemoteCollectorFromDoc(doc []byte) (*troubleshootv1beta2.RemoteCollect
return nil, errors.Wrap(err, "failed to convert to v1beta2")
}
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode(doc, nil, nil)
obj, _, err := decoder.Decode(doc, nil, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to parse document")
}

View File

@@ -15,7 +15,6 @@ const (
DEFAULT_LOGS_COLLECTOR_TIMEOUT = 60 * time.Second
// Tracing constants
LIB_TRACER_NAME = "github.com/replicatedhq/troubleshoot"
TROUBLESHOOT_ROOT_SPAN_NAME = "ReplicatedTroubleshootRootSpan"
EXCLUDED = "excluded"
@@ -58,4 +57,12 @@ const (
EXIT_CODE_SPEC_ISSUES = 2
EXIT_CODE_FAIL = 3
EXIT_CODE_WARN = 4
// Troubleshoot label constants
SupportBundleKey = "support-bundle-spec"
RedactorKey = "redactor-spec"
PreflightKey = "preflight.yaml" // Shouldn't this be "preflight-spec"?
// Troubleshoot spec constants
Troubleshootv1beta2Kind = "troubleshoot.sh/v1beta2"
)

290
pkg/loader/loader.go Normal file
View File

@@ -0,0 +1,290 @@
package loader
import (
"context"
"strings"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/internal/util"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/constants"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"github.com/replicatedhq/troubleshoot/pkg/types"
"gopkg.in/yaml.v2"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
)
var decoder runtime.Decoder
func init() {
// Allow serializing Secrets and ConfigMaps
_ = v1.AddToScheme(scheme.Scheme)
decoder = scheme.Codecs.UniversalDeserializer()
}
type parsedDoc struct {
Kind string `json:"kind" yaml:"kind"`
APIVersion string `json:"apiVersion" yaml:"apiVersion"`
Data map[string]any `json:"data" yaml:"data"`
StringData map[string]string `json:"stringData" yaml:"stringData"`
}
type LoadOptions struct {
RawSpecs []string
RawSpec string
}
// LoadSpecs takes sources to load specs from and returns a TroubleshootKinds object
// that contains all the parsed troubleshoot specs.
//
// The fetched specs need to be yaml documents. The documents can be a multidoc yaml
// separated by "---" which get split and parsed one at a time. This function will
// return an error if any of the documents are not valid yaml. If Secrets or ConfigMaps
// are found, they will be parsed and the support bundle, redactor or preflight spec
// will be extracted from them, else they will be ignored.
// Any other yaml documents will be ignored.
func LoadSpecs(ctx context.Context, opt LoadOptions) (*TroubleshootKinds, error) {
opt.RawSpecs = append(opt.RawSpecs, opt.RawSpec)
return loadFromStrings(opt.RawSpecs...)
}
type TroubleshootKinds struct {
AnalyzersV1Beta2 []troubleshootv1beta2.Analyzer
CollectorsV1Beta2 []troubleshootv1beta2.Collector
HostCollectorsV1Beta2 []troubleshootv1beta2.HostCollector
HostPreflightsV1Beta2 []troubleshootv1beta2.HostPreflight
PreflightsV1Beta2 []troubleshootv1beta2.Preflight
RedactorsV1Beta2 []troubleshootv1beta2.Redactor
RemoteCollectorsV1Beta2 []troubleshootv1beta2.RemoteCollector
SupportBundlesV1Beta2 []troubleshootv1beta2.SupportBundle
}
func (kinds *TroubleshootKinds) IsEmpty() bool {
return len(kinds.AnalyzersV1Beta2) == 0 &&
len(kinds.CollectorsV1Beta2) == 0 &&
len(kinds.HostCollectorsV1Beta2) == 0 &&
len(kinds.HostPreflightsV1Beta2) == 0 &&
len(kinds.PreflightsV1Beta2) == 0 &&
len(kinds.RedactorsV1Beta2) == 0 &&
len(kinds.RemoteCollectorsV1Beta2) == 0 &&
len(kinds.SupportBundlesV1Beta2) == 0
}
func NewTroubleshootKinds() *TroubleshootKinds {
return &TroubleshootKinds{}
}
// loadFromStrings accepts a list of strings (exploded) which should be yaml documents
func loadFromStrings(rawSpecs ...string) (*TroubleshootKinds, error) {
splitdocs := []string{}
multiRawDocs := []string{}
// 1. First split multidoc yaml documents.
for _, rawSpec := range rawSpecs {
multiRawDocs = append(multiRawDocs, strings.Split(rawSpec, "\n---\n")...)
}
// 2. Go through each document to see if it is a configmap, secret or troubleshoot kind
// For secrets and configmaps, extract support bundle, redactor or preflight specs
// For troubleshoot kinds, pass them through
for _, rawDoc := range multiRawDocs {
var parsed parsedDoc
err := yaml.Unmarshal([]byte(rawDoc), &parsed)
if err != nil {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrapf(err, "failed to parse yaml: '%s'", string(rawDoc)))
}
if isConfigMap(parsed) || isSecret(parsed) {
// Extract specs from configmap or secret
obj, _, err := decoder.Decode([]byte(rawDoc), nil, nil)
if err != nil {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES,
errors.Wrapf(err, "failed to decode raw spec: '%s'", string(rawDoc)),
)
}
// 3. Extract the raw troubleshoot specs
switch v := obj.(type) {
case *v1.ConfigMap:
specs, err := getSpecFromConfigMap(v)
if err != nil {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
}
splitdocs = append(splitdocs, specs...)
case *v1.Secret:
specs, err := getSpecFromSecret(v)
if err != nil {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
}
splitdocs = append(splitdocs, specs...)
default:
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Errorf("%T type is not a Secret or ConfigMap", v))
}
} else if parsed.APIVersion == constants.Troubleshootv1beta2Kind {
// If it's not a configmap or secret, just append it to the splitdocs
splitdocs = append(splitdocs, rawDoc)
} else {
klog.V(1).Infof("skip loading %q kind", parsed.Kind)
}
}
// 4. Then load the specs into the kinds struct
return loadFromSplitDocs(splitdocs)
}
func loadFromSplitDocs(splitdocs []string) (*TroubleshootKinds, error) {
kinds := NewTroubleshootKinds()
for _, doc := range splitdocs {
converted, err := docrewrite.ConvertToV1Beta2([]byte(doc))
if err != nil {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrapf(err, "failed to convert doc to troubleshoot.sh/v1beta2 kind: '%s'", doc))
}
obj, _, err := decoder.Decode([]byte(converted), nil, nil)
if err != nil {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrapf(err, "failed to decode '%s'", converted))
}
switch spec := obj.(type) {
case *troubleshootv1beta2.Analyzer:
kinds.AnalyzersV1Beta2 = append(kinds.AnalyzersV1Beta2, *spec)
case *troubleshootv1beta2.Collector:
kinds.CollectorsV1Beta2 = append(kinds.CollectorsV1Beta2, *spec)
case *troubleshootv1beta2.HostCollector:
kinds.HostCollectorsV1Beta2 = append(kinds.HostCollectorsV1Beta2, *spec)
case *troubleshootv1beta2.HostPreflight:
kinds.HostPreflightsV1Beta2 = append(kinds.HostPreflightsV1Beta2, *spec)
case *troubleshootv1beta2.Preflight:
kinds.PreflightsV1Beta2 = append(kinds.PreflightsV1Beta2, *spec)
case *troubleshootv1beta2.Redactor:
kinds.RedactorsV1Beta2 = append(kinds.RedactorsV1Beta2, *spec)
case *troubleshootv1beta2.RemoteCollector:
kinds.RemoteCollectorsV1Beta2 = append(kinds.RemoteCollectorsV1Beta2, *spec)
case *troubleshootv1beta2.SupportBundle:
kinds.SupportBundlesV1Beta2 = append(kinds.SupportBundlesV1Beta2, *spec)
default:
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Errorf("unknown troubleshoot kind %T", obj))
}
}
klog.V(1).Info("loaded troubleshoot specs successfully")
return kinds, nil
}
func isSecret(parsedDocHead parsedDoc) bool {
if parsedDocHead.Kind == "Secret" && parsedDocHead.APIVersion == "v1" {
return true
}
return false
}
func isConfigMap(parsedDocHead parsedDoc) bool {
if parsedDocHead.Kind == "ConfigMap" && parsedDocHead.APIVersion == "v1" {
return true
}
return false
}
// getSpecFromConfigMap extracts multiple troubleshoot specs from a secret
func getSpecFromConfigMap(cm *v1.ConfigMap) ([]string, error) {
specs := []string{}
str, ok := cm.Data[constants.SupportBundleKey]
if ok {
spec, err := validateYaml(str)
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
str, ok = cm.Data[constants.RedactorKey]
if ok {
spec, err := validateYaml(str)
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
str, ok = cm.Data[constants.PreflightKey]
if ok {
spec, err := validateYaml(str)
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
return specs, nil
}
// getSpecFromSecret extracts multiple troubleshoot specs from a secret
func getSpecFromSecret(secret *v1.Secret) ([]string, error) {
specs := []string{}
specBytes, ok := secret.Data[constants.SupportBundleKey]
if ok {
spec, err := validateYaml(string(specBytes))
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
specBytes, ok = secret.Data[constants.RedactorKey]
if ok {
spec, err := validateYaml(string(specBytes))
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
specBytes, ok = secret.Data[constants.PreflightKey]
if ok {
spec, err := validateYaml(string(specBytes))
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
str, ok := secret.StringData[constants.SupportBundleKey]
if ok {
spec, err := validateYaml(str)
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
str, ok = secret.StringData[constants.RedactorKey]
if ok {
spec, err := validateYaml(str)
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
str, ok = secret.StringData[constants.PreflightKey]
if ok {
spec, err := validateYaml(str)
if err != nil {
return nil, err
}
specs = append(specs, util.SplitYAML(spec)...)
}
return specs, nil
}
func validateYaml(raw string) (string, error) {
var parsed map[string]any
err := yaml.Unmarshal([]byte(raw), &parsed)
if err != nil {
return "", errors.Wrapf(err, "failed to parse yaml: '%s'", string(raw))
}
return raw, nil
}

408
pkg/loader/loader_test.go Normal file
View File

@@ -0,0 +1,408 @@
package loader
import (
"context"
"testing"
"github.com/replicatedhq/troubleshoot/internal/testutils"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestLoadingHelmTemplate_Succeeds(t *testing.T) {
s := testutils.GetTestFixture(t, "yamldocs/helm-template.yaml")
kinds, err := loadFromStrings(s)
require.NoError(t, err)
require.NotNil(t, kinds)
assert.Len(t, kinds.AnalyzersV1Beta2, 0)
assert.Len(t, kinds.CollectorsV1Beta2, 0)
assert.Len(t, kinds.HostCollectorsV1Beta2, 0)
assert.Len(t, kinds.HostPreflightsV1Beta2, 0)
assert.Len(t, kinds.RemoteCollectorsV1Beta2, 0)
require.Len(t, kinds.PreflightsV1Beta2, 2)
require.Len(t, kinds.RedactorsV1Beta2, 1)
require.Len(t, kinds.SupportBundlesV1Beta2, 2)
// Assert a few fields from the loaded troubleshoot specs
assert.Equal(t, "redactor-spec-1", kinds.RedactorsV1Beta2[0].ObjectMeta.Name)
assert.Equal(t, "REDACT SECOND TEXT PLEASE", kinds.RedactorsV1Beta2[0].Spec.Redactors[0].Removals.Values[0])
assert.Equal(t, "sb-spec-1", kinds.SupportBundlesV1Beta2[0].ObjectMeta.Name)
assert.Equal(t, "sb-spec-2", kinds.SupportBundlesV1Beta2[1].ObjectMeta.Name)
assert.Equal(t, "wg-easy", kinds.SupportBundlesV1Beta2[1].Spec.Collectors[0].Logs.CollectorName)
assert.Equal(t, "Node Count Check", kinds.PreflightsV1Beta2[0].Spec.Analyzers[0].NodeResources.CheckName)
assert.Len(t, kinds.PreflightsV1Beta2[0].Spec.Collectors, 0)
assert.Equal(t, true, kinds.PreflightsV1Beta2[1].Spec.Collectors[0].ClusterResources.IgnoreRBAC)
}
func TestLoadingRandomValidYaml_IgnoreDoc(t *testing.T) {
tests := []string{
"",
"---",
"configVersion: v1",
`
array:
- 1
- 2
`,
}
for _, ts := range tests {
ctx := context.Background()
kinds, err := LoadSpecs(ctx, LoadOptions{RawSpecs: []string{ts}})
assert.NoError(t, err)
assert.Equal(t, NewTroubleshootKinds(), kinds)
}
}
func TestLoadingInvalidYaml_ReturnError(t *testing.T) {
tests := []string{
"@",
"-",
`
array:- 1
- 2
`,
}
for _, ts := range tests {
t.Run(ts, func(t *testing.T) {
ctx := context.Background()
kinds, err := LoadSpecs(ctx, LoadOptions{RawSpec: ts})
assert.Error(t, err)
assert.Nil(t, kinds)
})
}
}
func TestLoadingMultidocsWithTroubleshootSpecs(t *testing.T) {
s := testutils.GetTestFixture(t, "yamldocs/multidoc-spec-1.yaml")
ctx := context.Background()
kinds, err := LoadSpecs(ctx, LoadOptions{RawSpec: s})
require.NoError(t, err)
require.NotNil(t, kinds)
assert.Equal(t, []troubleshootv1beta2.Analyzer{
{
TypeMeta: metav1.TypeMeta{
Kind: "Analyzer",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.AnalyzerSpec{
Analyzers: []*troubleshootv1beta2.Analyze{
{
ClusterVersion: &troubleshootv1beta2.ClusterVersion{},
},
},
HostAnalyzers: []*troubleshootv1beta2.HostAnalyze{
{
TCPLoadBalancer: &troubleshootv1beta2.TCPLoadBalancerAnalyze{},
},
},
},
},
}, kinds.AnalyzersV1Beta2)
assert.Equal(t, []troubleshootv1beta2.Collector{
{
TypeMeta: metav1.TypeMeta{
Kind: "Collector",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.CollectorSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
ClusterResources: &troubleshootv1beta2.ClusterResources{
CollectorMeta: troubleshootv1beta2.CollectorMeta{
CollectorName: "my-cluster-resources",
},
},
},
},
},
},
}, kinds.CollectorsV1Beta2)
assert.Equal(t, []troubleshootv1beta2.HostCollector{
{
TypeMeta: metav1.TypeMeta{
Kind: "HostCollector",
APIVersion: "troubleshoot.sh/v1beta2",
},
ObjectMeta: metav1.ObjectMeta{
Name: "my-host-collector",
},
Spec: troubleshootv1beta2.HostCollectorSpec{
Collectors: []*troubleshootv1beta2.HostCollect{
{
CPU: &troubleshootv1beta2.CPU{},
},
},
},
},
}, kinds.HostCollectorsV1Beta2)
assert.Equal(t, []troubleshootv1beta2.HostPreflight{
{
TypeMeta: metav1.TypeMeta{
Kind: "HostPreflight",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.HostPreflightSpec{
RemoteCollectors: []*troubleshootv1beta2.RemoteCollect{
{
Certificate: &troubleshootv1beta2.RemoteCertificate{
CertificatePath: "/etc/ssl/corp.crt",
KeyPath: "/etc/ssl/corp.key",
},
},
},
Analyzers: []*troubleshootv1beta2.HostAnalyze{
{
Certificate: &troubleshootv1beta2.CertificateAnalyze{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "Certificate key pair is valid",
},
},
},
},
},
},
},
},
}, kinds.HostPreflightsV1Beta2)
assert.Equal(t, []troubleshootv1beta2.Preflight{
{
TypeMeta: metav1.TypeMeta{
Kind: "Preflight",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.PreflightSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
Data: &troubleshootv1beta2.Data{
Data: "5",
},
},
},
Analyzers: []*troubleshootv1beta2.Analyze{
{
ClusterVersion: &troubleshootv1beta2.ClusterVersion{},
},
},
},
},
}, kinds.PreflightsV1Beta2)
assert.Equal(t, []troubleshootv1beta2.Redactor{
{
TypeMeta: metav1.TypeMeta{
Kind: "Redactor",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.RedactorSpec{
Redactors: []*troubleshootv1beta2.Redact{
{
Name: "replace password",
FileSelector: troubleshootv1beta2.FileSelector{
File: "data/my-password-dump",
},
Removals: troubleshootv1beta2.Removals{
Values: []string{"abc123"},
},
},
},
},
},
}, kinds.RedactorsV1Beta2)
assert.Equal(t, []troubleshootv1beta2.RemoteCollector{
{
TypeMeta: metav1.TypeMeta{
Kind: "RemoteCollector",
APIVersion: "troubleshoot.sh/v1beta2",
},
ObjectMeta: metav1.ObjectMeta{
Name: "certificate",
},
Spec: troubleshootv1beta2.RemoteCollectorSpec{
Collectors: []*troubleshootv1beta2.RemoteCollect{
{
CPU: &troubleshootv1beta2.RemoteCPU{},
},
},
},
},
}, kinds.RemoteCollectorsV1Beta2)
assert.Equal(t, []troubleshootv1beta2.SupportBundle{
{
TypeMeta: metav1.TypeMeta{
Kind: "SupportBundle",
APIVersion: "troubleshoot.sh/v1beta2",
},
ObjectMeta: metav1.ObjectMeta{
Name: "my-support-bundle",
},
Spec: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
Logs: &troubleshootv1beta2.Logs{
Name: "all-logs",
},
},
},
HostCollectors: []*troubleshootv1beta2.HostCollect{
{
HostOS: &troubleshootv1beta2.HostOS{},
},
},
Analyzers: []*troubleshootv1beta2.Analyze{
{
ClusterVersion: &troubleshootv1beta2.ClusterVersion{},
},
},
},
},
}, kinds.SupportBundlesV1Beta2)
}
func TestLoadingConfigMapWithMultipleSpecs_PreflightSupportBundleAndRedactorDataKeys(t *testing.T) {
s := testutils.GetTestFixture(t, "yamldocs/multidoc-spec-2.yaml")
kinds, err := loadFromStrings(s)
require.NoError(t, err)
require.NotNil(t, kinds)
assert.Equal(t, &TroubleshootKinds{
SupportBundlesV1Beta2: []troubleshootv1beta2.SupportBundle{
{
TypeMeta: metav1.TypeMeta{
Kind: "SupportBundle",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
Logs: &troubleshootv1beta2.Logs{
Name: "all-logs",
},
},
},
},
},
},
RedactorsV1Beta2: []troubleshootv1beta2.Redactor{
{
TypeMeta: metav1.TypeMeta{
Kind: "Redactor",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.RedactorSpec{
Redactors: []*troubleshootv1beta2.Redact{
{
Name: "redact-text-1",
Removals: troubleshootv1beta2.Removals{
Values: []string{"abc123"},
},
},
},
},
},
},
PreflightsV1Beta2: []troubleshootv1beta2.Preflight{
{
TypeMeta: metav1.TypeMeta{
Kind: "Preflight",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.PreflightSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
ClusterResources: &troubleshootv1beta2.ClusterResources{
IgnoreRBAC: true,
},
},
},
Analyzers: []*troubleshootv1beta2.Analyze{
{
ClusterVersion: &troubleshootv1beta2.ClusterVersion{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "Cluster is up to date",
},
},
},
},
},
},
},
},
},
}, kinds)
}
func TestLoadingConfigMapWithMultipleSpecs_SupportBundleMultidoc(t *testing.T) {
s := testutils.GetTestFixture(t, "yamldocs/multidoc-spec-3.yaml")
kinds, err := loadFromStrings(s)
require.NoError(t, err)
require.NotNil(t, kinds)
assert.Equal(t, &TroubleshootKinds{
SupportBundlesV1Beta2: []troubleshootv1beta2.SupportBundle{
{
TypeMeta: metav1.TypeMeta{
Kind: "SupportBundle",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
Logs: &troubleshootv1beta2.Logs{
Name: "all-logs",
},
},
},
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: "SupportBundle",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
ClusterResources: &troubleshootv1beta2.ClusterResources{},
},
},
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: "SupportBundle",
APIVersion: "troubleshoot.sh/v1beta2",
},
Spec: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
ClusterInfo: &troubleshootv1beta2.ClusterInfo{},
},
},
},
},
},
}, kinds)
}
func TestKindsIsEmpty(t *testing.T) {
assert.True(t, NewTroubleshootKinds().IsEmpty())
kinds := NewTroubleshootKinds()
kinds.AnalyzersV1Beta2 = append(kinds.AnalyzersV1Beta2, troubleshootv1beta2.Analyzer{})
assert.False(t, kinds.IsEmpty())
}

View File

@@ -9,7 +9,7 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
"github.com/replicatedhq/troubleshoot/pkg/version"
"oras.land/oras-go/pkg/auth"
dockerauth "oras.land/oras-go/pkg/auth/docker"

View File

@@ -7,7 +7,7 @@ import (
"github.com/pkg/errors"
ui "github.com/replicatedhq/termui/v3"
"github.com/replicatedhq/termui/v3/widgets"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
)

View File

@@ -7,7 +7,7 @@ import (
"time"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/replicatedhq/troubleshoot/pkg/convert"
)

View File

@@ -1,7 +1,7 @@
package preflight
import (
"encoding/base64"
"context"
"fmt"
"io"
"net/http"
@@ -10,41 +10,15 @@ import (
"strings"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/constants"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"github.com/replicatedhq/troubleshoot/pkg/loader"
"github.com/replicatedhq/troubleshoot/pkg/oci"
"github.com/replicatedhq/troubleshoot/pkg/specs"
"github.com/replicatedhq/troubleshoot/pkg/types"
"gopkg.in/yaml.v2"
"k8s.io/client-go/kubernetes/scheme"
)
type documentHead struct {
Kind string `yaml:"kind"`
Metadata documentMetadata `yaml:"metadata,omitempty"`
Data documentData `yaml:"data,omitempty"`
StringData documentStringData `yaml:"stringData,omitempty"`
}
type documentMetadata struct {
Labels documentMetadataLabels `yaml:"labels,omitempty"`
}
type documentMetadataLabels struct {
TroubleshootKind string `yaml:"troubleshoot.sh/kind,omitempty"`
}
type documentData struct {
PreflightYaml string `yaml:"preflight.yaml,omitempty"`
}
type documentStringData struct {
PreflightYaml string `yaml:"preflight.yaml,omitempty"`
}
type PreflightSpecs struct {
PreflightSpec *troubleshootv1beta2.Preflight
HostPreflightSpec *troubleshootv1beta2.HostPreflight
@@ -55,6 +29,7 @@ func (p *PreflightSpecs) Read(args []string) error {
var preflightContent []byte
var err error
// TODO: Earmarked for cleanup in favour of loader.LoadFromArgs(args []string)
for _, v := range args {
if strings.HasPrefix(v, "secret/") {
// format secret/namespace-name/secret-name
@@ -126,70 +101,24 @@ func (p *PreflightSpecs) Read(args []string) error {
}
}
multidocs := strings.Split(string(preflightContent), "\n---\n")
ctx := context.Background()
kinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{
RawSpec: string(preflightContent),
})
if err != nil {
return err
}
for _, doc := range multidocs {
var parsedDocHead documentHead
err := yaml.Unmarshal([]byte(doc), &parsedDocHead)
if err != nil {
return types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrap(err, "failed to parse yaml"))
for _, v := range kinds.PreflightsV1Beta2 {
if v.Spec.UploadResultsTo == "" {
p.PreflightSpec = ConcatPreflightSpec(p.PreflightSpec, &v)
} else {
p.UploadResultSpecs = append(p.UploadResultSpecs, &v)
}
}
// We're going to look for either of "kind: Preflight" OR "kind: Secret" with the label "troubleshoot.sh/kind: preflight"
if parsedDocHead.Kind != "Preflight" && parsedDocHead.Kind != "Secret" {
continue
}
if parsedDocHead.Kind == "Secret" {
if parsedDocHead.Metadata.Labels.TroubleshootKind == "preflight" {
secretSpecDoc := ""
// In a Secret, we need to get the document out of the data.`preflight.yaml` or stringData.`preflight.yaml` (stringData takes precedence)
if len(parsedDocHead.Data.PreflightYaml) > 0 {
b64DecPreflightYaml, err := base64.StdEncoding.DecodeString(parsedDocHead.Data.PreflightYaml)
if err != nil {
return types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrap(err, "failed to base64 decode preflight secret data"))
}
secretSpecDoc = strings.TrimSpace(string(b64DecPreflightYaml))
}
// Do stringData second, if found overwrite data (as per K8s docs)
if len(parsedDocHead.StringData.PreflightYaml) > 0 {
secretSpecDoc = parsedDocHead.StringData.PreflightYaml
}
//
if len(secretSpecDoc) > 0 {
doc = secretSpecDoc
} else {
return types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrap(err, "secret spec with preflight label found, but no preflight stringData or data?"))
}
} else {
// Not a preflight spec, skip
continue
}
}
preflightContent, err = docrewrite.ConvertToV1Beta2([]byte(doc))
if err != nil {
return types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrap(err, "failed to convert to v1beta2"))
}
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(preflightContent), nil, nil)
if err != nil {
return types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrapf(err, "failed to parse %s", v))
}
if spec, ok := obj.(*troubleshootv1beta2.Preflight); ok {
if spec.Spec.UploadResultsTo == "" {
p.PreflightSpec = ConcatPreflightSpec(p.PreflightSpec, spec)
} else {
p.UploadResultSpecs = append(p.UploadResultSpecs, spec)
}
} else if spec, ok := obj.(*troubleshootv1beta2.HostPreflight); ok {
p.HostPreflightSpec = ConcatHostPreflightSpec(p.HostPreflightSpec, spec)
}
for _, v := range kinds.HostPreflightsV1Beta2 {
p.HostPreflightSpec = ConcatHostPreflightSpec(p.HostPreflightSpec, &v)
}
}

View File

@@ -29,6 +29,7 @@ type PreflightSpecsReadTest struct {
wantUploadResultSpecs []*troubleshootv1beta2.Preflight
}
// TODO: Simplify tests and rely on the loader tests
func TestPreflightSpecsRead(t *testing.T) {
// NOTE: don't use t.Parallel(), these tests manipulate os.Stdin
@@ -46,7 +47,7 @@ func TestPreflightSpecsRead(t *testing.T) {
Spec: troubleshootv1beta2.PreflightSpec{
UploadResultsTo: "",
Collectors: []*troubleshootv1beta2.Collect{
&troubleshootv1beta2.Collect{
{
Data: &troubleshootv1beta2.Data{
CollectorMeta: troubleshootv1beta2.CollectorMeta{
CollectorName: "",
@@ -72,7 +73,7 @@ func TestPreflightSpecsRead(t *testing.T) {
},
RemoteCollectors: []*troubleshootv1beta2.RemoteCollect(nil),
Analyzers: []*troubleshootv1beta2.Analyze{
&troubleshootv1beta2.Analyze{
{
JsonCompare: &troubleshootv1beta2.JsonCompare{
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
CheckName: "Compare JSON Example",
@@ -83,13 +84,13 @@ func TestPreflightSpecsRead(t *testing.T) {
Value: `123
`,
Outcomes: []*troubleshootv1beta2.Outcome{
&troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
When: "false",
Message: "The collected data does not match the value.",
},
},
&troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
When: "true",
Message: "The collected data matches the value.",
@@ -131,19 +132,19 @@ func TestPreflightSpecsRead(t *testing.T) {
UploadResultsTo: "",
RemoteCollectors: []*troubleshootv1beta2.RemoteCollect(nil),
Analyzers: []*troubleshootv1beta2.Analyze{
&troubleshootv1beta2.Analyze{
{
NodeResources: &troubleshootv1beta2.NodeResources{
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
CheckName: "Node Count Check",
},
Outcomes: []*troubleshootv1beta2.Outcome{
&troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
When: "count() < 3",
Message: "The cluster needs a minimum of 3 nodes.",
},
},
&troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "There are not enough nodes to run this application (3 or more)",
},
@@ -151,24 +152,24 @@ func TestPreflightSpecsRead(t *testing.T) {
},
},
},
&troubleshootv1beta2.Analyze{
{
ClusterVersion: &troubleshootv1beta2.ClusterVersion{
Outcomes: []*troubleshootv1beta2.Outcome{
&troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
When: "< 1.16.0",
Message: "The application requires at least Kubernetes 1.16.0, and recommends 1.18.0.",
URI: "https://kubernetes.io",
},
},
&troubleshootv1beta2.Outcome{
{
Warn: &troubleshootv1beta2.SingleOutcome{
When: "< 1.18.0",
Message: "Your cluster meets the minimum version of Kubernetes, but we recommend you update to 1.18.0 or later.",
URI: "https://kubernetes.io",
},
},
&troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "Your cluster meets the recommended and required versions of Kubernetes.",
},

View File

@@ -11,7 +11,6 @@ import (
"github.com/fatih/color"
"github.com/pkg/errors"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/constants"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
@@ -122,12 +121,10 @@ func RunPreflights(interactive bool, output string, format string, args []string
}
}
if uploadAnalyzeResultsMap != nil {
for k, v := range uploadAnalyzeResultsMap {
err := uploadResults(k, v)
if err != nil {
progressCh <- err
}
for k, v := range uploadAnalyzeResultsMap {
err := uploadResults(k, v)
if err != nil {
progressCh <- err
}
}
@@ -161,7 +158,7 @@ func RunPreflights(interactive bool, output string, format string, args []string
// If all checks passed: 0
// If 1 or more checks failed: 3
// If no checks failed, but 1 or more warn: 4
func checkOutcomesToExitCode(analyzeResults []*analyzerunner.AnalyzeResult) int {
func checkOutcomesToExitCode(analyzeResults []*analyzer.AnalyzeResult) int {
// Assume pass until they don't
exitCode := 0

View File

@@ -1,6 +1,12 @@
package specs
import "github.com/replicatedhq/troubleshoot/pkg/constants"
const (
SupportBundleKey = "support-bundle-spec"
RedactorKey = "redactor-spec"
// Preserved for backwards compatibility
// Deprecated: Use constants.SupportBundleKey instead
SupportBundleKey = constants.SupportBundleKey
// Deprecated: Use constants.RedactorKey instead
RedactorKey = constants.RedactorKey
)

View File

@@ -9,10 +9,9 @@ import (
"strings"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"github.com/replicatedhq/troubleshoot/pkg/httputil"
"github.com/replicatedhq/troubleshoot/pkg/oci"
@@ -43,7 +42,6 @@ func ParseSupportBundle(doc []byte, followURI bool) (*troubleshootv1beta2.Suppor
return nil, errors.Wrap(err, "failed to convert to v1beta2")
}
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode(doc, nil, nil)

403
testdata/yamldocs/helm-template.yaml vendored Normal file
View File

@@ -0,0 +1,403 @@
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: Secret
metadata:
name: sb-spec-1-secret
labels:
troubleshoot.io/kind: support-bundle
stringData:
support-bundle-spec: |-
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: sb-spec-1
spec:
collectors:
- clusterResources: {}
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: sb-spec-2-configmap
labels:
troubleshoot.io/kind: support-bundle
data:
support-bundle-spec: |-
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: sb-spec-2
spec:
collectors:
- logs:
collectorName: wg-easy
---
# Source: wg-easy/templates/replicated-library.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: release-name-wg-easy-config
labels:
app.kubernetes.io/instance: release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: wg-easy
app.kubernetes.io/version: "7"
helm.sh/chart: wg-easy-0.1.2
annotations:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: Service
metadata:
name: release-name-wg-easy-vpn
labels:
app.kubernetes.io/instance: release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: wg-easy
app.kubernetes.io/version: "7"
helm.sh/chart: wg-easy-0.1.2
annotations:
spec:
type: LoadBalancer
ports:
- port: 51820
targetPort: 51820
protocol: UDP
name: udp
selector:
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: redactor-spec-1-configmap
labels:
troubleshoot.io/kind: support-bundle
data:
redactor-spec: |
apiVersion: troubleshoot.sh/v1beta2
kind: Redactor
metadata:
name: redactor-spec-1
spec:
redactors:
- name: redact-text-1
removals:
values:
- REDACT SECOND TEXT PLEASE
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: Service
metadata:
name: release-name-wg-easy-web
labels:
app.kubernetes.io/instance: release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: wg-easy
app.kubernetes.io/version: "7"
helm.sh/chart: wg-easy-0.1.2
annotations:
spec:
type: ClusterIP
ipFamilyPolicy: SingleStack
ports:
- port: 51821
targetPort: 51821
protocol: TCP
name: http
selector:
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: release-name-wg-easy-wg-easy
labels:
app.kubernetes.io/instance: release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: wg-easy
app.kubernetes.io/version: "7"
helm.sh/chart: wg-easy-0.1.2
spec:
revisionHistoryLimit:
replicas: 1
strategy:
type: RollingUpdate
selector:
matchLabels:
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
template:
metadata:
labels:
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
spec:
serviceAccountName:
automountServiceAccountToken:
dnsPolicy: ClusterFirst
enableServiceLinks:
containers:
- name: wg-container
image: "weejewel/wg-easy:7"
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_ADMIN
drop: []
env:
- name: WG_HOST
value: vpn.example.com
ports:
- containerPort: 51821
protocol: TCP
- containerPort: 51820
protocol: UDP
volumeMounts:
- mountPath: /etc/wireguard
name: config
resources:
requests:
cpu: 50m
memory: 50Mi
livenessProbe:
failureThreshold: 5
initialDelaySeconds: 0
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 51821
terminationGracePeriodSeconds: 30
timeoutSeconds: 5
readinessProbe:
failureThreshold: 5
initialDelaySeconds: 0
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 51821
timeoutSeconds: 1
volumes:
- name: config
persistentVolumeClaim:
claimName: release-name-wg-easy-config
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: Secret
metadata:
annotations:
"helm.sh/hook": pre-install, pre-upgrade
"helm.sh/hook-weight": "-6"
"helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed
labels:
app.kubernetes.io/managed-by: "Helm"
app.kubernetes.io/instance: "release-name"
app.kubernetes.io/version: 0.62.1
helm.sh/chart: "troubleshoot-0.1.0"
troubleshoot.io/kind: preflight
name: "release-name-preflight-config"
data:
preflight.yaml: CmFwaVZlcnNpb246IHRyb3VibGVzaG9vdC5zaC92MWJldGEyCmtpbmQ6IFByZWZsaWdodAptZXRhZGF0YToKICBuYW1lOiBwcmVmbGlnaHQtc2FtcGxlCnNwZWM6CiAgCiAgYW5hbHl6ZXJzOgogICAgLSBub2RlUmVzb3VyY2VzOgogICAgICAgIGNoZWNrTmFtZTogTm9kZSBDb3VudCBDaGVjawogICAgICAgIG91dGNvbWVzOgogICAgICAgICAgLSBmYWlsOgogICAgICAgICAgICAgIHdoZW46ICdjb3VudCgpIDwgMycKICAgICAgICAgICAgICBtZXNzYWdlOiBUaGUgY2x1c3RlciBuZWVkcyBhIG1pbmltdW0gb2YgMyBub2Rlcy4KICAgICAgICAgIC0gcGFzczoKICAgICAgICAgICAgICBtZXNzYWdlOiBUaGVyZSBhcmUgbm90IGVub3VnaCBub2RlcyB0byBydW4gdGhpcyBhcHBsaWNhdGlvbiAoMyBvciBtb3JlKQogICAgLSBjbHVzdGVyVmVyc2lvbjoKICAgICAgICBvdXRjb21lczoKICAgICAgICAgIC0gZmFpbDoKICAgICAgICAgICAgICB3aGVuOiAiPCAxLjE2LjAiCiAgICAgICAgICAgICAgbWVzc2FnZTogVGhlIGFwcGxpY2F0aW9uIHJlcXVpcmVzIGF0IGxlYXN0IEt1YmVybmV0ZXMgMS4xNi4wLCBhbmQgcmVjb21tZW5kcyAxLjE4LjAuCiAgICAgICAgICAgICAgdXJpOiBodHRwczovL2t1YmVybmV0ZXMuaW8KICAgICAgICAgIC0gd2FybjoKICAgICAgICAgICAgICB3aGVuOiAiPCAxLjE4LjAiCiAgICAgICAgICAgICAgbWVzc2FnZTogWW91ciBjbHVzdGVyIG1lZXRzIHRoZSBtaW5pbXVtIHZlcnNpb24gb2YgS3ViZXJuZXRlcywgYnV0IHdlIHJlY29tbWVuZCB5b3UgdXBkYXRlIHRvIDEuMTguMCBvciBsYXRlci4KICAgICAgICAgICAgICB1cmk6IGh0dHBzOi8va3ViZXJuZXRlcy5pbwogICAgICAgICAgLSBwYXNzOgogICAgICAgICAgICAgIG1lc3NhZ2U6IFlvdXIgY2x1c3RlciBtZWV0cyB0aGUgcmVjb21tZW5kZWQgYW5kIHJlcXVpcmVkIHZlcnNpb25zIG9mIEt1YmVybmV0ZXMuCiAgICA=
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: release-name-preflight-wg-preflights
labels:
helm.sh/chart: wg-easy-0.1.2
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "7"
app.kubernetes.io/managed-by: Helm
troubleshoot.io/kind: preflight
annotations:
"helm.sh/hook": pre-install, pre-upgrade
"helm.sh/hook-weight": "-6"
"helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed
secrets:
- name: release-name-wg-easy-preflight-wg-preflights
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: Secret
metadata:
name: release-name-wg-easy-preflight-wg-preflights
labels:
helm.sh/chart: wg-easy-0.1.2
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "7"
app.kubernetes.io/managed-by: Helm
troubleshoot.io/kind: preflight
annotations:
"helm.sh/hook": pre-install, pre-upgrade
"helm.sh/hook-weight": "-6"
"helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed
stringData:
preflight.yaml: |-
apiVersion: troubleshoot.sh/v1beta2
kind: Preflight
metadata:
name: preflight-1
spec:
collectors:
- clusterResources:
ignoreRBAC: true
analyzers:
- clusterVersion:
outcomes:
- pass:
message: Your cluster meets the recommended and required versions of Kubernetes.
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: release-name-preflight-wg-preflights
labels:
helm.sh/chart: wg-easy-0.1.2
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "7"
app.kubernetes.io/managed-by: Helm
troubleshoot.io/kind: preflight
annotations:
"helm.sh/hook": pre-install, pre-upgrade
"helm.sh/hook-weight": "-6"
"helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed
rules:
- apiGroups:
- ""
resources:
- "namespaces"
verbs:
- "get"
- "watch"
- "list"
- apiGroups:
- ""
resources:
- "nodes"
verbs:
- "get"
- "watch"
- "list"
- apiGroups:
- ""
resources:
- "pods"
verbs:
- "get"
- "watch"
- "list"
- "create"
- apiGroups:
- "apiextensions.k8s.io"
resources:
- "customresourcedefinitions"
verbs:
- "get"
- "watch"
- "list"
- apiGroups:
- "storage.k8s.io"
resources:
- "storageclasses"
verbs:
- "get"
- "watch"
- "list"
- apiGroups:
- ""
resources:
- "pods/log"
verbs:
- "get"
- "list"
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: Secret
metadata:
name: "some-secret"
stringData:
somesecret: gibberish text
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: release-name-preflight-wg-preflights
labels:
helm.sh/chart: wg-easy-0.1.2
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "7"
app.kubernetes.io/managed-by: Helm
troubleshoot.io/kind: preflight
annotations:
"helm.sh/hook": pre-install, pre-upgrade
"helm.sh/hook-weight": "-6"
"helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed
subjects:
- kind: ServiceAccount
name: release-name-preflight-wg-preflights
namespace: default
roleRef:
kind: ClusterRole
name: release-name-preflight-wg-preflights
apiGroup: rbac.authorization.k8s.io
---
# Source: wg-easy/templates/replicated-library.yaml
apiVersion: v1
kind: Pod
metadata:
name: release-name-preflight-check
labels:
helm.sh/chart: wg-easy-0.1.2
app.kubernetes.io/name: wg-easy
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "7"
app.kubernetes.io/managed-by: Helm
troubleshoot.io/kind: preflight
annotations:
"helm.sh/hook": pre-install, pre-upgrade
"helm.sh/show-output": "true"
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed
"helm.sh/hook-output-log-policy": hook-failed, hook-succeeded
spec:
serviceAccountName: release-name-preflight-wg-preflights
restartPolicy: Never
volumes:
- name: preflights
secret:
secretName: release-name-wg-easy-preflight-wg-preflights
containers:
- name: pre-install-job
image: replicated/preflight:latest
command:
- "preflight"
- "--interactive=false"
- "/preflights/preflight.yaml"
volumeMounts:
- name: preflights
mountPath: /preflights

77
testdata/yamldocs/multidoc-spec-1.yaml vendored Normal file
View File

@@ -0,0 +1,77 @@
---
apiVersion: troubleshoot.sh/v1beta2
kind: Analyzer
spec:
analyzers:
- clusterVersion: {}
hostAnalyzers:
- tcpLoadBalancer: {}
---
apiVersion: troubleshoot.sh/v1beta2
kind: Collector
spec:
collectors:
- clusterResources:
collectorName: my-cluster-resources
---
apiVersion: troubleshoot.sh/v1beta2
kind: HostCollector
metadata:
name: my-host-collector
spec:
collectors:
- cpu: {}
---
apiVersion: troubleshoot.sh/v1beta2
kind: HostPreflight
spec:
remoteCollectors:
- certificate:
certificatePath: /etc/ssl/corp.crt
keyPath: /etc/ssl/corp.key
analyzers:
- certificate:
outcomes:
- pass:
message: Certificate key pair is valid
---
apiVersion: troubleshoot.sh/v1beta2
kind: Preflight
spec:
collectors:
- data:
data: "5"
analyzers:
- clusterVersion: {}
---
apiVersion: troubleshoot.sh/v1beta2
kind: Redactor
spec:
redactors:
- name: replace password # names are not used internally, but are useful for recordkeeping
fileSelector:
file: data/my-password-dump # this targets a single file
removals:
values:
- abc123 # this is a very good password, and I don't want it to be exposed
---
apiVersion: troubleshoot.sh/v1beta2
kind: RemoteCollector
metadata:
name: certificate
spec:
collectors:
- cpu: {}
---
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: my-support-bundle
spec:
collectors:
- logs:
name: all-logs
hostCollectors:
- hostOS: {}
analyzers:
- clusterVersion: {}

35
testdata/yamldocs/multidoc-spec-2.yaml vendored Normal file
View File

@@ -0,0 +1,35 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: multi-spec
labels:
troubleshoot.io/kind: support-bundle
data:
support-bundle-spec: |-
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
collectors:
- logs:
name: all-logs
redactor-spec: |
apiVersion: troubleshoot.sh/v1beta2
kind: Redactor
spec:
redactors:
- name: redact-text-1
removals:
values:
- abc123
preflight.yaml: |-
apiVersion: troubleshoot.sh/v1beta2
kind: Preflight
spec:
collectors:
- clusterResources:
ignoreRBAC: true
analyzers:
- clusterVersion:
outcomes:
- pass:
message: Cluster is up to date

26
testdata/yamldocs/multidoc-spec-3.yaml vendored Normal file
View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: sb-spec
labels:
troubleshoot.io/kind: support-bundle
data:
support-bundle-spec: |-
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
collectors:
- logs:
name: all-logs
---
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
collectors:
- clusterResources: {}
---
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
collectors:
- clusterInfo: {}