Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

airgap bundle upgrade #6682

Merged
merged 4 commits into from
Feb 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions components/automate-cli/cmd/chef-automate/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,12 @@ func statusUpgradeCmd(cmd *cobra.Command, args []string) error {
case api.UpgradeStatusResponse_IDLE:
switch {
//Todo(milestone) - update the comparison logic of current version and latest available version
case resp.CurrentVersion != "" && resp.CurrentVersion < resp.LatestAvailableVersion:
writer.Printf("Automate is out-of-date (current version: %s; latest available: %s; airgapped: %v)\n",
resp.CurrentVersion, resp.LatestAvailableVersion, resp.IsAirgapped)
case resp.CurrentVersion != "":
if resp.IsAirgapped {
writer.Printf("Automate is up-to-date with airgap bundle (%s)\n", resp.CurrentVersion)
} else if resp.CurrentVersion < resp.LatestAvailableVersion {
writer.Printf("Automate is out-of-date (current version: %s; latest available: %s; airgapped: %v)\n",
resp.CurrentVersion, resp.LatestAvailableVersion, resp.IsAirgapped)
} else {
writer.Printf("Automate is up-to-date (%s)\n", resp.CurrentVersion)
}
Expand Down
152 changes: 95 additions & 57 deletions components/automate-deployment/pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1864,9 +1864,45 @@ func (s *server) IsValidUpgrade(ctx context.Context, req *api.UpgradeRequest) (*
nextManifestVersion = compVersion
}
}
} else {
m, err := s.releaseManifestProvider.RefreshManifest(ctx, channel)
if err != nil {
return nil, err
}
nextManifestVersion = m.Version()

//compare minimum compatible version with current version, i.e current version should be greater than or equal than min compatible version
minCompVersion := m.MinCompatibleVer
if minCompVersion == "" {
return nil, status.Error(codes.InvalidArgument, "mandatory minimum compatable version is missing")
} else if !isCompatibleForAirgap(currentRelease, minCompVersion) {
return nil, status.Errorf(codes.OutOfRange, "the version specified %q is not compatible for the current version %q. The compatible version is %q", nextManifestVersion, currentRelease, minCompVersion)
}

//check for upgrade or degrade, we should not allow degrading
if isDegrade(currentRelease, nextManifestVersion) {
return nil, status.Errorf(codes.OutOfRange, "the version specified %q is not compatible for the current version %q", nextManifestVersion, currentRelease)
}

isActualMajorUpgrade := isMajorUpgrade(currentRelease, nextManifestVersion)

//check the upgrade is major or not, and if the upgrade is minor/patch, user should not provide --major flag
if !isActualMajorUpgrade && req.IsMajorUpgrade {
return nil, status.Errorf(codes.InvalidArgument, "please use `chef-automate upgrade run --airgap-bundle` to further upgrade")
}

//check the upgrade is major or not, and if the upgrade is major user should provide --major flag.
if isActualMajorUpgrade && !req.IsMajorUpgrade {
return nil, status.Errorf(codes.InvalidArgument, "please use `chef-automate upgrade run --major --airgap-bundle` to further upgrade")
}

}

if req.Version != "" {
if airgap.AirgapInUse() {
return nil, status.Errorf(codes.InvalidArgument, "specifying a version is not allowed in airgap mode, please use `chef-automate upgrade run --airgap-bundle`")
}

if nextManifestVersion != req.Version && !isCompatible(currentRelease, req.Version, nextManifestVersion) {
return nil, status.Errorf(codes.OutOfRange, "the version specified %q is not compatible for the current version %q", req.Version, currentRelease)
}
Expand All @@ -1888,65 +1924,13 @@ func (s *server) IsValidUpgrade(ctx context.Context, req *api.UpgradeRequest) (*

// Upgrade requests the deployment-service pulls down the latest manifest and applies it
func (s *server) Upgrade(ctx context.Context, req *api.UpgradeRequest) (*api.UpgradeResponse, error) {
if !s.HasConfiguredDeployment() {
return nil, ErrorNotConfigured
}

var currentRelease = ""
s.deployment.Lock()
if s.deployment.CurrentReleaseManifest != nil {
currentRelease = s.deployment.CurrentReleaseManifest.Version()
}
channel := s.deployment.Channel()
s.deployment.Unlock()

var m *manifest.A2
var err error

nextManifestVersion := currentRelease
if !airgap.AirgapInUse() { //internet connected machine
isMinorAvailable, isMajorAvailable, compVersion, err := s.releaseManifestProvider.GetCompatibleVersion(ctx, channel, currentRelease)
if err != nil {
return nil, err
}

if !req.IsMajorUpgrade { //normal upgrade
if isMinorAvailable {
nextManifestVersion = compVersion
} else if isMajorAvailable {
return nil, status.Errorf(codes.InvalidArgument, "please use `chef-automate upgrade run --major` to further upgrade")
}
} else { //major upgrade
if isMinorAvailable {
return nil, status.Errorf(codes.InvalidArgument, "minor/patch version is available, please use `chef-automate upgrade run`")
} else if isMajorAvailable {
nextManifestVersion = compVersion
}
}
}

if req.Version != "" {
if airgap.AirgapInUse() {
return nil, status.Errorf(codes.InvalidArgument, "specifying a version is not allowed in airgap mode, please use `chef-automate upgrade run --airgap-bundle`")
}

if !isCompatible(currentRelease, req.Version, nextManifestVersion) {
return nil, status.Errorf(codes.OutOfRange, "the version specified %q is not compatible for the current version %q", req.Version, currentRelease)
}

nextManifestVersion = req.Version

// TODO(ssd) 2018-09-13: We are not currently
// requiring that the version passed is actually in
// the channel they have configured. Should we?
validatedResp, err := s.IsValidUpgrade(ctx, req)
if err != nil {
return nil, err
}
m, err = s.releaseManifestProvider.GetManifest(ctx, nextManifestVersion)
/*} else {
//m, err = s.releaseManifestProvider.RefreshManifest(ctx, channel)
//Todo(milestone) in airgap, get the manifest and perform the compatibility check.
}*/

//Todo(milestone) incase of airgap find out the upgrade is major or minor
m, err := s.releaseManifestProvider.GetManifest(ctx, validatedResp.TargetVersion)

_, ok := err.(*manifest.NoSuchManifestError)
if ok {
Expand Down Expand Up @@ -1980,12 +1964,66 @@ func (s *server) Upgrade(ctx context.Context, req *api.UpgradeRequest) (*api.Upg
}

return &api.UpgradeResponse{
PreviousVersion: currentRelease,
PreviousVersion: validatedResp.CurrentVersion,
NextVersion: m.Version(),
TaskId: task.ID.String(),
}, nil
}

//isDegrade return true, if the v2 is previous version of v1
func isDegrade(v1, v2 string) bool {
_, isV1Sem := manifest.IsSemVersionFmt(v1)
_, isV2Sem := manifest.IsSemVersionFmt(v2)

if !isV1Sem && !isV2Sem && v1 > v2 {
return true
}
if isV1Sem && isV2Sem && !manifest.IsCompareSemVersions(v1, v2) {
return true
}

if isV1Sem && !isV2Sem {
return true
}
return false
}

// IsMajorUpgrade returns true if the v2 is next major upgrade of v1 else return false
func isMajorUpgrade(v1, v2 string) bool {
v1Major, isV1Sem := manifest.IsSemVersionFmt(v1)
v2Major, isV2Sem := manifest.IsSemVersionFmt(v2)

if !isV1Sem && isV2Sem {
return true
}

if isV1Sem && isV2Sem && v1Major != v2Major {
return true
}

return false
}

//isCompatibleForAirgap will return true if the current version is greater than or equal to min compatible version
func isCompatibleForAirgap(current, minCompatibleVer string) bool {
_, isCurrentSem := manifest.IsSemVersionFmt(current)
_, isMinCompSem := manifest.IsSemVersionFmt(minCompatibleVer)

if !isCurrentSem && !isMinCompSem {
return current >= minCompatibleVer
}

if isCurrentSem && isMinCompSem {
return manifest.IsCompareSemVersions(minCompatibleVer, current)
}

//if minCompatibleVer is in timestampversion and current version is semantic version - we need to allow the upgrade
if !isMinCompSem && isCurrentSem {
return true
}
return false
}

func isCompatible(current, givenVersion, maxPossibleVersion string) bool {
_, isCurrentSem := manifest.IsSemVersionFmt(current)
givenMajor, isGivenVSem := manifest.IsSemVersionFmt(givenVersion)
Expand Down
Loading