├── .blaze ├── blaze.conf ├── blaze.java └── pom.xml ├── .github └── workflows │ ├── java11.yaml │ ├── java17.yaml │ ├── java21.yaml │ ├── java8.yaml │ ├── macos-arm64.yaml │ └── windows-x64.yaml ├── .gitignore ├── CHANGELOG.md ├── README.md ├── Vagrantfile ├── blaze.jar ├── buildx-results.txt ├── docs ├── CANONICAL_LAYOUT.md └── DEV.md ├── pom.xml ├── setup └── jsl.0.99x.zip ├── stork-assembly ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── fizzed │ └── stork │ └── assembly │ ├── AssemblyMain.java │ ├── AssemblyUtils.java │ └── CopyFile.java ├── stork-bom └── pom.xml ├── stork-cli ├── pom.xml └── src │ └── main │ ├── launchers │ ├── stork-deploy.yml │ └── stork-launcher.yml │ └── resources │ └── logback.xml ├── stork-core ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── fizzed │ └── stork │ └── core │ ├── ArgumentException.java │ └── BaseApplication.java ├── stork-demo ├── stork-demo-dropwizard │ ├── README.md │ ├── conf │ │ └── hello.yml │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── fizzed │ │ │ └── stork │ │ │ └── demo │ │ │ └── dropwizard │ │ │ ├── HelloApplication.java │ │ │ ├── HelloConfiguration.java │ │ │ └── HelloResource.java │ │ └── launchers │ │ └── stork-demo-dropwizard.yml └── stork-demo-hellod │ ├── Dockerfile │ ├── README.md │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── com │ │ └── fizzed │ │ └── stork │ │ └── demo │ │ └── hellod │ │ └── Hellod.java │ ├── launchers │ └── stork-demo-hellod.yml │ └── resources │ └── logback.xml ├── stork-deploy ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── fizzed │ │ └── stork │ │ └── deploy │ │ ├── Archive.java │ │ ├── Assembly.java │ │ ├── Assemblys.java │ │ ├── BasicFile.java │ │ ├── CloseablePath.java │ │ ├── Daemon.java │ │ ├── DeployHelper.java │ │ ├── DeployMain.java │ │ ├── DeployOptions.java │ │ ├── Deployer.java │ │ ├── DeployerException.java │ │ ├── Deployment.java │ │ ├── DeploymentType.java │ │ ├── Deployments.java │ │ ├── ExistingDeployment.java │ │ ├── InitType.java │ │ ├── SshTarget.java │ │ ├── SystemdHelper.java │ │ ├── Target.java │ │ ├── Targets.java │ │ ├── UnixTarget.java │ │ └── VersionedPath.java │ └── test │ ├── java │ └── com │ │ └── fizzed │ │ └── stork │ │ └── deploy │ │ ├── AssemblysTest.java │ │ ├── DeployMain.java │ │ ├── DeployerBaseTest.java │ │ ├── DeployerConsoleTest.java │ │ ├── DeployerDaemonTest.java │ │ ├── TargetsTest.java │ │ └── TestHelper.java │ ├── launchers │ ├── stork-console1.yml │ └── stork-daemon1.yml │ └── resources │ ├── fixtures │ ├── hello-conf-1.2.4-SNAPSHOT.zip │ ├── hello-console-1.2.4.tar.gz │ ├── hello-console-1.2.4.zip │ ├── hello-world-1.2.4-SNAPSHOT.tar.gz │ └── hello-world-1.2.4-SNAPSHOT.zip │ └── logback.xml ├── stork-gradle-plugin ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── pom.xml └── src │ ├── main │ └── groovy │ │ └── com │ │ └── fizzed │ │ └── stork │ │ └── gradle │ │ ├── StorkPlugin.groovy │ │ └── tasks │ │ ├── AssemblyExtension.groovy │ │ ├── AssemblyTask.groovy │ │ ├── LauncherExtension.groovy │ │ ├── LaunchersExtension.groovy │ │ └── LaunchersTask.groovy │ └── test │ └── groovy │ └── com │ └── fizzed │ └── stork │ └── gradle │ └── StorkPluginTests.groovy ├── stork-launcher ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── fizzed │ │ │ └── stork │ │ │ └── launcher │ │ │ ├── Configuration.java │ │ │ ├── ConfigurationFactory.java │ │ │ ├── FileUtil.java │ │ │ ├── Generator.java │ │ │ ├── JacksonUtil.java │ │ │ ├── LauncherMain.java │ │ │ ├── LauncherModel.java │ │ │ ├── MergeMain.java │ │ │ ├── Merger.java │ │ │ └── PlatformConfiguration.java │ └── resources │ │ └── com │ │ └── fizzed │ │ └── stork │ │ └── launcher │ │ ├── linux │ │ ├── initd-daemon.ftl │ │ ├── script-console.ftl │ │ ├── script-daemon-nohup.ftl │ │ ├── script-functions.sh │ │ ├── script-header.ftl │ │ ├── script-java-detect-header.sh │ │ ├── script-java-detect.sh │ │ ├── script-java.ftl │ │ ├── systemd-daemon.ftl │ │ ├── test-function.sh │ │ ├── test-java-detect.sh │ │ └── test-loop.sh │ │ ├── osx │ │ └── launchd.ftl │ │ └── windows │ │ ├── batch-console.ftl │ │ ├── batch-daemon-jslwin.ftl │ │ ├── batch-find-java.bat │ │ ├── batch-footer.ftl │ │ ├── batch-header.ftl │ │ ├── batch-java.ftl │ │ ├── config-daemon-jslwin.ftl │ │ ├── config-daemon-winsw.ftl │ │ ├── jslwin │ │ ├── jsl.exe │ │ ├── jsl.jar │ │ ├── jsl64.exe │ │ ├── jsl64_debug.exe │ │ └── jsl_debug.exe │ │ └── winsw │ │ ├── winsw-1.16-bin.exe │ │ └── winsw.exe.config │ └── test │ ├── java │ └── com │ │ └── fizzed │ │ └── stork │ │ └── launcher │ │ ├── LauncherTest.java │ │ └── TestHelper.java │ └── launchers │ ├── cat.yml │ ├── echo-console1.yml │ ├── echo-console2.yml │ ├── echo-console3.yml │ └── echo-daemon1.yml ├── stork-maven-plugin ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── fizzed │ └── stork │ └── maven │ ├── AssemblyMojo.java │ ├── LauncherMojo.java │ └── MergeMojo.java └── stork-test-app ├── pom.xml └── src └── main └── java └── com └── fizzed └── stork └── test ├── Arguments.java ├── CatMain.java ├── EchoConsoleMain.java ├── EchoDaemonMain.java └── LaunchData.java /.blaze/blaze.conf: -------------------------------------------------------------------------------- 1 | blaze.dependencies = [ 2 | "com.fizzed:blaze-ssh" 3 | "com.fizzed:blaze-public-project:1.0.1" 4 | ] 5 | 6 | java.source.version = 8 7 | -------------------------------------------------------------------------------- /.blaze/blaze.java: -------------------------------------------------------------------------------- 1 | import static com.fizzed.blaze.Contexts.fail; 2 | import static com.fizzed.blaze.Systems.exec; 3 | import static com.fizzed.blaze.Systems.which; 4 | 5 | import com.fizzed.blaze.project.PublicBlaze; 6 | 7 | import java.nio.file.Path; 8 | 9 | public class blaze extends PublicBlaze { 10 | 11 | private String getTestHost(boolean required) { 12 | String host = config.value("host").getOr(""); 13 | 14 | if (host.equals("")) { 15 | log.info("NOTE: you can limit which host your unit tests run on"); 16 | log.info(" by adding a -Dhost=HOST to your command. Valid hosts"); 17 | log.info(" are either 'local' or run 'vagrant status' for a list"); 18 | if (required) { 19 | fail("host is required"); 20 | } 21 | } else { 22 | log.info("NOTE: limiting unit tests to host {}", host); 23 | } 24 | 25 | return host; 26 | } 27 | 28 | public void test_launcher() { 29 | String host = getTestHost(false); 30 | exec("mvn", "test", "-am", "-pl", "stork-launcher-test", "-Dhost=" + host).run(); 31 | } 32 | 33 | public void test_deploy() { 34 | String host = getTestHost(false); 35 | exec("mvn", "test", "-am", "-pl", "stork-deploy", "-Dhost=" + host).run(); 36 | } 37 | 38 | public void demo_launcher() { 39 | exec("mvn", "package", "-DskipTests=true", "-am", "-pl", "stork-cli").run(); 40 | exec("stork-launcher", "-o", "target/stork-fake", "stork-cli/src/main/launchers") 41 | .workingDir("stork-cli/target/stork/bin") 42 | .run(); 43 | } 44 | 45 | public void demo_deploy() { 46 | String host = getTestHost(true); 47 | exec("mvn", "package", "-DskipTests=true", "-am", "-pl", "stork-cli").run(); 48 | exec("stork-deploy", "-a", "stork-deploy/src/test/resources/fixtures/hello-console-1.2.4.tar.gz", "vagrant+ssh://" + host) 49 | .workingDir("stork-cli/target/stork/bin") 50 | .run(); 51 | } 52 | 53 | public void demo_hellod() { 54 | exec("mvn", "package", "-DskipTests=true", "-am", "-pl", "stork-demo/stork-demo-hellod").run(); 55 | final Path command = which("stork-demo-hellod") 56 | .path("stork-demo/stork-demo-hellod/target/stork/bin") 57 | .run(); 58 | exec(command, "--run") 59 | .run(); 60 | } 61 | 62 | public void demo_dropwizard() { 63 | exec("mvn", "package", "-DskipTests=true", "-am", "-pl", "stork-demo/stork-demo-dropwizard").run(); 64 | final Path command = which("stork-demo-dropwizard") 65 | .path("stork-demo/stork-demo-dropwizard/target/stork/bin") 66 | .run(); 67 | exec(command, "--run") 68 | .env("EXTRA_JAVA_ARGS", "-Da=1") 69 | .run(); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /.blaze/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | blaze 4 | stork-blaze 5 | 0.0.1 6 | 7 | 12 | 13 | 14 | 8 15 | 8 16 | true 17 | true 18 | 19 | 20 | ${project.basedir} 21 | 22 | 23 | 24 | org.apache.ivy 25 | ivy 26 | 2.5.2 27 | 28 | 29 | com.fizzed 30 | blaze-core 31 | 1.8.0 32 | 33 | 34 | commons-io 35 | commons-io 36 | 2.16.1 37 | 38 | 39 | com.typesafe 40 | config 41 | 1.4.3 42 | 43 | 44 | com.fizzed 45 | blaze-ivy 46 | 1.8.0 47 | 48 | 49 | org.slf4j 50 | slf4j-simple 51 | 2.0.13 52 | 53 | 54 | org.slf4j 55 | slf4j-api 56 | 2.0.13 57 | 58 | 59 | org.zeroturnaround 60 | zt-exec 61 | 1.12 62 | 63 | 64 | com.fizzed 65 | blaze-ssh 66 | 1.8.0 67 | 68 | 69 | com.fizzed 70 | blaze-public-project 71 | 1.0.1 72 | 73 | 74 | -------------------------------------------------------------------------------- /.github/workflows/java11.yaml: -------------------------------------------------------------------------------- 1 | name: Java 11 2 | on: 3 | - push 4 | - workflow_dispatch 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - name: Set up Azul JDK 11 11 | uses: actions/setup-java@v3 12 | with: 13 | java-version: 11 14 | distribution: 'zulu' 15 | cache: 'maven' 16 | - name: Build with Maven 17 | run: mvn test 18 | -------------------------------------------------------------------------------- /.github/workflows/java17.yaml: -------------------------------------------------------------------------------- 1 | name: Java 17 2 | on: 3 | - push 4 | - workflow_dispatch 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - name: Set up Azul JDK 17 11 | uses: actions/setup-java@v3 12 | with: 13 | java-version: 17 14 | distribution: 'zulu' 15 | cache: 'maven' 16 | - name: Build with Maven 17 | run: mvn test 18 | -------------------------------------------------------------------------------- /.github/workflows/java21.yaml: -------------------------------------------------------------------------------- 1 | name: Java 21 2 | on: 3 | - push 4 | - workflow_dispatch 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - name: Set up Azul JDK 21 11 | uses: actions/setup-java@v3 12 | with: 13 | java-version: 21 14 | distribution: 'zulu' 15 | cache: 'maven' 16 | - name: Build with Maven 17 | run: mvn test 18 | -------------------------------------------------------------------------------- /.github/workflows/java8.yaml: -------------------------------------------------------------------------------- 1 | name: Java 8 2 | on: 3 | - push 4 | - workflow_dispatch 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - name: Set up Azul JDK 8 11 | uses: actions/setup-java@v3 12 | with: 13 | java-version: 8 14 | distribution: 'zulu' 15 | cache: 'maven' 16 | - name: Build with Maven 17 | run: mvn test 18 | -------------------------------------------------------------------------------- /.github/workflows/macos-arm64.yaml: -------------------------------------------------------------------------------- 1 | name: MacOS arm64 2 | on: 3 | - push 4 | - workflow_dispatch 5 | jobs: 6 | build: 7 | runs-on: macos-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - name: Set up Azul JDK 11 11 | uses: actions/setup-java@v3 12 | with: 13 | java-version: 11 14 | distribution: 'zulu' 15 | cache: 'maven' 16 | - name: Build with Maven 17 | run: mvn test 18 | -------------------------------------------------------------------------------- /.github/workflows/windows-x64.yaml: -------------------------------------------------------------------------------- 1 | name: Windows x64 2 | on: 3 | - push 4 | - workflow_dispatch 5 | jobs: 6 | build: 7 | runs-on: windows-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - name: Set up Azul JDK 11 11 | uses: actions/setup-java@v3 12 | with: 13 | java-version: 11 14 | distribution: 'zulu' 15 | cache: 'maven' 16 | - name: Build with Maven 17 | run: mvn test 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .vagrant 3 | *.iml 4 | .buildx 5 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure(2) do |config| 5 | 6 | config.vm.define "ubuntu14" do |guest| 7 | guest.vm.box = "minimal/trusty64" 8 | guest.vm.box_version = "14.04.3" 9 | guest.vm.provision :shell, inline: "echo 'install depends'; apt-get update; apt-get install -y openjdk-7-jre-headless unzip curl" 10 | # unit tests required passing along env vars in ssh commands 11 | guest.vm.provision :shell, inline: "echo 'forcing sshd to accept env'; echo 'AcceptEnv *' >> /etc/ssh/sshd_config" 12 | guest.vm.provision :shell, inline: "echo 'restart sshd'; service ssh restart" 13 | end 14 | 15 | config.vm.define "ubuntu16" do |guest| 16 | guest.vm.box = "bento/ubuntu-16.04" 17 | guest.vm.box_version = "201801.02.0" 18 | guest.vm.provision :shell, inline: "echo 'install depends'; apt update; apt install -y openjdk-8-jre-headless unzip curl" 19 | # unit tests required passing along env vars in ssh commands 20 | guest.vm.provision :shell, inline: "echo 'forcing sshd to accept env'; echo 'AcceptEnv *' >> /etc/ssh/sshd_config" 21 | guest.vm.provision :shell, inline: "echo 'restart sshd'; service ssh restart" 22 | end 23 | 24 | config.vm.define "ubuntu20" do |guest| 25 | guest.vm.box = "bento/ubuntu-20.04" 26 | guest.vm.box_version = "202005.21.0" 27 | guest.vm.provision :shell, inline: "echo 'install depends'; apt update; apt install -y openjdk-11-jre-headless unzip curl" 28 | # unit tests required passing along env vars in ssh commands 29 | guest.vm.provision :shell, inline: "echo 'forcing sshd to accept env'; echo 'AcceptEnv *' >> /etc/ssh/sshd_config" 30 | guest.vm.provision :shell, inline: "echo 'restart sshd'; service ssh restart" 31 | end 32 | 33 | config.vm.define "windows10" do |guest| 34 | guest.vm.box = "giorgioinf/win10N-shell" 35 | guest.vm.box_version = "0.0.1" 36 | # box crawls to a halt if less than 2G of RAM 37 | guest.vm.provider "virtualbox" do |vb| 38 | vb.customize ["modifyvm", :id, "--memory", "2048"] 39 | end 40 | # go into box and then run "choco install -y jdk8" 41 | #guest.vm.provision :shell, powershell_elevated_interactive: true, privileged: true, inline: "choco install -y jdk8" 42 | #guest.vm.provision :shell, path: "https://raw.githubusercontent.com/xpando/Dash/master/PowerShell/Scripts/Install-JDK8.ps1" 43 | end 44 | 45 | config.vm.define "debian8", autostart: false do |guest| 46 | guest.vm.box = "minimal/jessie64" 47 | guest.vm.box_version = "8.0" 48 | guest.vm.provision :shell, inline: "apt-get update; apt-get install -y openjdk-7-jre-headless unzip curl" 49 | # unit tests required passing along env vars in ssh commands 50 | guest.vm.provision :shell, inline: "echo 'forcing sshd to accept env'; echo 'AcceptEnv *' >> /etc/ssh/sshd_config" 51 | guest.vm.provision :shell, inline: "/etc/init.d/ssh restart" 52 | end 53 | 54 | config.vm.define "centos7", autostart: false do |guest| 55 | guest.vm.box = "minimal/centos7" 56 | guest.vm.box_version = "7.0" 57 | guest.vm.provision :shell, inline: "yum install -y java-1.7.0-openjdk-headless unzip curl" 58 | # unit tests required passing along env vars in ssh commands 59 | guest.vm.provision :shell, inline: "echo 'forcing sshd to accept env'; echo 'UseDNS no' >> /etc/ssh/sshd_config" 60 | guest.vm.provision :shell, inline: "echo 'forcing sshd to accept env'; echo 'AcceptEnv *' >> /etc/ssh/sshd_config" 61 | guest.vm.provision :shell, inline: "systemctl restart sshd.service" 62 | end 63 | 64 | config.vm.define "freebsd10", autostart: false do |guest| 65 | guest.vm.box = "bento/freebsd-10.3" 66 | guest.vm.box_version = "201708.22.0" 67 | guest.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".git/" 68 | guest.vm.provision :shell, inline: "pkg install -y openjdk; echo 'fdesc /dev/fd fdescfs rw 0 0' >> /etc/fstab; echo 'proc /proc procfs rw 0 0' >> /etc/fstab; mount /dev/fd; mount /proc" 69 | # unit tests required passing along env vars in ssh commands 70 | guest.vm.provision :shell, inline: "echo 'AcceptEnv *' >> /etc/ssh/sshd_config" 71 | guest.vm.provision :shell, inline: "service sshd restart" 72 | end 73 | 74 | config.vm.define "openbsd60", autostart: false do |guest| 75 | guest.vm.box = "ryanmaclean/openbsd-6.0" 76 | guest.vm.provider "virtualbox" do |vb| 77 | vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 78 | end 79 | guest.ssh.sudo_command = "doas su -" 80 | guest.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__rsync_path: "doas rsync", rsync__exclude: ".git/" 81 | guest.vm.provision :shell, inline: "PKG_PATH=\"http://ftp.openbsd.org/pub/OpenBSD/`uname -r`/packages/`arch -s`/\" pkg_add -I wget--" 82 | guest.vm.provision :shell, inline: "cd /tmp; wget \"http://ftp.openbsd.org/pub/OpenBSD/`uname -r`/`arch -s`/xbase58.tgz\"; cd /; tar xzvphf /tmp/xbase58.tgz" 83 | guest.vm.provision :shell, inline: "PKG_PATH=\"http://ftp.openbsd.org/pub/OpenBSD/`uname -r`/packages/`arch -s`/\" pkg_add -I jdk-1.7.0.80p0v0" 84 | end 85 | 86 | config.vm.define "osx1010", autostart: false do |guest| 87 | guest.vm.box = "jhcook/osx-yosemite-10.10" 88 | guest.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".git/" 89 | end 90 | 91 | end -------------------------------------------------------------------------------- /blaze.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/blaze.jar -------------------------------------------------------------------------------- /buildx-results.txt: -------------------------------------------------------------------------------- 1 | Buildx Results 2 | -------------- 3 | Cross platform tests use the Buildx project: https://github.com/fizzed/buildx 4 | Commit: aa2d1b30848ab59157d0113644d6dacf4345ff14 5 | Date: 2025-01-20T18:58:28.564812Z[UTC] 6 | 7 | linux-x64 success 8 | linux-arm64 success 9 | linux-riscv64 success 10 | linux_musl-x64 success 11 | macos-x64 success 12 | macos-arm64 success 13 | windows-x64 success 14 | windows-arm64 success 15 | freebsd-x64 success 16 | openbsd-x64 success 17 | 18 | -------------------------------------------------------------------------------- /docs/CANONICAL_LAYOUT.md: -------------------------------------------------------------------------------- 1 | Stork by Fizzed 2 | ======================================= 3 | 4 | ## Canonical java application layout 5 | 6 | All of Stork's tools need to know where to look for various files in order to 7 | function in a standard way. Stork uses the following conventional app layout: 8 | 9 | / ( 10 | bin/ (launcher scripts, overwrite on upgrade) 11 | lib/ (all jars, overwrite on upgrade, fat jars not recommended) 12 | share/ (arch indep data for install/running/info; overwrite on upgrade) 13 | conf/ (config files; retain on upgrade) 14 | data/ (not included in assembly/install; retain on upgrade) 15 | log/ (not included in assembly/install; retain on upgrade) 16 | run/ (not included in assembly/install; retain on upgrade) 17 | 18 | ### bin/ (executables) 19 | 20 | For all read-only executables. These are the binaries the user will execute to 21 | run your console application or start/stop your daemon. The executables should 22 | look and feel like a native application. 23 | 24 | Examples include batch files or shell scripts to start your Java app. Assume 25 | file permissions of 0775. 26 | 27 | ### lib/ (libraries) 28 | 29 | All shared files and libraries required for running the application(s). 30 | 31 | Examples include jar files containing compiled Java classes. Assume file permissions 32 | of 0664. 33 | 34 | ### conf/ (configuration data) 35 | 36 | All configuration files for the application(s). Any files in this directory 37 | need to be carefully examined during an upgrade -- since the user may have 38 | edited the config for their specific system. Assume file permissions of 0664. 39 | 40 | ### share/ (architecture-independent data) 41 | 42 | For all read-only architecture independent data files. 43 | 44 | Examples would include sql scripts to setup databases; linux/unix init.d scripts, or 45 | documentation. Assume this data will be overwritten on application upgrades. 46 | Assume file permissions of 0664. 47 | 48 | ### data/ (variable state information) 49 | 50 | State information is data that programs modify while they run, and that pertains 51 | to one specific host. State information remains valid after a reboot, should 52 | not be logging output, and should not be spooled data. 53 | 54 | Files in this directory should be retained between upgrades. 55 | 56 | Examples would include an application's database. On Linux/UNIX, this could/may be 57 | symlinked to /var/data/. Assume file permissions of 0644. 58 | 59 | ### log/ (logfiles) 60 | 61 | Logfiles for application (startup, runtime, etc.). It must be acceptable to 62 | truncate or delete files in this directory w/o affecting the application on 63 | its next invocation. 64 | 65 | Files in this directory may be retained between upgrades, but assume they will 66 | be deleted. On Linux/UNIX, this could be symlinked to /var/log/. 67 | 68 | ### run/ (run-time variable data) 69 | 70 | This directory contains system information data describing the system since it 71 | was booted. Files under this directory may/will be cleared (removed or truncated 72 | as appropriate) at the beginning of the boot process. On some versions of linux, 73 | /var/run is mounted as a temporary file system. 74 | 75 | Examples would include an application's process id (pid) file or named sockets. 76 | On Linux/UNIX, this could be symlinked to /var/run/. 77 | -------------------------------------------------------------------------------- /docs/DEV.md: -------------------------------------------------------------------------------- 1 | Stork by Fizzed 2 | =============== 3 | 4 | ## Overview 5 | 6 | Stork heavily interacts with various operating systems. While many unit tests 7 | are designed to run locally (and not in a virtual machine), to truly do development 8 | with Stork you'll want to verify what you changed works across a number of 9 | operating systems. 10 | 11 | ## Vagrant 12 | 13 | Make sure you have at least Vagrant v1.9.8 installed as well as the extension pack. 14 | You can verify your version by running: 15 | 16 | vagrant -v 17 | 18 | Vagrant is used to help setup virtual machines running various operating systems 19 | so we can run unit tests against them. The unit tests are designed to detect what's 20 | virtual machines are running and then run tests against them -- so you only need to 21 | spin up what you'd like to test against. Let's run thru an "ubuntu14" example: 22 | 23 | To spin up an Ubuntu 14.04 virtual machine: 24 | 25 | vagrant up ubuntu14 26 | 27 | ## Running Unit Tests 28 | 29 | To run all unit tests against a specific virtual machine: 30 | 31 | mvn test -Dhost=ubuntu14 32 | 33 | To test only the stork-launcher module on that host: 34 | 35 | mvn -am -pl stork-launcher test -DfailIfNoTests=false -Dtest=com.fizzed.stork.launcher.*Test -Dhost=ubuntu14 36 | 37 | To test only the stork-deploy module on that host: 38 | 39 | mvn -am -pl stork-deploy test -DfailIfNoTests=false -Dtest=com.fizzed.stork.deploy.*Test -Dhost=ubuntu14 40 | 41 | To run your tests locally, just use the host of `local`: 42 | 43 | mvn test -Dhost=local 44 | 45 | ## Testing for Windows on Linux/Mac 46 | 47 | To run tests against Windows (if on Linux or OSX): 48 | 49 | vagrant up windows10 50 | 51 | Be patient as the image is ~6GB to download. Once ready, you'll need to make 52 | sure Java 8 is on it. We didn't have time to make the vagrant install do all 53 | the prep, so there's a couple manual steps. Open up VirtualBox, double click 54 | the vm, then open powershell: 55 | 56 | choco install -y jdk8 57 | 58 | Then you can run any of the tests above against the host `windows10`: 59 | 60 | mvn test -Dhost=windows10 61 | 62 | NOTE: its incredibly important your windows scripts have correct line endings or 63 | the Windows cmd.exe interpreter will give you strange results. 64 | 65 | unix2dos stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/* -------------------------------------------------------------------------------- /setup/jsl.0.99x.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/setup/jsl.0.99x.zip -------------------------------------------------------------------------------- /stork-assembly/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.fizzed 5 | stork-assembly 6 | jar 7 | stork-assembly 8 | 9 | 10 | com.fizzed 11 | stork 12 | 3.2.1-SNAPSHOT 13 | 14 | 15 | 16 | 17 | 18 | org.slf4j 19 | slf4j-api 20 | 21 | 22 | 23 | com.fizzed 24 | stork-launcher 25 | 26 | 27 | 28 | org.apache.commons 29 | commons-compress 30 | 31 | 32 | 33 | 34 | org.hamcrest 35 | java-hamcrest 36 | test 37 | 38 | 39 | 40 | junit 41 | junit 42 | test 43 | 44 | 45 | 46 | org.mockito 47 | mockito-core 48 | test 49 | 50 | 51 | 52 | ch.qos.logback 53 | logback-classic 54 | test 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /stork-assembly/src/main/java/com/fizzed/stork/assembly/AssemblyMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.fizzed.stork.assembly; 18 | 19 | import java.io.File; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | public class AssemblyMain { 24 | private static final Logger logger = LoggerFactory.getLogger(AssemblyMain.class); 25 | 26 | static public void main(String[] args) throws Exception { 27 | if (args.length != 3) { 28 | System.err.println("Expected 3 arguments"); 29 | System.exit(1); 30 | } 31 | 32 | File outputDir = new File(args[0]); 33 | File inputDir = new File(args[1]); 34 | String name = args[2]; 35 | 36 | File tgzFile = AssemblyUtils.createTGZ(outputDir, inputDir, name); 37 | logger.info("Created {}", tgzFile); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /stork-assembly/src/main/java/com/fizzed/stork/assembly/AssemblyUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 mfizz. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.fizzed.stork.assembly; 18 | 19 | import java.io.BufferedOutputStream; 20 | import java.io.File; 21 | import java.io.FileFilter; 22 | import java.io.FileInputStream; 23 | import java.io.FileOutputStream; 24 | import java.io.IOException; 25 | import java.util.zip.GZIPOutputStream; 26 | import org.apache.commons.compress.archivers.tar.TarArchiveEntry; 27 | import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; 28 | import org.apache.commons.io.FileUtils; 29 | import org.apache.commons.io.IOUtils; 30 | import org.slf4j.Logger; 31 | import org.slf4j.LoggerFactory; 32 | 33 | public class AssemblyUtils { 34 | private static final Logger logger = LoggerFactory.getLogger(AssemblyUtils.class); 35 | 36 | static public void copyStandardProjectResources(File projectDir, File outputDir) throws IOException { 37 | FileUtils.copyDirectory(projectDir, outputDir, new FileFilter() { 38 | @Override 39 | public boolean accept(File pathname) { 40 | String name = pathname.getName().toLowerCase(); 41 | if (name.startsWith("readme") || name.startsWith("changelog") || name.startsWith("release") || name.startsWith("license")) { 42 | return true; 43 | } else { 44 | return false; 45 | } 46 | } 47 | }); 48 | } 49 | 50 | /** 51 | * Create .tar.gz archive file "name.tar.gz" with the contents of inputDir 52 | * using the prefix of "/name" 53 | * @param outputDir 54 | * @param inputDir 55 | * @param name 56 | * @return 57 | * @throws IOException 58 | */ 59 | static public File createTGZ(File outputDir, File inputDir, String name) throws IOException { 60 | // create tarball 61 | File tgzFile = new File(outputDir, name + ".tar.gz"); 62 | try (TarArchiveOutputStream tgzout = AssemblyUtils.createTGZStream(tgzFile)) { 63 | addFileToTGZStream(tgzout, inputDir, name, false); 64 | } 65 | return tgzFile; 66 | } 67 | 68 | static public TarArchiveOutputStream createTGZStream(File tgzFile) throws IOException { 69 | TarArchiveOutputStream tgzout = new TarArchiveOutputStream( 70 | new GZIPOutputStream( 71 | new BufferedOutputStream(new FileOutputStream(tgzFile)))); 72 | tgzout.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR); 73 | tgzout.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); 74 | return tgzout; 75 | } 76 | 77 | static public void addFileToTGZStream(TarArchiveOutputStream tgzout, File f, String base, boolean appendName) throws IOException { 78 | //File f = new File(path); 79 | String entryName = base; 80 | if (appendName) { 81 | if (!entryName.equals("")) { 82 | if (!entryName.endsWith("/")) { 83 | entryName += "/" + f.getName(); 84 | } else { 85 | entryName += f.getName(); 86 | } 87 | } else { 88 | entryName += f.getName(); 89 | } 90 | } 91 | TarArchiveEntry tarEntry = new TarArchiveEntry(f, entryName); 92 | 93 | if (f.isFile()) { 94 | if (f.canExecute()) { 95 | // -rwxr-xr-x 96 | tarEntry.setMode(493); 97 | } else { 98 | // keep default mode 99 | } 100 | } 101 | 102 | tgzout.putArchiveEntry(tarEntry); 103 | 104 | if (f.isFile()) { 105 | try (FileInputStream in = new FileInputStream(f)) { 106 | IOUtils.copy(in, tgzout); 107 | } 108 | tgzout.closeArchiveEntry(); 109 | } else { 110 | tgzout.closeArchiveEntry(); 111 | File[] children = f.listFiles(); 112 | if (children != null){ 113 | for (File child : children) { 114 | logger.info(" adding: " + entryName + "/" + child.getName()); 115 | addFileToTGZStream(tgzout, child, entryName + "/", true); 116 | } 117 | } 118 | } 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /stork-assembly/src/main/java/com/fizzed/stork/assembly/CopyFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.fizzed.stork.assembly; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import org.apache.commons.io.FileUtils; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | /** 28 | * Utility for copy files/dirs while retaining execute permissions. 29 | */ 30 | public class CopyFile { 31 | private static final Logger logger = LoggerFactory.getLogger(CopyFile.class); 32 | 33 | static public void main(String[] args) throws Exception { 34 | new CopyFile().run(args); 35 | } 36 | 37 | public void run(String[] args) { 38 | if (args.length < 2) { 39 | System.err.println("At least two arguments required"); 40 | System.exit(1); 41 | } 42 | 43 | File outputDir = new File(args[0]); 44 | 45 | List inputFiles = new ArrayList<>(); 46 | 47 | for (int i = 1; i < args.length; i++) { 48 | inputFiles.add(new File(args[i])); 49 | } 50 | 51 | if (inputFiles.isEmpty()) { 52 | logger.error("No input file(s)/dir(s)"); 53 | System.exit(1); 54 | } 55 | 56 | for (File inputFile : inputFiles) { 57 | try { 58 | if (inputFile.isDirectory()) { 59 | File[] files = inputFile.listFiles(); 60 | for (File f : files) { 61 | copyFile(f, outputDir); 62 | } 63 | } else { 64 | copyFile(inputFile, outputDir); 65 | } 66 | } catch (Exception e) { 67 | logger.error("", e); 68 | System.exit(1); 69 | } 70 | } 71 | } 72 | 73 | public void copyFile(File inputFile, File outputDir) throws IOException { 74 | if (inputFile.isDirectory()) { 75 | File[] files = inputFile.listFiles(); 76 | File newOutputDir = new File(outputDir, inputFile.getName()); 77 | for (File f : files) { 78 | copyFile(f, newOutputDir); 79 | } 80 | } else { 81 | File outputFile = new File(outputDir, inputFile.getName()); 82 | outputDir.mkdirs(); 83 | logger.info(" copying " + inputFile + " to " + outputFile); 84 | FileUtils.copyFile(inputFile, outputFile); 85 | if (inputFile.canExecute()) { 86 | outputFile.setExecutable(true); 87 | } 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /stork-bom/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | stork-bom 5 | stork-bom 6 | pom 7 | 8 | 9 | com.fizzed 10 | stork 11 | 3.2.1-SNAPSHOT 12 | 13 | 14 | 15 | 16 | 17 | com.fizzed 18 | stork-core 19 | ${project.version} 20 | 21 | 22 | 23 | com.fizzed 24 | stork-launcher 25 | ${project.version} 26 | 27 | 28 | 29 | com.fizzed 30 | stork-maven-plugin 31 | ${project.version} 32 | 33 | 34 | 35 | com.fizzed 36 | stork-assembly 37 | ${project.version} 38 | 39 | 40 | 41 | com.fizzed 42 | stork-deploy 43 | ${project.version} 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /stork-cli/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.fizzed 5 | stork-cli 6 | jar 7 | stork-cli 8 | 9 | 10 | com.fizzed 11 | stork 12 | 3.2.1-SNAPSHOT 13 | 14 | 15 | 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | com.fizzed 24 | stork-maven-plugin 25 | ${project.version} 26 | 27 | 28 | stork-launcher 29 | package 30 | 31 | launcher 32 | 33 | 34 | 35 | stork-assembly 36 | package 37 | 38 | assembly 39 | 40 | 41 | stork-${project.version} 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | com.fizzed 53 | stork-launcher 54 | 55 | 56 | 57 | com.fizzed 58 | stork-deploy 59 | 60 | 61 | 62 | 63 | com.fizzed 64 | blaze-core 65 | runtime 66 | 67 | 68 | org.apache.ivy 69 | ivy 70 | 71 | 72 | 73 | 74 | 75 | com.fizzed 76 | blaze-ssh 77 | runtime 78 | 79 | 80 | 81 | com.fizzed 82 | blaze-vagrant 83 | runtime 84 | 85 | 86 | 87 | 88 | ch.qos.logback 89 | logback-classic 90 | runtime 91 | 92 | 93 | -------------------------------------------------------------------------------- /stork-cli/src/main/launchers/stork-deploy.yml: -------------------------------------------------------------------------------- 1 | name: "stork-deploy" 2 | domain: "com.fizzed.stork" 3 | display_name: "Stork Deploy by Fizzed" 4 | short_description: "Utility for deploying stork assemblies" 5 | type: CONSOLE 6 | main_class: "com.fizzed.stork.deploy.DeployMain" 7 | platforms: [ WINDOWS, LINUX ] 8 | working_dir_mode: RETAIN 9 | min_java_version: "1.8" 10 | symlink_java: false -------------------------------------------------------------------------------- /stork-cli/src/main/launchers/stork-launcher.yml: -------------------------------------------------------------------------------- 1 | name: "stork-launcher" 2 | domain: "com.fizzed.stork" 3 | display_name: "Stork Launcher Generator by Fizzed" 4 | short_description: "Utility for creating scripts to launch Java apps" 5 | type: CONSOLE 6 | main_class: "com.fizzed.stork.launcher.LauncherMain" 7 | platforms: [ WINDOWS, LINUX ] 8 | working_dir_mode: RETAIN 9 | min_java_version: "1.6" 10 | symlink_java: false -------------------------------------------------------------------------------- /stork-cli/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | [%level] %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /stork-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.fizzed 5 | stork-core 6 | jar 7 | stork-core 8 | 9 | 10 | com.fizzed 11 | stork 12 | 3.2.1-SNAPSHOT 13 | 14 | 15 | 16 | com.fizzed.stork.core 17 | 18 | 19 | 20 | 21 | 22 | org.slf4j 23 | slf4j-api 24 | 25 | 26 | 27 | 28 | org.hamcrest 29 | java-hamcrest 30 | test 31 | 32 | 33 | 34 | junit 35 | junit 36 | test 37 | 38 | 39 | 40 | org.mockito 41 | mockito-core 42 | test 43 | 44 | 45 | 46 | ch.qos.logback 47 | logback-classic 48 | test 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /stork-core/src/main/java/com/fizzed/stork/core/ArgumentException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.fizzed.stork.core; 18 | 19 | public class ArgumentException extends Exception { 20 | 21 | /** 22 | * Creates a new instance of ArgumentException without detail 23 | * message. 24 | */ 25 | public ArgumentException() { 26 | } 27 | 28 | /** 29 | * Constructs an instance of ArgumentException with the 30 | * specified detail message. 31 | * 32 | * @param msg the detail message. 33 | */ 34 | public ArgumentException(String msg) { 35 | super(msg); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /stork-core/src/main/java/com/fizzed/stork/core/BaseApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.core; 17 | 18 | import java.util.ArrayDeque; 19 | import java.util.Arrays; 20 | import java.util.Deque; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | public abstract class BaseApplication { 25 | 26 | public abstract void printUsage(); 27 | 28 | public Logger getLogger() { 29 | return LoggerFactory.getLogger(this.getClass()); 30 | } 31 | 32 | public void logWelcomeMessage() { 33 | Logger log = getLogger(); 34 | log.info(" __ __ "); 35 | log.info(" _______/ |_ ___________| | __"); 36 | log.info(" / ___/\\ __\\/ _ \\_ __ \\ |/ /"); 37 | log.info(" \\___ \\ | | ( <_> ) | \\/ < "); 38 | log.info("/____ > |__| \\____/|__| |__|_ \\"); 39 | log.info(" \\/ \\/"); 40 | log.info(" v" + Version.getVersion()); 41 | log.info(""); 42 | } 43 | 44 | public void printError(String errorMessage) { 45 | System.err.println("Error: " + errorMessage); 46 | } 47 | 48 | public void printUsageAndExitWithError() { 49 | printUsage(); 50 | System.exit(1); 51 | } 52 | 53 | public void printErrorThenHelpHintAndExit(String errorMessage) { 54 | printError(errorMessage); 55 | System.out.println("Try with -h argument for usage info"); 56 | System.exit(1); 57 | } 58 | 59 | public String nextArg(String arg, Deque args) { 60 | if (args.isEmpty()) { 61 | printErrorThenHelpHintAndExit("argument '" + arg + "' requires a value as the next argument"); 62 | } 63 | return args.remove(); 64 | } 65 | 66 | final public void run(String[] args) { 67 | run(new ArrayDeque<>(Arrays.asList(args))); 68 | } 69 | 70 | public abstract void run(Deque args); 71 | 72 | } 73 | -------------------------------------------------------------------------------- /stork-demo/stork-demo-dropwizard/README.md: -------------------------------------------------------------------------------- 1 | Stork by Fizzed 2 | ======================================= 3 | 4 | ## Overview 5 | 6 | Stork example project demonstrating the following: 7 | 8 | - Maven build system using Stork Maven plugin to create launchers and assembly 9 | during package phase. 10 | - DropWizard-based HTTP server 11 | -------------------------------------------------------------------------------- /stork-demo/stork-demo-dropwizard/conf/hello.yml: -------------------------------------------------------------------------------- 1 | server: 2 | 3 | applicationConnectors: 4 | - type: http 5 | port: 8080 6 | 7 | adminConnectors: 8 | - type: http 9 | port: 8081 10 | -------------------------------------------------------------------------------- /stork-demo/stork-demo-dropwizard/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.fizzed 5 | stork-demo-dropwizard 6 | jar 7 | stork-demo-dropwizard 8 | 9 | 10 | com.fizzed 11 | stork 12 | 3.2.1-SNAPSHOT 13 | ../../pom.xml 14 | 15 | 16 | 17 | true 18 | com.fizzed.stork.demo.dropwizard 19 | 0.7.1 20 | 2.3.3 21 | true 22 | 23 | 24 | 25 | 26 | 27 | 28 | com.fizzed 29 | stork-maven-plugin 30 | ${project.version} 31 | 32 | 33 | stork-launcher 34 | package 35 | 36 | launcher 37 | 38 | 39 | 40 | stork-assembly 41 | package 42 | 43 | assembly 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | io.dropwizard 55 | dropwizard-core 56 | ${dropwizard.version} 57 | 58 | 59 | io.dropwizard 60 | dropwizard-views-freemarker 61 | ${dropwizard.version} 62 | 63 | 64 | io.dropwizard 65 | dropwizard-assets 66 | ${dropwizard.version} 67 | 68 | 69 | ch.qos.logback 70 | logback-classic 71 | runtime 72 | 73 | 74 | 75 | 76 | jakarta.xml.bind 77 | jakarta.xml.bind-api 78 | 2.3.2 79 | 80 | 81 | 82 | 83 | org.glassfish.jaxb 84 | jaxb-runtime 85 | 2.3.2 86 | 87 | 88 | 89 | 90 | junit 91 | junit 92 | test 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /stork-demo/stork-demo-dropwizard/src/main/java/com/fizzed/stork/demo/dropwizard/HelloApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 mfizz. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.demo.dropwizard; 17 | 18 | import io.dropwizard.Application; 19 | import io.dropwizard.setup.Bootstrap; 20 | import io.dropwizard.setup.Environment; 21 | import io.dropwizard.views.ViewBundle; 22 | 23 | public class HelloApplication extends Application { 24 | public static void main(String[] args) throws Exception { 25 | new HelloApplication().run(args); 26 | } 27 | 28 | @Override 29 | public String getName() { 30 | return "hello-dropwizard"; 31 | } 32 | 33 | @Override 34 | public void initialize(Bootstrap bootstrap) { 35 | bootstrap.addBundle(new ViewBundle()); 36 | } 37 | 38 | @Override 39 | public void run(HelloConfiguration configuration, Environment environment) throws ClassNotFoundException { 40 | environment.jersey().register(new HelloResource()); 41 | } 42 | } -------------------------------------------------------------------------------- /stork-demo/stork-demo-dropwizard/src/main/java/com/fizzed/stork/demo/dropwizard/HelloConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 mfizz. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.demo.dropwizard; 17 | 18 | import io.dropwizard.Configuration; 19 | 20 | public class HelloConfiguration extends Configuration { 21 | 22 | // nothing 23 | 24 | } 25 | -------------------------------------------------------------------------------- /stork-demo/stork-demo-dropwizard/src/main/java/com/fizzed/stork/demo/dropwizard/HelloResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 mfizz. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.demo.dropwizard; 17 | 18 | import com.codahale.metrics.annotation.Timed; 19 | import com.google.common.base.Optional; 20 | import io.dropwizard.jersey.caching.CacheControl; 21 | import java.util.Date; 22 | 23 | import javax.ws.rs.*; 24 | import javax.ws.rs.core.MediaType; 25 | import java.util.concurrent.TimeUnit; 26 | import javax.ws.rs.core.Response; 27 | 28 | @Path("/") 29 | @Produces(MediaType.TEXT_HTML) 30 | public class HelloResource { 31 | 32 | static Date startedAt = new Date(); 33 | 34 | public HelloResource() { 35 | // do nothing 36 | } 37 | 38 | @GET 39 | @Timed 40 | @CacheControl(maxAge = 1, maxAgeUnit = TimeUnit.DAYS) 41 | public Response index(@QueryParam("name") Optional name) { 42 | return Response.ok(createBody()).build(); 43 | 44 | } 45 | 46 | static String[] sysprops = { "user.dir","user.name","user.home","launcher.name","launcher.type","launcher.action","launcher.app.dir","java.class.path","java.home","java.version","java.vendor","os.arch","os.name","os.version" }; 47 | 48 | static public String createBody() { 49 | StringBuilder sb = new StringBuilder(); 50 | sb.append(""); 51 | sb.append("Hello Server using DropWizard!"); 52 | sb.append(""); 53 | sb.append("

Stork by Fizzed

"); 54 | sb.append("

Example using DropWizard

"); 55 | // Version.java auto created by Fizzed parent POM file (I use this in all my projects) 56 | sb.append("Version: ").append(com.fizzed.stork.demo.dropwizard.Version.getLongVersion()).append("
"); 57 | sb.append("Now: ").append(new Date()).append("
"); 58 | sb.append("Started: ").append(startedAt).append("
"); 59 | sb.append("Some system properties:
"); 60 | for (String sysprop : sysprops) { 61 | sb.append(" - ").append(sysprop).append(": ").append(System.getProperty(sysprop)).append("
"); 62 | } 63 | sb.append(""); 64 | sb.append(""); 65 | return sb.toString(); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /stork-demo/stork-demo-dropwizard/src/main/launchers/stork-demo-dropwizard.yml: -------------------------------------------------------------------------------- 1 | 2 | # Name of application (make sure it has no spaces) 3 | name: "stork-demo-dropwizard" 4 | 5 | # Domain of application (e.g. com.example) 6 | domain: "com.fizzed.stork.demo" 7 | 8 | # Display name of application (can have spaces) 9 | # Usually also the application directory for Windows/Mac OSX (e.g. Program Files\Hello Server) 10 | display_name: "Stork dropwizard demo" 11 | 12 | short_description: "Stork dropwizard demo" 13 | 14 | # Type of launcher (CONSOLE or DAEMON) 15 | type: DAEMON 16 | 17 | # Java class to run 18 | main_class: "com.fizzed.stork.demo.dropwizard.HelloApplication" 19 | 20 | # Platform launchers to generate (WINDOWS, LINUX, MAC_OSX) 21 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 22 | 23 | # Include a share/helper/java-detect script (troubleshoot JVM searching, or 24 | # use within an installer / deployer) 25 | include_java_detect_helper: true 26 | 27 | # Working directory for app 28 | # RETAIN will not change the working directory 29 | # APP_HOME will change the workding directory to the home of the app 30 | #working_dir_mode: APP_HOME 31 | 32 | # Arguments for application (as though user typed them on command-line) 33 | # These will be added immediately after the main class part of java command 34 | app_args: "server conf/hello.yml" 35 | 36 | # Arguments to use with the java command (e.g. way to pass -D arguments) 37 | # "-Xrs" is good to include with daemons 38 | java_args: "-Xrs" 39 | 40 | # minimum version of java required (system will be searched for acceptable jvm) 41 | min_java_version: "1.7" 42 | 43 | # min/max fixed memory (measured in MB) 44 | #min_java_memory: 256 45 | #max_java_memory: 1024 46 | 47 | # min/max memory by percentage of system 48 | #min_java_memory_pct: 10 49 | #max_java_memory_pct: 80 50 | 51 | platform_configurations: 52 | LINUX: 53 | daemon_method: NOHUP 54 | user: "daemon" 55 | group: "daemon" 56 | 57 | MAC_OSX: 58 | user: "_daemon" 59 | group: "_daemon" 60 | 61 | WINDOWS: 62 | daemon_method: JSLWIN 63 | 64 | symlink_java: true 65 | 66 | #run_dir: /var/run -------------------------------------------------------------------------------- /stork-demo/stork-demo-hellod/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Fizzed, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM openjdk:8-jre 15 | COPY target/stork /opt/demo-hellod 16 | # --run will allow you to still CTRL-C vs. --exec 17 | CMD ["/opt/demo-hellod/bin/stork-demo-hellod", "--run"] -------------------------------------------------------------------------------- /stork-demo/stork-demo-hellod/README.md: -------------------------------------------------------------------------------- 1 | Stork by Fizzed 2 | =============== 3 | 4 | Example of a DAEMON/SERVICE Java app. 5 | 6 | Uses the stork maven plugin to generate launchers from [src/main/launchers](src/main/launchers) 7 | and then package the app into an assembly. 8 | -------------------------------------------------------------------------------- /stork-demo/stork-demo-hellod/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.fizzed 5 | stork-demo-hellod 6 | jar 7 | stork-demo-hellod 8 | 9 | 10 | com.fizzed 11 | stork 12 | 3.2.1-SNAPSHOT 13 | ../../pom.xml 14 | 15 | 16 | 17 | com.fizzed.stork.demo.hellod 18 | true 19 | 20 | 21 | 22 | 23 | 24 | 25 | com.fizzed 26 | stork-maven-plugin 27 | ${project.version} 28 | 29 | 30 | stork-launcher 31 | package 32 | 33 | launcher 34 | 35 | 36 | 37 | stork-assembly 38 | package 39 | 40 | assembly 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | io.netty 52 | netty-codec-http 53 | 4.0.23.Final 54 | 55 | 56 | 57 | 58 | ch.qos.logback 59 | logback-classic 60 | runtime 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /stork-demo/stork-demo-hellod/src/main/launchers/stork-demo-hellod.yml: -------------------------------------------------------------------------------- 1 | 2 | # Name of application (make sure it has no spaces) 3 | name: "stork-demo-hellod" 4 | 5 | # Domain of application (e.g. com.example) 6 | domain: "com.fizzed.stork.demo" 7 | 8 | # Display name of application (can have spaces) 9 | # Usually also the application directory for Windows/Mac OSX (e.g. Program Files\Hello Server) 10 | display_name: "Stork Hello Server" 11 | 12 | short_description: "Stork Hello Server" 13 | 14 | # Type of launcher (CONSOLE or DAEMON) 15 | type: DAEMON 16 | 17 | # Java class to run 18 | main_class: "com.fizzed.stork.demo.hellod.Hellod" 19 | 20 | # Platform launchers to generate (WINDOWS, LINUX, MAC_OSX) 21 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 22 | 23 | # Working directory for app 24 | # RETAIN will not change the working directory 25 | # APP_HOME will change the workding directory to the home of the app 26 | #working_dir_mode: APP_HOME 27 | 28 | # Arguments for application (as though user typed them on command-line) 29 | # These will be added immediately after the main class part of java command 30 | #app_args: "-c config.yml" 31 | 32 | # Arguments to use with the java command (e.g. way to pass -D arguments) 33 | # "-Xrs" is good to include with daemons 34 | java_args: "-Xrs" 35 | 36 | # minimum version of java required (system will be searched for acceptable jvm) 37 | min_java_version: "1.6" 38 | 39 | # min/max fixed memory (measured in MB) 40 | #min_java_memory: 30 41 | #max_java_memory: 256 42 | 43 | # min/max memory by percentage of system 44 | #min_java_memory_pct: 10 45 | #max_java_memory_pct: 80 46 | 47 | platform_configurations: 48 | LINUX: 49 | daemon_method: NOHUP 50 | user: "daemon" 51 | group: "daemon" 52 | 53 | MAC_OSX: 54 | user: "_daemon" 55 | group: "_daemon" 56 | 57 | WINDOWS: 58 | daemon_method: JSLWIN 59 | 60 | symlink_java: true 61 | 62 | #run_dir: /var/run -------------------------------------------------------------------------------- /stork-demo/stork-demo-hellod/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %-5level: %logger{36} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/Assemblys.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import com.fizzed.blaze.util.Globber; 19 | import java.io.Closeable; 20 | import java.io.IOException; 21 | import java.nio.file.Files; 22 | import java.nio.file.Path; 23 | import java.util.ArrayList; 24 | import java.util.Arrays; 25 | import java.util.List; 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | 29 | public class Assemblys { 30 | static private final Logger log = LoggerFactory.getLogger(Assemblys.class); 31 | 32 | static public Assembly process(Path archiveFile) throws IOException { 33 | Path tempDir = Files.createTempDirectory("stork-deploy."); 34 | CloseablePath closeablePath = new CloseablePath(tempDir); 35 | return process(archiveFile, tempDir, Arrays.asList(closeablePath)); 36 | } 37 | 38 | static public Assembly process(Path archiveFile, Path workDir, List resources) throws IOException { 39 | if (!Files.exists(archiveFile)) { 40 | throw new IOException("Archive file " + archiveFile + " does not exist"); 41 | } 42 | 43 | Archive archive = new Archive(archiveFile); 44 | 45 | Path unpackedDir = archive.unpack(workDir); 46 | 47 | String filename = unpackedDir.getFileName().toString(); 48 | 49 | boolean snapshot = false; 50 | if (filename.endsWith("-SNAPSHOT")) { 51 | snapshot = true; 52 | filename = filename.replace("-SNAPSHOT", ""); 53 | } 54 | 55 | // find version and strip it out 56 | int versionPos = filename.lastIndexOf("-"); 57 | if (versionPos < 0) { 58 | throw new IOException("Unable to parse version from " + filename); 59 | } 60 | 61 | String version = filename.substring(versionPos+1); 62 | String name = filename.substring(0, versionPos); 63 | 64 | // find all supported daemon init types 65 | List daemons = new ArrayList<>(); 66 | 67 | findSysvDaemons(unpackedDir, daemons); 68 | findSystemdDaemons(unpackedDir, daemons); 69 | 70 | return new Assembly(archive, unpackedDir, name, version, snapshot, daemons, resources); 71 | } 72 | 73 | static private void findSysvDaemons(Path unpackedDir, List daemons) throws IOException { 74 | Path dir = unpackedDir.resolve("share/init.d"); 75 | 76 | if (!Files.exists(dir)) { 77 | log.debug("{} dir not found (no sysv daemons?)", dir); 78 | return; 79 | } 80 | 81 | Globber.globber(dir, "*.init").filesOnly().stream().forEach((initFile) -> { 82 | log.debug("Detected sysv daemon {}", initFile); 83 | String name = initFile.getFileName().toString().replace(".init", ""); 84 | daemons.add(new Daemon(InitType.SYSV, name, null, null)); 85 | }); 86 | } 87 | 88 | static private void findSystemdDaemons(Path unpackedDir, List daemons) throws IOException { 89 | Path dir = unpackedDir.resolve("share/systemd"); 90 | 91 | if (!Files.exists(dir)) { 92 | log.debug("{} dir not found (no systemd daemons?)", dir); 93 | return; 94 | } 95 | 96 | Globber.globber(dir, "*.service").filesOnly().stream().forEach((serviceFile) -> { 97 | log.debug("Detected systemd daemon {}", serviceFile); 98 | String name = serviceFile.getFileName().toString().replace(".service", ""); 99 | daemons.add(new Daemon(InitType.SYSTEMD, name, null, null)); 100 | }); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/BasicFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.io.File; 19 | import java.nio.file.Path; 20 | 21 | public class BasicFile { 22 | 23 | private final Path path; 24 | private final long createdAt; 25 | private final int userId; 26 | private final int groupId; 27 | 28 | public BasicFile(Path path, long createdAt, int userId, int groupId) { 29 | this.path = path; 30 | this.createdAt = createdAt; 31 | this.userId = userId; 32 | this.groupId = groupId; 33 | } 34 | 35 | public Path getPath() { 36 | return path; 37 | } 38 | 39 | public long getCreatedAt() { 40 | return createdAt; 41 | } 42 | 43 | public int getUserId() { 44 | return userId; 45 | } 46 | 47 | public int getGroupId() { 48 | return groupId; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return path.toString(); 54 | } 55 | 56 | static public String pathToUnixString(Path path) { 57 | if (path == null) { 58 | return null; 59 | } 60 | String s = path.toString(); 61 | if (File.separatorChar == '\\') { 62 | s = s.replace('\\', '/'); 63 | } 64 | return s; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/CloseablePath.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.io.Closeable; 19 | import java.io.IOException; 20 | import java.nio.file.Path; 21 | 22 | public class CloseablePath implements Closeable { 23 | 24 | private final Path path; 25 | 26 | public CloseablePath(Path path) { 27 | this.path = path; 28 | } 29 | 30 | public Path getPath() { 31 | return path; 32 | } 33 | 34 | @Override 35 | public void close() throws IOException { 36 | DeployHelper.deleteRecursively(this.path); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/Daemon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.util.Objects; 19 | 20 | public class Daemon { 21 | 22 | private final InitType initType; 23 | private final String name; 24 | private final String user; 25 | private final String group; 26 | 27 | public Daemon(InitType initType, String name, String user, String group) { 28 | this.name = name; 29 | this.initType = initType; 30 | this.user = user; 31 | this.group = group; 32 | } 33 | 34 | public InitType getInitType() { 35 | return initType; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | public String getUser() { 43 | return user; 44 | } 45 | 46 | public String getGroup() { 47 | return group; 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | int hash = 3; 53 | hash = 37 * hash + Objects.hashCode(this.initType); 54 | hash = 37 * hash + Objects.hashCode(this.name); 55 | return hash; 56 | } 57 | 58 | @Override 59 | public boolean equals(Object obj) { 60 | if (this == obj) { 61 | return true; 62 | } 63 | if (obj == null) { 64 | return false; 65 | } 66 | if (getClass() != obj.getClass()) { 67 | return false; 68 | } 69 | final Daemon other = (Daemon) obj; 70 | if (!Objects.equals(this.name, other.name)) { 71 | return false; 72 | } 73 | if (this.initType != other.initType) { 74 | return false; 75 | } 76 | return true; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/DeployHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.io.IOException; 19 | import java.nio.file.FileVisitResult; 20 | import java.nio.file.Files; 21 | import java.nio.file.Path; 22 | import java.nio.file.SimpleFileVisitor; 23 | import java.nio.file.attribute.BasicFileAttributes; 24 | import java.time.Instant; 25 | import java.time.LocalDateTime; 26 | import java.time.ZoneOffset; 27 | import java.time.format.DateTimeFormatter; 28 | import java.util.Locale; 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | public class DeployHelper { 33 | private static final Logger log = LoggerFactory.getLogger(DeployHelper.class); 34 | 35 | static public void deleteRecursively(final Path path) throws IOException { 36 | if (!Files.exists(path)) { 37 | return; 38 | } 39 | 40 | log.info("Deleting local {}", path); 41 | 42 | Files.walkFileTree(path, new SimpleFileVisitor() { 43 | @Override 44 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 45 | //try { 46 | // if (!Files.isWritable(file)) { 47 | // log.error("File {} is not writable!!!", file); 48 | // } 49 | Files.deleteIfExists(file); 50 | //} catch (IOException e) { 51 | // log.error("Unable to delete {} wth attrs {}", file, attrs, e); 52 | //} 53 | return FileVisitResult.CONTINUE; 54 | } 55 | 56 | @Override 57 | public FileVisitResult postVisitDirectory(Path dir, IOException ioe) throws IOException { 58 | Files.deleteIfExists(dir); 59 | return FileVisitResult.CONTINUE; 60 | } 61 | 62 | @Override 63 | public FileVisitResult visitFileFailed(Path file, IOException ioe) throws IOException { 64 | return FileVisitResult.SKIP_SUBTREE; 65 | } 66 | }); 67 | 68 | Files.deleteIfExists(path); 69 | } 70 | 71 | static private final DateTimeFormatter versionDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss", Locale.US); 72 | 73 | static public String toVersionDateTime(long millis) { 74 | Instant instant = Instant.ofEpochMilli(millis); 75 | LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC); 76 | return ldt.format(versionDateTimeFormatter); 77 | } 78 | 79 | static public String toFriendlyDateTime(long millis) { 80 | Instant instant = Instant.ofEpochMilli(millis); 81 | LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC); 82 | return ldt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/DeployOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.io.IOException; 19 | import java.io.InputStream; 20 | import java.nio.file.Files; 21 | import java.nio.file.Path; 22 | import java.util.Properties; 23 | 24 | public class DeployOptions { 25 | 26 | private String prefixDir; 27 | private String organization; 28 | private String user; 29 | private String group; 30 | private Boolean unattended; 31 | private Integer retain; 32 | 33 | public DeployOptions() { 34 | // no defaults! 35 | } 36 | 37 | public String getPrefixDir() { 38 | return prefixDir; 39 | } 40 | 41 | public DeployOptions prefixDir(String prefixDir) { 42 | this.prefixDir = prefixDir; 43 | return this; 44 | } 45 | 46 | public String getOrganization() { 47 | return organization; 48 | } 49 | 50 | public DeployOptions organization(String organization) { 51 | this.organization = organization; 52 | return this; 53 | } 54 | 55 | public String getUser() { 56 | return user; 57 | } 58 | 59 | public DeployOptions user(String user) { 60 | this.user = user; 61 | return this; 62 | } 63 | 64 | public String getGroup() { 65 | return group; 66 | } 67 | 68 | public DeployOptions group(String group) { 69 | this.group = group; 70 | return this; 71 | } 72 | 73 | public Boolean getUnattended() { 74 | return unattended; 75 | } 76 | 77 | public DeployOptions unattended(Boolean unattended) { 78 | this.unattended = unattended; 79 | return this; 80 | } 81 | 82 | public boolean safeUnattended() { 83 | return this.unattended != null && this.unattended; 84 | } 85 | 86 | public Integer getRetain() { 87 | return retain; 88 | } 89 | 90 | public DeployOptions retain(Integer retain) { 91 | this.retain = retain; 92 | return this; 93 | } 94 | 95 | public void overlay(DeployOptions options) { 96 | if (options == null) { return; } 97 | if (options.prefixDir != null) { this.prefixDir = options.prefixDir; } 98 | if (options.organization != null) { this.organization = options.organization; } 99 | if (options.user != null) { this.user = options.user; } 100 | if (options.group != null) { this.group = options.group; } 101 | if (options.unattended != null) { this.unattended = options.unattended; } 102 | if (options.retain != null) { this.retain = options.retain; } 103 | } 104 | 105 | static public DeployOptions from(Path file) throws IOException { 106 | Properties properties = new Properties(); 107 | try (InputStream is = Files.newInputStream(file)) { 108 | properties.load(is); 109 | } 110 | return from(properties); 111 | } 112 | 113 | static public DeployOptions from(Properties properties) { 114 | DeployOptions options = new DeployOptions(); 115 | options.prefixDir = properties.getProperty("prefix.dir"); 116 | options.organization = properties.getProperty("organization"); 117 | options.user = properties.getProperty("user"); 118 | options.group = properties.getProperty("group"); 119 | String unattendedValue = properties.getProperty("unattended"); 120 | if (unattendedValue != null) { 121 | options.unattended = Boolean.valueOf(unattendedValue); 122 | } 123 | String retainValue = properties.getProperty("retain"); 124 | if (retainValue != null) { 125 | options.retain = Integer.valueOf(retainValue); 126 | } 127 | return options; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/DeployerException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | public class DeployerException extends Exception { 19 | 20 | public DeployerException(String msg) { 21 | super(msg); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/Deployment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.util.Optional; 19 | import java.util.UUID; 20 | 21 | public class Deployment { 22 | 23 | private final String uuid; 24 | private final String baseDir; 25 | private final String currentDir; 26 | private final String versionDir; 27 | private final Optional user; 28 | private final Optional group; 29 | 30 | public Deployment(String baseDir, String currentDir, String versionDir, String user, String group) { 31 | this.uuid = UUID.randomUUID().toString(); 32 | this.baseDir = baseDir; 33 | this.currentDir = currentDir; 34 | this.versionDir = versionDir; 35 | this.user = Optional.ofNullable(user); 36 | this.group = Optional.ofNullable(group); 37 | } 38 | 39 | public String getUuid() { 40 | return uuid; 41 | } 42 | 43 | public String getBaseDir() { 44 | return baseDir; 45 | } 46 | 47 | public String getCurrentDir() { 48 | return currentDir; 49 | } 50 | 51 | public String getVersionDir() { 52 | return versionDir; 53 | } 54 | 55 | public Optional getUser() { 56 | return user; 57 | } 58 | 59 | public Optional getGroup() { 60 | return group; 61 | } 62 | 63 | public Optional getOwner() { 64 | if (!this.user.isPresent()) { 65 | return Optional.empty(); 66 | } else { 67 | if (this.group.isPresent()) { 68 | return Optional.of(this.user.get() + ":" + this.group.get()); 69 | } else { 70 | return this.user; 71 | } 72 | } 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/DeploymentType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | public enum DeploymentType { 19 | 20 | FRESH, 21 | UPGRADE 22 | 23 | } 24 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/ExistingDeployment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.util.Optional; 19 | import java.util.SortedSet; 20 | 21 | public class ExistingDeployment extends Deployment { 22 | 23 | private final Long deployedAt; 24 | private final SortedSet versionDirs; 25 | private final Optional retain; 26 | 27 | public ExistingDeployment(String baseDir, String currentDir, String versionDir, String user, String group, Long deployedAt, SortedSet versionDirs, Optional retain) { 28 | super(baseDir, currentDir, versionDir, user, group); 29 | this.versionDirs = versionDirs; 30 | this.deployedAt = deployedAt; 31 | this.retain = retain; 32 | } 33 | 34 | public Long getDeployedAt() { 35 | return deployedAt; 36 | } 37 | 38 | public SortedSet getVersionDirs() { 39 | return versionDirs; 40 | } 41 | 42 | public boolean isFresh() { 43 | return getCurrentDir() == null; 44 | } 45 | 46 | public boolean isUpgrade() { 47 | return getCurrentDir() != null; 48 | } 49 | 50 | public Optional getRetain() { 51 | return retain; 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/InitType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | public enum InitType { 19 | 20 | UNKNOWN, 21 | SYSV, 22 | SYSTEMD, 23 | UPSTART 24 | 25 | } 26 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/SshTarget.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import com.fizzed.blaze.SecureShells; 19 | import com.fizzed.blaze.ssh.SshExec; 20 | import com.fizzed.blaze.ssh.SshSession; 21 | import java.util.ArrayDeque; 22 | import java.util.Arrays; 23 | import java.util.Deque; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import com.fizzed.blaze.ssh.SshSftpSession; 27 | import java.io.IOException; 28 | import java.util.Map; 29 | 30 | abstract public class SshTarget extends Target { 31 | static private final Logger log = LoggerFactory.getLogger(SshTarget.class); 32 | 33 | protected final SshSession ssh; 34 | protected final SshSftpSession sftp; 35 | protected final Map commands; 36 | 37 | public SshTarget(SshSession ssh, SshSftpSession sftp, String uname, InitType initType, String tempDir, Map commands) { 38 | super(ssh.uri(), uname, initType, tempDir); 39 | this.ssh = ssh; 40 | this.sftp = sftp; 41 | this.commands = commands; 42 | } 43 | 44 | public SshExec sshExec(boolean sudo, boolean shell, Object... args) { 45 | Deque arguments = new ArrayDeque<>(); 46 | 47 | if (sudo) { 48 | if (commands.containsKey("doas")) { 49 | arguments.add("doas"); 50 | } else { 51 | // man sudo 52 | // -S The -S (stdin) option causes sudo to read the password from the 53 | // standard input instead of the terminal device. 54 | arguments.add("sudo"); 55 | arguments.add("-S"); 56 | } 57 | } 58 | 59 | if (shell) { 60 | arguments.add("sh"); 61 | arguments.add("-c"); 62 | } 63 | 64 | arguments.addAll(Arrays.asList(args)); 65 | 66 | SshExec exec = SecureShells.sshExec(ssh); 67 | 68 | exec.command(arguments.pop().toString()); 69 | 70 | while (arguments.size() > 0) { 71 | exec.arg(arguments.pop()); 72 | } 73 | 74 | return exec; 75 | } 76 | 77 | @Override 78 | public void close() throws IOException { 79 | /** 80 | if (this.sftp != null) { 81 | this.sftp.close(); 82 | } 83 | */ 84 | if (this.ssh != null) { 85 | this.ssh.close(); 86 | } 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/SystemdHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.io.IOException; 19 | import java.io.UncheckedIOException; 20 | import java.nio.file.Files; 21 | import java.nio.file.Path; 22 | import java.nio.file.StandardOpenOption; 23 | import java.util.List; 24 | import java.util.Set; 25 | import java.util.stream.Collectors; 26 | import org.slf4j.Logger; 27 | 28 | public class SystemdHelper { 29 | static private int indexOfAny(String value, String[] finds) { 30 | for (String find : finds) { 31 | int pos = value.indexOf(find); 32 | if (pos >= 0) { return pos; } 33 | } 34 | return -1; 35 | } 36 | 37 | static public void modifyForInstall(Logger log, Assembly assembly, Deployment install) { 38 | Set daemons = assembly.getDaemons(InitType.SYSTEMD); 39 | 40 | if (daemons == null) { 41 | return; 42 | } 43 | 44 | for (Daemon daemon : daemons) { 45 | // systemd service files (unfortunately) cannot be scripted with paths 46 | // for ExecStart, User, Group, etc. so we need to modify those when 47 | // we finally install the .service file 48 | Path systemdServiceFile = assembly.getUnpackedDir().resolve("share/systemd/" + daemon.getName() + ".service"); 49 | try { 50 | List modifiedSystemdLines 51 | = Files.lines(systemdServiceFile) 52 | .map((line) -> { 53 | int equalsPos = line.indexOf("="); 54 | if (equalsPos > 0) { 55 | String key = line.substring(0, equalsPos); 56 | String value = line.substring(equalsPos+1).trim(); 57 | 58 | // does the value reference a /bin or /run? 59 | int dirPos = indexOfAny(line, new String[] { "/bin", "/run" }); 60 | 61 | if (dirPos > 0) { 62 | return line.substring(0, equalsPos+1) 63 | + install.getCurrentDir() 64 | + line.substring(dirPos); 65 | } else if (key.equalsIgnoreCase("user")) { 66 | return "User=" + install.getUser().orElse(""); 67 | } else if (key.equalsIgnoreCase("group")) { 68 | return "Group=" + install.getGroup().orElse(""); 69 | } 70 | } 71 | return line; 72 | }) 73 | .collect(Collectors.toList()); 74 | 75 | Files.write(systemdServiceFile, modifiedSystemdLines); 76 | // on windows this file is marked as read-only by default 77 | systemdServiceFile.toFile().setWritable(true, true); 78 | 79 | log.info("Modified for install: {}", systemdServiceFile); 80 | } catch (IOException e) { 81 | throw new UncheckedIOException(e); 82 | } 83 | } 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/Target.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import com.fizzed.blaze.util.ImmutableUri; 19 | import java.io.Closeable; 20 | import java.nio.file.Path; 21 | import java.util.List; 22 | 23 | abstract public class Target implements Closeable { 24 | 25 | private final ImmutableUri uri; 26 | private final String uname; 27 | private final InitType initType; 28 | private final String tempDir; 29 | 30 | public Target(ImmutableUri uri, String uname, InitType initType, String tempDir) { 31 | this.uri = uri; 32 | this.uname = uname; 33 | this.initType = initType; 34 | this.tempDir = tempDir; 35 | } 36 | 37 | public ImmutableUri getUri() { 38 | return uri; 39 | } 40 | 41 | public String getUname() { 42 | return uname; 43 | } 44 | 45 | public InitType getInitType() { 46 | return initType; 47 | } 48 | 49 | public String getTempDir() { 50 | return this.tempDir; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return this.uri.toString(); 56 | } 57 | 58 | abstract public boolean hasUser(String user); 59 | 60 | abstract public boolean hasGroup(String group); 61 | 62 | abstract public List listFiles(Object path); 63 | 64 | abstract public Path readlink(Object path); 65 | 66 | abstract public Path realpath(Object path); 67 | 68 | abstract public void createDirectories(boolean sudo, Object path); 69 | 70 | abstract public void remove(boolean sudo, Object... paths); 71 | 72 | abstract public void put(Path source, String target); 73 | 74 | abstract public void unpack(String path, String targetDir); 75 | 76 | abstract public void copyFiles(boolean sudo, String source, String target); 77 | 78 | abstract public void moveFiles(boolean sudo, String source, String target); 79 | 80 | abstract public void symlink(boolean sudo, String target, String link); 81 | 82 | abstract public void chown(boolean sudo, boolean recursive, String owner, String target); 83 | 84 | abstract public void chmod(boolean sudo, boolean recursive, String permissions, String target); 85 | 86 | abstract public void startDaemon(Daemon daemon) throws DeployerException; 87 | 88 | abstract public void stopDaemon(Daemon daemon) throws DeployerException; 89 | 90 | abstract public void installDaemon(Deployment install, Daemon daemon, boolean onBoot) throws DeployerException; 91 | 92 | } 93 | -------------------------------------------------------------------------------- /stork-deploy/src/main/java/com/fizzed/stork/deploy/VersionedPath.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.util.Objects; 19 | 20 | public class VersionedPath implements Comparable { 21 | 22 | private final long createdAt; 23 | private final String path; 24 | 25 | public VersionedPath(long createdAt, String path) { 26 | this.createdAt = createdAt; 27 | this.path = path; 28 | } 29 | 30 | public long getCreatedAt() { 31 | return createdAt; 32 | } 33 | 34 | public String getPath() { 35 | return path; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return this.path; 41 | } 42 | 43 | @Override 44 | public int hashCode() { 45 | int hash = 7; 46 | hash = 89 * hash + (int) (this.createdAt ^ (this.createdAt >>> 32)); 47 | hash = 89 * hash + Objects.hashCode(this.path); 48 | return hash; 49 | } 50 | 51 | @Override 52 | public boolean equals(Object obj) { 53 | if (this == obj) { 54 | return true; 55 | } 56 | if (obj == null) { 57 | return false; 58 | } 59 | if (getClass() != obj.getClass()) { 60 | return false; 61 | } 62 | final VersionedPath other = (VersionedPath) obj; 63 | if (this.createdAt != other.createdAt) { 64 | return false; 65 | } 66 | return Objects.equals(this.path, other.path); 67 | } 68 | 69 | @Override 70 | public int compareTo(VersionedPath o) { 71 | // descending order 72 | int c = (int)(o.createdAt - this.createdAt); 73 | if (c == 0) { 74 | return o.path.compareTo(this.path); 75 | } 76 | return c; 77 | } 78 | } -------------------------------------------------------------------------------- /stork-deploy/src/test/java/com/fizzed/stork/deploy/AssemblysTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.nio.file.Path; 19 | import java.util.Set; 20 | import static org.hamcrest.CoreMatchers.containsString; 21 | import static org.hamcrest.CoreMatchers.is; 22 | import static org.hamcrest.Matchers.contains; 23 | import static org.hamcrest.Matchers.hasSize; 24 | import static org.junit.Assert.assertThat; 25 | import static org.junit.Assert.fail; 26 | import org.junit.Test; 27 | 28 | public class AssemblysTest { 29 | 30 | @Test 31 | public void processConsoleAndDaemons() throws Exception { 32 | Path archiveFile = TestHelper.getResource("/fixtures/hello-world-1.2.4-SNAPSHOT.zip"); 33 | 34 | try (Assembly assembly = Assemblys.process(archiveFile)) { 35 | assertThat(assembly.getName(), is("hello-world")); 36 | assertThat(assembly.getVersion(), is("1.2.4")); 37 | assertThat(assembly.isSnapshot(), is(true)); 38 | assertThat(assembly.getArchiveFile(), is(archiveFile)); 39 | assertThat(assembly.getUnpackedDir().getFileName().toString(), is("hello-world-1.2.4-SNAPSHOT")); 40 | 41 | Set sysvDaemons = assembly.getDaemons(InitType.SYSV); 42 | 43 | assertThat(sysvDaemons, hasSize(1)); 44 | assertThat(sysvDaemons, contains(new Daemon(InitType.SYSV, "hello-daemon", null, null))); 45 | 46 | Set systemdDaemons = assembly.getDaemons(InitType.SYSTEMD); 47 | 48 | assertThat(systemdDaemons, hasSize(1)); 49 | assertThat(systemdDaemons, contains(new Daemon(InitType.SYSTEMD, "hello-daemon", null, null))); 50 | 51 | // this should succeed 52 | assembly.verify(); 53 | 54 | // remove a daemon type 55 | systemdDaemons.clear(); 56 | 57 | try { 58 | assembly.verify(); 59 | fail(); 60 | } catch (DeployerException e) { 61 | assertThat(e.getMessage(), containsString("Size mismatch")); 62 | } 63 | } 64 | } 65 | 66 | @Test 67 | public void processConsole() throws Exception { 68 | Path archiveFile = TestHelper.getResource("/fixtures/hello-console-1.2.4.tar.gz"); 69 | 70 | try (Assembly assembly = Assemblys.process(archiveFile)) { 71 | assertThat(assembly.getName(), is("hello-console")); 72 | assertThat(assembly.getVersion(), is("1.2.4")); 73 | assertThat(assembly.isSnapshot(), is(false)); 74 | assertThat(assembly.getArchiveFile(), is(archiveFile)); 75 | assertThat(assembly.getUnpackedDir().getFileName().toString(), is("hello-console-1.2.4")); 76 | assertThat(assembly.hasDaemons(), is(false)); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /stork-deploy/src/test/java/com/fizzed/stork/deploy/DeployMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.nio.file.Path; 19 | import java.nio.file.Paths; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | public class DeployMain { 24 | static private final Logger log = LoggerFactory.getLogger(DeployMain.class); 25 | 26 | static public void main(String[] args) throws Exception { 27 | //Path assemblyFile = Paths.get("src/test/resources/fixtures/hello-conf-1.2.4-SNAPSHOT.zip"); 28 | //Path assemblyFile = Paths.get("src/test/resources/fixtures/hello-world-1.2.4-SNAPSHOT.zip"); 29 | Path assemblyFile = Paths.get("src/test/resources/fixtures/hello-console-1.2.4.tar.gz"); 30 | String uri = "vagrant+ssh://ubuntu1404"; 31 | //String uri = "vagrant+ssh://freebsd102"; 32 | //String uri = "vagrant+ssh://centos7"; 33 | //String uri = "vagrant+ssh://openbsd58"; 34 | //String uri = "vagrant+ssh://debian8"; 35 | 36 | DeployOptions options = new DeployOptions() 37 | //.prefixDir("/opt") 38 | //.organization("fizzed") 39 | //.user("daemon") 40 | //.group("daemon"); 41 | .user(null); 42 | 43 | try (Assembly assembly = Assemblys.process(assemblyFile)) { 44 | new Deployer().deploy(assembly, options, uri); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /stork-deploy/src/test/java/com/fizzed/stork/deploy/DeployerBaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import com.fizzed.blaze.core.ContextHolder; 19 | import com.fizzed.blaze.internal.ContextImpl; 20 | import com.fizzed.crux.vagrant.VagrantClient; 21 | import com.fizzed.crux.vagrant.VagrantClients; 22 | import static org.junit.Assume.*; 23 | import org.junit.Before; 24 | 25 | public class DeployerBaseTest { 26 | 27 | static public final VagrantClient VAGRANT_CLIENT = VagrantClients.cachingOrEmptyClient(); 28 | 29 | protected final String host; 30 | 31 | @Before 32 | public void isVagrantHostRunning() { 33 | assumeTrue("Is vagrant " + host + " running?", VAGRANT_CLIENT.machinesRunning().contains(host)); 34 | } 35 | 36 | @Before 37 | public void bindBlazeContext() { 38 | // bind context before calling any blazified scripts 39 | ContextHolder.set(new ContextImpl(null, null, null, null)); 40 | } 41 | 42 | public DeployerBaseTest(String host) { 43 | this.host = host; 44 | } 45 | 46 | public String getHostUri() { 47 | return "vagrant+ssh://" + host; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /stork-deploy/src/test/java/com/fizzed/stork/deploy/DeployerDaemonTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.nio.file.Path; 19 | import java.nio.file.Paths; 20 | import java.util.Collection; 21 | import static org.hamcrest.CoreMatchers.containsString; 22 | import static org.junit.Assert.assertThat; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.junit.runners.Parameterized; 26 | import org.junit.runners.Parameterized.Parameters; 27 | 28 | @RunWith(Parameterized.class) 29 | public class DeployerDaemonTest extends DeployerBaseTest { 30 | 31 | @Parameters(name = "{index}: vagrant={0}") 32 | public static Collection data() { 33 | return TestHelper.getDaemonVagrantHosts(); 34 | } 35 | 36 | public DeployerDaemonTest(String host) { 37 | super(host); 38 | } 39 | 40 | @Test 41 | public void deploy() throws Exception { 42 | Path assemblyFile = Paths.get("target/stork-daemon1-1.0.0-SNAPSHOT.tar.gz"); 43 | 44 | DeployOptions options = new DeployOptions() 45 | .prefixDir("/opt") 46 | .user("daemon") 47 | .group("daemon"); 48 | 49 | // create our own target for assisting with preparing for tests 50 | // assume its unix for now 51 | UnixTarget target = (UnixTarget)Targets.connect(getHostUri()); 52 | 53 | target.sshExec(true, true, "kill $(ps aux | grep java | grep -v grep | awk \"{print \\$2}\")") 54 | .exitValues(0, 1, 2) 55 | .run(); 56 | target.remove(true, "/opt/stork-daemon1"); 57 | target.remove(true, "/etc/init.d/stork-daemon1"); 58 | target.remove(true, "/etc/default/stork-daemon1"); 59 | target.remove(true, "/etc/sysconfig/stork-daemon1"); 60 | target.remove(true, "/etc/systemd/system/stork-daemon1.service"); 61 | 62 | try (Assembly assembly = Assemblys.process(assemblyFile)) { 63 | new Deployer().deploy(assembly, options, target); 64 | } 65 | 66 | // is the server running on port? 67 | String output 68 | = target.sshExec(false, false, "curl", "http://localhost:18745") 69 | .exitValues(0) 70 | .runCaptureOutput() 71 | .asString(); 72 | 73 | assertThat(output, containsString("Hello World!")); 74 | 75 | 76 | // 77 | // verify upgrade works too 78 | // 79 | try (Assembly assembly = Assemblys.process(assemblyFile)) { 80 | new Deployer().deploy(assembly, options, target); 81 | } 82 | 83 | // is the server running on port 84 | output 85 | = target.sshExec(false, false, "curl", "http://localhost:18745") 86 | .exitValues(0) 87 | .runCaptureOutput() 88 | .asString(); 89 | 90 | assertThat(output, containsString("Hello World!")); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /stork-deploy/src/test/java/com/fizzed/stork/deploy/TargetsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import com.fizzed.blaze.SecureShells; 19 | import com.fizzed.blaze.core.ContextHolder; 20 | import com.fizzed.blaze.internal.ContextImpl; 21 | import com.fizzed.blaze.ssh.SshSession; 22 | import com.fizzed.blaze.ssh.SshSftpSession; 23 | import com.fizzed.blaze.util.MutableUri; 24 | import static com.fizzed.stork.deploy.DeployerBaseTest.VAGRANT_CLIENT; 25 | import java.nio.file.Path; 26 | import java.util.Collection; 27 | import static org.hamcrest.CoreMatchers.instanceOf; 28 | import static org.hamcrest.CoreMatchers.is; 29 | import static org.junit.Assert.assertThat; 30 | import static org.junit.Assert.fail; 31 | import org.junit.Test; 32 | import static org.junit.Assume.*; 33 | import org.junit.Before; 34 | import org.junit.runner.RunWith; 35 | import org.junit.runners.Parameterized; 36 | import org.junit.runners.Parameterized.Parameters; 37 | 38 | @RunWith(Parameterized.class) 39 | public class TargetsTest { 40 | 41 | private final String host; 42 | private final MutableUri uri; 43 | private final Path sshConfigFile; 44 | 45 | @Parameters(name = "{index}: vagrant={0}") 46 | public static Collection data() { 47 | return TestHelper.getConsoleVagrantHosts(); 48 | } 49 | 50 | @Before 51 | public void isVagrantHostRunning() { 52 | assumeTrue("is " + host + " running?", VAGRANT_CLIENT.machinesRunning().contains(host)); 53 | } 54 | 55 | public TargetsTest(String host) { 56 | this.host = host; 57 | this.uri = MutableUri.of("ssh://{}", host); 58 | ContextHolder.set(new ContextImpl(null, null, null, null)); 59 | if (VAGRANT_CLIENT.machinesRunning().contains(host)) { 60 | this.sshConfigFile = VAGRANT_CLIENT.sshConfig(host); 61 | } else { 62 | this.sshConfigFile = null; 63 | } 64 | } 65 | 66 | @Test 67 | public void probe() throws Exception { 68 | try (SshSession ssh = SecureShells.sshConnect(uri).configFile(sshConfigFile).run()) { 69 | try (SshSftpSession sftp = SecureShells.sshSftp(ssh).run()) { 70 | Target target = Targets.probe(ssh, sftp); 71 | 72 | switch (host) { 73 | case "ubuntu14": 74 | assertThat(target.getInitType(), is(InitType.UPSTART)); 75 | assertThat(target, instanceOf(UnixTarget.class)); 76 | break; 77 | case "ubuntu16": 78 | case "debian8": 79 | case "centos7": 80 | assertThat(target.getInitType(), is(InitType.SYSTEMD)); 81 | assertThat(target, instanceOf(UnixTarget.class)); 82 | break; 83 | case "freebsd10": 84 | assertThat(target.getInitType(), is(InitType.UNKNOWN)); 85 | assertThat(target, instanceOf(UnixTarget.class)); 86 | break; 87 | case "openbsd58": 88 | assertThat(target.getInitType(), is(InitType.UNKNOWN)); 89 | assertThat(target, instanceOf(UnixTarget.class)); 90 | break; 91 | default: 92 | fail("Did you forget to add host " + host + "?"); 93 | break; 94 | } 95 | } 96 | } 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /stork-deploy/src/test/java/com/fizzed/stork/deploy/TestHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.deploy; 17 | 18 | import java.net.URI; 19 | import java.nio.file.Path; 20 | import java.nio.file.Paths; 21 | import java.util.Arrays; 22 | import java.util.List; 23 | 24 | public class TestHelper { 25 | 26 | // all hosts we support for deploys w/ only console apps 27 | static private final List VAGRANT_CONSOLE_HOSTS = 28 | Arrays.asList("ubuntu14", "ubuntu16", "debian8", "centos7", "freebsd10", "openbsd58"); 29 | 30 | // subset of hosts we support for deploys w/ daemon apps 31 | static private final List VAGRANT_DAEMON_HOSTS = 32 | Arrays.asList("ubuntu14", "ubuntu16", "debian8", "centos7"); 33 | 34 | static public List filterVagrantHosts(List hosts) { 35 | String host = System.getProperty("host"); 36 | if (host != null && !host.equals("")) { 37 | // is it in the array? 38 | if (hosts.contains(host)) { 39 | return Arrays.asList(host); 40 | } else { 41 | return Arrays.asList(); 42 | } 43 | } else { 44 | return hosts; 45 | } 46 | } 47 | 48 | static public List getConsoleVagrantHosts() { 49 | return filterVagrantHosts(VAGRANT_CONSOLE_HOSTS); 50 | } 51 | 52 | static public List getDaemonVagrantHosts() { 53 | return filterVagrantHosts(VAGRANT_DAEMON_HOSTS); 54 | } 55 | 56 | static public Path getResource(String resourceName) throws Exception { 57 | URI uri = TestHelper.class.getResource(resourceName).toURI(); 58 | return Paths.get(uri); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /stork-deploy/src/test/launchers/stork-console1.yml: -------------------------------------------------------------------------------- 1 | name: "stork-console1" 2 | domain: "com.fizzed.stork.test" 3 | display_name: "Echo Console 1" 4 | short_description: "Unit Testing: should work" 5 | type: CONSOLE 6 | main_class: "com.fizzed.stork.test.EchoConsoleMain" 7 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 8 | working_dir_mode: RETAIN 9 | min_java_version: "1.7" 10 | min_java_memory: 32 11 | max_java_memory: 64 12 | symlink_java: false -------------------------------------------------------------------------------- /stork-deploy/src/test/launchers/stork-daemon1.yml: -------------------------------------------------------------------------------- 1 | name: "stork-daemon1" 2 | domain: "com.fizzed.stork.test" 3 | display_name: "Echo Daemon 1" 4 | short_description: "Echo Daemon" 5 | type: DAEMON 6 | main_class: "com.fizzed.stork.test.EchoDaemonMain" 7 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 8 | working_dir_mode: APP_HOME 9 | min_java_version: "7" 10 | max_java_version: "30" 11 | min_java_memory: 32 12 | max_java_memory: 64 13 | symlink_java: true -------------------------------------------------------------------------------- /stork-deploy/src/test/resources/fixtures/hello-conf-1.2.4-SNAPSHOT.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-deploy/src/test/resources/fixtures/hello-conf-1.2.4-SNAPSHOT.zip -------------------------------------------------------------------------------- /stork-deploy/src/test/resources/fixtures/hello-console-1.2.4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-deploy/src/test/resources/fixtures/hello-console-1.2.4.tar.gz -------------------------------------------------------------------------------- /stork-deploy/src/test/resources/fixtures/hello-console-1.2.4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-deploy/src/test/resources/fixtures/hello-console-1.2.4.zip -------------------------------------------------------------------------------- /stork-deploy/src/test/resources/fixtures/hello-world-1.2.4-SNAPSHOT.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-deploy/src/test/resources/fixtures/hello-world-1.2.4-SNAPSHOT.tar.gz -------------------------------------------------------------------------------- /stork-deploy/src/test/resources/fixtures/hello-world-1.2.4-SNAPSHOT.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-deploy/src/test/resources/fixtures/hello-world-1.2.4-SNAPSHOT.zip -------------------------------------------------------------------------------- /stork-deploy/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%-5level] %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /stork-gradle-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'groovy' 4 | id 'eclipse' 5 | id 'idea' 6 | id "java-gradle-plugin" 7 | id "com.gradle.plugin-publish" version "0.9.8" 8 | } 9 | 10 | repositories { 11 | mavenLocal() 12 | mavenCentral() 13 | } 14 | 15 | def addDependency(configurationName, dependency) { 16 | def coordinates = [ 17 | 'group': dependency.groupId.text(), 18 | 'name': dependency.artifactId.text(), 19 | 'version': dependency.version.text() 20 | ] 21 | dependencies { 22 | add configurationName, coordinates 23 | } 24 | } 25 | 26 | def effectivePomFile = file('target/effective-pom.xml') 27 | if (effectivePomFile.file) { 28 | def pom = new XmlSlurper().parseText(file('target/effective-pom.xml').text) 29 | pom.dependencies.dependency.each { dependency -> 30 | def scope = dependency.scope.text() 31 | if (scope == 'compile') { 32 | addDependency scope, dependency 33 | } 34 | else if (scope == 'test') { 35 | addDependency 'testCompile', dependency 36 | } 37 | } 38 | } 39 | 40 | task createClasspathManifest { 41 | def outputDir = file("$buildDir/$name") 42 | 43 | inputs.files sourceSets.main.runtimeClasspath 44 | outputs.dir outputDir 45 | 46 | doLast { 47 | outputDir.mkdirs() 48 | file("$outputDir/plugin-classpath.txt").text = sourceSets.main.runtimeClasspath.join("\n") 49 | } 50 | } 51 | 52 | dependencies { 53 | compile gradleApi() 54 | compile localGroovy() 55 | 56 | testCompile gradleTestKit() 57 | testCompile 'junit:junit:4.12' 58 | testRuntime files(createClasspathManifest) 59 | } 60 | 61 | gradlePlugin { 62 | plugins { 63 | storkPlugin { 64 | id = "com.fizzed.stork" 65 | implementationClass = "com.fizzed.stork.gradle.StorkPlugin" 66 | } 67 | } 68 | } 69 | 70 | task sourcesJar(type: Jar) { 71 | classifier = 'sources' 72 | from sourceSets.main.allSource 73 | } 74 | 75 | task javadocJar(type: Jar) { 76 | classifier = "javadoc" 77 | from javadoc 78 | } 79 | 80 | artifacts { 81 | archives sourcesJar 82 | archives javadocJar 83 | } 84 | 85 | pluginBundle { 86 | website = 'https://github.com/fizzed/stork' 87 | vcsUrl = 'https://github.com/fizzed/stork' 88 | description = 'Plugin for stork launcher & assembly' 89 | tags = ['distribution', 'application'] 90 | 91 | plugins { 92 | storkPlugin { 93 | id = "com.fizzed.stork" 94 | displayName = 'Stork gradle plugin' 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /stork-gradle-plugin/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.daemon=false -------------------------------------------------------------------------------- /stork-gradle-plugin/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-gradle-plugin/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /stork-gradle-plugin/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-bin.zip 6 | -------------------------------------------------------------------------------- /stork-gradle-plugin/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /stork-gradle-plugin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.fizzed 9 | stork 10 | 2.6.2-SNAPSHOT 11 | 12 | 13 | stork-gradle-plugin 14 | 2.6.2-SNAPSHOT 15 | pom 16 | 17 | 18 | ${basedir}/../.. 19 | ./gradlew 20 | build 21 | 22 | 23 | 24 | 25 | com.fizzed 26 | stork-launcher 27 | 28 | 29 | com.fizzed 30 | stork-assembly 31 | 32 | 33 | 34 | 35 | 36 | maven-help-plugin 37 | org.apache.maven.plugins 38 | 39 | 40 | prepare-package 41 | 42 | effective-pom 43 | 44 | 45 | ${project.build.directory}/effective-pom.xml 46 | 47 | 48 | 49 | 50 | 51 | org.codehaus.mojo 52 | exec-maven-plugin 53 | 54 | 55 | gradle 56 | prepare-package 57 | 58 | ${gradle.executable} 59 | 60 | clean 61 | ${gradle.task} 62 | -Pversion=${project.version} 63 | -Pdescription=${project.description} 64 | 65 | 66 | 67 | exec 68 | 69 | 70 | 71 | 72 | 73 | org.codehaus.mojo 74 | build-helper-maven-plugin 75 | 1.12 76 | 77 | 78 | attach-artifacts 79 | package 80 | 81 | attach-artifact 82 | 83 | 84 | 85 | 86 | build/libs/${project.artifactId}-${project.version}.jar 87 | jar 88 | 89 | 90 | build/libs/${project.artifactId}-${project.version}-javadoc.jar 91 | jar 92 | javadoc 93 | 94 | 95 | build/libs/${project.artifactId}-${project.version}-sources.jar 96 | jar 97 | sources 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | windows 110 | 111 | 112 | windows 113 | 114 | 115 | 116 | gradlew.bat 117 | 118 | 119 | 120 | skipTests 121 | 122 | 123 | skipTests 124 | true 125 | 126 | 127 | 128 | assemble 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /stork-gradle-plugin/src/main/groovy/com/fizzed/stork/gradle/StorkPlugin.groovy: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.gradle 2 | 3 | import com.fizzed.stork.gradle.tasks.AssemblyExtension 4 | import com.fizzed.stork.gradle.tasks.AssemblyTask 5 | import com.fizzed.stork.gradle.tasks.LaunchersExtension 6 | import com.fizzed.stork.gradle.tasks.LaunchersTask 7 | import org.gradle.api.GradleException 8 | import org.gradle.api.Plugin 9 | import org.gradle.api.Project 10 | import org.gradle.api.file.CopySpec 11 | import org.gradle.api.tasks.Copy 12 | import org.gradle.util.GradleVersion 13 | 14 | class StorkPlugin implements Plugin { 15 | 16 | @Override 17 | void apply(Project project) { 18 | if (GradleVersion.current() < GradleVersion.version("4.0")) { 19 | throw new GradleException("Stork plugin require Gradle 4.0 or later") 20 | } 21 | 22 | LaunchersExtension lext = project.extensions.create("storkLaunchers", LaunchersExtension, project) 23 | LaunchersTask launchersTask = project.tasks.create(LaunchersTask.TASK_NAME, LaunchersTask) { 24 | description = "Generate Stork launchers scripts" 25 | group = "stork" 26 | outputDirectory = lext.outputDirectory 27 | inputFiles = lext.inputFiles 28 | launchers = lext.launchers 29 | } 30 | 31 | AssemblyExtension aext = project.extensions.create("storkAssembly", AssemblyExtension, project) 32 | Copy prepareAssembly = project.tasks.create("storkPrepareAssembly", Copy) { 33 | group("stork") 34 | dependsOn launchersTask 35 | } 36 | prepareAssembly.destinationDir = aext.stageDirectory 37 | prepareAssembly.with(configureAssemblySpec(project)) 38 | 39 | AssemblyTask assemblyTask = project.tasks.create(AssemblyTask.TASK_NAME, AssemblyTask) { 40 | description = "Create stork assembly archive" 41 | group = "stork" 42 | outputDirectory = aext.outputDirectory 43 | stageDirectory = aext.stageDirectory 44 | filename = aext.filename 45 | dependsOn prepareAssembly 46 | } 47 | } 48 | 49 | private CopySpec configureAssemblySpec(Project project) { 50 | project.copySpec() { 51 | from(new File(project.projectDir, "src/assembly")) 52 | 53 | into("lib") { 54 | from(project.getTasksByName("jar", true)) 55 | from(project.configurations.runtime) 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /stork-gradle-plugin/src/main/groovy/com/fizzed/stork/gradle/tasks/AssemblyExtension.groovy: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.gradle.tasks 2 | 3 | import org.gradle.api.Project 4 | 5 | class AssemblyExtension { 6 | 7 | final Project project 8 | 9 | File outputDirectory 10 | 11 | File stageDirectory 12 | 13 | String filename 14 | 15 | AssemblyExtension(Project project) { 16 | this.project = project 17 | this.outputDirectory = project.buildDir 18 | this.stageDirectory = new File(project.buildDir, "stork") 19 | this.filename = "${project.name}-${project.version}".toString() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /stork-gradle-plugin/src/main/groovy/com/fizzed/stork/gradle/tasks/AssemblyTask.groovy: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.gradle.tasks 2 | 3 | import com.fizzed.stork.assembly.AssemblyUtils 4 | import org.gradle.api.DefaultTask 5 | import org.gradle.api.tasks.TaskAction 6 | 7 | class AssemblyTask extends DefaultTask { 8 | 9 | public static final String TASK_NAME = "storkAssembly" 10 | 11 | File outputDirectory 12 | 13 | File stageDirectory 14 | 15 | String filename 16 | 17 | @TaskAction 18 | void action() { 19 | AssemblyUtils.copyStandardProjectResources(project.projectDir, stageDirectory) 20 | File tgzFile = AssemblyUtils.createTGZ(outputDirectory, stageDirectory, filename) 21 | logger.info("Generated maven stork assembly: ${tgzFile}") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /stork-gradle-plugin/src/main/groovy/com/fizzed/stork/gradle/tasks/LauncherExtension.groovy: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.gradle.tasks 2 | 3 | import com.fizzed.stork.launcher.Configuration 4 | import com.fizzed.stork.launcher.PlatformConfiguration 5 | 6 | class LauncherExtension { 7 | 8 | Configuration.Platform[] platforms 9 | String name 10 | String displayName 11 | String domain 12 | String shortDescription 13 | String longDescription 14 | String mainClass 15 | Configuration.Type type 16 | Configuration.WorkingDirMode workingDirMode 17 | String appArgs = "" 18 | String javaArgs = "" 19 | String extraAppArgs = "" 20 | String extraJavaArgs = "" 21 | String minJavaVersion = "1.6" 22 | Integer minJavaMemory = null 23 | Integer maxJavaMemory = null 24 | Integer minJavaMemoryPct = null 25 | Integer maxJavaMemoryPct = null 26 | boolean includeJavaXrs = true 27 | boolean symlinkJava = false 28 | boolean includeJavaDetectHelper = false 29 | Integer daemonMinLifetime = 5 30 | 31 | private Map platformConfigurations 32 | 33 | Configuration toConfiguration() { 34 | Configuration cfg = new Configuration() 35 | cfg.file = new File(name + ".yml") 36 | cfg.name = name 37 | cfg.displayName = displayName 38 | cfg.Domain = domain 39 | cfg.ShortDescription = shortDescription 40 | cfg.LongDescription = longDescription 41 | cfg.MainClass = mainClass 42 | cfg.Type = type 43 | cfg.WorkingDirMode = workingDirMode 44 | cfg.AppArgs = appArgs 45 | cfg.JavaArgs = javaArgs 46 | cfg.ExtraAppArgs = extraAppArgs 47 | cfg.ExtraJavaArgs = extraJavaArgs 48 | cfg.MinJavaVersion = minJavaVersion 49 | cfg.MinJavaMemory = minJavaMemory 50 | cfg.MaxJavaMemory = maxJavaMemory 51 | cfg.MinJavaMemoryPct = minJavaMemoryPct 52 | cfg.MaxJavaMemoryPct = maxJavaMemoryPct 53 | cfg.IncludeJavaXrs = includeJavaXrs 54 | cfg.SymlinkJava = symlinkJava 55 | cfg.IncludeJavaDetectHelper = includeJavaDetectHelper 56 | cfg.DaemonMinLifetime = daemonMinLifetime 57 | 58 | Set ps = new HashSet<>() 59 | ps.addAll(platforms) 60 | cfg.platforms = ps 61 | 62 | if (platformConfigurations != null) { 63 | Map pcm = new HashMap<>() 64 | for (Map.Entry pc : platformConfigurations.entrySet()) { 65 | pcm.put(Configuration.Platform.valueOf(pc.key), pc.value) 66 | } 67 | } 68 | 69 | return cfg 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /stork-gradle-plugin/src/main/groovy/com/fizzed/stork/gradle/tasks/LaunchersExtension.groovy: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.gradle.tasks 2 | 3 | import org.gradle.api.Project 4 | 5 | class LaunchersExtension { 6 | 7 | final Project project 8 | 9 | File outputDirectory 10 | 11 | List launchers = new ArrayList<>() 12 | 13 | List inputFiles 14 | 15 | LaunchersExtension(Project project) { 16 | this.project = project 17 | this.outputDirectory = new File(project.buildDir, "stork") 18 | this.inputFiles = ["${project.projectDir}/src/main/launchers".toString()] 19 | } 20 | 21 | LauncherExtension launcher(Closure closure) { 22 | LauncherExtension cfg = project.configure(new LauncherExtension(), closure) 23 | println("launcher "+ cfg) 24 | launchers.add(cfg) 25 | cfg 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /stork-gradle-plugin/src/main/groovy/com/fizzed/stork/gradle/tasks/LaunchersTask.groovy: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.gradle.tasks; 2 | 3 | import com.fizzed.stork.core.ArgumentException 4 | import com.fizzed.stork.launcher.Configuration 5 | import com.fizzed.stork.launcher.ConfigurationFactory 6 | import com.fizzed.stork.launcher.FileUtil 7 | import com.fizzed.stork.launcher.Generator 8 | import org.gradle.api.DefaultTask 9 | import org.gradle.api.GradleException 10 | import org.gradle.api.tasks.TaskAction 11 | 12 | /** 13 | * Gradle task equivalent to maven plugin "stork-launcher" 14 | * 15 | * @author by BertrandA 16 | */ 17 | class LaunchersTask extends DefaultTask { 18 | 19 | public static final String TASK_NAME = "storkLaunchers" 20 | 21 | File outputDirectory 22 | 23 | List inputFiles 24 | 25 | List launchers 26 | 27 | @TaskAction 28 | void action() throws IOException { 29 | if (!outputDirectory.exists()) { 30 | if (!outputDirectory.mkdirs()) { 31 | throw new IOException("Could not create directory:" + outputDirectory) 32 | } 33 | } 34 | 35 | try { 36 | def configFiles = FileUtil.findAllFiles(inputFiles, true) 37 | // read launchers from yml files 38 | List configs = new ConfigurationFactory().read(configFiles) 39 | // appends launchers configured into gradle build scripts 40 | println("configs: "+ configs) 41 | println("launchers: "+ launchers) 42 | launchers.each { configs.add(it.toConfiguration()) } 43 | 44 | println("configs: "+ configs) 45 | int generated = new Generator().generate(configs, outputDirectory) 46 | logger.info("generated ${generated} launcher(s)") 47 | } catch (ArgumentException | IOException e) { 48 | throw new GradleException(e.getMessage(), e) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /stork-gradle-plugin/src/test/groovy/com/fizzed/stork/gradle/StorkPluginTests.groovy: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.gradle 2 | 3 | import com.fizzed.stork.gradle.tasks.LaunchersTask 4 | import org.gradle.api.Project 5 | import org.gradle.testfixtures.ProjectBuilder 6 | import org.gradle.testkit.runner.BuildResult 7 | import org.gradle.testkit.runner.GradleRunner 8 | import org.junit.Before 9 | import org.junit.Rule 10 | import org.junit.Test 11 | import org.junit.rules.TemporaryFolder 12 | 13 | import java.nio.file.Paths 14 | 15 | import static org.gradle.testkit.runner.TaskOutcome.SUCCESS 16 | import static org.hamcrest.MatcherAssert.assertThat 17 | import static org.hamcrest.core.IsEqual.equalTo 18 | import static org.junit.Assert.assertTrue 19 | 20 | class StorkPluginTests { 21 | @Rule 22 | public final TemporaryFolder testProjectDir = new TemporaryFolder() 23 | 24 | def pluginClasspathResource = getClass().classLoader.findResource("plugin-classpath.txt") 25 | def pluginClasspath = pluginClasspathResource.readLines().collect { new File(it) } 26 | 27 | File buildFile 28 | 29 | @Before 30 | void setup() throws IOException { 31 | buildFile = testProjectDir.newFile("build.gradle") 32 | } 33 | 34 | @Test 35 | void testBasic() { 36 | Project project = ProjectBuilder.builder().build() 37 | project.pluginManager.apply("java") 38 | project.pluginManager.apply 'com.fizzed.stork' 39 | 40 | assertTrue(project.tasks.storkLaunchers instanceof LaunchersTask) 41 | } 42 | 43 | @Test 44 | void testLauncherDsl() { 45 | buildFile << """ 46 | plugins { 47 | id 'java' 48 | id 'com.fizzed.stork' 49 | } 50 | 51 | storkLaunchers { 52 | launcher { 53 | name = "test" 54 | displayName = "test" 55 | domain = "com.dcode.asgard" 56 | shortDescription = "desc" 57 | type = "DAEMON" 58 | platforms = ["LINUX","MAC_OSX"] 59 | workingDirMode = "APP_HOME" 60 | mainClass="class" 61 | } 62 | } 63 | """ 64 | 65 | BuildResult result = GradleRunner.create() 66 | .withProjectDir(testProjectDir.root) 67 | .withPluginClasspath(pluginClasspath) 68 | .withArguments(LaunchersTask.TASK_NAME, "--stacktrace") 69 | .build() 70 | 71 | assertThat(result.task(":" + LaunchersTask.TASK_NAME).outcome, equalTo(SUCCESS)) 72 | //check if script has been created 73 | assertTrue(Paths.get(testProjectDir.root.toString(), "build", "stork", "bin", "test").toFile().exists()) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /stork-launcher/src/main/java/com/fizzed/stork/launcher/ConfigurationFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import com.fasterxml.jackson.core.JsonProcessingException; 19 | import com.fasterxml.jackson.databind.JsonNode; 20 | import com.fasterxml.jackson.databind.ObjectMapper; 21 | import com.fasterxml.jackson.databind.PropertyNamingStrategy; 22 | import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | import java.util.Set; 28 | import javax.validation.ConstraintViolation; 29 | import javax.validation.Validation; 30 | import javax.validation.Validator; 31 | import javax.validation.ValidatorFactory; 32 | 33 | /** 34 | * 35 | * @author joelauer 36 | */ 37 | public class ConfigurationFactory { 38 | 39 | private final ObjectMapper mapper; 40 | 41 | public ConfigurationFactory() { 42 | this.mapper = createObjectMapper(); 43 | } 44 | 45 | static public ObjectMapper createObjectMapper() { 46 | // create json deserializer 47 | ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); 48 | mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); 49 | return mapper; 50 | } 51 | 52 | ObjectMapper getMapper() { 53 | return mapper; 54 | } 55 | 56 | JsonNode createDefaultNode() { 57 | return mapper.valueToTree(new Configuration()); 58 | } 59 | 60 | JsonNode createConfigNode(File configFile) throws IOException { 61 | return mapper.readTree(configFile); 62 | } 63 | 64 | JsonNode mergeNodes(JsonNode node, JsonNode updateNode) { 65 | return JacksonUtil.merge(node, updateNode); 66 | } 67 | 68 | Configuration create(JsonNode node) throws JsonProcessingException { 69 | return mapper.treeToValue(node, Configuration.class); 70 | } 71 | 72 | public Configuration read(File configFile) throws IOException { 73 | // tree of defaults 74 | JsonNode defaultNode = createDefaultNode(); 75 | 76 | // tree of configuration 77 | JsonNode configNode = createConfigNode(configFile); 78 | 79 | // merge defaults + config 80 | JsonNode mergedNode = mergeNodes(defaultNode, configNode); 81 | 82 | Configuration config = create(mergedNode); 83 | config.setFile(configFile); 84 | 85 | // create validator 86 | ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 87 | Validator validator = factory.getValidator(); 88 | 89 | Set> violations = validator.validate(config); 90 | if (violations.size() > 0) { 91 | for (ConstraintViolation violation : violations) { 92 | throw new IOException("Configuration file invalid: property [" + violation.getPropertyPath() + "] error [" + violation.getMessage() + "]"); 93 | } 94 | } 95 | 96 | return config; 97 | } 98 | 99 | public List read(List configFiles) throws IOException { 100 | List configs = new ArrayList<>(); 101 | 102 | // no input files return an empty array of configs 103 | if (configFiles == null || configFiles.isEmpty()) { 104 | return configs; 105 | } 106 | 107 | // parse each configuration file into a configuration object 108 | for (File configFile : configFiles) { 109 | try { 110 | configs.add(this.read(configFile)); 111 | } catch (Exception e) { 112 | throw new IOException("Launcher config file [" + configFile + "] failed parsing", e); 113 | } 114 | } 115 | 116 | return configs; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /stork-launcher/src/main/java/com/fizzed/stork/launcher/FileUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 mfizz. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import java.io.File; 19 | import java.io.FileFilter; 20 | import java.io.IOException; 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.Collections; 24 | import java.util.List; 25 | import org.apache.commons.io.filefilter.WildcardFileFilter; 26 | 27 | public class FileUtil { 28 | 29 | static public List findAllFiles(List fileStrings, boolean ignoreNonExistent) throws IOException { 30 | List allFiles = new ArrayList<>(); 31 | for (String fileString : fileStrings) { 32 | List files = FileUtil.findFiles(fileString, ignoreNonExistent); 33 | allFiles.addAll(files); 34 | } 35 | return allFiles; 36 | } 37 | 38 | static public List findFiles(String fileString, boolean ignoreNonExistent) throws IOException { 39 | if (fileString.endsWith("*")) { 40 | // file string contains a glob... 41 | File f = new File(fileString); 42 | File parent = f.getParentFile(); 43 | if (parent == null) { 44 | parent = new File("."); 45 | } 46 | FileFilter fileFilter = new WildcardFileFilter(f.getName()); 47 | File[] files = parent.listFiles(fileFilter); 48 | return Arrays.asList(files); 49 | } else { 50 | File f = new File(fileString); 51 | if (!f.exists()) { 52 | if (ignoreNonExistent) { 53 | return Collections.EMPTY_LIST; 54 | } else { 55 | throw new IOException("File [" + fileString + "] does not exist"); 56 | } 57 | } else { 58 | if (f.isDirectory()) { 59 | return Arrays.asList(f.listFiles()); 60 | } else { 61 | return Arrays.asList(f); 62 | } 63 | } 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /stork-launcher/src/main/java/com/fizzed/stork/launcher/JacksonUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.node.ObjectNode; 20 | import java.util.Iterator; 21 | 22 | /** 23 | * 24 | * @author joelauer 25 | */ 26 | public class JacksonUtil { 27 | 28 | public static JsonNode merge(JsonNode mainNode, JsonNode updateNode) { 29 | Iterator fieldNames = updateNode.fieldNames(); 30 | while (fieldNames.hasNext()) { 31 | 32 | String fieldName = fieldNames.next(); 33 | JsonNode jsonNode = mainNode.get(fieldName); 34 | // if field exists and is an embedded object 35 | if (jsonNode != null && jsonNode.isObject()) { 36 | merge(jsonNode, updateNode.get(fieldName)); 37 | } 38 | else { 39 | if (mainNode instanceof ObjectNode) { 40 | // Overwrite field 41 | JsonNode value = updateNode.get(fieldName); 42 | ((ObjectNode) mainNode).put(fieldName, value); 43 | } 44 | } 45 | } 46 | return mainNode; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /stork-launcher/src/main/java/com/fizzed/stork/launcher/LauncherMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import com.fizzed.stork.core.ArgumentException; 19 | import com.fizzed.stork.core.BaseApplication; 20 | import java.io.File; 21 | import java.io.IOException; 22 | import java.util.ArrayList; 23 | import java.util.Deque; 24 | import java.util.List; 25 | import org.slf4j.Logger; 26 | 27 | /** 28 | * Main entry point for creating console/daemon launchers 29 | * 30 | * @author joelauer 31 | */ 32 | public class LauncherMain extends BaseApplication { 33 | 34 | static public void main(String[] args) { 35 | new LauncherMain().run(args); 36 | } 37 | 38 | @Override 39 | public void printUsage() { 40 | System.out.println("Usage: stork-launcher -o ..."); 41 | System.out.println(""); 42 | System.out.println("Create console/daemon launchers for your Java apps. Input may"); 43 | System.out.println("either be a file or include a wildcard to support searching."); 44 | System.out.println(""); 45 | System.out.println("Arguments"); 46 | System.out.println(""); 47 | System.out.println(" -v, --version Print version and exit"); 48 | System.out.println(" -h, --help Print help and exit"); 49 | System.out.println(" -o, --output-dir Output directory"); 50 | System.out.println(""); 51 | } 52 | 53 | @Override 54 | public void run(Deque args) { 55 | File outputDir = null; 56 | List configFileStrings = new ArrayList<>(); 57 | 58 | while (!args.isEmpty()) { 59 | String arg = args.remove(); 60 | 61 | switch (arg) { 62 | case "-v": 63 | case "--version": { 64 | System.out.println("stork-launcher " + com.fizzed.stork.core.Version.getLongVersion()); 65 | System.out.println(" by Fizzed, Inc. (http://fizzed.com)"); 66 | System.out.println(" at https://github.com/fizzed/stork"); 67 | System.exit(0); 68 | break; 69 | } 70 | case "-h": 71 | case "--help": { 72 | printUsage(); 73 | System.exit(0); 74 | break; 75 | } 76 | case "-o": 77 | case "--output-dir": { 78 | outputDir = new File(nextArg(arg, args)); 79 | break; 80 | } 81 | default: { 82 | if (arg.startsWith("-")) { 83 | printErrorThenHelpHintAndExit("invalid argument [" + arg + "]"); 84 | } else { 85 | configFileStrings.add(arg); 86 | break; 87 | } 88 | } 89 | } 90 | } 91 | 92 | if (outputDir == null) { 93 | printErrorThenHelpHintAndExit("output dir required"); 94 | } 95 | 96 | if (configFileStrings.isEmpty()) { 97 | printErrorThenHelpHintAndExit("input file required"); 98 | } 99 | 100 | final Logger log = this.getLogger(); 101 | logWelcomeMessage(); 102 | 103 | try { 104 | List configFiles = FileUtil.findAllFiles(configFileStrings, false); 105 | ConfigurationFactory configFactory = new ConfigurationFactory(); 106 | List configs = configFactory.read(configFiles); 107 | int generated = new Generator().generate(configs, outputDir); 108 | log.info("Created " + generated + " launchers"); 109 | } catch (ArgumentException e) { 110 | printErrorThenHelpHintAndExit(e.getMessage()); 111 | } catch (IOException e) { 112 | // serious enough to dump a stack trace 113 | log.error("Unable to cleanly generate launcher(s)", e); 114 | printErrorThenHelpHintAndExit(e.getMessage()); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /stork-launcher/src/main/java/com/fizzed/stork/launcher/LauncherModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import com.fizzed.stork.core.Version; 19 | 20 | public class LauncherModel { 21 | 22 | private final String version; 23 | private final Configuration config; 24 | 25 | public LauncherModel(Configuration config) { 26 | this.version = Version.getVersion(); 27 | this.config = config; 28 | } 29 | 30 | public String getVersion() { 31 | return version; 32 | } 33 | 34 | public Configuration getConfig() { 35 | return config; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /stork-launcher/src/main/java/com/fizzed/stork/launcher/MergeMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import com.fizzed.stork.core.BaseApplication; 19 | import java.io.File; 20 | import java.util.ArrayList; 21 | import java.util.Deque; 22 | import java.util.List; 23 | 24 | public class MergeMain extends BaseApplication { 25 | 26 | @Override 27 | public void printUsage() { 28 | System.err.println("Usage: stork-merge -i -o [-i ...]"); 29 | System.err.println("-v Print version and exit"); 30 | System.err.println("-i Input file (dir or wildcard accepted)"); 31 | System.err.println("-o Output file"); 32 | } 33 | 34 | static public void main(String[] args) { 35 | new MergeMain().run(args); 36 | } 37 | 38 | @Override 39 | public void run(Deque args) { 40 | File outputFile = null; 41 | List configFiles = new ArrayList<>(); 42 | 43 | while (!args.isEmpty()) { 44 | String arg = args.remove(); 45 | 46 | /** 47 | 48 | if (argSwitch.equals("-v") || argSwitch.equals("--version")) { 49 | System.err.println("stork-merge: v" + com.fizzed.stork.launcher.Version.getLongVersion()); 50 | System.exit(0); 51 | } else if (argSwitch.equals("-h") || argSwitch.equals("--help")) { 52 | printUsage(); 53 | System.exit(0); 54 | } else if (argSwitch.equals("-i") || argSwitch.equals("--input")) { 55 | String fileString = popNextArg(argSwitch, argList); 56 | try { 57 | List files = FileUtil.findFiles(fileString, false); 58 | configFiles.addAll(files); 59 | } catch (IOException e) { 60 | printErrorThenUsageAndExit(e.getMessage()); 61 | } 62 | } else if (argSwitch.equals("-o") || argSwitch.equals("--output")) { 63 | outputFile = new File(popNextArg(argSwitch, argList)); 64 | File outputDir = outputFile.getParentFile(); 65 | if (!outputDir.exists()) { 66 | if (!outputDir.mkdirs()) { 67 | printErrorThenUsageAndExit("unable to make output dir [" + outputDir + "]"); 68 | } else { 69 | System.out.println("Created output directory: " + outputDir); 70 | } 71 | } 72 | if (!outputDir.isDirectory()) { 73 | printErrorThenUsageAndExit("output dir [" + outputDir + "] exists but is not a directory"); 74 | } 75 | if (!outputDir.canWrite()) { 76 | printErrorThenUsageAndExit("output dir [" + outputDir + "] is not writable"); 77 | } 78 | } else { 79 | printErrorThenUsageAndExit("invalid argument switch [" + argSwitch + "] found"); 80 | } 81 | */ 82 | } 83 | 84 | /** 85 | try { 86 | merge(configFiles, outputFile); 87 | } catch (IOException e) { 88 | logger.error("Unable to cleanly merge launcher configs", e); 89 | printErrorThenUsageAndExit(e.getMessage()); 90 | } 91 | */ 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /stork-launcher/src/main/java/com/fizzed/stork/launcher/Merger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.util.List; 22 | 23 | /** 24 | * Merges config files together. 25 | * 26 | * @author joelauer 27 | */ 28 | public class Merger { 29 | 30 | static public void merge(List configFiles, File outputFile) throws IOException { 31 | // validate required arguments 32 | if (configFiles == null || configFiles.isEmpty()) { 33 | throw new IllegalArgumentException("No input config files were found"); 34 | } 35 | 36 | if (outputFile == null) { 37 | throw new IOException("no output file was specified"); 38 | } 39 | 40 | ConfigurationFactory factory = new ConfigurationFactory(); 41 | JsonNode mergedNode = null; 42 | 43 | // parse each configuration file into a configuration object 44 | for (File configFile : configFiles) { 45 | try { 46 | JsonNode updateNode = factory.createConfigNode(configFile); 47 | if (mergedNode == null) { 48 | mergedNode = updateNode; 49 | } else { 50 | mergedNode = factory.mergeNodes(mergedNode, updateNode); 51 | } 52 | } catch (Exception e) { 53 | throw new IOException("Config file [" + configFile + "] invalid"); 54 | } 55 | } 56 | 57 | try { 58 | // write merged file back out 59 | factory.getMapper().writeValue(outputFile, mergedNode); 60 | System.out.println("Wrote merged config file: " + outputFile); 61 | } catch (Exception e) { 62 | throw new IOException("Unable to cleanly write merged config"); 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /stork-launcher/src/main/java/com/fizzed/stork/launcher/PlatformConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import com.fizzed.stork.launcher.Configuration.DaemonMethod; 19 | 20 | public class PlatformConfiguration { 21 | 22 | private Configuration.DaemonMethod daemonMethod; 23 | private String user; 24 | private String group; 25 | private String prefixDir; 26 | private String logDir; 27 | private String runDir; 28 | 29 | public DaemonMethod getDaemonMethod() { 30 | return daemonMethod; 31 | } 32 | 33 | public void setDaemonMethod(DaemonMethod daemonMethod) { 34 | this.daemonMethod = daemonMethod; 35 | } 36 | 37 | public String getUser() { 38 | return user; 39 | } 40 | 41 | public void setUser(String user) { 42 | this.user = user; 43 | } 44 | 45 | public String getGroup() { 46 | return group; 47 | } 48 | 49 | public void setGroup(String group) { 50 | this.group = group; 51 | } 52 | 53 | public String getPrefixDir() { 54 | return prefixDir; 55 | } 56 | 57 | public void setPrefixDir(String prefixDir) { 58 | this.prefixDir = prefixDir; 59 | } 60 | 61 | public String getLogDir() { 62 | return logDir; 63 | } 64 | 65 | public void setLogDir(String logDir) { 66 | this.logDir = logDir; 67 | } 68 | 69 | public String getRunDir() { 70 | return runDir; 71 | } 72 | 73 | public void setRunDir(String runDir) { 74 | this.runDir = runDir; 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/initd-daemon.ftl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # /etc/init.d/${config.name} 5 | # Redhat and/or debian-compatible startup script 6 | # Generated via Stork Launcher by Fizzed 7 | # http://github.com/fizzed/java-stork 8 | # 9 | 10 | ### BEGIN INIT INFO 11 | # Provides: ${config.name} 12 | # Required-Start: $remote_fs $syslog 13 | # Required-Stop: $remote_fs $syslog 14 | # Default-Start: 2 3 4 5 15 | # Default-Stop: 0 1 6 16 | # Short-Description: ${config.shortDescription} 17 | # Description: ${config.longDescription!""} 18 | ### END INIT INFO 19 | 20 | PATH=/bin:/usr/bin:/sbin:/usr/sbin 21 | 22 | NAME="${config.name}" 23 | SCRIPTNAME="/etc/init.d/${config.name}" 24 | APP_HOME="${config.getPlatformPrefixDir("LINUX")}/${config.name}" 25 | APP_USER="${config.getPlatformUser("LINUX")!""}" 26 | APP_GROUP="${config.getPlatformGroup("LINUX")!""}" 27 | RUN_DIR="${config.getPlatformRunDir("LINUX")!""}" 28 | LOG_DIR="${config.getPlatformLogDir("LINUX")!""}" 29 | SU="/bin/su" 30 | SUDO="sudo" 31 | 32 | # make sure we are run as root 33 | if [ `id -u` -ne 0 ]; then 34 | echo "The $NAME init script can only be run as root" 35 | exit 1 36 | fi 37 | 38 | # any system defaults (sysconfig on redhat; default on debian) 39 | [ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME 40 | [ -r /etc/default/$NAME ] && . /etc/default/$NAME 41 | 42 | # run/log directories may have been removed from prior invocation 43 | if [ ! -z $RUN_DIR ]; then 44 | if [ ! -d "$RUN_DIR" ]; then 45 | mkdir -p "$RUN_DIR" 46 | if [ ! -z $APP_USER ]; then 47 | chown -R $APP_USER:$APP_GROUP "$RUN_DIR" 48 | fi 49 | fi 50 | fi 51 | 52 | if [ ! -z $LOG_DIR ]; then 53 | if [ ! -d "$LOG_DIR" ]; then 54 | mkdir -p "$LOG_DIR" 55 | if [ ! -z $APP_USER ]; then 56 | chown -R $APP_USER:$APP_GROUP "$LOG_DIR" 57 | fi 58 | fi 59 | fi 60 | 61 | # in order to use su/sudo below without a app_user set, set one if missing 62 | if [ -z $APP_USER ]; then 63 | APP_USER="$USER" 64 | fi 65 | 66 | # everything needs to be run as requested user 67 | case "$1" in 68 | start) 69 | $SU $APP_USER -s /bin/sh -m -c "\"$APP_HOME/bin/$NAME\" --start" 70 | ;; 71 | run) 72 | # running with su does not correctly kill subshells - must use sudo to run 73 | $SUDO -u $APP_USER "$APP_HOME/bin/$NAME" --run 74 | ;; 75 | stop) 76 | $SU $APP_USER -s /bin/sh -m -c "\"$APP_HOME/bin/$NAME\" --stop" 77 | ;; 78 | restart) 79 | $SU $APP_USER -s /bin/sh -m -c "\"$APP_HOME/bin/$NAME\" --stop" 80 | $SU $APP_USER -s /bin/sh -m -c "\"$APP_HOME/bin/$NAME\" --start" 81 | ;; 82 | status) 83 | $SU $APP_USER -s /bin/sh -m -c "\"$APP_HOME/bin/$NAME\" --status" 84 | ;; 85 | *) 86 | echo "Usage: $SCRIPTNAME {start|stop|status|restart|run}" >&2 87 | exit 3 88 | ;; 89 | esac 90 | 91 | # passthru exit code from command above (errors can be detected with exit code...) 92 | exit $? -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/script-console.ftl: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # run console app 4 | # 5 | 6 | eval $RUN_CMD 7 | 8 | # 9 | # end of script 10 | # 11 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/script-daemon-nohup.ftl: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # usage for daemon using NOHUP method 4 | # 5 | 6 | usage() 7 | { 8 | echo "Usage: $0 [--start|--stop|--exec|--run|--status}" 9 | exit 1 10 | } 11 | 12 | [ ! -z "$APP_ACTION_ARG" ] || usage 13 | 14 | 15 | # 16 | # can we write to log directory (run directory checked previously)? 17 | # 18 | if [ ! -d "$APP_LOG_DIR" ]; then 19 | mkdir -p "$APP_LOG_DIR" 2>/dev/null 20 | if [ ! -d "$APP_LOG_DIR" ]; then 21 | echo "Unable to create log dir: $APP_LOG_DIR_ABS (check permissions; is user `whoami` owner?)" 22 | exit 1 23 | fi 24 | fi 25 | if [ ! -w "$APP_LOG_DIR" ]; then 26 | echo "Unable to write files in log dir: $APP_LOG_DIR_ABS (check permissions; is user `whoami` owner?)" 27 | exit 1 28 | fi 29 | 30 | 31 | # more intelligent info on location of nohup output 32 | # if the initial working directory is not the same as the app home then 33 | # use the full path to the outfile 34 | NOHUP_OUT="$APP_LOG_DIR_ABS/$NAME.out" 35 | if [ "$APP_HOME" != "$INITIAL_WORKING_DIR" ]; then 36 | NOHUP_OUT="$APP_HOME/$APP_LOG_DIR/$NAME.out" 37 | fi 38 | # if outfile already exists, make sure it its writable by us 39 | if [ -f "$NOHUP_OUT" ] && [ ! -w "$NOHUP_OUT" ]; then 40 | echo "Unable to overwrite existing nohup log file: $NOHUP_OUT (check permissions; is user `whoami` owner?)" 41 | exit 1 42 | fi 43 | 44 | case "$APP_ACTION_ARG" in 45 | 46 | --start) 47 | printf "Starting $NAME: " 48 | verifyNotRunning $APP_PID_FILE 49 | 50 | # log start time first into outfile 51 | echo "$NAME starting at `date`" > "$NOHUP_OUT" 52 | 53 | #nohup "$JAVA_EXE" $RUN_ARGS "$NOHUP_OUT" 2>&1 & 54 | nohup "$JAVA_EXE" -Dlauncher.name=$NAME -Dlauncher.type=$RUN_TYPE "-Dlauncher.app.dir=$APP_HOME" $JAVA_ARGS -classpath "$APP_JAVA_CLASSPATH" $MAIN_CLASS $APP_ARGS "$NOHUP_OUT" 2>&1 & 55 | PID=$! 56 | echo $PID > $APP_PID_FILE 57 | 58 | # confirm the daemon started by making sure its alive for a certain time 59 | CONFIRMED="" 60 | if [ ! -z $DAEMON_MIN_LIFETIME ]; then 61 | # wait for minimum amount of time 62 | timeout=$DAEMON_MIN_LIFETIME 63 | while [ $timeout -gt 0 ]; do 64 | sleep 1 65 | # check if daemon not running 66 | if running "$APP_PID_FILE"; then 67 | printf "." 68 | else 69 | echo "failed" 70 | tail -n 100 "$NOHUP_OUT" 71 | exit 1 72 | fi 73 | timeout=`expr $timeout - 1` 74 | done 75 | CONFIRMED="min_lifetime" 76 | fi 77 | 78 | echo "OK" 79 | 80 | if [ -z $CONFIRMED ]; then 81 | echo "Please 'tail -f $NOHUP_OUT' for application output" 82 | fi 83 | ;; 84 | 85 | --exec) 86 | # best choice for running from systemd 87 | echo "Starting $NAME: ..." 88 | 89 | # some launcher frameworks manage the PID (this skips the check entirely) 90 | # only enable this env var if you know what you're doing 91 | if [ "$SKIP_PID_CHECK" = "0" ]; then 92 | verifyNotRunning $APP_PID_FILE 93 | fi 94 | 95 | # take pid of shell for pid lock 96 | echo $$ > $APP_PID_FILE 97 | 98 | # best effort to remove pid file upon exit via trap 99 | trap 'echo "Removing pid file $APP_PID_FILE"; rm -f "$APP_PID_FILE"' 2 3 6 15 100 | 101 | # shell will now become the java process :-) 102 | exec "$JAVA_EXE" -Dlauncher.name=$NAME -Dlauncher.type=$RUN_TYPE "-Dlauncher.app.dir=$APP_HOME" $JAVA_ARGS -classpath "$APP_JAVA_CLASSPATH" $MAIN_CLASS $APP_ARGS 103 | ;; 104 | 105 | --stop) 106 | printf "Stopping $NAME: " 107 | if running "$APP_PID_FILE"; then 108 | stopJavaApp "$APP_PID_FILE" 109 | echo "OK" 110 | else 111 | echo "not running" 112 | fi 113 | ;; 114 | 115 | --run) 116 | # some launcher frameworks manage the PID (this skips the check entirely) 117 | # only enable this env var if you know what you're doing 118 | if [ "$SKIP_PID_CHECK" = "0" ]; then 119 | verifyNotRunning $APP_PID_FILE 120 | fi 121 | 122 | # take pid of shell for pid lock 123 | echo $$ > $APP_PID_FILE 124 | 125 | # best effort to remove pid file upon exit via trap 126 | trap 'echo "Removing pid file $APP_PID_FILE"; rm -f "$APP_PID_FILE"' 2 3 6 15 127 | 128 | # eval will passthru SIGHUP and allows you to CTRL-C an app in foreground 129 | eval $RUN_CMD 130 | ;; 131 | 132 | --status) 133 | echo "Status for $NAME: " 134 | echo "app_home: $APP_HOME" 135 | echo "run_dir: $APP_RUN_DIR_DEBUG" 136 | echo "log_dir: $APP_LOG_DIR_DEBUG" 137 | echo "lib_dir: $APP_LIB_DIR_DEBUG" 138 | echo "pid_file: $APP_PID_FILE_DEBUG" 139 | echo "java_min_version_required: $MIN_JAVA_VERSION" 140 | echo "java_exe: $JAVA_EXE" 141 | echo "java_version: $JAVA_VERSION" 142 | echo "java_run: $RUN_CMD" 143 | echo 144 | if running "$APP_PID_FILE"; then 145 | echo "$NAME running with pid="`cat $APP_PID_FILE` 146 | exit 0 147 | else 148 | echo "$NAME not running" 149 | fi 150 | exit 1 151 | ;; 152 | 153 | *) 154 | usage 155 | ;; 156 | esac 157 | 158 | # 159 | # end of script 160 | # 161 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/script-java-detect-header.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Shell script to detect Java installed 5 | # 6 | # Auto generated by mfz-jtools-launcher. 7 | # Web: http://fizzed.com 8 | # Twitter: http://twitter.com/fizzed_inc 9 | # 10 | 11 | [ -z $LAUNCHER_DEBUG ] && LAUNCHER_DEBUG="0" 12 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/script-java-detect.sh: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # handle options 4 | # 5 | 6 | doAllJavaExecutables() 7 | { 8 | local all_java_bins=`findAllJavaExecutables` 9 | if [ -z "$all_java_bins" ]; then 10 | echo "No java executables found" 11 | exit 2 12 | else 13 | echo "$all_java_bins" 14 | fi 15 | } 16 | 17 | doFirstMinVersion() 18 | { 19 | local all_java_bins=`findAllJavaExecutables` 20 | local min_version="$1" 21 | if [ -z "$min_version" ]; then 22 | echo "parameter 2 required to be minimum java version (e.g. 1.7)" 23 | exit 1 24 | fi 25 | 26 | local java_bin=`findFirstJavaExecutableByMinimumMajorVersion "$all_java_bins" "$min_version"` 27 | if [ -z "$java_bin" ]; then 28 | if [ ! -z "$all_java_bins" ]; then 29 | echo "Java executables found but all < $min_version" 30 | exit 3 31 | else 32 | echo "No java executables found" 33 | exit 2 34 | fi 35 | else 36 | echo "$java_bin" 37 | fi 38 | } 39 | 40 | doLatestMajorVersion() 41 | { 42 | local all_java_bins=`findAllJavaExecutables` 43 | local java_bin=`findLatestJavaExecutableByMajorVersion "$all_java_bins"` 44 | if [ -z "$java_bin" ]; then 45 | echo "No java executables found" 46 | exit 2 47 | else 48 | echo "$java_bin" 49 | fi 50 | } 51 | 52 | doLatestMajorVersionNumber() 53 | { 54 | local java_bin=`doLatestMajorVersion` 55 | if [ -z "$java_bin" ]; then 56 | echo "No java executables found" 57 | exit 100 58 | else 59 | logJavaSearchDebug "found latest major java version, getting version from: $java_bin" 60 | java_ver=`getJavaVersion "$java_bin"` 61 | logJavaSearchDebug "extracting major version num from: $java_ver" 62 | java_maj_ver=`parseJavaMajorVersion "$java_ver"` 63 | echo $java_maj_ver 64 | exit $java_maj_ver 65 | fi 66 | } 67 | 68 | case "$1" in 69 | 70 | "--all-java-executables") 71 | doAllJavaExecutables 72 | ;; 73 | 74 | "--first-min-version") 75 | doFirstMinVersion $2 76 | ;; 77 | 78 | "--latest-major-version") 79 | doLatestMajorVersion 80 | ;; 81 | 82 | "--latest-major-version-number") 83 | doLatestMajorVersionNumber 84 | ;; 85 | 86 | *) 87 | echo "Usage: `basename $0` [command] [optional args per command]" >&2 88 | echo "Commands:" >&2 89 | echo " --all-java-executables" >&2 90 | echo " --first-min-version" >&2 91 | echo " --latest-major-version" >&2 92 | echo " --latest-major-version-number" >&2 93 | #echo " --all-java-executables Prints colon delimited list of" >&2 94 | #echo " all javas on system" >&2 95 | #echo " --first-min-version [min-version] " >&2 96 | exit 1 97 | ;; 98 | 99 | esac 100 | 101 | exit 0 -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/systemd-daemon.ftl: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=${config.shortDescription} 3 | After=network.target 4 | 5 | [Service] 6 | EnvironmentFile=/etc/default/${config.name} 7 | ExecStart=${config.getPlatformPrefixDir("LINUX")}/${config.name}/bin/${config.name} --exec 8 | ExecStop=${config.getPlatformPrefixDir("LINUX")}/${config.name}/bin/${config.name} --stop 9 | PIDFile=${config.getPlatformPrefixDir("LINUX")}/${config.name}/run/${config.name}.pid 10 | KillMode=process 11 | Restart=on-failure 12 | User=${config.getPlatformUser("LINUX")!""} 13 | Group=${config.getPlatformGroup("LINUX")!""} 14 | ${config.getSystemdServiceSection()!""} 15 | 16 | [Install] 17 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/test-function.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | . $(dirname $0)/script-functions.sh 4 | 5 | # test quietWhich 6 | sh_bin=`quietWhich "sh"` 7 | echo "location of sh: $sh_bin" 8 | 9 | blah_bin=`quietWhich "doesnotexist"` 10 | echo "location of something that does not exist: $blah_bin" 11 | 12 | echo "finding all java binaries on system..." 13 | java_cmds=`findJavaCommands` 14 | echo "all java cmds: $java_cmds" 15 | 16 | java_min_version="1.8" 17 | extracted_min_version=`extractPrimaryJavaVersion "$java_min_version"` 18 | echo "extracted min version from $java_min_version: $extracted_min_version" 19 | 20 | echo "finding all java binaries on system that are min $java_min_version..." 21 | java_bin=`findMinJavaVersion "$java_min_version" "$java_cmds"` 22 | 23 | if [ -z "$java_bin" ]; then 24 | echo "Unable to find Java runtime version >= $java_min_version" 25 | exit 1 26 | fi 27 | 28 | echo "found java: $java_bin" 29 | 30 | plat=`platform` 31 | echo "platform: $plat" 32 | 33 | system_memory=`systemMemory` 34 | echo "system_memory: $system_memory" 35 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/test-java-detect.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | . $(dirname $0)/script-java-detect-header.sh 4 | . $(dirname $0)/script-functions.sh 5 | 6 | all_java_bins=`findAllJavaExecutables` 7 | echo "all_java_bins: $all_java_bins" 8 | 9 | java_bin_6=`findFirstJavaExecutableByMinimumMajorVersion "$all_java_bins" "1.6"` 10 | echo "java_bin_6: $java_bin_6" 11 | 12 | java_bin_7=`findFirstJavaExecutableByMinimumMajorVersion "$all_java_bins" "1.7"` 13 | echo "java_bin_7: $java_bin_7" 14 | 15 | java_bin_8=`findFirstJavaExecutableByMinimumMajorVersion "$all_java_bins" "1.8"` 16 | echo "java_bin_8: $java_bin_8" 17 | 18 | java_bin_latest_maj=`findLatestJavaExecutableByMajorVersion "$all_java_bins"` 19 | echo "java_bin_latest_maj: $java_bin_latest_maj" 20 | 21 | java_bin_9=`findFirstJavaExecutableByMinimumMajorVersion "$all_java_bins" "9.0"` 22 | echo "java_bin_9: $java_bin_9" 23 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/linux/test-loop.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | paths="/usr:/usr/local" 4 | 5 | IFS=":"; for p in $paths; do 6 | IFS=":"; for b in "$p/*"; do 7 | echo "path: $p" 8 | done 9 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/osx/launchd.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Label${config.domain}.${config.name} 6 | KeepAlive 7 | RunAtLoad 8 | WorkingDirectory/Users/Shared/${config.displayName} 9 | Disabled 10 | LaunchOnlyOnce 11 | UserName${config.getPlatformUser("MAC_OSX")!""} 12 | GroupName${config.getPlatformUser("MAC_OSX")!""} 13 | EnvironmentVariables 14 | 15 | LAUNCHER_DEBUG 16 | 1 17 | SKIP_PID_CHECK 18 | 1 19 | 20 | 21 | StandardOutPathlog/${config.name}.stdout 22 | StandardErrorPathlog/${config.name}.stderr 23 | ProgramArguments 24 | 25 | bin/${config.name} 26 | --run 27 | 28 | 29 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/batch-console.ftl: -------------------------------------------------------------------------------- 1 | 2 | if "%LAUNCHER_DEBUG%"=="1" ( 3 | @ECHO ON 4 | ) 5 | 6 | "%java_bin_accepted%" -Dlauncher.name=%NAME% -Dlauncher.type=%RUN_TYPE% "-Dlauncher.app.dir=%APP_HOME%"m -cp "%APP_CLASSPATH%" %JAVA_ARGS% %MAIN_CLASS% %APP_ARGS% 7 | 8 | @ECHO OFF 9 | 10 | if %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% 11 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/batch-daemon-jslwin.ftl: -------------------------------------------------------------------------------- 1 | 2 | @REM 3 | @REM usage with no parameters? 4 | @REM 5 | 6 | IF %1.==. GOTO PrintUsageJSLWin 7 | 8 | @REM 9 | @REM log directory MUST MUST MUST exist or the service will fail to start 10 | @REM 11 | 12 | if not exist "%APP_LOG_DIR%" ( 13 | mkdir "%APP_LOG_DIR%" 14 | ) 15 | 16 | @REM 17 | @REM execute argument command 18 | @REM 19 | 20 | if %bit64%==n set TargetExe=${config.name}32.exe 21 | if %bit64%==y set TargetExe=${config.name}64.exe 22 | 23 | @REM 24 | @REM pop first app argument off so we can see what the user wants to do 25 | @REM 26 | set ARG= 27 | for /F "tokens=1*" %%a in ("%APP_ARGS%") do ( 28 | set ARG=%%a 29 | set APP_ARGS=%%b 30 | ) 31 | 32 | IF "%ARG%"=="--run" ( 33 | "%java_bin_accepted%" -Dlauncher.name=%NAME% -Dlauncher.type=CONSOLE "-Dlauncher.app.dir=%APP_HOME%" -cp "%APP_CLASSPATH%" %JAVA_ARGS% %MAIN_CLASS% %APP_ARGS% 34 | ) ELSE IF "%ARG%"=="--startdebug" ( 35 | "%APP_BIN_DIR%\%TargetExe%" -debug 36 | ) ELSE IF "%ARG%"=="--start" ( 37 | net start "${config.displayName}" 38 | ) ELSE IF "%ARG%"=="--stop" ( 39 | net stop "${config.displayName}" 40 | ) ELSE IF "%ARG%"=="--install" ( 41 | "%APP_BIN_DIR%\%TargetExe%" -install 42 | ) ELSE IF "%ARG%"=="--uninstall" ( 43 | "%APP_BIN_DIR%\%TargetExe%" -remove 44 | ) ELSE ( 45 | echo Error unsupported argument 46 | GOTO PrintUsageJSLWin 47 | ) 48 | 49 | GOTO endLabel 50 | 51 | :PrintUsageJSLWin 52 | REM annoying string escaping 53 | echo Usage: ^[^-^-^r^u^n^|^-^-^s^t^a^r^t^|^-^-^s^t^o^p^|^-^-^ins^tall^|^-^-^un^inst^a^ll^|^-^-^s^t^a^r^t^d^eb^u^g] 54 | goto :errorlabel 55 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/batch-footer.ftl: -------------------------------------------------------------------------------- 1 | :endLabel 2 | goto :eof 3 | 4 | :errorlabel 5 | setlocal 6 | SET error_code=%~1 7 | IF "%error_code%" NEQ "" EXIT /B %error_code 8 | Exit /B %ERRORLEVEL% 9 | goto :eof 10 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/batch-header.ftl: -------------------------------------------------------------------------------- 1 | @setlocal ENABLEDELAYEDEXPANSION 2 | @echo OFF 3 | 4 | @REM 5 | @REM Batch script to launch Java app ${config.name} 6 | @REM 7 | @REM Description: ${config.shortDescription} 8 | @REM 9 | @REM Auto generated via Stork Launcher v${version} made by Fizzed, Inc. 10 | @REM Web: http://fizzed.com 11 | @REM Twitter: http://twitter.com/fizzed_inc 12 | @REM Github: https://github.com/fizzed/stork 13 | @REM 14 | 15 | @REM 16 | @REM working directory setup 17 | @REM 18 | 19 | set INITIAL_WORKING_DIR=%CD% 20 | 21 | SET SCRIPTPATH=%~dp0 22 | SET SCRIPTPATH=%SCRIPTPATH:~0,-1% 23 | set APP_HOME_REL=%SCRIPTPATH%\.. 24 | @REM echo app_home_relative %APP_HOME_REL% 25 | 26 | @REM 27 | @REM constants 28 | @REM 29 | 30 | @REM set to 1 if you want to see more info about what the script is doing 31 | if "%LAUNCHER_DEBUG%"=="" set LAUNCHER_DEBUG=0 32 | 33 | set NAME=${config.name} 34 | set TYPE=${config.type} 35 | set MAIN_CLASS=${config.mainClass} 36 | if "%MIN_JAVA_VERSION%"=="" set MIN_JAVA_VERSION=${config.minJavaVersion} 37 | if "%MAX_JAVA_VERSION%"=="" set MAX_JAVA_VERSION=${config.maxJavaVersion!"0"} 38 | if "%WORKING_DIR_MODE%"=="" set WORKING_DIR_MODE=${config.workingDirMode} 39 | if "%INCLUDE_JAVA_XRS%"=="" set INCLUDE_JAVA_XRS=${config.includeJavaXrs?string("1", "0")} 40 | 41 | @REM echo temporarily change working directory to get good abs path for home 42 | pushd %APP_HOME_REL% 43 | set APP_HOME=!CD! 44 | 45 | if %WORKING_DIR_MODE%==RETAIN ( 46 | popd 47 | ) 48 | 49 | @REM 50 | @REM settings 51 | @REM 52 | 53 | if "%LOG_DIR%"=="" set LOG_DIR=${config.logDir!""} 54 | if "%RUN_DIR%"=="" set RUN_DIR=${config.runDir!""} 55 | if "%BIN_DIR%"=="" set BIN_DIR=${config.binDir!""} 56 | if "%LIB_DIR%"=="" set LIB_DIR=${config.libDir!""} 57 | if "%APP_ARGS%"=="" set APP_ARGS=${config.appArgs} 58 | if "%EXTRA_APP_ARGS%"=="" set EXTRA_APP_ARGS=${config.extraAppArgs} 59 | if "%JAVA_ARGS%"=="" set JAVA_ARGS=${config.javaArgs} 60 | if "%EXTRA_JAVA_ARGS%"=="" set EXTRA_JAVA_ARGS=${config.extraJavaArgs} 61 | 62 | @REM setup remaining directories 63 | set APP_BIN_DIR=%APP_HOME%\%BIN_DIR% 64 | set APP_LOG_DIR=%APP_HOME%\%LOG_DIR% 65 | set APP_LIB_DIR=%APP_HOME%\%LIB_DIR% 66 | set APP_RUN_DIR=%APP_HOME%\%RUN_DIR% 67 | 68 | if "%LAUNCHER_DEBUG%"=="1" ( 69 | echo ^[LAUNCHER^] working_dir: %CD% 70 | echo ^[LAUNCHER^] app_home: %APP_HOME% 71 | echo ^[LAUNCHER^] app_bin: %APP_BIN_DIR% 72 | echo ^[LAUNCHER^] app_log: %APP_LOG_DIR% 73 | echo ^[LAUNCHER^] app_lib: %APP_LIB_DIR% 74 | echo ^[LAUNCHER^] app_run: %APP_RUN_DIR% 75 | ) 76 | 77 | set bit64=n 78 | if /I %Processor_Architecture%==AMD64 set bit64=y 79 | if /I "%PROCESSOR_ARCHITEW6432%"=="AMD64" set bit64=y 80 | @REM echo bit64: %bit64% 81 | 82 | @REM CONSOLE or DAEMON (so we can pass it thru as a system property) 83 | set RUN_TYPE=%TYPE% 84 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/batch-java.ftl: -------------------------------------------------------------------------------- 1 | 2 | @REM Bug with Java7 <= build 8 on wildcard classpath expansion 3 | @REM easy solution is to append a semi-colon at end onto classpath 4 | @REM http://stackoverflow.com/questions/9195073/broken-wildcard-expansion-for-java7-commandline-on-windows7 5 | set APP_CLASSPATH=%APP_LIB_DIR%\*; 6 | 7 | if "%LAUNCHER_DEBUG%"=="1" ( 8 | echo ^[LAUNCHER^] java_classpath: %APP_CLASSPATH% 9 | echo ^[LAUNCHER^] java_bin: "%java_bin_accepted%" 10 | ) 11 | 12 | @REM append extra app and java args? 13 | 14 | if NOT "%EXTRA_JAVA_ARGS%"=="" ( 15 | set JAVA_ARGS=%JAVA_ARGS% %EXTRA_JAVA_ARGS% 16 | ) 17 | 18 | if NOT "%EXTRA_APP_ARGS%"=="" ( 19 | set APP_ARGS=%APP_ARGS% %EXTRA_APP_ARGS% 20 | ) 21 | 22 | @REM 23 | @REM Process arguments into either app or java system property 24 | @REM With recursion used the various labels help prevent multiple executions 25 | @REM 26 | call :ProcessArgs %* 27 | goto :ProcessedArgs 28 | 29 | :ProcessArgs 30 | for /F "tokens=1*" %%a in ("%*") do ( 31 | set arg=%%a 32 | 33 | @REM quoted? 34 | IF !arg:~0^,1!!arg:~-1! equ "" ( 35 | IF "!arg:~1,3!"=="-D" ( 36 | set JAVA_ARGS=%JAVA_ARGS% !arg! 37 | ) ELSE ( 38 | set APP_ARGS=%APP_ARGS% !arg! 39 | ) 40 | ) ELSE ( 41 | IF "!arg:~0,2!"=="-D" ( 42 | set JAVA_ARGS=%JAVA_ARGS% !arg! 43 | ) ELSE ( 44 | set APP_ARGS=%APP_ARGS% !arg! 45 | ) 46 | ) 47 | 48 | if NOT x%%b==x call :ProcessArgs %%b 49 | ) 50 | goto :eof 51 | :ProcessedArgs 52 | 53 | @REM 54 | @REM prepend -Xrs flag? 55 | @REM 56 | if "%INCLUDE_JAVA_XRS%"=="1" ( 57 | set JAVA_ARGS=-Xrs %JAVA_ARGS% 58 | ) 59 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/config-daemon-winsw.ftl: -------------------------------------------------------------------------------- 1 | 2 | ${config.name} 3 | ${config.displayName} 4 | ${config.shortDescription} 5 | java 6 | -cp %BASE%\..\lib\* ${config.javaArgs} ${config.mainClass} ${config.appArgs} 7 | rotate 8 | %BASE%\..\${config.logDir} 9 | 10 | %BASE%\.. 11 | -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl.exe -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl.jar -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl64.exe -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl64_debug.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl64_debug.exe -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl_debug.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/jslwin/jsl_debug.exe -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/winsw/winsw-1.16-bin.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fizzed/stork/fcf82d42d0ab0f18a3a9c4fd07394a2f7a1be672/stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/winsw/winsw-1.16-bin.exe -------------------------------------------------------------------------------- /stork-launcher/src/main/resources/com/fizzed/stork/launcher/windows/winsw/winsw.exe.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /stork-launcher/src/test/java/com/fizzed/stork/launcher/TestHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.launcher; 17 | 18 | import com.fizzed.crux.vagrant.VagrantClient; 19 | import com.fizzed.crux.vagrant.VagrantClients; 20 | import java.nio.file.Path; 21 | import java.util.Arrays; 22 | import java.util.List; 23 | 24 | public class TestHelper { 25 | 26 | static public final VagrantClient VAGRANT_CLIENT = VagrantClients.cachingOrEmptyClient(); 27 | 28 | static public List hosts() { 29 | String host = System.getProperty("host"); 30 | if (host != null && !host.equals("")) { 31 | return Arrays.asList(host); 32 | } else { 33 | return Arrays.asList("local", "ubuntu14", "ubuntu16", "ubuntu20", "windows10", "debian8", "centos7", "freebsd10", "openbsd60"); 34 | } 35 | } 36 | 37 | static public boolean isWindows() { 38 | return System.getProperty("os.name").toLowerCase().contains("win"); 39 | } 40 | 41 | static public Path which(Path path, String name) { 42 | if (isWindows()) { 43 | return path.resolve(name + ".bat"); 44 | } else { 45 | return path.resolve(name); 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /stork-launcher/src/test/launchers/cat.yml: -------------------------------------------------------------------------------- 1 | name: "cat" 2 | domain: "com.fizzed.stork.test" 3 | display_name: "copy file to stdout" 4 | short_description: "cat file to stdout" 5 | type: CONSOLE 6 | main_class: "com.fizzed.stork.test.CatMain" 7 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 8 | working_dir_mode: APP_HOME 9 | min_java_version: "1.7" 10 | min_java_memory: 32 11 | max_java_memory: 64 12 | symlink_java: false -------------------------------------------------------------------------------- /stork-launcher/src/test/launchers/echo-console1.yml: -------------------------------------------------------------------------------- 1 | name: "echo-console1" 2 | domain: "com.fizzed.stork.test" 3 | display_name: "Echo Console 1" 4 | short_description: "Unit Testing: should work" 5 | type: CONSOLE 6 | main_class: "com.fizzed.stork.test.EchoConsoleMain" 7 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 8 | working_dir_mode: RETAIN 9 | min_java_version: "1.6" 10 | max_java_version: "30" 11 | min_java_memory: 32 12 | max_java_memory: 64 13 | symlink_java: false -------------------------------------------------------------------------------- /stork-launcher/src/test/launchers/echo-console2.yml: -------------------------------------------------------------------------------- 1 | name: "echo-console2" 2 | domain: "com.fizzed.stork.test" 3 | display_name: "Echo Console 2" 4 | short_description: "Unit Testing: main class will not be found" 5 | type: CONSOLE 6 | main_class: "com.fizzed.stork.test.ClassNotFoundMain" 7 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 8 | working_dir_mode: RETAIN 9 | min_java_version: "1.6" 10 | min_java_memory: 32 11 | max_java_memory: 64 12 | symlink_java: false -------------------------------------------------------------------------------- /stork-launcher/src/test/launchers/echo-console3.yml: -------------------------------------------------------------------------------- 1 | name: "echo-console3" 2 | domain: "com.fizzed.stork.test" 3 | display_name: "Echo Console 3" 4 | short_description: "Unit Testing: JVM 1.10 does not exist" 5 | type: CONSOLE 6 | main_class: "com.fizzed.stork.test.HelloMain" 7 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 8 | working_dir_mode: RETAIN 9 | min_java_version: "1.99" 10 | min_java_memory: 32 11 | max_java_memory: 64 12 | symlink_java: false -------------------------------------------------------------------------------- /stork-launcher/src/test/launchers/echo-daemon1.yml: -------------------------------------------------------------------------------- 1 | name: "echo-daemon1" 2 | domain: "com.fizzed.stork.test" 3 | display_name: "Echo Daemon 1" 4 | short_description: "Unit Testing: console app treated as daemon" 5 | type: DAEMON 6 | main_class: "com.fizzed.stork.test.EchoConsoleMain" 7 | platforms: [ WINDOWS, LINUX, MAC_OSX ] 8 | working_dir_mode: APP_HOME 9 | min_java_version: "1.6" 10 | min_java_memory: 32 11 | max_java_memory: 64 12 | symlink_java: false 13 | java_args: "-Xrs" -------------------------------------------------------------------------------- /stork-maven-plugin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.fizzed 5 | stork-maven-plugin 6 | maven-plugin 7 | stork-maven-plugin 8 | Maven plugin for Stork utilities 9 | 10 | 11 | com.fizzed 12 | stork 13 | 3.2.1-SNAPSHOT 14 | 15 | 16 | 17 | com.fizzed.stork.maven 18 | 3.1.1 19 | 20 | 21 | 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-plugin-plugin 26 | 3.6.0 27 | 28 | 29 | default-descriptor 30 | process-classes 31 | 32 | descriptor 33 | 34 | 35 | 36 | help-descriptor 37 | process-classes 38 | 39 | helpmojo 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | com.fizzed 52 | stork-launcher 53 | 54 | 55 | 56 | com.fizzed 57 | stork-assembly 58 | 59 | 60 | 61 | org.apache.maven 62 | maven-core 63 | ${maven.version} 64 | 65 | 66 | 67 | org.apache.maven 68 | maven-plugin-api 69 | ${maven.version} 70 | 71 | 72 | 73 | org.apache.maven.plugin-tools 74 | maven-plugin-annotations 75 | 3.6.0 76 | provided 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /stork-maven-plugin/src/main/java/com/fizzed/stork/maven/LauncherMojo.java: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.maven; 2 | 3 | import com.fizzed.stork.core.ArgumentException; 4 | import com.fizzed.stork.launcher.Configuration; 5 | import com.fizzed.stork.launcher.ConfigurationFactory; 6 | import com.fizzed.stork.launcher.FileUtil; 7 | import com.fizzed.stork.launcher.Generator; 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | import org.apache.maven.plugin.AbstractMojo; 13 | import org.apache.maven.plugin.MojoExecutionException; 14 | import org.apache.maven.plugin.MojoFailureException; 15 | import org.apache.maven.plugins.annotations.LifecyclePhase; 16 | import org.apache.maven.plugins.annotations.Mojo; 17 | import org.apache.maven.plugins.annotations.Parameter; 18 | import org.apache.maven.project.MavenProject; 19 | 20 | /** 21 | * Maven plugin akin to the "stork-launcher" command-line app but 22 | * directly accesses Java library (negating local install requirements). 23 | * 24 | * @author joelauer 25 | */ 26 | @Mojo(name = "launcher", 27 | defaultPhase = LifecyclePhase.PACKAGE, 28 | threadSafe = true 29 | ) 30 | public class LauncherMojo extends AbstractMojo { 31 | 32 | /** 33 | * Directory to output generated launchers. 34 | * 35 | * @since 1.2.0 36 | */ 37 | @Parameter(property = "outputDirectory", defaultValue = "${project.build.directory}/stork", required = true) 38 | protected File outputDirectory; 39 | 40 | /** 41 | * One or more input directories/files to generate. 42 | * 43 | * @since 1.2.0 44 | */ 45 | @Parameter(property = "inputFiles", defaultValue = "${basedir}/src/main/launchers") 46 | protected String[] inputFiles; 47 | 48 | @Parameter( defaultValue = "${project}", readonly = true ) 49 | protected MavenProject project; 50 | 51 | @Override 52 | public void execute() throws MojoExecutionException, MojoFailureException { 53 | if (this.outputDirectory == null || this.outputDirectory.equals("")) { 54 | getLog().info("Skipping (outputDirectory is empty)"); 55 | return; 56 | } 57 | 58 | try { 59 | List configFiles = FileUtil.findAllFiles(Arrays.asList(inputFiles), true); 60 | List configs = new ConfigurationFactory().read(configFiles); 61 | int generated = new Generator().generate(configs, outputDirectory); 62 | getLog().info("Created " + generated + " launchers"); 63 | } catch (ArgumentException | IOException e) { 64 | throw new MojoExecutionException(e.getMessage(), e); 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /stork-maven-plugin/src/main/java/com/fizzed/stork/maven/MergeMojo.java: -------------------------------------------------------------------------------- 1 | package com.fizzed.stork.maven; 2 | 3 | import com.fizzed.stork.launcher.Merger; 4 | import java.io.File; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import org.apache.maven.plugin.AbstractMojo; 8 | import org.apache.maven.plugin.MojoExecutionException; 9 | import org.apache.maven.plugin.MojoFailureException; 10 | import org.apache.maven.plugins.annotations.LifecyclePhase; 11 | import org.apache.maven.plugins.annotations.Mojo; 12 | import org.apache.maven.plugins.annotations.Parameter; 13 | import org.apache.maven.project.MavenProject; 14 | 15 | /** 16 | * Maven plugin akin to the "stork-merge" command-line app but 17 | * directly accesses Java library (negating local install requirements). 18 | * 19 | * @author joelauer 20 | */ 21 | @Mojo(name = "merge", 22 | defaultPhase = LifecyclePhase.PACKAGE, 23 | threadSafe = true 24 | ) 25 | public class MergeMojo extends AbstractMojo { 26 | 27 | /** 28 | * One or more input directories/files to merge (order is important). 29 | * 30 | * @since 1.2.0 31 | */ 32 | @Parameter(property = "inputFiles", required = true) 33 | protected String[] inputFiles; 34 | 35 | /** 36 | * Directory to output generated files. 37 | * 38 | * @since 1.2.0 39 | */ 40 | @Parameter(property = "outputFile", required = true) 41 | protected File outputFile; 42 | 43 | @Parameter( defaultValue = "${project}", readonly = true ) 44 | protected MavenProject project; 45 | 46 | @Override 47 | public void execute() throws MojoExecutionException, MojoFailureException { 48 | if (this.outputFile == null || this.outputFile.equals("")) { 49 | getLog().info("Skipping (outputFile is empty)"); 50 | return; 51 | } 52 | 53 | List files = new ArrayList<>(); 54 | for (String f : inputFiles) { 55 | files.add(new File(f)); 56 | } 57 | 58 | try { 59 | Merger.merge(files, outputFile); 60 | } catch (Exception e) { 61 | throw new MojoExecutionException(e.getMessage(), e); 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /stork-test-app/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.fizzed 5 | stork-test-app 6 | jar 7 | stork-test-app 8 | 9 | 10 | com.fizzed 11 | stork 12 | 3.2.1-SNAPSHOT 13 | 14 | 15 | 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-dependency-plugin 26 | 3.6.0 27 | 28 | 29 | copy-dependencies 30 | compile 31 | 32 | copy-dependencies 33 | 34 | 35 | true 36 | ${project.build.directory}/stork/lib 37 | true 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-jar-plugin 45 | 3.4.1 46 | 47 | 48 | compile 49 | 50 | jar 51 | 52 | 53 | com.fizzed.stork-test-app-${project.version} 54 | ${project.build.directory}/stork/lib 55 | dummy 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | com.fasterxml.jackson.core 68 | jackson-core 69 | 70 | 71 | 72 | com.fasterxml.jackson.core 73 | jackson-databind 74 | 75 | 76 | 77 | io.netty 78 | netty-codec-http 79 | 4.0.23.Final 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /stork-test-app/src/main/java/com/fizzed/stork/test/Arguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.test; 17 | 18 | import java.nio.file.Path; 19 | import java.nio.file.Paths; 20 | 21 | public class Arguments { 22 | 23 | private Path dataFile; 24 | 25 | public Arguments(String[] args) { 26 | for (int i = 0; i < args.length; i++) { 27 | String arg = args[i]; 28 | if (arg.equals("--data-file")) { 29 | i++; 30 | if (args.length <= i) { 31 | throw new IllegalArgumentException("--data-file requires an argument after it"); 32 | } 33 | this.dataFile = Paths.get(args[i]); 34 | } 35 | } 36 | } 37 | 38 | public Path getDataFile() { 39 | return dataFile; 40 | } 41 | 42 | public void setDataFile(Path dataFile) { 43 | this.dataFile = dataFile; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /stork-test-app/src/main/java/com/fizzed/stork/test/CatMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.test; 17 | 18 | import java.nio.file.Files; 19 | import java.nio.file.Path; 20 | import java.nio.file.Paths; 21 | 22 | public class CatMain { 23 | 24 | static public void main(String[] args) throws Exception { 25 | Path path = Paths.get(args[0]); 26 | Files.copy(path, System.out); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /stork-test-app/src/main/java/com/fizzed/stork/test/EchoConsoleMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.test; 17 | 18 | public class EchoConsoleMain { 19 | 20 | static public void main(String[] args) throws Exception { 21 | Arguments arguments = new Arguments(args); 22 | LaunchData launchData = LaunchData.create(args); 23 | LaunchData.prettyWrite(launchData, arguments); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /stork-test-app/src/main/java/com/fizzed/stork/test/LaunchData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Fizzed, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fizzed.stork.test; 17 | 18 | import com.fasterxml.jackson.databind.ObjectMapper; 19 | import com.fasterxml.jackson.databind.SerializationFeature; 20 | import java.io.IOException; 21 | import java.io.OutputStream; 22 | import java.lang.management.ManagementFactory; 23 | import java.lang.management.RuntimeMXBean; 24 | import java.nio.file.Files; 25 | import java.util.Arrays; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | 30 | public class LaunchData { 31 | 32 | private String confirm; 33 | private Map environment; 34 | private Map systemProperties; 35 | private List jvmArguments; 36 | private List arguments; 37 | 38 | public String getConfirm() { 39 | return confirm; 40 | } 41 | 42 | public void setConfirm(String confirm) { 43 | this.confirm = confirm; 44 | } 45 | 46 | public Map getEnvironment() { 47 | return environment; 48 | } 49 | 50 | public void setEnvironment(Map environment) { 51 | this.environment = environment; 52 | } 53 | 54 | public Map getSystemProperties() { 55 | return systemProperties; 56 | } 57 | 58 | public void setSystemProperties(Map systemProperties) { 59 | this.systemProperties = systemProperties; 60 | } 61 | 62 | public List getJvmArguments() { 63 | return jvmArguments; 64 | } 65 | 66 | public void setJvmArguments(List jvmArguments) { 67 | this.jvmArguments = jvmArguments; 68 | } 69 | 70 | public List getArguments() { 71 | return arguments; 72 | } 73 | 74 | public void setArguments(List arguments) { 75 | this.arguments = arguments; 76 | } 77 | 78 | static public final ObjectMapper OBJECT_MAPPER = new ObjectMapper() 79 | .configure(SerializationFeature.INDENT_OUTPUT, true); 80 | 81 | static public LaunchData parse(String json) throws IOException { 82 | return OBJECT_MAPPER.readValue(json, LaunchData.class); 83 | } 84 | 85 | static public LaunchData create(String[] args) { 86 | ObjectMapper mapper = new ObjectMapper(); 87 | mapper.configure(SerializationFeature.INDENT_OUTPUT, true); 88 | 89 | RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); 90 | List jvmArguments = runtimeMxBean.getInputArguments(); 91 | 92 | // convert system properties to a map 93 | Map systemProperties = new HashMap<>(); 94 | for (Map.Entry entry : System.getProperties().entrySet()) { 95 | systemProperties.put(entry.getKey().toString(), entry.getValue().toString()); 96 | } 97 | 98 | LaunchData data = new LaunchData(); 99 | data.setConfirm("Hello World!"); 100 | data.setEnvironment(System.getenv()); 101 | data.setSystemProperties(systemProperties); 102 | data.setJvmArguments(jvmArguments); 103 | data.setArguments(Arrays.asList(args)); 104 | 105 | return data; 106 | } 107 | 108 | static public String prettyJson(LaunchData output) throws IOException { 109 | return OBJECT_MAPPER.writeValueAsString(output); 110 | } 111 | 112 | static public void prettyWrite(LaunchData output, OutputStream os) throws IOException { 113 | OBJECT_MAPPER.writeValue(os, output); 114 | } 115 | 116 | static public void prettyWrite(LaunchData output, Arguments arguments) throws IOException { 117 | if (arguments.getDataFile() == null) { 118 | LaunchData.prettyWrite(output, System.out); 119 | } else { 120 | try (OutputStream os = Files.newOutputStream(arguments.getDataFile())) { 121 | LaunchData.prettyWrite(output, os); 122 | System.out.println("Wrote launch data to " + arguments.getDataFile()); 123 | } 124 | } 125 | } 126 | 127 | } 128 | --------------------------------------------------------------------------------