Merge pull request #5330 from backstage/kubernetes-common

Kubernetes common
This commit is contained in:
Fredrik Adelöw
2021-05-04 20:44:08 +02:00
committed by GitHub
29 changed files with 265 additions and 197 deletions
+1
View File
@@ -34,6 +34,7 @@
"@backstage/backend-common": "^0.6.3",
"@backstage/catalog-model": "^0.7.7",
"@backstage/config": "^0.1.4",
"@backstage/plugin-kubernetes-common": "^0.1.0",
"@google-cloud/container": "^2.2.0",
"@kubernetes/client-node": "^0.14.0",
"@types/express": "^4.17.6",
@@ -15,7 +15,8 @@
*/
import { KubernetesAuthTranslator } from './types';
import { KubernetesRequestBody, ClusterDetails } from '../types/types';
import { ClusterDetails } from '../types/types';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
export class GoogleKubernetesAuthTranslator
implements KubernetesAuthTranslator {
@@ -15,7 +15,8 @@
*/
import { KubernetesAuthTranslator } from './types';
import { KubernetesRequestBody, ClusterDetails } from '../types/types';
import { ClusterDetails } from '../types/types';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
export class ServiceAccountKubernetesAuthTranslator
implements KubernetesAuthTranslator {
@@ -14,7 +14,8 @@
* limitations under the License.
*/
import { KubernetesRequestBody, ClusterDetails } from '../types/types';
import { ClusterDetails } from '../types/types';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
export interface KubernetesAuthTranslator {
decorateClusterDetailsWithAuth(
@@ -20,9 +20,9 @@ import {
CustomResource,
KubernetesFetcher,
KubernetesObjectTypes,
KubernetesRequestBody,
KubernetesServiceLocator,
} from '../types/types';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
import { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';
import { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';
@@ -32,15 +32,17 @@ import lodash, { Dictionary } from 'lodash';
import { Logger } from 'winston';
import {
ClusterDetails,
FetchResponse,
FetchResponseWrapper,
KubernetesErrorTypes,
KubernetesFetcher,
KubernetesFetchError,
KubernetesObjectTypes,
ObjectFetchParams,
CustomResource,
} from '../types/types';
import {
FetchResponse,
KubernetesFetchError,
KubernetesErrorTypes,
} from '@backstage/plugin-kubernetes-common';
import { KubernetesClientProvider } from './KubernetesClientProvider';
export interface Clients {
@@ -23,11 +23,11 @@ import { MultiTenantServiceLocator } from '../service-locator/MultiTenantService
import {
ClusterDetails,
KubernetesClustersSupplier,
KubernetesRequestBody,
KubernetesServiceLocator,
ServiceLocatorMethod,
CustomResource,
} from '../types/types';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
import { KubernetesClientProvider } from './KubernetesClientProvider';
import { KubernetesFanOutHandler } from './KubernetesFanOutHandler';
import { KubernetesClientBasedFetcher } from './KubernetesFetcher';
+60 -146
View File
@@ -14,146 +14,14 @@
* limitations under the License.
*/
import {
ExtensionsV1beta1Ingress,
V1ConfigMap,
V1Deployment,
V1HorizontalPodAutoscaler,
V1Pod,
V1ReplicaSet,
V1Service,
} from '@kubernetes/client-node';
import { Entity } from '@backstage/catalog-model';
import type {
FetchResponse,
KubernetesFetchError,
} from '@backstage/plugin-kubernetes-common';
export interface ClusterDetails {
name: string;
url: string;
authProvider: string;
serviceAccountToken?: string | undefined;
skipTLSVerify?: boolean;
}
export interface KubernetesRequestBody {
auth?: {
google?: string;
};
entity: Entity;
}
export interface ClusterObjects {
cluster: { name: string };
resources: FetchResponse[];
errors: KubernetesFetchError[];
}
export interface ObjectsByEntityResponse {
items: ClusterObjects[];
}
export interface FetchResponseWrapper {
errors: KubernetesFetchError[];
responses: FetchResponse[];
}
export type FetchResponse =
| PodFetchResponse
| ServiceFetchResponse
| ConfigMapFetchResponse
| DeploymentFetchResponse
| ReplicaSetsFetchResponse
| HorizontalPodAutoscalersFetchResponse
| IngressesFetchResponse
| CustomResourceFetchResponse;
// TODO fairly sure there's a easier way to do this
export type KubernetesObjectTypes =
| 'pods'
| 'services'
| 'configmaps'
| 'deployments'
| 'replicasets'
| 'horizontalpodautoscalers'
| 'ingresses'
| 'customresources';
export interface PodFetchResponse {
type: 'pods';
resources: Array<V1Pod>;
}
export interface ServiceFetchResponse {
type: 'services';
resources: Array<V1Service>;
}
export interface ConfigMapFetchResponse {
type: 'configmaps';
resources: Array<V1ConfigMap>;
}
export interface DeploymentFetchResponse {
type: 'deployments';
resources: Array<V1Deployment>;
}
export interface ReplicaSetsFetchResponse {
type: 'replicasets';
resources: Array<V1ReplicaSet>;
}
export interface HorizontalPodAutoscalersFetchResponse {
type: 'horizontalpodautoscalers';
resources: Array<V1HorizontalPodAutoscaler>;
}
export interface IngressesFetchResponse {
type: 'ingresses';
resources: Array<ExtensionsV1beta1Ingress>;
}
export interface CustomResourceFetchResponse {
type: 'customresources';
resources: Array<any>;
}
export interface ObjectFetchParams {
serviceId: string;
clusterDetails: ClusterDetails;
objectTypesToFetch: Set<KubernetesObjectTypes>;
labelSelector: string;
customResources: CustomResource[];
}
// Fetches information from a kubernetes cluster using the cluster details object
// to target a specific cluster
export interface KubernetesFetcher {
fetchObjectsForService(
params: ObjectFetchParams,
): Promise<FetchResponseWrapper>;
}
// Used to locate which cluster(s) a service is running on
export interface KubernetesServiceLocator {
getClustersByServiceId(serviceId: string): Promise<ClusterDetails[]>;
}
// Used to load cluster details from different sources
export interface KubernetesClustersSupplier {
getClusters(): Promise<ClusterDetails[]>;
}
export type KubernetesErrorTypes =
| 'BAD_REQUEST'
| 'UNAUTHORIZED_ERROR'
| 'SYSTEM_ERROR'
| 'UNKNOWN_ERROR';
export interface KubernetesFetchError {
errorType: KubernetesErrorTypes;
statusCode?: number;
resourcePath?: string;
}
export type ClusterLocatorMethod =
| ConfigClusterLocatorMethod
| GKEClusterLocatorMethod;
export interface ConfigClusterLocatorMethod {
/**
@@ -195,15 +63,61 @@ export interface GKEClusterLocatorMethod {
region?: string;
}
export type ClusterLocatorMethod =
| ConfigClusterLocatorMethod
| GKEClusterLocatorMethod;
export type ServiceLocatorMethod = 'multiTenant' | 'http'; // TODO implement http
export type AuthProviderType = 'google' | 'serviceAccount' | 'aws';
export interface CustomResource {
group: string;
apiVersion: string;
plural: string;
}
export interface ObjectFetchParams {
serviceId: string;
clusterDetails: ClusterDetails;
objectTypesToFetch: Set<KubernetesObjectTypes>;
labelSelector: string;
customResources: CustomResource[];
}
// Fetches information from a kubernetes cluster using the cluster details object
// to target a specific cluster
export interface KubernetesFetcher {
fetchObjectsForService(
params: ObjectFetchParams,
): Promise<FetchResponseWrapper>;
}
export interface FetchResponseWrapper {
errors: KubernetesFetchError[];
responses: FetchResponse[];
}
// TODO fairly sure there's a easier way to do this
export type KubernetesObjectTypes =
| 'pods'
| 'services'
| 'configmaps'
| 'deployments'
| 'replicasets'
| 'horizontalpodautoscalers'
| 'ingresses'
| 'customresources';
// Used to load cluster details from different sources
export interface KubernetesClustersSupplier {
getClusters(): Promise<ClusterDetails[]>;
}
// Used to locate which cluster(s) a service is running on
export interface KubernetesServiceLocator {
getClustersByServiceId(serviceId: string): Promise<ClusterDetails[]>;
}
export type ServiceLocatorMethod = 'multiTenant' | 'http'; // TODO implement http
export interface ClusterDetails {
name: string;
url: string;
authProvider: string;
serviceAccountToken?: string | undefined;
skipTLSVerify?: boolean;
}
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
extends: [require.resolve('@backstage/cli/config/eslint.backend')],
};
+7
View File
@@ -0,0 +1,7 @@
# @backstage/plugin-kubernetes-common
## 0.1.0
### Minor Changes
- Adds types to be shared by the backend and the front end.
+3
View File
@@ -0,0 +1,3 @@
# @backstage/plugin-kubernetes-common
Common types and functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend.
+49
View File
@@ -0,0 +1,49 @@
{
"name": "@backstage/plugin-kubernetes-common",
"description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin",
"version": "0.1.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "plugin/kubernetes-common"
},
"keywords": [
"techdocs",
"kubernetes"
],
"files": [
"dist"
],
"scripts": {
"build": "backstage-cli build",
"lint": "backstage-cli lint",
"test": "backstage-cli test --passWithNoTests",
"prepack": "backstage-cli prepack",
"postpack": "backstage-cli postpack",
"clean": "backstage-cli clean"
},
"bugs": {
"url": "https://github.com/backstage/backstage/issues"
},
"dependencies": {
"@backstage/catalog-model": "^0.7.6",
"@kubernetes/client-node": "^0.14.0"
},
"devDependencies": {
"@backstage/cli": "^0.6.5"
},
"jest": {
"roots": [
".."
]
}
}
@@ -14,29 +14,4 @@
* limitations under the License.
*/
import {
ClusterLocatorMethod,
CustomResource,
} from '@backstage/plugin-kubernetes-backend';
export interface Config {
kubernetes?: {
/**
* @visibility frontend
*/
serviceLocatorMethod: {
/**
* @visibility frontend
*/
type: 'multiTenant';
};
/**
* @visibility frontend
*/
clusterLocatorMethods: ClusterLocatorMethod[];
/**
* @visibility frontend
*/
customResources?: CustomResource[];
};
}
export * from './types';
+107
View File
@@ -0,0 +1,107 @@
/*
* Copyright 2020 Spotify AB
*
* 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 {
ExtensionsV1beta1Ingress,
V1ConfigMap,
V1Deployment,
V1HorizontalPodAutoscaler,
V1Pod,
V1ReplicaSet,
V1Service,
} from '@kubernetes/client-node';
import { Entity } from '@backstage/catalog-model';
export interface KubernetesRequestBody {
auth?: {
google?: string;
};
entity: Entity;
}
export interface ClusterObjects {
cluster: { name: string };
resources: FetchResponse[];
errors: KubernetesFetchError[];
}
export interface ObjectsByEntityResponse {
items: ClusterObjects[];
}
export type AuthProviderType = 'google' | 'serviceAccount' | 'aws';
export type FetchResponse =
| PodFetchResponse
| ServiceFetchResponse
| ConfigMapFetchResponse
| DeploymentFetchResponse
| ReplicaSetsFetchResponse
| HorizontalPodAutoscalersFetchResponse
| IngressesFetchResponse
| CustomResourceFetchResponse;
export interface PodFetchResponse {
type: 'pods';
resources: Array<V1Pod>;
}
export interface ServiceFetchResponse {
type: 'services';
resources: Array<V1Service>;
}
export interface ConfigMapFetchResponse {
type: 'configmaps';
resources: Array<V1ConfigMap>;
}
export interface DeploymentFetchResponse {
type: 'deployments';
resources: Array<V1Deployment>;
}
export interface ReplicaSetsFetchResponse {
type: 'replicasets';
resources: Array<V1ReplicaSet>;
}
export interface HorizontalPodAutoscalersFetchResponse {
type: 'horizontalpodautoscalers';
resources: Array<V1HorizontalPodAutoscaler>;
}
export interface IngressesFetchResponse {
type: 'ingresses';
resources: Array<ExtensionsV1beta1Ingress>;
}
export interface CustomResourceFetchResponse {
type: 'customresources';
resources: Array<any>;
}
export interface KubernetesFetchError {
errorType: KubernetesErrorTypes;
statusCode?: number;
resourcePath?: string;
}
export type KubernetesErrorTypes =
| 'BAD_REQUEST'
| 'UNAUTHORIZED_ERROR'
| 'SYSTEM_ERROR'
| 'UNKNOWN_ERROR';
+2 -4
View File
@@ -19,7 +19,6 @@
"backstage",
"kubernetes"
],
"configSchema": "schema.d.ts",
"scripts": {
"build": "backstage-cli plugin:build",
"start": "backstage-cli plugin:serve",
@@ -35,7 +34,7 @@
"@backstage/config": "^0.1.4",
"@backstage/core": "^0.7.7",
"@backstage/plugin-catalog-react": "^0.1.3",
"@backstage/plugin-kubernetes-backend": "^0.3.2",
"@backstage/plugin-kubernetes-common": "^0.1.0",
"@backstage/theme": "^0.2.6",
"@kubernetes/client-node": "^0.14.0",
"@material-ui/core": "^4.11.0",
@@ -63,7 +62,6 @@
"msw": "^0.21.2"
},
"files": [
"dist",
"schema.d.ts"
"dist"
]
}
@@ -19,7 +19,7 @@ import { KubernetesApi } from './types';
import {
KubernetesRequestBody,
ObjectsByEntityResponse,
} from '@backstage/plugin-kubernetes-backend';
} from '@backstage/plugin-kubernetes-common';
export class KubernetesBackendClient implements KubernetesApi {
private readonly discoveryApi: DiscoveryApi;
+1 -1
View File
@@ -18,7 +18,7 @@ import { createApiRef } from '@backstage/core';
import {
KubernetesRequestBody,
ObjectsByEntityResponse,
} from '@backstage/plugin-kubernetes-backend';
} from '@backstage/plugin-kubernetes-common';
export const kubernetesApiRef = createApiRef<KubernetesApi>({
id: 'plugin.kubernetes.service',
@@ -17,7 +17,7 @@
import React from 'react';
import { WarningPanel } from '@backstage/core';
import { Typography } from '@material-ui/core';
import { ClusterObjects } from '@backstage/plugin-kubernetes-backend';
import { ClusterObjects } from '@backstage/plugin-kubernetes-common';
const clustersWithErrorsToErrorMessage = (
clustersWithErrors: ClusterObjects[],
@@ -31,7 +31,7 @@ import {
StatusOK,
} from '@backstage/core';
import { Entity } from '@backstage/catalog-model';
import { ClusterObjects } from '@backstage/plugin-kubernetes-backend';
import { ClusterObjects } from '@backstage/plugin-kubernetes-common';
import { ErrorPanel } from './ErrorPanel';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { DeploymentsAccordions } from '../DeploymentsAccordions';
@@ -30,7 +30,7 @@ import * as maxedOutHpa from './__fixtures__/hpa-maxed-out.json';
import {
FetchResponse,
ObjectsByEntityResponse,
} from '@backstage/plugin-kubernetes-backend';
} from '@backstage/plugin-kubernetes-common';
const CLUSTER_NAME = 'cluster-a';
@@ -15,7 +15,7 @@
*/
import { DetectedError, DetectedErrorsByCluster } from './types';
import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-backend';
import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common';
import { groupResponses } from '../utils/response';
import { detectErrorsInPods } from './pods';
import { detectErrorsInDeployments } from './deployments';
@@ -22,7 +22,7 @@ import { useEffect, useState } from 'react';
import {
KubernetesRequestBody,
ObjectsByEntityResponse,
} from '@backstage/plugin-kubernetes-backend';
} from '@backstage/plugin-kubernetes-common';
export interface KubernetesObjects {
kubernetesObjects: ObjectsByEntityResponse | undefined;
@@ -15,7 +15,7 @@
*/
import { KubernetesAuthProvider } from './types';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-backend';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
export class AwsKubernetesAuthProvider implements KubernetesAuthProvider {
async decorateRequestBodyForAuth(
@@ -16,7 +16,7 @@
import { OAuthApi } from '@backstage/core';
import { KubernetesAuthProvider } from './types';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-backend';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider {
authProvider: OAuthApi;
@@ -15,7 +15,7 @@
*/
import { OAuthApi } from '@backstage/core';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-backend';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
import { KubernetesAuthProvider, KubernetesAuthProvidersApi } from './types';
import { GoogleKubernetesAuthProvider } from './GoogleKubernetesAuthProvider';
import { ServiceAccountKubernetesAuthProvider } from './ServiceAccountKubernetesAuthProvider';
@@ -15,7 +15,7 @@
*/
import { KubernetesAuthProvider } from './types';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-backend';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
export class ServiceAccountKubernetesAuthProvider
implements KubernetesAuthProvider {
@@ -15,7 +15,7 @@
*/
import { createApiRef } from '@backstage/core';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-backend';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
export interface KubernetesAuthProvider {
decorateRequestBodyForAuth(
+1 -1
View File
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { FetchResponse } from '@backstage/plugin-kubernetes-backend';
import { FetchResponse } from '@backstage/plugin-kubernetes-common';
import { GroupedResponses } from '../types/types';
// TODO this could probably be a lodash groupBy