diff --git a/packaging/org.pongasoft.glu.packaging-setup-impl/build.gradle b/packaging/org.pongasoft.glu.packaging-setup-impl/build.gradle index 60c047f4..2329c0f0 100644 --- a/packaging/org.pongasoft.glu.packaging-setup-impl/build.gradle +++ b/packaging/org.pongasoft.glu.packaging-setup-impl/build.gradle @@ -18,10 +18,9 @@ apply plugin: 'groovy' apply plugin: 'org.linkedin.release' dependencies { - compile spec.external.utilsMiscCore + compile project(':utils:org.linkedin.glu.utils') compile spec.external.groovy - testCompile spec.external.utilsMiscGroovy testCompile spec.external.junit testRuntime project(':utils:org.linkedin.glu.utils.log4j-test-config') diff --git a/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/BasePackager.groovy b/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/BasePackager.groovy new file mode 100644 index 00000000..3d3aada7 --- /dev/null +++ b/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/BasePackager.groovy @@ -0,0 +1,27 @@ +package org.pongasoft.glu.packaging.setup + +import org.linkedin.util.io.resource.Resource +import org.linkedin.groovy.util.io.fs.FileSystem + +/** + * @author yan@pongasoft.com */ +public class BasePackager +{ + FileSystem fileSystem + Resource outputFolder + Resource inputPackage + + String getPackageName() + { + def fileName = inputPackage.filename + if(fileName.endsWith(".tgz")) + return fileName[0..-5] + else + return fileName + } + + Resource copyInputPackage(Resource destination) + { + + } +} \ No newline at end of file diff --git a/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/KeysGenerator.groovy b/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/KeysGenerator.groovy index 41b70641..7212e6ed 100644 --- a/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/KeysGenerator.groovy +++ b/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/KeysGenerator.groovy @@ -16,17 +16,16 @@ package org.pongasoft.glu.packaging.setup +import org.linkedin.groovy.util.io.fs.FileSystem import org.linkedin.util.codec.Base64Codec import org.linkedin.util.codec.Codec import org.linkedin.util.codec.CodecUtils import org.linkedin.util.codec.OneWayCodec import org.linkedin.util.codec.OneWayMessageDigestCodec +import org.linkedin.util.io.resource.Resource import org.slf4j.Logger import org.slf4j.LoggerFactory -import java.nio.file.Files -import java.nio.file.Path - /** * The purpose of this class is to generate keys and keystore for glu * @@ -38,7 +37,8 @@ public class KeysGenerator Codec base64Codec = new Base64Codec() - Path outputFolder + FileSystem fileSystem + Resource outputFolder String masterPassword String sha1Password = 'gluos1way1' String encryptingKey = 'gluos2way' @@ -105,20 +105,20 @@ public class KeysGenerator } } - String computeChecksum(Path path) + String computeChecksum(Resource resource) { OneWayCodec oneWayCodec = OneWayMessageDigestCodec.createSHA1Instance(new String(sha1Password), new Base64Codec(new String(encryptingKey))); - return oneWayCodec.encode(readFile(path)) + return oneWayCodec.encode(readFile(resource)) } - private static byte[] readFile(Path path) throws IOException + private static byte[] readFile(Resource resource) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Files.newInputStream(path).withStream { stream -> + resource.inputStream.withStream { stream -> baos << stream } @@ -128,17 +128,17 @@ public class KeysGenerator /** * Step 1: generate agent keystore * - * @return the path to the keystore + * @return the resource to the keystore */ - Path generateAgentKeystore() + Resource generateAgentKeystore() { - createPathInOutputFolder('agent.keystore') { Path agentKeystore -> + createResourceInOutputFolder('agent.keystore') { Resource agentKeystore -> def cmd = [ 'keytool', '-noprompt', '-genkey', '-alias', 'agent', - '-keystore', agentKeystore.toString(), + '-keystore', agentKeystore.file.canonicalPath, '-storepass', getPasswords().agentKeystore, '-keypass', getPasswords().agentKey, '-keyalg', opts.keyalg, @@ -147,7 +147,7 @@ public class KeysGenerator '-dname', opts.dname.collect {k, v -> "${k}=${v}"}.join(', ') ] - def res = executeCommand(cmd) + def res = SetupUtils.executeCommand(cmd) log.info "Created agent.keystore" if(res) @@ -160,26 +160,26 @@ public class KeysGenerator /** * Step 2: extract the certificate from the agent keystore to create the agent truststore * - * @return the path to the truststore + * @return the resource to the truststore */ - Path generateAgentTruststore(Path agentKeystore) + Resource generateAgentTruststore(Resource agentKeystore) { - createPathInOutputFolder('agent.truststore') { Path agentTruststore -> + createResourceInOutputFolder('agent.truststore') { Resource agentTruststore -> - createPathInOutputFolder('agent.cert.temp', false) { Path tempFile -> + createResourceInOutputFolder('agent.cert.temp', false) { Resource tempFile -> try { def cmd = [ 'keytool', '-noprompt', '-export', - '-keystore', agentKeystore.toString(), + '-keystore', agentKeystore.file.canonicalPath, '-storepass', getPasswords().agentKeystore, '-alias', 'agent', - '-file', tempFile.toString() + '-file', tempFile.file.canonicalPath ] - def res = executeCommand(cmd) + def res = SetupUtils.executeCommand(cmd) log.debug "Created agent.cert.temp" if(res) @@ -190,12 +190,12 @@ public class KeysGenerator '-noprompt', '-import', '-alias', 'agent', - '-keystore', agentTruststore.toString(), + '-keystore', agentTruststore.file.canonicalPath, '-storepass', getPasswords().agentTruststore, - '-file', tempFile.toString() + '-file', tempFile.file.canonicalPath ] - res = executeCommand(cmd) + res = SetupUtils.executeCommand(cmd) log.info "Created agent.truststore" if(res) @@ -204,7 +204,7 @@ public class KeysGenerator } finally { - Files.delete(tempFile) + fileSystem.rm(tempFile) } return tempFile @@ -217,17 +217,17 @@ public class KeysGenerator /** * Step 3: generate console keystore * - * @return the path to the keystore + * @return the resource to the keystore */ - Path generateConsoleKeystore() + Resource generateConsoleKeystore() { - createPathInOutputFolder('console.keystore') { Path consoleKeystore -> + createResourceInOutputFolder('console.keystore') { Resource consoleKeystore -> def cmd = [ 'keytool', '-noprompt', '-genkey', '-alias', 'console', - '-keystore', consoleKeystore.toString(), + '-keystore', consoleKeystore.file.canonicalPath, '-storepass', getPasswords().consoleKeystore, '-keypass', getPasswords().consoleKey, '-keyalg', opts.keyalg, @@ -236,7 +236,7 @@ public class KeysGenerator '-dname', opts.dname.collect {k, v -> "${k}=${v}"}.join(', ') ] - def res = executeCommand(cmd) + def res = SetupUtils.executeCommand(cmd) log.info "Created console.keystore" if(res) @@ -250,26 +250,26 @@ public class KeysGenerator /** * Step 4: extract the certificate from the console keystore to create the console truststore * - * @return the path to the truststore + * @return the resource to the truststore */ - Path generateConsoleTruststore(Path consoleKeystore) + Resource generateConsoleTruststore(Resource consoleKeystore) { - createPathInOutputFolder('console.truststore') { Path consoleTruststore -> + createResourceInOutputFolder('console.truststore') { Resource consoleTruststore -> - createPathInOutputFolder('console.cert.temp', false) { Path tempFile -> + createResourceInOutputFolder('console.cert.temp', false) { Resource tempFile -> try { def cmd = [ 'keytool', '-noprompt', '-export', - '-keystore', consoleKeystore.toString(), + '-keystore', consoleKeystore.file.canonicalPath, '-storepass', getPasswords().consoleKeystore, '-alias', 'console', - '-file', tempFile.toString() + '-file', tempFile.file.canonicalPath ] - def res = executeCommand(cmd) + def res = SetupUtils.executeCommand(cmd) log.debug "Created console.cert.temp" if(res) @@ -280,12 +280,12 @@ public class KeysGenerator '-noprompt', '-import', '-alias', 'console', - '-keystore', consoleTruststore.toString(), + '-keystore', consoleTruststore.file.canonicalPath, '-storepass', getPasswords().consoleTruststore, - '-file', tempFile.toString() + '-file', tempFile.file.canonicalPath ] - res = executeCommand(cmd) + res = SetupUtils.executeCommand(cmd) log.info "Created console.truststore" if(res) @@ -294,7 +294,7 @@ public class KeysGenerator } finally { - Files.delete(tempFile) + fileSystem.rm(tempFile) } return tempFile @@ -304,33 +304,16 @@ public class KeysGenerator } } - private String executeCommand(def cmd) - { - Process process = cmd.execute() - Thread.start { - System.err << process.errorStream - } - Thread.start { - process.outputStream.close() - } - def res = process.text - - if(process.waitFor() != 0) - throw new Exception("error while executing command") - - return res - } - - private Path createPathInOutputFolder(String name, - boolean callClosureOnlyIfFileDoesNotExist = true, - Closure closure) + private Resource createResourceInOutputFolder(String name, + boolean callClosureOnlyIfFileDoesNotExist = true, + Closure closure) { - if(!Files.exists(outputFolder)) - Files.createDirectories(outputFolder) - Path path = outputFolder.resolve(name).toAbsolutePath() - if(!callClosureOnlyIfFileDoesNotExist || !Files.exists(path)) - path = closure(path) - return path + if(!outputFolder.exists()) + fileSystem.mkdirs(outputFolder) + Resource resource = outputFolder.createRelative(name) + if(!callClosureOnlyIfFileDoesNotExist || !resource.exists()) + resource = closure(resource) + return resource } } \ No newline at end of file diff --git a/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/SetupUtils.groovy b/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/SetupUtils.groovy new file mode 100644 index 00000000..167e514e --- /dev/null +++ b/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/SetupUtils.groovy @@ -0,0 +1,27 @@ +package org.pongasoft.glu.packaging.setup + +/** + * Contains a set of utilities methods + * + * @author yan@pongasoft.com */ +public class SetupUtils +{ + static String executeCommand(def cmd) + { + println cmd + Process process = cmd.execute() + Thread.start { + System.err << process.errorStream + } + Thread.start { + process.outputStream.close() + } + def res = process.text + + if(process.waitFor() != 0) + throw new Exception("error while executing command") + + return res + } + +} \ No newline at end of file diff --git a/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/ZooKeeperPackager.groovy b/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/ZooKeeperPackager.groovy new file mode 100644 index 00000000..f0fa46ba --- /dev/null +++ b/packaging/org.pongasoft.glu.packaging-setup-impl/src/main/groovy/org/pongasoft/glu/packaging/setup/ZooKeeperPackager.groovy @@ -0,0 +1,26 @@ +package org.pongasoft.glu.packaging.setup + +import org.linkedin.util.io.resource.Resource + +/** + * @author yan@pongasoft.com */ +public class ZooKeeperPackager extends BasePackager +{ + def zookeperServers = [:] + + Collection createPackages() + { + int serverIndex = 1 + zookeperServers.collect { String host, post -> + createPackage(serverIndex++, host, post.toString() as int) + } + } + + Resource createPackage(int serverIndex, String host, int port) + { + def newPackageName = "${packageName}-${host}-${port}" + Resource packagePath = outputFolder.createRelative(newPackageName) + return packagePath + } + +} \ No newline at end of file diff --git a/packaging/org.pongasoft.glu.packaging-setup-impl/src/test/groovy/test/setup/TestKeysGenerator.groovy b/packaging/org.pongasoft.glu.packaging-setup-impl/src/test/groovy/test/setup/TestKeysGenerator.groovy index 8321fc2c..df9fd989 100644 --- a/packaging/org.pongasoft.glu.packaging-setup-impl/src/test/groovy/test/setup/TestKeysGenerator.groovy +++ b/packaging/org.pongasoft.glu.packaging-setup-impl/src/test/groovy/test/setup/TestKeysGenerator.groovy @@ -18,11 +18,9 @@ package test.setup import org.linkedin.groovy.util.io.fs.FileSystem import org.linkedin.groovy.util.io.fs.FileSystemImpl +import org.linkedin.util.io.resource.Resource import org.pongasoft.glu.packaging.setup.KeysGenerator -import java.nio.file.Files -import java.nio.file.Path - /** * @author yan@pongasoft.com */ public class TestKeysGenerator extends GroovyTestCase @@ -31,13 +29,14 @@ public class TestKeysGenerator extends GroovyTestCase { FileSystemImpl.createTempFileSystem { FileSystem fs -> - def generator = new KeysGenerator(outputFolder: fs.toResource('/keys').getFile().toPath(), + def generator = new KeysGenerator(fileSystem: fs, + outputFolder: fs.toResource('/keys'), masterPassword: "abcdefgh") def keys = generator.generateKeys() assertEquals(4, keys.size()) - assertNull(keys.values().find { Path path -> - !Files.exists(path) + assertNull(keys.values().find { Resource resource -> + !resource.exists() }) def expectedPasswords = [ @@ -68,13 +67,14 @@ public class TestKeysGenerator extends GroovyTestCase { FileSystemImpl.createTempFileSystem { FileSystem fs -> - def generator = new KeysGenerator(outputFolder: fs.toResource('/keys').getFile().toPath(), + def generator = new KeysGenerator(fileSystem: fs, + outputFolder: fs.toResource('/keys'), masterPassword: "abcdefgh") // since keystores and truststores change every time, we need to create a file for // which we control the content so that the checksum is predictable assertEquals('kH_rwI1Cii2_Wk8HBcDju9vKbq3', - generator.computeChecksum(fs.saveContent('/foo.txt', 'abcdef').file.toPath())) + generator.computeChecksum(fs.saveContent('/foo.txt', 'abcdef'))) } }