internal/helm/detail.go
Rama main · réplica de lectura del repositorio original.
package helm
import (
"cmp"
"context"
"errors"
"strings"
"sigs.k8s.io/yaml"
"github.com/sophotechlabs/spinoza/internal/api"
)
var ErrNoRelease = errors.New("no such helm release")
type Kind struct {
Group string
Version string
Resource string
Namespaced bool
}
type Resolver func(apiVersion, kind string) (Kind, bool)
func (s *Service) Detail(
ctx context.Context,
namespace, name string,
revision int64,
resolve Resolver,
) (api.HelmReleaseDetail, error) {
if !nameFormat.MatchString(namespace) || !nameFormat.MatchString(name) {
return api.HelmReleaseDetail{}, errors.New("namespace and name must be valid kubernetes names")
}
bounded, cancel := context.WithTimeout(ctx, listTimeout)
defer cancel()
var ref storedRef
var err error
if revision < 1 {
ref, err = s.latestRef(bounded, namespace, name)
} else {
ref, err = s.refAt(bounded, namespace, name, revision)
}
if err != nil {
return api.HelmReleaseDetail{}, err
}
body, bodyErr := s.body(bounded, ref)
if bodyErr != nil {
return api.HelmReleaseDetail{}, bodyErr
}
selected := stored{
driver: ref.driver,
namespace: ref.namespace,
name: ref.name,
revision: ref.revision,
status: ref.status,
created: ref.created,
body: body,
}
release, decoded, decodeErr := selected.decoded()
detail := api.HelmReleaseDetail{
Release: release,
Driver: selected.driver,
History: []api.HelmRevision{},
}
if decodeErr != nil {
detail.Error = "the selected revision's payload could not be read: " + decodeErr.Error()
return detail, nil
}
detail.Values = valuesOf(decoded)
detail.Notes = decoded.Info.Notes
detail.Manifest = decoded.Manifest
detail.FirstDeployed = decoded.Info.FirstDeployed
detail.Resources = resourcesOf(decoded.Manifest, release.Namespace, resolve)
return detail, nil
}
func newerRevision(left, right stored) int {
return cmp.Compare(right.revision, left.revision)
}
func valuesOf(decoded payload) string {
if len(decoded.Config) == 0 {
return ""
}
body, err := yaml.Marshal(decoded.Config)
if err != nil {
return ""
}
return string(body)
}
type manifestDoc struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Metadata struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
} `json:"metadata"`
}
func resourcesOf(manifest, namespace string, resolve Resolver) []api.HelmResource {
out := []api.HelmResource{}
for doc := range strings.SplitSeq(manifest, "\n---") {
trimmed := strings.TrimSpace(doc)
if trimmed == "" {
continue
}
var parsed manifestDoc
err := yaml.Unmarshal([]byte(trimmed), &parsed)
if err != nil {
continue
}
if parsed.Kind == "" || parsed.Metadata.Name == "" {
continue
}
out = append(out, resourceOf(parsed, namespace, resolve))
}
return out
}
func resourceOf(parsed manifestDoc, namespace string, resolve Resolver) api.HelmResource {
resource := api.HelmResource{
APIVersion: parsed.APIVersion,
Kind: parsed.Kind,
Name: parsed.Metadata.Name,
Namespace: parsed.Metadata.Namespace,
}
if resolve == nil {
return resource
}
found, ok := resolve(parsed.APIVersion, parsed.Kind)
if !ok {
return resource
}
resource.Group = found.Group
resource.Version = found.Version
resource.Resource = found.Resource
if found.Namespaced && resource.Namespace == "" {
resource.Namespace = namespace
}
return resource
}