github.com/sleungcy-sap/cli@v7.1.0+incompatible/cf/commands/application/copy_source.go (about) 1 package application 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 "code.cloudfoundry.org/cli/cf/api/applications" 9 "code.cloudfoundry.org/cli/cf/api/authentication" 10 "code.cloudfoundry.org/cli/cf/api/copyapplicationsource" 11 "code.cloudfoundry.org/cli/cf/api/organizations" 12 "code.cloudfoundry.org/cli/cf/api/spaces" 13 "code.cloudfoundry.org/cli/cf/commandregistry" 14 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 15 "code.cloudfoundry.org/cli/cf/flags" 16 . "code.cloudfoundry.org/cli/cf/i18n" 17 "code.cloudfoundry.org/cli/cf/models" 18 "code.cloudfoundry.org/cli/cf/requirements" 19 "code.cloudfoundry.org/cli/cf/terminal" 20 ) 21 22 type CopySource struct { 23 ui terminal.UI 24 config coreconfig.Reader 25 authRepo authentication.Repository 26 appRepo applications.Repository 27 orgRepo organizations.OrganizationRepository 28 spaceRepo spaces.SpaceRepository 29 copyAppSourceRepo copyapplicationsource.Repository 30 appRestart Restarter 31 } 32 33 func init() { 34 commandregistry.Register(&CopySource{}) 35 } 36 37 func (cmd *CopySource) MetaData() commandregistry.CommandMetadata { 38 fs := make(map[string]flags.FlagSet) 39 fs["no-restart"] = &flags.BoolFlag{Name: "no-restart", Usage: T("Override restart of the application in target environment after copy-source completes")} 40 fs["o"] = &flags.StringFlag{ShortName: "o", Usage: T("Org that contains the target application")} 41 fs["s"] = &flags.StringFlag{ShortName: "s", Usage: T("Space that contains the target application")} 42 43 return commandregistry.CommandMetadata{ 44 Name: "copy-source", 45 Description: T("Copies the source code of an application to another existing application (and restarts that application)"), 46 Usage: []string{ 47 T(" CF_NAME copy-source SOURCE-APP TARGET-APP [-s TARGET-SPACE [-o TARGET-ORG]] [--no-restart]\n"), 48 }, 49 Flags: fs, 50 } 51 } 52 53 func (cmd *CopySource) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) { 54 usageReq := requirementsFactory.NewUsageRequirement(commandregistry.CLICommandUsagePresenter(cmd), 55 T("Requires SOURCE-APP TARGET-APP as arguments"), 56 func() bool { 57 return len(fc.Args()) != 2 58 }, 59 ) 60 61 reqs := []requirements.Requirement{ 62 usageReq, 63 requirementsFactory.NewLoginRequirement(), 64 requirementsFactory.NewTargetedSpaceRequirement(), 65 } 66 67 return reqs, nil 68 } 69 70 func (cmd *CopySource) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command { 71 cmd.ui = deps.UI 72 cmd.config = deps.Config 73 cmd.authRepo = deps.RepoLocator.GetAuthenticationRepository() 74 cmd.appRepo = deps.RepoLocator.GetApplicationRepository() 75 cmd.orgRepo = deps.RepoLocator.GetOrganizationRepository() 76 cmd.spaceRepo = deps.RepoLocator.GetSpaceRepository() 77 cmd.copyAppSourceRepo = deps.RepoLocator.GetCopyApplicationSourceRepository() 78 79 //get command from registry for dependency 80 commandDep := commandregistry.Commands.FindCommand("restart") 81 commandDep = commandDep.SetDependency(deps, false) 82 cmd.appRestart = commandDep.(Restarter) 83 84 return cmd 85 } 86 87 func (cmd *CopySource) Execute(c flags.FlagContext) error { 88 sourceAppName := c.Args()[0] 89 targetAppName := c.Args()[1] 90 91 targetOrg := c.String("o") 92 targetSpace := c.String("s") 93 94 if targetOrg != "" && targetSpace == "" { 95 return errors.New(T("Please provide the space within the organization containing the target application")) 96 } 97 98 _, err := cmd.authRepo.RefreshAuthToken() 99 if err != nil { 100 return err 101 } 102 103 sourceApp, err := cmd.appRepo.Read(sourceAppName) 104 if err != nil { 105 return err 106 } 107 108 var targetOrgName, targetSpaceName, spaceGUID, copyStr string 109 var spaceFields models.SpaceFields 110 if targetOrg != "" && targetSpace != "" { 111 spaceFields, err = cmd.findSpaceFields(targetOrg, targetSpace) 112 spaceGUID = spaceFields.GUID 113 if err != nil { 114 return err 115 } 116 117 targetOrgName = targetOrg 118 targetSpaceName = spaceFields.Name 119 } else if targetSpace != "" { 120 var space models.Space 121 space, err = cmd.spaceRepo.FindByName(targetSpace) 122 if err != nil { 123 return err 124 } 125 spaceGUID = space.GUID 126 targetOrgName = cmd.config.OrganizationFields().Name 127 targetSpaceName = space.Name 128 } else { 129 spaceGUID = cmd.config.SpaceFields().GUID 130 targetOrgName = cmd.config.OrganizationFields().Name 131 targetSpaceName = cmd.config.SpaceFields().Name 132 } 133 134 copyStr = buildCopyString(sourceAppName, targetAppName, targetOrgName, targetSpaceName, cmd.config.Username()) 135 136 targetApp, err := cmd.appRepo.ReadFromSpace(targetAppName, spaceGUID) 137 if err != nil { 138 return err 139 } 140 141 cmd.ui.Say(copyStr) 142 cmd.ui.Say(T("Note: this may take some time")) 143 cmd.ui.Say("") 144 145 err = cmd.copyAppSourceRepo.CopyApplication(sourceApp.GUID, targetApp.GUID) 146 if err != nil { 147 return err 148 } 149 150 if !c.Bool("no-restart") { 151 cmd.appRestart.ApplicationRestart(targetApp, targetOrgName, targetSpaceName) 152 } 153 154 cmd.ui.Ok() 155 return nil 156 } 157 158 func (cmd *CopySource) findSpaceFields(targetOrg, targetSpace string) (models.SpaceFields, error) { 159 org, err := cmd.orgRepo.FindByName(targetOrg) 160 if err != nil { 161 return models.SpaceFields{}, err 162 } 163 164 var spaceFields models.SpaceFields 165 var foundSpace bool 166 for _, s := range org.Spaces { 167 if strings.EqualFold(s.Name, targetSpace) { 168 spaceFields = s 169 foundSpace = true 170 } 171 } 172 173 if !foundSpace { 174 return models.SpaceFields{}, fmt.Errorf(T("Could not find space {{.Space}} in organization {{.Org}}", 175 map[string]interface{}{ 176 "Space": terminal.EntityNameColor(targetSpace), 177 "Org": terminal.EntityNameColor(targetOrg), 178 }, 179 )) 180 } 181 182 return spaceFields, nil 183 } 184 185 func buildCopyString(sourceAppName, targetAppName, targetOrgName, targetSpaceName, username string) string { 186 return fmt.Sprintf(T("Copying source from app {{.SourceApp}} to target app {{.TargetApp}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", 187 map[string]interface{}{ 188 "SourceApp": terminal.EntityNameColor(sourceAppName), 189 "TargetApp": terminal.EntityNameColor(targetAppName), 190 "OrgName": terminal.EntityNameColor(targetOrgName), 191 "SpaceName": terminal.EntityNameColor(targetSpaceName), 192 "Username": terminal.EntityNameColor(username), 193 }, 194 )) 195 196 }