diff --git a/cmd/airflow.go b/cmd/airflow.go index 329a3f900..78523ddab 100644 --- a/cmd/airflow.go +++ b/cmd/airflow.go @@ -60,7 +60,7 @@ func newAirflowRootCmd(client *houston.Client, out io.Writer) *cobra.Command { } cmd.AddCommand( newAirflowInitCmd(client, out), - newAirflowDeployCmd(), + newAirflowDeployCmd(client), newAirflowStartCmd(out), newAirflowKillCmd(out), newAirflowLogsCmd(out), @@ -80,7 +80,7 @@ func newDevRootCmd(client *houston.Client, out io.Writer) *cobra.Command { } cmd.AddCommand( newAirflowInitCmd(client, out), - newAirflowDeployCmd(), + newAirflowDeployCmd(client), newAirflowStartCmd(out), newAirflowKillCmd(out), newAirflowLogsCmd(out), @@ -112,8 +112,8 @@ func newAirflowInitCmd(client *houston.Client, out io.Writer) *cobra.Command { return cmd } -func newAirflowDeployCmd() *cobra.Command { - deployCmd := newDeployCmd() +func newAirflowDeployCmd(client *houston.Client) *cobra.Command { + deployCmd := newDeployCmd(client) cmd := &cobra.Command{ Use: "deploy DEPLOYMENT", Short: "Deploy an Airflow project", diff --git a/cmd/deploy.go b/cmd/deploy.go index 8206e5527..fa7cb77bc 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -60,14 +60,16 @@ Menu will be presented if you do not specify a deployment name: $ astro deploy ` -func newDeployCmd() *cobra.Command { +func newDeployCmd(client *houston.Client) *cobra.Command { cmd := &cobra.Command{ Use: "deploy DEPLOYMENT", Short: "Deploy an Airflow project", Long: "Deploy an Airflow project to an Astronomer Cluster", Args: cobra.MaximumNArgs(1), PreRunE: ensureProjectDir, - RunE: deploy, + RunE: func(cmd *cobra.Command, args []string) error { + return deploy(cmd, args, client) + }, Example: deployExample, Aliases: []string{"airflow deploy"}, } @@ -78,7 +80,7 @@ func newDeployCmd() *cobra.Command { return cmd } -func deploy(cmd *cobra.Command, args []string) error { +func deploy(cmd *cobra.Command, args []string, client *houston.Client) error { ws, err := coalesceWorkspace() if err != nil { return fmt.Errorf("failed to find a valid workspace: %w", err) @@ -107,10 +109,10 @@ func deploy(cmd *cobra.Command, args []string) error { // Silence Usage as we have now validated command input cmd.SilenceUsage = true - return deployAirflow(config.WorkingPath, releaseName, ws, forcePrompt) + return deployAirflow(config.WorkingPath, releaseName, ws, forcePrompt, client) } -func deployAirflow(path, name, wsID string, prompt bool) error { +func deployAirflow(path, name, wsID string, prompt bool, client *houston.Client) error { if wsID == "" { return errNoWorkspaceID } @@ -181,10 +183,12 @@ func deployAirflow(path, name, wsID string, prompt bool) error { } nextTag := "" + deploymentID := "" for i := range deployments { deployment := deployments[i] if deployment.ReleaseName == name { nextTag = deployment.DeploymentInfo.NextCli + deploymentID = deployment.ID } } @@ -196,7 +200,7 @@ func deployAirflow(path, name, wsID string, prompt bool) error { return err } - deploymentLink := buildAstroUIDeploymentLink(name, wsID) + deploymentLink := getAirflowUILink(deploymentID, client) fmt.Printf("Successfully pushed Docker image to Astronomer registry, it can take a few minutes to update the deployment with the new image. Navigate to the Astronomer UI to confirm the state of your deployment (%s).\n", deploymentLink) return nil @@ -295,10 +299,26 @@ func validImageRepo(image string) bool { return result } -func buildAstroUIDeploymentLink(deploymentName, wsID string) string { - context, err := config.GetCurrentContext() +func getAirflowUILink(deploymentID string, client *houston.Client) string { + if deploymentID == "" { + return "" + } + + vars := map[string]interface{}{"id": deploymentID} + + req := houston.Request{ + Query: houston.DeploymentGetRequest, + Variables: vars, + } + + resp, err := req.DoWithClient(client) if err != nil { return "" } - return fmt.Sprintf("%s://app.%s/w/%s/d/%s", config.CFG.CloudAPIProtocol.GetString(), context.Domain, wsID, deploymentName) + for _, url := range resp.Data.GetDeployment.Urls { + if url.Type == houston.AirflowURLType { + return url.URL + } + } + return "" } diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index ad5315179..acd835218 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -1,8 +1,10 @@ package cmd import ( + "bytes" "encoding/json" - "fmt" + "io/ioutil" + "net/http" "testing" "github.com/astronomer/astro-cli/airflow" @@ -144,13 +146,40 @@ func TestBuildPushDockerImageFailure(t *testing.T) { mockImageHandler.AssertExpectations(t) } -func TestBuildAstroUIDeploymentLink(t *testing.T) { +func TestGetAirflowUILink(t *testing.T) { fs := afero.NewMemMapFs() configYaml := testUtil.NewTestConfig("docker") afero.WriteFile(fs, config.HomeConfigFile, configYaml, 0o777) config.InitConfig(fs) - houstonHost := testUtil.GetEnv("HOUSTON_HOST", "localhost") - expectedResult := fmt.Sprintf("https://app.%s/w/wsID1234/d/test", houstonHost) - actualResult := buildAstroUIDeploymentLink("test", "wsID1234") + + okResponse := `{ + "data": { + "deployment": { + "id": "ckbv801t300qh0760pck7ea0c", + "executor": "CeleryExecutor", + "urls": [ + { + "type": "airflow", + "url": "https://deployments.local.astronomer.io/testDeploymentID/airflow" + }, + { + "type": "flower", + "url": "https://deployments.local.astronomer.io/testDeploymentID/flower" + } + ] + } + } + }` + + client := testUtil.NewTestClient(func(req *http.Request) *http.Response { + return &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewBufferString(okResponse)), + Header: make(http.Header), + } + }) + api := houston.NewHoustonClient(client) + expectedResult := "https://deployments.local.astronomer.io/testDeploymentID/airflow" + actualResult := getAirflowUILink("testDeploymentID", api) assert.Equal(t, expectedResult, actualResult) } diff --git a/cmd/root.go b/cmd/root.go index 2ee34e33e..2c7a3e78d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -47,7 +47,7 @@ func NewRootCmd(client *houston.Client, out io.Writer) *cobra.Command { newCompletionCmd(client, out), newConfigRootCmd(client, out), newDeploymentRootCmd(client, out), - newDeployCmd(), + newDeployCmd(client), newSaRootCmd(client, out), // TODO: remove newAirflowRootCmd, after 1.0 we have only devRootCmd newAirflowRootCmd(client, out), diff --git a/houston/constants.go b/houston/constants.go index b8f7f6015..c4e350cdd 100644 --- a/houston/constants.go +++ b/houston/constants.go @@ -7,4 +7,6 @@ const ( DeploymentAdmin = "DEPLOYMENT_ADMIN" DeploymentEditor = "DEPLOYMENT_EDITOR" DeploymentViewer = "DEPLOYMENT_VIEWER" + + AirflowURLType = "airflow" ) diff --git a/houston/queries.go b/houston/queries.go index 2ea0e4686..cbbbeec16 100644 --- a/houston/queries.go +++ b/houston/queries.go @@ -127,6 +127,10 @@ var ( id airflowVersion desiredAirflowVersion + urls { + type + url + } } }`