From 222f1208a7665b60103293cb3230c36fc880c69f Mon Sep 17 00:00:00 2001 From: "tuti." Date: Wed, 18 Dec 2024 09:24:51 -0800 Subject: [PATCH] [release tool] refactor pinnedversion (#9595) * refactor pinnedversion ref: DE-2970 * address review --- release/cmd/hashrelease.go | 58 ++-- release/cmd/release.go | 12 +- .../internal/pinnedversion/pinnedversion.go | 265 +++++++++--------- ...aml.gotmpl => calico-versions.yaml.gotmpl} | 2 +- release/internal/version/version.go | 49 +++- release/pkg/manager/calico/manager.go | 24 +- release/pkg/manager/calico/options.go | 21 +- release/pkg/tasks/hashrelease.go | 12 +- 8 files changed, 240 insertions(+), 203 deletions(-) rename release/internal/pinnedversion/templates/{calico-version.yaml.gotmpl => calico-versions.yaml.gotmpl} (95%) diff --git a/release/cmd/hashrelease.go b/release/cmd/hashrelease.go index 90271c02f8a..1684b0df531 100644 --- a/release/cmd/hashrelease.go +++ b/release/cmd/hashrelease.go @@ -16,6 +16,7 @@ package main import ( "fmt" + "os" "path/filepath" "github.com/sirupsen/logrus" @@ -64,57 +65,59 @@ func hashreleaseSubCommands(cfg *Config) []*cli.Command { return err } + // Clone the operator repository. + operatorDir := filepath.Join(cfg.TmpDir, operator.DefaultRepoName) + err := operator.Clone(c.String(operatorOrgFlag.Name), c.String(operatorRepoFlag.Name), c.String(operatorBranchFlag.Name), operatorDir) + if err != nil { + return fmt.Errorf("failed to clone operator repository: %v", err) + } + // Create the pinned config. - pinnedCfg := pinnedversion.Config{ + pinned := pinnedversion.CalicoPinnedVersions{ + Dir: cfg.TmpDir, RootDir: cfg.RepoRootDir, ReleaseBranchPrefix: c.String(releaseBranchPrefixFlag.Name), - Operator: pinnedversion.OperatorConfig{ + OperatorCfg: pinnedversion.OperatorConfig{ Image: c.String(operatorImageFlag.Name), Registry: c.String(operatorRegistryFlag.Name), Branch: c.String(operatorBranchFlag.Name), - Dir: filepath.Join(cfg.TmpDir, operator.DefaultRepoName), + Dir: operatorDir, }, } - // Clone the operator repository. - err := operator.Clone(c.String(operatorOrgFlag.Name), c.String(operatorRepoFlag.Name), c.String(operatorBranchFlag.Name), pinnedCfg.Operator.Dir) - if err != nil { - return fmt.Errorf("failed to clone operator repository: %v", err) - } - - _, data, err := pinnedversion.GeneratePinnedVersionFile(pinnedCfg, cfg.TmpDir) + data, err := pinned.GenerateFile() if err != nil { return fmt.Errorf("failed to generate pinned version file: %v", err) } - dir := hashreleaseOutputDir(cfg.RepoRootDir, data.Hash) - versions := &version.Data{ - ProductVersion: version.New(data.ProductVersion), - OperatorVersion: version.New(data.Operator.Version), + // Create the output directory for the hashrelease. + dir := hashreleaseOutputDir(cfg.RepoRootDir, data.Hash()) + if err := os.MkdirAll(dir, utils.DirPerms); err != nil { + return fmt.Errorf("failed to create hashrelease output directory: %v", err) } // Check if the hashrelease has already been published. - if published, err := tasks.HashreleasePublished(hashreleaseServerConfig(c), data.Hash, c.Bool(ciFlag.Name)); err != nil { + if published, err := tasks.HashreleasePublished(hashreleaseServerConfig(c), data.Hash(), c.Bool(ciFlag.Name)); err != nil { return fmt.Errorf("failed to check if hashrelease has been published: %v", err) } else if published { // On CI, we want it to fail if the hashrelease has already been published. // However, on local builds, we just log a warning and continue. if c.Bool(ciFlag.Name) { - return fmt.Errorf("hashrelease %s has already been published", data.Hash) + return fmt.Errorf("hashrelease %s has already been published", data.Hash()) } else { - logrus.Warnf("hashrelease %s has already been published", data.Hash) + logrus.Warnf("hashrelease %s has already been published", data.Hash()) } } // Build the operator operatorOpts := []operator.Option{ - operator.WithOperatorDirectory(pinnedCfg.Operator.Dir), + operator.WithOperatorDirectory(operatorDir), operator.WithReleaseBranchPrefix(c.String(operatorReleaseBranchPrefixFlag.Name)), operator.IsHashRelease(), operator.WithArchitectures(c.StringSlice(archFlag.Name)), operator.WithValidate(!c.Bool(skipValidationFlag.Name)), operator.WithReleaseBranchValidation(!c.Bool(skipBranchCheckFlag.Name)), - operator.WithVersion(versions.OperatorVersion.FormattedString()), + operator.WithVersion(data.OperatorVersion()), operator.WithCalicoDirectory(cfg.RepoRootDir), operator.WithTempDirectory(cfg.TmpDir), } @@ -127,11 +130,14 @@ func hashreleaseSubCommands(cfg *Config) []*cli.Command { // Configure a release builder using the generated versions, and use it // to build a Calico release. - opts := []calico.Option{ + pinnedOpts, err := pinned.ManagerOptions() + if err != nil { + return fmt.Errorf(("failed to retrieve pinned version options for manager: %v"), err) + } + opts := append(pinnedOpts, calico.WithRepoRoot(cfg.RepoRootDir), calico.WithReleaseBranchPrefix(c.String(releaseBranchPrefixFlag.Name)), calico.IsHashRelease(), - calico.WithVersions(versions), calico.WithOutputDir(dir), calico.WithBuildImages(c.Bool(buildHashreleaseImageFlag.Name)), calico.WithValidate(!c.Bool(skipValidationFlag.Name)), @@ -140,7 +146,7 @@ func hashreleaseSubCommands(cfg *Config) []*cli.Command { calico.WithRepoName(c.String(repoFlag.Name)), calico.WithRepoRemote(c.String(repoRemoteFlag.Name)), calico.WithArchitectures(c.StringSlice(archFlag.Name)), - } + ) if reg := c.StringSlice(registryFlag.Name); len(reg) > 0 { opts = append(opts, calico.WithImageRegistries(reg)) } @@ -152,7 +158,7 @@ func hashreleaseSubCommands(cfg *Config) []*cli.Command { // For real releases, release notes are generated prior to building the release. // For hash releases, generate a set of release notes and add them to the hashrelease directory. - releaseVersion, err := version.DetermineReleaseVersion(versions.ProductVersion, c.String(devTagSuffixFlag.Name)) + releaseVersion, err := version.DetermineReleaseVersion(version.New(data.ProductVersion()), c.String(devTagSuffixFlag.Name)) if err != nil { return fmt.Errorf("failed to determine release version: %v", err) } @@ -208,10 +214,8 @@ func hashreleaseSubCommands(cfg *Config) []*cli.Command { opts := []calico.Option{ calico.WithRepoRoot(cfg.RepoRootDir), calico.IsHashRelease(), - calico.WithVersions(&version.Data{ - ProductVersion: version.New(hashrel.ProductVersion), - OperatorVersion: version.New(hashrel.OperatorVersion), - }), + calico.WithVersion(hashrel.ProductVersion), + calico.WithOperatorVersion(hashrel.OperatorVersion), calico.WithGithubOrg(c.String(orgFlag.Name)), calico.WithRepoName(c.String(repoFlag.Name)), calico.WithRepoRemote(c.String(repoRemoteFlag.Name)), diff --git a/release/cmd/release.go b/release/cmd/release.go index 2328acc11a0..94e7faf519a 100644 --- a/release/cmd/release.go +++ b/release/cmd/release.go @@ -91,10 +91,8 @@ func releaseSubCommands(cfg *Config) []*cli.Command { opts := []calico.Option{ calico.WithRepoRoot(cfg.RepoRootDir), calico.WithReleaseBranchPrefix(c.String(releaseBranchPrefixFlag.Name)), - calico.WithVersions(&version.Data{ - ProductVersion: ver, - OperatorVersion: operatorVer, - }), + calico.WithVersion(ver.FormattedString()), + calico.WithOperatorVersion(operatorVer.FormattedString()), calico.WithOutputDir(releaseOutputDir(cfg.RepoRootDir, ver.FormattedString())), calico.WithArchitectures(c.StringSlice(archFlag.Name)), calico.WithGithubOrg(c.String(orgFlag.Name)), @@ -127,10 +125,8 @@ func releaseSubCommands(cfg *Config) []*cli.Command { } opts := []calico.Option{ calico.WithRepoRoot(cfg.RepoRootDir), - calico.WithVersions(&version.Data{ - ProductVersion: ver, - OperatorVersion: operatorVer, - }), + calico.WithVersion(ver.FormattedString()), + calico.WithOperatorVersion(operatorVer.FormattedString()), calico.WithOutputDir(releaseOutputDir(cfg.RepoRootDir, ver.FormattedString())), calico.WithGithubOrg(c.String(orgFlag.Name)), calico.WithRepoName(c.String(repoFlag.Name)), diff --git a/release/internal/pinnedversion/pinnedversion.go b/release/internal/pinnedversion/pinnedversion.go index 7b9784335a4..301817d8402 100644 --- a/release/internal/pinnedversion/pinnedversion.go +++ b/release/internal/pinnedversion/pinnedversion.go @@ -31,10 +31,11 @@ import ( "github.com/projectcalico/calico/release/internal/registry" "github.com/projectcalico/calico/release/internal/utils" "github.com/projectcalico/calico/release/internal/version" + "github.com/projectcalico/calico/release/pkg/manager/calico" ) -//go:embed templates/calico-version.yaml.gotmpl -var calicoVersionTemplateData string +//go:embed templates/calico-versions.yaml.gotmpl +var calicoTemplate string const ( pinnedVersionFileName = "pinned-version.yaml" @@ -47,167 +48,192 @@ var noImageComponents = []string{ "networking-calico", } -type OperatorConfig struct { - // Dir is the directory to clone the operator repository. - Dir string - - // Branch is the repository for the operator - Branch string +type PinnedVersions interface { + GenerateFile() (version.Data, error) + ManagerOptions() ([]calico.Option, error) +} - // Registry is the registry for Tigera operator +type OperatorConfig struct { + Dir string + Branch string Registry string - - // Image is the image for Tigera operator - Image string + Image string // i.e tigera/operator } -func (c OperatorConfig) GitVersion() version.Version { - previousTag, err := command.GitVersion(c.Dir, true) +func (c OperatorConfig) GitVersion() (string, error) { + tag, err := command.GitVersion(c.Dir, true) if err != nil { - logrus.WithError(err).Fatal("Failed to determine latest git version") + logrus.WithError(err).Error("Failed to determine operator git version") + return "", err } - logrus.WithField("out", previousTag).Info("Current git describe") - return version.New(previousTag) + logrus.WithField("out", tag).Info("Current git describe") + return tag, nil } func (c OperatorConfig) GitBranch() (string, error) { return command.GitInDir(c.Dir, "rev-parse", "--abbrev-ref", "HEAD") } -// Config represents the configuration needed to generate the pinned version file. -type Config struct { - // RootDir is the root directory of the repository. - RootDir string - - // ReleaseBranchPrefix is the prefix for the release branch. - ReleaseBranchPrefix string - - // Operator is the configuration for the operator. - Operator OperatorConfig -} - -// PinnedVersionData represents the data needed to generate the pinned version file from the template. -type PinnedVersionData struct { - // ReleaseName is the name of the release. - ReleaseName string - - // BaseDomain is the base domain for the docs site. - BaseDomain string - - // ProductVersion is the version of the product. - ProductVersion string - - // Operator is the operator component. - Operator registry.Component - - // Note is the note for the release. - Note string - - // Hash is the hash of the release. - Hash string - - // ReleaseBranch is the release branch of the release. - ReleaseBranch string -} - // PinnedVersion represents an entry in pinned version file. type PinnedVersion struct { Title string `yaml:"title"` ManifestURL string `yaml:"manifest_url"` - ReleaseName string `yaml:"release_name"` + ReleaseName string `yaml:"release_name,omitempty"` Note string `yaml:"note"` Hash string `yaml:"full_hash"` TigeraOperator registry.Component `yaml:"tigera-operator"` Components map[string]registry.Component `yaml:"components"` } -// PinnedVersionFile represents the pinned version file. -type PinnedVersionFile []PinnedVersion +// calicoTemplateData is used to generate the pinned version file from the template. +type calicoTemplateData struct { + ReleaseName string + BaseDomain string + ProductVersion string + Operator registry.Component + Note string + Hash string + ReleaseBranch string +} + +func (d *calicoTemplateData) ReleaseURL() string { + return fmt.Sprintf("https://%s.%s", d.ReleaseName, d.BaseDomain) +} func pinnedVersionFilePath(outputDir string) string { return filepath.Join(outputDir, pinnedVersionFileName) } -func operatorComponentsFilePath(outputDir string) string { - return filepath.Join(outputDir, operatorComponentsFileName) +// CalicoPinnedVersions is the implementation of PinnedVersions for Calico. +// It generates the pinned version file for Calico +// and provides the manager options for the Calico manager. +type CalicoPinnedVersions struct { + // RootDir is the root directory of the repository. + RootDir string + + // Dir is the directory to store the pinned version file. + Dir string + + // ReleaseBranchPrefix is the prefix for the release branch. + ReleaseBranchPrefix string + + // OperatorCfg is the configuration for the operator. + OperatorCfg OperatorConfig } -// GeneratePinnedVersionFile generates the pinned version file. -func GeneratePinnedVersionFile(cfg Config, outputDir string) (string, *PinnedVersionData, error) { - pinnedVersionPath := pinnedVersionFilePath(outputDir) +// GenerateFile generates the pinned version file. +func (p *CalicoPinnedVersions) GenerateFile() (version.Data, error) { + pinnedVersionPath := pinnedVersionFilePath(p.Dir) - productBranch, err := utils.GitBranch(cfg.RootDir) + productBranch, err := utils.GitBranch(p.RootDir) if err != nil { - return "", nil, err + return nil, err } - - productVersion := version.GitVersion() - releaseName := fmt.Sprintf("%s-%s-%s", time.Now().Format("2006-01-02"), version.DeterminePublishStream(productBranch, string(productVersion)), RandomWord()) + productVer, err := command.GitVersion(p.RootDir, true) + if err != nil { + logrus.WithError(err).Error("Failed to determine product git version") + return nil, err + } + releaseName := fmt.Sprintf("%s-%s-%s", time.Now().Format("2006-01-02"), version.DeterminePublishStream(productBranch, productVer), RandomWord()) releaseName = strings.ReplaceAll(releaseName, ".", "-") - operatorBranch, err := cfg.Operator.GitBranch() + operatorBranch, err := p.OperatorCfg.GitBranch() + if err != nil { + return nil, err + } + operatorVer, err := p.OperatorCfg.GitVersion() if err != nil { - return "", nil, err + return nil, err } - operatorVersion := cfg.Operator.GitVersion() - tmpl, err := template.New("pinnedversion").Parse(calicoVersionTemplateData) + versionData := version.NewVersionData(version.New(productVer), operatorVer) + tmpl, err := template.New("pinnedversion").Parse(calicoTemplate) if err != nil { - return "", nil, err + return nil, err } - data := &PinnedVersionData{ + tmplData := &calicoTemplateData{ ReleaseName: releaseName, BaseDomain: hashreleaseserver.BaseDomain, - ProductVersion: productVersion.FormattedString(), + ProductVersion: versionData.ProductVersion(), Operator: registry.Component{ - Version: operatorVersion.FormattedString() + "-" + releaseName, - Image: cfg.Operator.Image, - Registry: cfg.Operator.Registry, + Version: versionData.OperatorVersion(), + Image: p.OperatorCfg.Image, + Registry: p.OperatorCfg.Registry, }, - Hash: productVersion.FormattedString() + "-" + operatorVersion.FormattedString(), + Hash: versionData.Hash(), Note: fmt.Sprintf("%s - generated at %s using %s release branch with %s operator branch", releaseName, time.Now().Format(time.RFC1123), productBranch, operatorBranch), - ReleaseBranch: productVersion.ReleaseBranch(cfg.ReleaseBranchPrefix), + ReleaseBranch: versionData.ReleaseBranch(p.ReleaseBranchPrefix), } logrus.WithField("file", pinnedVersionPath).Info("Generating pinned version file") pinnedVersionFile, err := os.Create(pinnedVersionPath) if err != nil { - return "", nil, err + return nil, err } defer pinnedVersionFile.Close() - if err := tmpl.Execute(pinnedVersionFile, data); err != nil { - return "", nil, err + if err := tmpl.Execute(pinnedVersionFile, tmplData); err != nil { + return nil, err + } + + return versionData, nil +} + +// ManagerOptions returns the options for the manager. +func (p *CalicoPinnedVersions) ManagerOptions() ([]calico.Option, error) { + pinnedVersion, err := retrievePinnedVersion(p.Dir) + if err != nil { + return nil, err + } + + components := pinnedVersion.Components + operator := registry.OperatorComponent{Component: pinnedVersion.TigeraOperator} + components[operator.Image] = operator.Component + initImage := operator.InitImage() + components[initImage.Image] = operator.InitImage() + for name, component := range components { + // Remove components that do not produce images. + if utils.Contains(noImageComponents, name) { + delete(components, name) + continue + } + img := registry.ImageMap[name] + if img != "" { + component.Image = img + } else if component.Image == "" { + component.Image = name + } + components[name] = component } - return pinnedVersionPath, data, nil + return []calico.Option{ + calico.WithVersion(pinnedVersion.Title), + calico.WithOperatorVersion(pinnedVersion.TigeraOperator.Version), + calico.WithComponents(components), + }, nil } // GenerateOperatorComponents generates the components-version.yaml for operator. func GenerateOperatorComponents(outputDir string) (registry.OperatorComponent, string, error) { op := registry.OperatorComponent{} - pinnedVersionPath := pinnedVersionFilePath(outputDir) - logrus.WithField("file", pinnedVersionPath).Info("Generating components-version.yaml for operator") - var pinnedversion PinnedVersionFile - if pinnedVersionData, err := os.ReadFile(pinnedVersionPath); err != nil { - return op, "", err - } else if err := yaml.Unmarshal([]byte(pinnedVersionData), &pinnedversion); err != nil { + pinnedVersion, err := retrievePinnedVersion(outputDir) + if err != nil { return op, "", err } - operatorComponentsFilePath := operatorComponentsFilePath(outputDir) + operatorComponentsFilePath := filepath.Join(outputDir, operatorComponentsFileName) operatorComponentsFile, err := os.Create(operatorComponentsFilePath) if err != nil { return op, "", err } defer operatorComponentsFile.Close() - if err = yaml.NewEncoder(operatorComponentsFile).Encode(pinnedversion[0]); err != nil { + if err = yaml.NewEncoder(operatorComponentsFile).Encode(pinnedVersion); err != nil { return op, "", err } - op.Component = pinnedversion[0].TigeraOperator + op.Component = pinnedVersion.TigeraOperator return op, operatorComponentsFilePath, nil } -// RetrievePinnedVersion retrieves the pinned version from the pinned version file. -func RetrievePinnedVersion(outputDir string) (PinnedVersion, error) { +// retrievePinnedVersion retrieves the pinned version from the pinned version file. +func retrievePinnedVersion(outputDir string) (PinnedVersion, error) { pinnedVersionPath := pinnedVersionFilePath(outputDir) - var pinnedVersionFile PinnedVersionFile + var pinnedVersionFile []PinnedVersion if pinnedVersionData, err := os.ReadFile(pinnedVersionPath); err != nil { return PinnedVersion{}, err } else if err := yaml.Unmarshal([]byte(pinnedVersionData), &pinnedVersionFile); err != nil { @@ -218,49 +244,15 @@ func RetrievePinnedVersion(outputDir string) (PinnedVersion, error) { // RetrievePinnedOperatorVersion retrieves the operator version from the pinned version file. func RetrievePinnedOperator(outputDir string) (registry.OperatorComponent, error) { - pinnedVersionPath := pinnedVersionFilePath(outputDir) - var pinnedVersionFile PinnedVersionFile - if pinnedVersionData, err := os.ReadFile(pinnedVersionPath); err != nil { - return registry.OperatorComponent{}, err - } else if err := yaml.Unmarshal([]byte(pinnedVersionData), &pinnedVersionFile); err != nil { + pinnedVersion, err := retrievePinnedVersion(outputDir) + if err != nil { return registry.OperatorComponent{}, err } return registry.OperatorComponent{ - Component: pinnedVersionFile[0].TigeraOperator, + Component: pinnedVersion.TigeraOperator, }, nil } -// RetrieveComponentsToValidate retrieves the components to validate from the pinned version file. -func RetrieveComponentsToValidate(outputDir string) (map[string]registry.Component, error) { - pinnedVersionPath := pinnedVersionFilePath(outputDir) - var pinnedversion PinnedVersionFile - if pinnedVersionData, err := os.ReadFile(pinnedVersionPath); err != nil { - return nil, err - } else if err := yaml.Unmarshal([]byte(pinnedVersionData), &pinnedversion); err != nil { - return nil, err - } - components := pinnedversion[0].Components - operator := registry.OperatorComponent{Component: pinnedversion[0].TigeraOperator} - components[operator.Image] = operator.Component - initImage := operator.InitImage() - components[initImage.Image] = operator.InitImage() - for name, component := range components { - // Remove components that do not produce images. - if utils.Contains(noImageComponents, name) { - delete(components, name) - continue - } - img := registry.ImageMap[name] - if img != "" { - component.Image = img - } else if component.Image == "" { - component.Image = name - } - components[name] = component - } - return components, nil -} - // LoadHashrelease loads the hashrelease from the pinned version file. func LoadHashrelease(repoRootDir, outputDir, hashreleaseSrcBaseDir string, latest bool) (*hashreleaseserver.Hashrelease, error) { productBranch, err := utils.GitBranch(repoRootDir) @@ -268,7 +260,7 @@ func LoadHashrelease(repoRootDir, outputDir, hashreleaseSrcBaseDir string, lates logrus.WithError(err).Error("Failed to get current branch") return nil, err } - pinnedVersion, err := RetrievePinnedVersion(outputDir) + pinnedVersion, err := retrievePinnedVersion(outputDir) if err != nil { logrus.WithError(err).Fatal("Failed to get pinned version") } @@ -284,3 +276,12 @@ func LoadHashrelease(repoRootDir, outputDir, hashreleaseSrcBaseDir string, lates Latest: latest, }, nil } + +func RetrieveVersions(outputDir string) (version.Data, error) { + pinnedVersion, err := retrievePinnedVersion(outputDir) + if err != nil { + return nil, err + } + + return version.NewVersionData(version.New(pinnedVersion.Title), pinnedVersion.TigeraOperator.Version), nil +} diff --git a/release/internal/pinnedversion/templates/calico-version.yaml.gotmpl b/release/internal/pinnedversion/templates/calico-versions.yaml.gotmpl similarity index 95% rename from release/internal/pinnedversion/templates/calico-version.yaml.gotmpl rename to release/internal/pinnedversion/templates/calico-versions.yaml.gotmpl index 5630171efb3..810ed8fdc17 100644 --- a/release/internal/pinnedversion/templates/calico-version.yaml.gotmpl +++ b/release/internal/pinnedversion/templates/calico-versions.yaml.gotmpl @@ -1,5 +1,5 @@ - title: {{.ProductVersion}} - manifests_url: https://{{.ReleaseName}}.{{.BaseDomain}} + manifests_url: {{.ReleaseURL}} release_name: {{.ReleaseName}} note: {{.Note}} full_hash: {{.Hash}} diff --git a/release/internal/version/version.go b/release/internal/version/version.go index a4182d82437..f5aa333e32e 100644 --- a/release/internal/version/version.go +++ b/release/internal/version/version.go @@ -27,12 +27,46 @@ import ( "github.com/projectcalico/calico/release/internal/utils" ) -type Data struct { - // ProductVersion is the version of the product - ProductVersion Version +// Data is the interface that provides version data for a release. +type Data interface { + Hash() string + ProductVersion() string + OperatorVersion() string + HelmChartVersion() string + ReleaseBranch(releaseBranchPrefix string) string +} + +func NewVersionData(calico Version, operator string) Data { + return &CalicoVersionData{ + calico: calico, + operator: operator, + } +} + +// CalicoVersionData provides version data for a Calico release. +type CalicoVersionData struct { + calico Version + operator string +} + +func (v *CalicoVersionData) ProductVersion() string { + return v.calico.FormattedString() +} - // OperatorVersion is the version of operator - OperatorVersion Version +func (v *CalicoVersionData) OperatorVersion() string { + return v.operator +} + +func (v *CalicoVersionData) HelmChartVersion() string { + return v.calico.FormattedString() +} + +func (v *CalicoVersionData) Hash() string { + return fmt.Sprintf("%s-%s", v.calico.FormattedString(), v.operator) +} + +func (v *CalicoVersionData) ReleaseBranch(releaseBranchPrefix string) string { + return fmt.Sprintf("%s-%s", releaseBranchPrefix, v.calico.Stream()) } // Version represents a version, and contains methods for working with versions. @@ -72,11 +106,6 @@ func (v *Version) Stream() string { return fmt.Sprintf("v%d.%d", ver.Major(), ver.Minor()) } -// ReleaseBranch returns the release branch which corresponds with this version. -func (v *Version) ReleaseBranch(releaseBranchPrefix string) string { - return fmt.Sprintf("%s-%s", releaseBranchPrefix, v.Stream()) -} - func (v *Version) Semver() *semver.Version { ver := semver.MustParse(string(*v)) return ver diff --git a/release/pkg/manager/calico/manager.go b/release/pkg/manager/calico/manager.go index f0a5353fb5f..9c5e3d19120 100644 --- a/release/pkg/manager/calico/manager.go +++ b/release/pkg/manager/calico/manager.go @@ -30,7 +30,6 @@ import ( "github.com/projectcalico/calico/release/internal/command" "github.com/projectcalico/calico/release/internal/hashreleaseserver" "github.com/projectcalico/calico/release/internal/imagescanner" - "github.com/projectcalico/calico/release/internal/pinnedversion" "github.com/projectcalico/calico/release/internal/registry" "github.com/projectcalico/calico/release/internal/utils" ) @@ -203,6 +202,7 @@ type CalicoManager struct { // image scanning configuration. imageScanning bool imageScanningConfig imagescanner.Config + imageComponents map[string]registry.Component // external configuration. githubToken string @@ -556,16 +556,12 @@ func (r *CalicoManager) hashreleasePrereqs() error { return fmt.Errorf("missing hashrelease server configuration") } } - images, err := pinnedversion.RetrieveComponentsToValidate(r.tmpDir) - if err != nil { - return fmt.Errorf("failed to get components to validate: %s", err) - } if r.publishImages { return r.assertImageVersions() } else { - results := make(map[string]imageExistsResult, len(images)) + results := make(map[string]imageExistsResult, len(r.imageComponents)) ch := make(chan imageExistsResult) - for name, component := range images { + for name, component := range r.imageComponents { go imgExists(name, component, ch) } for range images { @@ -573,14 +569,14 @@ func (r *CalicoManager) hashreleasePrereqs() error { results[res.name] = res } failedImageList := []string{} - for name, r := range results { + for name, result := range results { logrus.WithFields(logrus.Fields{ - "image": r.image, - "exists": r.exists, + "image": result.image, + "exists": result.exists, }).Info("Validating image") - if r.err != nil || !r.exists { - logrus.WithError(r.err).WithField("image", name).Error("Error checking image") - failedImageList = append(failedImageList, images[name].String()) + if result.err != nil || !result.exists { + logrus.WithError(result.err).WithField("image", name).Error("Error checking image") + failedImageList = append(failedImageList, r.imageComponents[name].String()) } else { logrus.WithField("image", name).Info("Image exists") } @@ -593,7 +589,7 @@ func (r *CalicoManager) hashreleasePrereqs() error { if r.imageScanning { logrus.Info("Sending images to ISS") imageList := []string{} - for _, component := range images { + for _, component := range r.imageComponents { imageList = append(imageList, component.String()) } imageScanner := imagescanner.New(r.imageScanningConfig) diff --git a/release/pkg/manager/calico/options.go b/release/pkg/manager/calico/options.go index 8b69668a45d..bb3df089785 100644 --- a/release/pkg/manager/calico/options.go +++ b/release/pkg/manager/calico/options.go @@ -17,7 +17,7 @@ package calico import ( "github.com/projectcalico/calico/release/internal/hashreleaseserver" "github.com/projectcalico/calico/release/internal/imagescanner" - "github.com/projectcalico/calico/release/internal/version" + "github.com/projectcalico/calico/release/internal/registry" ) type Option func(*CalicoManager) error @@ -50,10 +50,16 @@ func WithReleaseBranchValidation(validate bool) Option { } } -func WithVersions(versions *version.Data) Option { +func WithVersion(version string) Option { return func(r *CalicoManager) error { - r.calicoVersion = versions.ProductVersion.FormattedString() - r.operatorVersion = versions.OperatorVersion.FormattedString() + r.calicoVersion = version + return nil + } +} + +func WithOperatorVersion(version string) Option { + return func(r *CalicoManager) error { + r.operatorVersion = version return nil } } @@ -165,6 +171,13 @@ func WithImageScanning(scanning bool, cfg imagescanner.Config) Option { } } +func WithComponents(components map[string]registry.Component) Option { + return func(r *CalicoManager) error { + r.imageComponents = components + return nil + } +} + func WithGithubToken(token string) Option { return func(r *CalicoManager) error { r.githubToken = token diff --git a/release/pkg/tasks/hashrelease.go b/release/pkg/tasks/hashrelease.go index edbb45bc51a..1f701fd1855 100644 --- a/release/pkg/tasks/hashrelease.go +++ b/release/pkg/tasks/hashrelease.go @@ -85,18 +85,17 @@ func HashreleaseSlackMessage(slackCfg *slack.Config, hashrel *hashreleaseserver. // - Copy ocp.tgz to manifests/ocp.tgz func ReformatHashrelease(hashreleaseOutputDir, tmpDir string) error { logrus.Info("Modifying hashrelease output to match legacy format") - pinned, err := pinnedversion.RetrievePinnedVersion(tmpDir) + versions, err := pinnedversion.RetrieveVersions(tmpDir) if err != nil { - return err + return fmt.Errorf("failed to retrieve pinned versions: %w", err) } - ver := pinned.Components[utils.Calico].Version // Copy the windows zip file to files/windows/calico-windows-.zip if err := os.MkdirAll(filepath.Join(hashreleaseOutputDir, "files", "windows"), 0o755); err != nil { return err } - windowsZip := filepath.Join(hashreleaseOutputDir, fmt.Sprintf("calico-windows-%s.zip", ver)) - windowsZipDst := filepath.Join(hashreleaseOutputDir, "files", "windows", fmt.Sprintf("calico-windows-%s.zip", ver)) + windowsZip := filepath.Join(hashreleaseOutputDir, fmt.Sprintf("calico-windows-%s.zip", versions.ProductVersion())) + windowsZipDst := filepath.Join(hashreleaseOutputDir, "files", "windows", fmt.Sprintf("calico-windows-%s.zip", versions.ProductVersion())) if err := utils.CopyFile(windowsZip, windowsZipDst); err != nil { return err } @@ -109,8 +108,7 @@ func ReformatHashrelease(hashreleaseOutputDir, tmpDir string) error { } // Copy the operator tarball to tigera-operator.tgz - helmChartVersion := ver - operatorTarball := filepath.Join(hashreleaseOutputDir, fmt.Sprintf("tigera-operator-%s.tgz", helmChartVersion)) + operatorTarball := filepath.Join(hashreleaseOutputDir, fmt.Sprintf("tigera-operator-%s.tgz", versions.HelmChartVersion())) operatorTarballDst := filepath.Join(hashreleaseOutputDir, "tigera-operator.tgz") if err := utils.CopyFile(operatorTarball, operatorTarballDst); err != nil { return err