diff --git a/go.mod b/go.mod index 064c434f0..e161d90c3 100644 --- a/go.mod +++ b/go.mod @@ -266,7 +266,7 @@ replace github.com/apcera/gssapi => github.com/openshift/gssapi v0.0.0-201610102 replace github.com/openshift/library-go => github.com/aguidirh/library-go v0.0.0-20240911111857-f8fdb642dea5 -replace github.com/openshift/oc => github.com/aguidirh/oc v0.0.1 +replace github.com/openshift/oc => github.com/aguidirh/oc v0.0.2 replace github.com/distribution/distribution/v3 => github.com/aguidirh/distribution/v3 v3.0.0-beta.1.ocmirror1 diff --git a/go.sum b/go.sum index 69f658634..9ebdb47bc 100644 --- a/go.sum +++ b/go.sum @@ -861,8 +861,8 @@ github.com/aguidirh/distribution/v3 v3.0.0-beta.1.ocmirror1 h1:/UsfVGVrtbsD4N0Lh github.com/aguidirh/distribution/v3 v3.0.0-beta.1.ocmirror1/go.mod h1:IcvaJQ0kCbNUrffwSTSblDLCb1IKa1FkZF/1cCstzhs= github.com/aguidirh/library-go v0.0.0-20240911111857-f8fdb642dea5 h1:89Qy0b27BXOgF0T7FxFhTxk0IDL/qry2FqXr/sVhvxA= github.com/aguidirh/library-go v0.0.0-20240911111857-f8fdb642dea5/go.mod h1:HUFcTET58RjthS3VZVQw1mqCofklZa3EdBEoxDooAZM= -github.com/aguidirh/oc v0.0.1 h1:f2qa+WrF2jRHQUDGvnE0wJizHMWC9494ISQ1k/ikryU= -github.com/aguidirh/oc v0.0.1/go.mod h1:qPruyC9vtw2CKOWJ0EVGR3E9iSobdjN7hpAEfqqBZPE= +github.com/aguidirh/oc v0.0.2 h1:3SMqNBpdyxyepMDXY9ocg4/t7stDj47FXMcCR3ToC1E= +github.com/aguidirh/oc v0.0.2/go.mod h1:qPruyC9vtw2CKOWJ0EVGR3E9iSobdjN7hpAEfqqBZPE= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= diff --git a/v2/internal/pkg/version/version.go b/v2/internal/pkg/version/version.go index 65dbb6c26..ec6378c61 100644 --- a/v2/internal/pkg/version/version.go +++ b/v2/internal/pkg/version/version.go @@ -6,11 +6,14 @@ import ( "fmt" "os" "runtime" + "strings" - clog "github.com/openshift/oc-mirror/v2/internal/pkg/log" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/version" "k8s.io/kubectl/pkg/util/templates" "sigs.k8s.io/yaml" + + clog "github.com/openshift/oc-mirror/v2/internal/pkg/log" ) var ( @@ -30,16 +33,35 @@ var ( gitTreeState string ) -type Info struct { - Major string `json:"major"` - Minor string `json:"minor"` - GitVersion string `json:"gitVersion"` - GitCommit string `json:"gitCommit"` - GitTreeState string `json:"gitTreeState"` - BuildDate string `json:"buildDate"` - GoVersion string `json:"goVersion"` - Compiler string `json:"compiler"` - Platform string `json:"platform"` +var ( + // releaseVersionPadded may be replaced in the binary with Release + // Metadata: Version that overrides releaseVersion as a null-terminated + // string within the allowed character length. This allows a distributor to + // override the version without having to rebuild the source. + releaseVersionPadded = "\x00_RELEASE_VERSION_LOCATION_\x00XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\x00" + releaseVersionPrefix = "\x00_RELEASE_VERSION_LOCATION_\x00" + releaseVersionLength = len(releaseVersionPadded) +) + +func ExtractVersion() (version.Info, string, error) { + if strings.HasPrefix(releaseVersionPadded, releaseVersionPrefix) { + return Get(), "", nil + } + nullTerminator := strings.IndexByte(releaseVersionPadded, '\x00') + if nullTerminator == -1 { + // the binary has been altered, but we didn't find a null terminator within the release name constant which is an error + return version.Info{}, "", fmt.Errorf("release name location was replaced but without a null terminator before %d bytes", releaseVersionLength) + } else if nullTerminator > releaseVersionLength { + // the binary has been altered, but the null terminator is *longer* than the constant encoded in the library + return version.Info{}, "", fmt.Errorf("release name location contains no null-terminator and constant is corrupted") + } + releaseName := releaseVersionPadded[:nullTerminator] + if len(releaseName) == 0 { + // the binary has been altered, but the replaced release name is empty which is incorrect + // the oc-mirror binary will not be pinned to Release Metadata: Version + return version.Info{}, "", fmt.Errorf("release name was incorrectly replaced during extract") + } + return Get(), releaseName, nil } type VersionOptions struct { @@ -50,7 +72,8 @@ type VersionOptions struct { // Version is a struct for version information type Version struct { - ClientVersion *Info `json:"clientVersion,omitempty" yaml:"clientVersion,omitempty"` + ClientVersion *version.Info `json:"clientVersion,omitempty" yaml:"clientVersion,omitempty"` + ReleaseVersion string `json:"releaseVersion,omitempty" yaml:"releaseVersion,omitempty"` } func NewVersionCommand(log clog.PluggableLoggerInterface) *cobra.Command { @@ -63,16 +86,12 @@ func NewVersionCommand(log clog.PluggableLoggerInterface) *cobra.Command { # Get oc-mirror version oc-mirror version `), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { if err := o.Validate(); err != nil { - log.Error(" %v ", err) - os.Exit(1) + return err } - if err := o.Run(); err != nil { - log.Error(" %v ", err) - os.Exit(1) - } + return o.Run() }, } @@ -100,7 +119,13 @@ func (o *VersionOptions) Validate() error { func (o *VersionOptions) Run() error { var versionInfo Version - clientVersion := Get() + clientVersion, reportedVersion, err := ExtractVersion() + if err != nil { + return fmt.Errorf("could not determine binary version: %w", err) + } + if len(reportedVersion) != 0 { + versionInfo.ReleaseVersion = reportedVersion + } versionInfo.ClientVersion = &clientVersion switch o.Output { @@ -111,6 +136,9 @@ func (o *VersionOptions) Run() error { fmt.Fprintf(os.Stderr, "WARNING: This version information is deprecated and will be replaced with the output from --short. Use --output=yaml|json to get the full version.\n") fmt.Fprintf(os.Stdout, "Client Version: %#v\n", clientVersion) } + if len(versionInfo.ReleaseVersion) != 0 { + fmt.Fprintf(os.Stdout, "Client Release Version: %s\n", versionInfo.ReleaseVersion) + } case "yaml": marshalled, err := yaml.Marshal(&versionInfo) if err != nil { @@ -130,8 +158,8 @@ func (o *VersionOptions) Run() error { return nil } -func Get() Info { - return Info{ +func Get() version.Info { + return version.Info{ Major: majorFromGit, Minor: minorFromGit, GitCommit: commitFromGit,