Skip to content

Commit

Permalink
Merge pull request #2577 from replicatedhq/stefan/sc-36475/allow-reup…
Browse files Browse the repository at this point in the history
…load-lic-if-install-fails

allow reupload of license if app is not installed
  • Loading branch information
stefanrepl committed Mar 4, 2022
2 parents 61918c7 + fddd350 commit f6f0ca8
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 9 deletions.
22 changes: 17 additions & 5 deletions pkg/automation/automation.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,15 @@ LICENSE_LOOP:
continue
}
if existingLicense != nil {
logger.Errorf("license already exists for app %s", verifiedLicense.Spec.AppSlug)
cleanup(&licenseSecret, verifiedLicense.Spec.AppSlug)
continue
resolved, err := kotslicense.ResolveExistingLicense(verifiedLicense)
if err != nil {
logger.Error(errors.Wrap(err, "failed to resolve existing license conflict"))
}
if !resolved {
logger.Errorf("license already exists for app %s", verifiedLicense.Spec.AppSlug)
cleanup(&licenseSecret, verifiedLicense.Spec.AppSlug)
continue
}
}

instParams, err := kotsutil.GetInstallationParams(kotsadmtypes.KotsadmConfigMap)
Expand Down Expand Up @@ -309,8 +315,14 @@ func AirgapInstall(appSlug string, additionalFiles map[string][]byte) error {
return errors.Wrapf(err, "failed to check if license already exists for app %s", verifiedLicense.Spec.AppSlug)
}
if existingLicense != nil {
cleanup(&licenseSecret, verifiedLicense.Spec.AppSlug)
return errors.Errorf("license already exists for app %s", verifiedLicense.Spec.AppSlug)
resolved, err := kotslicense.ResolveExistingLicense(verifiedLicense)
if err != nil {
logger.Error(errors.Wrap(err, "failed to resolve existing license conflict"))
}
if !resolved {
cleanup(&licenseSecret, verifiedLicense.Spec.AppSlug)
return errors.Errorf("license already exists for app %s", verifiedLicense.Spec.AppSlug)
}
}

instParams, err := kotsutil.GetInstallationParams(kotsadmtypes.KotsadmConfigMap)
Expand Down
16 changes: 12 additions & 4 deletions pkg/handlers/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,19 @@ func (h *Handler) UploadNewLicense(w http.ResponseWriter, r *http.Request) {
JSON(w, 500, uploadLicenseResponse)
return
}

if existingLicense != nil {
uploadLicenseResponse.Error = "License already exists"
uploadLicenseResponse.DeleteAppCommand = fmt.Sprintf("kubectl kots remove %s -n %s --force", existingLicense.Spec.AppSlug, util.PodNamespace)
JSON(w, 400, uploadLicenseResponse)
return
resolved, err := kotslicense.ResolveExistingLicense(verifiedLicense)
if err != nil {
logger.Error(errors.Wrap(err, "failed to resolve existing license conflict"))
}

if !resolved {
uploadLicenseResponse.Error = "License already exists"
uploadLicenseResponse.DeleteAppCommand = fmt.Sprintf("kubectl kots remove %s -n %s --force", existingLicense.Spec.AppSlug, util.PodNamespace)
JSON(w, http.StatusBadRequest, uploadLicenseResponse)
return
}
}

installationParams, err := kotsutil.GetInstallationParams(kotsadmtypes.KotsadmConfigMap)
Expand Down
12 changes: 12 additions & 0 deletions pkg/handlers/mock/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions pkg/license/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,41 @@ import (
kotsv1beta1 "github.com/replicatedhq/kots/kotskinds/apis/kots/v1beta1"
"github.com/replicatedhq/kots/kotskinds/client/kotsclientset/scheme"
"github.com/replicatedhq/kots/pkg/buildversion"
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/store"
)

type LicenseData struct {
LicenseBytes []byte
License *kotsv1beta1.License
}

func ResolveExistingLicense(newLicense *kotsv1beta1.License) (bool, error) {
notInstalledApps, err := store.GetStore().ListFailedApps()
if err != nil {
logger.Error(errors.Wrap(err, "failed to list failed apps"))
return false, err
}

for _, app := range notInstalledApps {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(app.License), nil, nil)
if err != nil {
continue
}
license := obj.(*kotsv1beta1.License)
if license.Spec.LicenseID != newLicense.Spec.LicenseID {
continue
}

if err := store.GetStore().RemoveApp(app.ID); err != nil {
return false, errors.Wrap(err, "failed to remove existing app record")
}
}

return true, nil
}

func GetLatestLicense(license *kotsv1beta1.License) (*LicenseData, error) {
url := fmt.Sprintf("%s/license/%s", license.Spec.Endpoint, license.Spec.AppSlug)

Expand Down
25 changes: 25 additions & 0 deletions pkg/store/kotsstore/app_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,31 @@ func (s *KOTSStore) ListInstalledApps() ([]*apptypes.App, error) {
return apps, nil
}

func (s *KOTSStore) ListFailedApps() ([]*apptypes.App, error) {
db := persistence.MustGetDBSession()
query := `select id from app where install_state != 'installed'`
rows, err := db.Query(query)
if err != nil {
return nil, errors.Wrap(err, "failed to query db")
}
defer rows.Close()

apps := []*apptypes.App{}
for rows.Next() {
var appID string
if err := rows.Scan(&appID); err != nil {
return nil, errors.Wrap(err, "failed to scan")
}
app, err := s.GetApp(appID)
if err != nil {
return nil, errors.Wrap(err, "failed to get app")
}
apps = append(apps, app)
}

return apps, nil
}

func (s *KOTSStore) ListInstalledAppSlugs() ([]string, error) {
db := persistence.MustGetDBSession()
query := `select slug from app where install_state = 'installed'`
Expand Down
30 changes: 30 additions & 0 deletions pkg/store/mock/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions pkg/store/ocistore/app_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ func (s *OCIStore) ListInstalledApps() ([]*apptypes.App, error) {
return apps, nil
}

func (s *OCIStore) ListFailedApps() ([]*apptypes.App, error) {
appListConfigmap, err := s.getConfigmap(AppListConfigmapName)
if err != nil {
return nil, errors.Wrap(err, "failed to get app list configmap")
}

apps := []*apptypes.App{}
for _, appData := range appListConfigmap.Data {
app := apptypes.App{}
if err := json.Unmarshal([]byte(appData), &app); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal app data")
}
if app.InstallState != "installed" {
apps = append(apps, &app)
}
}

return apps, nil
}

func (s *OCIStore) ListInstalledAppSlugs() ([]string, error) {
apps, err := s.ListInstalledApps()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/store/store_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ type AppStore interface {
SetAppInstallState(appID string, state string) error
ListInstalledApps() ([]*apptypes.App, error)
ListInstalledAppSlugs() ([]string, error)
ListFailedApps() ([]*apptypes.App, error)
GetAppIDFromSlug(slug string) (appID string, err error)
GetApp(appID string) (*apptypes.App, error)
GetAppFromSlug(slug string) (*apptypes.App, error)
Expand Down

0 comments on commit f6f0ca8

Please sign in to comment.