Skip to content

Commit

Permalink
airgap bundle upgrade (#6682)
Browse files Browse the repository at this point in the history
* airgap upgrade

Signed-off-by: Durga Sarat Chandra Maddu <[email protected]>

* upgrade status for airgap

Signed-off-by: Durga Sarat Chandra Maddu <[email protected]>

* upgrade status for airgap instance

Signed-off-by: Durga Sarat Chandra Maddu <[email protected]>

* addressing review comments

Signed-off-by: Durga Sarat Chandra Maddu <[email protected]>
  • Loading branch information
Dmaddu committed Feb 28, 2022
1 parent c565896 commit dbc94f2
Show file tree
Hide file tree
Showing 4 changed files with 318 additions and 63 deletions.
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

0 comments on commit dbc94f2

Please sign in to comment.