Skip to content

Commit

Permalink
Refactor migration logic for recorded app (#501)
Browse files Browse the repository at this point in the history
  • Loading branch information
praveenrewar authored May 4, 2022
1 parent 3ffaa2e commit c464deb
Showing 1 changed file with 117 additions and 123 deletions.
240 changes: 117 additions & 123 deletions pkg/kapp/app/recorded_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,43 @@ func (a *RecordedApp) UpdateUsedGVsAndGKs(gvs []schema.GroupVersion, gks []schem
func (a *RecordedApp) CreateOrUpdate(labels map[string]string) error {
defer a.logger.DebugFunc("CreateOrUpdate").Finish()

app, foundMigratedApp, err := a.find(a.fqName())
if err != nil {
return err
}

if foundMigratedApp {
a.isMigrated = true
return a.updateApp(app, labels)
}

app, foundNonMigratedApp, err := a.find(a.name)
if err != nil {
return err
}

if foundNonMigratedApp {
if a.isMigrationEnabled() {
return a.migrate(app, labels, a.fqName())
}
return a.updateApp(app, labels)
}

return a.create(labels)
}

func (a *RecordedApp) find(name string) (*corev1.ConfigMap, bool, error) {
cm, err := a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return nil, false, nil
}
return nil, false, fmt.Errorf("Getting app: %w", err)
}
return cm, true, nil
}

func (a *RecordedApp) create(labels map[string]string) error {
configMap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: a.name,
Expand All @@ -145,59 +182,24 @@ func (a *RecordedApp) CreateOrUpdate(labels map[string]string) error {
}.AsData(),
}

migratedAnnotation := map[string]string{KappIsConfigmapMigratedAnnotationKey: KappIsConfigmapMigratedAnnotationValue}

configMapWithSuffix, err := a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), a.fqName(), metav1.GetOptions{})
if err == nil {
return a.updateApp(configMapWithSuffix, labels)
}

if errors.IsNotFound(err) {
configmapWithoutSuffix, err := a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), a.name, metav1.GetOptions{})
if err == nil {
if a.isMigrationEnabled() {
return a.migrate(configmapWithoutSuffix, labels, a.fqName())
}
return a.updateApp(configmapWithoutSuffix, labels)

} else if errors.IsNotFound(err) {
if a.isMigrationEnabled() {
configMap.ObjectMeta.Name = a.fqName()

err = a.mergeAppAnnotationUpdates(configMap, migratedAnnotation)
if err != nil {
return err
}
}
if a.isMigrationEnabled() {
configMap.ObjectMeta.Name = a.fqName()
a.isMigrated = true

return a.createOrUpdate(configMap, labels)
err := a.mergeAppAnnotationUpdates(configMap, map[string]string{KappIsConfigmapMigratedAnnotationKey: KappIsConfigmapMigratedAnnotationValue})
if err != nil {
return err
}
}

return fmt.Errorf("Getting app: %s", err)
}

func (a *RecordedApp) createOrUpdate(c *corev1.ConfigMap, labels map[string]string) error {
err := a.mergeAppUpdates(c, labels)
err := a.mergeAppUpdates(configMap, labels)
if err != nil {
return err
}

_, err = a.coreClient.CoreV1().ConfigMaps(a.nsName).Create(context.TODO(), c, metav1.CreateOptions{})
if err != nil {
if errors.IsAlreadyExists(err) {
existingConfigMap, err := a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), c.GetObjectMeta().GetName(), metav1.GetOptions{})
if err != nil {
return fmt.Errorf("Getting app: %s", err)
}

return a.updateApp(existingConfigMap, labels)
}

return fmt.Errorf("Creating app: %s", err)
}
_, err = a.coreClient.CoreV1().ConfigMaps(a.nsName).Create(context.TODO(), configMap, metav1.CreateOptions{})

return nil
return err
}

func (a *RecordedApp) updateApp(existingConfigMap *corev1.ConfigMap, labels map[string]string) error {
Expand All @@ -216,65 +218,52 @@ func (a *RecordedApp) updateApp(existingConfigMap *corev1.ConfigMap, labels map[

func (a *RecordedApp) RenamePrevApp(prevAppName string, labels map[string]string) error {
defer a.logger.DebugFunc("RenamePrevApp").Finish()
var c *corev1.ConfigMap
var err error

newConf := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: a.name,
Namespace: a.nsName,
Labels: map[string]string{
KappIsAppLabelKey: kappIsAppLabelValue,
},
},
Data: Meta{
LabelKey: kappAppLabelKey,
LabelValue: fmt.Sprintf("%d", time.Now().UTC().UnixNano()),
UsedGKs: &[]schema.GroupKind{},
}.AsData(),
app, foundMigratedApp, err := a.find(a.fqName())
if err != nil {
return err
}

c, err = a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), a.fqName(), metav1.GetOptions{})
if err == nil {
return a.updateApp(c, labels)
} else if err != nil {
if errors.IsNotFound(err) {
c, err = a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), a.name, metav1.GetOptions{})
if err == nil {
if a.isMigrationEnabled() {
return a.migrate(c, labels, a.fqName())
}
return a.updateApp(c, labels)
}
if foundMigratedApp {
a.isMigrated = true
return a.updateApp(app, labels)
}

app, foundNonMigratedApp, err := a.find(a.name)
if err != nil {
return err
}

if foundNonMigratedApp {
if a.isMigrationEnabled() {
return a.migrate(app, labels, a.fqName())
}
return a.updateApp(app, labels)
}

if errors.IsNotFound(err) {
c, err = a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), prevAppName+AppSuffix, metav1.GetOptions{})
if err == nil {
return a.renameConfigMap(c, a.fqName(), a.nsName)
} else if errors.IsNotFound(err) {
c, err = a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), prevAppName, metav1.GetOptions{})
if err == nil {
if a.isMigrationEnabled() {
return a.migrate(c, labels, a.fqName())
}
return a.renameConfigMap(c, a.name, a.nsName)

} else if errors.IsNotFound(err) {
if a.isMigrationEnabled() {
newConf.Name = a.fqName()
err = a.mergeAppAnnotationUpdates(newConf, map[string]string{KappIsConfigmapMigratedAnnotationKey: KappIsConfigmapMigratedAnnotationValue})
if err != nil {
return err
}
}
return a.createOrUpdate(newConf, labels)
}
app, foundMigratedPrevApp, err := a.find(prevAppName + AppSuffix)
if err != nil {
return err
}

if foundMigratedPrevApp {
a.isMigrated = true
return a.renameConfigMap(app, a.fqName(), a.nsName)
}

app, foundNonMigratedPrevApp, err := a.find(prevAppName)
if err != nil {
return err
}

if foundNonMigratedPrevApp {
if a.isMigrationEnabled() {
return a.migrate(app, labels, a.fqName())
}
return a.renameConfigMap(app, a.name, a.nsName)
}

return fmt.Errorf("Getting app: %s", err)
return a.create(labels)
}

func (a *RecordedApp) migrate(c *corev1.ConfigMap, labels map[string]string, newName string) error {
Expand All @@ -298,6 +287,8 @@ func (a *RecordedApp) migrate(c *corev1.ConfigMap, labels map[string]string, new
return fmt.Errorf("Updating app: %s", err)
}

a.isMigrated = true

return nil
}

Expand Down Expand Up @@ -332,24 +323,25 @@ func (a *RecordedApp) mergeAppAnnotationUpdates(cm *corev1.ConfigMap, annotation
}

func (a *RecordedApp) Exists() (bool, string, error) {
_, foundMigratedApp, err := a.find(a.fqName())
if err != nil {
return false, "", err
}

_, err := a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), a.fqName(), metav1.GetOptions{})
if err == nil {
if foundMigratedApp {
a.isMigrated = true
return true, "", nil
} else if !errors.IsNotFound(err) {
// return if error is anything other than configmap not found
return false, "", fmt.Errorf("Getting app: %s", err)
}

_, err = a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), a.name, metav1.GetOptions{})
_, foundNonMigratedApp, err := a.find(a.name)
if err != nil {
if errors.IsNotFound(err) {
desc := fmt.Sprintf("App '%s' (namespace: %s) does not exist%s",
a.name, a.nsName, a.appInDiffNsHintMsgFunc(a.name))
return false, desc, nil
}
return false, "", fmt.Errorf("Getting app: %s", err)
return false, "", err
}

if !foundNonMigratedApp {
desc := fmt.Sprintf("App '%s' (namespace: %s) does not exist%s",
a.name, a.nsName, a.appInDiffNsHintMsgFunc(a.name))
return false, desc, nil
}

return true, "", nil
Expand Down Expand Up @@ -390,14 +382,14 @@ func (a *RecordedApp) Rename(newName string, newNamespace string) error {
name = a.fqName()
}

app, err := a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), name, metav1.GetOptions{})
app, found, err := a.find(name)
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("App '%s' (namespace: %s) does not exist: %s%s",
a.name, a.nsName, err, a.appInDiffNsHintMsgFunc(name))
}
return err
}

return fmt.Errorf("Getting app: %s", err)
if !found {
return fmt.Errorf("App '%s' (namespace: %s) does not exist: %s",
a.name, a.nsName, a.appInDiffNsHintMsgFunc(name))
}

// use fully qualified name if app had been previously migrated
Expand Down Expand Up @@ -476,22 +468,24 @@ func (a *RecordedApp) meta() (Meta, error) {
return *a.memoizedMeta, nil
}

app, err := a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), a.fqName(), metav1.GetOptions{})
if err == nil {
app, foundMigratedApp, err := a.find(a.fqName())
if err != nil {
return Meta{}, err
}

if foundMigratedApp {
a.isMigrated = true
return a.setMeta(*app)
} else if !errors.IsNotFound(err) {
// return if error is anything other than configmap not found
return Meta{}, fmt.Errorf("Getting app: %s", err)
}

app, err = a.coreClient.CoreV1().ConfigMaps(a.nsName).Get(context.TODO(), a.name, metav1.GetOptions{})
app, foundNonMigratedApp, err := a.find(a.name)
if err != nil {
if errors.IsNotFound(err) {
return Meta{}, fmt.Errorf("App '%s' (namespace: %s) does not exist: %s%s",
a.name, a.nsName, err, a.appInDiffNsHintMsgFunc(a.fqName()))
}
return Meta{}, fmt.Errorf("Getting app: %s", err)
return Meta{}, err
}

if !foundNonMigratedApp {
return Meta{}, fmt.Errorf("App '%s' (namespace: %s) does not exist: %s",
a.name, a.nsName, a.appInDiffNsHintMsgFunc(a.name))
}

return a.setMeta(*app)
Expand Down

0 comments on commit c464deb

Please sign in to comment.