// Copyright 2019 The Kubeflow Authors // // 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. import * as path from 'path'; import { loadJSON } from './utils'; import { loadArtifactsProxyConfig, ArtifactsProxyConfig } from './handlers/artifacts'; export const BASEPATH = '/pipeline'; export const apiVersion1 = 'v1beta1'; export const apiVersion1Prefix = `apis/${apiVersion1}`; export const apiVersion2 = 'v2beta1'; export const apiVersion2Prefix = `apis/${apiVersion2}`; export enum Deployments { NOT_SPECIFIED = 'NOT_SPECIFIED', KUBEFLOW = 'KUBEFLOW', MARKETPLACE = 'MARKETPLACE', } /** converts string to bool */ const asBool = (value: string) => ['true', '1'].includes(value.toLowerCase()); function parseArgs(argv: string[]) { if (argv.length < 3) { const msg = `\ Usage: node server.js [port]. You can specify the API server address using the ML_PIPELINE_SERVICE_HOST and ML_PIPELINE_SERVICE_PORT env vars.`; throw new Error(msg); } const staticDir = path.resolve(argv[2]); const port = parseInt(argv[3] || '3000', 10); return { staticDir, port }; } export type ProcessEnv = NodeJS.ProcessEnv | { [key: string]: string }; export function loadConfigs(argv: string[], env: ProcessEnv): UIConfigs { const { staticDir, port } = parseArgs(argv); /** All configurable environment variables can be found here. */ const { /** minio client use these to retrieve minio objects/artifacts */ MINIO_ACCESS_KEY = 'minio', MINIO_SECRET_KEY = 'minio123', MINIO_PORT = '9000', MINIO_HOST = 'minio-service', MINIO_NAMESPACE = 'kubeflow', MINIO_SSL = 'false', /** minio client use these to retrieve s3 objects/artifacts */ AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_S3_ENDPOINT, AWS_SSL = 'true', /** http/https base URL */ HTTP_BASE_URL = '', /** By default, allowing access to all domains. Modify this flag to allow querying matching domains */ ALLOWED_ARTIFACT_DOMAIN_REGEX = '^.*$', /** http/https fetch with this authorization header key (for example: 'Authorization') */ HTTP_AUTHORIZATION_KEY = '', /** http/https fetch with this authorization header value by default when absent in client request at above key */ HTTP_AUTHORIZATION_DEFAULT_VALUE = '', /** API service will listen to this host */ ML_PIPELINE_SERVICE_HOST = 'localhost', /** API service will listen to this port */ ML_PIPELINE_SERVICE_PORT = '3001', /** path to viewer:tensorboard pod template spec */ VIEWER_TENSORBOARD_POD_TEMPLATE_SPEC_PATH, /** Tensorflow image used for tensorboard viewer */ VIEWER_TENSORBOARD_TF_IMAGE_NAME = 'tensorflow/tensorflow', /** Whether custom visualizations are allowed to be generated by the frontend */ ALLOW_CUSTOM_VISUALIZATIONS = 'false', /** Envoy service will listen to this host */ METADATA_ENVOY_SERVICE_SERVICE_HOST = 'localhost', /** Envoy service will listen to this port */ METADATA_ENVOY_SERVICE_SERVICE_PORT = '9090', /** Is Argo log archive enabled? */ ARGO_ARCHIVE_LOGS = 'false', /** Use minio or s3 client to retrieve archives. */ ARGO_ARCHIVE_ARTIFACTORY = 'minio', /** Bucket to retrive logs from */ ARGO_ARCHIVE_BUCKETNAME = 'mlpipeline', /** Prefix to logs. */ ARGO_ARCHIVE_PREFIX = 'logs', /** Should use server API for log streaming? */ STREAM_LOGS_FROM_SERVER_API = 'false', /** The main container name of a pod where logs are retrieved */ POD_LOG_CONTAINER_NAME = 'main', /** Disables GKE metadata endpoint. */ DISABLE_GKE_METADATA = 'false', /** Enable authorization checks for multi user mode. */ ENABLE_AUTHZ = 'false', /** Deployment type. */ DEPLOYMENT: DEPLOYMENT_STR = '', /** * Set to true to hide the SideNav. When DEPLOYMENT is KUBEFLOW, HIDE_SIDENAV * defaults to true if not explicitly set to false. */ HIDE_SIDENAV, /** * A header user requests have when authenticated. It carries user identity information. * The default value works with Google Cloud IAP. */ KUBEFLOW_USERID_HEADER = 'x-goog-authenticated-user-email', /** * KUBEFLOW_USERID_HEADER's value may have a prefix before user identity. * Use this header to specify what the prefix is. * * e.g. a valid header value for default values can be like `accounts.google.com:user@gmail.com`. */ KUBEFLOW_USERID_PREFIX = 'accounts.google.com:', } = env; return { argo: { archiveArtifactory: ARGO_ARCHIVE_ARTIFACTORY, archiveBucketName: ARGO_ARCHIVE_BUCKETNAME, archiveLogs: asBool(ARGO_ARCHIVE_LOGS), archivePrefix: ARGO_ARCHIVE_PREFIX, }, pod: { logContainerName: POD_LOG_CONTAINER_NAME, }, artifacts: { aws: { accessKey: AWS_ACCESS_KEY_ID || '', endPoint: AWS_S3_ENDPOINT || 's3.amazonaws.com', region: AWS_REGION || 'us-east-1', secretKey: AWS_SECRET_ACCESS_KEY || '', useSSL: asBool(AWS_SSL), }, http: { auth: { defaultValue: HTTP_AUTHORIZATION_DEFAULT_VALUE, key: HTTP_AUTHORIZATION_KEY, }, baseUrl: HTTP_BASE_URL, }, minio: { accessKey: MINIO_ACCESS_KEY, endPoint: MINIO_NAMESPACE && MINIO_NAMESPACE.length > 0 ? `${MINIO_HOST}.${MINIO_NAMESPACE}` : MINIO_HOST, port: parseInt(MINIO_PORT, 10), secretKey: MINIO_SECRET_KEY, useSSL: asBool(MINIO_SSL), }, proxy: loadArtifactsProxyConfig(env), streamLogsFromServerApi: asBool(STREAM_LOGS_FROM_SERVER_API), allowedDomain: ALLOWED_ARTIFACT_DOMAIN_REGEX, }, metadata: { envoyService: { host: METADATA_ENVOY_SERVICE_SERVICE_HOST, port: METADATA_ENVOY_SERVICE_SERVICE_PORT, }, }, pipeline: { host: ML_PIPELINE_SERVICE_HOST, port: ML_PIPELINE_SERVICE_PORT, }, server: { apiVersion1Prefix, apiVersion2Prefix, basePath: BASEPATH, deployment: DEPLOYMENT_STR.toUpperCase() === Deployments.KUBEFLOW ? Deployments.KUBEFLOW : DEPLOYMENT_STR.toUpperCase() === Deployments.MARKETPLACE ? Deployments.MARKETPLACE : Deployments.NOT_SPECIFIED, hideSideNav: HIDE_SIDENAV === undefined ? DEPLOYMENT_STR.toUpperCase() === Deployments.KUBEFLOW : asBool(HIDE_SIDENAV), port, staticDir, }, viewer: { tensorboard: { podTemplateSpec: loadJSON(VIEWER_TENSORBOARD_POD_TEMPLATE_SPEC_PATH), tfImageName: VIEWER_TENSORBOARD_TF_IMAGE_NAME, }, }, visualizations: { allowCustomVisualizations: asBool(ALLOW_CUSTOM_VISUALIZATIONS), }, gkeMetadata: { disabled: asBool(DISABLE_GKE_METADATA), }, auth: { enabled: asBool(ENABLE_AUTHZ), kubeflowUserIdHeader: KUBEFLOW_USERID_HEADER, kubeflowUserIdPrefix: KUBEFLOW_USERID_PREFIX, }, }; } export interface MinioConfigs { accessKey: string; secretKey: string; endPoint: string; port: number; useSSL: boolean; } export interface AWSConfigs { endPoint: string; region: string; accessKey: string; secretKey: string; useSSL: boolean; } export interface HttpConfigs { baseUrl: string; auth: { key: string; defaultValue: string; }; } export interface PipelineConfigs { host: string; port: string | number; } export interface ViewerTensorboardConfig { podTemplateSpec?: object; tfImageName: string; } export interface ViewerConfigs { tensorboard: ViewerTensorboardConfig; } export interface VisualizationsConfigs { allowCustomVisualizations: boolean; } export interface MetadataConfigs { envoyService: { host: string; port: string | number; }; } export interface ArgoConfigs { archiveLogs: boolean; archiveArtifactory: string; archiveBucketName: string; archivePrefix: string; } export interface ServerConfigs { basePath: string; port: string | number; staticDir: string; apiVersion1Prefix: string; apiVersion2Prefix: string; deployment: Deployments; hideSideNav: boolean; } export interface GkeMetadataConfigs { disabled: boolean; } export interface AuthConfigs { enabled: boolean; kubeflowUserIdHeader: string; kubeflowUserIdPrefix: string; } export interface UIConfigs { server: ServerConfigs; artifacts: { aws: AWSConfigs; minio: MinioConfigs; http: HttpConfigs; proxy: ArtifactsProxyConfig; streamLogsFromServerApi: boolean; allowedDomain: string; }; pod: { logContainerName: string; }; argo: ArgoConfigs; metadata: MetadataConfigs; visualizations: VisualizationsConfigs; viewer: ViewerConfigs; pipeline: PipelineConfigs; gkeMetadata: GkeMetadataConfigs; auth: AuthConfigs; }