Skip to content

Commit

Permalink
Refactor DiagnosticBundle to explicitly use a factory (aws#414)
Browse files Browse the repository at this point in the history
* use factory creational pattern for diagnostic bundle generation

* move consts and manifest to proper file

* update mocks
  • Loading branch information
danbudris authored Oct 18, 2021
1 parent 80a0a21 commit b43ccb5
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 138 deletions.
14 changes: 4 additions & 10 deletions cmd/eksctl-anywhere/cmd/generatebundleconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ func (gsbo *generateSupportBundleOptions) validateCmdInput() error {
func (gsbo *generateSupportBundleOptions) generateBundleConfig(ctx context.Context) (*diagnostics.EksaDiagnosticBundle, error) {
f := gsbo.fileName
if f == "" {
return diagnostics.NewDiagnosticBundleDefault(diagnostics.NewAnalyzerFactory(), diagnostics.NewDefaultCollectorFactory()), nil
factory := diagnostics.NewFactory(diagnostics.EksaDiagnosticBundleFactoryOpts{})
return factory.NewDiagnosticBundleDefault(), nil
}

clusterSpec, err := cluster.NewSpec(f, version.Get())
Expand All @@ -89,20 +90,13 @@ func (gsbo *generateSupportBundleOptions) generateBundleConfig(ctx context.Conte

deps, err := dependencies.ForSpec(ctx, clusterSpec).
WithProvider(f, clusterSpec.Cluster, cc.skipIpCheck).
WithAnalyzerFactory().
WithCollectorFactory().
WithWriter().
WithDiagnosticBundleFactory().
Build()
if err != nil {
return nil, err
}

opts := diagnostics.EksaDiagnosticBundleOpts{
AnalyzerFactory: deps.AnalyzerFactory,
CollectorFactory: deps.CollectorFactory,
Writer: deps.Writer,
}
return diagnostics.NewDiagnosticBundleFromSpec(clusterSpec, deps.Provider, gsbo.kubeConfig(clusterSpec.Name), opts)
return deps.DignosticCollectorFactory.NewDiagnosticBundleFromSpec(clusterSpec, deps.Provider, gsbo.kubeConfig(clusterSpec.Name))
}

func (gsbo *generateSupportBundleOptions) kubeConfig(clusterName string) string {
Expand Down
16 changes: 2 additions & 14 deletions cmd/eksctl-anywhere/cmd/supportbundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,25 +94,13 @@ func (csbo *createSupportBundleOptions) createBundle(ctx context.Context, since,

deps, err := dependencies.ForSpec(ctx, clusterSpec).
WithProvider(csbo.fileName, clusterSpec.Cluster, cc.skipIpCheck).
WithKubectl().
WithAnalyzerFactory().
WithCollectorFactory().
WithWriter().
WithTroubleshoot().
WithDiagnosticBundleFactory().
Build()
if err != nil {
return err
}

opts := diagnostics.EksaDiagnosticBundleOpts{
AnalyzerFactory: deps.AnalyzerFactory,
CollectorFactory: deps.CollectorFactory,
Client: deps.Troubleshoot,
Writer: deps.Writer,
Kubectl: deps.Kubectl,
}

supportBundle, err := diagnostics.NewDiagnosticBundle(clusterSpec, deps.Provider, csbo.kubeConfig(clusterSpec.Name), bundleConfig, opts)
supportBundle, err := deps.DignosticCollectorFactory.NewDiagnosticBundle(clusterSpec, deps.Provider, csbo.kubeConfig(clusterSpec.Name), bundleConfig)
if err != nil {
return fmt.Errorf("failed to parse collector: %v", err)
}
Expand Down
59 changes: 41 additions & 18 deletions pkg/dependencies/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,24 @@ import (
)

type Dependencies struct {
Provider providers.Provider
ClusterAwsCli *executables.Clusterawsadm
DockerClient *executables.Docker
Kubectl *executables.Kubectl
Govc *executables.Govc
Writer filewriter.FileWriter
Kind *executables.Kind
Clusterctl *executables.Clusterctl
Flux *executables.Flux
Troubleshoot *executables.Troubleshoot
Networking clustermanager.Networking
ClusterManager *clustermanager.ClusterManager
Bootstrapper *bootstrapper.Bootstrapper
FluxAddonClient *addonclients.FluxAddonClient
AnalyzerFactory diagnostics.AnalyzerFactory
CollectorFactory diagnostics.CollectorFactory
CAPIUpgrader *clusterapi.Upgrader
Provider providers.Provider
ClusterAwsCli *executables.Clusterawsadm
DockerClient *executables.Docker
Kubectl *executables.Kubectl
Govc *executables.Govc
Writer filewriter.FileWriter
Kind *executables.Kind
Clusterctl *executables.Clusterctl
Flux *executables.Flux
Troubleshoot *executables.Troubleshoot
Networking clustermanager.Networking
ClusterManager *clustermanager.ClusterManager
Bootstrapper *bootstrapper.Bootstrapper
FluxAddonClient *addonclients.FluxAddonClient
AnalyzerFactory diagnostics.AnalyzerFactory
CollectorFactory diagnostics.CollectorFactory
DignosticCollectorFactory diagnostics.DiagnosticBundleFactory
CAPIUpgrader *clusterapi.Upgrader
}

func ForSpec(ctx context.Context, clusterSpec *cluster.Spec) *Factory {
Expand Down Expand Up @@ -356,6 +357,28 @@ func (f *Factory) WithFluxAddonClient(ctx context.Context, clusterConfig *v1alph
return f
}

func (f *Factory) WithDiagnosticBundleFactory() *Factory {
f.WithWriter().WithTroubleshoot().WithCollectorFactory().WithAnalyzerFactory().WithKubectl()
f.buildSteps = append(f.buildSteps, func() error {
if f.dependencies.DignosticCollectorFactory != nil {
return nil
}

opts := diagnostics.EksaDiagnosticBundleFactoryOpts{
AnalyzerFactory: f.dependencies.AnalyzerFactory,
Client: f.dependencies.Troubleshoot,
CollectorFactory: f.dependencies.CollectorFactory,
Kubectl: f.dependencies.Kubectl,
Writer: f.dependencies.Writer,
}

f.dependencies.DignosticCollectorFactory = diagnostics.NewFactory(opts)
return nil
})

return f
}

func (f *Factory) WithAnalyzerFactory() *Factory {
f.buildSteps = append(f.buildSteps, func() error {
if f.dependencies.AnalyzerFactory != nil {
Expand All @@ -381,7 +404,7 @@ func (f *Factory) WithCollectorFactory() *Factory {
}

if f.diagnosticCollectorImage == "" {
return errors.New("diagnostic collector image is required to build CollectorFactory")
return errors.New("diagnostic collector image is required to build collectorFactory")
}

f.dependencies.CollectorFactory = diagnostics.NewCollectorFactory(f.diagnosticCollectorImage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"

"github.com/aws/eks-anywhere/pkg/api/v1alpha1"
Expand All @@ -30,14 +29,6 @@ const (
backOffPeriod = 5 * time.Second
)

type EksaDiagnosticBundleOpts struct {
AnalyzerFactory AnalyzerFactory
Client BundleClient
CollectorFactory CollectorFactory
Kubectl *executables.Kubectl
Writer filewriter.FileWriter
}

type EksaDiagnosticBundle struct {
bundle *supportBundle
bundlePath string
Expand All @@ -51,83 +42,6 @@ type EksaDiagnosticBundle struct {
writer filewriter.FileWriter
}

func NewDiagnosticBundle(spec *cluster.Spec, provider providers.Provider, kubeconfig string, bundlePath string, opts EksaDiagnosticBundleOpts) (*EksaDiagnosticBundle, error) {
if bundlePath == "" && spec != nil {
return NewDiagnosticBundleFromSpec(spec, provider, kubeconfig, opts)
}
return NewDiagnosticBundleCustom(kubeconfig, bundlePath, opts), nil
}

func NewDiagnosticBundleFromSpec(spec *cluster.Spec, provider providers.Provider, kubeconfig string, opts EksaDiagnosticBundleOpts) (*EksaDiagnosticBundle, error) {
b := &EksaDiagnosticBundle{
bundle: &supportBundle{
TypeMeta: metav1.TypeMeta{
Kind: "SupportBundle",
APIVersion: troubleshootApiVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%sBundle", spec.Name),
},
Spec: supportBundleSpec{},
},
analyzerFactory: opts.AnalyzerFactory,
collectorFactory: opts.CollectorFactory,
client: opts.Client,
clusterSpec: spec,
kubeconfig: kubeconfig,
kubectl: opts.Kubectl,
retrier: retrier.NewWithMaxRetries(maxRetries, backOffPeriod),
writer: opts.Writer,
}

b = b.
WithGitOpsConfig(spec.GitOpsConfig).
WithOidcConfig(spec.OIDCConfig).
WithExternalEtcd(spec.Spec.ExternalEtcdConfiguration).
WithDatacenterConfig(spec.Spec.DatacenterRef).
WithMachineConfigs(provider.MachineConfigs()).
WithDefaultAnalyzers().
WithDefaultCollectors().
WithLogTextAnalyzers()

err := b.WriteBundleConfig()
if err != nil {
return nil, fmt.Errorf("error writing bundle config: %v", err)
}

return b, nil
}

func NewDiagnosticBundleDefault(af AnalyzerFactory, cf CollectorFactory) *EksaDiagnosticBundle {
b := &EksaDiagnosticBundle{
bundle: &supportBundle{
TypeMeta: metav1.TypeMeta{
Kind: "SupportBundle",
APIVersion: troubleshootApiVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: "defaultBundle",
},
Spec: supportBundleSpec{},
},
analyzerFactory: af,
collectorFactory: cf,
}
return b.WithDefaultAnalyzers().WithDefaultCollectors()
}

func NewDiagnosticBundleCustom(kubeconfig string, bundlePath string, opts EksaDiagnosticBundleOpts) *EksaDiagnosticBundle {
return &EksaDiagnosticBundle{
bundlePath: bundlePath,
analyzerFactory: opts.AnalyzerFactory,
collectorFactory: opts.CollectorFactory,
client: opts.Client,
kubeconfig: kubeconfig,
kubectl: opts.Kubectl,
retrier: retrier.NewWithMaxRetries(maxRetries, backOffPeriod),
}
}

func (e *EksaDiagnosticBundle) CollectAndAnalyze(ctx context.Context, sinceTimeValue *time.Time) error {
e.createDiagnosticNamespaceAndRoles(ctx)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,14 @@ func TestGenerateBundleConfigWithExternalEtcd(t *testing.T) {
w := givenWriter(t)
w.EXPECT().Write(gomock.Any(), gomock.Any())

opts := diagnostics.EksaDiagnosticBundleOpts{
opts := diagnostics.EksaDiagnosticBundleFactoryOpts{
AnalyzerFactory: a,
CollectorFactory: c,
Writer: w,
}

_, _ = diagnostics.NewDiagnosticBundleFromSpec(spec, p, "", opts)
f := diagnostics.NewFactory(opts)
_, _ = f.NewDiagnosticBundleFromSpec(spec, p, "")
})
}

Expand Down Expand Up @@ -166,13 +167,14 @@ func TestGenerateBundleConfigWithOidc(t *testing.T) {
c.EXPECT().DefaultCollectors().Return(nil)
c.EXPECT().EksaHostCollectors(gomock.Any()).Return(nil)

opts := diagnostics.EksaDiagnosticBundleOpts{
opts := diagnostics.EksaDiagnosticBundleFactoryOpts{
AnalyzerFactory: a,
CollectorFactory: c,
Writer: w,
}

_, _ = diagnostics.NewDiagnosticBundleFromSpec(spec, p, "", opts)
f := diagnostics.NewFactory(opts)
_, _ = f.NewDiagnosticBundleFromSpec(spec, p, "")
})
}

Expand Down Expand Up @@ -215,13 +217,14 @@ func TestGenerateBundleConfigWithGitOps(t *testing.T) {
c.EXPECT().DefaultCollectors().Return(nil)
c.EXPECT().EksaHostCollectors(gomock.Any()).Return(nil)

opts := diagnostics.EksaDiagnosticBundleOpts{
opts := diagnostics.EksaDiagnosticBundleFactoryOpts{
AnalyzerFactory: a,
CollectorFactory: c,
Writer: w,
}

_, _ = diagnostics.NewDiagnosticBundleFromSpec(spec, p, "", opts)
f := diagnostics.NewFactory(opts)
_, _ = f.NewDiagnosticBundleFromSpec(spec, p, "")
})
}

Expand All @@ -233,13 +236,23 @@ func TestGenerateDefaultBundle(t *testing.T) {
c := givenMockCollectorsFactory(t)
c.EXPECT().DefaultCollectors().Return(nil)

_ = diagnostics.NewDiagnosticBundleDefault(a, c)
w := givenWriter(t)

opts := diagnostics.EksaDiagnosticBundleFactoryOpts{
AnalyzerFactory: a,
CollectorFactory: c,
Writer: w,
}

f := diagnostics.NewFactory(opts)
_ = f.NewDiagnosticBundleDefault()
})
}

func TestGenerateCustomBundle(t *testing.T) {
t.Run(t.Name(), func(t *testing.T) {
_ = diagnostics.NewDiagnosticBundleCustom("", "", getOpts(t))
f := diagnostics.NewFactory(getOpts(t))
_ = f.NewDiagnosticBundleCustom("", "")
})
}

Expand All @@ -253,8 +266,8 @@ func givenMockCollectorsFactory(t *testing.T) *supportMocks.MockCollectorFactory
return supportMocks.NewMockCollectorFactory(ctrl)
}

func getOpts(t *testing.T) diagnostics.EksaDiagnosticBundleOpts {
return diagnostics.EksaDiagnosticBundleOpts{
func getOpts(t *testing.T) diagnostics.EksaDiagnosticBundleFactoryOpts {
return diagnostics.EksaDiagnosticBundleFactoryOpts{
AnalyzerFactory: givenMockAnalyzerFactory(t),
CollectorFactory: givenMockCollectorsFactory(t),
}
Expand Down
Loading

0 comments on commit b43ccb5

Please sign in to comment.