refactor: Refactors the Kubernetes plugin in line with ADR11 (#19446)

* refactor: k8s plugins

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

* chore: move more files

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

* chore: fix

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

* fix: tsc

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

* chore: changeset

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

* chore: api report

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

* fix: catalog

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

* fix: types

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

* fix: update lock

Signed-off-by: Matthew Clarke <mclarke@spotify.com>

---------

Signed-off-by: Matthew Clarke <mclarke@spotify.com>
This commit is contained in:
Matthew Clarke
2023-09-26 18:40:10 -04:00
committed by GitHub
parent ec13fcc4a7
commit 2d8151061c
215 changed files with 17249 additions and 992 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-kubernetes-common': minor
'@backstage/plugin-kubernetes-react': minor
'@backstage/plugin-kubernetes': minor
---
Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet
+119
View File
@@ -5,7 +5,9 @@
```ts
import { BasicPermission } from '@backstage/plugin-permission-common';
import { Entity } from '@backstage/catalog-model';
import { FetchResponse as FetchResponse_2 } from '@backstage/plugin-kubernetes-common';
import type { JsonObject } from '@backstage/types';
import { ObjectsByEntityResponse as ObjectsByEntityResponse_2 } from '@backstage/plugin-kubernetes-common';
import { PodStatus } from '@kubernetes/client-node';
import { V1ConfigMap } from '@kubernetes/client-node';
import { V1CronJob } from '@kubernetes/client-node';
@@ -174,6 +176,67 @@ export interface DeploymentFetchResponse {
type: 'deployments';
}
// @public (undocumented)
export interface DeploymentResources {
// (undocumented)
deployments: V1Deployment[];
// (undocumented)
horizontalPodAutoscalers: V1HorizontalPodAutoscaler[];
// (undocumented)
pods: V1Pod[];
// (undocumented)
replicaSets: V1ReplicaSet[];
}
// @public
export interface DetectedError {
// (undocumented)
message: string;
// (undocumented)
occurrenceCount: number;
// (undocumented)
proposedFix?: ProposedFix;
// (undocumented)
severity: ErrorSeverity;
// (undocumented)
sourceRef: ResourceRef;
// (undocumented)
type: string;
}
// @public
export type DetectedErrorsByCluster = Map<string, DetectedError[]>;
// @public
export const detectErrors: (
objects: ObjectsByEntityResponse_2,
) => DetectedErrorsByCluster;
// @public (undocumented)
export interface DocsSolution extends ProposedFixBase {
// (undocumented)
docsLink: string;
// (undocumented)
type: 'docs';
}
// @public (undocumented)
export interface ErrorMapper<T> {
// (undocumented)
detectErrors: (resource: T) => DetectedError[];
}
// @public
export type ErrorSeverity = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
// @public (undocumented)
export interface EventsSolution extends ProposedFixBase {
// (undocumented)
podName: string;
// (undocumented)
type: 'events';
}
// @public (undocumented)
export type FetchResponse =
| PodFetchResponse
@@ -191,6 +254,29 @@ export type FetchResponse =
| DaemonSetsFetchResponse
| PodStatusFetchResponse;
// @public (undocumented)
export interface GroupedResponses extends DeploymentResources {
// (undocumented)
configMaps: V1ConfigMap[];
// (undocumented)
cronJobs: V1CronJob[];
// (undocumented)
customResources: any[];
// (undocumented)
ingresses: V1Ingress[];
// (undocumented)
jobs: V1Job[];
// (undocumented)
services: V1Service[];
// (undocumented)
statefulsets: V1StatefulSet[];
}
// @public (undocumented)
export const groupResponses: (
fetchResponse: FetchResponse_2[],
) => GroupedResponses;
// @public (undocumented)
export interface HorizontalPodAutoscalersFetchResponse {
// (undocumented)
@@ -251,6 +337,14 @@ export interface LimitRangeFetchResponse {
type: 'limitranges';
}
// @public (undocumented)
export interface LogSolution extends ProposedFixBase {
// (undocumented)
container: string;
// (undocumented)
type: 'logs';
}
// @public (undocumented)
export interface ObjectsByEntityResponse {
// (undocumented)
@@ -273,6 +367,19 @@ export interface PodStatusFetchResponse {
type: 'podstatus';
}
// @public (undocumented)
export type ProposedFix = LogSolution | DocsSolution | EventsSolution;
// @public (undocumented)
export interface ProposedFixBase {
// (undocumented)
actions: string[];
// (undocumented)
errorType: string;
// (undocumented)
rootCauseExplanation: string;
}
// @public (undocumented)
export interface RawFetchError {
// (undocumented)
@@ -289,6 +396,18 @@ export interface ReplicaSetsFetchResponse {
type: 'replicasets';
}
// @public
export interface ResourceRef {
// (undocumented)
apiGroup: string;
// (undocumented)
kind: string;
// (undocumented)
name: string;
// (undocumented)
namespace: string;
}
// @public (undocumented)
export interface ServiceFetchResponse {
// (undocumented)
+11 -2
View File
@@ -40,11 +40,20 @@
},
"dependencies": {
"@backstage/catalog-model": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"@kubernetes/client-node": "0.18.1"
"@backstage/types": "workspace:^",
"@kubernetes/client-node": "0.18.1",
"kubernetes-models": "^4.3.1",
"lodash": "^4.17.21",
"luxon": "^3.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^"
"@backstage/cli": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/test-utils": "workspace:^",
"msw": "^1.3.1"
},
"jest": {
"roots": [
@@ -16,7 +16,7 @@
import { DetectedError, DetectedErrorsByCluster } from './types';
import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common';
import { groupResponses } from '../utils/response';
import { groupResponses } from '../util';
import { detectErrorsInPods } from './pods';
import { detectErrorsInDeployments } from './deployments';
import { detectErrorsInHpa } from './hpas';
@@ -0,0 +1,18 @@
/*
* Copyright 2020 The Backstage 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.
*/
export * from './types';
export { detectErrors } from './error-detection';
@@ -54,29 +54,35 @@ export interface DetectedError {
occurrenceCount: number;
}
/** @public */
export type ProposedFix = LogSolution | DocsSolution | EventsSolution;
interface ProposedFixBase {
/** @public */
export interface ProposedFixBase {
errorType: string;
rootCauseExplanation: string;
actions: string[];
}
/** @public */
export interface LogSolution extends ProposedFixBase {
type: 'logs';
container: string;
}
/** @public */
export interface DocsSolution extends ProposedFixBase {
type: 'docs';
docsLink: string;
}
/** @public */
export interface EventsSolution extends ProposedFixBase {
type: 'events';
podName: string;
}
/** @public */
export interface ErrorMapper<T> {
detectErrors: (resource: T) => DetectedError[];
}
+2
View File
@@ -26,3 +26,5 @@ export {
kubernetesProxyPermission,
kubernetesPermissions,
} from './permissions';
export * from './error-detection';
export * from './util';
+19
View File
@@ -262,3 +262,22 @@ export interface ClientPodStatus {
memory: ClientCurrentResourceUsage;
containers: ClientContainerStatus[];
}
/** @public */
export interface DeploymentResources {
pods: V1Pod[];
replicaSets: V1ReplicaSet[];
deployments: V1Deployment[];
horizontalPodAutoscalers: V1HorizontalPodAutoscaler[];
}
/** @public */
export interface GroupedResponses extends DeploymentResources {
services: V1Service[];
configMaps: V1ConfigMap[];
ingresses: V1Ingress[];
jobs: V1Job[];
cronJobs: V1CronJob[];
customResources: any[];
statefulsets: V1StatefulSet[];
}
@@ -13,4 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Cluster } from './Cluster';
export * from './response';
@@ -15,12 +15,13 @@
*/
import { FetchResponse } from '@backstage/plugin-kubernetes-common';
import { GroupedResponses } from '../types/types';
import { GroupedResponses } from '../types';
// TODO this could probably be a lodash groupBy
/** @public */
export const groupResponses = (
fetchResponse: FetchResponse[],
): GroupedResponses => {
// TODO this could probably be a lodash groupBy
return fetchResponse.reduce(
(prev, next) => {
switch (next.type) {
+1
View File
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
+5
View File
@@ -0,0 +1,5 @@
# @backstage/plugin-kubernetes-react
Welcome to the web library package for the kubernetes-react plugin!
_This plugin was created through the Backstage CLI_
+751
View File
@@ -0,0 +1,751 @@
## API Report File for "@backstage/plugin-kubernetes-react"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { ApiRef } from '@backstage/core-plugin-api';
import { AsyncState } from 'react-use/lib/useAsyncFn';
import { ClientContainerStatus } from '@backstage/plugin-kubernetes-common';
import { ClientPodStatus } from '@backstage/plugin-kubernetes-common';
import { ClusterAttributes } from '@backstage/plugin-kubernetes-common';
import { ClusterObjects } from '@backstage/plugin-kubernetes-common';
import { CustomObjectsByEntityRequest } from '@backstage/plugin-kubernetes-common';
import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common';
import { DetectedError } from '@backstage/plugin-kubernetes-common';
import { DetectedErrorsByCluster } from '@backstage/plugin-kubernetes-common';
import { DiscoveryApi } from '@backstage/core-plugin-api';
import { Entity } from '@backstage/catalog-model';
import { Event as Event_2 } from 'kubernetes-models/v1';
import { GroupedResponses } from '@backstage/plugin-kubernetes-common';
import { IContainer } from 'kubernetes-models/v1';
import { IContainerStatus } from 'kubernetes-models/v1';
import { IdentityApi } from '@backstage/core-plugin-api';
import { IIoK8sApimachineryPkgApisMetaV1ObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta';
import { IObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta';
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
import { OAuthApi } from '@backstage/core-plugin-api';
import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common';
import { OpenIdConnectApi } from '@backstage/core-plugin-api';
import { Pod } from 'kubernetes-models/v1';
import { Pod as Pod_2 } from 'kubernetes-models/v1/Pod';
import { default as React_2 } from 'react';
import * as React_3 from 'react';
import { TypeMeta } from '@kubernetes-models/base';
import { V1HorizontalPodAutoscaler } from '@kubernetes/client-node';
import { V1Job } from '@kubernetes/client-node';
import { V1ObjectMeta } from '@kubernetes/client-node';
import { V1Pod } from '@kubernetes/client-node';
import { WorkloadsByEntityRequest } from '@backstage/plugin-kubernetes-common';
// @public (undocumented)
export class AksKubernetesAuthProvider implements KubernetesAuthProvider {
constructor(microsoftAuthApi: OAuthApi);
// (undocumented)
decorateRequestBodyForAuth(
requestBody: KubernetesRequestBody,
): Promise<KubernetesRequestBody>;
// (undocumented)
getCredentials(): Promise<{
token?: string;
}>;
}
// @public
export const Cluster: ({
clusterObjects,
podsWithErrors,
}: ClusterProps) => React_2.JSX.Element;
// @public (undocumented)
export const ClusterContext: React_2.Context<ClusterAttributes>;
// @public
export type ClusterProps = {
clusterObjects: ClusterObjects;
podsWithErrors: Set<string>;
children?: React_2.ReactNode;
};
// @public
export const ContainerCard: React_2.FC<ContainerCardProps>;
// @public
export interface ContainerCardProps {
// (undocumented)
containerMetrics?: ClientContainerStatus;
// (undocumented)
containerSpec?: IContainer;
// (undocumented)
containerStatus: IContainerStatus;
// (undocumented)
podScope: PodScope;
}
// @public
export interface ContainerScope extends PodScope {
// (undocumented)
containerName: string;
}
// @public (undocumented)
export const CronJobsAccordions: ({}: CronJobsAccordionsProps) => React_2.JSX.Element;
// @public (undocumented)
export type CronJobsAccordionsProps = {
children?: React_2.ReactNode;
};
// @public (undocumented)
export const CustomResources: ({}: CustomResourcesProps) => React_2.JSX.Element;
// @public (undocumented)
export interface CustomResourcesProps {
// (undocumented)
children?: React_2.ReactNode;
}
// @public
export const DetectedErrorsContext: React_2.Context<DetectedError[]>;
// @public
export const ErrorList: ({
podAndErrors,
}: ErrorListProps) => React_2.JSX.Element;
// @public
export interface ErrorListProps {
// (undocumented)
podAndErrors: PodAndErrors[];
}
// @public (undocumented)
export type ErrorMatcher = {
metadata?: IIoK8sApimachineryPkgApisMetaV1ObjectMeta;
} & TypeMeta;
// @public (undocumented)
export const ErrorPanel: ({
entityName,
errorMessage,
clustersWithErrors,
}: ErrorPanelProps) => React_2.JSX.Element;
// @public (undocumented)
export type ErrorPanelProps = {
entityName: string;
errorMessage?: string;
clustersWithErrors?: ClusterObjects[];
children?: React_2.ReactNode;
};
// @public (undocumented)
export const ErrorReporting: ({
detectedErrors,
}: ErrorReportingProps) => React_3.JSX.Element;
// @public (undocumented)
export type ErrorReportingProps = {
detectedErrors: DetectedErrorsByCluster;
};
// @public
export const Events: ({
involvedObjectName,
namespace,
clusterName,
warningEventsOnly,
}: EventsProps) => React_2.JSX.Element;
// @public
export const EventsContent: ({
events,
warningEventsOnly,
}: EventsContentProps) => React_2.JSX.Element;
// @public
export interface EventsContentProps {
// (undocumented)
events: Event_2[];
// (undocumented)
warningEventsOnly?: boolean;
}
// @public
export interface EventsOptions {
// (undocumented)
clusterName: string;
// (undocumented)
involvedObjectName: string;
// (undocumented)
namespace: string;
}
// @public
export interface EventsProps {
// (undocumented)
clusterName: string;
// (undocumented)
involvedObjectName: string;
// (undocumented)
namespace: string;
// (undocumented)
warningEventsOnly?: boolean;
}
// @public
export const FixDialog: React_2.FC<FixDialogProps>;
// @public
export interface FixDialogProps {
// (undocumented)
clusterName: string;
// (undocumented)
error: DetectedError;
// (undocumented)
open?: boolean;
// (undocumented)
pod: Pod_2;
}
// @public (undocumented)
export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider {
constructor(authProvider: OAuthApi);
// (undocumented)
authProvider: OAuthApi;
// (undocumented)
decorateRequestBodyForAuth(
requestBody: KubernetesRequestBody,
): Promise<KubernetesRequestBody>;
// (undocumented)
getCredentials(): Promise<{
token: string;
}>;
}
// @public (undocumented)
export const GroupedResponsesContext: React_2.Context<GroupedResponses>;
// @public (undocumented)
export const HorizontalPodAutoscalerDrawer: (props: {
hpa: V1HorizontalPodAutoscaler;
expanded?: boolean;
children?: React_2.ReactNode;
}) => React_2.JSX.Element;
// @public (undocumented)
export const IngressesAccordions: ({}: IngressesAccordionsProps) => React_2.JSX.Element;
// @public (undocumented)
export type IngressesAccordionsProps = {};
// @public (undocumented)
export const JobsAccordions: ({
jobs,
}: JobsAccordionsProps) => React_2.JSX.Element;
// @public (undocumented)
export type JobsAccordionsProps = {
jobs: V1Job[];
children?: React_2.ReactNode;
};
// @public (undocumented)
export interface KubernetesApi {
// (undocumented)
getClusters(): Promise<
{
name: string;
authProvider: string;
oidcTokenProvider?: string | undefined;
}[]
>;
// (undocumented)
getCustomObjectsByEntity(
request: CustomObjectsByEntityRequest,
): Promise<ObjectsByEntityResponse>;
// (undocumented)
getObjectsByEntity(
requestBody: KubernetesRequestBody,
): Promise<ObjectsByEntityResponse>;
// (undocumented)
getWorkloadsByEntity(
request: WorkloadsByEntityRequest,
): Promise<ObjectsByEntityResponse>;
// (undocumented)
proxy(options: {
clusterName: string;
path: string;
init?: RequestInit;
}): Promise<Response>;
}
// @public (undocumented)
export const kubernetesApiRef: ApiRef<KubernetesApi>;
// @public (undocumented)
export interface KubernetesAuthProvider {
// (undocumented)
decorateRequestBodyForAuth(
requestBody: KubernetesRequestBody,
): Promise<KubernetesRequestBody>;
// (undocumented)
getCredentials(): Promise<{
token?: string;
}>;
}
// @public (undocumented)
export class KubernetesAuthProviders implements KubernetesAuthProvidersApi {
constructor(options: {
microsoftAuthApi: OAuthApi;
googleAuthApi: OAuthApi;
oidcProviders?: {
[key: string]: OpenIdConnectApi;
};
});
// (undocumented)
decorateRequestBodyForAuth(
authProvider: string,
requestBody: KubernetesRequestBody,
): Promise<KubernetesRequestBody>;
// (undocumented)
getCredentials(authProvider: string): Promise<{
token?: string;
}>;
}
// @public (undocumented)
export interface KubernetesAuthProvidersApi {
// (undocumented)
decorateRequestBodyForAuth(
authProvider: string,
requestBody: KubernetesRequestBody,
): Promise<KubernetesRequestBody>;
// (undocumented)
getCredentials(authProvider: string): Promise<{
token?: string;
}>;
}
// @public (undocumented)
export const kubernetesAuthProvidersApiRef: ApiRef<KubernetesAuthProvidersApi>;
// @public (undocumented)
export class KubernetesBackendClient implements KubernetesApi {
constructor(options: {
discoveryApi: DiscoveryApi;
identityApi: IdentityApi;
kubernetesAuthProvidersApi: KubernetesAuthProvidersApi;
});
// (undocumented)
getClusters(): Promise<
{
name: string;
authProvider: string;
}[]
>;
// (undocumented)
getCustomObjectsByEntity(
request: CustomObjectsByEntityRequest,
): Promise<ObjectsByEntityResponse>;
// (undocumented)
getObjectsByEntity(
requestBody: KubernetesRequestBody,
): Promise<ObjectsByEntityResponse>;
// (undocumented)
getWorkloadsByEntity(
request: WorkloadsByEntityRequest,
): Promise<ObjectsByEntityResponse>;
// (undocumented)
proxy(options: {
clusterName: string;
path: string;
init?: RequestInit;
}): Promise<Response>;
}
// @public
export const KubernetesDrawer: ({
open,
label,
drawerContentsHeader,
kubernetesObject,
children,
}: KubernetesDrawerProps) => React_2.JSX.Element;
// @public (undocumented)
export interface KubernetesDrawerable {
// (undocumented)
metadata?: V1ObjectMeta;
}
// @public
export interface KubernetesDrawerProps {
// (undocumented)
children?: React_2.ReactNode;
// (undocumented)
drawerContentsHeader?: React_2.ReactNode;
// (undocumented)
kubernetesObject: KubernetesObject;
// (undocumented)
label: React_2.ReactNode;
// (undocumented)
open?: boolean;
}
// @public
export interface KubernetesObject {
// (undocumented)
kind: string;
// (undocumented)
metadata?: IObjectMeta;
}
// @public (undocumented)
export interface KubernetesObjects {
// (undocumented)
error?: string;
// (undocumented)
kubernetesObjects?: ObjectsByEntityResponse;
// (undocumented)
loading: boolean;
}
// @public (undocumented)
export interface KubernetesProxyApi {
// (undocumented)
getEventsByInvolvedObjectName(request: {
clusterName: string;
involvedObjectName: string;
namespace: string;
}): Promise<Event_2[]>;
// (undocumented)
getPodLogs(request: {
podName: string;
namespace: string;
clusterName: string;
containerName: string;
previous?: boolean;
}): Promise<{
text: string;
}>;
}
// @public (undocumented)
export const kubernetesProxyApiRef: ApiRef<KubernetesProxyApi>;
// @public
export class KubernetesProxyClient {
constructor(options: { kubernetesApi: KubernetesApi });
// (undocumented)
getEventsByInvolvedObjectName({
clusterName,
involvedObjectName,
namespace,
}: {
clusterName: string;
involvedObjectName: string;
namespace: string;
}): Promise<Event_2[]>;
// (undocumented)
getPodLogs({
podName,
namespace,
clusterName,
containerName,
previous,
}: {
podName: string;
namespace: string;
clusterName: string;
containerName: string;
previous?: boolean;
}): Promise<{
text: string;
}>;
}
// @public (undocumented)
export const KubernetesStructuredMetadataTableDrawer: <
T extends KubernetesDrawerable,
>({
object,
renderObject,
kind,
buttonVariant,
expanded,
children,
}: KubernetesStructuredMetadataTableDrawerProps<T>) => React_2.JSX.Element;
// @public (undocumented)
export interface KubernetesStructuredMetadataTableDrawerProps<
T extends KubernetesDrawerable,
> {
// (undocumented)
buttonVariant?: 'h5' | 'subtitle2';
// (undocumented)
children?: React_2.ReactNode;
// (undocumented)
expanded?: boolean;
// (undocumented)
kind: string;
// (undocumented)
object: T;
// (undocumented)
renderObject: (obj: T) => object;
}
// @public (undocumented)
export const LinkErrorPanel: ({
cluster,
errorMessage,
}: LinkErrorPanelProps) => React_2.JSX.Element;
// @public (undocumented)
export type LinkErrorPanelProps = {
cluster: ClusterAttributes;
errorMessage?: string;
children?: React_2.ReactNode;
};
// @public
export const ManifestYaml: ({
object,
}: ManifestYamlProps) => React_2.JSX.Element;
// @public
export interface ManifestYamlProps {
// (undocumented)
object: object;
}
// @public (undocumented)
export class OidcKubernetesAuthProvider implements KubernetesAuthProvider {
constructor(providerName: string, authProvider: OpenIdConnectApi);
// (undocumented)
authProvider: OpenIdConnectApi;
// (undocumented)
decorateRequestBodyForAuth(
requestBody: KubernetesRequestBody,
): Promise<KubernetesRequestBody>;
// (undocumented)
getCredentials(): Promise<{
token: string;
}>;
// (undocumented)
providerName: string;
}
// @public
export const PendingPodContent: ({
pod,
}: PendingPodContentProps) => React_2.JSX.Element;
// @public
export interface PendingPodContentProps {
// (undocumented)
pod: Pod;
}
// @public
export interface PodAndErrors {
// (undocumented)
clusterName: string;
// (undocumented)
errors: DetectedError[];
// (undocumented)
pod: Pod;
}
// @public (undocumented)
export type PodColumns = 'READY' | 'RESOURCE';
// @public
export const PodDrawer: ({
podAndErrors,
open,
}: PodDrawerProps) => React_2.JSX.Element;
// @public
export interface PodDrawerProps {
// (undocumented)
open?: boolean;
// (undocumented)
podAndErrors: PodAndErrors;
}
// @public
export const PodExecTerminal: (
props: PodExecTerminalProps,
) => React_2.JSX.Element;
// @public
export const PodExecTerminalDialog: (
props: PodExecTerminalProps,
) => React_2.JSX.Element;
// @public
export interface PodExecTerminalProps {
// (undocumented)
clusterName: string;
// (undocumented)
containerName: string;
// (undocumented)
podName: string;
// (undocumented)
podNamespace: string;
}
// @public
export const PodLogs: React_2.FC<PodLogsProps>;
// @public
export const PodLogsDialog: ({
containerScope,
}: PodLogsDialogProps) => React_2.JSX.Element;
// @public
export interface PodLogsDialogProps {
// (undocumented)
containerScope: ContainerScope;
}
// @public
export interface PodLogsOptions {
// (undocumented)
containerScope: ContainerScope;
// (undocumented)
previous?: boolean;
}
// @public
export interface PodLogsProps {
// (undocumented)
containerScope: ContainerScope;
// (undocumented)
previous?: boolean;
}
// @public
export const PodMetricsContext: React_2.Context<Map<string, ClientPodStatus[]>>;
// @public (undocumented)
export type PodMetricsMatcher = {
metadata?: IObjectMeta;
};
// @public (undocumented)
export const PodNamesWithErrorsContext: React_2.Context<Set<string>>;
// @public (undocumented)
export const PodNamesWithMetricsContext: React_2.Context<
Map<string, ClientPodStatus>
>;
// @public
export interface PodScope {
// (undocumented)
clusterName: string;
// (undocumented)
podName: string;
// (undocumented)
podNamespace: string;
}
// @public (undocumented)
export const PodsTable: ({
pods,
extraColumns,
}: PodsTablesProps) => React_2.JSX.Element;
// @public (undocumented)
export type PodsTablesProps = {
pods: Pod_2 | V1Pod[];
extraColumns?: PodColumns[];
children?: React_2.ReactNode;
};
// @public (undocumented)
export const READY_COLUMNS: PodColumns;
// @public (undocumented)
export const RESOURCE_COLUMNS: PodColumns;
// @public
export const ResourceUtilization: ({
compressed,
title,
usage,
total,
totalFormatted,
}: ResourceUtilizationProps) => React_2.JSX.Element;
// @public
export interface ResourceUtilizationProps {
// (undocumented)
compressed?: boolean;
// (undocumented)
title: string;
// (undocumented)
total: number | string;
// (undocumented)
totalFormatted: string;
// (undocumented)
usage: number | string;
}
// @public
export class ServerSideKubernetesAuthProvider
implements KubernetesAuthProvider
{
// (undocumented)
decorateRequestBodyForAuth(
requestBody: KubernetesRequestBody,
): Promise<KubernetesRequestBody>;
// (undocumented)
getCredentials(): Promise<{}>;
}
// @public (undocumented)
export const ServicesAccordions: ({}: ServicesAccordionsProps) => React_2.JSX.Element;
// @public (undocumented)
export type ServicesAccordionsProps = {};
// @public
export const useCustomResources: (
entity: Entity,
customResourceMatchers: CustomResourceMatcher[],
intervalMs?: number,
) => KubernetesObjects;
// @public
export const useEvents: ({
involvedObjectName,
namespace,
clusterName,
}: EventsOptions) => AsyncState<Event_2[]>;
// @public (undocumented)
export const useKubernetesObjects: (
entity: Entity,
intervalMs?: number,
) => KubernetesObjects;
// @public
export const useMatchingErrors: (matcher: ErrorMatcher) => DetectedError[];
// @public
export const usePodLogs: ({
containerScope,
previous,
}: PodLogsOptions) => AsyncState<{
text: string;
}>;
// @public
export const usePodMetrics: (
clusterName: string,
matcher: PodMetricsMatcher,
) => ClientPodStatus | undefined;
```
@@ -0,0 +1,11 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: backstage-plugin-kubernetes-react
title: '@backstage/plugin-kubernetes-react'
description: >-
Shared frontend utilities for Kubernetes plugins
spec:
lifecycle: experimental
type: backstage-web-library
owner: kubernetes-maintainers
+66
View File
@@ -0,0 +1,66 @@
{
"name": "@backstage/plugin-kubernetes-react",
"description": "Web library for the kubernetes-react plugin",
"version": "0.0.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"
},
"backstage": {
"role": "web-library"
},
"sideEffects": false,
"scripts": {
"start": "backstage-cli package start",
"build": "backstage-cli package build",
"lint": "backstage-cli package lint",
"test": "backstage-cli package test",
"clean": "backstage-cli package clean",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack"
},
"dependencies": {
"@backstage/catalog-model": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/plugin-kubernetes-common": "workspace:^",
"@backstage/types": "workspace:^",
"@kubernetes-models/apimachinery": "^1.1.0",
"@kubernetes-models/base": "^4.0.1",
"@kubernetes/client-node": "^0.19.0",
"@material-ui/core": "^4.9.13",
"@material-ui/icons": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.61",
"@types/react": "^16.13.1 || ^17.0.0",
"cronstrue": "^2.32.0",
"js-yaml": "^4.1.0",
"kubernetes-models": "^4.3.1",
"lodash": "^4.17.21",
"luxon": "^3.0.0",
"react-use": "^17.4.0",
"xterm": "^5.3.0",
"xterm-addon-attach": "^0.9.0",
"xterm-addon-fit": "^0.8.0"
},
"peerDependencies": {
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^12.1.3",
"@testing-library/react-hooks": "^8.0.1",
"jest-websocket-mock": "^2.5.0",
"msw": "^1.3.1"
},
"files": [
"dist"
]
}
@@ -0,0 +1,446 @@
{
"cronJobs": [
{
"metadata": {
"name": "dice-roller-cronjob",
"namespace": "default",
"uid": "9ea073bc-7a4b-4b99-8321-0305bce85568",
"resourceVersion": "1362732552",
"creationTimestamp": "2021-07-16T22:39:58Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller"
},
"annotations": {}
},
"spec": {
"schedule": "30 5 * * *",
"startingDeadlineSeconds": 1800,
"concurrencyPolicy": "Forbid",
"suspend": false,
"jobTemplate": {
"metadata": { "creationTimestamp": null },
"spec": {
"backoffLimit": 2,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"backstage.io/kubernetes-id": "dice-roller"
},
"annotations": {}
},
"spec": {
"containers": [
{
"name": "busybox",
"image": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"imagePullPolicy": "IfNotPresent",
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"]
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"securityContext": {},
"schedulerName": "default-scheduler"
}
}
}
},
"successfulJobsHistoryLimit": 2,
"failedJobsHistoryLimit": 2
},
"status": {
"active": [
{
"kind": "Job",
"namespace": "default",
"name": "dice-roller-cronjob-1637028600",
"uid": "32be1b89-5b53-45b2-aa84-277e75214f61",
"apiVersion": "batch/v1",
"resourceVersion": "1361174163"
}
],
"lastScheduleTime": "2021-11-16T02:10:00Z"
}
}
],
"jobs": [
{
"metadata": {
"name": "dice-roller-cronjob-1637025000",
"namespace": "default",
"uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"resourceVersion": "1361029181",
"creationTimestamp": "2021-11-16T01:10:24Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller"
},
"ownerReferences": [
{
"apiVersion": "batch/v1",
"kind": "CronJob",
"name": "dice-roller-cronjob",
"uid": "9ea073bc-7a4b-4b99-8321-0305bce85568",
"controller": true,
"blockOwnerDeletion": true
}
]
},
"spec": {
"parallelism": 1,
"completions": 1,
"backoffLimit": 2,
"selector": {
"matchLabels": {
"controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a"
}
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"backstage.io/kubernetes-id": "dice-roller",
"controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"job-name": "dice-roller-cronjob-1637025000"
},
"annotations": {}
},
"spec": {
"containers": [
{
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"],
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"securityContext": {},
"schedulerName": "default-scheduler"
}
}
},
"status": {
"conditions": [
{
"type": "Complete",
"status": "True",
"lastProbeTime": "2021-11-16T01:11:31Z",
"lastTransitionTime": "2021-11-16T01:11:31Z"
}
],
"startTime": "2021-11-16T01:10:24Z",
"completionTime": "2021-11-16T01:11:31Z",
"succeeded": 1
}
},
{
"metadata": {
"name": "dice-roller-cronjob-1637028600",
"namespace": "default",
"uid": "32be1b89-5b53-45b2-aa84-277e75214f61",
"resourceVersion": "1361174166",
"creationTimestamp": "2021-11-16T02:10:22Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller"
},
"ownerReferences": [
{
"apiVersion": "batch/v1",
"kind": "CronJob",
"name": "dice-roller-cronjob",
"uid": "9ea073bc-7a4b-4b99-8321-0305bce85568",
"controller": true,
"blockOwnerDeletion": true
}
]
},
"spec": {
"parallelism": 1,
"completions": 1,
"backoffLimit": 2,
"selector": {
"matchLabels": {
"controller-uid": "32be1b89-5b53-45b2-aa84-277e75214f61"
}
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"backstage.io/kubernetes-id": "dice-roller",
"controller-uid": "32be1b89-5b53-45b2-aa84-277e75214f61",
"job-name": "dice-roller-cronjob-1637028600"
},
"annotations": {}
},
"spec": {
"containers": [
{
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"],
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"securityContext": {},
"schedulerName": "default-scheduler"
}
}
},
"status": { "startTime": "2021-11-16T02:10:22Z", "active": 1 }
}
],
"pods": [
{
"metadata": {
"name": "dice-roller-cronjob-1637025000-gstc4",
"generateName": "dice-roller-cronjob-1637025000-",
"namespace": "default",
"uid": "3b0f2b65-5ae2-441a-beda-bdc92bcafaf0",
"resourceVersion": "1361029179",
"creationTimestamp": "2021-11-16T01:10:24Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller",
"controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"job-name": "dice-roller-cronjob-1637025000"
},
"annotations": {},
"ownerReferences": [
{
"apiVersion": "batch/v1",
"kind": "Job",
"name": "dice-roller-cronjob-1637025000",
"uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"controller": true,
"blockOwnerDeletion": true
}
]
},
"spec": {
"volumes": [],
"containers": [
{
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"],
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"serviceAccountName": "default",
"serviceAccount": "default",
"nodeName": "minikube",
"securityContext": {},
"schedulerName": "default-scheduler",
"tolerations": [
{
"key": "node.kubernetes.io/not-ready",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
},
{
"key": "node.kubernetes.io/unreachable",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
}
],
"priority": 0,
"enableServiceLinks": true
},
"status": {
"phase": "Succeeded",
"conditions": [
{
"type": "Initialized",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2021-11-16T01:10:27Z",
"reason": "PodCompleted"
},
{
"type": "Ready",
"status": "False",
"lastProbeTime": null,
"lastTransitionTime": "2021-11-16T01:11:31Z",
"reason": "PodCompleted"
},
{
"type": "ContainersReady",
"status": "False",
"lastProbeTime": null,
"lastTransitionTime": "2021-11-16T01:11:31Z",
"reason": "PodCompleted"
},
{
"type": "PodScheduled",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2021-11-16T01:10:24Z"
}
],
"hostIP": "192.168.49.2",
"podIP": "172.17.0.25",
"podIPs": [{ "ip": "172.17.0.25" }],
"startTime": "2021-11-16T01:10:24Z",
"containerStatuses": [
{
"name": "busybox",
"state": {
"terminated": {
"exitCode": 0,
"reason": "Completed",
"startedAt": "2021-11-16T01:10:31Z",
"finishedAt": "2021-11-16T01:11:30Z",
"containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615"
}
},
"lastState": {},
"ready": false,
"restartCount": 0,
"image": "busybox:latest/node",
"imageID": "docker-pullable://busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353",
"containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615",
"started": false
}
],
"qosClass": "Burstable"
}
},
{
"metadata": {
"name": "dice-roller-cronjob-1637028600-p4mlc",
"generateName": "dice-roller-cronjob-1637028600-",
"namespace": "default",
"uid": "acddd5d2-ac7f-473b-a9d8-17a89f99ac39",
"resourceVersion": "1361174579",
"creationTimestamp": "2021-11-16T02:10:22Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller",
"controller-uid": "32be1b89-5b53-45b2-aa84-277e75214f61",
"job-name": "dice-roller-cronjob-1637028600"
},
"annotations": {},
"ownerReferences": [
{
"apiVersion": "batch/v1",
"kind": "Job",
"name": "dice-roller-cronjob-1637028600",
"uid": "32be1b89-5b53-45b2-aa84-277e75214f61",
"controller": true,
"blockOwnerDeletion": true
}
]
},
"spec": {
"volumes": [],
"containers": [
{
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"],
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"serviceAccountName": "default",
"serviceAccount": "default",
"nodeName": "minikube",
"securityContext": {},
"schedulerName": "default-scheduler",
"tolerations": [
{
"key": "node.kubernetes.io/not-ready",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
},
{
"key": "node.kubernetes.io/unreachable",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
}
],
"priority": 0,
"enableServiceLinks": true
},
"status": {
"phase": "Running",
"conditions": [
{
"type": "Initialized",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2021-11-16T02:10:25Z"
},
{
"type": "Ready",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2021-11-16T02:10:35Z"
},
{
"type": "ContainersReady",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2021-11-16T02:10:35Z"
},
{
"type": "PodScheduled",
"status": "True",
"lastProbeTime": null,
"lastTransitionTime": "2021-11-16T02:10:22Z"
}
],
"hostIP": "192.168.49.2",
"podIP": "172.17.0.25",
"podIPs": [{ "ip": "172.17.0.25" }],
"startTime": "2021-11-16T02:10:22Z",
"containerStatuses": [
{
"name": "busybox",
"state": {
"running": { "startedAt": "2021-11-16T02:10:31Z" }
},
"lastState": {},
"ready": true,
"restartCount": 0,
"image": "busybox:latest",
"imageID": "docker-pullable://busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353",
"containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615",
"started": true
}
],
"qosClass": "Burstable"
}
}
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,385 @@
{
"cronJobs": [
{
"metadata": {
"name": "dice-roller-cronjob",
"namespace": "default",
"uid": "9ea073bc-7a4b-4b99-8321-0305bce85568",
"resourceVersion": "1362732552",
"creationTimestamp": "2021-07-16T22:39:58Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller"
},
"annotations": {}
},
"spec": {
"schedule": "* */2 * * *",
"startingDeadlineSeconds": 1800,
"concurrencyPolicy": "Forbid",
"suspend": true,
"jobTemplate": {
"metadata": { "creationTimestamp": null },
"spec": {
"backoffLimit": 2,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"backstage.io/kubernetes-id": "dice-roller"
},
"annotations": {}
},
"spec": {
"containers": [
{
"name": "busybox",
"image": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"imagePullPolicy": "IfNotPresent",
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"]
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"securityContext": {},
"schedulerName": "default-scheduler"
}
}
}
},
"successfulJobsHistoryLimit": 2,
"failedJobsHistoryLimit": 2
},
"status": {
"lastScheduleTime": "2021-11-16T02:10:00Z"
}
}
],
"jobs": [
{
"metadata": {
"name": "dice-roller-cronjob-1637025000",
"namespace": "default",
"uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"resourceVersion": "1361029181",
"creationTimestamp": "2021-11-16T01:10:24Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller"
},
"ownerReferences": [
{
"apiVersion": "batch/v1",
"kind": "CronJob",
"name": "dice-roller-cronjob",
"uid": "9ea073bc-7a4b-4b99-8321-0305bce85568",
"controller": true,
"blockOwnerDeletion": true
}
]
},
"spec": {
"parallelism": 1,
"completions": 1,
"backoffLimit": 2,
"selector": {
"matchLabels": {
"controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a"
}
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"backstage.io/kubernetes-id": "dice-roller",
"controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"job-name": "dice-roller-cronjob-1637025000"
},
"annotations": {}
},
"spec": {
"containers": [
{
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"],
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"securityContext": {},
"schedulerName": "default-scheduler"
}
}
},
"status": {
"conditions": [
{
"type": "Failed",
"status": "True",
"reason": "BackoffLimitExceeded",
"lastProbeTime": "2021-11-16T01:11:31Z",
"lastTransitionTime": "2021-11-16T01:11:31Z"
}
],
"startTime": "2021-11-16T01:10:24Z",
"failed": 2
}
}
],
"pods": [
{
"metadata": {
"name": "dice-roller-cronjob-1637025000-gstc4",
"generateName": "dice-roller-cronjob-1637025000-",
"namespace": "default",
"uid": "3b0f2b65-5ae2-441a-beda-bdc92bcafaf0",
"resourceVersion": "1361029179",
"creationTimestamp": "2021-11-16T01:10:24Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller",
"controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"job-name": "dice-roller-cronjob-1637025000"
},
"annotations": {},
"ownerReferences": [
{
"apiVersion": "batch/v1",
"kind": "Job",
"name": "dice-roller-cronjob-1637025000",
"uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"controller": true,
"blockOwnerDeletion": true
}
]
},
"spec": {
"volumes": [],
"containers": [
{
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"],
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"serviceAccountName": "default",
"serviceAccount": "default",
"nodeName": "minikube",
"securityContext": {},
"schedulerName": "default-scheduler",
"tolerations": [
{
"key": "node.kubernetes.io/not-ready",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
},
{
"key": "node.kubernetes.io/unreachable",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
}
],
"priority": 0,
"enableServiceLinks": true
},
"status": {
"phase": "Failed",
"conditions": [
{
"lastProbeTime": null,
"lastTransitionTime": "2021-11-18T19:10:13Z",
"status": "True",
"type": "Initialized"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-11-18T19:11:02Z",
"message": "containers with unready status: [busybox]",
"reason": "ContainersNotReady",
"status": "False",
"type": "Ready"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-11-18T19:11:02Z",
"message": "containers with unready status: [busybox]",
"reason": "ContainersNotReady",
"status": "False",
"type": "ContainersReady"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-11-18T19:10:08Z",
"status": "True",
"type": "PodScheduled"
}
],
"hostIP": "192.168.49.2",
"podIP": "172.17.0.25",
"podIPs": [{ "ip": "172.17.0.25" }],
"startTime": "2021-11-18T19:10:08Z",
"containerStatuses": [
{
"name": "busybox",
"state": {
"terminated": {
"exitCode": 1,
"finishedAt": "2021-11-18T19:11:01Z",
"reason": "Error",
"startedAt": "2021-11-18T19:10:17Z",
"containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615"
}
},
"lastState": {},
"ready": false,
"restartCount": 0,
"image": "busybox:latest",
"imageID": "docker-pullable://busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353",
"containerID": "docker://1062343e1bb3625e36717bc15617c1bbca976366c3c9dd87035c71f33d015615",
"started": false
}
],
"qosClass": "Burstable"
}
},
{
"metadata": {
"name": "dice-roller-cronjob-1637025000-p4mlc",
"generateName": "dice-roller-cronjob-1637025000-",
"namespace": "default",
"uid": "acddd5d2-ac7f-473b-a9d8-17a89f99ac39",
"resourceVersion": "1361174579",
"creationTimestamp": "2021-11-16T02:10:22Z",
"labels": {
"backstage.io/kubernetes-id": "dice-roller",
"controller-uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"job-name": "dice-roller-cronjob-1637025000"
},
"annotations": {},
"ownerReferences": [
{
"apiVersion": "batch/v1",
"kind": "Job",
"name": "dice-roller-cronjob-1637025000",
"uid": "69d5d242-a9a4-47b8-b9c7-c536ae8f151a",
"controller": true,
"blockOwnerDeletion": true
}
]
},
"spec": {
"volumes": [],
"containers": [
{
"command": ["/bin/sh", "-c", "date; echo Rolling a die!"],
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"restartPolicy": "Never",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"serviceAccountName": "default",
"serviceAccount": "default",
"nodeName": "minikube",
"securityContext": {},
"schedulerName": "default-scheduler",
"tolerations": [
{
"key": "node.kubernetes.io/not-ready",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
},
{
"key": "node.kubernetes.io/unreachable",
"operator": "Exists",
"effect": "NoExecute",
"tolerationSeconds": 300
}
],
"priority": 0,
"enableServiceLinks": true
},
"status": {
"phase": "Failed",
"conditions": [
{
"lastProbeTime": null,
"lastTransitionTime": "2021-11-18T19:10:13Z",
"status": "True",
"type": "Initialized"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-11-18T19:11:02Z",
"message": "containers with unready status: [busybox]",
"reason": "ContainersNotReady",
"status": "False",
"type": "Ready"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-11-18T19:11:02Z",
"message": "containers with unready status: [busybox]",
"reason": "ContainersNotReady",
"status": "False",
"type": "ContainersReady"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-11-18T19:10:08Z",
"status": "True",
"type": "PodScheduled"
}
],
"hostIP": "192.168.49.2",
"podIP": "172.17.0.25",
"podIPs": [{ "ip": "172.17.0.25" }],
"startTime": "2021-11-16T02:10:22Z",
"containerStatuses": [
{
"name": "busybox",
"state": {
"terminated": {
"exitCode": 1,
"finishedAt": "2021-11-18T19:11:01Z",
"reason": "Error",
"startedAt": "2021-11-18T19:10:17Z",
"containerID": "docker://2659c4d0f8a68f2b49863c18738322f1686d5b87275428e5e641fd9fd9e06739"
}
},
"lastState": {},
"ready": true,
"restartCount": 0,
"image": "busybox:latest",
"imageID": "docker-pullable://busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353",
"containerID": "docker://2659c4d0f8a68f2b49863c18738322f1686d5b87275428e5e641fd9fd9e06739",
"started": true
}
],
"qosClass": "Burstable"
}
}
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -26,6 +26,7 @@ import { stringifyEntityRef } from '@backstage/catalog-model';
import { KubernetesAuthProvidersApi } from '../kubernetes-auth-provider';
import { NotFoundError } from '@backstage/errors';
/** @public */
export class KubernetesBackendClient implements KubernetesApi {
private readonly discoveryApi: DiscoveryApi;
private readonly identityApi: IdentityApi;
@@ -23,14 +23,17 @@ import {
import { createApiRef } from '@backstage/core-plugin-api';
import { Event } from 'kubernetes-models/v1';
/** @public */
export const kubernetesApiRef = createApiRef<KubernetesApi>({
id: 'plugin.kubernetes.service',
});
/** @public */
export const kubernetesProxyApiRef = createApiRef<KubernetesProxyApi>({
id: 'plugin.kubernetes.proxy-service',
});
/** @public */
export interface KubernetesApi {
getObjectsByEntity(
requestBody: KubernetesRequestBody,
@@ -55,6 +58,7 @@ export interface KubernetesApi {
}): Promise<Response>;
}
/** @public */
export interface KubernetesProxyApi {
getPodLogs(request: {
podName: string;
@@ -25,11 +25,11 @@ import {
import {
ClientPodStatus,
ClusterObjects,
groupResponses,
} from '@backstage/plugin-kubernetes-common';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { DeploymentsAccordions } from '../DeploymentsAccordions';
import { StatefulSetsAccordions } from '../StatefulSetsAccordions';
import { groupResponses } from '../../utils/response';
import { IngressesAccordions } from '../IngressesAccordions';
import { ServicesAccordions } from '../ServicesAccordions';
import { CronJobsAccordions } from '../CronJobsAccordions';
@@ -103,12 +103,22 @@ const ClusterSummary = ({
);
};
type ClusterProps = {
/**
* Props for Cluster
*
* @public
*/
export type ClusterProps = {
clusterObjects: ClusterObjects;
podsWithErrors: Set<string>;
children?: React.ReactNode;
};
/**
* Component for rendering Kubernetes resources in a cluster
*
* @public
*/
export const Cluster = ({ clusterObjects, podsWithErrors }: ClusterProps) => {
const groupedResponses = groupResponses(clusterObjects.resources);
@@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { ErrorPanel } from './ErrorPanel';
export * from './Cluster';
@@ -30,7 +30,12 @@ import { GroupedResponsesContext } from '../../hooks';
import { StatusError, StatusOK } from '@backstage/core-components';
import { humanizeCron } from '../../utils/crons';
type CronJobsAccordionsProps = {
/**
*
*
* @public
*/
export type CronJobsAccordionsProps = {
children?: React.ReactNode;
};
@@ -101,6 +106,11 @@ const CronJobAccordion = ({ cronJob, ownedJobs }: CronJobAccordionProps) => {
);
};
/**
*
*
* @public
*/
export const CronJobsAccordions = ({}: CronJobsAccordionsProps) => {
const groupedResponses = useContext(GroupedResponsesContext);
@@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { JobsAccordions } from './JobsAccordions';
export * from './CronJobsAccordions';
@@ -20,7 +20,12 @@ import { RolloutAccordions } from './ArgoRollouts';
import { DefaultCustomResourceAccordions } from './DefaultCustomResource';
import { GroupedResponsesContext } from '../../hooks';
interface CustomResourcesProps {
/**
*
*
* @public
*/
export interface CustomResourcesProps {
children?: React.ReactNode;
}
@@ -30,6 +35,11 @@ const kindToResource = (customResources: any[]): Dictionary<any[]> => {
});
};
/**
*
*
* @public
*/
export const CustomResources = ({}: CustomResourcesProps) => {
const groupedResponses = useContext(GroupedResponsesContext);
const kindToResourceMap = kindToResource(groupedResponses.customResources);
@@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { ErrorReporting } from './ErrorReporting';
export * from './CustomResources';
@@ -41,13 +41,23 @@ const clustersWithErrorsToErrorMessage = (
});
};
type ErrorPanelProps = {
/**
*
*
* @public
*/
export type ErrorPanelProps = {
entityName: string;
errorMessage?: string;
clustersWithErrors?: ClusterObjects[];
children?: React.ReactNode;
};
/**
*
*
* @public
*/
export const ErrorPanel = ({
entityName,
errorMessage,
@@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { CustomResources } from './CustomResources';
export * from './ErrorPanel';
@@ -14,10 +14,18 @@
* limitations under the License.
*/
import * as React from 'react';
import { DetectedError, DetectedErrorsByCluster } from '../../error-detection';
import {
DetectedError,
DetectedErrorsByCluster,
} from '@backstage/plugin-kubernetes-common';
import { Table, TableColumn } from '@backstage/core-components';
type ErrorReportingProps = {
/**
*
*
* @public
*/
export type ErrorReportingProps = {
detectedErrors: DetectedErrorsByCluster;
};
@@ -65,6 +73,11 @@ const sortBySeverity = (a: Row, b: Row) => {
return 0;
};
/**
*
*
* @public
*/
export const ErrorReporting = ({ detectedErrors }: ErrorReportingProps) => {
const errors = Array.from(detectedErrors.entries())
.flatMap(([clusterName, resourceErrors]) => {
@@ -0,0 +1,16 @@
/*
* Copyright 2020 The Backstage 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.
*/
export * from './ErrorReporting';
@@ -27,7 +27,12 @@ import { IngressDrawer } from './IngressDrawer';
import { GroupedResponsesContext } from '../../hooks';
import { StructuredMetadataTable } from '@backstage/core-components';
type IngressesAccordionsProps = {};
/**
*
*
* @public
*/
export type IngressesAccordionsProps = {};
type IngressAccordionProps = {
ingress: V1Ingress;
@@ -78,6 +83,12 @@ const IngressAccordion = ({ ingress }: IngressAccordionProps) => {
</Accordion>
);
};
/**
*
*
* @public
*/
export const IngressesAccordions = ({}: IngressesAccordionsProps) => {
const groupedResponses = useContext(GroupedResponsesContext);
return (
@@ -0,0 +1,16 @@
/*
* Copyright 2020 The Backstage 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.
*/
export * from './IngressesAccordions';
@@ -32,7 +32,12 @@ import {
StatusPending,
} from '@backstage/core-components';
type JobsAccordionsProps = {
/**
*
*
* @public
*/
export type JobsAccordionsProps = {
jobs: V1Job[];
children?: React.ReactNode;
};
@@ -98,6 +103,11 @@ const JobAccordion = ({ job, ownedPods }: JobAccordionProps) => {
);
};
/**
*
*
* @public
*/
export const JobsAccordions = ({ jobs }: JobsAccordionsProps) => {
const groupedResponses = useContext(GroupedResponsesContext);
@@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { CronJobsAccordions } from './CronJobsAccordions';
export * from './JobsAccordions';
@@ -48,7 +48,12 @@ const useDrawerContentStyles = makeStyles((_theme: Theme) =>
}),
);
interface KubernetesObject {
/**
* The type of object that can be represented by the Drawer
*
* @public
*/
export interface KubernetesObject {
kind: string;
metadata?: IObjectMeta;
}
@@ -60,7 +65,7 @@ interface KubernetesDrawerContentProps {
children?: React.ReactNode;
}
export const KubernetesDrawerContent = ({
const KubernetesDrawerContent = ({
children,
header,
kubernetesObject,
@@ -115,7 +120,12 @@ export const KubernetesDrawerContent = ({
);
};
interface KubernetesDrawerProps {
/**
* Props of KubernetesDrawer
*
* @public
*/
export interface KubernetesDrawerProps {
open?: boolean;
kubernetesObject: KubernetesObject;
label: React.ReactNode;
@@ -142,6 +152,11 @@ const DrawerButton = withStyles({
},
})(Button);
/**
* Button/Drawer component for Kubernetes Objects
*
* @public
*/
export const KubernetesDrawer = ({
open,
label,
@@ -86,13 +86,26 @@ const PodDrawerButton = withStyles({
},
})(Button);
type ErrorPanelProps = {
/**
*
*
* @public
*/
export type LinkErrorPanelProps = {
cluster: ClusterAttributes;
errorMessage?: string;
children?: React.ReactNode;
};
export const LinkErrorPanel = ({ cluster, errorMessage }: ErrorPanelProps) => (
/**
*
*
* @public
*/
export const LinkErrorPanel = ({
cluster,
errorMessage,
}: LinkErrorPanelProps) => (
<WarningPanel
title="There was a problem formatting the link to the Kubernetes dashboard"
message={`Could not format the link to the dashboard of your cluster named '${
@@ -107,7 +120,12 @@ export const LinkErrorPanel = ({ cluster, errorMessage }: ErrorPanelProps) => (
</WarningPanel>
);
interface KubernetesDrawerable {
/**
*
*
* @public
*/
export interface KubernetesDrawerable {
metadata?: V1ObjectMeta;
}
@@ -234,7 +252,12 @@ const KubernetesStructuredMetadataTableDrawerContent = <
</>
);
};
interface KubernetesStructuredMetadataTableDrawerProps<
/**
*
* @public
*/
export interface KubernetesStructuredMetadataTableDrawerProps<
T extends KubernetesDrawerable,
> {
object: T;
@@ -245,6 +268,10 @@ interface KubernetesStructuredMetadataTableDrawerProps<
children?: React.ReactNode;
}
/**
*
* @public
*/
export const KubernetesStructuredMetadataTableDrawer = <
T extends KubernetesDrawerable,
>({
@@ -18,10 +18,20 @@ import { FormControlLabel, Switch } from '@material-ui/core';
import jsyaml from 'js-yaml';
import React, { useState } from 'react';
/**
* Props of ManifestYaml
*
* @public
*/
export interface ManifestYamlProps {
object: object;
}
/**
* Renders a Kubernetes object as a YAML code snippet
*
* @public
*/
export const ManifestYaml = ({ object }: ManifestYamlProps) => {
// Toggle whether the Kubernetes resource managed fields should be shown in
// the YAML display. This toggle is only available when the YAML is being
@@ -16,3 +16,4 @@
export * from './KubernetesStructuredMetadataTableDrawer';
export * from './KubernetesDrawer';
export * from './ManifestYaml';
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'xterm/css/xterm.css';
import 'xterm';
import { discoveryApiRef, useApi } from '@backstage/core-plugin-api';
import React, { useEffect, useMemo, useState } from 'react';

Some files were not shown because too many files have changed in this diff Show More