Skip to content

Commit

Permalink
Add astro dbt delete command (#1672)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremybeard authored Jul 3, 2024
1 parent 1162f34 commit 27ee9e8
Show file tree
Hide file tree
Showing 4 changed files with 349 additions and 109 deletions.
81 changes: 65 additions & 16 deletions cloud/deploy/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,24 @@ import (
)

type DeployBundleInput struct {
BundlePath string
MountPath string
DeploymentID string
BundleType string
Description string
Wait bool
BundlePath string
MountPath string
DeploymentID string
BundleType string
Description string
Wait bool
PlatformCoreClient astroplatformcore.CoreClient
CoreClient astrocore.CoreClient
}

func DeployBundle(input *DeployBundleInput, platformCoreClient astroplatformcore.CoreClient, coreClient astrocore.CoreClient) error {
func DeployBundle(input *DeployBundleInput) error {
c, err := config.GetCurrentContext()
if err != nil {
return err
}

// get the current deployment so we can check the deploy is valid
currentDeployment, err := deployment.CoreGetDeployment(c.Organization, input.DeploymentID, platformCoreClient)
currentDeployment, err := deployment.CoreGetDeployment(c.Organization, input.DeploymentID, input.PlatformCoreClient)
if err != nil {
return err
}
Expand All @@ -52,7 +54,7 @@ func DeployBundle(input *DeployBundleInput, platformCoreClient astroplatformcore
gitMetadata := retrieveLocalGitMetadata(input.BundlePath)

// initialize the deploy
deploy, err := createBundleDeploy(c.Organization, input, gitMetadata, coreClient)
deploy, err := createBundleDeploy(c.Organization, input, gitMetadata, input.CoreClient)
if err != nil {
return err
}
Expand All @@ -69,15 +71,62 @@ func DeployBundle(input *DeployBundleInput, platformCoreClient astroplatformcore
}

// finalize the deploy
_, err = finalizeBundleDeploy(c.Organization, deploy.Id, tarballVersion, input, coreClient)
err = finalizeBundleDeploy(c.Organization, input.DeploymentID, deploy.Id, tarballVersion, input.CoreClient)
if err != nil {
return err
}
fmt.Println("Successfully uploaded bundle with version " + tarballVersion + " to Astro.")

// if requested, wait for the deploy to finish by polling the deployment until it is healthy
if input.Wait {
err = deployment.HealthPoll(currentDeployment.Id, currentDeployment.WorkspaceId, dagOnlyDeploySleepTime, tickNum, timeoutNum, platformCoreClient)
err = deployment.HealthPoll(currentDeployment.Id, currentDeployment.WorkspaceId, dagOnlyDeploySleepTime, tickNum, timeoutNum, input.PlatformCoreClient)
if err != nil {
return err
}
}

return nil
}

type DeleteBundleInput struct {
MountPath string
DeploymentID string
WorkspaceID string
BundleType string
Description string
Wait bool
CoreClient astrocore.CoreClient
PlatformCoreClient astroplatformcore.CoreClient
}

func DeleteBundle(input *DeleteBundleInput) error {
c, err := config.GetCurrentContext()
if err != nil {
return err
}

// initialize the deploy
createInput := &DeployBundleInput{
MountPath: input.MountPath,
DeploymentID: input.DeploymentID,
BundleType: input.BundleType,
Description: input.Description,
}
deploy, err := createBundleDeploy(c.Organization, createInput, nil, input.CoreClient)
if err != nil {
return err
}

// immediately finalize with no version, which will delete the bundle from the deployment
err = finalizeBundleDeploy(c.Organization, input.DeploymentID, deploy.Id, "", input.CoreClient)
if err != nil {
return err
}
fmt.Println("Successfully requested bundle delete for mount path " + input.MountPath + " from Astro.")

// if requested, wait for the deploy to finish by polling the deployment until it is healthy
if input.Wait {
err = deployment.HealthPoll(input.DeploymentID, input.WorkspaceID, dagOnlyDeploySleepTime, tickNum, timeoutNum, input.PlatformCoreClient)
if err != nil {
return err
}
Expand Down Expand Up @@ -146,19 +195,19 @@ func createBundleDeploy(organizationID string, input *DeployBundleInput, deployG
return resp.JSON200, nil
}

func finalizeBundleDeploy(organizationID, deployID, tarballVersion string, input *DeployBundleInput, coreClient astrocore.CoreClient) (*astrocore.UpdateDeployResponse, error) {
func finalizeBundleDeploy(organizationID, deploymentID, deployID, tarballVersion string, coreClient astrocore.CoreClient) error {
request := astrocore.UpdateDeployRequest{
BundleTarballVersion: &tarballVersion,
}
resp, err := coreClient.UpdateDeployWithResponse(context.Background(), organizationID, input.DeploymentID, deployID, request)
resp, err := coreClient.UpdateDeployWithResponse(context.Background(), organizationID, deploymentID, deployID, request)
if err != nil {
return nil, err
return err
}
err = astrocore.NormalizeAPIError(resp.HTTPResponse, resp.Body)
if err != nil {
return nil, err
return err
}
return resp, nil
return nil
}

func retrieveLocalGitMetadata(bundlePath string) *astrocore.DeployGit {
Expand Down
99 changes: 67 additions & 32 deletions cloud/deploy/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,35 @@ import (
"github.com/stretchr/testify/suite"
)

type Suite struct {
type BundleSuite struct {
suite.Suite
mockPlatformCoreClient *astroplatformcore_mocks.ClientWithResponsesInterface
mockCoreClient *astrocore_mocks.ClientWithResponsesInterface
}

func (s *Suite) SetupTest() {
func (s *BundleSuite) SetupTest() {
testUtil.InitTestConfig(testUtil.LocalPlatform)
s.mockPlatformCoreClient = new(astroplatformcore_mocks.ClientWithResponsesInterface)
s.mockCoreClient = new(astrocore_mocks.ClientWithResponsesInterface)
}

func TestBundleDeploy(t *testing.T) {
suite.Run(t, new(Suite))
func TestBundles(t *testing.T) {
suite.Run(t, new(BundleSuite))
}

func (s *Suite) TestBundleDeploy_Success() {
func (s *BundleSuite) TestBundleDeploy_Success() {
canCiCdDeploy = func(token string) bool {
return true
}

input := &DeployBundleInput{
BundlePath: "test-bundle-path",
MountPath: "test-mount-path",
DeploymentID: "test-deployment-id",
BundleType: "test-bundle-type",
Description: "test-description",
BundlePath: "test-bundle-path",
MountPath: "test-mount-path",
DeploymentID: "test-deployment-id",
BundleType: "test-bundle-type",
Description: "test-description",
PlatformCoreClient: s.mockPlatformCoreClient,
CoreClient: s.mockCoreClient,
}

mockGetDeployment(s.mockPlatformCoreClient, true, true)
Expand All @@ -58,55 +60,62 @@ func (s *Suite) TestBundleDeploy_Success() {
Description: &input.Description,
}
mockCreateDeploy(s.mockCoreClient, "http://bundle-upload-url", expectedDeploy)
mockUpdateDeploy(s.mockCoreClient)
mockUpdateDeploy(s.mockCoreClient, "version-id")

azureUploader = func(sasLink string, file io.Reader) (string, error) {
return "version-id", nil
}

err := DeployBundle(input, s.mockPlatformCoreClient, s.mockCoreClient)
err := DeployBundle(input)
assert.NoError(s.T(), err)

s.mockCoreClient.AssertExpectations(s.T())
s.mockPlatformCoreClient.AssertExpectations(s.T())
}

func (s *Suite) TestBundleDeploy_CiCdIncompatible() {
func (s *BundleSuite) TestBundleDeploy_CiCdIncompatible() {
canCiCdDeploy = func(token string) bool {
return false
}

input := &DeployBundleInput{
DeploymentID: "test-deployment-id",
DeploymentID: "test-deployment-id",
PlatformCoreClient: s.mockPlatformCoreClient,
CoreClient: s.mockCoreClient,
}

mockGetDeployment(s.mockPlatformCoreClient, true, true)

err := DeployBundle(input, s.mockPlatformCoreClient, s.mockCoreClient)
err := DeployBundle(input)
assert.Error(s.T(), err)

s.mockCoreClient.AssertExpectations(s.T())
s.mockPlatformCoreClient.AssertExpectations(s.T())
}

func (s *Suite) TestBundleDeploy_DagDeployDisabled() {
input := &DeployBundleInput{}
func (s *BundleSuite) TestBundleDeploy_DagDeployDisabled() {
input := &DeployBundleInput{
PlatformCoreClient: s.mockPlatformCoreClient,
CoreClient: s.mockCoreClient,
}

mockGetDeployment(s.mockPlatformCoreClient, false, false)

err := DeployBundle(input, s.mockPlatformCoreClient, s.mockCoreClient)
err := DeployBundle(input)
assert.Error(s.T(), err)

s.mockCoreClient.AssertExpectations(s.T())
s.mockPlatformCoreClient.AssertExpectations(s.T())
}

func (s *Suite) TestBundleDeploy_GitMetadataRetrieved() {
func (s *BundleSuite) TestBundleDeploy_GitMetadataRetrieved() {
sha, gitPath := s.createTestGitRepository(false)
defer os.RemoveAll(gitPath)

input := &DeployBundleInput{
BundlePath: gitPath,
BundlePath: gitPath,
PlatformCoreClient: s.mockPlatformCoreClient,
CoreClient: s.mockCoreClient,
}

mockGetDeployment(s.mockPlatformCoreClient, true, false)
Expand All @@ -128,25 +137,27 @@ func (s *Suite) TestBundleDeploy_GitMetadataRetrieved() {
},
}
mockCreateDeploy(s.mockCoreClient, "http://bundle-upload-url", expectedDeploy)
mockUpdateDeploy(s.mockCoreClient)
mockUpdateDeploy(s.mockCoreClient, "version-id")

azureUploader = func(sasLink string, file io.Reader) (string, error) {
return "version-id", nil
}

err := DeployBundle(input, s.mockPlatformCoreClient, s.mockCoreClient)
err := DeployBundle(input)
assert.NoError(s.T(), err)

s.mockCoreClient.AssertExpectations(s.T())
s.mockPlatformCoreClient.AssertExpectations(s.T())
}

func (s *Suite) TestBundleDeploy_GitHasUncommittedChanges() {
func (s *BundleSuite) TestBundleDeploy_GitHasUncommittedChanges() {
_, gitPath := s.createTestGitRepository(true)
defer os.RemoveAll(gitPath)

input := &DeployBundleInput{
BundlePath: gitPath,
BundlePath: gitPath,
PlatformCoreClient: s.mockPlatformCoreClient,
CoreClient: s.mockCoreClient,
}

mockGetDeployment(s.mockPlatformCoreClient, true, false)
Expand All @@ -159,21 +170,24 @@ func (s *Suite) TestBundleDeploy_GitHasUncommittedChanges() {
Git: nil,
}
mockCreateDeploy(s.mockCoreClient, "http://bundle-upload-url", expectedDeploy)
mockUpdateDeploy(s.mockCoreClient)
mockUpdateDeploy(s.mockCoreClient, "version-id")

azureUploader = func(sasLink string, file io.Reader) (string, error) {
return "version-id", nil
}

err := DeployBundle(input, s.mockPlatformCoreClient, s.mockCoreClient)
err := DeployBundle(input)
assert.NoError(s.T(), err)

s.mockCoreClient.AssertExpectations(s.T())
s.mockPlatformCoreClient.AssertExpectations(s.T())
}

func (s *Suite) TestBundleDeploy_BundleUploadUrlMissing() {
input := &DeployBundleInput{}
func (s *BundleSuite) TestBundleDeploy_BundleUploadUrlMissing() {
input := &DeployBundleInput{
PlatformCoreClient: s.mockPlatformCoreClient,
CoreClient: s.mockCoreClient,
}

mockGetDeployment(s.mockPlatformCoreClient, true, false)

Expand All @@ -183,13 +197,31 @@ func (s *Suite) TestBundleDeploy_BundleUploadUrlMissing() {
return "version-id", nil
}

err := DeployBundle(input, s.mockPlatformCoreClient, s.mockCoreClient)
err := DeployBundle(input)
assert.Error(s.T(), err)

s.mockCoreClient.AssertExpectations(s.T())
s.mockPlatformCoreClient.AssertExpectations(s.T())
}

func (s *BundleSuite) TestBundleDelete_Success() {
input := &DeleteBundleInput{
DeploymentID: "test-deployment-id",
MountPath: "test-mount-path",
PlatformCoreClient: s.mockPlatformCoreClient,
CoreClient: s.mockCoreClient,
}

mockCreateDeploy(s.mockCoreClient, "", nil)
mockUpdateDeploy(s.mockCoreClient, "")

err := DeleteBundle(input)
assert.NoError(s.T(), err)

s.mockCoreClient.AssertExpectations(s.T())
s.mockPlatformCoreClient.AssertExpectations(s.T())
}

func mockCreateDeploy(client *astrocore_mocks.ClientWithResponsesInterface, bundleUploadURL string, expectedDeploy *astrocore.CreateDeployRequest) {
var request any
if expectedDeploy != nil {
Expand All @@ -211,8 +243,11 @@ func mockCreateDeploy(client *astrocore_mocks.ClientWithResponsesInterface, bund
client.On("CreateDeployWithResponse", mock.Anything, mock.Anything, mock.Anything, request).Return(response, nil)
}

func mockUpdateDeploy(client *astrocore_mocks.ClientWithResponsesInterface) {
client.On("UpdateDeployWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&astrocore.UpdateDeployResponse{
func mockUpdateDeploy(client *astrocore_mocks.ClientWithResponsesInterface, expectedBundleVersion string) {
request := astrocore.UpdateDeployRequest{
BundleTarballVersion: &expectedBundleVersion,
}
client.On("UpdateDeployWithResponse", mock.Anything, mock.Anything, mock.Anything, mock.Anything, request).Return(&astrocore.UpdateDeployResponse{
HTTPResponse: &http.Response{
StatusCode: astrocore.HTTPStatus200,
},
Expand All @@ -232,7 +267,7 @@ func mockGetDeployment(client *astroplatformcore_mocks.ClientWithResponsesInterf
}, nil)
}

func (s *Suite) createTestGitRepository(withUncommittedFile bool) (sha, path string) {
func (s *BundleSuite) createTestGitRepository(withUncommittedFile bool) (sha, path string) {
dir, err := os.MkdirTemp("", "test-git-repo")
require.NoError(s.T(), err)

Expand Down
Loading

0 comments on commit 27ee9e8

Please sign in to comment.