Skip to content

Commit

Permalink
Merge pull request #1033 from replicatedhq/ocistore
Browse files Browse the repository at this point in the history
Refactoring createAppVersion to make it fit into the store
  • Loading branch information
marccampbell committed Aug 31, 2020
2 parents 82d61e4 + ea1cebd commit 3b6dfd1
Show file tree
Hide file tree
Showing 12 changed files with 544 additions and 229 deletions.
2 changes: 1 addition & 1 deletion kotsadm/pkg/handlers/app.go
Expand Up @@ -134,7 +134,7 @@ func responseAppFromApp(a *apptypes.App) (*ResponseApp, error) {
return nil, errors.Wrap(err, "failed to get license")
}

currentVersion, err := version.Get(a.ID, a.CurrentSequence)
currentVersion, err := store.GetStore().GetAppVersion(a.ID, a.CurrentSequence)
if err != nil {
return nil, errors.Wrap(err, "failed to get app version")
}
Expand Down
63 changes: 33 additions & 30 deletions kotsadm/pkg/handlers/config.go
Expand Up @@ -129,7 +129,7 @@ func UpdateAppConfig(w http.ResponseWriter, r *http.Request) {
for _, version := range laterVersions {
_, err := updateAppConfig(foundApp, version.Sequence, updateAppConfigRequest, false)
if err != nil {
logger.Error(errors.Wrapf(err, "error creating app with new config based on sequence %d for upstream %q", version.Sequence, version.VersionLabel))
logger.Error(errors.Wrapf(err, "error creating app with new config based on sequence %d for upstream %q", version.Sequence, version.KOTSKinds.Installation.Spec.VersionLabel))
}
}

Expand Down Expand Up @@ -447,49 +447,52 @@ func decrypt(input string, cipher *crypto.AESCipher) (string, error) {
}

func getLaterVersions(versionedApp *apptypes.App, startSequence int64) (int64, []versiontypes.AppVersion, error) {
versions, err := version.GetVersions(versionedApp.ID)
thisAppVersion, err := store.GetStore().GetAppVersion(versionedApp.ID, startSequence)
if err != nil {
return -1, nil, errors.Wrap(err, "failed to get app versions")
return -1, nil, errors.Wrap(err, "failed to get this appversion")
}

thisUpdateCursor := -1
latestSequenceWithUpdateCursor := startSequence
laterVersions := map[int]versiontypes.AppVersion{}
for _, version := range versions {
if version.Sequence == startSequence {
thisUpdateCursor = version.UpdateCursor
}
}
if thisUpdateCursor == -1 {
err := fmt.Errorf("unable to find update cursor for sequence %d in %+v", startSequence, versions)
return -1, nil, err
laterAppVersions, err := store.GetStore().GetAppVersionsAfter(versionedApp.ID, startSequence)
if err != nil {
return -1, nil, errors.Wrap(err, "failed to get later app versions")
}
for _, version := range versions {
if version.UpdateCursor == thisUpdateCursor && version.Sequence > latestSequenceWithUpdateCursor {
latestSequenceWithUpdateCursor = version.Sequence

// latestSequenceWithThisUpdateCursor is the newest local version
// of the same upstream version
latestSequenceWithThisUpdateCursor := thisAppVersion.Sequence
for _, laterAppVersion := range laterAppVersions {
if laterAppVersion.KOTSKinds.Installation.Spec.UpdateCursor == thisAppVersion.KOTSKinds.Installation.Spec.UpdateCursor {
if laterAppVersion.Sequence > latestSequenceWithThisUpdateCursor {
latestSequenceWithThisUpdateCursor = laterAppVersion.Sequence
}
}
if version.UpdateCursor > thisUpdateCursor {
// save the latest sequence # for a given update cursor
ver, ok := laterVersions[version.UpdateCursor]
if !ok {
laterVersions[version.UpdateCursor] = version
} else if ver.Sequence < version.Sequence {
laterVersions[version.UpdateCursor] = version
}

laterVersions := map[string][]versiontypes.AppVersion{}
for _, laterAppVersion := range laterAppVersions {
if current, ok := laterVersions[laterAppVersion.KOTSKinds.Installation.Spec.UpdateCursor]; ok {
current = append(current, *laterAppVersion)
laterVersions[laterAppVersion.KOTSKinds.Installation.Spec.UpdateCursor] = current
} else {
laterVersions[laterAppVersion.KOTSKinds.Installation.Spec.UpdateCursor] = []versiontypes.AppVersion{
*laterAppVersion,
}
}
}

// ensure that the returned versions array is sorted by GVK
keys := []int{}
for key, _ := range laterVersions {
// ensure that the returned versions array is sorted
keys := []string{}
for key := range laterVersions {
keys = append(keys, key)
}
sort.Ints(keys)

// TODO sort by something in kotsutil that i need to write (these are either ints or semvers)
sort.Strings(keys)

sortedVersions := []versiontypes.AppVersion{}
for _, key := range keys {
sortedVersions = append(sortedVersions, laterVersions[key])
sortedVersions = append(sortedVersions, laterVersions[key]...)
}

return latestSequenceWithUpdateCursor, sortedVersions, nil
return latestSequenceWithThisUpdateCursor, sortedVersions, nil
}
4 changes: 4 additions & 0 deletions kotsadm/pkg/kotsutil/kots.go
Expand Up @@ -349,6 +349,10 @@ func LoadInstallationFromPath(installationFilePath string) (*kotsv1beta1.Install
return nil, errors.Wrap(err, "failed to read installation file")
}

return LoadInstallationFromContents(installationData)
}

func LoadInstallationFromContents(installationData []byte) (*kotsv1beta1.Installation, error) {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, gvk, err := decode([]byte(installationData), nil, nil)
if err != nil {
Expand Down
67 changes: 53 additions & 14 deletions kotsadm/pkg/store/ocistore/app_store.go
Expand Up @@ -22,16 +22,56 @@ import (

const (
AppListConfigmapName = "kotsadm-apps"
DownstreamListConfigmapName = "kotsadm-downstreams"
AppDownstreamsConfigMapName = "kotsadm-appdownstreams"
)

func (s OCIStore) AddAppToAllDownstreams(appID string) error {
return ErrNotImplemented
clusters, err := s.ListClusters()
if err != nil {
return errors.Wrap(err, "failed to list clusters")
}

configMap, err := s.getConfigmap(AppDownstreamsConfigMapName)
if err != nil {
return errors.Wrap(err, "failed to get appdownstreams configmap")
}

if configMap.Data == nil {
configMap.Data = map[string]string{}
}

clusterIDs := []string{}
for _, cluster := range clusters {
clusterIDs = append(clusterIDs, cluster.ClusterID)
}

b, err := json.Marshal(clusterIDs)
if err != nil {
return errors.Wrap(err, "failed to marshal cluster ids")
}

configMap.Data[fmt.Sprintf("app.%s", appID)] = string(b)

if err := s.updateConfigmap(configMap); err != nil {
return errors.Wrap(err, "failed to update config map")
}

return nil
}

func (s OCIStore) SetAppInstallState(appID string, state string) error {
return ErrNotImplemented
app, err := s.GetApp(appID)
if err != nil {
return errors.Wrap(err, "failed to get app")
}

app.InstallState = state

if err := s.updateApp(app); err != nil {
return errors.Wrap(err, "failed to update app")
}

return nil
}

func (s OCIStore) ListInstalledApps() ([]*apptypes.App, error) {
Expand Down Expand Up @@ -187,7 +227,7 @@ func (s OCIStore) ListDownstreamsForApp(appID string) ([]downstreamtypes.Downstr
return nil, errors.Wrap(err, "failed to get app downstreams list configmap")
}

key := fmt.Sprintf("app:%s", appID)
key := fmt.Sprintf("app.%s", appID)
downstreamIDsMarshaled, ok := appDownstreamsConfigMap.Data[key]
if !ok {
return []downstreamtypes.Downstream{}, nil
Expand All @@ -197,22 +237,21 @@ func (s OCIStore) ListDownstreamsForApp(appID string) ([]downstreamtypes.Downstr
return nil, errors.Wrap(err, "failed to unmarshal downstream ids for app")
}

downstreamsConfigMap, err := s.getConfigmap(DownstreamListConfigmapName)
clusters, err := s.ListClusters()
if err != nil {
return nil, errors.Wrap(err, "failed to get downsteams config map")
return nil, errors.Wrap(err, "failed to list clusters")
}

downstreams := []downstreamtypes.Downstream{}
for _, downstreamData := range downstreamsConfigMap.Data {
downstream := downstreamtypes.Downstream{}
if err := json.Unmarshal([]byte(downstreamData), &downstream); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal app downstream data")
matchingClusters := []downstreamtypes.Downstream{}
for _, cluster := range clusters {
for _, downstreamID := range downstreamIDs {
if cluster.ClusterID == downstreamID {
matchingClusters = append(matchingClusters, *cluster)
}
}

downstreams = append(downstreams, downstream)
}

return downstreams, nil
return matchingClusters, nil
}

func (s OCIStore) ListAppsForDownstream(clusterID string) ([]*apptypes.App, error) {
Expand Down
11 changes: 10 additions & 1 deletion kotsadm/pkg/store/ocistore/license_store.go
Expand Up @@ -28,5 +28,14 @@ func (s OCIStore) GetLatestLicenseForApp(appID string) (*kotsv1beta1.License, er
}

func (s OCIStore) GetLicenseForAppVersion(appID string, sequence int64) (*kotsv1beta1.License, error) {
return nil, ErrNotImplemented
appVersion, err := s.GetAppVersion(appID, sequence)
if err != nil {
return nil, errors.Wrap(err, "failed to get app version")
}

if appVersion == nil {
return s.GetInitialLicenseForApp(appID)
}

return appVersion.KOTSKinds.License, nil
}
96 changes: 91 additions & 5 deletions kotsadm/pkg/store/ocistore/task_store.go
Expand Up @@ -2,6 +2,7 @@ package ocistore

import (
"encoding/json"
"time"

"github.com/pkg/errors"
)
Expand All @@ -11,20 +12,105 @@ const (
)

type taskStatus struct {
Message string `json:"message"`
Status string `json:"status"`
Message string `json:"message"`
Status string `json:"status"`
UpdatedAt time.Time `json:"updatedAt"`
}

func (s OCIStore) SetTaskStatus(id string, message string, status string) error {
return ErrNotImplemented
configmap, err := s.getConfigmap(TaskStatusConfigMapName)
if err != nil {
return errors.Wrap(err, "failed to get task status configmap")
}

if configmap.Data == nil {
configmap.Data = map[string]string{}
}

ts := taskStatus{}
existingTsData, ok := configmap.Data[id]
if ok {
if err := json.Unmarshal([]byte(existingTsData), &ts); err != nil {
return errors.Wrap(err, "failed to unmarshal task status")
}
}

ts.Message = message
ts.Status = status
ts.UpdatedAt = time.Now()

b, err := json.Marshal(ts)
if err != nil {
return errors.Wrap(err, "failed to marshal task status")
}

configmap.Data[id] = string(b)

if err := s.updateConfigmap(configmap); err != nil {
return errors.Wrap(err, "failed to update task status configmap")
}

return nil
}

func (s OCIStore) UpdateTaskStatusTimestamp(id string) error {
return ErrNotImplemented
configmap, err := s.getConfigmap(TaskStatusConfigMapName)
if err != nil {
return errors.Wrap(err, "failed to get task status configmap")
}

if configmap.Data == nil {
configmap.Data = map[string]string{}
}

data, ok := configmap.Data[id]
if !ok {
return nil // copied from s3pgstore
}

ts := taskStatus{}
if err := json.Unmarshal([]byte(data), &ts); err != nil {
return errors.Wrap(err, "failed to unmarshal task status")
}

ts.UpdatedAt = time.Now()

b, err := json.Marshal(ts)
if err != nil {
return errors.Wrap(err, "failed to marshal task status")
}

configmap.Data[id] = string(b)

if err := s.updateConfigmap(configmap); err != nil {
return errors.Wrap(err, "failed to update task status configmap")
}

return nil
}

func (s OCIStore) ClearTaskStatus(id string) error {
return ErrNotImplemented
configmap, err := s.getConfigmap(TaskStatusConfigMapName)
if err != nil {
return errors.Wrap(err, "failed to get task status configmap")
}

if configmap.Data == nil {
configmap.Data = map[string]string{}
}

_, ok := configmap.Data[id]
if !ok {
return nil // copied from s3pgstore
}

delete(configmap.Data, id)

if err := s.updateConfigmap(configmap); err != nil {
return errors.Wrap(err, "failed to update task status configmap")
}

return nil
}

func (s OCIStore) GetTaskStatus(id string) (string, string, error) {
Expand Down

0 comments on commit 3b6dfd1

Please sign in to comment.