diff --git a/internal/cmd/local/local.go b/internal/cmd/local/local.go index 8f730a4..bbe1d83 100644 --- a/internal/cmd/local/local.go +++ b/internal/cmd/local/local.go @@ -34,7 +34,7 @@ func NewCmdLocal(provider k8s.Provider) *cobra.Command { Short: "Manages local Airbyte installations", } - cmd.AddCommand(NewCmdInstall(provider), NewCmdUninstall(provider)) + cmd.AddCommand(NewCmdInstall(provider), NewCmdUninstall(provider), NewCmdStatus(provider)) return cmd } diff --git a/internal/cmd/local/local/cmd.go b/internal/cmd/local/local/cmd.go index 4d1a089..b1e76c0 100644 --- a/internal/cmd/local/local/cmd.go +++ b/internal/cmd/local/local/cmd.go @@ -494,6 +494,30 @@ func (c *Command) Uninstall(ctx context.Context) error { return nil } +// Status handles the status of local Airbyte. +func (c *Command) Status(_ context.Context) error { + charts := []string{airbyteChartRelease, nginxChartRelease} + for _, name := range charts { + c.spinner.UpdateText(fmt.Sprintf("Verifying %s Helm Chart installation status", name)) + + rel, err := c.helm.GetRelease(name) + if err != nil { + pterm.Warning.Println("Could not get airbyte release") + pterm.Debug.Printfln("could not get airbyte release: %s", err) + continue + } + + pterm.Info.Println(fmt.Sprintf( + "Found helm chart '%s'\n Status: %s\n Chart Version: %s\n App Version: %s", + name, rel.Info.Status.String(), rel.Chart.Metadata.Version, rel.Chart.Metadata.AppVersion, + )) + } + + pterm.Info.Println(fmt.Sprintf("Airbyte should be accessible via http://localhost:%d", c.portHTTP)) + + return nil +} + // chartRequest exists to make all the parameters to handleChart somewhat manageable type chartRequest struct { name string @@ -551,7 +575,7 @@ func (c *Command) handleChart( c.tel.Attr(fmt.Sprintf("helm_%s_release_version", req.name), strconv.Itoa(helmRelease.Version)) pterm.Success.Printfln( - "Installed Helm Chart %s:\n name: %s\n namespace: %s\n version: %s\n release: %d", + "Installed Helm Chart %s:\n Name: %s\n Namespace: %s\n Version: %s\n Release: %d", req.chartName, helmRelease.Name, helmRelease.Namespace, helmRelease.Chart.Metadata.Version, helmRelease.Version) return nil } diff --git a/internal/cmd/local/local_status.go b/internal/cmd/local/local_status.go new file mode 100644 index 0000000..0348797 --- /dev/null +++ b/internal/cmd/local/local_status.go @@ -0,0 +1,93 @@ +package local + +import ( + "fmt" + "github.com/airbytehq/abctl/internal/cmd/local/docker" + "github.com/airbytehq/abctl/internal/cmd/local/k8s" + "github.com/airbytehq/abctl/internal/cmd/local/local" + "github.com/airbytehq/abctl/internal/telemetry" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +func NewCmdStatus(provider k8s.Provider) *cobra.Command { + spinner := &pterm.DefaultSpinner + + cmd := &cobra.Command{ + Use: "status", + Short: "Status of local Airbyte", + PreRunE: func(cmd *cobra.Command, args []string) error { + spinner, _ = spinner.Start("Starting status check") + spinner.UpdateText("Checking for Docker installation") + + dockerVersion, err := dockerInstalled(cmd.Context()) + if err != nil { + pterm.Error.Println("Unable to determine if Docker is installed") + return fmt.Errorf("could not determine docker installation status: %w", err) + } + + telClient.Attr("docker_version", dockerVersion.Version) + telClient.Attr("docker_arch", dockerVersion.Arch) + telClient.Attr("docker_platform", dockerVersion.Platform) + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + return telemetry.Wrapper(cmd.Context(), telemetry.Status, func() error { + spinner.UpdateText(fmt.Sprintf("Checking for existing Kubernetes cluster '%s'", provider.ClusterName)) + + cluster, err := provider.Cluster() + if err != nil { + pterm.Error.Printfln("Could not determine status of any existing '%s' cluster", provider.ClusterName) + return err + } + + if !cluster.Exists() { + pterm.Warning.Println("Airbyte does not appear to be installed locally") + return nil + } + + var port int + pterm.Success.Printfln("Existing cluster '%s' found", provider.ClusterName) + spinner.UpdateText(fmt.Sprintf("Validating existing cluster '%s'", provider.ClusterName)) + + // only for kind do we need to check the existing port + if provider.Name == k8s.Kind { + if dockerClient == nil { + dockerClient, err = docker.New(cmd.Context()) + if err != nil { + pterm.Error.Printfln("Could not connect to Docker daemon") + return fmt.Errorf("could not connect to docker: %w", err) + } + } + + port, err = dockerClient.Port(cmd.Context(), fmt.Sprintf("%s-control-plane", provider.ClusterName)) + if err != nil { + pterm.Warning.Printfln("Could not determine docker port for cluster '%s'", provider.ClusterName) + return nil + } + } + + lc, err := local.New(provider, + local.WithPortHTTP(port), + local.WithTelemetryClient(telClient), + local.WithSpinner(spinner), + ) + if err != nil { + pterm.Error.Printfln("Failed to initialize 'local' command") + return fmt.Errorf("could not initialize local command: %w", err) + } + + if err := lc.Status(cmd.Context()); err != nil { + spinner.Fail("Unable to install Airbyte locally") + return err + } + + spinner.Success("Status check") + return nil + }) + }, + } + + return cmd +} diff --git a/internal/telemetry/client.go b/internal/telemetry/client.go index fded5c9..1dca7a5 100644 --- a/internal/telemetry/client.go +++ b/internal/telemetry/client.go @@ -24,6 +24,7 @@ type EventType string const ( Install EventType = "install" + Status EventType = "status" Uninstall EventType = "uninstall" )