Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/laverya/sc-106273/pass-config-va…
Browse files Browse the repository at this point in the history
…lues-to-embedded-cluster-during' into laverya/sc-106273/pass-config-values-to-embedded-cluster-during
  • Loading branch information
laverya committed Oct 31, 2024
2 parents fe88fca + a30d9b8 commit 6d711a1
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 50 deletions.
5 changes: 5 additions & 0 deletions cmd/kotsadm/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"os"
"strings"

"github.com/replicatedhq/kots/pkg/store"
"github.com/replicatedhq/kots/pkg/store/kotsstore"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand All @@ -15,6 +17,9 @@ func RootCmd() *cobra.Command {
Short: "kotsadm is the Admin Console for KOTS",
Long: ``,
Args: cobra.MinimumNArgs(1),
PersistentPreRun: func(cmd *cobra.Command, args []string) {
store.SetStore(kotsstore.StoreFromEnv())
},
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.Flags())
},
Expand Down
6 changes: 1 addition & 5 deletions pkg/apparchive/helm-v1beta1.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@ import (
)

var (
goTemplateRegex *regexp.Regexp
)

func init() {
goTemplateRegex = regexp.MustCompile(`({{)|(}})`)
}
)

func GetRenderedV1Beta1ChartsArchive(versionArchive string, downstreamName, kustomizeBinPath string) ([]byte, map[string][]byte, error) {
renderedChartsDir := filepath.Join(versionArchive, "rendered", downstreamName, "charts")
Expand Down
81 changes: 65 additions & 16 deletions pkg/store/kotsstore/downstream_store.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package kotsstore

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"time"
Expand All @@ -13,8 +15,10 @@ import (
"github.com/replicatedhq/kots/pkg/kotsutil"
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/persistence"
"github.com/replicatedhq/kots/pkg/store"
"github.com/replicatedhq/kots/pkg/store/types"
"github.com/replicatedhq/kots/pkg/tasks"
"github.com/replicatedhq/kots/pkg/util"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
"github.com/rqlite/gorqlite"
)
Expand Down Expand Up @@ -423,7 +427,10 @@ func (s *KOTSStore) GetDownstreamVersions(appID string, clusterID string, downlo
if err := s.AddDownstreamVersionDetails(appID, clusterID, v, false); err != nil {
return nil, errors.Wrap(err, "failed to add details to latest downloaded version")
}
v.IsDeployable, v.NonDeployableCause = isAppVersionDeployable(v, result, license.Spec.IsSemverRequired)
v.IsDeployable, v.NonDeployableCause, err = isAppVersionDeployable(s, appID, v, result, license.Spec.IsSemverRequired)
if err != nil {
return nil, errors.Wrapf(err, "failed to check if version %s is deployable", v.VersionLabel)
}
break
}

Expand Down Expand Up @@ -676,7 +683,10 @@ func (s *KOTSStore) AddDownstreamVersionsDetails(appID string, clusterID string,
}

for _, v := range versions {
v.IsDeployable, v.NonDeployableCause = isAppVersionDeployable(v, allVersions, license.Spec.IsSemverRequired)
v.IsDeployable, v.NonDeployableCause, err = isAppVersionDeployable(s, appID, v, allVersions, license.Spec.IsSemverRequired)
if err != nil {
return errors.Wrapf(err, "failed to check if version %s is deployable", v.VersionLabel)
}
}
}

Expand Down Expand Up @@ -866,28 +876,32 @@ func isSameUpstreamRelease(v1 *downstreamtypes.DownstreamVersion, v2 *downstream
return v1.Semver.EQ(*v2.Semver)
}

func isAppVersionDeployable(version *downstreamtypes.DownstreamVersion, appVersions *downstreamtypes.DownstreamVersions, isSemverRequired bool) (bool, string) {
func isAppVersionDeployable(
versionStore store.VersionStore,
appID string, version *downstreamtypes.DownstreamVersion, appVersions *downstreamtypes.DownstreamVersions,
isSemverRequired bool,
) (bool, string, error) {
if version.HasFailingStrictPreflights {
return false, "Deployment is disabled as a strict analyzer in this version's preflight checks has failed or has not been run."
return false, "Deployment is disabled as a strict analyzer in this version's preflight checks has failed or has not been run.", nil
}

if version.Status == types.VersionPendingDownload {
return false, "Version is pending download."
return false, "Version is pending download.", nil
}

if version.Status == types.VersionPendingConfig {
return false, "Version is pending configuration."
return false, "Version is pending configuration.", nil
}

if appVersions.CurrentVersion == nil {
// no version has been deployed yet, treat as an initial install where any version can be deployed at first.
return true, ""
return true, "", nil
}

if version.Sequence == appVersions.CurrentVersion.Sequence {
// version is currently deployed, so previous required versions should've already been deployed.
// also, we shouldn't block re-deploying if a previous release is edited later by the vendor to be required.
return true, ""
return true, "", nil
}

// rollback support is determined across all versions from all channels
Expand All @@ -906,18 +920,41 @@ func isAppVersionDeployable(version *downstreamtypes.DownstreamVersion, appVersi
break
}
}

// This is a past version
if versionIndex > deployedVersionIndex {
// this is a past version
// rollback support is based off of the latest downloaded version
// Rollback support is based off of the latest downloaded version so that a vendor can
// toggle on support without requiring the end user to deploy a new version.
for _, v := range appVersions.AllVersions {
// Find the first version that is not pending download. This will be the latest
// version.
if v.Status == types.VersionPendingDownload {
continue
}
if v.KOTSKinds == nil || !v.KOTSKinds.KotsApplication.Spec.AllowRollback {
return false, "Rollback is not supported."
return false, "Rollback is not supported.", nil
}
break
}

if util.IsEmbeddedCluster() && appVersions.CurrentVersion != nil {
currentECConfig, err := getRawEmbeddedClusterConfigForVersion(versionStore, appID, appVersions.CurrentVersion.Sequence)
if err != nil {
return false, "", errors.Wrapf(err, "failed to get embedded cluster config for current version %d", appVersions.CurrentVersion.Sequence)
}
newECConfig, err := getRawEmbeddedClusterConfigForVersion(versionStore, appID, version.Sequence)
if err != nil {
return false, "", errors.Wrapf(err, "failed to get embedded cluster config for version %d", version.Sequence)
}
if util.IsEmbeddedCluster() && currentECConfig != nil {
// Compare the embedded cluster config of the version specified to the currently
// deployed version to check if it has changed. If it has, then we do not allow
// rollbacks.
if !bytes.Equal(currentECConfig, newECConfig) {
return false, "Rollback is not supported, cluster configuration has changed.", nil
}
}
}
}

// if semantic versioning is not enabled, only require versions from the same channel AND with a lower cursor/channel sequence
Expand Down Expand Up @@ -951,7 +988,7 @@ func isAppVersionDeployable(version *downstreamtypes.DownstreamVersion, appVersi

if deployedVersionIndex == -1 {
// the deployed version is from a different channel
return true, ""
return true, "", nil
}

// find required versions between the deployed version and the desired version
Expand All @@ -969,7 +1006,7 @@ ALL_VERSIONS_LOOP:
// this is a past version
// >= because if the deployed version is required, rolling back isn't allowed
if i >= deployedVersionIndex && i < versionIndex {
return false, "One or more non-reversible versions have been deployed since this version."
return false, "One or more non-reversible versions have been deployed since this version.", nil
}
continue
}
Expand Down Expand Up @@ -997,12 +1034,24 @@ ALL_VERSIONS_LOOP:
}
versionLabelsStr := strings.Join(versionLabels, ", ")
if len(requiredVersions) == 1 {
return false, fmt.Sprintf("This version cannot be deployed because version %s is required and must be deployed first.", versionLabelsStr)
return false, fmt.Sprintf("This version cannot be deployed because version %s is required and must be deployed first.", versionLabelsStr), nil
}
return false, fmt.Sprintf("This version cannot be deployed because versions %s are required and must be deployed first.", versionLabelsStr)
return false, fmt.Sprintf("This version cannot be deployed because versions %s are required and must be deployed first.", versionLabelsStr), nil
}

return true, ""
return true, "", nil
}

func getRawEmbeddedClusterConfigForVersion(versionStore store.VersionStore, appID string, sequence int64) ([]byte, error) {
currentConf, err := versionStore.GetEmbeddedClusterConfigForVersion(appID, sequence)
if err != nil {
return nil, errors.Wrap(err, "failed to get embedded cluster config")
}
b, err := json.Marshal(currentConf)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal embedded cluster config")
}
return b, nil
}

func getReleaseNotes(appID string, parentSequence int64) (string, error) {
Expand Down
Loading

0 comments on commit 6d711a1

Please sign in to comment.