Skip to content

Commit

Permalink
[PLAT-13761] fixed import/export universe with new style releases
Browse files Browse the repository at this point in the history
Summary:
Because import export relies on formatting objects to json, I made a
simplified "releaseContainer" specifically for this workflow.

In addition, during deserialization of release and release artifact, we should not
automatically save the models. Converted the custom "setXYZ" to "saveXYZ"
and leverage the default setters for set. This allows jackson to deserialize
correctly

Test Plan:
test exporting a release, and then importing it both with the release existing
and it deleted. Imported successfully for both cases.

Reviewers: muthu, anijhawan, cwang

Reviewed By: muthu, cwang

Subscribers: yugaware

Differential Revision: https://phorge.dev.yugabyte.com/D34679
  • Loading branch information
shubin-yb committed May 3, 2024
1 parent c2b8a40 commit bfed1f0
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ public void downloadYbHelmChart(String version, String ybReleasesPath) {
this.metadata.chartPath = chartPath.toString();
} else {
ReleaseLocalFile rlf = ReleaseLocalFile.create(chartPath.toString());
artifact.setPackageFileID(rlf.getFileUUID());
artifact.savePackageFileID(rlf.getFileUUID());
}
} catch (Exception e) {
log.error("failed to download helmchart from " + urlPath, e);
Expand Down Expand Up @@ -452,6 +452,13 @@ public ReleaseManager.ReleaseMetadata getMetadata() {
}
}

public void setArtifactMatchingArchitecture(Architecture arch) {
// only relevant for non-legacy
if (!isLegacy()) {
this.artifact = release.getArtifactForArchitecture(arch);
}
}

private void setArtifactMatchingPackage(String ybPackage) {
for (ReleaseArtifact artifact : this.release.getArtifacts()) {
if (artifact.getPackageURL() != null && artifact.getPackageURL().equals(ybPackage)) {
Expand Down Expand Up @@ -481,4 +488,18 @@ public boolean isActive() {
return this.release.getState() == Release.ReleaseState.ACTIVE;
}
}

public static class ImportExportRelease {
public ReleaseMetadata releaseMetadata;
public Release release;
public ReleaseArtifact releaseArtifact;
}

public ImportExportRelease toImportExportRelease() {
ImportExportRelease ier = new ImportExportRelease();
ier.releaseMetadata = this.metadata;
ier.release = this.release;
ier.releaseArtifact = this.artifact;
return ier;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import com.typesafe.config.Config;
import com.yugabyte.yw.cloud.PublicCloudConstants.Architecture;
import com.yugabyte.yw.common.ReleaseManager.ReleaseMetadata;
import com.yugabyte.yw.common.config.GlobalConfKeys;
import com.yugabyte.yw.common.config.RuntimeConfGetter;
import com.yugabyte.yw.common.utils.FileUtils;
import com.yugabyte.yw.models.Release;
import com.yugabyte.yw.models.ReleaseArtifact;
Expand Down Expand Up @@ -45,6 +47,7 @@ public class ReleasesUtils {

@Inject private Config appConfig;
@Inject private ConfigHelper configHelper;
@Inject private RuntimeConfGetter confGetter;

public final String RELEASE_PATH_CONFKEY = "yb.releases.artifacts.upload_path";

Expand Down Expand Up @@ -422,6 +425,9 @@ public ReleaseMetadata.HttpLocation httpLocationFromUrl(ReleaseArtifact artifact
}

public void validateVersionAgainstCurrentYBA(String version) {
if (confGetter.getGlobalConf(GlobalConfKeys.skipVersionChecks)) {
return;
}
String currVersion = ybaCurrentVersion();
if (Util.compareYbVersions(version, currVersion) > 0) {
log.error("invalid version {} is newer then the yba version {}", version, currVersion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ public Result exportUniverse(UUID customerUUID, UUID universeUUID, Request reque
if (release != null && release.hasLocalRelease()) {
release = null;
}
if (release != null) {
release.setArtifactMatchingArchitecture(universe.getUniverseDetails().arch);
}

List<NodeInstance> nodeInstances = NodeInstance.listByUniverse(universe.getUniverseUUID());

Expand Down Expand Up @@ -204,7 +207,7 @@ public Result exportUniverse(UUID customerUUID, UUID universeUUID, Request reque
.schedules(schedules)
.backups(backups)
.customerConfigs(customerConfigs)
.ybReleaseMetadata(release)
.ybReleaseMetadata(release != null ? release.toImportExportRelease() : null)
.oldPlatformPaths(platformPaths)
.skipReleases(detachUniverseFormData.skipReleases)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,14 @@ public Result update(UUID customerUUID, UUID releaseUUID, Http.Request request)
if (reqRelease.release_tag != null
&& !reqRelease.release_tag.equals(release.getReleaseTag())) {
log.debug("updating release tag to {}", reqRelease.release_tag);
release.setReleaseTag(reqRelease.release_tag);
release.saveReleaseTag(reqRelease.release_tag);
}
if (reqRelease.release_date != null) {
try {
Date releaseDate = Date.from(Instant.ofEpochSecond(reqRelease.release_date));
if (!releaseDate.equals(release.getReleaseDate())) {
log.debug("updating release date to {}", reqRelease.release_date);
release.setReleaseDate(releaseDate);
release.saveReleaseDate(releaseDate);
}
} catch (IllegalArgumentException | DateTimeException e) {
log.warn("unable to parse date format", e);
Expand All @@ -278,7 +278,7 @@ public Result update(UUID customerUUID, UUID releaseUUID, Http.Request request)
if (reqRelease.release_notes != null
&& !reqRelease.release_notes.equals(release.getReleaseNotes())) {
log.debug("updating release notes to {}", reqRelease.release_notes);
release.setReleaseNotes(reqRelease.release_notes);
release.saveReleaseNotes(reqRelease.release_notes);
}
if (reqRelease.state != null
&& !release.getState().equals(Release.ReleaseState.valueOf(reqRelease.state))) {
Expand All @@ -287,7 +287,7 @@ public Result update(UUID customerUUID, UUID releaseUUID, Http.Request request)
BAD_REQUEST, "cannot change state of in-use release " + releaseUUID);
}
log.info("updating release state to {}", reqRelease.state);
release.setState(Release.ReleaseState.valueOf(reqRelease.state));
release.saveState(Release.ReleaseState.valueOf(reqRelease.state));
}

// Now, check if any artifacts have changed, and update them as needed
Expand Down Expand Up @@ -325,7 +325,7 @@ public Result update(UUID customerUUID, UUID releaseUUID, Http.Request request)
"updating artifact {} sha to {}",
artifact.getArtifactUUID(),
reqArtifact.sha256);
artifact.setSha256(reqArtifact.sha256);
artifact.saveSha256(reqArtifact.sha256);
}
break;
}
Expand Down
12 changes: 8 additions & 4 deletions managed/src/main/java/com/yugabyte/yw/models/Release.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public void addArtifact(ReleaseArtifact artifact) {
"artifact matching platform %s and architecture %s already exists",
artifact.getPlatform(), artifact.getArchitecture()));
}
artifact.setReleaseUUID(releaseUUID);
artifact.saveReleaseUUID(releaseUUID);

// Move the state from incomplete to active when adding a Linux type. Kubernetes artifacts
// are not sufficient to make a release move into the "active" state.
Expand All @@ -225,7 +225,7 @@ public ReleaseArtifact getKubernetesArtifact() {
return ReleaseArtifact.getForReleaseKubernetesArtifact(releaseUUID);
}

public void setReleaseTag(String tag) {
public void saveReleaseTag(String tag) {
this.releaseTag = encodeReleaseTag(tag);
save();
}
Expand All @@ -240,12 +240,12 @@ public String getRawReleaseTag() {
return releaseTag;
}

public void setReleaseDate(Date date) {
public void saveReleaseDate(Date date) {
this.releaseDate = date;
save();
}

public void setReleaseNotes(String notes) {
public void saveReleaseNotes(String notes) {
this.releaseNotes = notes;
save();
}
Expand All @@ -256,6 +256,10 @@ public void setState(ReleaseState state) {
BAD_REQUEST, "cannot update release state from 'INCOMPLETE'");
}
this.state = state;
}

public void saveState(ReleaseState state) {
setState(state);
save();
}

Expand Down
37 changes: 20 additions & 17 deletions managed/src/main/java/com/yugabyte/yw/models/ReleaseArtifact.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,21 @@
import java.util.List;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import play.libs.Json;

@Slf4j
@Getter
@Setter
@Entity
public class ReleaseArtifact extends Model {
@Getter @Id private UUID artifactUUID = UUID.randomUUID();
@Id private UUID artifactUUID = UUID.randomUUID();

@Column(name = "release")
@Getter
private UUID releaseUUID;

@Column @Getter private String sha256;
@Column private String sha256;

public enum Platform {
@EnumValue("linux")
Expand All @@ -37,25 +39,24 @@ public enum Platform {
KUBERNETES;
}

@Column @Getter private Platform platform;
@Column private Platform platform;

@Column
@Enumerated(EnumType.STRING)
@Getter
private PublicCloudConstants.Architecture architecture;

@Column @Getter private String signature;
@Column private String signature;

@Column @Getter private UUID packageFileID;
@Column private UUID packageFileID;

public void setPackageFileID(UUID fileID) {
public void savePackageFileID(UUID fileID) {
this.packageFileID = fileID;
save();
}

@Column @Getter private String packageURL;
@Column private String packageURL;

public void setPackageURL(String url) {
public void savePackageURL(String url) {
this.packageURL = url;
save();
}
Expand All @@ -65,13 +66,12 @@ public static class GCSFile {
public String credentialsJson;
}

@Getter private GCSFile gcsFile;
private GCSFile gcsFile;

@Column(name = "gcs_file")
@Getter
private String gcsFileJson;

public void setGCSFile(GCSFile gcsFile) {
public void saveGCSFile(GCSFile gcsFile) {
this.gcsFileJson = Json.stringify(Json.toJson(gcsFile));
this.gcsFile = gcsFile;
save();
Expand All @@ -83,13 +83,12 @@ public static class S3File {
public String secretAccessKey;
}

@Getter private S3File s3File;
private S3File s3File;

@Column(name = "s3_file")
@Getter
private String s3FileJson;

public void setS3File(S3File s3File) {
public void saveS3File(S3File s3File) {
this.s3FileJson = Json.stringify(Json.toJson(s3File));
this.s3File = s3File;
save();
Expand Down Expand Up @@ -282,7 +281,7 @@ public static List<ReleaseArtifact> getAllPlatformArchitecture(
return artifacts;
}

public void setReleaseUUID(UUID releaseUuid) {
public void saveReleaseUUID(UUID releaseUuid) {
this.releaseUUID = releaseUuid;
save();
}
Expand All @@ -300,6 +299,10 @@ public void setSha256(String sha256) {
log.error("invalid sha256", e);
return;
}
}

public void saveSha256(String sha256) {
setSha256(sha256);
save();
}

Expand Down
19 changes: 13 additions & 6 deletions managed/src/main/java/com/yugabyte/yw/models/UniverseSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.yugabyte.yw.commissioner.Common;
import com.yugabyte.yw.common.PlatformServiceException;
import com.yugabyte.yw.common.ReleaseContainer;
import com.yugabyte.yw.common.ReleaseContainer.ImportExportRelease;
import com.yugabyte.yw.common.ReleaseManager;
import com.yugabyte.yw.common.SwamperHelper;
import com.yugabyte.yw.common.Util;
Expand Down Expand Up @@ -101,7 +101,7 @@ public class UniverseSpec {

public PlatformPaths oldPlatformPaths;

private ReleaseContainer ybReleaseMetadata;
private ImportExportRelease ybReleaseMetadata;

private boolean skipReleases;

Expand Down Expand Up @@ -720,12 +720,19 @@ public void save(
String universeVersion =
this.universe.getUniverseDetails().getPrimaryCluster().userIntent.ybSoftwareVersion;
if (releaseManager.getReleaseByVersion(universeVersion) == null) {
if (ybReleaseMetadata.isLegacy()) {
releaseManager.addReleaseWithMetadata(universeVersion, ybReleaseMetadata.getMetadata());
if (ybReleaseMetadata.releaseMetadata != null) {
releaseManager.addReleaseWithMetadata(
universeVersion, ybReleaseMetadata.releaseMetadata);
} else {
ybReleaseMetadata.release.save();
if (ybReleaseMetadata.releaseArtifact != null) {
ybReleaseMetadata.releaseArtifact.save();
}
}
} else {
if (ybReleaseMetadata.isLegacy()) {
releaseManager.updateReleaseMetadata(universeVersion, ybReleaseMetadata.getMetadata());
if (ybReleaseMetadata.releaseMetadata != null) {
releaseManager.updateReleaseMetadata(
universeVersion, ybReleaseMetadata.releaseMetadata);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import com.yugabyte.yw.cloud.PublicCloudConstants.Architecture;
import com.yugabyte.yw.common.ReleasesUtils.ExtractedMetadata;
import com.yugabyte.yw.common.config.GlobalConfKeys;
import com.yugabyte.yw.common.config.RuntimeConfGetter;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
Expand All @@ -26,6 +28,7 @@ public class ReleasesUtilsTest extends FakeDBApplication {
@InjectMocks ReleasesUtils releasesUtils;

@Mock ConfigHelper configHelper;
@Mock RuntimeConfGetter confGetter;

@Test
public void testVersionMetadataFromUrl() {
Expand Down Expand Up @@ -77,6 +80,7 @@ public void testReleaseTypeFromVersion() {
public void testValidateVersionAgainstCurrentYBA() {
when(configHelper.getConfig(ConfigHelper.ConfigType.SoftwareVersion))
.thenReturn(getVersionMap("2024.1.0.0-b23"));
when(confGetter.getGlobalConf(GlobalConfKeys.skipVersionChecks)).thenReturn(false);

// Should pass
releasesUtils.validateVersionAgainstCurrentYBA("2024.1.0.0-b23");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public void testGetKubernetesForRelease() {
ReleaseLocalFile.create(rlfUUID, "path", false);
ReleaseArtifact artifact =
ReleaseArtifact.create("", ReleaseArtifact.Platform.KUBERNETES, null, rlfUUID);
artifact.setReleaseUUID(releaseUUID);
artifact.saveReleaseUUID(releaseUUID);
ReleaseArtifact foundArtifact = ReleaseArtifact.getForReleaseKubernetesArtifact(releaseUUID);
assertNotNull(foundArtifact);
assertEquals(artifact.getArtifactUUID(), foundArtifact.getArtifactUUID());
Expand All @@ -86,7 +86,7 @@ public void testGetForX86Architecture() {
Release.create(releaseUUID, "version", "lts");
ReleaseArtifact artifact =
ReleaseArtifact.create("", ReleaseArtifact.Platform.LINUX, Architecture.x86_64, "url");
artifact.setReleaseUUID(releaseUUID);
artifact.saveReleaseUUID(releaseUUID);
ReleaseArtifact foundArtifact =
ReleaseArtifact.getForReleaseArchitecture(releaseUUID, Architecture.x86_64);
assertNotNull(foundArtifact);
Expand All @@ -99,7 +99,7 @@ public void testGetForArchitectureKubernetes() {
Release.create(releaseUUID, "version", "lts");
ReleaseArtifact artifact =
ReleaseArtifact.create("", ReleaseArtifact.Platform.KUBERNETES, null, "url");
artifact.setReleaseUUID(releaseUUID);
artifact.saveReleaseUUID(releaseUUID);
ReleaseArtifact foundArtifact = ReleaseArtifact.getForReleaseArchitecture(releaseUUID, null);
assertNotNull(foundArtifact);
assertEquals(artifact.getArtifactUUID(), foundArtifact.getArtifactUUID());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,6 @@ public void testTagRenaming() {
assertNull(release.getReleaseTag());
assertEquals(Release.NULL_CONSTANT, release.getRawReleaseTag());
assertThrows(
PlatformServiceException.class, () -> release.setReleaseTag(Release.NULL_CONSTANT));
PlatformServiceException.class, () -> release.saveReleaseTag(Release.NULL_CONSTANT));
}
}

0 comments on commit bfed1f0

Please sign in to comment.