From 044b636a57ca46c4bfe222df1bf230a3ef1068b3 Mon Sep 17 00:00:00 2001 From: bijayasharma Date: Thu, 4 Feb 2021 15:25:07 -0500 Subject: [PATCH] Updated executor definition to introduce a status interface Change-Id: Ib95cb2f6464b2d15ba7378e9b40a13899d273ba3 Signed-off-by: bijayasharma Relates-To: #409 Closes: #409 --- pkg/phase/client.go | 15 ++++++++ pkg/phase/client_test.go | 4 +++ pkg/phase/executors/baremetal_manager.go | 6 ++++ pkg/phase/executors/clusterctl.go | 6 ++++ pkg/phase/executors/container.go | 5 +++ pkg/phase/executors/ephemeral.go | 5 +++ pkg/phase/executors/k8s_applier.go | 44 ++++++++++++++++++++++++ pkg/phase/ifc/executor.go | 4 +++ pkg/phase/ifc/phase.go | 6 ++++ 9 files changed, 95 insertions(+) diff --git a/pkg/phase/client.go b/pkg/phase/client.go index 79e329a43..a0ef7f6bb 100644 --- a/pkg/phase/client.go +++ b/pkg/phase/client.go @@ -178,6 +178,21 @@ func (p *phase) Render(w io.Writer, executorRender bool, options ifc.RenderOptio return rendered.Write(w) } +// Status returns the status of the given phase +func (p *phase) Status() (ifc.PhaseStatus, error) { + executor, err := p.Executor() + if err != nil { + return ifc.PhaseStatus{}, err + } + + sts, err := executor.Status() + if err != nil { + return ifc.PhaseStatus{}, err + } + + return ifc.PhaseStatus{ExecutorStatus: sts}, err +} + // DocumentRoot root that holds all the documents associated with the phase func (p *phase) DocumentRoot() (string, error) { relativePath := p.apiObj.Config.DocumentEntryPoint diff --git a/pkg/phase/client_test.go b/pkg/phase/client_test.go index 41bdd0e7a..394219318 100644 --- a/pkg/phase/client_test.go +++ b/pkg/phase/client_test.go @@ -208,6 +208,10 @@ func TestPhaseValidate(t *testing.T) { } } +func (e fakeExecutor) Status() (ifc.ExecutorStatus, error) { + return ifc.ExecutorStatus{}, nil +} + // TODO develop tests, when we add phase object validation func TestClientByAPIObj(t *testing.T) { helper, err := phase.NewHelper(testConfig(t)) diff --git a/pkg/phase/executors/baremetal_manager.go b/pkg/phase/executors/baremetal_manager.go index deca9d8ac..5305daef3 100644 --- a/pkg/phase/executors/baremetal_manager.go +++ b/pkg/phase/executors/baremetal_manager.go @@ -21,6 +21,7 @@ import ( "opendev.org/airship/airshipctl/pkg/api/v1alpha1" airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" + "opendev.org/airship/airshipctl/pkg/errors" "opendev.org/airship/airshipctl/pkg/events" "opendev.org/airship/airshipctl/pkg/inventory" inventoryifc "opendev.org/airship/airshipctl/pkg/inventory/ifc" @@ -140,3 +141,8 @@ func toCommandOptions(i inventoryifc.Inventory, Timeout: timeout, } } + +// Status returns the status of the given phase +func (e *BaremetalManagerExecutor) Status() (ifc.ExecutorStatus, error) { + return ifc.ExecutorStatus{}, errors.ErrNotImplemented{What: BMHManager} +} diff --git a/pkg/phase/executors/clusterctl.go b/pkg/phase/executors/clusterctl.go index 2eb1806c1..7e5639afe 100755 --- a/pkg/phase/executors/clusterctl.go +++ b/pkg/phase/executors/clusterctl.go @@ -24,6 +24,7 @@ import ( "opendev.org/airship/airshipctl/pkg/cluster/clustermap" "opendev.org/airship/airshipctl/pkg/clusterctl/client" "opendev.org/airship/airshipctl/pkg/document" + "opendev.org/airship/airshipctl/pkg/errors" airerrors "opendev.org/airship/airshipctl/pkg/errors" "opendev.org/airship/airshipctl/pkg/events" "opendev.org/airship/airshipctl/pkg/k8s/kubeconfig" @@ -231,3 +232,8 @@ func (c *ClusterctlExecutor) Render(w io.Writer, ro ifc.RenderOptions) error { } return filtered.Write(w) } + +// Status returns the status of the given phase +func (c *ClusterctlExecutor) Status() (ifc.ExecutorStatus, error) { + return ifc.ExecutorStatus{}, errors.ErrNotImplemented{What: Clusterctl} +} diff --git a/pkg/phase/executors/container.go b/pkg/phase/executors/container.go index 1979f5396..838613022 100644 --- a/pkg/phase/executors/container.go +++ b/pkg/phase/executors/container.go @@ -199,3 +199,8 @@ func (c *ContainerExecutor) setConfig() error { } return nil } + +// Status returns the status of the given phase +func (c *ContainerExecutor) Status() (ifc.ExecutorStatus, error) { + return ifc.ExecutorStatus{}, errors.ErrNotImplemented{What: GenericContainer} +} diff --git a/pkg/phase/executors/ephemeral.go b/pkg/phase/executors/ephemeral.go index 17c4c9ffe..06667fd8d 100644 --- a/pkg/phase/executors/ephemeral.go +++ b/pkg/phase/executors/ephemeral.go @@ -140,3 +140,8 @@ func (c *EphemeralExecutor) Render(w io.Writer, _ ifc.RenderOptions) error { log.Print("Ephemeral Executor Render() will be implemented later.") return nil } + +// Status returns the status of the given phase +func (c *EphemeralExecutor) Status() (ifc.ExecutorStatus, error) { + return ifc.ExecutorStatus{}, errors.ErrNotImplemented{What: Ephemeral} +} diff --git a/pkg/phase/executors/k8s_applier.go b/pkg/phase/executors/k8s_applier.go index 53083e739..957fab23e 100644 --- a/pkg/phase/executors/k8s_applier.go +++ b/pkg/phase/executors/k8s_applier.go @@ -19,6 +19,10 @@ import ( "time" "sigs.k8s.io/cli-utils/pkg/common" + "sigs.k8s.io/cli-utils/pkg/kstatus/polling/aggregator" + "sigs.k8s.io/cli-utils/pkg/kstatus/polling/event" + "sigs.k8s.io/cli-utils/pkg/kstatus/status" + "sigs.k8s.io/cli-utils/pkg/provider" airshipv1 "opendev.org/airship/airshipctl/pkg/api/v1alpha1" "opendev.org/airship/airshipctl/pkg/cluster/clustermap" @@ -146,3 +150,43 @@ func (e *KubeApplierExecutor) Render(w io.Writer, o ifc.RenderOptions) error { } return bundle.Write(w) } + +// Status returns the status of the given phase +func (e *KubeApplierExecutor) Status() (sts ifc.ExecutorStatus, err error) { + var ctx string + ctx, err = e.clusterMap.ClusterKubeconfigContext(e.clusterName) + if err != nil { + return sts, err + } + log.Debug("Getting kubeconfig file information from kubeconfig provider") + path, _, err := e.kubeconfig.GetFile() + if err != nil { + return sts, err + } + + cf := provider.NewProvider(utils.FactoryFromKubeConfig(path, ctx)) + rm, err := cf.Factory().ToRESTMapper() + if err != nil { + return + } + r := utils.DefaultManifestReaderFactory(false, e.ExecutorBundle, rm) + infos, err := r.Read() + if err != nil { + return + } + + var resSts event.ResourceStatuses + + for _, info := range infos { + s, sErr := status.Compute(info) + if sErr != nil { + return + } + st := &event.ResourceStatus{ + Status: s.Status, + } + resSts = append(resSts, st) + } + _ = aggregator.AggregateStatus(resSts, status.CurrentStatus) + return ifc.ExecutorStatus{}, err +} diff --git a/pkg/phase/ifc/executor.go b/pkg/phase/ifc/executor.go index 6308e1d6b..5df7cf603 100644 --- a/pkg/phase/ifc/executor.go +++ b/pkg/phase/ifc/executor.go @@ -30,8 +30,12 @@ type Executor interface { Run(chan events.Event, RunOptions) Render(io.Writer, RenderOptions) error Validate() error + Status() (ExecutorStatus, error) } +// ExecutorStatus is a struct which defines the status +type ExecutorStatus struct{} + // RunOptions holds options for run method type RunOptions struct { DryRun bool diff --git a/pkg/phase/ifc/phase.go b/pkg/phase/ifc/phase.go index 5df30c668..618689292 100644 --- a/pkg/phase/ifc/phase.go +++ b/pkg/phase/ifc/phase.go @@ -29,6 +29,12 @@ type Phase interface { Details() (string, error) Executor() (Executor, error) Render(io.Writer, bool, RenderOptions) error + Status() (PhaseStatus, error) +} + +// PhaseStatus is a struct which defines status of phase +type PhaseStatus struct { + ExecutorStatus ExecutorStatus } // Plan provides a way to interact with phase plans