Skip to content

Commit

Permalink
Surface cluster upgrade errors
Browse files Browse the repository at this point in the history
  • Loading branch information
sgalsaleh committed Jul 11, 2024
1 parent b6e9bad commit 5fdb3bf
Show file tree
Hide file tree
Showing 33 changed files with 556 additions and 591 deletions.
7 changes: 0 additions & 7 deletions .github/workflows/build-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1939,13 +1939,6 @@ jobs:
exit $EXIT_CODE
fi
# validate that preflight checks ran
JSON_PATH="jsonpath={.data['automated-install-slug-$APP_SLUG']}"
if [ "$(kubectl get cm kotsadm-tasks -n "$APP_SLUG" -o "$JSON_PATH" | grep -c pending_preflight)" != "1" ]; then
echo "Preflight checks did not run"
exit 1
fi
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
Expand Down
39 changes: 32 additions & 7 deletions cmd/kots/cli/airgap-update.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/replicatedhq/kots/pkg/image"
imagetypes "github.com/replicatedhq/kots/pkg/image/types"
"github.com/replicatedhq/kots/pkg/k8sutil"
"github.com/replicatedhq/kots/pkg/kotsutil"
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/tasks"
"github.com/replicatedhq/kots/pkg/upload"
Expand Down Expand Up @@ -88,14 +89,10 @@ func AirgapUpdateCmd() *cobra.Command {
return errors.Wrap(err, "failed to stat airgap bundle")
}

updateFiles := []string{
"airgap.yaml",
"app.tar.gz",
}
if util.IsEmbeddedCluster() {
updateFiles = append(updateFiles, "embedded-cluster/artifacts/kots.tar.gz")
updateFiles, err := getAirgapUpdateFiles(airgapBundle)
if err != nil {
return errors.Wrap(err, "failed to get airgap update files")
}

airgapUpdate, err := archives.FilterAirgapBundle(airgapBundle, updateFiles)
if err != nil {
return errors.Wrap(err, "failed to create filtered airgap bundle")
Expand Down Expand Up @@ -170,6 +167,34 @@ func getProgressWriter(v *viper.Viper, log *logger.CLILogger) io.Writer {
return os.Stdout
}

func getAirgapUpdateFiles(airgapBundle string) ([]string, error) {
airgap, err := kotsutil.FindAirgapMetaInBundle(airgapBundle)
if err != nil {
return nil, errors.Wrap(err, "failed to find airgap meta in bundle")
}

if airgap.Spec.EmbeddedClusterArtifacts == nil {
return nil, errors.New("embedded cluster artifacts not found in airgap bundle")
}

if airgap.Spec.EmbeddedClusterArtifacts.Metadata == "" {
return nil, errors.New("embedded cluster metadata not found in airgap bundle")
}

if airgap.Spec.EmbeddedClusterArtifacts.AdditionalArtifacts == nil {
return nil, errors.New("embedded cluster additional artifacts not found in airgap bundle")
}

files := []string{
"airgap.yaml",
"app.tar.gz",
airgap.Spec.EmbeddedClusterArtifacts.Metadata,
airgap.Spec.EmbeddedClusterArtifacts.AdditionalArtifacts["kots"],
}

return files, nil
}

func uploadAirgapUpdate(airgapBundle string, uploadEndpoint string, namespace string) error {
buffer := bytes.NewBuffer(nil)
writer := multipart.NewWriter(buffer)
Expand Down
16 changes: 5 additions & 11 deletions cmd/kots/cli/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,18 @@ func VersionCmd() *cobra.Command {

output := v.GetString("output")

isLatest, latestVer, err := buildversion.IsLatestRelease()
versionOutput := VersionOutput{
Version: buildversion.Version(),
}
if !v.GetBool("skip-checks") {
isLatest, latestVer, err := buildversion.IsLatestRelease()
if err == nil && !isLatest {
versionOutput.LatestVersion = latestVer
versionOutput.InstallLatest = "curl https://kots.io/install | bash"
}
if err == nil && !isLatest {
versionOutput.LatestVersion = latestVer
versionOutput.InstallLatest = "curl https://kots.io/install | bash"
}

if output != "json" && output != "" {
return errors.Errorf("output format %s not supported (allowed formats are: json)", output)
}

if output == "json" {
} else if output == "json" {
// marshal JSON
outputJSON, err := json.Marshal(versionOutput)
if err != nil {
Expand All @@ -66,8 +62,6 @@ func VersionCmd() *cobra.Command {
}

cmd.Flags().StringP("output", "o", "", "output format (currently supported: json)")
cmd.Flags().Bool("skip-checks", false, "skip any checks and just print the version")
cmd.Flags().MarkHidden("skip-checks")

return cmd
}
2 changes: 1 addition & 1 deletion pkg/airgap/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func UpdateAppFromECBundle(appSlug string, airgapBundlePath string) (finalError
finishedChan <- finalError
}()

kotsBin, err := archives.GetKOTSBinFromAirgapBundle(airgapBundlePath)
kotsBin, err := kotsutil.GetKOTSBinFromAirgapBundle(airgapBundlePath)
if err != nil {
return errors.Wrap(err, "failed to get kots binary from airgap bundle")
}
Expand Down
2 changes: 0 additions & 2 deletions pkg/api/handlers/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ type ResponseGitOps struct {
type ResponseCluster struct {
ID string `json:"id"`
Slug string `json:"slug"`
// IsUpgrading represents whether the embedded cluster is currently being upgraded
IsUpgrading bool `json:"isUpgrading"`
// State represents the current state of the most recently deployed embedded cluster config
State string `json:"state,omitempty"`
}
Expand Down
17 changes: 0 additions & 17 deletions pkg/archives/airgap.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,3 @@ func FilterAirgapBundle(airgapBundle string, filesToKeep []string) (string, erro

return f.Name(), nil
}

func GetKOTSBinFromAirgapBundle(airgapBundle string) (string, error) {
kotsTGZ, err := GetFileFromTGZArchive("embedded-cluster/artifacts/kots.tar.gz", airgapBundle)
if err != nil {
return "", errors.Wrap(err, "failed to get kots tarball from airgap bundle")
}
defer os.Remove(kotsTGZ)

kotsBin, err := GetFileFromTGZArchive("kots", kotsTGZ)
if err != nil {
return "", errors.Wrap(err, "failed to get kots binary from kots tarball")
}
if err := os.Chmod(kotsBin, 0755); err != nil {
return "", errors.Wrap(err, "failed to chmod kots binary")
}
return kotsBin, nil
}
5 changes: 0 additions & 5 deletions pkg/buildversion/buildversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"io/ioutil"
"net/http"
"runtime"
"strings"
"time"

semver "github.com/Masterminds/semver/v3"
Expand Down Expand Up @@ -85,10 +84,6 @@ func GetUserAgent() string {
return fmt.Sprintf("KOTS/%s", Version())
}

func IsSameVersion(version string) bool {
return strings.TrimPrefix(Version(), "v") == strings.TrimPrefix(version, "v")
}

// IsLatestRelease queries github for the latest release in the project repo. If that release has a semver greater
// than the current release, it returns false and the new latest release semver. Otherwise, it returns true or error
func IsLatestRelease() (bool, string, error) {
Expand Down
32 changes: 11 additions & 21 deletions pkg/embeddedcluster/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"sort"
"time"

embeddedclusterv1beta1 "github.com/replicatedhq/embedded-cluster-kinds/apis/v1beta1"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
Expand Down Expand Up @@ -77,27 +76,18 @@ func ListInstallations(ctx context.Context, kbClient kbclient.Client) ([]embedde
return installationList.Items, nil
}

// WaitForInstallation will block until the current installation object reaches a terminal state.
func WaitForInstallation(ctx context.Context, kbClient kbclient.Client) error {
for {
select {
case <-ctx.Done():
return fmt.Errorf("context cancelled")
default:
ins, err := GetCurrentInstallation(ctx, kbClient)
if err != nil {
return fmt.Errorf("failed to get current installation: %w", err)
}
switch ins.Status.State {
case embeddedclusterv1beta1.InstallationStateInstalled,
embeddedclusterv1beta1.InstallationStateObsolete,
embeddedclusterv1beta1.InstallationStateFailed,
embeddedclusterv1beta1.InstallationStateHelmChartUpdateFailure:
return nil
}
time.Sleep(5 * time.Second)
}
func InstallationSucceeded(ctx context.Context, ins *embeddedclusterv1beta1.Installation) bool {
return ins.Status.State == embeddedclusterv1beta1.InstallationStateInstalled
}

func InstallationFailed(ctx context.Context, ins *embeddedclusterv1beta1.Installation) bool {
switch ins.Status.State {
case embeddedclusterv1beta1.InstallationStateFailed,
embeddedclusterv1beta1.InstallationStateHelmChartUpdateFailure,
embeddedclusterv1beta1.InstallationStateObsolete:
return true
}
return false
}

// ClusterConfig will extract the current cluster configuration from the latest installation
Expand Down
8 changes: 0 additions & 8 deletions pkg/handlers/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
storetypes "github.com/replicatedhq/kots/pkg/store/types"
"github.com/replicatedhq/kots/pkg/tasks"
"github.com/replicatedhq/kots/pkg/update"
upgradeservicedeploy "github.com/replicatedhq/kots/pkg/upgradeservice/deploy"
"github.com/replicatedhq/kots/pkg/util"
"github.com/replicatedhq/kots/pkg/version"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
Expand Down Expand Up @@ -278,14 +277,7 @@ func responseAppFromApp(ctx context.Context, a *apptypes.App) (*types.ResponseAp
ID: d.ClusterID,
Slug: d.ClusterSlug,
}

if util.IsEmbeddedCluster() {
isUpgrading, err := upgradeservicedeploy.IsClusterUpgrading(ctx, a.Slug)
if err != nil {
return nil, errors.Wrap(err, "failed to check if cluster is upgrading")
}
cluster.IsUpgrading = isUpgrading

kbClient, err := k8sutil.GetKubeClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get kubeclient: %w", err)
Expand Down
34 changes: 19 additions & 15 deletions pkg/handlers/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/replicatedhq/kots/pkg/k8sutil"
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/store"
"github.com/replicatedhq/kots/pkg/util"
"github.com/replicatedhq/kots/pkg/version"
)

Expand Down Expand Up @@ -39,20 +40,6 @@ func (h *Handler) GetAppDashboard(w http.ResponseWriter, r *http.Request) {
return
}

kbClient, err := k8sutil.GetKubeClient(r.Context())
if err != nil {
logger.Error(err)
w.WriteHeader(500)
return
}

ecInstallation, err := embeddedcluster.GetCurrentInstallation(r.Context(), kbClient)
if err != nil {
logger.Error(err)
w.WriteHeader(500)
return
}

parentSequence, err := store.GetStore().GetCurrentParentSequence(a.ID, clusterID)
if err != nil {
logger.Error(err)
Expand All @@ -79,11 +66,28 @@ func (h *Handler) GetAppDashboard(w http.ResponseWriter, r *http.Request) {
metrics = version.GetMetricCharts(graphs, prometheusAddress)
}

embeddedClusterState := ""
if util.IsEmbeddedCluster() {
kbClient, err := k8sutil.GetKubeClient(r.Context())
if err != nil {
logger.Error(err)
w.WriteHeader(500)
return
}
ecInstallation, err := embeddedcluster.GetCurrentInstallation(r.Context(), kbClient)
if err != nil {
logger.Error(err)
w.WriteHeader(500)
return
}
embeddedClusterState = ecInstallation.Status.State
}

getAppDashboardResponse := GetAppDashboardResponse{
AppStatus: appStatus,
Metrics: metrics,
PrometheusAddress: prometheusAddress,
EmbeddedClusterState: ecInstallation.Status.State,
EmbeddedClusterState: embeddedClusterState,
}

JSON(w, 200, getAppDashboardResponse)
Expand Down
36 changes: 15 additions & 21 deletions pkg/handlers/upgrade_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"github.com/phayes/freeport"
"github.com/pkg/errors"
apptypes "github.com/replicatedhq/kots/pkg/app/types"
"github.com/replicatedhq/kots/pkg/archives"
"github.com/replicatedhq/kots/pkg/buildversion"
"github.com/replicatedhq/kots/pkg/kotsutil"
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/replicatedapp"
Expand All @@ -21,6 +19,7 @@ import (
"github.com/replicatedhq/kots/pkg/upgradeservice"
upgradeservicetask "github.com/replicatedhq/kots/pkg/upgradeservice/task"
upgradeservicetypes "github.com/replicatedhq/kots/pkg/upgradeservice/types"
"github.com/replicatedhq/kots/pkg/util"
)

type StartUpgradeServiceRequest struct {
Expand Down Expand Up @@ -212,7 +211,7 @@ func getUpgradeServiceParams(a *apptypes.App, r StartUpgradeServiceRequest) (*up
return nil, errors.Wrap(err, "failed to parse app license")
}

var updateKOTSVersion string
var updateECVersion string
var updateKOTSBin string
var updateAirgapBundle string

Expand All @@ -222,32 +221,27 @@ func getUpgradeServiceParams(a *apptypes.App, r StartUpgradeServiceRequest) (*up
return nil, errors.Wrap(err, "failed to get airgap update")
}
updateAirgapBundle = au
kb, err := archives.GetKOTSBinFromAirgapBundle(au)
kb, err := kotsutil.GetKOTSBinFromAirgapBundle(au)
if err != nil {
return nil, errors.Wrap(err, "failed to get kots binary from airgap bundle")
}
updateKOTSBin = kb
kv, err := kotsutil.GetKOTSVersionFromBinary(kb)
ecv, err := kotsutil.GetECVersionFromAirgapBundle(au)
if err != nil {
return nil, errors.Wrap(err, "failed to get kots version from binary")
}
updateKOTSVersion = kv
updateECVersion = ecv
} else {
kv, err := replicatedapp.GetKOTSVersionForRelease(license, r.VersionLabel)
kb, err := replicatedapp.DownloadKOTSBinary(license, r.VersionLabel)
if err != nil {
return nil, errors.Wrap(err, "failed to get kots version for release")
return nil, errors.Wrap(err, "failed to download kots binary")
}
updateKOTSVersion = kv

if buildversion.IsSameVersion(kv) {
updateKOTSBin = kotsutil.GetKOTSBinPath()
} else {
kb, err := replicatedapp.DownloadKOTSBinary(license, r.VersionLabel)
if err != nil {
return nil, errors.Wrap(err, "failed to download kots binary")
}
updateKOTSBin = kb
updateKOTSBin = kb
ecv, err := replicatedapp.GetECVersionForRelease(license, r.VersionLabel)
if err != nil {
return nil, errors.Wrap(err, "failed to get kots version for release")
}
updateECVersion = ecv
}

port, err := freeport.GetFreePort()
Expand All @@ -273,11 +267,11 @@ func getUpgradeServiceParams(a *apptypes.App, r StartUpgradeServiceRequest) (*up
UpdateVersionLabel: r.VersionLabel,
UpdateCursor: r.UpdateCursor,
UpdateChannelID: r.ChannelID,
UpdateECVersion: updateECVersion,
UpdateKOTSBin: updateKOTSBin,
UpdateAirgapBundle: updateAirgapBundle,

CurrentKOTSVersion: buildversion.Version(),
UpdateKOTSVersion: updateKOTSVersion,
UpdateKOTSBin: updateKOTSBin,
CurrentECVersion: util.EmbeddedClusterVersion(),

RegistryEndpoint: registrySettings.Hostname,
RegistryUsername: registrySettings.Username,
Expand Down
2 changes: 1 addition & 1 deletion pkg/k8sutil/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func WaitForDeploymentReady(ctx context.Context, clientset kubernetes.Interface,

time.Sleep(time.Second)

if time.Now().Sub(start) > timeout {
if time.Since(start) > timeout {
return &types.ErrorTimeout{Message: "timeout waiting for deployment to become ready"}
}
}
Expand Down
Loading

0 comments on commit 5fdb3bf

Please sign in to comment.