Search in sources :

Example 1 with KubernetesFunctionAuthProvider

use of org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider in project pulsar by apache.

the class KubernetesRuntimeFactory method initialize.

@Override
public void initialize(WorkerConfig workerConfig, AuthenticationConfig authenticationConfig, SecretsProviderConfigurator secretsProviderConfigurator, ConnectorsManager connectorsManager, Optional<FunctionAuthProvider> functionAuthProvider, Optional<RuntimeCustomizer> runtimeCustomizer) {
    KubernetesRuntimeFactoryConfig factoryConfig = RuntimeUtils.getRuntimeFunctionConfig(workerConfig.getFunctionRuntimeFactoryConfigs(), KubernetesRuntimeFactoryConfig.class);
    this.k8Uri = factoryConfig.getK8Uri();
    if (!isEmpty(factoryConfig.getJobNamespace())) {
        this.jobNamespace = factoryConfig.getJobNamespace();
    } else {
        this.jobNamespace = "default";
    }
    if (!isEmpty(factoryConfig.getJobName())) {
        this.jobName = factoryConfig.getJobName();
    } else {
        this.jobName = null;
    }
    if (!isEmpty(factoryConfig.getPulsarDockerImageName())) {
        this.pulsarDockerImageName = factoryConfig.getPulsarDockerImageName();
    } else {
        this.pulsarDockerImageName = "apachepulsar/pulsar";
    }
    this.functionDockerImages = factoryConfig.getFunctionDockerImages();
    if (!isEmpty(factoryConfig.getImagePullPolicy())) {
        this.imagePullPolicy = factoryConfig.getImagePullPolicy();
    } else {
        this.imagePullPolicy = "IfNotPresent";
    }
    if (!isEmpty(factoryConfig.getPulsarRootDir())) {
        this.pulsarRootDir = factoryConfig.getPulsarRootDir();
    } else {
        this.pulsarRootDir = "/pulsar";
    }
    if (!isEmpty(factoryConfig.getConfigAdminCLI())) {
        this.configAdminCLI = factoryConfig.getConfigAdminCLI();
    } else {
        this.configAdminCLI = "/bin/pulsar-admin";
    }
    this.downloadDirectory = isNotEmpty(workerConfig.getDownloadDirectory()) ? workerConfig.getDownloadDirectory() : // for backward comp
    this.pulsarRootDir;
    if (!Paths.get(this.downloadDirectory).isAbsolute()) {
        this.downloadDirectory = this.pulsarRootDir + "/" + this.downloadDirectory;
    }
    this.submittingInsidePod = factoryConfig.getSubmittingInsidePod();
    this.installUserCodeDependencies = factoryConfig.getInstallUserCodeDependencies();
    this.pythonDependencyRepository = factoryConfig.getPythonDependencyRepository();
    this.pythonExtraDependencyRepository = factoryConfig.getPythonExtraDependencyRepository();
    if (StringUtils.isNotEmpty(factoryConfig.getExtraFunctionDependenciesDir())) {
        if (Paths.get(factoryConfig.getExtraFunctionDependenciesDir()).isAbsolute()) {
            this.extraDependenciesDir = factoryConfig.getExtraFunctionDependenciesDir();
        } else {
            this.extraDependenciesDir = this.pulsarRootDir + "/" + factoryConfig.getExtraFunctionDependenciesDir();
        }
    } else {
        this.extraDependenciesDir = this.pulsarRootDir + "/instances/deps";
    }
    this.customLabels = factoryConfig.getCustomLabels();
    this.percentMemoryPadding = factoryConfig.getPercentMemoryPadding();
    this.cpuOverCommitRatio = factoryConfig.getCpuOverCommitRatio();
    this.memoryOverCommitRatio = factoryConfig.getMemoryOverCommitRatio();
    this.gracePeriodSeconds = factoryConfig.getGracePeriodSeconds();
    this.pulsarServiceUrl = StringUtils.isEmpty(factoryConfig.getPulsarServiceUrl()) ? workerConfig.getPulsarServiceUrl() : factoryConfig.getPulsarServiceUrl();
    this.pulsarAdminUrl = StringUtils.isEmpty(factoryConfig.getPulsarAdminUrl()) ? workerConfig.getPulsarWebServiceUrl() : factoryConfig.getPulsarAdminUrl();
    this.stateStorageServiceUri = workerConfig.getStateStorageServiceUrl();
    this.authConfig = authenticationConfig;
    this.expectedMetricsCollectionInterval = factoryConfig.getExpectedMetricsCollectionInterval() == null ? -1 : factoryConfig.getExpectedMetricsCollectionInterval();
    this.changeConfigMap = factoryConfig.getChangeConfigMap();
    this.changeConfigMapNamespace = factoryConfig.getChangeConfigMapNamespace();
    this.functionInstanceMinResources = workerConfig.getFunctionInstanceMinResources();
    this.functionInstanceMaxResources = workerConfig.getFunctionInstanceMaxResources();
    this.functionInstanceResourceGranularities = workerConfig.getFunctionInstanceResourceGranularities();
    this.functionInstanceResourceChangeInLockStep = workerConfig.isFunctionInstanceResourceChangeInLockStep();
    this.secretsProviderConfigurator = secretsProviderConfigurator;
    this.authenticationEnabled = workerConfig.isAuthenticationEnabled();
    this.javaInstanceJarFile = this.pulsarRootDir + "/instances/java-instance.jar";
    this.pythonInstanceFile = this.pulsarRootDir + "/instances/python-instance/python_instance_main.py";
    this.serverCaBytes = workerConfig.getTlsTrustChainBytes();
    try {
        setupClient();
    } catch (Exception e) {
        log.error("Failed to setup client", e);
        throw new RuntimeException(e);
    }
    // make sure the provided class is a kubernetes auth provider, this needs to run before the authProvider!
    if (runtimeCustomizer.isPresent()) {
        if (!(runtimeCustomizer.get() instanceof KubernetesManifestCustomizer)) {
            throw new IllegalArgumentException("Function runtime customizer " + runtimeCustomizer.get().getClass().getName() + " must implement KubernetesManifestCustomizer");
        } else {
            KubernetesManifestCustomizer manifestCustomizer = (KubernetesManifestCustomizer) runtimeCustomizer.get();
            this.manifestCustomizer = Optional.of(manifestCustomizer);
        }
    } else {
        this.manifestCustomizer = Optional.empty();
    }
    // make sure the provided class is a kubernetes auth provider
    if (functionAuthProvider.isPresent()) {
        if (!(functionAuthProvider.get() instanceof KubernetesFunctionAuthProvider)) {
            throw new IllegalArgumentException("Function authentication provider " + functionAuthProvider.get().getClass().getName() + " must implement KubernetesFunctionAuthProvider");
        } else {
            KubernetesFunctionAuthProvider kubernetesFunctionAuthProvider = (KubernetesFunctionAuthProvider) functionAuthProvider.get();
            kubernetesFunctionAuthProvider.initialize(coreClient, serverCaBytes, (funcDetails) -> getRuntimeCustomizer().map((customizer) -> customizer.customizeNamespace(funcDetails, jobNamespace)).orElse(jobNamespace));
            this.authProvider = Optional.of(kubernetesFunctionAuthProvider);
        }
    } else {
        this.authProvider = Optional.empty();
    }
    this.grpcPort = factoryConfig.getGrpcPort();
    this.metricsPort = factoryConfig.getMetricsPort();
    this.narExtractionDirectory = factoryConfig.getNarExtractionDirectory();
    this.functionInstanceClassPath = factoryConfig.getFunctionInstanceClassPath();
}
Also used : KubernetesFunctionAuthProvider(org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider)

Example 2 with KubernetesFunctionAuthProvider

use of org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider in project pulsar by apache.

the class KubernetesRuntime method submitStatefulSet.

private void submitStatefulSet() throws Exception {
    final V1StatefulSet statefulSet = createStatefulSet();
    // Configure function authentication if needed
    if (authenticationEnabled) {
        functionAuthDataCacheProvider.ifPresent(kubernetesFunctionAuthProvider -> kubernetesFunctionAuthProvider.configureAuthDataStatefulSet(statefulSet, Optional.ofNullable(getFunctionAuthData(Optional.ofNullable(instanceConfig.getFunctionAuthenticationSpec())))));
    }
    log.info("Submitting the following spec to k8 {}", appsClient.getApiClient().getJSON().serialize(statefulSet));
    String fqfn = FunctionCommon.getFullyQualifiedName(instanceConfig.getFunctionDetails());
    Actions.Action createStatefulSet = Actions.Action.builder().actionName(String.format("Submitting statefulset for function %s", fqfn)).numRetries(KubernetesRuntimeFactory.numRetries).sleepBetweenInvocationsMs(KubernetesRuntimeFactory.sleepBetweenRetriesMs).supplier(() -> {
        final V1StatefulSet response;
        try {
            response = appsClient.createNamespacedStatefulSet(jobNamespace, statefulSet, null, null, null);
        } catch (ApiException e) {
            // already exists
            if (e.getCode() == HTTP_CONFLICT) {
                log.warn("Statefulset already present for function {}", fqfn);
                return Actions.ActionResult.builder().success(true).build();
            }
            String errorMsg = e.getResponseBody() != null ? e.getResponseBody() : e.getMessage();
            return Actions.ActionResult.builder().success(false).errorMsg(errorMsg).build();
        }
        return Actions.ActionResult.builder().success(true).build();
    }).build();
    AtomicBoolean success = new AtomicBoolean(false);
    Actions.newBuilder().addAction(createStatefulSet.toBuilder().onSuccess((ignored) -> success.set(true)).build()).run();
    if (!success.get()) {
        throw new RuntimeException(String.format("Failed to create statefulset for function %s", fqfn));
    }
}
Also used : Arrays(java.util.Arrays) ManagedChannel(io.grpc.ManagedChannel) V1PodList(io.kubernetes.client.openapi.models.V1PodList) V1Toleration(io.kubernetes.client.openapi.models.V1Toleration) V1ResourceRequirements(io.kubernetes.client.openapi.models.V1ResourceRequirements) StringUtils(org.apache.commons.lang3.StringUtils) Empty(com.google.protobuf.Empty) Matcher(java.util.regex.Matcher) V1EnvVar(io.kubernetes.client.openapi.models.V1EnvVar) Gson(com.google.gson.Gson) Map(java.util.Map) V1StatefulSet(io.kubernetes.client.openapi.models.V1StatefulSet) Quantity(io.kubernetes.client.custom.Quantity) FunctionAuthUtils.getFunctionAuthData(org.apache.pulsar.functions.auth.FunctionAuthUtils.getFunctionAuthData) V1ObjectFieldSelector(io.kubernetes.client.openapi.models.V1ObjectFieldSelector) V1DeleteOptions(io.kubernetes.client.openapi.models.V1DeleteOptions) Function(org.apache.pulsar.functions.proto.Function) Runtime(org.apache.pulsar.functions.runtime.Runtime) V1LabelSelector(io.kubernetes.client.openapi.models.V1LabelSelector) FunctionCommon.roundDecimal(org.apache.pulsar.functions.utils.FunctionCommon.roundDecimal) List(java.util.List) Slf4j(lombok.extern.slf4j.Slf4j) StringUtils.isNotBlank(org.apache.commons.lang3.StringUtils.isNotBlank) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) V1ServiceSpec(io.kubernetes.client.openapi.models.V1ServiceSpec) V1EnvVarSource(io.kubernetes.client.openapi.models.V1EnvVarSource) KubernetesFunctionAuthProvider(org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider) HTTP_NOT_FOUND(java.net.HttpURLConnection.HTTP_NOT_FOUND) MoreExecutors(com.google.common.util.concurrent.MoreExecutors) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Getter(lombok.Getter) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) InstanceCommunication(org.apache.pulsar.functions.proto.InstanceCommunication) V1PodTemplateSpec(io.kubernetes.client.openapi.models.V1PodTemplateSpec) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AuthenticationConfig(org.apache.pulsar.functions.instance.AuthenticationConfig) AppsV1Api(io.kubernetes.client.openapi.apis.AppsV1Api) ArrayList(java.util.ArrayList) ApiException(io.kubernetes.client.openapi.ApiException) V1StatefulSetSpec(io.kubernetes.client.openapi.models.V1StatefulSetSpec) V1ObjectMeta(io.kubernetes.client.openapi.models.V1ObjectMeta) Response(okhttp3.Response) V1ContainerPort(io.kubernetes.client.openapi.models.V1ContainerPort) FunctionStatus(org.apache.pulsar.functions.proto.InstanceCommunication.FunctionStatus) RuntimeUtils(org.apache.pulsar.functions.runtime.RuntimeUtils) V1Container(io.kubernetes.client.openapi.models.V1Container) LinkedList(java.util.LinkedList) InstanceUtils(org.apache.pulsar.functions.instance.InstanceUtils) IOException(java.io.IOException) CoreV1Api(io.kubernetes.client.openapi.apis.CoreV1Api) FutureCallback(com.google.common.util.concurrent.FutureCallback) PackageType(org.apache.pulsar.packages.management.core.common.PackageType) TimeUnit(java.util.concurrent.TimeUnit) InstanceControlGrpc(org.apache.pulsar.functions.proto.InstanceControlGrpc) ManagedChannelBuilder(io.grpc.ManagedChannelBuilder) V1PodSpec(io.kubernetes.client.openapi.models.V1PodSpec) Futures(com.google.common.util.concurrent.Futures) SecretsProviderConfigurator(org.apache.pulsar.functions.secretsproviderconfigurator.SecretsProviderConfigurator) FunctionCommon(org.apache.pulsar.functions.utils.FunctionCommon) StringUtils.left(org.apache.commons.lang3.StringUtils.left) V1ServicePort(io.kubernetes.client.openapi.models.V1ServicePort) HTTP_CONFLICT(java.net.HttpURLConnection.HTTP_CONFLICT) Actions(org.apache.pulsar.functions.utils.Actions) InstanceConfig(org.apache.pulsar.functions.instance.InstanceConfig) VisibleForTesting(com.google.common.annotations.VisibleForTesting) DigestUtils(org.apache.commons.codec.digest.DigestUtils) V1Service(io.kubernetes.client.openapi.models.V1Service) Collections(java.util.Collections) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) V1StatefulSet(io.kubernetes.client.openapi.models.V1StatefulSet) Actions(org.apache.pulsar.functions.utils.Actions) ApiException(io.kubernetes.client.openapi.ApiException)

Example 3 with KubernetesFunctionAuthProvider

use of org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider in project pulsar by yahoo.

the class KubernetesRuntime method submitStatefulSet.

private void submitStatefulSet() throws Exception {
    final V1StatefulSet statefulSet = createStatefulSet();
    // Configure function authentication if needed
    if (authenticationEnabled) {
        functionAuthDataCacheProvider.ifPresent(kubernetesFunctionAuthProvider -> kubernetesFunctionAuthProvider.configureAuthDataStatefulSet(statefulSet, Optional.ofNullable(getFunctionAuthData(Optional.ofNullable(instanceConfig.getFunctionAuthenticationSpec())))));
    }
    log.info("Submitting the following spec to k8 {}", appsClient.getApiClient().getJSON().serialize(statefulSet));
    String fqfn = FunctionCommon.getFullyQualifiedName(instanceConfig.getFunctionDetails());
    Actions.Action createStatefulSet = Actions.Action.builder().actionName(String.format("Submitting statefulset for function %s", fqfn)).numRetries(KubernetesRuntimeFactory.numRetries).sleepBetweenInvocationsMs(KubernetesRuntimeFactory.sleepBetweenRetriesMs).supplier(() -> {
        final V1StatefulSet response;
        try {
            response = appsClient.createNamespacedStatefulSet(jobNamespace, statefulSet, null, null, null);
        } catch (ApiException e) {
            // already exists
            if (e.getCode() == HTTP_CONFLICT) {
                log.warn("Statefulset already present for function {}", fqfn);
                return Actions.ActionResult.builder().success(true).build();
            }
            String errorMsg = e.getResponseBody() != null ? e.getResponseBody() : e.getMessage();
            return Actions.ActionResult.builder().success(false).errorMsg(errorMsg).build();
        }
        return Actions.ActionResult.builder().success(true).build();
    }).build();
    AtomicBoolean success = new AtomicBoolean(false);
    Actions.newBuilder().addAction(createStatefulSet.toBuilder().onSuccess((ignored) -> success.set(true)).build()).run();
    if (!success.get()) {
        throw new RuntimeException(String.format("Failed to create statefulset for function %s", fqfn));
    }
}
Also used : Arrays(java.util.Arrays) ManagedChannel(io.grpc.ManagedChannel) V1PodList(io.kubernetes.client.openapi.models.V1PodList) V1Toleration(io.kubernetes.client.openapi.models.V1Toleration) V1ResourceRequirements(io.kubernetes.client.openapi.models.V1ResourceRequirements) StringUtils(org.apache.commons.lang3.StringUtils) Empty(com.google.protobuf.Empty) Matcher(java.util.regex.Matcher) V1EnvVar(io.kubernetes.client.openapi.models.V1EnvVar) Gson(com.google.gson.Gson) Map(java.util.Map) V1StatefulSet(io.kubernetes.client.openapi.models.V1StatefulSet) Quantity(io.kubernetes.client.custom.Quantity) FunctionAuthUtils.getFunctionAuthData(org.apache.pulsar.functions.auth.FunctionAuthUtils.getFunctionAuthData) V1ObjectFieldSelector(io.kubernetes.client.openapi.models.V1ObjectFieldSelector) V1DeleteOptions(io.kubernetes.client.openapi.models.V1DeleteOptions) Function(org.apache.pulsar.functions.proto.Function) Runtime(org.apache.pulsar.functions.runtime.Runtime) V1LabelSelector(io.kubernetes.client.openapi.models.V1LabelSelector) FunctionCommon.roundDecimal(org.apache.pulsar.functions.utils.FunctionCommon.roundDecimal) List(java.util.List) Slf4j(lombok.extern.slf4j.Slf4j) StringUtils.isNotBlank(org.apache.commons.lang3.StringUtils.isNotBlank) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) V1ServiceSpec(io.kubernetes.client.openapi.models.V1ServiceSpec) V1EnvVarSource(io.kubernetes.client.openapi.models.V1EnvVarSource) KubernetesFunctionAuthProvider(org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider) HTTP_NOT_FOUND(java.net.HttpURLConnection.HTTP_NOT_FOUND) MoreExecutors(com.google.common.util.concurrent.MoreExecutors) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Getter(lombok.Getter) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) InstanceCommunication(org.apache.pulsar.functions.proto.InstanceCommunication) V1PodTemplateSpec(io.kubernetes.client.openapi.models.V1PodTemplateSpec) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AuthenticationConfig(org.apache.pulsar.functions.instance.AuthenticationConfig) AppsV1Api(io.kubernetes.client.openapi.apis.AppsV1Api) ArrayList(java.util.ArrayList) ApiException(io.kubernetes.client.openapi.ApiException) V1StatefulSetSpec(io.kubernetes.client.openapi.models.V1StatefulSetSpec) V1ObjectMeta(io.kubernetes.client.openapi.models.V1ObjectMeta) Response(okhttp3.Response) V1ContainerPort(io.kubernetes.client.openapi.models.V1ContainerPort) FunctionStatus(org.apache.pulsar.functions.proto.InstanceCommunication.FunctionStatus) RuntimeUtils(org.apache.pulsar.functions.runtime.RuntimeUtils) V1Container(io.kubernetes.client.openapi.models.V1Container) LinkedList(java.util.LinkedList) InstanceUtils(org.apache.pulsar.functions.instance.InstanceUtils) IOException(java.io.IOException) CoreV1Api(io.kubernetes.client.openapi.apis.CoreV1Api) FutureCallback(com.google.common.util.concurrent.FutureCallback) PackageType(org.apache.pulsar.packages.management.core.common.PackageType) TimeUnit(java.util.concurrent.TimeUnit) InstanceControlGrpc(org.apache.pulsar.functions.proto.InstanceControlGrpc) ManagedChannelBuilder(io.grpc.ManagedChannelBuilder) V1PodSpec(io.kubernetes.client.openapi.models.V1PodSpec) Futures(com.google.common.util.concurrent.Futures) SecretsProviderConfigurator(org.apache.pulsar.functions.secretsproviderconfigurator.SecretsProviderConfigurator) FunctionCommon(org.apache.pulsar.functions.utils.FunctionCommon) StringUtils.left(org.apache.commons.lang3.StringUtils.left) V1ServicePort(io.kubernetes.client.openapi.models.V1ServicePort) HTTP_CONFLICT(java.net.HttpURLConnection.HTTP_CONFLICT) Actions(org.apache.pulsar.functions.utils.Actions) InstanceConfig(org.apache.pulsar.functions.instance.InstanceConfig) VisibleForTesting(com.google.common.annotations.VisibleForTesting) DigestUtils(org.apache.commons.codec.digest.DigestUtils) V1Service(io.kubernetes.client.openapi.models.V1Service) Collections(java.util.Collections) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) V1StatefulSet(io.kubernetes.client.openapi.models.V1StatefulSet) Actions(org.apache.pulsar.functions.utils.Actions) ApiException(io.kubernetes.client.openapi.ApiException)

Example 4 with KubernetesFunctionAuthProvider

use of org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider in project pulsar by yahoo.

the class KubernetesRuntimeFactory method initialize.

@Override
public void initialize(WorkerConfig workerConfig, AuthenticationConfig authenticationConfig, SecretsProviderConfigurator secretsProviderConfigurator, ConnectorsManager connectorsManager, Optional<FunctionAuthProvider> functionAuthProvider, Optional<RuntimeCustomizer> runtimeCustomizer) {
    KubernetesRuntimeFactoryConfig factoryConfig = RuntimeUtils.getRuntimeFunctionConfig(workerConfig.getFunctionRuntimeFactoryConfigs(), KubernetesRuntimeFactoryConfig.class);
    this.k8Uri = factoryConfig.getK8Uri();
    if (!isEmpty(factoryConfig.getJobNamespace())) {
        this.jobNamespace = factoryConfig.getJobNamespace();
    } else {
        this.jobNamespace = "default";
    }
    if (!isEmpty(factoryConfig.getJobName())) {
        this.jobName = factoryConfig.getJobName();
    } else {
        this.jobName = null;
    }
    if (!isEmpty(factoryConfig.getPulsarDockerImageName())) {
        this.pulsarDockerImageName = factoryConfig.getPulsarDockerImageName();
    } else {
        this.pulsarDockerImageName = "apachepulsar/pulsar";
    }
    this.functionDockerImages = factoryConfig.getFunctionDockerImages();
    if (!isEmpty(factoryConfig.getImagePullPolicy())) {
        this.imagePullPolicy = factoryConfig.getImagePullPolicy();
    } else {
        this.imagePullPolicy = "IfNotPresent";
    }
    if (!isEmpty(factoryConfig.getPulsarRootDir())) {
        this.pulsarRootDir = factoryConfig.getPulsarRootDir();
    } else {
        this.pulsarRootDir = "/pulsar";
    }
    if (!isEmpty(factoryConfig.getConfigAdminCLI())) {
        this.configAdminCLI = factoryConfig.getConfigAdminCLI();
    } else {
        this.configAdminCLI = "/bin/pulsar-admin";
    }
    this.downloadDirectory = isNotEmpty(workerConfig.getDownloadDirectory()) ? workerConfig.getDownloadDirectory() : // for backward comp
    this.pulsarRootDir;
    if (!Paths.get(this.downloadDirectory).isAbsolute()) {
        this.downloadDirectory = this.pulsarRootDir + "/" + this.downloadDirectory;
    }
    this.submittingInsidePod = factoryConfig.getSubmittingInsidePod();
    this.installUserCodeDependencies = factoryConfig.getInstallUserCodeDependencies();
    this.pythonDependencyRepository = factoryConfig.getPythonDependencyRepository();
    this.pythonExtraDependencyRepository = factoryConfig.getPythonExtraDependencyRepository();
    if (StringUtils.isNotEmpty(factoryConfig.getExtraFunctionDependenciesDir())) {
        if (Paths.get(factoryConfig.getExtraFunctionDependenciesDir()).isAbsolute()) {
            this.extraDependenciesDir = factoryConfig.getExtraFunctionDependenciesDir();
        } else {
            this.extraDependenciesDir = this.pulsarRootDir + "/" + factoryConfig.getExtraFunctionDependenciesDir();
        }
    } else {
        this.extraDependenciesDir = this.pulsarRootDir + "/instances/deps";
    }
    this.customLabels = factoryConfig.getCustomLabels();
    this.percentMemoryPadding = factoryConfig.getPercentMemoryPadding();
    this.cpuOverCommitRatio = factoryConfig.getCpuOverCommitRatio();
    this.memoryOverCommitRatio = factoryConfig.getMemoryOverCommitRatio();
    this.gracePeriodSeconds = factoryConfig.getGracePeriodSeconds();
    this.pulsarServiceUrl = StringUtils.isEmpty(factoryConfig.getPulsarServiceUrl()) ? workerConfig.getPulsarServiceUrl() : factoryConfig.getPulsarServiceUrl();
    this.pulsarAdminUrl = StringUtils.isEmpty(factoryConfig.getPulsarAdminUrl()) ? workerConfig.getPulsarWebServiceUrl() : factoryConfig.getPulsarAdminUrl();
    this.stateStorageServiceUri = workerConfig.getStateStorageServiceUrl();
    this.authConfig = authenticationConfig;
    this.expectedMetricsCollectionInterval = factoryConfig.getExpectedMetricsCollectionInterval() == null ? -1 : factoryConfig.getExpectedMetricsCollectionInterval();
    this.changeConfigMap = factoryConfig.getChangeConfigMap();
    this.changeConfigMapNamespace = factoryConfig.getChangeConfigMapNamespace();
    this.functionInstanceMinResources = workerConfig.getFunctionInstanceMinResources();
    this.functionInstanceMaxResources = workerConfig.getFunctionInstanceMaxResources();
    this.functionInstanceResourceGranularities = workerConfig.getFunctionInstanceResourceGranularities();
    this.functionInstanceResourceChangeInLockStep = workerConfig.isFunctionInstanceResourceChangeInLockStep();
    this.secretsProviderConfigurator = secretsProviderConfigurator;
    this.authenticationEnabled = workerConfig.isAuthenticationEnabled();
    this.javaInstanceJarFile = this.pulsarRootDir + "/instances/java-instance.jar";
    this.pythonInstanceFile = this.pulsarRootDir + "/instances/python-instance/python_instance_main.py";
    this.serverCaBytes = workerConfig.getTlsTrustChainBytes();
    try {
        setupClient();
    } catch (Exception e) {
        log.error("Failed to setup client", e);
        throw new RuntimeException(e);
    }
    // make sure the provided class is a kubernetes auth provider, this needs to run before the authProvider!
    if (runtimeCustomizer.isPresent()) {
        if (!(runtimeCustomizer.get() instanceof KubernetesManifestCustomizer)) {
            throw new IllegalArgumentException("Function runtime customizer " + runtimeCustomizer.get().getClass().getName() + " must implement KubernetesManifestCustomizer");
        } else {
            KubernetesManifestCustomizer manifestCustomizer = (KubernetesManifestCustomizer) runtimeCustomizer.get();
            this.manifestCustomizer = Optional.of(manifestCustomizer);
        }
    } else {
        this.manifestCustomizer = Optional.empty();
    }
    // make sure the provided class is a kubernetes auth provider
    if (functionAuthProvider.isPresent()) {
        if (!(functionAuthProvider.get() instanceof KubernetesFunctionAuthProvider)) {
            throw new IllegalArgumentException("Function authentication provider " + functionAuthProvider.get().getClass().getName() + " must implement KubernetesFunctionAuthProvider");
        } else {
            KubernetesFunctionAuthProvider kubernetesFunctionAuthProvider = (KubernetesFunctionAuthProvider) functionAuthProvider.get();
            kubernetesFunctionAuthProvider.initialize(coreClient, serverCaBytes, (funcDetails) -> getRuntimeCustomizer().map((customizer) -> customizer.customizeNamespace(funcDetails, jobNamespace)).orElse(jobNamespace));
            this.authProvider = Optional.of(kubernetesFunctionAuthProvider);
        }
    } else {
        this.authProvider = Optional.empty();
    }
    this.grpcPort = factoryConfig.getGrpcPort();
    this.metricsPort = factoryConfig.getMetricsPort();
    this.narExtractionDirectory = factoryConfig.getNarExtractionDirectory();
    this.functionInstanceClassPath = factoryConfig.getFunctionInstanceClassPath();
}
Also used : KubernetesFunctionAuthProvider(org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider)

Example 5 with KubernetesFunctionAuthProvider

use of org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider in project pulsar by yahoo.

the class KubernetesRuntimeFactory method createContainer.

@Override
public KubernetesRuntime createContainer(InstanceConfig instanceConfig, String codePkgUrl, String originalCodeFileName, Long expectedHealthCheckInterval) throws Exception {
    String instanceFile = null;
    switch(instanceConfig.getFunctionDetails().getRuntime()) {
        case JAVA:
            instanceFile = javaInstanceJarFile;
            break;
        case PYTHON:
            instanceFile = pythonInstanceFile;
            break;
        case GO:
            break;
        default:
            throw new RuntimeException("Unsupported Runtime " + instanceConfig.getFunctionDetails().getRuntime());
    }
    // adjust the auth config to support auth
    if (authenticationEnabled) {
        authProvider.ifPresent(kubernetesFunctionAuthProvider -> kubernetesFunctionAuthProvider.configureAuthenticationConfig(authConfig, Optional.ofNullable(getFunctionAuthData(Optional.ofNullable(instanceConfig.getFunctionAuthenticationSpec())))));
    }
    Optional<KubernetesManifestCustomizer> manifestCustomizer = getRuntimeCustomizer();
    String overriddenNamespace = manifestCustomizer.map((customizer) -> customizer.customizeNamespace(instanceConfig.getFunctionDetails(), jobNamespace)).orElse(jobNamespace);
    String overriddenName = manifestCustomizer.map((customizer) -> customizer.customizeName(instanceConfig.getFunctionDetails(), jobName)).orElse(jobName);
    // pass metricsPort configured in functionRuntimeFactoryConfigs.metricsPort in functions_worker.yml
    if (metricsPort != null) {
        instanceConfig.setMetricsPort(metricsPort);
    }
    return new KubernetesRuntime(appsClient, coreClient, // get the namespace for this function
    overriddenNamespace, overriddenName, customLabels, installUserCodeDependencies, pythonDependencyRepository, pythonExtraDependencyRepository, pulsarDockerImageName, functionDockerImages, imagePullPolicy, pulsarRootDir, instanceConfig, instanceFile, extraDependenciesDir, logDirectory, configAdminCLI, codePkgUrl, originalCodeFileName, pulsarServiceUrl, pulsarAdminUrl, stateStorageServiceUri, authConfig, secretsProviderConfigurator, expectedMetricsCollectionInterval, percentMemoryPadding, cpuOverCommitRatio, memoryOverCommitRatio, gracePeriodSeconds, authProvider, authenticationEnabled, grpcPort, narExtractionDirectory, manifestCustomizer, functionInstanceClassPath, downloadDirectory);
}
Also used : Timer(java.util.Timer) Resources(org.apache.pulsar.common.functions.Resources) AuthenticationConfig(org.apache.pulsar.functions.instance.AuthenticationConfig) RuntimeCustomizer(org.apache.pulsar.functions.runtime.RuntimeCustomizer) StringUtils(org.apache.commons.lang3.StringUtils) AppsV1Api(io.kubernetes.client.openapi.apis.AppsV1Api) StringUtils.isNotEmpty(org.apache.commons.lang3.StringUtils.isNotEmpty) ApiClient(io.kubernetes.client.openapi.ApiClient) Configuration(io.kubernetes.client.openapi.Configuration) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap) Map(java.util.Map) ToString(lombok.ToString) RuntimeUtils(org.apache.pulsar.functions.runtime.RuntimeUtils) TimerTask(java.util.TimerTask) StringUtils.isEmpty(org.apache.commons.lang3.StringUtils.isEmpty) FunctionAuthUtils.getFunctionAuthData(org.apache.pulsar.functions.auth.FunctionAuthUtils.getFunctionAuthData) RuntimeFactory(org.apache.pulsar.functions.runtime.RuntimeFactory) FunctionAuthProvider(org.apache.pulsar.functions.auth.FunctionAuthProvider) ConnectorsManager(org.apache.pulsar.functions.worker.ConnectorsManager) Function(org.apache.pulsar.functions.proto.Function) CoreV1Api(io.kubernetes.client.openapi.apis.CoreV1Api) WorkerConfig(org.apache.pulsar.functions.worker.WorkerConfig) Field(java.lang.reflect.Field) EqualsAndHashCode(lombok.EqualsAndHashCode) Config(io.kubernetes.client.util.Config) Slf4j(lombok.extern.slf4j.Slf4j) SecretsProviderConfigurator(org.apache.pulsar.functions.secretsproviderconfigurator.SecretsProviderConfigurator) Paths(java.nio.file.Paths) Data(lombok.Data) Optional(java.util.Optional) InstanceConfig(org.apache.pulsar.functions.instance.InstanceConfig) VisibleForTesting(com.google.common.annotations.VisibleForTesting) KubernetesFunctionAuthProvider(org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider) ToString(lombok.ToString)

Aggregations

KubernetesFunctionAuthProvider (org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider)9 VisibleForTesting (com.google.common.annotations.VisibleForTesting)6 AppsV1Api (io.kubernetes.client.openapi.apis.AppsV1Api)6 CoreV1Api (io.kubernetes.client.openapi.apis.CoreV1Api)6 Map (java.util.Map)6 Optional (java.util.Optional)6 Slf4j (lombok.extern.slf4j.Slf4j)6 StringUtils (org.apache.commons.lang3.StringUtils)6 FunctionAuthUtils.getFunctionAuthData (org.apache.pulsar.functions.auth.FunctionAuthUtils.getFunctionAuthData)6 AuthenticationConfig (org.apache.pulsar.functions.instance.AuthenticationConfig)6 InstanceConfig (org.apache.pulsar.functions.instance.InstanceConfig)6 Function (org.apache.pulsar.functions.proto.Function)6 RuntimeUtils (org.apache.pulsar.functions.runtime.RuntimeUtils)6 SecretsProviderConfigurator (org.apache.pulsar.functions.secretsproviderconfigurator.SecretsProviderConfigurator)6 FutureCallback (com.google.common.util.concurrent.FutureCallback)3 Futures (com.google.common.util.concurrent.Futures)3 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)3 MoreExecutors (com.google.common.util.concurrent.MoreExecutors)3 Gson (com.google.gson.Gson)3 Empty (com.google.protobuf.Empty)3