package cmd import ( "encoding/base64" "encoding/json" "fmt" "gitea.stuzer.link/stuzer05/docker-registry-manager/internal/app" "net/http" "strings" ) func RegistryRm(app *app.App, imageArg string) { parts := strings.SplitN(imageArg, ":", 2) imageName := parts[0] tag := "" if len(parts) > 1 { tag = parts[1] } if tag == "" { deleteImageByName(app, imageName) } else { deleteImageByTag(app, imageName, tag) } } func deleteImageByName(app *app.App, imageName string) { type tagList struct { Tags []string `json:"tags"` } resp, err := http.Get(fmt.Sprintf("%s/v2/%s/tags/list", app.RegistryURL, imageName)) if err != nil { fmt.Println("Error fetching tags:", err) return } defer resp.Body.Close() if resp.StatusCode == http.StatusNotFound { fmt.Printf("Error: Image '%s' not found in the registry.\n", imageName) return } var tl tagList if err := json.NewDecoder(resp.Body).Decode(&tl); err != nil { fmt.Println("Error decoding response:", err) return } for _, tag := range tl.Tags { deleteImageByTag(app, imageName, tag) } } func deleteImageByTag(app *app.App, imageName, tag string) { client := &http.Client{} req, err := http.NewRequest("HEAD", fmt.Sprintf("%s/v2/%s/manifests/%s", app.RegistryURL, imageName, tag), nil) if err != nil { fmt.Println("Error creating request:", err) return } req.Header.Set("Accept", "application/vnd.docker.distribution.manifest.v2+json") resp, err := client.Do(req) if err != nil { fmt.Println("Error fetching manifest:", err) return } defer resp.Body.Close() if resp.StatusCode == http.StatusNotFound { fmt.Printf("Error: Image '%s:%s' not found in the registry.\n", imageName, tag) return } digest := resp.Header.Get("Docker-Content-Digest") req, err = http.NewRequest("DELETE", fmt.Sprintf("%s/v2/%s/manifests/%s", app.RegistryURL, imageName, digest), nil) if err != nil { fmt.Println("Error creating delete request:", err) return } // Join username and password for Basic Auth registryCredentials := app.RegistryUsername + ":" + app.RegistryPassword req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(registryCredentials))) resp, err = client.Do(req) if err != nil { fmt.Println("Error deleting image:", err) return } defer resp.Body.Close() if resp.StatusCode == http.StatusAccepted { fmt.Printf("Deleted image: %s:%s\n", imageName, tag) } else { fmt.Printf("Failed to delete image: %s:%s (status code: %d)\n", imageName, tag, resp.StatusCode) } }