Skip to content

Commit

Permalink
New application dashboard and version history behind feature flags (#…
Browse files Browse the repository at this point in the history
…2256)


Co-authored-by: murphybytes <murphybytes@gmail.com>
  • Loading branch information
GraysonNull and murphybytes committed Oct 19, 2021
1 parent a138035 commit d92c96b
Show file tree
Hide file tree
Showing 59 changed files with 5,357 additions and 1,135 deletions.
1 change: 1 addition & 0 deletions migrations/fixtures/fixtures/deploy-kots-version.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ apps:
registry_password: "password"
namespace: "kots-namespace"
last_registry_sync: "2019-04-19 01:23:45.567"
last_license_sync: "2019-04-19 01:23:45.567"
install_state: "installed"
users:
- deploy-kots-version-user-id
Expand Down
1 change: 1 addition & 0 deletions migrations/fixtures/fixtures/get-kots-app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ apps:
registry_password: "password"
namespace: "kots-namespace"
last_registry_sync: "2019-04-19 01:23:45.567"
last_license_sync: "2019-04-19 01:23:45.567"
install_state: "installed"
users:
- get-kots-app-user-id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ apps:
registry_password: "password"
namespace: "kots-namespace"
last_registry_sync: "2019-04-19 01:23:45.567"
last_license_sync: "2019-04-19 01:23:45.567"
install_state: "installed"
users:
- get-kots-downstream-history-user-id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ apps:
registry_password: "password"
namespace: "kots-namespace"
last_registry_sync: "2019-04-19 01:23:45.567"
last_license_sync: "2019-04-19 01:23:45.567"
install_state: "installed"
users:
- get-kots-preflight-result-user-id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ apps:
registry_password: "password"
namespace: "kots-namespace"
last_registry_sync: "2019-09-12 01:13:05.02"
last_license_sync: "2019-04-19 01:23:45.567"
install_state: "installed"
users:
- get-latest-kots-preflight-result-user-id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ apps:
registry_password: "password"
namespace: "kots-namespace"
last_registry_sync: "2019-04-19 01:23:45.567"
last_license_sync: "2019-04-19 01:23:45.567"
install_state: "installed"
users:
- kots-different-sequence-user-id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ apps:
registry_password: "password"
namespace: "kots-namespace"
last_registry_sync: "2019-04-19 01:23:45.567"
last_license_sync: "2019-04-19 01:23:45.567"
install_state: "installed"
users:
- kots-no-release-notes-user-id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ apps:
registry_password: "password"
namespace: "kots-namespace"
last_registry_sync: "2019-04-19 01:23:45.567"
last_license_sync: "2019-04-19 01:23:45.567"
install_state: "installed"
users:
- kots-release-notes-user-id
Expand Down
2 changes: 2 additions & 0 deletions migrations/fixtures/src/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export class Schema {
registry_password,
namespace,
last_registry_sync,
last_license_sync
install_state
) VALUES (
%L, %L, %L, %L, %L, %L, ${app.current_sequence}, %L, %L, %L, %L, %L, %L, %L, %L, %L, %L)`,
Expand All @@ -201,6 +202,7 @@ export class Schema {
app.registry_password,
app.namespace,
app.last_registry_sync,
app.last_license_sync,
app.install_state
)
);
Expand Down
2 changes: 2 additions & 0 deletions migrations/tables/app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ spec:
type: boolean
- name: last_registry_sync
type: timestamp without time zone
- name: last_license_sync
type: timestamp without time zone
- name: install_state
type: text
- name: is_airgap
Expand Down
1 change: 1 addition & 0 deletions pkg/app/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ type App struct {
UpdateCheckerSpec string `json:"updateCheckerSpec"`
IsGitOps bool `json:"isGitOps"`
InstallState string `json:"installState"`
LastLicenseSync string `json:"lastLicenseSync"`
}
3 changes: 3 additions & 0 deletions pkg/handlers/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type LicenseResponse struct {
IsIdentityServiceSupported bool `json:"isIdentityServiceSupported"`
IsGeoaxisSupported bool `json:"isGeoaxisSupported"`
IsSnapshotSupported bool `json:"isSnapshotSupported"`
LastSyncedAt string `json:"lastSyncedAt"`
}

type SyncLicenseResponse struct {
Expand Down Expand Up @@ -150,6 +151,7 @@ func (h *Handler) SyncLicense(w http.ResponseWriter, r *http.Request) {
IsIdentityServiceSupported: latestLicense.Spec.IsIdentityServiceSupported,
IsGeoaxisSupported: latestLicense.Spec.IsGeoaxisSupported,
IsSnapshotSupported: latestLicense.Spec.IsSnapshotSupported,
LastSyncedAt: foundApp.LastLicenseSync,
}

JSON(w, http.StatusOK, syncLicenseResponse)
Expand Down Expand Up @@ -199,6 +201,7 @@ func (h *Handler) GetLicense(w http.ResponseWriter, r *http.Request) {
IsIdentityServiceSupported: license.Spec.IsIdentityServiceSupported,
IsGeoaxisSupported: license.Spec.IsGeoaxisSupported,
IsSnapshotSupported: license.Spec.IsSnapshotSupported,
LastSyncedAt: foundApp.LastLicenseSync,
}

JSON(w, http.StatusOK, getLicenseResponse)
Expand Down
5 changes: 5 additions & 0 deletions pkg/kotsadmlicense/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ func Sync(a *apptypes.App, licenseString string, failOnVersionCreate bool) (*kot
return nil, false, errors.Wrap(err, "failed to run preflights")
}
synced = true
} else {
err := store.GetStore().UpdateAppLicenseSyncNow(a.ID)
if err != nil {
return nil, false, errors.Wrap(err, "failed to update license sync time")
}
}

return updatedLicense, synced, nil
Expand Down
2 changes: 2 additions & 0 deletions pkg/persistence/sqlite_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ spec:
type: boolean
- name: last_registry_sync
type: integer
- name: last_license_sync
type: integer
- name: install_state
type: text
- name: is_airgap
Expand Down
6 changes: 4 additions & 2 deletions pkg/store/kotsstore/app_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (s *KOTSStore) GetApp(id string) (*apptypes.App, error) {
// zap.String("id", id))

db := persistence.MustGetDBSession()
query := `select id, name, license, upstream_uri, icon_uri, created_at, updated_at, slug, current_sequence, last_update_check_at, is_airgap, snapshot_ttl_new, snapshot_schedule, restore_in_progress_name, restore_undeploy_status, update_checker_spec, install_state from app where id = $1`
query := `select id, name, license, upstream_uri, icon_uri, created_at, updated_at, slug, current_sequence, last_update_check_at, last_license_sync, is_airgap, snapshot_ttl_new, snapshot_schedule, restore_in_progress_name, restore_undeploy_status, update_checker_spec, install_state from app where id = $1`
row := db.QueryRow(query, id)

app := apptypes.App{}
Expand All @@ -126,13 +126,14 @@ func (s *KOTSStore) GetApp(id string) (*apptypes.App, error) {
var updatedAt persistence.NullStringTime
var currentSequence sql.NullInt64
var lastUpdateCheckAt sql.NullString
var lastLicenseSync sql.NullString
var snapshotTTLNew sql.NullString
var snapshotSchedule sql.NullString
var restoreInProgressName sql.NullString
var restoreUndeployStatus sql.NullString
var updateCheckerSpec sql.NullString

if err := row.Scan(&app.ID, &app.Name, &licenseStr, &upstreamURI, &iconURI, &createdAt, &updatedAt, &app.Slug, &currentSequence, &lastUpdateCheckAt, &app.IsAirgap, &snapshotTTLNew, &snapshotSchedule, &restoreInProgressName, &restoreUndeployStatus, &updateCheckerSpec, &app.InstallState); err != nil {
if err := row.Scan(&app.ID, &app.Name, &licenseStr, &upstreamURI, &iconURI, &createdAt, &updatedAt, &app.Slug, &currentSequence, &lastUpdateCheckAt, &lastLicenseSync, &app.IsAirgap, &snapshotTTLNew, &snapshotSchedule, &restoreInProgressName, &restoreUndeployStatus, &updateCheckerSpec, &app.InstallState); err != nil {
return nil, errors.Wrap(err, "failed to scan app")
}

Expand All @@ -141,6 +142,7 @@ func (s *KOTSStore) GetApp(id string) (*apptypes.App, error) {
app.UpstreamURI = upstreamURI.String
app.IconURI = iconURI.String
app.LastUpdateCheckAt = lastUpdateCheckAt.String
app.LastLicenseSync = lastLicenseSync.String
app.SnapshotTTL = snapshotTTLNew.String
app.SnapshotSchedule = snapshotSchedule.String
app.RestoreInProgressName = restoreInProgressName.String
Expand Down
23 changes: 21 additions & 2 deletions pkg/store/kotsstore/license_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"database/sql"
"io/ioutil"
"path/filepath"
"time"

"github.com/pkg/errors"
kotsv1beta1 "github.com/replicatedhq/kots/kotskinds/apis/kots/v1beta1"
Expand Down Expand Up @@ -107,8 +108,8 @@ func (s *KOTSStore) UpdateAppLicense(appID string, sequence int64, archiveDir st
}

// app has the original license data received from the server
updateQuery := `update app set license=$1 where id = $2`
_, err = tx.Exec(updateQuery, originalLicenseData, appID)
updateQuery := `update app set license=$1, last_license_sync=$2 where id = $3`
_, err = tx.Exec(updateQuery, originalLicenseData, time.Now(), appID)
if err != nil {
return int64(0), errors.Wrapf(err, "update app %q license", appID)
}
Expand All @@ -130,6 +131,24 @@ func (s *KOTSStore) UpdateAppLicense(appID string, sequence int64, archiveDir st
return newSeq, nil
}

func (s *KOTSStore) UpdateAppLicenseSyncNow(appID string) error {
db := persistence.MustGetDBSession()

tx, err := db.Begin()
if err != nil {
return errors.Wrap(err, "failed to begin")
}
defer tx.Rollback()

updateQuery := `update app set last_license_sync=$1 where id = $2`
_, err = tx.Exec(updateQuery, time.Now(), appID)
if err != nil {
return errors.Wrapf(err, "update app %q license sync time", appID)
}

return nil
}

func (s *KOTSStore) createNewVersionForLicenseChange(tx *sql.Tx, appID string, sequence int64, archiveDir string, gitops gitopstypes.DownstreamGitOps, renderer rendertypes.Renderer) (int64, error) {
registrySettings, err := s.GetRegistryDetailsForApp(appID)
if err != nil {
Expand Down
28 changes: 28 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.

4 changes: 4 additions & 0 deletions pkg/store/ocistore/license_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ func (s *OCIStore) GetAllAppLicenses() ([]*kotsv1beta1.License, error) {
func (s *OCIStore) UpdateAppLicense(appID string, sequence int64, archiveDir string, newLicense *kotsv1beta1.License, originalLicenseData string, failOnVersionCreate bool, gitops gitopstypes.DownstreamGitOps, renderer rendertypes.Renderer) (int64, error) {
return int64(0), ErrNotImplemented
}

func (s *OCIStore) UpdateAppLicenseSyncNow(appID string) error {
return ErrNotImplemented
}
1 change: 1 addition & 0 deletions pkg/store/store_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ type LicenseStore interface {

// originalLicenseData is the data received from the replicated API that was never marshalled locally so all fields are intact
UpdateAppLicense(appID string, sequence int64, archiveDir string, newLicense *kotsv1beta1.License, originalLicenseData string, failOnVersionCreate bool, gitops gitopstypes.DownstreamGitOps, renderer rendertypes.Renderer) (int64, error)
UpdateAppLicenseSyncNow(appID string) error
}

type UserStore interface {
Expand Down
2 changes: 2 additions & 0 deletions web/src/Root.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ class Root extends Component {
appSlugFromMetadata: parseUpstreamUri(data.upstreamUri),
appNameSpace: data.namespace,
isKurlEnabled: data.isKurlEnabled,
featureFlags: data.consoleFeatureFlags,
fetchingMetadata: false
});
})
Expand Down Expand Up @@ -400,6 +401,7 @@ class Root extends Component {
appNameSpace={this.state.appNameSpace}
appName={this.state.selectedAppName}
snapshotInProgressApps={this.state.snapshotInProgressApps}
featureFlags={this.state.featureFlags}
ping={this.ping}
/>
)
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/AirgapUploadProgress.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class AirgapUploadProgress extends React.Component {
percentage = (progress * 100).toFixed(2) + "%";
progressBar = (
<div className={`progressbar ${smallSize ? "small" : ""}`}>
<div className={`progressbar-meter ${uploadComplete ? "complete" : ""}`} style={{ width: `${(progress) * (smallSize ? 100 : 600)}px` }} />
<div className={`progressbar-meter ${uploadComplete ? "complete" : ""}`} style={{ width: `${(progress) * (smallSize ? 355 : 600)}px` }} />
</div>
);
} else {
Expand Down Expand Up @@ -149,7 +149,7 @@ class AirgapUploadProgress extends React.Component {
statusDiv = statusMsg && (
<div
className={`u-marginTop--10 u-paddingRight--30 u-textColor--bodyCopy u-fontWeight--bold u-lineHeight--medium u-textAlign--center`}
style={{ maxWidth: 200 }}
style={{ maxWidth: "355px" }}
>
{statusMsg.substring(0, 30) + "..."}
</div>
Expand Down
38 changes: 36 additions & 2 deletions web/src/components/apps/AppDetailPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import { KotsSidebarItem } from "@src/components/watches/WatchSidebarItem";
import { HelmChartSidebarItem } from "@src/components/watches/WatchSidebarItem";
import NotFound from "../static/NotFound";
import Dashboard from "./Dashboard";
import DashboardClassic from "./DashboardClassic";
import CodeSnippet from "../shared/CodeSnippet";
import DownstreamTree from "../../components/tree/KotsApplicationTree";
import AppVersionHistory from "./AppVersionHistory";
import { isAwaitingResults, Utilities } from "../../utilities/utilities";
import { isAwaitingResults, Utilities, isFeatureEnabled } from "../../utilities/utilities";
import { Repeater } from "../../utilities/repeater";
import PreflightResultPage from "../PreflightResultPage";
import AppConfig from "./AppConfig";
Expand All @@ -28,6 +29,7 @@ import TroubleshootContainer from "../troubleshoot/TroubleshootContainer";
import ErrorModal from "../modals/ErrorModal";

import "../../scss/components/watches/WatchDetailPage.scss";
import AppVersionHistoryClassic from "./AppVersionHistoryClassic";

class AppDetailPage extends Component {
constructor(props) {
Expand Down Expand Up @@ -343,6 +345,7 @@ class AppDetailPage extends Component {
/>
<Switch>
<Route exact path="/app/:slug" render={() =>
isFeatureEnabled(this.props.featureFlags, "new-app-dashboard") ?
<Dashboard
app={app}
cluster={app.downstreams?.length && app.downstreams[0]?.cluster}
Expand All @@ -354,12 +357,27 @@ class AppDetailPage extends Component {
refreshAppData={this.getApp}
snapshotInProgressApps={this.props.snapshotInProgressApps}
ping={this.props.ping}
/>}
/>
:
<DashboardClassic
app={app}
cluster={app.downstreams?.length && app.downstreams[0]?.cluster}
updateCallback={this.refetchData}
onActiveInitSession={this.props.onActiveInitSession}
toggleIsBundleUploading={this.toggleIsBundleUploading}
isBundleUploading={isBundleUploading}
isVeleroInstalled={isVeleroInstalled}
refreshAppData={this.getApp}
snapshotInProgressApps={this.props.snapshotInProgressApps}
ping={this.props.ping}
/>
}
/>

<Route exact path="/app/:slug/tree/:sequence?" render={props => <DownstreamTree {...props} app={app} appNameSpace={this.props.appNameSpace} />} />

<Route exact path={["/app/:slug/version-history", "/app/:slug/version-history/diff/:firstSequence/:secondSequence"]} render={() =>
isFeatureEnabled(this.props.featureFlags, "new-version-history") ?
<AppVersionHistory
app={app}
match={this.props.match}
Expand All @@ -375,6 +393,22 @@ class AppDetailPage extends Component {
redeployVersion={this.redeployVersion}
redeployVersionErrMsg={this.state.redeployVersionErrMsg}
/>
:
<AppVersionHistoryClassic
app={app}
match={this.props.match}
makeCurrentVersion={this.makeCurrentRelease}
makingCurrentVersionErrMsg={this.state.makingCurrentReleaseErrMsg}
updateCallback={this.refetchData}
toggleIsBundleUploading={this.toggleIsBundleUploading}
isBundleUploading={isBundleUploading}
refreshAppData={this.getApp}
displayErrorModal={this.state.displayErrorModal}
toggleErrorModal={this.toggleErrorModal}
makingCurrentRelease={this.state.makingCurrentRelease}
redeployVersion={this.redeployVersion}
redeployVersionErrMsg={this.state.redeployVersionErrMsg}
/>
} />
<Route exact path="/app/:slug/downstreams/:downstreamSlug/version-history/preflight/:sequence" render={props => <PreflightResultPage logo={app.iconUri} {...props} />} />
<Route exact path="/app/:slug/config/:sequence?" render={() =>
Expand Down

0 comments on commit d92c96b

Please sign in to comment.