feat: Implemented (un)install,start/stop flow and fixed actions flow
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.dcntrlized.org/Dcntrlized/Maestro/lib/logger"
|
||||
"git.dcntrlized.org/Dcntrlized/Maestro/lib/types"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/authn"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
@@ -17,29 +18,6 @@ import (
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
// RegistryContainer represents a clean API payload specifically for container registry items.
|
||||
type RegistryContainer struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Image string `json:"image"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Author string `json:"author,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
CreatedAt string `json:"created_at,omitempty"`
|
||||
}
|
||||
|
||||
type RawPackage struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
Repository *struct {
|
||||
HTMLURL string `json:"html_url"`
|
||||
} `json:"repository"`
|
||||
}
|
||||
|
||||
func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
// 1. Query Gitea REST API using the exact Org name
|
||||
apiURL := fmt.Sprintf("https://git.dcntrlized.org/api/v1/packages/%s?type=container", os.Getenv("GITEA_ORG"))
|
||||
@@ -51,7 +29,7 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debug(fmt.Sprintf("%s", os.Getenv("GITEA_RW_PACKAGE_TOKEN")))
|
||||
logger.Debug("Querying Gitea package API at %s", apiURL)
|
||||
req.Header.Set("Authorization", "token "+os.Getenv("GITEA_RW_PACKAGE_TOKEN"))
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
@@ -69,7 +47,7 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var rawPackages []RawPackage
|
||||
var rawPackages []types.RawPackage
|
||||
if err := json.NewDecoder(resp.Body).Decode(&rawPackages); err != nil {
|
||||
logger.Error("Failed to decode registry response: %v", err)
|
||||
http.Error(w, "Failed to decode registry response", http.StatusInternalServerError)
|
||||
@@ -77,7 +55,7 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 2. Group by Name and filter out "latest" & "sha256:"
|
||||
groupedPackages := make(map[string][]RawPackage)
|
||||
groupedPackages := make(map[string][]types.RawPackage)
|
||||
for _, pkg := range rawPackages {
|
||||
if pkg.Version == "latest" || strings.HasPrefix(pkg.Version, "sha256:") {
|
||||
continue
|
||||
@@ -94,7 +72,7 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 3. For each container name, find the package entry with the highest semver
|
||||
var latestPackages []RawPackage
|
||||
var latestPackages []types.RawPackage
|
||||
for _, pkgs := range groupedPackages {
|
||||
if len(pkgs) == 0 {
|
||||
continue
|
||||
@@ -118,23 +96,24 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
ociAuth := remote.WithAuth(&authn.Basic{
|
||||
Username: os.Getenv("GITEA_USER"),
|
||||
Password: os.Getenv("GITEA_RO_TOKEN"),
|
||||
Password: os.Getenv("GITEA_RW_PACKAGE_TOKEN"),
|
||||
})
|
||||
|
||||
ociOrg := strings.ToLower(os.Getenv("GITEA_ORG"))
|
||||
var registryItems []RegistryContainer
|
||||
var registryItems []types.RegistryContainer
|
||||
|
||||
// 4. Fetch OCI metadata only for the highest version of each package
|
||||
for _, pkg := range latestPackages {
|
||||
pkgNameLower := strings.ToLower(pkg.Name)
|
||||
imageRef := fmt.Sprintf("git.dcntrlized.org/%s/%s:%s", ociOrg, pkgNameLower, pkg.Version)
|
||||
|
||||
// Default fallback source from Gitea REST API
|
||||
source := pkg.HTMLURL
|
||||
if pkg.Repository != nil && pkg.Repository.HTMLURL != "" {
|
||||
source = pkg.Repository.HTMLURL
|
||||
}
|
||||
|
||||
item := RegistryContainer{
|
||||
item := types.RegistryContainer{
|
||||
Name: pkg.Name,
|
||||
Version: pkg.Version,
|
||||
Image: imageRef,
|
||||
@@ -156,7 +135,12 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Extract annotations from OCI manifest
|
||||
// Fetch image digest (sha256:...)
|
||||
if digest, err := img.Digest(); err == nil {
|
||||
item.Digest = digest.String()
|
||||
}
|
||||
|
||||
// 1. Extract standard OCI annotations from OCI Manifest
|
||||
if manifest, err := img.Manifest(); err == nil && manifest != nil {
|
||||
if title, ok := manifest.Annotations["org.opencontainers.image.title"]; ok {
|
||||
item.Title = title
|
||||
@@ -170,11 +154,30 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
if desc, ok := manifest.Annotations["org.opencontainers.image.description"]; ok {
|
||||
item.Description = desc
|
||||
}
|
||||
if src, ok := manifest.Annotations["org.opencontainers.image.source"]; ok && src != "" {
|
||||
item.Source = src
|
||||
}
|
||||
if rev, ok := manifest.Annotations["org.opencontainers.image.revision"]; ok {
|
||||
item.Revision = rev
|
||||
}
|
||||
if lic, ok := manifest.Annotations["org.opencontainers.image.licenses"]; ok {
|
||||
item.Licenses = lic
|
||||
}
|
||||
if url, ok := manifest.Annotations["org.opencontainers.image.url"]; ok {
|
||||
item.URL = url
|
||||
}
|
||||
if doc, ok := manifest.Annotations["org.opencontainers.image.documentation"]; ok {
|
||||
item.Documentation = doc
|
||||
}
|
||||
if created, ok := manifest.Annotations["org.opencontainers.image.created"]; ok && created != "" {
|
||||
item.CreatedAt = created
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to Image Config labels
|
||||
// 2. Fallback to Image Config Labels (where docker buildx puts them when targeting v2 registries)
|
||||
if configFile, err := img.ConfigFile(); err == nil && configFile != nil {
|
||||
labels := configFile.Config.Labels
|
||||
|
||||
if item.Title == "" {
|
||||
item.Title = labels["org.opencontainers.image.title"]
|
||||
}
|
||||
@@ -187,6 +190,24 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
if item.Description == "" {
|
||||
item.Description = labels["org.opencontainers.image.description"]
|
||||
}
|
||||
if src, ok := labels["org.opencontainers.image.source"]; ok && src != "" {
|
||||
item.Source = src
|
||||
}
|
||||
if item.Revision == "" {
|
||||
item.Revision = labels["org.opencontainers.image.revision"]
|
||||
}
|
||||
if item.Licenses == "" {
|
||||
item.Licenses = labels["org.opencontainers.image.licenses"]
|
||||
}
|
||||
if item.URL == "" {
|
||||
item.URL = labels["org.opencontainers.image.url"]
|
||||
}
|
||||
if item.Documentation == "" {
|
||||
item.Documentation = labels["org.opencontainers.image.documentation"]
|
||||
}
|
||||
if item.CreatedAt == "" && labels["org.opencontainers.image.created"] != "" {
|
||||
item.CreatedAt = labels["org.opencontainers.image.created"]
|
||||
}
|
||||
}
|
||||
|
||||
registryItems = append(registryItems, item)
|
||||
|
||||
Reference in New Issue
Block a user