Skip to content

Commit

Permalink
save config api for upgrade service (#4681)
Browse files Browse the repository at this point in the history
* save config api for upgrade service

* update setProgress and setResults

* remove TODO

* Update pkg/upgradeservice/preflight/preflight.go

Co-authored-by: Salah Al Saleh <[email protected]>

* clean up result and progress funcs

* remove run error from setResult func

---------

Co-authored-by: Salah Al Saleh <[email protected]>
  • Loading branch information
Craig O'Donnell and sgalsaleh authored Jun 14, 2024
1 parent 28b553e commit b4deb57
Show file tree
Hide file tree
Showing 20 changed files with 669 additions and 271 deletions.
28 changes: 4 additions & 24 deletions pkg/handlers/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
registrytypes "github.com/replicatedhq/kots/pkg/registry/types"
"github.com/replicatedhq/kots/pkg/render"
rendertypes "github.com/replicatedhq/kots/pkg/render/types"
"github.com/replicatedhq/kots/pkg/reporting"
"github.com/replicatedhq/kots/pkg/store"
storetypes "github.com/replicatedhq/kots/pkg/store/types"
"github.com/replicatedhq/kots/pkg/template"
Expand Down Expand Up @@ -650,7 +651,7 @@ func updateAppConfig(updateApp *apptypes.App, sequence int64, configGroups []kot
return updateAppConfigResponse, err
}

requiredItems, requiredItemsTitles := getMissingRequiredConfig(configGroups)
requiredItems, requiredItemsTitles := kotsadmconfig.GetMissingRequiredConfig(configGroups)

// not having all the required items is only a failure for the version that the user intended to edit
if len(requiredItems) > 0 && isPrimaryVersion {
Expand All @@ -663,7 +664,7 @@ func updateAppConfig(updateApp *apptypes.App, sequence int64, configGroups []kot
// so we don't need the complex logic in kots, we can just write
if kotsKinds.ConfigValues != nil {
values := kotsKinds.ConfigValues.Spec.Values
kotsKinds.ConfigValues.Spec.Values = updateAppConfigValues(values, configGroups)
kotsKinds.ConfigValues.Spec.Values = kotsadmconfig.UpdateAppConfigValues(values, configGroups)

configValuesSpec, err := kotsKinds.Marshal("kots.io", "v1beta1", "ConfigValues")
if err != nil {
Expand Down Expand Up @@ -736,6 +737,7 @@ func updateAppConfig(updateApp *apptypes.App, sequence int64, configGroups []kot
Downstreams: downstreams,
RegistrySettings: registrySettings,
Sequence: renderSequence,
ReportingInfo: reporting.GetReportingInfo(app.ID),
})
if err != nil {
cause := errors.Cause(err)
Expand Down Expand Up @@ -800,28 +802,6 @@ func updateAppConfig(updateApp *apptypes.App, sequence int64, configGroups []kot
return updateAppConfigResponse, nil
}

func getMissingRequiredConfig(configGroups []kotsv1beta1.ConfigGroup) ([]string, []string) {
requiredItems := make([]string, 0, 0)
requiredItemsTitles := make([]string, 0, 0)
for _, group := range configGroups {
if group.When == "false" {
continue
}
for _, item := range group.Items {
if kotsadmconfig.IsRequiredItem(item) && kotsadmconfig.IsUnsetItem(item) {
requiredItems = append(requiredItems, item.Name)
if item.Title != "" {
requiredItemsTitles = append(requiredItemsTitles, item.Title)
} else {
requiredItemsTitles = append(requiredItemsTitles, item.Name)
}
}
}
}

return requiredItems, requiredItemsTitles
}

func updateAppConfigValues(values map[string]kotsv1beta1.ConfigValue, configGroups []kotsv1beta1.ConfigGroup) map[string]kotsv1beta1.ConfigValue {
for _, group := range configGroups {
for _, item := range group.Items {
Expand Down
2 changes: 2 additions & 0 deletions pkg/handlers/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/replicatedhq/kots/pkg/rbac"
"github.com/replicatedhq/kots/pkg/render"
rendertypes "github.com/replicatedhq/kots/pkg/render/types"
"github.com/replicatedhq/kots/pkg/reporting"
"github.com/replicatedhq/kots/pkg/store"
"github.com/replicatedhq/kots/pkg/util"
"github.com/replicatedhq/kots/pkg/version"
Expand Down Expand Up @@ -461,6 +462,7 @@ func (h *Handler) ConfigureAppIdentityService(w http.ResponseWriter, r *http.Req
Downstreams: downstreams,
RegistrySettings: registrySettings,
Sequence: nextAppSequence,
ReportingInfo: reporting.GetReportingInfo(a.ID),
})
if err != nil {
err = errors.Wrap(err, "failed to render archive directory")
Expand Down
2 changes: 2 additions & 0 deletions pkg/handlers/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/replicatedhq/kots/pkg/preflight"
"github.com/replicatedhq/kots/pkg/render"
rendertypes "github.com/replicatedhq/kots/pkg/render/types"
"github.com/replicatedhq/kots/pkg/reporting"
"github.com/replicatedhq/kots/pkg/store"
storetypes "github.com/replicatedhq/kots/pkg/store/types"
"github.com/replicatedhq/kots/pkg/util"
Expand Down Expand Up @@ -165,6 +166,7 @@ func (h *Handler) UploadExistingApp(w http.ResponseWriter, r *http.Request) {
Downstreams: downstreams,
RegistrySettings: registrySettings,
Sequence: nextAppSequence,
ReportingInfo: reporting.GetReportingInfo(a.ID),
})
if err != nil {
cause := errors.Cause(err)
Expand Down
75 changes: 75 additions & 0 deletions pkg/kotsadmconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ package kotsadmconfig

import (
"context"
"encoding/base64"
"fmt"
"os"
"strconv"

"github.com/pkg/errors"
kotsconfig "github.com/replicatedhq/kots/pkg/config"
"github.com/replicatedhq/kots/pkg/crypto"
"github.com/replicatedhq/kots/pkg/k8sutil"
"github.com/replicatedhq/kots/pkg/kotsutil"
"github.com/replicatedhq/kots/pkg/logger"
registrytypes "github.com/replicatedhq/kots/pkg/registry/types"
"github.com/replicatedhq/kots/pkg/template"
"github.com/replicatedhq/kots/pkg/util"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
"github.com/replicatedhq/kotskinds/multitype"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -91,6 +96,76 @@ func NeedsConfiguration(appSlug string, sequence int64, isAirgap bool, kotsKinds
return false, nil
}

func GetMissingRequiredConfig(configGroups []kotsv1beta1.ConfigGroup) ([]string, []string) {
requiredItems := make([]string, 0, 0)
requiredItemsTitles := make([]string, 0, 0)
for _, group := range configGroups {
if group.When == "false" {
continue
}
for _, item := range group.Items {
if IsRequiredItem(item) && IsUnsetItem(item) {
requiredItems = append(requiredItems, item.Name)
if item.Title != "" {
requiredItemsTitles = append(requiredItemsTitles, item.Title)
} else {
requiredItemsTitles = append(requiredItemsTitles, item.Name)
}
}
}
}

return requiredItems, requiredItemsTitles
}

func UpdateAppConfigValues(values map[string]kotsv1beta1.ConfigValue, configGroups []kotsv1beta1.ConfigGroup) map[string]kotsv1beta1.ConfigValue {
for _, group := range configGroups {
for _, item := range group.Items {
if item.Type == "file" {
v := values[item.Name]
v.Filename = item.Filename
values[item.Name] = v
}
if item.Value.Type == multitype.Bool {
updatedValue := item.Value.BoolVal
v := values[item.Name]
v.Value = strconv.FormatBool(updatedValue)
values[item.Name] = v
} else if item.Value.Type == multitype.String {
updatedValue := item.Value.String()
if item.Type == "password" {
// encrypt using the key
// if the decryption succeeds, don't encrypt again
_, err := util.DecryptConfigValue(updatedValue)
if err != nil {
updatedValue = base64.StdEncoding.EncodeToString(crypto.Encrypt([]byte(updatedValue)))
}
}

v := values[item.Name]
v.Value = updatedValue
values[item.Name] = v
}
for _, repeatableValues := range item.ValuesByGroup {
// clear out all variadic values for this group first
for name, value := range values {
if value.RepeatableItem == item.Name {
delete(values, name)
}
}
// add variadic groups back in declaratively
for itemName, valueItem := range repeatableValues {
v := values[itemName]
v.Value = fmt.Sprintf("%v", valueItem)
v.RepeatableItem = item.Name
values[itemName] = v
}
}
}
}
return values
}

func ReadConfigValuesFromInClusterSecret() (string, error) {
log := logger.NewCLILogger(os.Stdout)

Expand Down
7 changes: 5 additions & 2 deletions pkg/kotsadmlicense/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/replicatedhq/kots/pkg/preflight"
"github.com/replicatedhq/kots/pkg/render"
"github.com/replicatedhq/kots/pkg/replicatedapp"
"github.com/replicatedhq/kots/pkg/reporting"
"github.com/replicatedhq/kots/pkg/store"
"github.com/replicatedhq/kots/pkg/version"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
Expand Down Expand Up @@ -84,7 +85,8 @@ func Sync(a *apptypes.App, licenseString string, failOnVersionCreate bool) (*kot
if updatedLicense.Spec.ChannelID != currentLicense.Spec.ChannelID {
channelChanged = true
}
newSequence, err := store.GetStore().UpdateAppLicense(a.ID, latestSequence, archiveDir, updatedLicense, licenseString, channelChanged, failOnVersionCreate, &version.DownstreamGitOps{}, &render.Renderer{})
reportingInfo := reporting.GetReportingInfo(a.ID)
newSequence, err := store.GetStore().UpdateAppLicense(a.ID, latestSequence, archiveDir, updatedLicense, licenseString, channelChanged, failOnVersionCreate, &version.DownstreamGitOps{}, &render.Renderer{}, reportingInfo)
if err != nil {
return nil, false, errors.Wrap(err, "failed to update license")
}
Expand Down Expand Up @@ -190,7 +192,8 @@ func Change(a *apptypes.App, newLicenseString string) (*kotsv1beta1.License, err
if newLicense.Spec.ChannelID != currentLicense.Spec.ChannelID {
channelChanged = true
}
newSequence, err := store.GetStore().UpdateAppLicense(a.ID, latestSequence, archiveDir, newLicense, newLicenseString, channelChanged, true, &version.DownstreamGitOps{}, &render.Renderer{})
reportingInfo := reporting.GetReportingInfo(a.ID)
newSequence, err := store.GetStore().UpdateAppLicense(a.ID, latestSequence, archiveDir, newLicense, newLicenseString, channelChanged, true, &version.DownstreamGitOps{}, &render.Renderer{}, reportingInfo)
if err != nil {
return nil, errors.Wrap(err, "failed to update license")
}
Expand Down
65 changes: 22 additions & 43 deletions pkg/preflight/execute.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package preflight

import (
"encoding/json"
"strings"
"sync"
"time"
Expand All @@ -10,45 +9,16 @@ import (
"github.com/replicatedhq/kots/pkg/k8sutil"
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/preflight/types"
"github.com/replicatedhq/kots/pkg/store"
troubleshootanalyze "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
troubleshootcollect "github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/preflight"
troubleshootpreflight "github.com/replicatedhq/troubleshoot/pkg/preflight"
"go.uber.org/zap"
)

func setPreflightResult(appID string, sequence int64, preflightResults *types.PreflightResults, preflightRunError error) error {
if preflightRunError != nil {
if preflightResults.Errors == nil {
preflightResults.Errors = []*types.PreflightError{}
}
preflightResults.Errors = append(preflightResults.Errors, &types.PreflightError{
Error: preflightRunError.Error(),
IsRBAC: false,
})
}

b, err := json.Marshal(preflightResults)
if err != nil {
return errors.Wrap(err, "failed to marshal preflight results")
}

if err := store.GetStore().SetPreflightResults(appID, sequence, b); err != nil {
return errors.Wrap(err, "failed to set preflight results")
}

return nil
}

// execute will execute the preflights using spec in preflightSpec.
// Execute will Execute the preflights using spec in preflightSpec.
// This spec should be rendered, no template functions remaining
func execute(appID string, sequence int64, preflightSpec *troubleshootv1beta2.Preflight, ignorePermissionErrors bool) (*types.PreflightResults, error) {
logger.Info("executing preflight checks",
zap.String("appID", appID),
zap.Int64("sequence", sequence))

func Execute(preflightSpec *troubleshootv1beta2.Preflight, ignorePermissionErrors bool, setProgress func(progress map[string]interface{}) error, setResults func(results *types.PreflightResults) error) (*types.PreflightResults, error) {
progressChan := make(chan interface{}, 0) // non-zero buffer will result in missed messages
defer close(progressChan)

Expand All @@ -73,26 +43,25 @@ func execute(appID string, sequence int64, preflightSpec *troubleshootv1beta2.Pr
}
}

progress, ok := msg.(preflight.CollectProgress)
collectProgress, ok := msg.(preflight.CollectProgress)
if !ok {
continue
}

// TODO: We need a nice title to display
progressBytes, err := json.Marshal(map[string]interface{}{
"completedCount": progress.CompletedCount,
"totalCount": progress.TotalCount,
"currentName": progress.CurrentName,
"currentStatus": progress.CurrentStatus,
progress := map[string]interface{}{
"completedCount": collectProgress.CompletedCount,
"totalCount": collectProgress.TotalCount,
"currentName": collectProgress.CurrentName,
"currentStatus": collectProgress.CurrentStatus,
"updatedAt": time.Now().Format(time.RFC3339),
})
if err != nil {
continue
}

completeMx.Lock()
if !isComplete {
_ = store.GetStore().SetPreflightProgress(appID, sequence, string(progressBytes))
if err := setProgress(progress); err != nil {
logger.Error(errors.Wrap(err, "failed to set preflight progress"))
}
}
completeMx.Unlock()
}
Expand All @@ -104,7 +73,17 @@ func execute(appID string, sequence int64, preflightSpec *troubleshootv1beta2.Pr
defer completeMx.Unlock()

isComplete = true
if err := setPreflightResult(appID, sequence, uploadPreflightResults, preflightRunError); err != nil {

if preflightRunError != nil {
if uploadPreflightResults.Errors == nil {
uploadPreflightResults.Errors = []*types.PreflightError{}
}
uploadPreflightResults.Errors = append(uploadPreflightResults.Errors, &types.PreflightError{
Error: preflightRunError.Error(),
IsRBAC: false,
})
}
if err := setResults(uploadPreflightResults); err != nil {
logger.Error(errors.Wrap(err, "failed to set preflight results"))
return
}
Expand Down
Loading

0 comments on commit b4deb57

Please sign in to comment.