hub/internal/pkg/metadata.go

107 lines
3.3 KiB
Go

package pkg
import (
"errors"
"fmt"
"io/ioutil"
"time"
"github.com/Masterminds/semver/v3"
"github.com/artifacthub/hub/internal/hub"
"gopkg.in/yaml.v2"
)
var (
// ErrInvalidMetadata indicates that the metadata provided is not valid.
ErrInvalidMetadata = errors.New("invalid metadata")
)
// GetPackageMetadata reads, parses and validates the package metadata file provided.
func GetPackageMetadata(mdFile string) (*hub.PackageMetadata, error) {
var data []byte
var err error
for _, extension := range []string{".yml", ".yaml"} {
data, err = ioutil.ReadFile(mdFile + extension)
if err == nil {
break
}
}
if err != nil {
return nil, fmt.Errorf("error reading package metadata file: %w", err)
}
var md *hub.PackageMetadata
if err = yaml.Unmarshal(data, &md); err != nil || md == nil {
return nil, fmt.Errorf("error unmarshaling package metadata file: %w", err)
}
if err := ValidatePackageMetadata(md); err != nil {
return nil, fmt.Errorf("error validating package metadata file: %w", err)
}
return md, nil
}
// PreparePackageFromMetadata prepares a Package struct that will be used to
// proceed with a package registration from the PackageMetadata provided by the
// publisher.
func PreparePackageFromMetadata(md *hub.PackageMetadata) (*hub.Package, error) {
if err := ValidatePackageMetadata(md); err != nil {
return nil, err
}
sv, _ := semver.NewVersion(md.Version)
p := &hub.Package{
Name: md.Name,
IsOperator: md.Operator,
DisplayName: md.DisplayName,
Description: md.Description,
Keywords: md.Keywords,
HomeURL: md.HomeURL,
Readme: md.Readme,
Install: md.Install,
Changes: md.Changes,
ContainsSecurityUpdates: md.ContainsSecurityUpdates,
Prerelease: md.Prerelease,
Links: md.Links,
Version: sv.String(),
AppVersion: md.AppVersion,
Digest: md.Digest,
Deprecated: md.Deprecated,
License: md.License,
ContainersImages: md.ContainersImages,
Maintainers: md.Maintainers,
Recommendations: md.Recommendations,
}
if md.Provider != nil {
p.Provider = md.Provider.Name
}
ts, _ := time.Parse(time.RFC3339, md.CreatedAt)
p.TS = ts.Unix()
return p, nil
}
// ValidatePackageMetadata validates if the package metadata provided is valid.
func ValidatePackageMetadata(md *hub.PackageMetadata) error {
if md.Version == "" {
return fmt.Errorf("%w: %s", ErrInvalidMetadata, "version not provided")
}
if _, err := semver.NewVersion(md.Version); err != nil {
return fmt.Errorf("%w: %s: %v", ErrInvalidMetadata, "invalid version (semver expected)", err)
}
if md.Name == "" {
return fmt.Errorf("%w: %s", ErrInvalidMetadata, "name not provided")
}
if md.DisplayName == "" {
return fmt.Errorf("%w: %s", ErrInvalidMetadata, "display name not provided")
}
if md.CreatedAt == "" {
return fmt.Errorf("%w: %s", ErrInvalidMetadata, "createdAt not provided")
}
if _, err := time.Parse(time.RFC3339, md.CreatedAt); err != nil {
return fmt.Errorf("%w: %s: %v", ErrInvalidMetadata, "invalid createdAt (RFC3339 expected)", err)
}
if md.Description == "" {
return fmt.Errorf("%w: %s", ErrInvalidMetadata, "description not provided")
}
return nil
}