From 7dc42a49585fbec369d542d462d58fb8c2161472 Mon Sep 17 00:00:00 2001 From: Fraser Davidson Date: Mon, 13 Nov 2023 12:17:56 +0000 Subject: [PATCH] FTR-99: Refactor cross-project approach (#15) --- go.mod | 4 +- go.sum | 15 +++- pkg/cmd/app/deploy/set.go | 67 ++++++++++------- pkg/cmd/app/destroy/set.go | 76 ++++++++++++-------- pkg/core/types.go | 20 +++++- pkg/core/workload_destroy_prevented_error.go | 7 ++ pkg/core/workload_result.go | 11 +-- 7 files changed, 131 insertions(+), 69 deletions(-) create mode 100644 pkg/core/workload_destroy_prevented_error.go diff --git a/go.mod b/go.mod index 9b9b224..6f03b41 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,9 @@ module github.com/frontierdigital/ranger go 1.21 require ( - github.com/frontierdigital/utils v0.0.8-1 + github.com/frontierdigital/utils v0.0.9 github.com/google/uuid v1.1.2 + github.com/libgit2/git2go/v34 v34.0.0 github.com/otiai10/copy v1.9.0 github.com/segmentio/ksuid v1.0.4 github.com/spf13/cobra v1.6.1 @@ -31,6 +32,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.4.1 // indirect + golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect golang.org/x/sys v0.3.0 // indirect golang.org/x/text v0.4.0 // indirect diff --git a/go.sum b/go.sum index 8f74ce6..ac299b7 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/frontierdigital/utils v0.0.8-1 h1:J4cYMjEWq/XMewPfSBDtGb7+DUnpj/gKvjd/yts0AtQ= -github.com/frontierdigital/utils v0.0.8-1/go.mod h1:iz+lbB9iGA9ZsVbber/tPosKC9HFTgKTDP8/UC6XxBY= +github.com/frontierdigital/utils v0.0.9 h1:Lw2UDw9Z71x47t1N4gHnDuohuIHH5TV5AjDRuk09nbY= +github.com/frontierdigital/utils v0.0.9/go.mod h1:iz+lbB9iGA9ZsVbber/tPosKC9HFTgKTDP8/UC6XxBY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -146,6 +146,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -182,6 +184,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/libgit2/git2go/v34 v34.0.0 h1:UKoUaKLmiCRbOCD3PtUi2hD6hESSXzME/9OUZrGcgu8= +github.com/libgit2/git2go/v34 v34.0.0/go.mod h1:blVco2jDAw6YTXkErMMqzHLcAjKkwF0aWIRHBqiJkZ0= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -299,8 +303,11 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -404,6 +411,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190812172437-4e8604ab3aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -424,6 +432,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -435,6 +444,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/pkg/cmd/app/deploy/set.go b/pkg/cmd/app/deploy/set.go index 52b4e28..8dff821 100644 --- a/pkg/cmd/app/deploy/set.go +++ b/pkg/cmd/app/deploy/set.go @@ -36,8 +36,7 @@ func DeploySet(config *core.Config, projectName string, organisationName string) workloadInstance.PrintHeader() result := DeployWorkload(*azureDevOps, config, projectName, organisationName, manifest.Environment, manifest.Set, workloadInstance) - if result.Error != nil { - output.PrintfError(result.Error.Error()) + if result.Status == core.WorkloadResultStatusValuesType.Failed { hasErrors = true } @@ -52,34 +51,50 @@ func DeploySet(config *core.Config, projectName string, organisationName string) } func DeployWorkload(azureDevOps azuredevops.AzureDevOps, config *core.Config, projectName string, organisationName string, environment string, set string, workloadInstance *core.WorkloadInstance) (result *core.WorkloadResult) { + defer func() { + if e, ok := recover().(error); ok { + result.Status = core.WorkloadResultStatusValuesType.Failed + output.PrintfError(e.Error()) + } + }() + result = &core.WorkloadResult{ Workload: workloadInstance, } typeProjectName, typeRepositoryName := workloadInstance.GetTypeProjectAndRepositoryNames() - pipelineName := fmt.Sprintf("%s (deploy)", typeRepositoryName) - buildDefinition, err := azureDevOps.GetBuildDefinitionByName(typeProjectName, pipelineName) + repository, err := azureDevOps.GetRepository(typeProjectName, typeRepositoryName) if err != nil { - result.Error = err - return + panic(err) } - output.PrintlnfInfo("Found deploy pipeline definition with Id '%d' for workload type '%s' (https://dev.azure.com/%s/%s/_build?definitionId=%d)", - *buildDefinition.Id, workloadInstance.Type, organisationName, projectName, *buildDefinition.Id) + output.PrintlnfInfo("Found repository with Id '%s' for workload type '%s' (%s)", repository.Id, workloadInstance.Type, *repository.WebUrl) - repository, err := azureDevOps.GetRepository(typeProjectName, typeRepositoryName) + var buildDefinitionId *int + pipelineName := fmt.Sprintf("%s~%s (deploy)", typeProjectName, typeRepositoryName) + buildDefinitionRef, err := azureDevOps.GetBuildDefinitionByName(projectName, pipelineName) if err != nil { - result.Error = err - return + if _, ok := err.(*azuredevops.BuildNotFoundError); ok { + buildDefinition, err := azureDevOps.CreateBuildDefinition(projectName, repository.Id.String(), "Ranger/Workloads", pipelineName, "azure-pipelines.deploy.yml") + if err != nil { + panic(err) + } + buildDefinitionId = buildDefinition.Id + output.PrintlnfInfo("Created deploy pipeline definition with Id '%d' for workload type '%s' (https://dev.azure.com/%s/%s/_build?definitionId=%d)", + *buildDefinitionId, workloadInstance.Type, organisationName, projectName, *buildDefinitionId) + } else { + panic(err) + } + } else { + buildDefinitionId = buildDefinitionRef.Id + output.PrintlnfInfo("Found deploy pipeline definition with Id '%d' for workload type '%s' (https://dev.azure.com/%s/%s/_build?definitionId=%d)", + *buildDefinitionId, workloadInstance.Type, organisationName, projectName, *buildDefinitionId) } - output.PrintlnfInfo("Found repository with Id '%s' for workload type '%s' (%s)", repository.Id, workloadInstance.Type, *repository.WebUrl) - configRef, err := workload.PrepareConfig(config, projectName, organisationName, environment, set, workloadInstance) if err != nil { - result.Error = err - return + panic(err) } tags := []string{environment, set} @@ -98,10 +113,9 @@ func DeployWorkload(azureDevOps azuredevops.AzureDevOps, config *core.Config, pr sourceBranchName := fmt.Sprintf("refs/tags/%s", workloadInstance.Version) - build, err := azureDevOps.QueueBuild(typeProjectName, buildDefinition.Id, sourceBranchName, templateParameters, tags) + build, err := azureDevOps.QueueBuild(projectName, *buildDefinitionId, sourceBranchName, templateParameters, tags) if err != nil { - result.Error = err - return + panic(err) } buildLinks := build.Links.(map[string]interface{}) buildWebLinks := buildLinks["web"].(map[string]interface{}) @@ -116,16 +130,14 @@ func DeployWorkload(azureDevOps azuredevops.AzureDevOps, config *core.Config, pr output.PrintlnfInfo("Waiting for build '%s' (%s)", *build.BuildNumber, buildWebLink) - err = azureDevOps.WaitForBuild(typeProjectName, build.Id, WaitForBuildAttempts, WaitForBuildInterval) + err = azureDevOps.WaitForBuild(projectName, *build.Id, WaitForBuildAttempts, WaitForBuildInterval) if err != nil { - result.Error = err - return + panic(err) } - build, err = azureDevOps.GetBuild(typeProjectName, build.Id) + build, err = azureDevOps.GetBuild(projectName, *build.Id) if err != nil { - result.Error = err - return + panic(err) } if build.FinishTime != nil { @@ -133,16 +145,17 @@ func DeployWorkload(azureDevOps azuredevops.AzureDevOps, config *core.Config, pr } if err != nil { - result.Error = err output.PrintlnfInfo("Build '%s' has not completed (%s)", *build.BuildNumber, buildWebLink) - return + panic(err) } output.PrintlnfInfo("Build '%s' has completed with result '%s' (%s)", *build.BuildNumber, *build.Result, buildWebLink) if *build.Result != "succeeded" { - result.Error = fmt.Errorf("build '%d' has result '%s'", *build.Id, *build.Result) + panic(fmt.Errorf("build '%d' has result '%s'", *build.Id, *build.Result)) } + result.Status = core.WorkloadResultStatusValuesType.Succeeded + return } diff --git a/pkg/cmd/app/destroy/set.go b/pkg/cmd/app/destroy/set.go index 830664a..5c2840f 100644 --- a/pkg/cmd/app/destroy/set.go +++ b/pkg/cmd/app/destroy/set.go @@ -38,8 +38,7 @@ func DestroySet(config *core.Config, projectName string, organisationName string workloadInstance.PrintHeader() result := DestroyWorkload(*azureDevOps, config, projectName, organisationName, manifest.Environment, manifest.Set, workloadInstance) - if result.Error != nil { - output.PrintfError(result.Error.Error()) + if result.Status == core.WorkloadResultStatusValuesType.Failed { hasErrors = true } @@ -54,43 +53,64 @@ func DestroySet(config *core.Config, projectName string, organisationName string } func DestroyWorkload(azureDevOps azuredevops.AzureDevOps, config *core.Config, projectName string, organisationName string, environment string, set string, workloadInstance *core.WorkloadInstance) (result *core.WorkloadResult) { + defer func() { + if e, ok := recover().(error); ok { + if _, ok := e.(*core.WorkloadDestroyPreventedError); ok { + result.Status = core.WorkloadResultStatusValuesType.Skipped + } else { + result.Status = core.WorkloadResultStatusValuesType.Failed + } + output.PrintfError(e.Error()) + } + }() + result = &core.WorkloadResult{ Workload: workloadInstance, } if workloadInstance.PreventDestroy { - output.PrintlnfInfo("Instance configuration prevents destroy; skipping") now := time.Now() result.Link = "N/A" result.QueueTime = &now result.FinishTime = &now - return + panic(&core.WorkloadDestroyPreventedError{ + Workload: workloadInstance, + }) } typeProjectName, typeRepositoryName := workloadInstance.GetTypeProjectAndRepositoryNames() - pipelineName := fmt.Sprintf("%s (destroy)", typeRepositoryName) - buildDefinition, err := azureDevOps.GetBuildDefinitionByName(typeProjectName, pipelineName) + repository, err := azureDevOps.GetRepository(typeProjectName, typeRepositoryName) if err != nil { - result.Error = err - return + panic(err) } - output.PrintlnfInfo("Found destroy pipeline definition with Id '%d' for workload type '%s' (https://dev.azure.com/%s/%s/_build?definitionId=%d)", - *buildDefinition.Id, workloadInstance.Type, organisationName, projectName, *buildDefinition.Id) + output.PrintlnfInfo("Found repository with Id '%s' for workload type '%s' (%s)", repository.Id, workloadInstance.Type, *repository.WebUrl) - repository, err := azureDevOps.GetRepository(typeProjectName, typeRepositoryName) + var buildDefinitionId *int + pipelineName := fmt.Sprintf("%s~%s (destroy)", typeProjectName, typeRepositoryName) + buildDefinitionRef, err := azureDevOps.GetBuildDefinitionByName(projectName, pipelineName) if err != nil { - result.Error = err - return + if _, ok := err.(*azuredevops.BuildNotFoundError); ok { + buildDefinition, err := azureDevOps.CreateBuildDefinition(projectName, repository.Id.String(), "Ranger/Workloads", pipelineName, "azure-pipelines.destroy.yml") + if err != nil { + panic(err) + } + buildDefinitionId = buildDefinition.Id + output.PrintlnfInfo("Created destroy pipeline definition with Id '%d' for workload type '%s' (https://dev.azure.com/%s/%s/_build?definitionId=%d)", + *buildDefinitionId, workloadInstance.Type, organisationName, projectName, *buildDefinitionId) + } else { + panic(err) + } + } else { + buildDefinitionId = buildDefinitionRef.Id + output.PrintlnfInfo("Found destroy pipeline definition with Id '%d' for workload type '%s' (https://dev.azure.com/%s/%s/_build?definitionId=%d)", + *buildDefinitionId, workloadInstance.Type, organisationName, projectName, *buildDefinitionId) } - output.PrintlnfInfo("Found repository with Id '%s' for workload type '%s' (%s)", repository.Id, workloadInstance.Type, *repository.WebUrl) - configRef, err := workload.PrepareConfig(config, projectName, organisationName, environment, set, workloadInstance) if err != nil { - result.Error = err - return + panic(err) } tags := []string{environment, set} @@ -109,10 +129,9 @@ func DestroyWorkload(azureDevOps azuredevops.AzureDevOps, config *core.Config, p sourceBranchName := fmt.Sprintf("refs/tags/%s", workloadInstance.Version) - build, err := azureDevOps.QueueBuild(typeProjectName, buildDefinition.Id, sourceBranchName, templateParameters, tags) + build, err := azureDevOps.QueueBuild(projectName, *buildDefinitionId, sourceBranchName, templateParameters, tags) if err != nil { - result.Error = err - return + panic(err) } buildLinks := build.Links.(map[string]interface{}) buildWebLinks := buildLinks["web"].(map[string]interface{}) @@ -127,16 +146,14 @@ func DestroyWorkload(azureDevOps azuredevops.AzureDevOps, config *core.Config, p output.PrintlnfInfo("Waiting for build '%s' (%s)", *build.BuildNumber, buildWebLink) - err = azureDevOps.WaitForBuild(typeProjectName, build.Id, WaitForBuildAttempts, WaitForBuildInterval) + err = azureDevOps.WaitForBuild(projectName, *build.Id, WaitForBuildAttempts, WaitForBuildInterval) if err != nil { - result.Error = err - return + panic(err) } - build, err = azureDevOps.GetBuild(typeProjectName, build.Id) + build, err = azureDevOps.GetBuild(projectName, *build.Id) if err != nil { - result.Error = err - return + panic(err) } if build.FinishTime != nil { @@ -144,16 +161,17 @@ func DestroyWorkload(azureDevOps azuredevops.AzureDevOps, config *core.Config, p } if err != nil { - result.Error = err output.PrintlnfInfo("Build '%s' has not completed (%s)", *build.BuildNumber, buildWebLink) - return + panic(err) } output.PrintlnfInfo("Build '%s' has completed with result '%s' (%s)", *build.BuildNumber, *build.Result, buildWebLink) if *build.Result != "succeeded" { - result.Error = fmt.Errorf("build '%d' has result '%s'", *build.Id, *build.Result) + panic(fmt.Errorf("build '%d' has result '%s'", *build.Id, *build.Result)) } + result.Status = core.WorkloadResultStatusValuesType.Succeeded + return } diff --git a/pkg/core/types.go b/pkg/core/types.go index 1b481aa..5870902 100644 --- a/pkg/core/types.go +++ b/pkg/core/types.go @@ -75,9 +75,27 @@ type WorkloadInstance struct { } type WorkloadResult struct { - Error error FinishTime *time.Time Link string QueueTime *time.Time + Status WorkloadResultStatus Workload *WorkloadInstance } + +type WorkloadResultStatus string + +type workloadResultStatusValuesType struct { + Succeeded WorkloadResultStatus + Failed WorkloadResultStatus + Skipped WorkloadResultStatus +} + +var WorkloadResultStatusValuesType = workloadResultStatusValuesType{ + Succeeded: "Succeeded", + Failed: "Failed", + Skipped: "Skipped", +} + +type WorkloadDestroyPreventedError struct { + Workload *WorkloadInstance +} diff --git a/pkg/core/workload_destroy_prevented_error.go b/pkg/core/workload_destroy_prevented_error.go new file mode 100644 index 0000000..c1efba1 --- /dev/null +++ b/pkg/core/workload_destroy_prevented_error.go @@ -0,0 +1,7 @@ +package core + +import "fmt" + +func (e *WorkloadDestroyPreventedError) Error() string { + return fmt.Sprintf("destroy prevented for workload with name '%s'", e.Workload.Name) +} diff --git a/pkg/core/workload_result.go b/pkg/core/workload_result.go index d73b858..fe0ff27 100644 --- a/pkg/core/workload_result.go +++ b/pkg/core/workload_result.go @@ -10,13 +10,6 @@ import ( ) func (d *WorkloadResult) PrintResult() { - var result string - if d.Error != nil { - result = "Failed" - } else { - result = "Succeeded" - } - var elasped time.Duration if d.QueueTime != nil && d.FinishTime != nil { elasped = d.FinishTime.Sub(*d.QueueTime) @@ -28,13 +21,13 @@ func (d *WorkloadResult) PrintResult() { } var finishTime string - if d.QueueTime != nil { + if d.FinishTime != nil { finishTime = d.FinishTime.Format(time.RFC1123) } builder := &strings.Builder{} builder.WriteString(fmt.Sprintf("%s\n", str.Repeat("-", 78))) - builder.WriteString(fmt.Sprintf("Result | %s\n", result)) + builder.WriteString(fmt.Sprintf("Result | %s\n", d.Status)) builder.WriteString(fmt.Sprintf("Link | %s\n", d.Link)) builder.WriteString(fmt.Sprintf("Queued | %s\n", queueTime)) builder.WriteString(fmt.Sprintf("Finished | %s\n", finishTime))