job.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. package commands
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "github.com/porter-dev/porter/cli/cmd/config"
  7. v2 "github.com/porter-dev/porter/cli/cmd/v2"
  8. "github.com/fatih/color"
  9. api "github.com/porter-dev/porter/api/client"
  10. "github.com/porter-dev/porter/api/types"
  11. "github.com/porter-dev/porter/cli/cmd/deploy"
  12. "github.com/porter-dev/porter/cli/cmd/deploy/wait"
  13. "github.com/spf13/cobra"
  14. )
  15. var imageRepoURI string
  16. func registerCommand_Job(cliConf config.CLIConfig) *cobra.Command {
  17. jobCmd := &cobra.Command{
  18. Use: "job",
  19. }
  20. batchImageUpdateCmd := &cobra.Command{
  21. Use: "update-images",
  22. Short: "Updates the image tag of all jobs in a namespace which use a specific image.",
  23. Long: fmt.Sprintf(`
  24. %s
  25. Updates the image tag of all jobs in a namespace which use a specific image. Note that for all
  26. jobs with version <= v0.4.0, this will trigger a new run of a manual job. However, for versions
  27. >= v0.5.0, this will not create a new run of the job.
  28. Example commands:
  29. %s
  30. This command is namespace-scoped and uses the default namespace. To specify a different namespace,
  31. use the --namespace flag:
  32. %s
  33. `,
  34. color.New(color.FgBlue, color.Bold).Sprintf("Help for \"porter job update-images\":"),
  35. color.New(color.FgGreen, color.Bold).Sprintf("porter job update-images --image-repo-uri my-image.registry.io --tag newtag"),
  36. color.New(color.FgGreen, color.Bold).Sprintf("porter job update-images --namespace custom-namespace --image-repo-uri my-image.registry.io --tag newtag"),
  37. ),
  38. Run: func(cmd *cobra.Command, args []string) {
  39. err := checkLoginAndRunWithConfig(cmd, cliConf, args, batchImageUpdate)
  40. if err != nil {
  41. os.Exit(1)
  42. }
  43. },
  44. }
  45. waitCmd := &cobra.Command{
  46. Use: "wait",
  47. Short: "Waits for a job to complete.",
  48. Long: fmt.Sprintf(`
  49. %s
  50. Waits for a job with a given name and namespace to complete a run. If the job completes successfully,
  51. this command exits with exit code 0. Otherwise, this command exits with exit code 1.
  52. Example commands:
  53. %s
  54. This command is namespace-scoped and uses the default namespace. To specify a different namespace,
  55. use the --namespace flag:
  56. %s
  57. `,
  58. color.New(color.FgBlue, color.Bold).Sprintf("Help for \"porter job wait\":"),
  59. color.New(color.FgGreen, color.Bold).Sprintf("porter job wait --name job-example"),
  60. color.New(color.FgGreen, color.Bold).Sprintf("porter job wait --name job-example --namespace custom-namespace"),
  61. ),
  62. Run: func(cmd *cobra.Command, args []string) {
  63. err := checkLoginAndRunWithConfig(cmd, cliConf, args, waitForJob)
  64. if err != nil {
  65. os.Exit(1)
  66. }
  67. },
  68. }
  69. runJobCmd := &cobra.Command{
  70. Use: "run",
  71. Short: "Manually runs a job and waits for it to complete.",
  72. Long: fmt.Sprintf(`
  73. %s
  74. Manually runs a job and waits for it to complete a run. If the job completes successfully,
  75. this command exits with exit code 0. Otherwise, this command exits with exit code 1.
  76. Example commands:
  77. %s
  78. This command is namespace-scoped and uses the default namespace. To specify a different namespace,
  79. use the --namespace flag:
  80. %s
  81. `,
  82. color.New(color.FgBlue, color.Bold).Sprintf("Help for \"porter job run\":"),
  83. color.New(color.FgGreen, color.Bold).Sprintf("porter job run --name job-example"),
  84. color.New(color.FgGreen, color.Bold).Sprintf("porter job run --name job-example --namespace custom-namespace"),
  85. ),
  86. Run: func(cmd *cobra.Command, args []string) {
  87. err := checkLoginAndRunWithConfig(cmd, cliConf, args, runJob)
  88. if err != nil {
  89. os.Exit(1)
  90. }
  91. },
  92. }
  93. jobCmd.AddCommand(batchImageUpdateCmd)
  94. jobCmd.AddCommand(waitCmd)
  95. jobCmd.AddCommand(runJobCmd)
  96. batchImageUpdateCmd.PersistentFlags().StringVar(
  97. &tag,
  98. "tag",
  99. "",
  100. "The new image tag to use.",
  101. )
  102. batchImageUpdateCmd.PersistentFlags().StringVar(
  103. &namespace,
  104. "namespace",
  105. "",
  106. "The namespace of the jobs.",
  107. )
  108. batchImageUpdateCmd.PersistentFlags().StringVarP(
  109. &imageRepoURI,
  110. "image-repo-uri",
  111. "i",
  112. "",
  113. "Image repo uri",
  114. )
  115. batchImageUpdateCmd.MarkPersistentFlagRequired("image-repo-uri")
  116. batchImageUpdateCmd.MarkPersistentFlagRequired("tag")
  117. waitCmd.PersistentFlags().StringVar(
  118. &namespace,
  119. "namespace",
  120. "",
  121. "The namespace of the jobs.",
  122. )
  123. waitCmd.PersistentFlags().StringVar(
  124. &name,
  125. "name",
  126. "",
  127. "The name of the jobs.",
  128. )
  129. waitCmd.MarkPersistentFlagRequired("name")
  130. runJobCmd.PersistentFlags().StringVar(
  131. &namespace,
  132. "namespace",
  133. "",
  134. "The namespace of the job.",
  135. )
  136. runJobCmd.PersistentFlags().StringVar(
  137. &name,
  138. "name",
  139. "",
  140. "The name of the job.",
  141. )
  142. runJobCmd.MarkPersistentFlagRequired("name")
  143. return jobCmd
  144. }
  145. func batchImageUpdate(ctx context.Context, _ *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, featureFlags config.FeatureFlags, args []string) error {
  146. if featureFlags.ValidateApplyV2Enabled {
  147. err := v2.BatchImageUpdate(ctx)
  148. if err != nil {
  149. return err
  150. }
  151. return nil
  152. }
  153. color.New(color.FgGreen).Println("Updating all jobs which use the image:", imageRepoURI)
  154. return client.UpdateBatchImage(
  155. ctx,
  156. cliConf.Project,
  157. cliConf.Cluster,
  158. namespace,
  159. &types.UpdateImageBatchRequest{
  160. ImageRepoURI: imageRepoURI,
  161. Tag: tag,
  162. },
  163. )
  164. }
  165. // waits for a job with a given name/namespace
  166. func waitForJob(ctx context.Context, _ *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, featureFlags config.FeatureFlags, args []string) error {
  167. if featureFlags.ValidateApplyV2Enabled {
  168. err := v2.WaitForJob(ctx)
  169. if err != nil {
  170. return err
  171. }
  172. return nil
  173. }
  174. return wait.WaitForJob(ctx, client, &wait.WaitOpts{
  175. ProjectID: cliConf.Project,
  176. ClusterID: cliConf.Cluster,
  177. Namespace: namespace,
  178. Name: name,
  179. })
  180. }
  181. func runJob(ctx context.Context, authRes *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, featureFlags config.FeatureFlags, args []string) error {
  182. if featureFlags.ValidateApplyV2Enabled {
  183. err := v2.RunJob(ctx)
  184. if err != nil {
  185. return err
  186. }
  187. return nil
  188. }
  189. color.New(color.FgGreen).Printf("Running job %s in namespace %s\n", name, namespace)
  190. waitForSuccessfulDeploy = true
  191. updateAgent := &deploy.DeployAgent{
  192. App: name,
  193. Client: client,
  194. Opts: &deploy.DeployOpts{
  195. SharedOpts: &deploy.SharedOpts{
  196. ProjectID: cliConf.Project,
  197. ClusterID: cliConf.Cluster,
  198. Namespace: namespace,
  199. },
  200. },
  201. }
  202. err := updateAgent.UpdateImageAndValues(
  203. ctx,
  204. map[string]interface{}{
  205. "paused": false,
  206. })
  207. if err != nil {
  208. return fmt.Errorf("error running job: %w", err)
  209. }
  210. err = waitForJob(ctx, authRes, client, cliConf, featureFlags, args)
  211. if err != nil {
  212. return fmt.Errorf("error waiting for job to complete: %w", err)
  213. }
  214. return nil
  215. }