fix: container name display and deployment retry after removal in survey prompt
- commit
- 26223e38de9da57e75659422b58352d7362b7b9c
- author
- Brice · · 2024-11-05 14:09 UTC
- parent
- b5fdca8
- signature
- unsigned
- refs
- tag: v0.1.14
2 files · +25 -21
M internal/cli/cmd/deploy.go +13 -12
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | package cmd | |
| 4 | 4 | ||
| 5 | 5 | import ( | |
| 6 | + | "bytes" | |
| 6 | 7 | "encoding/json" | |
| 7 | 8 | "errors" | |
| 8 | 9 | "fmt" | |
| @@ -115,6 +116,12 @@ func exportDockerImage(imageName string) (io.ReadCloser, int64, error) { | |||
| 115 | 116 | } | |
| 116 | 117 | ||
| 117 | 118 | func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error { | |
| 119 | + | // Convert reader to bytes for reuse | |
| 120 | + | imageData, err := io.ReadAll(reader) | |
| 121 | + | if err != nil { | |
| 122 | + | return fmt.Errorf("failed to read image data: %w", err) | |
| 123 | + | } | |
| 124 | + | ||
| 118 | 125 | log.Info("Attempting to deploy...", | |
| 119 | 126 | "image", imageName, | |
| 120 | 127 | "port", port, | |
| @@ -122,13 +129,14 @@ func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain str | |||
| 122 | 129 | ) | |
| 123 | 130 | ||
| 124 | 131 | for { | |
| 132 | + | // Create new reader from bytes for each attempt | |
| 125 | 133 | reqPayload := common.RequestPayload{ | |
| 126 | 134 | Type: "deploy", | |
| 127 | 135 | Payload: common.DeployPayload{ | |
| 128 | 136 | Port: port, | |
| 129 | 137 | TargetDomain: targetDomain, | |
| 130 | 138 | ImageName: imageName, | |
| 131 | - | Data: io.NopCloser(reader), | |
| 139 | + | Data: io.NopCloser(bytes.NewReader(imageData)), | |
| 132 | 140 | }, | |
| 133 | 141 | } | |
| 134 | 142 | ||
| @@ -138,28 +146,21 @@ func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain str | |||
| 138 | 146 | if errors.As(err, &deployErr) { | |
| 139 | 147 | var deployResponse common.DeployResponse | |
| 140 | 148 | if jsonErr := json.Unmarshal([]byte(deployErr.RawResponse), &deployResponse); jsonErr == nil { | |
| 141 | - | // Handle existing container case | |
| 142 | 149 | if deployErr.StatusCode == http.StatusConflict && deployResponse.ContainerID != "" { | |
| 143 | 150 | if err := handler.HandleExistingContainer(a, &deployResponse); err != nil { | |
| 144 | 151 | if strings.Contains(err.Error(), "cancelled by user") { | |
| 145 | 152 | log.Warn("Deployment cancelled by user") | |
| 146 | - | } else { | |
| 147 | - | log.Error("Failed to handle existing container", "error", err) | |
| 153 | + | return nil | |
| 148 | 154 | } | |
| 149 | - | return nil | |
| 155 | + | log.Error("Failed to handle existing container", "error", err) | |
| 156 | + | return err | |
| 150 | 157 | } | |
| 151 | 158 | log.Info("Retrying deployment...") | |
| 152 | 159 | continue // Retry deployment | |
| 153 | 160 | } | |
| 154 | - | ||
| 155 | - | log.Error("Deployment failed", | |
| 156 | - | "error", deployErr.Message, | |
| 157 | - | "status_code", deployErr.StatusCode, | |
| 158 | - | "container_id", deployResponse.ContainerID, | |
| 159 | - | ) | |
| 160 | 161 | } | |
| 161 | 162 | } | |
| 162 | - | return nil | |
| 163 | + | return err | |
| 163 | 164 | } | |
| 164 | 165 | ||
| 165 | 166 | var deployResponse common.DeployResponse | |
| @@ -3,6 +3,7 @@ | |||||
| 3 | package cmd | 3 | package cmd | ||
| 4 | 4 | ||||
| 5 | import ( | 5 | import ( | ||
| 6 | + | "bytes" | |||
| 6 | "encoding/json" | 7 | "encoding/json" | ||
| 7 | "errors" | 8 | "errors" | ||
| 8 | "fmt" | 9 | "fmt" | ||
| @@ -115,6 +116,12 @@ func exportDockerImage(imageName string) (io.ReadCloser, int64, error) { | |||||
| 115 | } | 116 | } | ||
| 116 | 117 | ||||
| 117 | func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error { | 118 | func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error { | ||
| 119 | + | // Convert reader to bytes for reuse | |||
| 120 | + | imageData, err := io.ReadAll(reader) | |||
| 121 | + | if err != nil { | |||
| 122 | + | return fmt.Errorf("failed to read image data: %w", err) | |||
| 123 | + | } | |||
| 124 | + | ||||
| 118 | log.Info("Attempting to deploy...", | 125 | log.Info("Attempting to deploy...", | ||
| 119 | "image", imageName, | 126 | "image", imageName, | ||
| 120 | "port", port, | 127 | "port", port, | ||
| @@ -122,13 +129,14 @@ func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain str | |||||
| 122 | ) | 129 | ) | ||
| 123 | 130 | ||||
| 124 | for { | 131 | for { | ||
| 132 | + | // Create new reader from bytes for each attempt | |||
| 125 | reqPayload := common.RequestPayload{ | 133 | reqPayload := common.RequestPayload{ | ||
| 126 | Type: "deploy", | 134 | Type: "deploy", | ||
| 127 | Payload: common.DeployPayload{ | 135 | Payload: common.DeployPayload{ | ||
| 128 | Port: port, | 136 | Port: port, | ||
| 129 | TargetDomain: targetDomain, | 137 | TargetDomain: targetDomain, | ||
| 130 | ImageName: imageName, | 138 | ImageName: imageName, | ||
| 131 | - | Data: io.NopCloser(reader), | 139 | + | Data: io.NopCloser(bytes.NewReader(imageData)), |
| 132 | }, | 140 | }, | ||
| 133 | } | 141 | } | ||
| 134 | 142 | ||||
| @@ -138,28 +146,21 @@ func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain str | |||||
| 138 | if errors.As(err, &deployErr) { | 146 | if errors.As(err, &deployErr) { | ||
| 139 | var deployResponse common.DeployResponse | 147 | var deployResponse common.DeployResponse | ||
| 140 | if jsonErr := json.Unmarshal([]byte(deployErr.RawResponse), &deployResponse); jsonErr == nil { | 148 | if jsonErr := json.Unmarshal([]byte(deployErr.RawResponse), &deployResponse); jsonErr == nil { | ||
| 141 | - | // Handle existing container case | |||
| 142 | if deployErr.StatusCode == http.StatusConflict && deployResponse.ContainerID != "" { | 149 | if deployErr.StatusCode == http.StatusConflict && deployResponse.ContainerID != "" { | ||
| 143 | if err := handler.HandleExistingContainer(a, &deployResponse); err != nil { | 150 | if err := handler.HandleExistingContainer(a, &deployResponse); err != nil { | ||
| 144 | if strings.Contains(err.Error(), "cancelled by user") { | 151 | if strings.Contains(err.Error(), "cancelled by user") { | ||
| 145 | log.Warn("Deployment cancelled by user") | 152 | log.Warn("Deployment cancelled by user") | ||
| 146 | - | } else { | 153 | + | return nil |
| 147 | - | log.Error("Failed to handle existing container", "error", err) | |||
| 148 | } | 154 | } | ||
| 149 | - | return nil | 155 | + | log.Error("Failed to handle existing container", "error", err) |
| 156 | + | return err | |||
| 150 | } | 157 | } | ||
| 151 | log.Info("Retrying deployment...") | 158 | log.Info("Retrying deployment...") | ||
| 152 | continue // Retry deployment | 159 | continue // Retry deployment | ||
| 153 | } | 160 | } | ||
| 154 | - | ||||
| 155 | - | log.Error("Deployment failed", | |||
| 156 | - | "error", deployErr.Message, | |||
| 157 | - | "status_code", deployErr.StatusCode, | |||
| 158 | - | "container_id", deployResponse.ContainerID, | |||
| 159 | - | ) | |||
| 160 | } | 161 | } | ||
| 161 | } | 162 | } | ||
| 162 | - | return nil | 163 | + | return err |
| 163 | } | 164 | } | ||
| 164 | 165 | ||||
| 165 | var deployResponse common.DeployResponse | 166 | var deployResponse common.DeployResponse | ||
M internal/httpserve/handlers/cli_endpoints.go +12 -9
| @@ -264,21 +264,24 @@ func PostDeploy(c echo.Context, a *server.App) error { | |||
| 264 | 264 | if err != nil { | |
| 265 | 265 | if strings.Contains(err.Error(), "is already in use") { | |
| 266 | 266 | log.Warn("Container already exists", "error", err) | |
| 267 | - | extractedID := extractContainerID(err.Error()) | |
| 268 | - | log.Info("Extracted container ID", "containerID", extractedID) | |
| 267 | + | existingContainerID := extractContainerID(err.Error()) | |
| 268 | + | existingContainerName, _ := docker.GetContainerName(existingContainerID) | |
| 269 | + | // Remove the / from the container name | |
| 270 | + | existingContainerName = strings.TrimLeft(existingContainerName, "/") | |
| 269 | 271 | ||
| 270 | - | if extractedID == "" { | |
| 271 | - | log.Error("Failed to extract container ID from error message") | |
| 272 | + | if existingContainerID == "" || existingContainerName == "" { | |
| 273 | + | log.Error("Failed to extract container ID or Name from error message") | |
| 272 | 274 | return sendJSONResponse(c, http.StatusConflict, DeployResponse{ | |
| 273 | 275 | Success: false, | |
| 274 | - | Message: "A container with this name already exists, but we couldn't extract its ID.", | |
| 276 | + | Message: "A container for this deploy already exists but could not be identified.", | |
| 275 | 277 | }) | |
| 276 | 278 | } | |
| 277 | 279 | ||
| 278 | 280 | return sendJSONResponse(c, http.StatusConflict, DeployResponse{ | |
| 279 | - | Success: false, | |
| 280 | - | Message: "A container for this deploy already exists.", | |
| 281 | - | ContainerID: extractedID, | |
| 281 | + | Success: false, | |
| 282 | + | Message: "A container for this deploy already exists.", | |
| 283 | + | ContainerID: existingContainerID, | |
| 284 | + | ContainerName: existingContainerName, | |
| 282 | 285 | }) | |
| 283 | 286 | } | |
| 284 | 287 | log.Error("Failed to create or start container", "error", err) | |
| @@ -305,7 +308,7 @@ func PostDeploy(c echo.Context, a *server.App) error { | |||
| 305 | 308 | return sendJSONResponse(c, http.StatusOK, response) | |
| 306 | 309 | } | |
| 307 | 310 | ||
| 308 | - | // is already in use by 08433f639cb1c01254d43f234360bfa793aa8c33b29e8de8ce42b0706c0090ba. example | |
| 311 | + | // extractContainerID extracts the container ID from the error message | |
| 309 | 312 | func extractContainerID(errorMessage string) string { | |
| 310 | 313 | re := regexp.MustCompile(`by\s+([0-9a-f]+)\.`) | |
| 311 | 314 | match := re.FindStringSubmatch(errorMessage) | |
| @@ -264,21 +264,24 @@ func PostDeploy(c echo.Context, a *server.App) error { | |||||
| 264 | if err != nil { | 264 | if err != nil { | ||
| 265 | if strings.Contains(err.Error(), "is already in use") { | 265 | if strings.Contains(err.Error(), "is already in use") { | ||
| 266 | log.Warn("Container already exists", "error", err) | 266 | log.Warn("Container already exists", "error", err) | ||
| 267 | - | extractedID := extractContainerID(err.Error()) | 267 | + | existingContainerID := extractContainerID(err.Error()) |
| 268 | - | log.Info("Extracted container ID", "containerID", extractedID) | 268 | + | existingContainerName, _ := docker.GetContainerName(existingContainerID) |
| 269 | + | // Remove the / from the container name | |||
| 270 | + | existingContainerName = strings.TrimLeft(existingContainerName, "/") | |||
| 269 | 271 | ||||
| 270 | - | if extractedID == "" { | 272 | + | if existingContainerID == "" || existingContainerName == "" { |
| 271 | - | log.Error("Failed to extract container ID from error message") | 273 | + | log.Error("Failed to extract container ID or Name from error message") |
| 272 | return sendJSONResponse(c, http.StatusConflict, DeployResponse{ | 274 | return sendJSONResponse(c, http.StatusConflict, DeployResponse{ | ||
| 273 | Success: false, | 275 | Success: false, | ||
| 274 | - | Message: "A container with this name already exists, but we couldn't extract its ID.", | 276 | + | Message: "A container for this deploy already exists but could not be identified.", |
| 275 | }) | 277 | }) | ||
| 276 | } | 278 | } | ||
| 277 | 279 | ||||
| 278 | return sendJSONResponse(c, http.StatusConflict, DeployResponse{ | 280 | return sendJSONResponse(c, http.StatusConflict, DeployResponse{ | ||
| 279 | - | Success: false, | 281 | + | Success: false, |
| 280 | - | Message: "A container for this deploy already exists.", | 282 | + | Message: "A container for this deploy already exists.", |
| 281 | - | ContainerID: extractedID, | 283 | + | ContainerID: existingContainerID, |
| 284 | + | ContainerName: existingContainerName, | |||
| 282 | }) | 285 | }) | ||
| 283 | } | 286 | } | ||
| 284 | log.Error("Failed to create or start container", "error", err) | 287 | log.Error("Failed to create or start container", "error", err) | ||
| @@ -305,7 +308,7 @@ func PostDeploy(c echo.Context, a *server.App) error { | |||||
| 305 | return sendJSONResponse(c, http.StatusOK, response) | 308 | return sendJSONResponse(c, http.StatusOK, response) | ||
| 306 | } | 309 | } | ||
| 307 | 310 | ||||
| 308 | - | // is already in use by 08433f639cb1c01254d43f234360bfa793aa8c33b29e8de8ce42b0706c0090ba. example | 311 | + | // extractContainerID extracts the container ID from the error message |
| 309 | func extractContainerID(errorMessage string) string { | 312 | func extractContainerID(errorMessage string) string { | ||
| 310 | re := regexp.MustCompile(`by\s+([0-9a-f]+)\.`) | 313 | re := regexp.MustCompile(`by\s+([0-9a-f]+)\.`) | ||
| 311 | match := re.FindStringSubmatch(errorMessage) | 314 | match := re.FindStringSubmatch(errorMessage) | ||