├── docs ├── .nojekyll ├── assets │ ├── js │ │ ├── 55960ee5.72573837.js │ │ ├── a2762952.6bf692cf.js │ │ ├── 65664f72.2e7a62fc.js │ │ ├── 34a804db.93cce336.js │ │ ├── 15bd92de.6623578a.js │ │ ├── 814f3328.db8f94e4.js │ │ ├── a22865bc.9bd4aa3d.js │ │ ├── common.982779c9.js.LICENSE.txt │ │ ├── 763fcd15.95a8f898.js │ │ ├── 75.8fe7757f.js │ │ ├── 935f2afb.11666b9e.js │ │ ├── 0e384e19.61658283.js │ │ ├── main.6f20bb18.js.LICENSE.txt │ │ ├── 3720c009.46d24c30.js │ │ ├── 9e4087bc.e0a9a0f2.js │ │ ├── 508a7d2f.43c89018.js │ │ ├── 1d48e3ab.8ff3c9fc.js │ │ ├── 74c14969.f1b0f9db.js │ │ ├── 0aa62002.6e47bd2d.js │ │ ├── 01a85c17.201a70b5.js │ │ ├── 54f44165.5cf5c70a.js │ │ └── runtime~main.48a448b1.js │ └── images │ │ └── vmware-test-case-flow-5b80eaa38ddb8f6d28abf2aa5f5295bd.jpg ├── img │ ├── 3.svg │ ├── 2.svg │ └── 1.svg ├── blog │ ├── rss.xml │ └── atom.xml ├── sitemap.xml ├── docs │ └── tags │ │ └── index.html └── 404.html ├── documentation ├── static │ ├── .nojekyll │ └── img │ │ ├── 3.svg │ │ ├── 2.svg │ │ └── 1.svg ├── docs │ ├── getting-started │ │ ├── _category_.json │ │ ├── examples.md │ │ ├── development.md │ │ ├── features.md │ │ ├── docker.md │ │ ├── installation.md │ │ └── libvirt.md │ └── intro.md ├── sidebars.js ├── babel.config.js ├── blog │ ├── pics │ │ └── vmware │ │ │ └── vmware-test-case-flow.jpg │ └── 2021-09-15-how-to-run-integration-tests-against-vmware.md ├── src │ ├── components │ │ ├── HomepageFeatures.module.css │ │ └── HomepageFeatures.js │ ├── pages │ │ ├── index.module.css │ │ └── index.js │ └── css │ │ └── custom.css ├── .gitignore ├── package.json └── docusaurus.config.js ├── src ├── test │ ├── resources │ │ ├── copyFilesTest │ │ │ ├── 1 │ │ │ │ └── file │ │ │ └── 2 │ │ │ │ ├── sub │ │ │ │ └── file3 │ │ │ │ └── file2 │ │ ├── dir-without-conf │ │ │ └── no-config-here │ │ ├── with space │ │ │ └── test.conf │ │ ├── property-path │ │ │ └── overcast.conf │ │ ├── fake-home │ │ │ └── .overcast │ │ │ │ └── overcast.conf │ │ ├── overcast.conf │ │ ├── logback-test.xml │ │ └── libvirt-xml │ │ │ ├── simple-domain.xml │ │ │ └── domain-with-filesystem.xml │ └── java │ │ └── com │ │ └── xebialabs │ │ └── overcast │ │ ├── host │ │ └── DockerHostTest.java │ │ ├── command │ │ └── CommandProcessorTest.java │ │ ├── support │ │ ├── libvirt │ │ │ └── jdom │ │ │ │ ├── DomainXmlTest.java │ │ │ │ └── FilesystemXmlTest.java │ │ ├── virtualbox │ │ │ └── VirtualboxStateTest.java │ │ └── vagrant │ │ │ ├── VagrantStateTest.java │ │ │ └── VagrantCloudHostTest.java │ │ ├── PropertiesLoaderTest.java │ │ └── OverthereUtilTest.java └── main │ └── java │ └── com │ └── xebialabs │ └── overcast │ ├── Strings.java │ ├── support │ ├── libvirt │ │ ├── IpNotFoundException.java │ │ ├── IpLookupException.java │ │ ├── IpLookupStrategy.java │ │ ├── LibvirtRuntimeException.java │ │ ├── LoggingOutputHandler.java │ │ ├── StaticIpLookupStrategy.java │ │ ├── jdom │ │ │ ├── DomainXml.java │ │ │ ├── InterfaceXml.java │ │ │ └── FilesystemXml.java │ │ ├── Filesystem.java │ │ ├── JDomUtil.java │ │ ├── Disk.java │ │ └── SshIpLookupStrategy.java │ ├── docker │ │ ├── ProcessHandlerLogger.java │ │ └── Config.java │ ├── vmware │ │ ├── VMWareVM.java │ │ └── JsonBodyHandler.java │ ├── virtualbox │ │ ├── VirtualboxState.java │ │ └── VirtualboxDriver.java │ └── vagrant │ │ ├── VagrantDriver.java │ │ └── VagrantState.java │ ├── Resources.java │ ├── command │ ├── CommandResponse.java │ ├── NonZeroCodeException.java │ ├── Command.java │ └── CommandProcessor.java │ ├── host │ ├── ExistingCloudHost.java │ ├── CloudHost.java │ ├── VirtualboxHost.java │ └── VagrantCloudHost.java │ ├── Preconditions.java │ ├── util │ └── RetryCommand.java │ ├── PropertiesLoader.java │ └── OverthereUtil.java ├── overcast.conf ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── license-header ├── README.markdown ├── .gitignore ├── gradle.properties ├── itest ├── overcast-vmware-itest │ ├── src │ │ └── test │ │ │ ├── resources │ │ │ └── overcast.conf │ │ │ └── java │ │ │ └── com │ │ │ └── xebialabs │ │ │ └── overcast │ │ │ └── host │ │ │ └── VMWareCloudHostItest.java │ └── build.gradle ├── overcast-vagrant-itest │ ├── src │ │ └── test │ │ │ ├── resources │ │ │ └── overcast.conf │ │ │ └── java │ │ │ └── com │ │ │ └── xebialabs │ │ │ └── overcast │ │ │ └── host │ │ │ └── CachedVagrantCloudHostItest.java │ ├── box │ │ └── Vagrantfile │ └── build.gradle ├── overcast-docker-itest │ ├── build.gradle │ └── src │ │ └── test │ │ └── resources │ │ └── overcast.conf └── overcast-libvirt-itest │ └── build.gradle ├── settings.gradle ├── .github └── workflows │ └── build.yaml └── gradlew.bat /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/copyFilesTest/2/sub/file3: -------------------------------------------------------------------------------- 1 | foo -------------------------------------------------------------------------------- /src/test/resources/dir-without-conf/no-config-here: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/with space/test.conf: -------------------------------------------------------------------------------- 1 | foo="bar" 2 | -------------------------------------------------------------------------------- /src/test/resources/copyFilesTest/1/file: -------------------------------------------------------------------------------- 1 | nothing interesting here. -------------------------------------------------------------------------------- /src/test/resources/copyFilesTest/2/file2: -------------------------------------------------------------------------------- 1 | nothing interesting here. -------------------------------------------------------------------------------- /overcast.conf: -------------------------------------------------------------------------------- 1 | // used in unit test 2 | precedenceTestValue=valueFromWork 3 | -------------------------------------------------------------------------------- /src/test/resources/property-path/overcast.conf: -------------------------------------------------------------------------------- 1 | precedenceTestValue=valueFromProperty 2 | -------------------------------------------------------------------------------- /src/test/resources/fake-home/.overcast/overcast.conf: -------------------------------------------------------------------------------- 1 | precedenceTestValue=valueFromHome 2 | -------------------------------------------------------------------------------- /documentation/docs/getting-started/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Getting Started", 3 | "position": 2 4 | } 5 | -------------------------------------------------------------------------------- /documentation/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}] 3 | }; 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebialabs/overcast/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /documentation/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /documentation/docs/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Introduction 6 | 7 | A Java library to test against hosts in the cloud. 8 | -------------------------------------------------------------------------------- /docs/assets/js/55960ee5.72573837.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[121],{8070:function(e){e.exports=[]}}]); -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Overcast 2 | 3 | Full documentation can be found by this link: 4 | [https://xebialabs.github.io/overcast](https://xebialabs.github.io/overcast/) 5 | -------------------------------------------------------------------------------- /documentation/blog/pics/vmware/vmware-test-case-flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebialabs/overcast/HEAD/documentation/blog/pics/vmware/vmware-test-case-flow.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | .classpath 3 | .project 4 | .settings 5 | .gradle 6 | bin 7 | build 8 | *.iml 9 | *.iws 10 | *.ipr 11 | .idea/ 12 | classes/ 13 | out/ 14 | -------------------------------------------------------------------------------- /docs/assets/images/vmware-test-case-flow-5b80eaa38ddb8f6d28abf2aa5f5295bd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebialabs/overcast/HEAD/docs/assets/images/vmware-test-case-flow-5b80eaa38ddb8f6d28abf2aa5f5295bd.jpg -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | hamcrestVersion=1.3 2 | jUnitVersion=5.6.2 3 | languageLevel=11 4 | logbackVersion=1.0.9 5 | mockitoCoreVersion=2.25.1 6 | slf4jVersion=1.7.16 7 | gradleCommitPluginVersion=1.0.0-930.1747 8 | -------------------------------------------------------------------------------- /itest/overcast-vmware-itest/src/test/resources/overcast.conf: -------------------------------------------------------------------------------- 1 | overcastVMWareHost { 2 | vmBaseImage=Base_centos7 3 | 4 | # vmwareApiHost=YOUR HOST HERE 5 | # vmwareAuthHashCredentials=YOUR AUTH HASH HERE 6 | } 7 | -------------------------------------------------------------------------------- /itest/overcast-vagrant-itest/src/test/resources/overcast.conf: -------------------------------------------------------------------------------- 1 | overcastVagrantHost { 2 | vagrantDir="./box" 3 | vagrantIp="10.10.200.200" 4 | vagrantVm="overcast_itest" 5 | vagrantSnapshotExpirationCmd="echo 'ohai'" 6 | } 7 | -------------------------------------------------------------------------------- /documentation/src/components/HomepageFeatures.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jan 15 10:38:41 CET 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-all.zip 7 | -------------------------------------------------------------------------------- /docs/assets/js/a2762952.6bf692cf.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[854],{8727:function(a){a.exports=JSON.parse('{"allTagsPath":"/overcast/blog/tags","slug":"/overcast/blog/tags/vmware","name":"vmware","count":1,"permalink":"/overcast/blog/tags/vmware"}')}}]); -------------------------------------------------------------------------------- /docs/assets/js/65664f72.2e7a62fc.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[5],{8893:function(a){a.exports=JSON.parse('{"allTagsPath":"/overcast/blog/tags","slug":"/overcast/blog/tags/overcast","name":"overcast","count":1,"permalink":"/overcast/blog/tags/overcast"}')}}]); -------------------------------------------------------------------------------- /docs/assets/js/34a804db.93cce336.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[177],{8957:function(e){e.exports=JSON.parse('{"permalink":"/overcast/blog","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"previousPage":null,"nextPage":null,"blogDescription":"Blog","blogTitle":"Blog"}')}}]); -------------------------------------------------------------------------------- /docs/assets/js/15bd92de.6623578a.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[127],{8784:function(t){t.exports=JSON.parse('{"allTagsPath":"/overcast/blog/tags","slug":"/overcast/blog/tags/integration-test","name":"integration-test","count":1,"permalink":"/overcast/blog/tags/integration-test"}')}}]); -------------------------------------------------------------------------------- /docs/assets/js/814f3328.db8f94e4.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[535],{5641:function(t){t.exports=JSON.parse('{"title":"Recent posts","items":[{"title":"How to run integration tests against VM Ware","permalink":"/overcast/blog/2021/09/15/how-to-run-integration-tests-against-vmware"}]}')}}]); -------------------------------------------------------------------------------- /documentation/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /documentation/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | .heroBanner { 2 | padding: 4rem 0; 3 | text-align: center; 4 | position: relative; 5 | overflow: hidden; 6 | } 7 | 8 | @media screen and (max-width: 966px) { 9 | .heroBanner { 10 | padding: 2rem; 11 | } 12 | } 13 | 14 | .buttons { 15 | display: flex; 16 | align-items: center; 17 | justify-content: center; 18 | } 19 | -------------------------------------------------------------------------------- /itest/overcast-vagrant-itest/box/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | 6 | config.vm.provider :virtualbox do |vb| 7 | vb.customize ["modifyvm", :id, "--name", "overcast_itest"] 8 | end 9 | 10 | config.vm.box = "ubuntu/trusty64" 11 | 12 | config.vm.define "overcast_itest" do |oi| 13 | oi.vm.network :private_network, ip: "10.10.200.200" 14 | end 15 | 16 | end 17 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenLocal() 4 | gradlePluginPortal() 5 | maven { 6 | url = uri("https://oss.sonatype.org/service/local/repositories/releases/content") 7 | } 8 | } 9 | } 10 | 11 | rootProject.name = 'overcast' 12 | 13 | include 'itest:overcast-docker-itest' 14 | include 'itest:overcast-libvirt-itest' 15 | include 'itest:overcast-vagrant-itest' 16 | include 'itest:overcast-vmware-itest' 17 | 18 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Run integration server 2 | on: [push] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - name: Set up JDK 11 9 | uses: actions/setup-java@v2 10 | with: 11 | java-version: '11' 12 | distribution: 'adopt' 13 | - name: Validate Gradle wrapper 14 | uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b 15 | - name: Build with Gradle 16 | run: ./gradlew clean build 17 | -------------------------------------------------------------------------------- /documentation/docs/getting-started/examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | --- 4 | 5 | # Examples 6 | 7 | ## Set up and Tear down 8 | 9 | @BeforeClass 10 | public static void doInitHost() { 11 | CloudHostFactory.getCloudHost("{my-host-label}").setup(); 12 | } 13 | 14 | @AfterClass 15 | public static void doTeardownHost() { 16 | CloudHostFactory.getCloudHost("{my-host-label}").teardown(); 17 | } 18 | 19 | Also Overcast is used for integration tests of [Overthere](https://github.com/xebialabs/overthere). 20 | 21 | -------------------------------------------------------------------------------- /gradle/license-header: -------------------------------------------------------------------------------- 1 | Copyright 2012-${year} ${name} 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 | -------------------------------------------------------------------------------- /docs/assets/js/a22865bc.9bd4aa3d.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[522],{8480:function(t){t.exports=JSON.parse('{"/overcast/blog/tags/overcast":{"allTagsPath":"/overcast/blog/tags","slug":"/overcast/blog/tags/overcast","name":"overcast","count":1,"permalink":"/overcast/blog/tags/overcast"},"/overcast/blog/tags/vmware":{"allTagsPath":"/overcast/blog/tags","slug":"/overcast/blog/tags/vmware","name":"vmware","count":1,"permalink":"/overcast/blog/tags/vmware"},"/overcast/blog/tags/integration-test":{"allTagsPath":"/overcast/blog/tags","slug":"/overcast/blog/tags/integration-test","name":"integration-test","count":1,"permalink":"/overcast/blog/tags/integration-test"}}')}}]); -------------------------------------------------------------------------------- /documentation/docs/getting-started/development.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # Development 6 | 7 | ## How to build the project 8 | 9 | `./gradlew clean build` 10 | 11 | ## Where documentation resides 12 | 13 | You can find the documentation to edit in documentation/docs folder. The `docs` folder contains built documentation 14 | which is served on GitHub Pages. 15 | 16 | ## How to run documentation site locally 17 | 18 | `./gradlew yarnRunStart` 19 | 20 | The site will be opened automatically in your default browser on page: [http://localhost:3001/overcast/](http://localhost:3001/overcast/) 21 | 22 | ## How to generate the documentation for GitHub 23 | 24 | `./gradlew docBuild` and commit all modified files in docs folder. 25 | -------------------------------------------------------------------------------- /itest/overcast-vmware-itest/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | testImplementation project(":") 3 | 4 | testImplementation "org.hamcrest:hamcrest-core:${hamcrestVersion}" 5 | testImplementation "org.hamcrest:hamcrest-library:${hamcrestVersion}" 6 | testImplementation "org.junit.jupiter:junit-jupiter-api:${jUnitVersion}" 7 | testImplementation("org.mockito:mockito-core:${mockitoCoreVersion}") 8 | 9 | testRuntimeOnly "ch.qos.logback:logback-classic:${logbackVersion}" 10 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}" 11 | testRuntimeOnly "org.slf4j:jcl-over-slf4j:${slf4jVersion}" 12 | testRuntimeOnly "org.slf4j:log4j-over-slf4j:${slf4jVersion}" 13 | } 14 | 15 | test.doFirst { 16 | println properties 17 | } 18 | -------------------------------------------------------------------------------- /itest/overcast-vagrant-itest/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | testImplementation project(":") 3 | 4 | testImplementation "org.hamcrest:hamcrest-core:${hamcrestVersion}" 5 | testImplementation "org.hamcrest:hamcrest-library:${hamcrestVersion}" 6 | testImplementation "org.junit.jupiter:junit-jupiter-api:${jUnitVersion}" 7 | testImplementation("org.mockito:mockito-core:${mockitoCoreVersion}") 8 | 9 | testRuntimeOnly "ch.qos.logback:logback-classic:${logbackVersion}" 10 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}" 11 | testRuntimeOnly "org.slf4j:jcl-over-slf4j:${slf4jVersion}" 12 | testRuntimeOnly "org.slf4j:log4j-over-slf4j:${slf4jVersion}" 13 | } 14 | 15 | test.doFirst { 16 | println properties 17 | } 18 | -------------------------------------------------------------------------------- /documentation/docs/getting-started/features.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Features 6 | 7 | * Decouple test and test machine setup. 8 | * Setup and tear-down for 9 | - Amazon EC2 hosts (Automatic host creation/destroy) 10 | - Vagrant hosts (Set up to the running state, tear down to the initial state) 11 | - VirtualBox hosts (Load snapshot and start, power off) 12 | - Libvirt managed KVM hosts (Fast clones using backing store, provisioning) 13 | - Docker containers 14 | - Tunneled cloud hosts (Reaching target host via ssh tunnel) 15 | - VMWare hosts (Instant clones, start/destroy VMs) 16 | 17 | * Provides hostname and port mapping of created host (@see Ec2CloudHost) 18 | * Caching of provisioned hosts (vagrant and KVM) with expiration checks 19 | -------------------------------------------------------------------------------- /src/test/resources/overcast.conf: -------------------------------------------------------------------------------- 1 | // ensure values in this file do not interfere with the itests 2 | 3 | value="foo" 4 | 5 | precedenceTestValue=valueFromClasspath 6 | 7 | some { 8 | nested { 9 | namespace { 10 | stringproperty = eulavemos 11 | } 12 | } 13 | nested.namespace.stringproperty = somevalue 14 | intprop : 42 15 | bar = ${value} 16 | boz = "${value}" 17 | } 18 | 19 | another.namespace { 20 | copiedValue = ${some.intprop} 21 | unixHome = ${?HOME} 22 | winHome : ""${?HOMEDRIVE}${?HOMEPATH} 23 | } 24 | 25 | unittestHost { 26 | someProp="someValue" 27 | vagrantDir="/httpd" 28 | home=""${?HOME}${?HOMEDRIVE}${?HOMEPATH} 29 | vagrantParameters { 30 | param1="value1" 31 | param2="value2" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /itest/overcast-docker-itest/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | testImplementation project(":") 3 | 4 | testImplementation "com.spotify:docker-client:8.16.0" 5 | 6 | testImplementation "org.hamcrest:hamcrest-core:${hamcrestVersion}" 7 | testImplementation "org.hamcrest:hamcrest-library:${hamcrestVersion}" 8 | testImplementation "org.junit.jupiter:junit-jupiter-api:${jUnitVersion}" 9 | 10 | testImplementation("org.mockito:mockito-core:${mockitoCoreVersion}") { 11 | exclude group: 'org.hamcrest', module: 'hamcrest-core' 12 | } 13 | 14 | testRuntimeOnly "ch.qos.logback:logback-classic:${logbackVersion}" 15 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}" 16 | testRuntimeOnly "org.slf4j:jcl-over-slf4j:${slf4jVersion}" 17 | testRuntimeOnly "org.slf4j:log4j-over-slf4j:${slf4jVersion}" 18 | } 19 | 20 | -------------------------------------------------------------------------------- /docs/assets/js/common.982779c9.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! ***************************************************************************** 2 | Copyright (c) Microsoft Corporation. 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | PERFORMANCE OF THIS SOFTWARE. 14 | ***************************************************************************** */ 15 | -------------------------------------------------------------------------------- /docs/assets/js/763fcd15.95a8f898.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[380],{6879:function(t){t.exports=JSON.parse('{"blogPosts":[{"id":"How to run integration tests against VM Ware","metadata":{"permalink":"/overcast/blog/2021/09/15/how-to-run-integration-tests-against-vmware","source":"@site/blog/2021-09-15-how-to-run-integration-tests-against-vmware.md","title":"How to run integration tests against VM Ware","description":"This article is for you, if you have to run VMs for your integration tests, and you use as a hypervisor - VM Ware 7.0","date":"2021-09-15T00:00:00.000Z","formattedDate":"September 15, 2021","tags":[{"label":"overcast","permalink":"/overcast/blog/tags/overcast"},{"label":"vmware","permalink":"/overcast/blog/tags/vmware"},{"label":"integration-test","permalink":"/overcast/blog/tags/integration-test"}],"readingTime":2.745,"truncated":false,"authors":[]}}]}')}}]); -------------------------------------------------------------------------------- /docs/img/3.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /documentation/static/img/3.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /itest/overcast-libvirt-itest/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | testImplementation project(":") 3 | 4 | testImplementation "org.hamcrest:hamcrest-core:${hamcrestVersion}" 5 | testImplementation "org.hamcrest:hamcrest-library:${hamcrestVersion}" 6 | testImplementation 'org.jdom:jdom2:2.0.5' 7 | testImplementation "org.junit.jupiter:junit-jupiter-api:${jUnitVersion}" 8 | testImplementation 'org.libvirt:libvirt:0.5.1' 9 | testImplementation "org.slf4j:slf4j-api:${slf4jVersion}" 10 | testImplementation("org.mockito:mockito-core:${mockitoCoreVersion}") { 11 | exclude group: 'org.hamcrest', module: 'hamcrest-core' 12 | } 13 | 14 | testRuntimeOnly "ch.qos.logback:logback-classic:${logbackVersion}" 15 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}" 16 | testRuntimeOnly "org.slf4j:jcl-over-slf4j:${slf4jVersion}" 17 | testRuntimeOnly "org.slf4j:log4j-over-slf4j:${slf4jVersion}" 18 | } 19 | 20 | -------------------------------------------------------------------------------- /documentation/src/css/custom.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --ifm-color-primary: #498500; 3 | --ifm-color-primary-dark: rgb(33, 175, 144); 4 | --ifm-color-primary-darker: rgb(31, 165, 136); 5 | --ifm-color-primary-darkest: rgb(26, 136, 112); 6 | --ifm-color-primary-light: rgb(70, 203, 174); 7 | --ifm-color-primary-lighter: rgb(102, 212, 189); 8 | --ifm-color-primary-lightest: rgb(146, 224, 208); 9 | --ifm-code-font-size: 95%; 10 | } 11 | 12 | .digitalai-highlight-code-line { 13 | background-color: rgba(0, 0, 0, 0.1); 14 | display: block; 15 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 16 | padding: 0 var(--ifm-pre-padding); 17 | } 18 | 19 | html[data-theme='dark'] .digitalai-highlight-code-line { 20 | background-color: rgba(0, 0, 0, 0.3); 21 | } 22 | 23 | .main-wrapper .container svg { 24 | height: 130px; 25 | width: 130px; 26 | } 27 | 28 | .navbar, .navbar * { 29 | background-color: white; 30 | color: black; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /docs/assets/js/75.8fe7757f.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[75],{4608:function(e,t,n){n.r(t);var a=n(7294),o=n(6698),l=n(4973);t.default=function(){return a.createElement(o.Z,{title:(0,l.I)({id:"theme.NotFound.title",message:"Page Not Found"})},a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(l.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."))))))}}}]); -------------------------------------------------------------------------------- /documentation/docs/getting-started/docker.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Docker 6 | 7 | ## Docker concepts 8 | During `setup()`, Overcast will create and start a new Docker container. If the image specified is not available in the local registry, it will be automatically pulled from the central Docker repository. 9 | 10 | During `teardown()`, it will stop the container and optionally remove the container (see remove property). 11 | 12 | Calling `getHostName()` will return the hostname of the Docker Host, assuming the container will run on that host, with the exposed ports accessible on the Docker host. 13 | 14 | Calling `getPort(port)` will translate the internal port (passed as an argument) to the port externally exposed by the Docker Container. The port number is dynamically determined by Docker. The port range used for dynamic allocation is 49153 to 65535 (defined by Docker). 15 | 16 | We use the [Spotify Docker Client](https://github.com/spotify/docker-client) library. 17 | 18 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/Strings.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast; 17 | 18 | public final class Strings { 19 | private Strings() {} 20 | 21 | public static boolean isNullOrEmpty(String s) { 22 | return s == null || s.isEmpty(); 23 | } 24 | 25 | public static boolean nonEmpty(String s) { return !s.isEmpty(); } 26 | } 27 | -------------------------------------------------------------------------------- /docs/blog/rss.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Overcast Blog 5 | https://xebialabs.github.io/overcast/blog 6 | Overcast Blog 7 | Wed, 15 Sep 2021 00:00:00 GMT 8 | https://validator.w3.org/feed/docs/rss2.html 9 | https://github.com/jpmonette/feed 10 | 11 | <![CDATA[How to run integration tests against VM Ware]]> 12 | https://xebialabs.github.io/overcast/blog/2021/09/15/how-to-run-integration-tests-against-vmware 13 | How to run integration tests against VM Ware 14 | Wed, 15 Sep 2021 00:00:00 GMT 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/blog/atom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://xebialabs.github.io/overcast/blog 4 | Overcast Blog 5 | 2021-09-15T00:00:00.000Z 6 | https://github.com/jpmonette/feed 7 | 8 | Overcast Blog 9 | https://xebialabs.github.io/overcast/img/digital_ai_deploy.svg 10 | 11 | <![CDATA[How to run integration tests against VM Ware]]> 12 | How to run integration tests against VM Ware 13 | 14 | 2021-09-15T00:00:00.000Z 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/assets/js/935f2afb.11666b9e.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[53],{1109:function(e){e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Introduction","href":"/overcast/docs/intro"},{"type":"category","label":"Getting Started","items":[{"type":"link","label":"Installation","href":"/overcast/docs/getting-started/installation"},{"type":"link","label":"Features","href":"/overcast/docs/getting-started/features"},{"type":"link","label":"Properties","href":"/overcast/docs/getting-started/properties"},{"type":"link","label":"Libvirt","href":"/overcast/docs/getting-started/libvirt"},{"type":"link","label":"Docker","href":"/overcast/docs/getting-started/docker"},{"type":"link","label":"Examples","href":"/overcast/docs/getting-started/examples"},{"type":"link","label":"Development","href":"/overcast/docs/getting-started/development"}],"collapsed":true,"collapsible":true}]}}')}}]); -------------------------------------------------------------------------------- /docs/assets/js/0e384e19.61658283.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[671],{9881:function(t,n,o){o.r(n),o.d(n,{frontMatter:function(){return s},contentTitle:function(){return c},metadata:function(){return u},toc:function(){return d},default:function(){return p}});var i=o(7462),e=o(3366),r=(o(7294),o(3905)),a=["components"],s={sidebar_position:1},c="Introduction",u={unversionedId:"intro",id:"intro",isDocsHomePage:!1,title:"Introduction",description:"A Java library to test against hosts in the cloud.",source:"@site/docs/intro.md",sourceDirName:".",slug:"/intro",permalink:"/overcast/docs/intro",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",next:{title:"Installation",permalink:"/overcast/docs/getting-started/installation"}},d=[],l={toc:d};function p(t){var n=t.components,o=(0,e.Z)(t,a);return(0,r.kt)("wrapper",(0,i.Z)({},l,o,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"introduction"},"Introduction"),(0,r.kt)("p",null,"A Java library to test against hosts in the cloud."))}p.isMDXComponent=!0}}]); -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/libvirt/IpNotFoundException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt; 17 | 18 | /** Indicates an {@link IpLookupStrategy} could not find the IP for a certain MAC. */ 19 | @SuppressWarnings("serial") 20 | public class IpNotFoundException extends RuntimeException { 21 | public IpNotFoundException(String message) { 22 | super(message); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/libvirt/IpLookupException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt; 17 | 18 | /** Indicates a failure occurred while an {@link IpLookupStrategy} was trying to look up the IP on a host. */ 19 | @SuppressWarnings("serial") 20 | public class IpLookupException extends RuntimeException { 21 | public IpLookupException(String message, Throwable cause) { 22 | super(message, cause); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/libvirt/IpLookupStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt; 17 | 18 | public interface IpLookupStrategy { 19 | /** 20 | * attempt to lookup an IP for a MAC. May throw {@link IpLookupException} when the lookup fails abnormally. May 21 | * throw {@link IpNotFoundException} when the IP was not found. mac may be null if it is not required 22 | * for the lookup. 23 | */ 24 | String lookup(String mac); 25 | } 26 | -------------------------------------------------------------------------------- /documentation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "documentation", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start --port=3001", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids" 15 | }, 16 | "dependencies": { 17 | "@docusaurus/core": "2.0.0-beta.6", 18 | "@docusaurus/preset-classic": "2.0.0-beta.6", 19 | "@mdx-js/react": "^1.6.21", 20 | "@svgr/webpack": "^5.5.0", 21 | "clsx": "^1.1.1", 22 | "file-loader": "^6.2.0", 23 | "prism-react-renderer": "^1.2.1", 24 | "react": "^17.0.1", 25 | "react-dom": "^17.0.1", 26 | "url-loader": "^4.1.1" 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.5%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/libvirt/LibvirtRuntimeException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt; 17 | 18 | @SuppressWarnings("serial") 19 | public class LibvirtRuntimeException extends RuntimeException { 20 | public LibvirtRuntimeException(Throwable e) { 21 | super(e); 22 | } 23 | 24 | public LibvirtRuntimeException(String message, Throwable e) { 25 | super(message, e); 26 | } 27 | 28 | public LibvirtRuntimeException(String message) { 29 | super(message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /docs/assets/js/main.6f20bb18.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress 8 | * @license MIT */ 9 | 10 | /** @license React v0.20.2 11 | * scheduler.production.min.js 12 | * 13 | * Copyright (c) Facebook, Inc. and its affiliates. 14 | * 15 | * This source code is licensed under the MIT license found in the 16 | * LICENSE file in the root directory of this source tree. 17 | */ 18 | 19 | /** @license React v16.13.1 20 | * react-is.production.min.js 21 | * 22 | * Copyright (c) Facebook, Inc. and its affiliates. 23 | * 24 | * This source code is licensed under the MIT license found in the 25 | * LICENSE file in the root directory of this source tree. 26 | */ 27 | 28 | /** @license React v17.0.2 29 | * react-dom.production.min.js 30 | * 31 | * Copyright (c) Facebook, Inc. and its affiliates. 32 | * 33 | * This source code is licensed under the MIT license found in the 34 | * LICENSE file in the root directory of this source tree. 35 | */ 36 | 37 | /** @license React v17.0.2 38 | * react.production.min.js 39 | * 40 | * Copyright (c) Facebook, Inc. and its affiliates. 41 | * 42 | * This source code is licensed under the MIT license found in the 43 | * LICENSE file in the root directory of this source tree. 44 | */ 45 | -------------------------------------------------------------------------------- /documentation/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import Layout from '@theme/Layout'; 4 | import Link from '@docusaurus/Link'; 5 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 6 | import styles from './index.module.css'; 7 | import HomepageFeatures from '../components/HomepageFeatures'; 8 | 9 | function HomepageHeader() { 10 | const {siteConfig} = useDocusaurusContext(); 11 | return ( 12 |
13 |
14 |

{siteConfig.title}

15 |

{siteConfig.tagline}

16 |
17 | 20 | Overcast Tutorial 21 | 22 |
23 |
24 |
25 | ); 26 | } 27 | 28 | export default function Home() { 29 | const {siteConfig} = useDocusaurusContext(); 30 | return ( 31 | 34 | 35 |
36 | 37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/Resources.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast; 17 | 18 | import java.net.URL; 19 | 20 | import static com.xebialabs.overcast.Preconditions.checkArgument; 21 | 22 | public final class Resources { 23 | private Resources() {} 24 | 25 | public static URL getResource(String resourceName) { 26 | ClassLoader loader = Thread.currentThread().getContextClassLoader(); 27 | if (loader == null) { 28 | loader = Resources.class.getClassLoader(); 29 | } 30 | URL url = loader.getResource(resourceName); 31 | checkArgument(url != null, "resource %s not found.", resourceName); 32 | return url; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/docker/ProcessHandlerLogger.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.docker; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | import com.spotify.docker.client.ProgressHandler; 21 | import com.spotify.docker.client.exceptions.DockerException; 22 | import com.spotify.docker.client.messages.ProgressMessage; 23 | 24 | public class ProcessHandlerLogger implements ProgressHandler { 25 | @Override 26 | public void progress(final ProgressMessage message) throws DockerException { 27 | logger.info(message.id() + " " + message.status()); 28 | } 29 | 30 | private static final Logger logger = LoggerFactory.getLogger(ProcessHandlerLogger.class); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/xebialabs/overcast/host/DockerHostTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.host; 17 | 18 | import org.junit.jupiter.api.Test; 19 | 20 | import static org.hamcrest.CoreMatchers.is; 21 | import static org.hamcrest.MatcherAssert.assertThat; 22 | 23 | public class DockerHostTest { 24 | @Test 25 | public void shouldReturnLocalhostForUnixSocket() { 26 | DockerHost dh = new DockerHost("image", "unix:///var/run/docker", null); 27 | assertThat("localhost", is(dh.getHostName())); 28 | } 29 | 30 | @Test 31 | public void shouldReturnOtherHostForUrl() { 32 | DockerHost dh = new DockerHost("image", "http://remotehost", null); 33 | assertThat("remotehost", is(dh.getHostName())); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/libvirt/LoggingOutputHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt; 17 | 18 | import org.slf4j.Logger; 19 | 20 | import com.xebialabs.overthere.OverthereExecutionOutputHandler; 21 | 22 | public class LoggingOutputHandler implements OverthereExecutionOutputHandler { 23 | private final Logger logger; 24 | private final String prefix; 25 | 26 | public LoggingOutputHandler(Logger logger, String prefix) { 27 | this.logger = logger; 28 | this.prefix = prefix; 29 | } 30 | 31 | @Override 32 | public void handleChar(char c) { 33 | // empty 34 | } 35 | 36 | @Override 37 | public void handleLine(String line) { 38 | logger.info("[{}] {}", prefix, line); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/assets/js/3720c009.46d24c30.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[751],{3578:function(e,t,a){a.r(t);var n=a(7294),r=a(6698),l=a(941),c=a(6584);t.default=function(e){var t=e.tags,a=(0,l.MA)();return n.createElement(r.Z,{title:a,wrapperClassName:l.kM.wrapper.docsPages,pageClassName:l.kM.page.docsTagsListPage,searchMetadatas:{tag:"doc_tags_list"}},n.createElement("div",{className:"container margin-vert--lg"},n.createElement("div",{className:"row"},n.createElement("main",{className:"col col--8 col--offset-2"},n.createElement("h1",null,a),n.createElement(c.Z,{tags:t})))))}},7211:function(e,t,a){a.d(t,{Z:function(){return u}});var n=a(7294),r=a(6010),l=a(6742),c="tag_1Okp",s="tagRegular_3MiF",m="tagWithCount_1HU1";var u=function(e){var t,a=e.permalink,u=e.name,i=e.count;return n.createElement(l.Z,{href:a,className:(0,r.Z)(c,(t={},t[s]=!i,t[m]=i,t))},u,i&&n.createElement("span",null,i))}},6584:function(e,t,a){a.d(t,{Z:function(){return m}});var n=a(7294),r=a(7211),l=a(941),c="tag_21yA";function s(e){var t=e.letterEntry;return n.createElement("article",null,n.createElement("h2",null,t.letter),n.createElement("ul",{className:"padding--none"},t.tags.map((function(e){return n.createElement("li",{key:e.permalink,className:c},n.createElement(r.Z,e))}))),n.createElement("hr",null))}var m=function(e){var t=e.tags,a=(0,l.PZ)(t);return n.createElement("section",{className:"margin-vert--lg"},a.map((function(e){return n.createElement(s,{key:e.letter,letterEntry:e})})))}}}]); -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/command/CommandResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.command; 17 | 18 | public class CommandResponse { 19 | 20 | private final int returnCode; 21 | 22 | private final String errors; 23 | 24 | private final String output; 25 | 26 | public CommandResponse(int returnCode, String errors, String output) { 27 | this.returnCode = returnCode; 28 | this.errors = errors; 29 | this.output = output; 30 | } 31 | 32 | public int getReturnCode() { 33 | return returnCode; 34 | } 35 | 36 | public String getErrors() { 37 | return errors; 38 | } 39 | 40 | public String getOutput() { 41 | return output; 42 | } 43 | 44 | public boolean isSuccessful() { 45 | return getReturnCode() == 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/host/ExistingCloudHost.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.host; 17 | 18 | import static com.xebialabs.overcast.OvercastProperties.getOvercastProperty; 19 | 20 | class ExistingCloudHost implements CloudHost { 21 | 22 | private final String hostname; 23 | 24 | public ExistingCloudHost(String hostLabel) { 25 | this.hostname = getOvercastProperty(hostLabel + ".hostname", hostLabel); 26 | } 27 | 28 | @Override 29 | public void setup() { 30 | // no-op 31 | } 32 | 33 | @Override 34 | public void teardown() { 35 | // no-op 36 | } 37 | 38 | @Override 39 | public String getHostName() { 40 | return hostname; 41 | } 42 | 43 | @Override 44 | public int getPort(int port) { 45 | return port; 46 | } 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/command/NonZeroCodeException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.command; 17 | 18 | /** 19 | * Thrown when {@link Command} returns non zero code 20 | */ 21 | @SuppressWarnings("serial") 22 | public class NonZeroCodeException extends RuntimeException { 23 | 24 | private final Command command; 25 | 26 | private final CommandResponse response; 27 | 28 | public NonZeroCodeException(final Command command, final CommandResponse response) { 29 | super("Command " + command.toString() + " returned non-zero code " + response.getReturnCode()); 30 | this.command = command; 31 | this.response = response; 32 | } 33 | 34 | public Command getCommand() { 35 | return command; 36 | } 37 | 38 | public CommandResponse getResponse() { 39 | return response; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/libvirt/StaticIpLookupStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt; 17 | 18 | import static com.xebialabs.overcast.OvercastProperties.getRequiredOvercastProperty; 19 | 20 | /** 21 | * Simple {@link IpLookupStrategy} that returns a pre-configured static IP. 22 | */ 23 | public class StaticIpLookupStrategy implements IpLookupStrategy { 24 | private static final String STATIC_IP_SUFFIX = ".static.ip"; 25 | 26 | private final String ip; 27 | 28 | public StaticIpLookupStrategy(String ip) { 29 | this.ip = ip; 30 | } 31 | 32 | public static StaticIpLookupStrategy create(String prefix) { 33 | String ip = getRequiredOvercastProperty(prefix + STATIC_IP_SUFFIX); 34 | return new StaticIpLookupStrategy(ip); 35 | } 36 | 37 | @Override 38 | public String lookup(String mac) { 39 | return ip; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/assets/js/9e4087bc.e0a9a0f2.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[608],{3012:function(e,t,a){a.r(t),a.d(t,{default:function(){return o}});var r=a(7294),n=a(6698),c=a(6742),l=a(4973);function i(e){var t=e.year,a=e.posts;return r.createElement(r.Fragment,null,r.createElement("h3",null,t),r.createElement("ul",null,a.map((function(e){return r.createElement("li",{key:e.metadata.date},r.createElement(c.Z,{to:e.metadata.permalink},e.metadata.formattedDate," - ",e.metadata.title))}))))}function m(e){var t=e.years;return r.createElement("section",{className:"margin-vert--lg"},r.createElement("div",{className:"container"},r.createElement("div",{className:"row"},t.map((function(e,t){return r.createElement("div",{key:t,className:"col col--4 margin-vert--lg"},r.createElement(i,e))})))))}function o(e){var t,a,c=e.archive,i=(0,l.I)({id:"theme.blog.archive.title",message:"Archive",description:"The page & hero title of the blog archive page"}),o=(0,l.I)({id:"theme.blog.archive.description",message:"Archive",description:"The page & hero description of the blog archive page"}),s=(t=c.blogPosts,a=t.reduceRight((function(e,t){var a=t.metadata.date.split("-")[0],r=e.get(a)||[];return e.set(a,[t].concat(r))}),new Map),Array.from(a,(function(e){return{year:e[0],posts:e[1]}})));return r.createElement(n.Z,{title:i,description:o},r.createElement("header",{className:"hero hero--primary"},r.createElement("div",{className:"container"},r.createElement("h1",{className:"hero__title"},i),r.createElement("p",{className:"hero__subtitle"},o))),r.createElement("main",null,s.length>0&&r.createElement(m,{years:s})))}}}]); -------------------------------------------------------------------------------- /documentation/docs/getting-started/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Installation 6 | 7 | ## Requirements 8 | 9 | - Virtualbox version >= 4.2 10 | - Vagrant version >= 1.2.7 11 | - Qemu/KVM version that supports domain metadata (QEMU-KVM 1.4.2 (Fedora 19), 2.0.0 (Ubuntu LTS 14)) 12 | - Docker >= 1.6 13 | - VMWare >= 7.0 14 | 15 | ## From maven repo 16 | 17 | [http://mvnrepository.com/artifact/com.xebialabs.cloud/overcast/2.5.1](http://mvnrepository.com/artifact/com.xebialabs.cloud/overcast/2.5.1) 18 | 19 | 20 | com.xebialabs.cloud 21 | overcast 22 | 2.5.1 23 | 24 | 25 | Note: the libvirt JNA wrapper may require adding the libvirt.org repository to your build: [http://www.libvirt.org/maven2/](http://www.libvirt.org/maven2/) 26 | 27 | ## From sources 28 | 29 | ```gradle build``` 30 | 31 | ## Usage 32 | 33 | ### Set up your host 34 | Overcast looks for configuration properties in this order: 35 | 36 | * `System.getProperty()` 37 | * `/.overcast/overcast.conf` 38 | * `/overcast.conf` 39 | * `/overcast.conf` 40 | 41 | :::note 42 | The home location takes precedence over the project location.
This allows developers to adapt settings to their local setup without changing the project defaults. 43 | ::: 44 | 45 | The `overcast.conf` files are in [Typesafe Config HOCON syntax](https://github.com/typesafehub/config#using-hocon-the-json-superset).
This is a flexible JSON superset that allows comments, substitution, file inclusion, and more. 46 | -------------------------------------------------------------------------------- /itest/overcast-vmware-itest/src/test/java/com/xebialabs/overcast/host/VMWareCloudHostItest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.host; 17 | 18 | import org.junit.jupiter.api.Test; 19 | 20 | import static org.hamcrest.CoreMatchers.is; 21 | import static org.hamcrest.CoreMatchers.notNullValue; 22 | import static org.hamcrest.MatcherAssert.assertThat; 23 | import static org.junit.jupiter.api.Assertions.fail; 24 | 25 | public class VMWareCloudHostItest { 26 | 27 | @Test 28 | public void shouldCloneAndDisposeVm() { 29 | VMWareHost h = (VMWareHost) CloudHostFactory.getCloudHost("overcastVMWareHost"); 30 | try { 31 | h.setup(); 32 | 33 | assertThat(h.getSessionId().length(), is(32)); 34 | assertThat(h.getHostName(), notNullValue()); 35 | } catch (Exception e) { 36 | fail(e.getMessage()); 37 | } finally { 38 | h.teardown(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/host/CloudHost.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.host; 17 | 18 | /** 19 | * Represents a host in the cloud. 20 | */ 21 | public interface CloudHost { 22 | 23 | /** 24 | * Ensures the host is available. 25 | */ 26 | void setup(); 27 | 28 | /** 29 | * Releases the host resources. 30 | */ 31 | void teardown(); 32 | 33 | /** 34 | * Returns the name or IP address of the host to connect to. Can only be called after {@link #setup()} has been 35 | * invoked. 36 | * 37 | * @return the host name. 38 | */ 39 | String getHostName(); 40 | 41 | /** 42 | * Translates a target port number to the port number to connect to. Can only be called after {@link #setup()} has 43 | * been invoked. 44 | * 45 | * @param port 46 | * the target port number 47 | * @return the translated port number. 48 | */ 49 | int getPort(int port); 50 | } 51 | -------------------------------------------------------------------------------- /docs/img/2.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /documentation/static/img/2.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] {%mdc} %-5level %logger{36} - %msg%n 23 | 24 | 25 | 26 | 27 | build/test.log 28 | 29 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] {%mdc} %-5level %logger{36} - %msg%n 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /docs/assets/js/508a7d2f.43c89018.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[90],{3339:function(t,e,n){n.r(e),n.d(e,{frontMatter:function(){return i},contentTitle:function(){return d},metadata:function(){return u},toc:function(){return l},default:function(){return c}});var o=n(7462),r=n(3366),a=(n(7294),n(3905)),s=["components"],i={sidebar_position:6},d="Examples",u={unversionedId:"getting-started/examples",id:"getting-started/examples",isDocsHomePage:!1,title:"Examples",description:"Set up and Tear down",source:"@site/docs/getting-started/examples.md",sourceDirName:"getting-started",slug:"/getting-started/examples",permalink:"/overcast/docs/getting-started/examples",tags:[],version:"current",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Docker",permalink:"/overcast/docs/getting-started/docker"},next:{title:"Development",permalink:"/overcast/docs/getting-started/development"}},l=[{value:"Set up and Tear down",id:"set-up-and-tear-down",children:[]}],p={toc:l};function c(t){var e=t.components,n=(0,r.Z)(t,s);return(0,a.kt)("wrapper",(0,o.Z)({},p,n,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"examples"},"Examples"),(0,a.kt)("h2",{id:"set-up-and-tear-down"},"Set up and Tear down"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'@BeforeClass\npublic static void doInitHost() {\n CloudHostFactory.getCloudHost("{my-host-label}").setup();\n}\n\n@AfterClass\npublic static void doTeardownHost() {\n CloudHostFactory.getCloudHost("{my-host-label}").teardown();\n}\n')),(0,a.kt)("p",null,"Also Overcast is used for integration tests of ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/xebialabs/overthere"},"Overthere"),"."))}c.isMDXComponent=!0}}]); -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/vmware/VMWareVM.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.vmware; 17 | 18 | public class VMWareVM { 19 | 20 | private final Integer cpuCount; 21 | private final String id; 22 | private final Integer memorySizeMb; 23 | private final String name; 24 | private final String powerState; 25 | 26 | public VMWareVM(Integer memorySizeMb, String id, String name, String powerState, Integer cpuCount) { 27 | this.memorySizeMb = memorySizeMb; 28 | this.id = id; 29 | this.name = name; 30 | this.powerState = powerState; 31 | this.cpuCount = cpuCount; 32 | } 33 | 34 | public Integer getMemorySizeMb() { 35 | return memorySizeMb; 36 | } 37 | 38 | public String getId() { 39 | return id; 40 | } 41 | 42 | public String getName() { 43 | return name; 44 | } 45 | 46 | public String getPowerState() { 47 | return powerState; 48 | } 49 | 50 | public Integer getCpuCount() { 51 | return cpuCount; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/docker/Config.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.docker; 17 | 18 | public class Config { 19 | public static final String DOCKER_CERTIFICATES_SUFFIX = ".certificates"; 20 | public static final String DOCKER_HOST_SUFFIX = ".dockerHost"; 21 | public static final String DOCKER_IMAGE_SUFFIX = ".dockerImage"; 22 | public static final String DOCKER_NAME_SUFFIX = ".name"; 23 | public static final String DOCKER_COMMAND_SUFFIX = ".command"; 24 | public static final String DOCKER_REMOVE_SUFFIX = ".remove"; 25 | public static final String DOCKER_REMOVE_VOLUME_SUFFIX = ".removeVolume"; 26 | public static final String DOCKER_ENV_SUFFIX = ".env"; 27 | public static final String DOCKER_LINKS_SUFFIX = ".links"; 28 | public static final String DOCKER_EXPOSED_PORTS_SUFFIX = ".exposedPorts"; 29 | public static final String DOCKER_PORT_BINDINGS_SUFFIX = ".portBindings"; 30 | 31 | public static final String DOCKER_EXPOSE_ALL_PORTS_SUFFIX = ".exposeAllPorts"; 32 | public static final String DOCKER_TTY_SUFFIX = ".tty"; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/host/VirtualboxHost.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.host; 17 | 18 | import com.xebialabs.overcast.command.CommandProcessor; 19 | import com.xebialabs.overcast.support.virtualbox.VirtualboxDriver; 20 | 21 | public class VirtualboxHost implements CloudHost { 22 | 23 | private final String ip; 24 | private final String uuid; 25 | private final String snapshot; 26 | 27 | public VirtualboxHost(final String ip, final String uuid, final String snapshot) { 28 | this.ip = ip; 29 | this.uuid = uuid; 30 | this.snapshot = snapshot; 31 | } 32 | 33 | @Override 34 | public void setup() { 35 | new VirtualboxDriver(CommandProcessor.atCurrentDir()).loadSnapshot(uuid, snapshot); 36 | } 37 | 38 | @Override 39 | public void teardown() { 40 | new VirtualboxDriver(CommandProcessor.atCurrentDir()).powerOff(uuid); 41 | } 42 | 43 | @Override 44 | public String getHostName() { 45 | return ip; 46 | } 47 | 48 | @Override 49 | public int getPort(final int port) { 50 | return port; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /documentation/src/components/HomepageFeatures.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import styles from './HomepageFeatures.module.css'; 4 | 5 | const FeatureList = [ 6 | { 7 | title: 'Easy to Use', 8 | Svg: require('../../static/img/1.svg').default, 9 | description: ( 10 | <> 11 | Overcast was designed from the ground up to be easy in use to spin up 12 | virtual machines for integration testing. 13 | 14 | ), 15 | }, 16 | { 17 | title: 'Focus on What Matters', 18 | Svg: require('../../static/img/2.svg').default, 19 | description: ( 20 | <> 21 | Overcast lets you focus on your test scenarios, and we'll do the chores to setup the environment. 22 | Go ahead and try it out. 23 | 24 | ), 25 | }, 26 | { 27 | title: 'Backed by Digital.ai', 28 | Svg: require('../../static/img/3.svg').default, 29 | description: ( 30 | <> 31 | Overcast made our test environment easier to operate with. 32 | 33 | ), 34 | }, 35 | ]; 36 | 37 | function Feature({Svg, title, description}) { 38 | return ( 39 |
40 |
41 | 42 |
43 |
44 |

{title}

45 |

{description}

46 |
47 |
48 | ); 49 | } 50 | 51 | export default function HomepageFeatures() { 52 | return ( 53 |
54 |
55 |
56 | {FeatureList.map((props, idx) => ( 57 | 58 | ))} 59 |
60 |
61 |
62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/virtualbox/VirtualboxState.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.virtualbox; 17 | 18 | public enum VirtualboxState { 19 | POWEROFF, ABORTED, SAVED, RUNNING; 20 | 21 | 22 | public static VirtualboxState fromStatusString(String s) { 23 | 24 | String stateString = findState(s); 25 | 26 | 27 | if (stateString.contains("powered off")) { 28 | return POWEROFF; 29 | } 30 | 31 | if (stateString.contains("saved")) { 32 | return POWEROFF; 33 | } 34 | 35 | if (stateString.contains("aborted")) { 36 | return ABORTED; 37 | } 38 | 39 | if (stateString.contains("running")) { 40 | return RUNNING; 41 | } 42 | 43 | throw new IllegalStateException("Can not detect state for state string: " + stateString); 44 | } 45 | 46 | private static String findState(String s) { 47 | String[] lines = s.split("\n"); 48 | for (String line : lines) { 49 | if (line.startsWith("State:")) { 50 | return line; 51 | } 52 | } 53 | throw new IllegalArgumentException("Expected 'State:...' but was: '" + s + "'."); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/xebialabs/overcast/command/CommandProcessorTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.command; 17 | 18 | import org.junit.jupiter.api.Test; 19 | 20 | import static com.xebialabs.overcast.command.Command.aCommand; 21 | import static com.xebialabs.overcast.command.CommandProcessor.atLocation; 22 | import static org.hamcrest.CoreMatchers.is; 23 | import static org.hamcrest.MatcherAssert.assertThat; 24 | import static org.junit.jupiter.api.Assertions.assertThrows; 25 | import static org.junit.jupiter.api.Assumptions.assumeTrue; 26 | 27 | public class CommandProcessorTest { 28 | 29 | @Test 30 | public void shouldThrowExceptionWhenCommandFailed() { 31 | //Test only for UNIX 32 | assumeTrue(System.getenv().containsKey("PATH")); 33 | 34 | assertThrows(NonZeroCodeException.class, () -> { 35 | atLocation("/tmp").run(aCommand("ls").withArguments("-wrong-argument")); 36 | }); 37 | } 38 | 39 | @Test 40 | public void shouldStoreOutput() { 41 | //Test only for UNIX 42 | assumeTrue(System.getenv().containsKey("PATH")); 43 | CommandResponse ls = atLocation("/tmp").run(aCommand("ls")); 44 | assertThat(ls.getReturnCode(), is(0)); 45 | assertThat(ls.getOutput().length() > 0, is(true)); 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/xebialabs/overcast/support/libvirt/jdom/DomainXmlTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt.jdom; 17 | 18 | import com.xebialabs.overcast.Resources; 19 | import org.jdom2.Document; 20 | import org.jdom2.input.SAXBuilder; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import static org.hamcrest.CoreMatchers.notNullValue; 24 | import static org.hamcrest.CoreMatchers.nullValue; 25 | import static org.hamcrest.MatcherAssert.assertThat; 26 | 27 | public class DomainXmlTest { 28 | 29 | public Document getXml(String file) throws Exception { 30 | SAXBuilder saxBuilder = new SAXBuilder(); 31 | return saxBuilder.build(Resources.getResource(file)); 32 | } 33 | 34 | @Test 35 | public void shouldPrepareForCloning() throws Exception { 36 | Document domainXml = getXml("libvirt-xml/simple-domain.xml"); 37 | 38 | assertThat(domainXml.getRootElement().getChild("uuid"), notNullValue()); 39 | assertThat(domainXml.getRootElement().getChild("devices").getChild("interface").getChild("mac"), notNullValue()); 40 | 41 | DomainXml.prepareForCloning(domainXml); 42 | 43 | assertThat(domainXml.getRootElement().getChild("uuid"), nullValue()); 44 | assertThat(domainXml.getRootElement().getChild("devices").getChild("interface").getChild("mac"), nullValue()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /itest/overcast-docker-itest/src/test/resources/overcast.conf: -------------------------------------------------------------------------------- 1 | 2 | // Configuration needed in users overcast.conf 3 | // overcastItest { 4 | // dockerHost=http://localhost:2375 5 | // } 6 | 7 | dockerMinimalConfig { 8 | dockerImage="busybox:1" 9 | command=["/bin/sh", "-c", "while true; do echo hello world; sleep 1; done"] 10 | remove=true 11 | removeVolume=true 12 | } 13 | 14 | greeterConfig { 15 | dockerHost="unix:///var/run/docker.sock" 16 | dockerHost=${?overcastItest.dockerHost} 17 | certificates=${?overcastItest.dockerCertificates} 18 | dockerImage="busybox:1" 19 | name="greeter" 20 | command=["/bin/sh", "-c", "echo hi | nc -l -p 8080"] 21 | remove=true 22 | removeVolume=true 23 | } 24 | 25 | dockerLinksConfig { 26 | dockerHost="unix:///var/run/docker.sock" 27 | dockerHost=${?overcastItest.dockerHost} 28 | certificates=${?overcastItest.dockerCertificates} 29 | dockerImage="busybox:1" 30 | name="receiver" 31 | links=["greeter:greeter"] 32 | command=["/bin/sh", "-c", "while ! nc greeter 8080; do sleep 1; done"] 33 | remove=true 34 | removeVolume=true 35 | } 36 | 37 | dockerAdvancedConfig { 38 | dockerHost="unix:///var/run/docker.sock" 39 | dockerHost=${?overcastItest.dockerHost} 40 | certificates=${?overcastItest.dockerCertificates} 41 | dockerImage="busybox:1" 42 | name="mycontainer" 43 | exposedPorts=["12345/tcp", "23456/tcp", "34567/tcp"] 44 | exposeAllPorts=true 45 | command=["/bin/sh", "-c", "while true; do echo hello world; sleep 1; done"] 46 | env = ["MYVAR1=AAA", "MYVAR2=BBB", "MYVAR3=CCC"] 47 | remove=true 48 | removeVolume=true 49 | } 50 | 51 | dockerAdvancedConfigTty { 52 | dockerHost="unix:///var/run/docker.sock" 53 | dockerHost=${?overcastItest.dockerHost} 54 | certificates=${?overcastItest.dockerCertificates} 55 | dockerImage="busybox:1" 56 | name="mycontainer" 57 | exposedPorts=["12345/tcp", "23456/tcp", "34567/tcp"] 58 | exposeAllPorts=true 59 | command=["/bin/sh", "-c", "while true; do echo hello world; sleep 1; done"] 60 | env = ["MYVAR1=AAA", "MYVAR2=BBB", "MYVAR3=CCC"] 61 | tty=true 62 | remove=true 63 | removeVolume=true 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/libvirt/jdom/DomainXml.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt.jdom; 17 | 18 | import org.jdom2.Document; 19 | import org.jdom2.Element; 20 | import org.jdom2.filter.Filters; 21 | import org.jdom2.xpath.XPathExpression; 22 | import org.jdom2.xpath.XPathFactory; 23 | 24 | public final class DomainXml { 25 | private DomainXml() { 26 | } 27 | 28 | public static Document setDomainName(Document domainXml, String name) { 29 | XPathFactory xpf = XPathFactory.instance(); 30 | 31 | XPathExpression nameExpr = xpf.compile("/domain/name", Filters.element()); 32 | Element nameElement = nameExpr.evaluateFirst(domainXml); 33 | nameElement.setText(name); 34 | 35 | return domainXml; 36 | } 37 | 38 | /** remove elements that need to be unique per clone. */ 39 | public static Document prepareForCloning(Document domainXml) { 40 | XPathFactory xpf = XPathFactory.instance(); 41 | 42 | // remove uuid so it will be generated 43 | domainXml.getRootElement().removeChild("uuid"); 44 | 45 | // remove mac address, so it will be generated 46 | XPathExpression macExpr = xpf.compile("/domain/devices/interface/mac", Filters.element()); 47 | for (Element mac : macExpr.evaluate(domainXml)) { 48 | mac.getParentElement().removeChild("mac"); 49 | } 50 | return domainXml; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/com/xebialabs/overcast/support/virtualbox/VirtualboxStateTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.virtualbox; 17 | 18 | import org.junit.jupiter.api.Test; 19 | 20 | import static org.hamcrest.CoreMatchers.is; 21 | import static org.hamcrest.MatcherAssert.assertThat; 22 | 23 | public class VirtualboxStateTest { 24 | 25 | @Test 26 | public void shouldRecognizePowerOffState() { 27 | String s = "Nested Paging: on\n" + 28 | "State: powered off (since 2013-03-26T17:33:45.000000000)\n" + 29 | "Monitor count: 1\n" + 30 | "3D Acceleration: off"; 31 | 32 | assertThat(VirtualboxState.fromStatusString(s), is(VirtualboxState.POWEROFF)); 33 | } 34 | 35 | @Test 36 | public void shouldRecognizeAbortedState() { 37 | String s = "Nested Paging: on\n" + 38 | "State: aborted (since 2013-03-26T17:33:45.000000000)\n" + 39 | "Monitor count: 1\n" + 40 | "3D Acceleration: off"; 41 | 42 | assertThat(VirtualboxState.fromStatusString(s), is(VirtualboxState.ABORTED)); 43 | } 44 | 45 | @Test 46 | public void shouldRecognizeRunningState() { 47 | String s = "Nested Paging: on\n" + 48 | "State: running (since 2013-03-26T17:33:45.000000000)\n" + 49 | "Monitor count: 1\n" + 50 | "3D Acceleration: off"; 51 | 52 | assertThat(VirtualboxState.fromStatusString(s), is(VirtualboxState.RUNNING)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/Preconditions.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast; 17 | 18 | import static com.xebialabs.overcast.Strings.isNullOrEmpty; 19 | 20 | public final class Preconditions { 21 | private Preconditions() {} 22 | 23 | public static void checkState( 24 | boolean expression, 25 | String errorMessageTemplate, 26 | Object... errorMessageArgs) { 27 | if (!expression) { 28 | throw new IllegalStateException(String.format(errorMessageTemplate, errorMessageArgs)); 29 | } 30 | } 31 | 32 | public static void checkArgument( 33 | boolean expression, 34 | String errorMessageTemplate, 35 | Object... errorMessageArgs) { 36 | if (!expression) { 37 | throw new IllegalArgumentException(String.format(errorMessageTemplate, errorMessageArgs)); 38 | } 39 | } 40 | 41 | public static void checkNotNull(Object reference) { 42 | if (reference == null) { 43 | throw new NullPointerException(); 44 | } 45 | } 46 | 47 | public static void checkNotNull( 48 | Object reference, String errorMessageTemplate, Object... errorMessageArgs) { 49 | if (reference == null) { 50 | throw new NullPointerException(String.format(errorMessageTemplate, errorMessageArgs)); 51 | } 52 | } 53 | 54 | public static void checkNotNullOrEmpty(String s) { 55 | if (isNullOrEmpty(s)) { 56 | throw new NullPointerException(); 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /docs/assets/js/1d48e3ab.8ff3c9fc.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[39],{4921:function(t,e,a){a.r(e),a.d(e,{frontMatter:function(){return o},contentTitle:function(){return u},metadata:function(){return l},toc:function(){return p},default:function(){return d}});var n=a(7462),r=a(3366),s=(a(7294),a(3905)),i=["components"],o={sidebar_position:2},u="Features",l={unversionedId:"getting-started/features",id:"getting-started/features",isDocsHomePage:!1,title:"Features",description:"* Decouple test and test machine setup.",source:"@site/docs/getting-started/features.md",sourceDirName:"getting-started",slug:"/getting-started/features",permalink:"/overcast/docs/getting-started/features",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Installation",permalink:"/overcast/docs/getting-started/installation"},next:{title:"Properties",permalink:"/overcast/docs/getting-started/properties"}},p=[],c={toc:p};function d(t){var e=t.components,a=(0,r.Z)(t,i);return(0,s.kt)("wrapper",(0,n.Z)({},c,a,{components:e,mdxType:"MDXLayout"}),(0,s.kt)("h1",{id:"features"},"Features"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("p",{parentName:"li"},"Decouple test and test machine setup.")),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("p",{parentName:"li"},"Setup and tear-down for"),(0,s.kt)("ul",{parentName:"li"},(0,s.kt)("li",{parentName:"ul"},"Amazon EC2 hosts (Automatic host creation/destroy)"),(0,s.kt)("li",{parentName:"ul"},"Vagrant hosts (Set up to the running state, tear down to the initial state)"),(0,s.kt)("li",{parentName:"ul"},"VirtualBox hosts (Load snapshot and start, power off)"),(0,s.kt)("li",{parentName:"ul"},"Libvirt managed KVM hosts (Fast clones using backing store, provisioning)"),(0,s.kt)("li",{parentName:"ul"},"Docker containers"),(0,s.kt)("li",{parentName:"ul"},"Tunneled cloud hosts (Reaching target host via ssh tunnel)"),(0,s.kt)("li",{parentName:"ul"},"VMWare hosts (Instant clones, start/destroy VMs)"))),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("p",{parentName:"li"},"Provides hostname and port mapping of created host (@see Ec2CloudHost)")),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("p",{parentName:"li"},"Caching of provisioned hosts (vagrant and KVM) with expiration checks"))))}d.isMDXComponent=!0}}]); -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/util/RetryCommand.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.util; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.concurrent.TimeUnit; 22 | import java.util.function.Supplier; 23 | 24 | public class RetryCommand { 25 | 26 | public static Logger logger = LoggerFactory.getLogger(RetryCommand.class); 27 | 28 | private final int maxRetries; 29 | 30 | public RetryCommand(int maxRetries) { 31 | this.maxRetries = maxRetries; 32 | } 33 | 34 | public T run(Supplier function) { 35 | try { 36 | return function.get(); 37 | } catch (Exception e) { 38 | logger.info(e.getMessage()); 39 | sleep(); 40 | return retry(function); 41 | } 42 | } 43 | 44 | private T retry(Supplier function) { 45 | int retryCounter = 0; 46 | while (retryCounter < maxRetries) { 47 | try { 48 | return function.get(); 49 | } catch (Exception ex) { 50 | retryCounter++; 51 | sleep(); 52 | logger.info(ex.getMessage()); 53 | if (retryCounter >= maxRetries) { 54 | break; 55 | } 56 | } 57 | } 58 | throw new RuntimeException("Command failed on all of " + maxRetries + " retries"); 59 | } 60 | 61 | private void sleep() { 62 | try { 63 | TimeUnit.SECONDS.sleep(5); 64 | } catch (InterruptedException e) { 65 | throw new RuntimeException(e); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/libvirt/Filesystem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt; 17 | 18 | import static com.xebialabs.overcast.Preconditions.checkNotNullOrEmpty; 19 | 20 | public class Filesystem { 21 | public enum AccessMode { 22 | /** The source is accessed with the permissions of the user inside the guest. This is the default. */ 23 | PASSTHROUGH, 24 | /** The source is accessed with the permissions of the hypervisor (QEMU process). */ 25 | MAPPED, 26 | /** 27 | * Similar to {@link AccessMode#PASSTHROUGH}, the exception is that failure of privileged operations like 28 | * 'chown' are ignored. This makes a passthrough-like mode usable for people who run the hypervisor as non-root. 29 | */ 30 | SQUASH, 31 | } 32 | 33 | public String source; 34 | public String target; 35 | public AccessMode accessMode; 36 | public boolean readOnly; 37 | 38 | public Filesystem(String source, String target, AccessMode accessMode, boolean readOnly) { 39 | checkNotNullOrEmpty(source); 40 | checkNotNullOrEmpty(target); 41 | 42 | this.source = source; 43 | this.target = target; 44 | this.accessMode = accessMode; 45 | this.readOnly = readOnly; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | return "Filesystem{" + 51 | "source='" + source + '\'' + 52 | ", target='" + target + '\'' + 53 | ", accessMode=" + accessMode + 54 | ", readOnly=" + readOnly + 55 | '}'; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/vmware/JsonBodyHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.vmware; 17 | 18 | import com.fasterxml.jackson.databind.ObjectMapper; 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.io.UncheckedIOException; 23 | import java.net.http.HttpResponse; 24 | import java.util.function.Supplier; 25 | 26 | public class JsonBodyHandler implements HttpResponse.BodyHandler> { 27 | 28 | private final Class wClass; 29 | 30 | public JsonBodyHandler(Class wClass) { 31 | this.wClass = wClass; 32 | } 33 | 34 | @Override 35 | public HttpResponse.BodySubscriber> apply(HttpResponse.ResponseInfo responseInfo) { 36 | return asJSON(wClass); 37 | } 38 | 39 | private static HttpResponse.BodySubscriber> asJSON(Class targetType) { 40 | HttpResponse.BodySubscriber upstream = HttpResponse.BodySubscribers.ofInputStream(); 41 | 42 | return HttpResponse.BodySubscribers.mapping( 43 | upstream, 44 | inputStream -> toSupplierOfType(inputStream, targetType)); 45 | } 46 | 47 | private static Supplier toSupplierOfType(InputStream inputStream, Class targetType) { 48 | return () -> { 49 | try (InputStream stream = inputStream) { 50 | ObjectMapper objectMapper = new ObjectMapper(); 51 | return objectMapper.readValue(stream, targetType); 52 | } catch (IOException e) { 53 | throw new UncheckedIOException(e); 54 | } 55 | }; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /documentation/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | const lightCodeTheme = require('prism-react-renderer/themes/github'); 2 | const darkCodeTheme = require('prism-react-renderer/themes/dracula'); 3 | 4 | module.exports = { 5 | title: 'Overcast', 6 | tagline: 'Cloud test -- Java helper classes to write your tests against hosts in the cloud', 7 | url: 'https://xebialabs.github.io', 8 | baseUrl: '/overcast/', 9 | onBrokenLinks: 'throw', 10 | onBrokenMarkdownLinks: 'warn', 11 | favicon: 'img/digital_ai_deploy.svg', 12 | organizationName: 'Digital.ai', 13 | projectName: 'overcast', 14 | themeConfig: { 15 | navbar: { 16 | title: 'Overcast', 17 | logo: { 18 | alt: 'Overcast Digital.ai', 19 | src: 'img/digital_ai_deploy.svg', 20 | }, 21 | items: [ 22 | { 23 | type: 'doc', 24 | docId: 'intro', 25 | position: 'left', 26 | label: 'Tutorial', 27 | }, 28 | 29 | { 30 | href: 'https://github.com/xebialabs/overcast', 31 | label: 'GitHub', 32 | position: 'right', 33 | }, 34 | { 35 | to: 'blog', 36 | label: 'Blog', 37 | position: 'left' 38 | } 39 | ], 40 | }, 41 | footer: { 42 | style: 'dark', 43 | links: [ 44 | { 45 | title: 'Docs', 46 | items: [ 47 | { 48 | label: 'Tutorial', 49 | to: '/docs/intro', 50 | }, 51 | { 52 | label: 'Blog', 53 | to: '/blog', 54 | }, 55 | { 56 | label: 'GitHub', 57 | href: 'https://github.com/xebialabs/overcast', 58 | }, 59 | ], 60 | }, 61 | ], 62 | copyright: `Copyright © ${new Date().getFullYear()} Overcast Digital.ai`, 63 | }, 64 | prism: { 65 | theme: lightCodeTheme, 66 | darkTheme: darkCodeTheme, 67 | }, 68 | }, 69 | presets: [ 70 | [ 71 | '@docusaurus/preset-classic', 72 | { 73 | docs: { 74 | sidebarPath: require.resolve('./sidebars.js') 75 | }, 76 | blog: { 77 | showReadingTime: true 78 | }, 79 | theme: { 80 | customCss: require.resolve('./src/css/custom.css'), 81 | }, 82 | }, 83 | ], 84 | ], 85 | }; 86 | -------------------------------------------------------------------------------- /docs/assets/js/74c14969.f1b0f9db.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[761],{6226:function(e,t,n){n.r(t),n.d(t,{frontMatter:function(){return c},contentTitle:function(){return s},metadata:function(){return l},toc:function(){return d},default:function(){return u}});var r=n(7462),o=n(3366),i=(n(7294),n(3905)),a=["components"],c={sidebar_position:5},s="Docker",l={unversionedId:"getting-started/docker",id:"getting-started/docker",isDocsHomePage:!1,title:"Docker",description:"Docker concepts",source:"@site/docs/getting-started/docker.md",sourceDirName:"getting-started",slug:"/getting-started/docker",permalink:"/overcast/docs/getting-started/docker",tags:[],version:"current",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Libvirt",permalink:"/overcast/docs/getting-started/libvirt"},next:{title:"Examples",permalink:"/overcast/docs/getting-started/examples"}},d=[{value:"Docker concepts",id:"docker-concepts",children:[]}],p={toc:d};function u(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"docker"},"Docker"),(0,i.kt)("h2",{id:"docker-concepts"},"Docker concepts"),(0,i.kt)("p",null,"During ",(0,i.kt)("inlineCode",{parentName:"p"},"setup()"),", Overcast will create and start a new Docker container. If the image specified is not available in the local registry, it will be automatically pulled from the central Docker repository."),(0,i.kt)("p",null,"During ",(0,i.kt)("inlineCode",{parentName:"p"},"teardown()"),", it will stop the container and optionally remove the container (see remove property)."),(0,i.kt)("p",null,"Calling ",(0,i.kt)("inlineCode",{parentName:"p"},"getHostName()")," will return the hostname of the Docker Host, assuming the container will run on that host, with the exposed ports accessible on the Docker host."),(0,i.kt)("p",null,"Calling ",(0,i.kt)("inlineCode",{parentName:"p"},"getPort(port)")," will translate the internal port (passed as an argument) to the port externally exposed by the Docker Container. The port number is dynamically determined by Docker. The port range used for dynamic allocation is 49153 to 65535 (defined by Docker)."),(0,i.kt)("p",null,"We use the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/spotify/docker-client"},"Spotify Docker Client")," library."))}u.isMDXComponent=!0}}]); -------------------------------------------------------------------------------- /src/test/java/com/xebialabs/overcast/support/libvirt/jdom/FilesystemXmlTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.libvirt.jdom; 17 | 18 | import java.util.Collections; 19 | import java.util.Map; 20 | 21 | import com.xebialabs.overcast.Resources; 22 | import org.jdom2.Document; 23 | import org.jdom2.input.SAXBuilder; 24 | 25 | import com.xebialabs.overcast.support.libvirt.Filesystem; 26 | import org.junit.jupiter.api.Test; 27 | 28 | import static org.hamcrest.CoreMatchers.equalTo; 29 | import static org.hamcrest.MatcherAssert.assertThat; 30 | import static org.hamcrest.Matchers.hasKey; 31 | import static org.hamcrest.Matchers.hasSize; 32 | 33 | public class FilesystemXmlTest { 34 | 35 | public Document getXml(String file) throws Exception { 36 | SAXBuilder saxBuilder = new SAXBuilder(); 37 | return saxBuilder.build(Resources.getResource(file)); 38 | } 39 | 40 | @Test 41 | public void shouldReadNoFilesystems() throws Exception { 42 | Document domainXml = getXml("libvirt-xml/simple-domain.xml"); 43 | Map fs = FilesystemXml.getFilesystems(domainXml); 44 | assertThat(fs, equalTo(Collections.EMPTY_MAP)); 45 | } 46 | 47 | @Test 48 | public void shouldReadFilesystems() throws Exception { 49 | Document domainXml = getXml("libvirt-xml/domain-with-filesystem.xml"); 50 | 51 | Map fs = FilesystemXml.getFilesystems(domainXml); 52 | assertThat(fs.keySet(), hasSize(2)); 53 | 54 | assertThat(fs, hasKey("/vagrant")); 55 | assertThat(fs.get("/vagrant").readOnly, equalTo(true)); 56 | 57 | assertThat(fs, hasKey("/data")); 58 | assertThat(fs.get("/data").readOnly, equalTo(false)); 59 | assertThat(fs.get("/data").source, equalTo("/mnt/data")); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /docs/assets/js/0aa62002.6e47bd2d.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdocumentation=self.webpackChunkdocumentation||[]).push([[240],{9200:function(e,t,o){o.r(t),o.d(t,{frontMatter:function(){return d},contentTitle:function(){return l},metadata:function(){return u},toc:function(){return c},default:function(){return p}});var n=o(7462),i=o(3366),r=(o(7294),o(3905)),a=["components"],d={sidebar_position:7},l="Development",u={unversionedId:"getting-started/development",id:"getting-started/development",isDocsHomePage:!1,title:"Development",description:"How to build the project",source:"@site/docs/getting-started/development.md",sourceDirName:"getting-started",slug:"/getting-started/development",permalink:"/overcast/docs/getting-started/development",tags:[],version:"current",sidebarPosition:7,frontMatter:{sidebar_position:7},sidebar:"tutorialSidebar",previous:{title:"Examples",permalink:"/overcast/docs/getting-started/examples"}},c=[{value:"How to build the project",id:"how-to-build-the-project",children:[]},{value:"Where documentation resides",id:"where-documentation-resides",children:[]},{value:"How to run documentation site locally",id:"how-to-run-documentation-site-locally",children:[]},{value:"How to generate the documentation for GitHub",id:"how-to-generate-the-documentation-for-github",children:[]}],s={toc:c};function p(e){var t=e.components,o=(0,i.Z)(e,a);return(0,r.kt)("wrapper",(0,n.Z)({},s,o,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"development"},"Development"),(0,r.kt)("h2",{id:"how-to-build-the-project"},"How to build the project"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"./gradlew clean build")),(0,r.kt)("h2",{id:"where-documentation-resides"},"Where documentation resides"),(0,r.kt)("p",null,"You can find the documentation to edit in documentation/docs folder. The ",(0,r.kt)("inlineCode",{parentName:"p"},"docs")," folder contains built documentation\nwhich is served on GitHub Pages."),(0,r.kt)("h2",{id:"how-to-run-documentation-site-locally"},"How to run documentation site locally"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"./gradlew yarnRunStart")),(0,r.kt)("p",null,"The site will be opened automatically in your default browser on page: ",(0,r.kt)("a",{parentName:"p",href:"http://localhost:3001/overcast/"},"http://localhost:3001/overcast/")," "),(0,r.kt)("h2",{id:"how-to-generate-the-documentation-for-github"},"How to generate the documentation for GitHub"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"./gradlew docBuild")," and commit all modified files in docs folder."))}p.isMDXComponent=!0}}]); -------------------------------------------------------------------------------- /itest/overcast-vagrant-itest/src/test/java/com/xebialabs/overcast/host/CachedVagrantCloudHostItest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.host; 17 | 18 | import com.xebialabs.overcast.command.CommandProcessor; 19 | import com.xebialabs.overcast.support.vagrant.VagrantDriver; 20 | import com.xebialabs.overcast.support.virtualbox.VirtualboxDriver; 21 | import com.xebialabs.overcast.support.virtualbox.VirtualboxState; 22 | import org.junit.jupiter.api.AfterEach; 23 | import org.junit.jupiter.api.BeforeEach; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import static org.hamcrest.CoreMatchers.is; 27 | import static org.hamcrest.MatcherAssert.assertThat; 28 | 29 | public class CachedVagrantCloudHostItest { 30 | 31 | public static final String VM = "overcast_itest"; 32 | private VirtualboxDriver vbox; 33 | private VagrantDriver vagrant; 34 | private CommandProcessor cmd; 35 | 36 | @BeforeEach 37 | public void before() { 38 | cmd = CommandProcessor.atLocation("./box"); 39 | vagrant = new VagrantDriver(VM, cmd); 40 | vbox = new VirtualboxDriver(cmd); 41 | } 42 | 43 | @AfterEach 44 | public void after() { 45 | vagrant.doVagrant(VM, "destroy", "-f"); 46 | } 47 | 48 | @Test 49 | public void shouldSetUpAndTearDownTheVm() { 50 | CloudHost h = CloudHostFactory.getCloudHost("overcastVagrantHost"); 51 | h.setup(); 52 | 53 | assertThat(vbox.vmExists(VM), is(true)); 54 | assertThat(vbox.vmState(VM), is(VirtualboxState.RUNNING)); 55 | 56 | h.teardown(); 57 | 58 | assertThat(vbox.vmState(VM), is(VirtualboxState.POWEROFF)); 59 | assertThat(vbox.getExtraData(VM, CachedVagrantCloudHost.EXPIRATION_TAG_PROPERTY_KEY), is("'ohai'")); 60 | 61 | h.setup(); 62 | 63 | assertThat(vbox.vmState(VM), is(VirtualboxState.RUNNING)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | https://xebialabs.github.io/overcast/weekly0.5https://xebialabs.github.io/overcast/blogweekly0.5https://xebialabs.github.io/overcast/blog/2021/09/15/how-to-run-integration-tests-against-vmwareweekly0.5https://xebialabs.github.io/overcast/blog/archiveweekly0.5https://xebialabs.github.io/overcast/blog/tagsweekly0.5https://xebialabs.github.io/overcast/blog/tags/integration-testweekly0.5https://xebialabs.github.io/overcast/blog/tags/overcastweekly0.5https://xebialabs.github.io/overcast/blog/tags/vmwareweekly0.5https://xebialabs.github.io/overcast/docs/tagsweekly0.5https://xebialabs.github.io/overcast/docs/getting-started/developmentweekly0.5https://xebialabs.github.io/overcast/docs/getting-started/dockerweekly0.5https://xebialabs.github.io/overcast/docs/getting-started/examplesweekly0.5https://xebialabs.github.io/overcast/docs/getting-started/featuresweekly0.5https://xebialabs.github.io/overcast/docs/getting-started/installationweekly0.5https://xebialabs.github.io/overcast/docs/getting-started/libvirtweekly0.5https://xebialabs.github.io/overcast/docs/getting-started/propertiesweekly0.5https://xebialabs.github.io/overcast/docs/introweekly0.5 -------------------------------------------------------------------------------- /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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /docs/img/1.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /documentation/static/img/1.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/vagrant/VagrantDriver.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.vagrant; 17 | 18 | import com.xebialabs.overcast.command.CommandProcessor; 19 | import com.xebialabs.overcast.command.CommandResponse; 20 | 21 | import static com.xebialabs.overcast.command.Command.aCommand; 22 | 23 | public class VagrantDriver { 24 | 25 | private final String hostLabel; 26 | private final CommandProcessor commandProcessor; 27 | 28 | public VagrantDriver(String hostLabel, CommandProcessor commandProcessor) { 29 | this.hostLabel = hostLabel; 30 | this.commandProcessor = commandProcessor; 31 | } 32 | 33 | /** 34 | * Executes vagrant command which means that arguments passed here will be prepended with "vagrant" 35 | * @param vagrantCommand arguments for vagrant command 36 | * @return vagrant response object 37 | */ 38 | public CommandResponse doVagrant(String vagrantVm, final String... vagrantCommand) { 39 | CommandResponse response = commandProcessor.run( 40 | aCommand("vagrant").withArguments(vagrantCommand).withOptions(vagrantVm) 41 | ); 42 | 43 | if(!response.isSuccessful()) { 44 | throw new RuntimeException("Errors during vagrant execution: \n" + response.getErrors()); 45 | } 46 | 47 | // Check for puppet errors. Not vagrant still returns 0 when puppet fails 48 | // May not be needed after this PR released: https://github.com/mitchellh/vagrant/pull/1175 49 | for (String line : response.getOutput().split("\n\u001B")) { 50 | if (line.startsWith("[1;35merr:")) { 51 | throw new RuntimeException("Error in puppet output: " + line); 52 | } 53 | } 54 | 55 | return response; 56 | } 57 | 58 | public CommandResponse status(String vm) { 59 | return doVagrant(vm, "status"); 60 | } 61 | 62 | public VagrantState state(String vm) { 63 | return VagrantState.fromStatusString(status(vm).getOutput()); 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return hostLabel; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/support/vagrant/VagrantState.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.vagrant; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | import java.util.Map; 21 | 22 | public enum VagrantState { 23 | NOT_CREATED, POWEROFF, ABORTED, SAVED, RUNNING; 24 | 25 | public static VagrantState fromStatusString(String s) { 26 | if (s.contains("not created")) return NOT_CREATED; 27 | if (s.contains("poweroff")) return POWEROFF; 28 | if (s.contains("aborted")) return ABORTED; 29 | if (s.contains("saved")) return SAVED; 30 | if (s.contains("running")) return RUNNING; 31 | 32 | throw new RuntimeException("Unknown status: " + s); 33 | } 34 | 35 | public static String[] getTransitionCommand(VagrantState newState, Map vagrantParameters) { 36 | 37 | switch (newState) { 38 | case NOT_CREATED: 39 | return new String[]{"destroy", "-f"}; 40 | case POWEROFF: 41 | return new String[]{"halt"}; 42 | case SAVED: 43 | return new String[]{"suspend"}; 44 | case RUNNING: 45 | if(isNullOrEmpty(vagrantParameters)) { 46 | return new String[]{"up", "--provision"}; 47 | } else { 48 | ArrayList arr = new ArrayList<>(); 49 | for (var entry : vagrantParameters.entrySet()) { 50 | arr.add("--" + entry.getKey() + "=" + entry.getValue()); 51 | } 52 | arr.add("up"); 53 | arr.add("--provision"); 54 | return arr.toArray(new String[0]); 55 | } 56 | case ABORTED: 57 | break; // ignore 58 | default: 59 | throw new IllegalArgumentException(String.format("The state %s is not known", newState)); 60 | } 61 | throw new RuntimeException("Unexpected state in getTransitionCommand "+newState.name()); 62 | } 63 | private static boolean isNullOrEmpty(final Map< ?, ? > m) { 64 | return m == null || m.isEmpty(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/xebialabs/overcast/host/VagrantCloudHost.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.host; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import com.xebialabs.overcast.support.vagrant.VagrantDriver; 22 | import com.xebialabs.overcast.support.vagrant.VagrantState; 23 | 24 | import java.util.Map; 25 | 26 | import static com.xebialabs.overcast.support.vagrant.VagrantState.NOT_CREATED; 27 | import static com.xebialabs.overcast.support.vagrant.VagrantState.getTransitionCommand; 28 | 29 | public class VagrantCloudHost implements CloudHost { 30 | 31 | protected String vagrantIp; 32 | 33 | protected String vagrantVm; 34 | 35 | protected VagrantDriver vagrantDriver; 36 | 37 | private VagrantState initialState; 38 | 39 | private Map vagrantParameters; 40 | 41 | private static final Logger logger = LoggerFactory.getLogger(VagrantCloudHost.class); 42 | 43 | public VagrantCloudHost(String vagrantVm, String vagrantIp, VagrantDriver vagrantDriver, 44 | Map vagrantParameters) { 45 | this.vagrantIp = vagrantIp; 46 | this.vagrantDriver = vagrantDriver; 47 | this.vagrantVm = vagrantVm; 48 | this.vagrantParameters = vagrantParameters; 49 | } 50 | 51 | @Override 52 | public void setup() { 53 | initialState = vagrantDriver.state(vagrantVm); 54 | logger.info("Vagrant host is in state {}.", initialState.toString()); 55 | vagrantDriver.doVagrant(vagrantVm, getTransitionCommand(VagrantState.RUNNING, vagrantParameters)); 56 | } 57 | 58 | @Override 59 | public void teardown() { 60 | VagrantState nextState; 61 | if (initialState != null) { 62 | logger.info("Bringing vagrant back to {} state.", initialState.toString()); 63 | nextState = initialState; 64 | } else { 65 | logger.warn("No initial state was captured. Destroying the VM."); 66 | nextState = NOT_CREATED; 67 | } 68 | vagrantDriver.doVagrant(vagrantVm, getTransitionCommand(nextState, vagrantParameters)); 69 | } 70 | 71 | @Override 72 | public String getHostName() { 73 | return vagrantIp; 74 | } 75 | 76 | @Override 77 | public int getPort(int port) { 78 | return port; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/com/xebialabs/overcast/support/vagrant/VagrantStateTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2012-2021 Digital.ai 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.xebialabs.overcast.support.vagrant; 17 | 18 | import org.junit.jupiter.api.Test; 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | 23 | import static com.xebialabs.overcast.support.vagrant.VagrantState.*; 24 | import static org.junit.jupiter.api.Assertions.assertEquals; 25 | 26 | public class VagrantStateTest { 27 | 28 | @Test 29 | public void shouldTranslateStatusStringToTest() { 30 | assertEquals( 31 | RUNNING, 32 | fromStatusString("Current VM states:\n" + 33 | "\n" + 34 | "default running\n" + 35 | "\n" + 36 | "The VM is running. To stop this VM, you can run `vagrant halt` to\n" + 37 | "shut it down forcefully, or you can run `vagrant suspend` to simply\n" + 38 | "suspend the virtual machine. In either case, to restart it again,\n" + 39 | "simply run `vagrant up`.") 40 | ); 41 | 42 | assertEquals(NOT_CREATED, fromStatusString("default not created\n")); 43 | assertEquals(POWEROFF, fromStatusString("default poweroff\n")); 44 | assertEquals(ABORTED, fromStatusString("default aborted\n")); 45 | assertEquals(SAVED, fromStatusString("default saved\n")); 46 | } 47 | 48 | @Test 49 | public void shouldGiveATransitionCommand() { 50 | Map vagrantParameters = new HashMap<>() {{ 51 | put("key1", "value1"); 52 | put("key2", "value2"); 53 | }}; 54 | assertEquals("up", getTransitionCommand(RUNNING, null)[0]); 55 | assertEquals("--key1=value1", getTransitionCommand(RUNNING, vagrantParameters)[0]); 56 | assertEquals("--key2=value2", getTransitionCommand(RUNNING, vagrantParameters)[1]); 57 | assertEquals("up", getTransitionCommand(RUNNING, vagrantParameters)[2]); 58 | assertEquals("halt", getTransitionCommand(POWEROFF, null)[0]); 59 | assertEquals("suspend", getTransitionCommand(SAVED, null)[0]); 60 | assertEquals("destroy", getTransitionCommand(NOT_CREATED, null)[0]); 61 | assertEquals("-f", getTransitionCommand(NOT_CREATED, null)[1]); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/test/resources/libvirt-xml/simple-domain.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | simple-domain 20 | 088e080a-7a01-0d61-d6ed-36066a3ada3b 21 | Simple domain 22 | 1048576 23 | 1048576 24 | 1 25 | 26 | hvm 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | destroy 36 | restart 37 | restart 38 | 39 | /usr/bin/kvm 40 | 41 | 42 | 43 | 44 |
45 | 46 | 47 | 48 | 49 | 50 |
51 | 52 | 53 |
54 | 55 | 56 |
57 | 58 | 59 | 60 | 61 | 62 | 63 |
64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |