/** * Copyright (c) 2018-2019, Mihai Emil Andronache * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1)Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2)Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3)Neither the name of docker-java-api nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package com.amihaiemil.docker; import java.io.IOException; import java.net.URI; import javax.json.JsonObject; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicHeader; /** * Restful Container. * @author Mihai Andronache ([email protected]) * @version $Id: dd37ca89fbe92ff751361d2dc3b42d65e87e2d17 $ * @since 0.0.1 * @todo #97:30min Continue implementing the rest of the Container operations * (pause, unpause, logs etc) See the Docker API Docs for reference: * https://docs.docker.com/engine/api/v1.35/#tag/Container */ final class RtContainer extends JsonResource implements Container { /** * Apache HttpClient which sends the requests. */ private final HttpClient client; /** * Base URI. */ private final URI baseUri; /** * Docker API. */ private final Docker docker; /** * Ctor. * @param rep JsonObject representation of this Container. * @param client Given HTTP Client. * @param baseUri Base URI, ending with /{containerId}. * @param dkr Docker where this Container came from. * @checkstyle ParameterNumber (5 lines) */ RtContainer( final JsonObject rep, final HttpClient client, final URI baseUri, final Docker dkr ) { super(rep); this.client = client; this.baseUri = baseUri; this.docker = dkr; } @Override public JsonObject inspect() throws IOException { return new Inspection(this.client, this.baseUri.toString() + "/json"); } @Override public void start() throws IOException { final HttpPost start = new HttpPost( this.baseUri.toString() + "/start" ); try { this.client.execute( start, new MatchStatus(start.getURI(), HttpStatus.SC_NO_CONTENT) ); } finally { start.releaseConnection(); } } @Override public String containerId() { return this.getString("Id"); } @Override public void stop() throws IOException { final HttpPost stop = new HttpPost( this.baseUri.toString() + "/stop" ); try { this.client.execute( stop, new MatchStatus(stop.getURI(), HttpStatus.SC_NO_CONTENT) ); } finally { stop.releaseConnection(); } } @Override public void kill() throws IOException, UnexpectedResponseException { final HttpPost kill = new HttpPost( this.baseUri.toString() + "/kill" ); try { this.client.execute( kill, new MatchStatus(kill.getURI(), HttpStatus.SC_NO_CONTENT) ); } finally { kill.releaseConnection(); } } @Override public void restart() throws IOException, UnexpectedResponseException { final HttpPost restart = new HttpPost( this.baseUri.toString() + "/restart" ); try { this.client.execute( restart, new MatchStatus(restart.getURI(), HttpStatus.SC_NO_CONTENT) ); } finally { restart.releaseConnection(); } } @Override public void rename(final String name) throws IOException, UnexpectedResponseException { final HttpPost rename = new HttpPost( this.baseUri.toString() + "/rename?name=" + name ); try { this.client.execute( rename, new MatchStatus(rename.getURI(), HttpStatus.SC_NO_CONTENT) ); } finally { rename.releaseConnection(); } } @Override public void remove() throws IOException, UnexpectedResponseException { this.remove(false, false, false); } @Override public void remove( final boolean volumes, final boolean force, final boolean link ) throws IOException, UnexpectedResponseException { final HttpDelete remove = new HttpDelete( new UncheckedUriBuilder(this.baseUri.toString()) .addParameter("v", String.valueOf(volumes)) .addParameter("force", String.valueOf(force)) .addParameter("link", String.valueOf(link)) .build() ); try { this.client.execute( remove, new MatchStatus(remove.getURI(), HttpStatus.SC_NO_CONTENT) ); } finally { remove.releaseConnection(); } } @Override public Logs logs() { return new RtLogs( this, this.client, URI.create(this.baseUri.toString() + "/logs") ); } @Override public Docker docker() { return this.docker; } @Override public void pause() throws IOException { final HttpPost pause = new HttpPost( this.baseUri.toString() + "/pause" ); try { this.client.execute( pause, new MatchStatus(pause.getURI(), HttpStatus.SC_NO_CONTENT) ); } finally { pause.releaseConnection(); } } @Override public void unpause() throws IOException { final HttpPost unpause = new HttpPost( this.baseUri.toString() + "/unpause" ); try { this.client.execute( unpause, new MatchStatus(unpause.getURI(), HttpStatus.SC_NO_CONTENT) ); } finally { unpause.releaseConnection(); } } @Override public int waitOn(final String state) throws IOException { UncheckedUriBuilder urib = new UncheckedUriBuilder( this.baseUri.toString().concat("/wait") ); if(!(null == state || state.isEmpty())){ urib.addParameter("condition", state); } final HttpPost waiter = new HttpPost(urib.build()); try { final JsonObject json = this.client.execute( waiter, new ReadJsonObject( new MatchStatus(waiter.getURI(), HttpStatus.SC_OK) ) ); return json.getInt("StatusCode"); } finally { waiter.releaseConnection(); } } @Override public Exec exec(final JsonObject config) throws IOException { final URI uri = new UncheckedUriBuilder( this.baseUri.toString() + "/exec") .build(); final HttpPost post = new HttpPost(uri); try { post.setEntity(new StringEntity(config.toString())); post.setHeader(new BasicHeader("Content-Type", "application/json")); final JsonObject json = this.client.execute( post, new ReadJsonObject( new MatchStatus(post.getURI(), HttpStatus.SC_CREATED) ) ); return this.docker.execs().get(json.getString("Id")); } finally { post.releaseConnection(); } } }