Permalink
Browse files

introduce CommandBuilder class

update some actions to use the CommandBuilder
fix some typos
  • Loading branch information...
Stanislav Tiurikov
Stanislav Tiurikov committed Oct 30, 2017
1 parent 20699b4 commit 562c3c8e562462169eb2731f5afc5d5fc7cc7cdc
@@ -37,7 +37,7 @@ class AwsMachineImageBuilder {
@Min(0l)
int waitingDelay = 3000
private static final String STATUS_HEARED = "> aws image builder:"
private static final String STATUS_HEADER = "> aws image builder:"
def node(Map params) { node(params, {}) }
def node(Closure closure) { node([:], closure) }
@@ -60,7 +60,7 @@ class AwsMachineImageBuilder {
info "staring image creation for '$imageName'"
statusLine "$STATUS_HEARED checking for an existing image with name '$imageName'"
statusLine "$STATUS_HEADER checking for an existing image with name '$imageName'"
def oldImage = findImage(amazonEC2, imageName)
info "checking if there is an existing image with the same name"
@@ -77,40 +77,40 @@ class AwsMachineImageBuilder {
info "creating a base EC2 instance"
statusLine "$STATUS_HEARED waiting for the base EC2 instance is running"
statusLine "$STATUS_HEADER waiting for the base EC2 instance is running"
awsNode.create(amazonEC2, usePublicIp)
statusLine "$STATUS_HEARED waiting for the instance SSH connectivity is available"
statusLine "$STATUS_HEADER waiting for the instance SSH connectivity is available"
retry(waitingCount, waitingDelay) {
assert canConnectTo(host: awsNode.host, port: awsNode.port)
}
info "configuring the base EC2 instance '$awsNode.id'"
statusLine "$STATUS_HEARED configuring the instance"
statusLine "$STATUS_HEADER configuring the instance"
provision([awsNode], closure)
info "stopping the base EC2 instance '$awsNode.id'"
awsNode.stop(amazonEC2)
statusLine "$STATUS_HEARED waiting for the base EC2 instance is stopped"
statusLine "$STATUS_HEADER waiting for the base EC2 instance is stopped"
waitForInstanceState(amazonEC2, awsNode.id, waitingCount, waitingDelay, 'stopped')
statusLine "$STATUS_HEARED creating an image"
statusLine "$STATUS_HEADER creating an image"
info "creating an image '$imageName'"
def newImageId = createImage(amazonEC2, imageName, awsNode.id)
statusLine "$STATUS_HEARED waiting for image is available"
statusLine "$STATUS_HEADER waiting for image is available"
waitForImageState(amazonEC2, newImageId, waitingCount, waitingDelay, 'available')
info "image creation is done: '$newImageId'"
if (terminateInstance) {
statusLine "$STATUS_HEARED terminating the instance"
statusLine "$STATUS_HEADER terminating the instance"
awsNode.remove(amazonEC2)
}
statusLine "$STATUS_HEARED image creation proccess has been done"
statusLine "$STATUS_HEADER image creation proccess has been done"
return newImageId
}
}
@@ -0,0 +1,28 @@
package io.infrastructor.core.inventory
class CommandBuilder {
def command = []
def add(def part) {
command << part
this
}
def add(def condition, def part) {
if (condition) { add part }
this
}
def build() {
command.join(' ')
}
def static CMD(def closure) {
def builder = new CommandBuilder()
closure.delegate = builder
closure()
builder.build()
}
}
@@ -7,6 +7,7 @@ import com.jcraft.jsch.JSchException
import static io.infrastructor.core.utils.RetryUtils.retry
import static io.infrastructor.core.logging.ConsoleLogger.*
import static io.infrastructor.core.inventory.SshClient.sshClient
import static io.infrastructor.core.inventory.CommandBuilder.CMD
@ToString(includePackage = false, includeNames = true, ignoreNulls = true)
public class Node {
@@ -56,37 +57,63 @@ public class Node {
return lastResult
}
def readFile(def file, def output, def sudo = false) {
execute output: output, command: CMD {
add sudo, "sudo"
add "cat '$file'"
}
}
def readFile(def file, def stream, def sudo = false) {
execute sudo: sudo, output: stream, command: "cat '$file'"
def writeFile(def target, def input, def sudo = false) {
execute command: CMD {
add sudo, "sudo"
add "sh -c \"dirname '$target' | xargs -I '{}' mkdir -p '{}'\""
}
execute input: input, command: CMD {
add "cat | "
add sudo, "sudo"
add "tee '$target'"
}
}
def writeText(def target, def content, def sudo = false) {
writeFile(target, new ByteArrayInputStream(content.getBytes()), sudo)
}
def writeFile(def target, def stream, def sudo = false) {
execute sudo: sudo, command: "sh -c \"dirname '$target' | xargs -I '{}' mkdir -p '{}'\""
execute input: stream, command: "cat | " + (sudo ? "sudo tee '$target'" : "tee '$target'")
}
def updateOwner(def target, def owner, def sudo = false) {
if (owner) execute sudo: sudo, command: "chown $owner: $target"
if (owner) {
execute command: CMD {
add sudo, "sudo"
add "chown $owner: $target"
}
}
}
def updateGroup(def target, def group, def sudo = false) {
if (group) execute sudo: sudo, command: "chown :$group $target"
if (group) {
execute command: CMD {
add sudo, "sudo"
add "chown :$group $target"
}
}
}
def updateMode(def target, def mode, def sudo = false) {
if (mode) execute sudo: sudo, command: "chmod $mode $target"
if (mode) {
execute command: CMD {
add sudo, "sudo"
add "chmod $mode $target"
}
}
}
def allTags() { tags }
def listTags() {
def list = []
allTags().each() { k, v -> list << ("$k:$v" as String) }
allTags().each { k, v -> list << ("$k:$v" as String) }
list
}
@@ -24,42 +24,39 @@ class SshClient {
}
def isConnected() {
session != null && session.isConnected()
session?.isConnected()
}
private def connect() {
if (!isConnected()) {
JSch jsch = new JSch()
JSch.setConfig("StrictHostKeyChecking", "no")
JSch.setLogger(new Logger() {
@Override
public boolean isEnabled(int level) { return true; }
public boolean isEnabled(int level) { return true }
@Override
public void log(int level, String message) { trace "jsch: $message" }
});
})
if (keyfile) jsch.addIdentity(keyfile)
session = jsch.getSession(username, host, port)
if (password) session.setPassword(password)
session.setServerAliveInterval(5000);
session.setServerAliveCountMax(1000000);
session.setServerAliveInterval(5000)
session.setServerAliveCountMax(1000000)
session.connect()
return session.isConnected()
}
}
def disconnect() {
if(isConnected()) {
session.disconnect()
}
if (isConnected()) { session.disconnect() }
session = null
}
def execute(def command) {
new SshCommand(command).execute()
def execute(def params) {
new SshCommand(params).execute()
}
private def executeSsh(String command, InputStream input, OutputStream output, OutputStream error) {
@@ -73,10 +70,12 @@ class SshClient {
channel.setOutputStream(output)
channel.setErrStream(error)
channel.connect()
while (!channel.isClosed()) {
Thread.sleep(55)
session.sendKeepAliveMsg()
}
return channel.getExitStatus()
} catch (Exception ex) {
throw new RuntimeException(ex)
@@ -86,40 +85,32 @@ class SshClient {
}
}
}
class SshCommand {
def command
def sudo = false
def output = new ByteArrayOutputStream()
def error = new ByteArrayOutputStream()
def input = new ByteArrayInputStream()
public def execute() {
try {
def result = [:]
result.exitcode = -1
def result = [exitcode: -1, command: command]
try { result.exitcode = executeSsh(withSudo(sudo, command), input, output, error) }
try { result.exitcode = executeSsh(command, input, output, error) }
catch (IOException ex) {
error "IO exception during command execution: $command"
error (ex.getMessage())
}
result.output = output.toString()
result.error = error.toString()
result.command = command
result.sudo = sudo
result.output = output.toString()
return result
} finally {
input.close()
output.close()
error.close()
}
}
public def withSudo(def sudo, def command) {
return sudo ? "sudo $command" : command
}
}
}
@@ -2,6 +2,8 @@ package io.infrastructor.core.processing.actions
import javax.validation.constraints.NotNull
import static io.infrastructor.core.inventory.CommandBuilder.CMD
public class DirectoryAction {
@NotNull
def target
@@ -11,7 +13,14 @@ public class DirectoryAction {
def sudo = false
def execute(def node) {
node.execute(command: "mkdir " + (mode ? "-m $mode" : "") + " -p $target", sudo: sudo)
def cmd = CMD {
add sudo, "sudo"
add "mkdir"
add mode, "-m $mode"
add "-p $target"
}
node.execute command: cmd
node.updateOwner(target, owner, sudo)
node.updateGroup(target, group, sudo)
node.lastResult
@@ -2,14 +2,23 @@ package io.infrastructor.core.processing.actions
import javax.validation.constraints.NotNull
import static io.infrastructor.core.inventory.CommandBuilder.CMD
public class GroupAction {
@NotNull
def name
def gid
def sudo = false
def execute(def node) {
node.execute(command: "groupadd ${gid ? '-g ' + gid : ''} $name", sudo: sudo)
def cmd = CMD {
add sudo, "sudo"
add "groupadd"
add gid, "-g $gid"
add name
}
node.execute command: cmd
node.lastResult
}
}
@@ -2,25 +2,33 @@ package io.infrastructor.core.processing.actions
import javax.validation.constraints.NotNull
import static io.infrastructor.core.inventory.CommandBuilder.CMD
class ShellAction {
@NotNull
def command
def sudo
def execute(def node) {
if (command.contains("\n")) {
def result = node.execute(command: "mktemp")
def result = node.execute command: "mktemp"
def temp = result.output.trim()
try {
node.writeText(temp, command.stripIndent())
node.execute(command: "sh $temp", sudo: sudo)
node.execute command: CMD {
add sudo, "sudo"
add "sh $temp"
}
return node.lastResult
} finally {
node.execute(command: "rm $temp")
node.execute command: "rm $temp"
}
} else {
node.execute(command: command, sudo: sudo)
node.execute command: CMD {
add sudo, "sudo"
add command
}
}
node.lastResult
Oops, something went wrong.

0 comments on commit 562c3c8

Please sign in to comment.