All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.cdap.cdap.internal.app.runtime.artifact.RemoteArtifactManager Maven / Gradle / Ivy

There is a newer version: 6.10.1
Show newest version
/*
 * Copyright © 2017-2018 Cask Data, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package io.cdap.cdap.internal.app.runtime.artifact;


import com.google.common.base.Throwables;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import io.cdap.cdap.api.artifact.ArtifactInfo;
import io.cdap.cdap.api.artifact.ArtifactScope;
import io.cdap.cdap.api.data.schema.Schema;
import io.cdap.cdap.common.ArtifactNotFoundException;
import io.cdap.cdap.common.conf.CConfiguration;
import io.cdap.cdap.common.conf.Constants;
import io.cdap.cdap.common.http.DefaultHttpRequestConfig;
import io.cdap.cdap.common.internal.remote.RemoteClient;
import io.cdap.cdap.common.internal.remote.RemoteClientFactory;
import io.cdap.cdap.common.io.Locations;
import io.cdap.cdap.common.service.Retries;
import io.cdap.cdap.common.service.RetryStrategy;
import io.cdap.cdap.internal.app.worker.sidecar.ArtifactLocalizerClient;
import io.cdap.cdap.internal.guava.reflect.TypeToken;
import io.cdap.cdap.internal.io.SchemaTypeAdapter;
import io.cdap.cdap.proto.id.ArtifactId;
import io.cdap.cdap.proto.id.NamespaceId;
import io.cdap.cdap.security.spi.authorization.UnauthorizedException;
import io.cdap.common.http.HttpMethod;
import io.cdap.common.http.HttpRequest;
import io.cdap.common.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.apache.twill.filesystem.Location;
import org.apache.twill.filesystem.LocationFactory;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;

/**
 * Implementation for {@link io.cdap.cdap.api.artifact.ArtifactManager}
 * communicating with internal REST endpoints {@link io.cdap.cdap.gateway.handlers.ArtifactHttpHandlerInternal}
 * and returning artifact info.
 */
public final class RemoteArtifactManager extends AbstractArtifactManager {

  private static final Gson GSON = new GsonBuilder()
    .registerTypeAdapter(Schema.class, new SchemaTypeAdapter())
    .create();
  private static final Type ARTIFACT_INFO_LIST_TYPE = new TypeToken>() { }.getType();

  private final LocationFactory locationFactory;
  private final NamespaceId namespaceId;
  private final RetryStrategy retryStrategy;
  private final RemoteClient remoteClientInternal;
  private final ArtifactLocalizerClient artifactLocalizerClient;

  @Inject
  RemoteArtifactManager(CConfiguration cConf, LocationFactory locationFactory, @Assisted NamespaceId namespaceId,
                        @Assisted RetryStrategy retryStrategy, RemoteClientFactory remoteClientFactory,
                        Optional optionalArtifactLocalizerClient) {
    super(cConf);
    this.locationFactory = locationFactory;
    this.namespaceId = namespaceId;
    this.retryStrategy = retryStrategy;
    this.artifactLocalizerClient = optionalArtifactLocalizerClient.orElse(null);
    this.remoteClientInternal = remoteClientFactory.createRemoteClient(
      Constants.Service.APP_FABRIC_HTTP,
      new DefaultHttpRequestConfig(false),
      String.format("%s", Constants.Gateway.INTERNAL_API_VERSION_3));
  }

  /**
   * For the specified namespace, return the available artifacts in the namespace and also the artifacts in system
   * namespace.
   * 

* If the app-fabric service is unavailable, it will be retried based on the passed in retry strategy. * * @return {@link List} * @throws IOException If there are any exception while retrieving artifacts */ @Override public List listArtifacts() throws IOException, UnauthorizedException { return listArtifacts(namespaceId.getNamespace()); } /** * For the specified namespace, return the available artifacts in the namespace and also the artifacts in system * namespace. *

* If the app-fabric service is unavailable, it will be retried based on the passed in retry strategy. * * @return {@link List} * @throws IOException If there are any exception while retrieving artifacts */ @Override public List listArtifacts(String namespace) throws IOException, UnauthorizedException { try { return Retries.callWithRetries(() -> { HttpRequest.Builder requestBuilder = remoteClientInternal.requestBuilder(HttpMethod.GET, String.format("namespaces/%s/artifacts", namespace)); return getArtifactsList(requestBuilder.build()); }, retryStrategy); } catch (UnauthorizedException | IOException e) { throw e; } catch (Exception e) { throw Throwables.propagate(e); } } private List getArtifactsList(HttpRequest httpRequest) throws IOException, UnauthorizedException { HttpResponse httpResponse = remoteClientInternal.execute(httpRequest); if (httpResponse.getResponseCode() == HttpResponseStatus.NOT_FOUND.code()) { throw new IOException("Could not list artifacts, endpoint not found"); } if (httpResponse.getResponseCode() == 200) { return GSON.fromJson(httpResponse.getResponseBodyAsString(), ARTIFACT_INFO_LIST_TYPE); } throw new IOException("Exception while getting artifacts list " + httpResponse.getResponseBodyAsString()); } @Override protected Location getArtifactLocation(ArtifactInfo artifactInfo, @Nullable String artifactNamespace) throws IOException, UnauthorizedException { String namespace; if (ArtifactScope.SYSTEM.equals(artifactInfo.getScope())) { namespace = NamespaceId.SYSTEM.getNamespace(); } else if (artifactNamespace != null) { namespace = artifactNamespace; } else { namespace = namespaceId.getNamespace(); } // If ArtifactLocalizerClient is set, use it to get the cached location of artifact. if (artifactLocalizerClient != null) { ArtifactId artifactId = new ArtifactId(namespace, artifactInfo.getName(), artifactInfo.getVersion()); try { // Always request for the unpacked version since the artifaction location is used for creation of // artifact ClassLoader only. return Locations.toLocation(artifactLocalizerClient.getUnpackedArtifactLocation(artifactId)); } catch (ArtifactNotFoundException e) { throw new IOException(String.format("Artifact %s is not found", artifactId), e); } } HttpRequest.Builder requestBuilder = remoteClientInternal.requestBuilder( HttpMethod.GET, String.format("namespaces/%s/artifacts/%s/versions/%s/location", namespace, artifactInfo.getName(), artifactInfo.getVersion())); HttpResponse httpResponse = remoteClientInternal.execute(requestBuilder.build()); if (httpResponse.getResponseCode() == HttpResponseStatus.NOT_FOUND.code()) { throw new IOException("Could not get artifact detail, endpoint not found"); } if (httpResponse.getResponseCode() != 200) { throw new IOException(String.format("Exception while getting artifacts list %s", httpResponse.getResponseBodyAsString())); } String path = httpResponse.getResponseBodyAsString(); Location location = Locations.getLocationFromAbsolutePath(locationFactory, path); if (!location.exists()) { throw new IOException(String.format("Artifact location does not exist %s for artifact %s version %s", path, artifactInfo.getName(), artifactInfo.getVersion())); } return location; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy