1package cmd 2 3import ( 4 bihttpagent "github.com/cloudfoundry/bosh-agent/agentclient/http" 5 bosherr "github.com/cloudfoundry/bosh-utils/errors" 6 bihttpclient "github.com/cloudfoundry/bosh-utils/httpclient" 7 boshlog "github.com/cloudfoundry/bosh-utils/logger" 8 "github.com/cppforlife/go-patch/patch" 9 10 biblobstore "github.com/cloudfoundry/bosh-cli/blobstore" 11 bicloud "github.com/cloudfoundry/bosh-cli/cloud" 12 biconfig "github.com/cloudfoundry/bosh-cli/config" 13 bicpirel "github.com/cloudfoundry/bosh-cli/cpi/release" 14 bidepl "github.com/cloudfoundry/bosh-cli/deployment" 15 boshtpl "github.com/cloudfoundry/bosh-cli/director/template" 16 biinstall "github.com/cloudfoundry/bosh-cli/installation" 17 boshinst "github.com/cloudfoundry/bosh-cli/installation" 18 biinstallmanifest "github.com/cloudfoundry/bosh-cli/installation/manifest" 19 birelsetmanifest "github.com/cloudfoundry/bosh-cli/release/set/manifest" 20 biui "github.com/cloudfoundry/bosh-cli/ui" 21) 22 23type DeploymentDeleter interface { 24 DeleteDeployment(skipDrain bool, stage biui.Stage) (err error) 25} 26 27func NewDeploymentDeleter( 28 ui biui.UI, 29 logTag string, 30 logger boshlog.Logger, 31 deploymentStateService biconfig.DeploymentStateService, 32 releaseManager boshinst.ReleaseManager, 33 cloudFactory bicloud.Factory, 34 agentClientFactory bihttpagent.AgentClientFactory, 35 blobstoreFactory biblobstore.Factory, 36 deploymentManagerFactory bidepl.ManagerFactory, 37 deploymentManifestPath string, 38 deploymentVars boshtpl.Variables, 39 deploymentOp patch.Op, 40 cpiInstaller bicpirel.CpiInstaller, 41 cpiUninstaller biinstall.Uninstaller, 42 releaseFetcher boshinst.ReleaseFetcher, 43 releaseSetAndInstallationManifestParser ReleaseSetAndInstallationManifestParser, 44 tempRootConfigurator TempRootConfigurator, 45 targetProvider biinstall.TargetProvider, 46) DeploymentDeleter { 47 return &deploymentDeleter{ 48 ui: ui, 49 logTag: logTag, 50 logger: logger, 51 deploymentStateService: deploymentStateService, 52 releaseManager: releaseManager, 53 cloudFactory: cloudFactory, 54 agentClientFactory: agentClientFactory, 55 blobstoreFactory: blobstoreFactory, 56 deploymentManagerFactory: deploymentManagerFactory, 57 deploymentManifestPath: deploymentManifestPath, 58 deploymentVars: deploymentVars, 59 deploymentOp: deploymentOp, 60 cpiInstaller: cpiInstaller, 61 cpiUninstaller: cpiUninstaller, 62 releaseFetcher: releaseFetcher, 63 releaseSetAndInstallationManifestParser: releaseSetAndInstallationManifestParser, 64 tempRootConfigurator: tempRootConfigurator, 65 targetProvider: targetProvider, 66 } 67} 68 69type deploymentDeleter struct { 70 ui biui.UI 71 logTag string 72 logger boshlog.Logger 73 deploymentStateService biconfig.DeploymentStateService 74 releaseManager boshinst.ReleaseManager 75 cloudFactory bicloud.Factory 76 agentClientFactory bihttpagent.AgentClientFactory 77 blobstoreFactory biblobstore.Factory 78 deploymentManagerFactory bidepl.ManagerFactory 79 deploymentManifestPath string 80 deploymentVars boshtpl.Variables 81 deploymentOp patch.Op 82 cpiInstaller bicpirel.CpiInstaller 83 cpiUninstaller biinstall.Uninstaller 84 releaseFetcher boshinst.ReleaseFetcher 85 releaseSetAndInstallationManifestParser ReleaseSetAndInstallationManifestParser 86 tempRootConfigurator TempRootConfigurator 87 targetProvider biinstall.TargetProvider 88} 89 90func (c *deploymentDeleter) DeleteDeployment(skipDrain bool, stage biui.Stage) (err error) { 91 c.ui.BeginLinef("Deployment state: '%s'\n", c.deploymentStateService.Path()) 92 93 if !c.deploymentStateService.Exists() { 94 c.ui.BeginLinef("No deployment state file found.\n") 95 return nil 96 } 97 98 deploymentState, err := c.deploymentStateService.Load() 99 if err != nil { 100 return bosherr.WrapError(err, "Loading deployment state") 101 } 102 103 target, err := c.targetProvider.NewTarget() 104 if err != nil { 105 return bosherr.WrapError(err, "Determining installation target") 106 } 107 108 err = c.tempRootConfigurator.PrepareAndSetTempRoot(target.TmpPath(), c.logger) 109 if err != nil { 110 return bosherr.WrapError(err, "Setting temp root") 111 } 112 113 defer func() { 114 err := c.releaseManager.DeleteAll() 115 if err != nil { 116 c.logger.Warn(c.logTag, "Deleting all extracted releases: %s", err.Error()) 117 } 118 }() 119 120 var installationManifest biinstallmanifest.Manifest 121 122 err = stage.PerformComplex("validating", func(stage biui.Stage) error { 123 var releaseSetManifest birelsetmanifest.Manifest 124 releaseSetManifest, installationManifest, err = c.releaseSetAndInstallationManifestParser.ReleaseSetAndInstallationManifest(c.deploymentManifestPath, c.deploymentVars, c.deploymentOp) 125 if err != nil { 126 return err 127 } 128 129 cpiReleaseName := installationManifest.Template.Release 130 cpiReleaseRef, found := releaseSetManifest.FindByName(cpiReleaseName) 131 if !found { 132 return bosherr.Errorf("installation release '%s' must refer to a release in releases", cpiReleaseName) 133 } 134 135 err = c.releaseFetcher.DownloadAndExtract(cpiReleaseRef, stage) 136 if err != nil { 137 return err 138 } 139 140 err = c.cpiInstaller.ValidateCpiRelease(installationManifest, stage) 141 142 return err 143 }) 144 if err != nil { 145 return err 146 } 147 148 err = c.cpiInstaller.WithInstalledCpiRelease(installationManifest, target, stage, func(localCpiInstallation biinstall.Installation) error { 149 return localCpiInstallation.WithRunningRegistry(c.logger, stage, func() error { 150 err = c.findAndDeleteDeployment(skipDrain, stage, localCpiInstallation, deploymentState.DirectorID, installationManifest.Mbus, installationManifest.Cert.CA) 151 152 if err != nil { 153 return err 154 } 155 156 return stage.Perform("Uninstalling local artifacts for CPI and deployment", func() error { 157 err := c.cpiUninstaller.Uninstall(localCpiInstallation.Target()) 158 if err != nil { 159 return err 160 } 161 162 return c.deploymentStateService.Cleanup() 163 }) 164 }) 165 }) 166 167 return err 168} 169 170func (c *deploymentDeleter) findAndDeleteDeployment(skipDrain bool, stage biui.Stage, installation biinstall.Installation, directorID, installationMbus, caCert string) error { 171 deploymentManager, err := c.deploymentManager(installation, directorID, installationMbus, caCert) 172 if err != nil { 173 return err 174 } 175 176 err = c.findCurrentDeploymentAndDelete(skipDrain, stage, deploymentManager) 177 if err != nil { 178 return bosherr.WrapError(err, "Deleting deployment") 179 } 180 181 return deploymentManager.Cleanup(stage) 182} 183 184func (c *deploymentDeleter) findCurrentDeploymentAndDelete(skipDrain bool, stage biui.Stage, deploymentManager bidepl.Manager) error { 185 c.logger.Debug(c.logTag, "Finding current deployment...") 186 187 deployment, found, err := deploymentManager.FindCurrent() 188 if err != nil { 189 return bosherr.WrapError(err, "Finding current deployment") 190 } 191 192 return stage.PerformComplex("deleting deployment", func(deleteStage biui.Stage) error { 193 if !found { 194 //TODO: skip? would require adding skip support to PerformComplex 195 c.logger.Debug(c.logTag, "No current deployment found...") 196 return nil 197 } 198 199 return deployment.Delete(skipDrain, deleteStage) 200 }) 201} 202 203func (c *deploymentDeleter) deploymentManager(installation biinstall.Installation, directorID, installationMbus, caCert string) (bidepl.Manager, error) { 204 c.logger.Debug(c.logTag, "Creating cloud client...") 205 206 stemcellApiVersion := 1 207 deploymentStateService, err := c.deploymentStateService.Load() 208 if err == nil { 209 for _, s := range deploymentStateService.Stemcells { 210 if deploymentStateService.CurrentStemcellID == s.ID { 211 stemcellApiVersion = s.ApiVersion 212 break 213 } 214 } 215 } 216 217 cloud, err := c.cloudFactory.NewCloud(installation, directorID, stemcellApiVersion) 218 if err != nil { 219 return nil, bosherr.WrapError(err, "Creating CPI client from CPI installation") 220 } 221 222 c.logger.Debug(c.logTag, "Creating agent client...") 223 224 agentClient, _ := c.agentClientFactory.NewAgentClient(directorID, installationMbus, caCert) 225 226 c.logger.Debug(c.logTag, "Creating blobstore client...") 227 228 blobstore, err := c.blobstoreFactory.Create(installationMbus, bihttpclient.CreateDefaultClientInsecureSkipVerify()) 229 if err != nil { 230 return nil, bosherr.WrapError(err, "Creating blobstore client") 231 } 232 233 c.logger.Debug(c.logTag, "Creating deployment manager...") 234 235 return c.deploymentManagerFactory.NewManager(cloud, agentClient, blobstore), nil 236} 237