Permalink
Browse files

FABRIC-73: Upgrade and rollback commands. Work in progress.

  • Loading branch information...
1 parent ce56818 commit 8e6c7924c4eaf98352ee6a90cb2dffeec9da442a @davsclaus davsclaus committed Feb 9, 2012
@@ -0,0 +1,94 @@
+/**
+ * Copyright (C) FuseSource, Inc.
+ * http://fusesource.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.fusesource.fabric.commands;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+import org.fusesource.fabric.api.Container;
+import org.fusesource.fabric.api.Profile;
+import org.fusesource.fabric.api.Version;
+import org.fusesource.fabric.commands.support.ContainerUpgradeSupport;
+
+@Command(name = "container-rollback", scope = "fabric", description = "Rollback containers to an older version")
+public class ContainerRollback extends ContainerUpgradeSupport {
+
+ @Option(name = "--version", description = "The version to rollback", required = true)
+ private String version;
+
+ @Argument(index = 0, name = "container", description = "The list of containers to rollback. Empty list assumes current container only.", required = false, multiValued = true)
+ private List<String> containerIds;
+
+ @Override
+ protected Object doExecute() throws Exception {
+ // check and validate version
+ Version version = fabricService.getVersion(this.version);
+
+ if (containerIds == null || containerIds.isEmpty()) {
+ containerIds = Arrays.asList(fabricService.getCurrentContainer().getId());
+ }
+
+ List<Container> toRollback = new ArrayList<Container>();
+ List<Container> same = new ArrayList<Container>();
+ for (String containerName : containerIds) {
+ Container container = fabricService.getContainer(containerName);
+
+ // check first that all can rollback
+ int num = canRollback(version, container);
+ if (num < 0) {
+ throw new IllegalArgumentException("Container " + container.getId() + " has already lower version " + container.getVersion()
+ + " than the requested version " + version + " to rollback.");
+ } else if (num == 0) {
+ // same version
+ same.add(container);
+ } else {
+ // needs rollback
+ toRollback.add(container);
+ }
+ }
+
+ // report same version
+ for (Container container : same) {
+ System.out.println("Container " + container.getId() + " is already version " + version);
+ }
+
+ // report and do rollbacks
+ for (Container container : toRollback) {
+ Version oldVersion = container.getVersion();
+ Profile[] oldProfiles = container.getProfiles();
+
+ // create list of new profiles
+ Profile[] newProfiles = getProfilesForUpgradeOrRollback(oldProfiles, version);
+
+ // rollback version first
+ container.setVersion(version);
+ // then set new profiles, which triggers container to update bundles and whatnot
+ container.setProfiles(newProfiles);
+
+ // get the profile for version 1.1
+ log.debug("Rolled back container {} from {} to {}", new Object[]{container, oldVersion, version});
+ System.out.println("Rolled back container " + container.getId() + " from version " + oldVersion + " to " + version);
+ }
+
+ return null;
+ }
+
+}
@@ -16,18 +16,20 @@
*/
package org.fusesource.fabric.commands;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.Option;
import org.fusesource.fabric.api.Container;
+import org.fusesource.fabric.api.Profile;
import org.fusesource.fabric.api.Version;
-import org.fusesource.fabric.commands.support.FabricCommand;
+import org.fusesource.fabric.commands.support.ContainerUpgradeSupport;
-@Command(name = "container-upgrade", scope = "fabric", description = "Upgrades containers to a new version")
-public class ContainerUpgrade extends FabricCommand {
+@Command(name = "container-upgrade", scope = "fabric", description = "Upgrade containers to a new version")
+public class ContainerUpgrade extends ContainerUpgradeSupport {
@Option(name = "--version", description = "The version to upgrade", required = true)
private String version;
@@ -44,26 +46,49 @@ protected Object doExecute() throws Exception {
containerIds = Arrays.asList(fabricService.getCurrentContainer().getId());
}
- // check that all container current version is <= the version to upgrade
+ List<Container> toUpgrade = new ArrayList<Container>();
+ List<Container> same = new ArrayList<Container>();
for (String containerName : containerIds) {
Container container = fabricService.getContainer(containerName);
- // version should be upgradeable, so compare current version to the upgraded version
- Version current = container.getVersion();
- int num = version.compareTo(current);
-
+ // check first that all can upgrade
+ int num = canUpgrade(version, container);
if (num < 0) {
- throw new IllegalArgumentException("Container " + container.getId() + " has already higher version " + current
- + " than the requested version " + version + " to be updated.");
- } else if (num > 0) {
- // upgrade container
- container.setVersion(version);
- System.out.println("Upgraded container " + container.getId() + " from version " + current + " to " + version);
+ throw new IllegalArgumentException("Container " + container.getId() + " has already higher version " + container.getVersion()
+ + " than the requested version " + version + " to update.");
+ } else if (num == 0) {
+ // same version
+ same.add(container);
} else {
- // already same version
- System.out.println("Container " + container.getId() + " is already version " + current);
+ // needs upgrade
+ toUpgrade.add(container);
}
}
+
+ // report same version
+ for (Container container : same) {
+ System.out.println("Container " + container.getId() + " is already version " + version);
+ }
+
+ // report and do upgrades
+ for (Container container : toUpgrade) {
+ Version oldVersion = container.getVersion();
+ Profile[] oldProfiles = container.getProfiles();
+
+ // create list of new profiles
+ Profile[] newProfiles = getProfilesForUpgradeOrRollback(oldProfiles, version);
+
+ // upgrade version first
+ container.setVersion(version);
+ // then set new profiles, which triggers container to update bundles and whatnot
+ container.setProfiles(newProfiles);
+
+ // get the profile for version 1.1
+ log.debug("Upgraded container {} from {} to {}", new Object[]{container, oldVersion, version});
+ System.out.println("Upgraded container " + container.getId() + " from version " + oldVersion + " to " + version);
+ }
+
return null;
}
+
}
@@ -28,7 +28,7 @@
@Option(name = "--parent", description = "The parent version (will default use latest version as parent)")
private String parentVersion;
- @Argument(index = 0, required = false)
+ @Argument(index = 0, description = "Version number. If left blank Fabric will use next minor version.", required = false)
private String name;
@Override
@@ -0,0 +1,59 @@
+package org.fusesource.fabric.commands.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.fusesource.fabric.api.Container;
+import org.fusesource.fabric.api.Profile;
+import org.fusesource.fabric.api.Version;
+
+public abstract class ContainerUpgradeSupport extends FabricCommand {
+
+ /**
+ * Gets the profiles for upgrade/rollback
+ *
+ * @param existingProfiles the existing profiles
+ * @param targetVersion the target version
+ * @return the new profiles to be used
+ */
+ protected Profile[] getProfilesForUpgradeOrRollback(Profile[] existingProfiles, Version targetVersion) {
+ List<Profile> list = new ArrayList<Profile>(existingProfiles.length);
+ for (Profile old : existingProfiles) {
+ // get new profile
+ Profile newProfile = targetVersion.getProfile(old.getId());
+ if (newProfile != null) {
+ list.add(newProfile);
+ } else {
+ // we expect a profile with the new version to exist
+ throw new IllegalArgumentException("Profile " + old.getId() + " with version " + targetVersion + " does not exists");
+ }
+ }
+
+ return list.toArray(new Profile[0]);
+ }
+
+ /**
+ * Compare the version with the container
+ *
+ * @param version the version to rollback to
+ * @param container the container
+ * @return <tt>-1</tt> if cannot rollback, <tt>0</tt> if same version, or <tt>1</tt> if can rollback
+ */
+ protected int canUpgrade(Version version, Container container) {
+ Version current = container.getVersion();
+ return version.compareTo(current);
+ }
+
+ /**
+ * Compare the version with the container
+ *
+ * @param version the version to rollback to
+ * @param container the container
+ * @return <tt>-1</tt> if cannot rollback, <tt>0</tt> if same version, or <tt>1</tt> if can rollback
+ */
+ protected int canRollback(Version version, Container container) {
+ // reverse login than canUpgrade so * -1
+ return canUpgrade(version, container) * -1;
+ }
+
+}
@@ -160,6 +160,14 @@
<ref component-id="containerCompleter"/>
</completers>
</command>
+ <command name="fabric/container-rollback">
+ <action class="org.fusesource.fabric.commands.ContainerRollback">
+ <property name="fabricService" ref="fabricService"/>
+ </action>
+ <completers>
+ <ref component-id="containerCompleter"/>
+ </completers>
+ </command>
<command name="fabric/container-domains">
<action class="org.fusesource.fabric.commands.ContainerDomains">

0 comments on commit 8e6c792

Please sign in to comment.