diff --git a/.changeset/eight-cougars-collect-due.md b/.changeset/eight-cougars-collect-due.md
new file mode 100644
index 0000000000..ff997f876a
--- /dev/null
+++ b/.changeset/eight-cougars-collect-due.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-kubernetes-cluster': patch
+'@backstage/plugin-kubernetes-react': patch
+---
+
+Improved rendering of Kubernetes resources' metadata.
diff --git a/.changeset/eight-cougars-collect.md b/.changeset/eight-cougars-collect.md
new file mode 100644
index 0000000000..edaa18d826
--- /dev/null
+++ b/.changeset/eight-cougars-collect.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Added `nestedValuesAsYaml` option to `StructuredMetadataTable` to render data as yaml.
diff --git a/packages/core-components/package.json b/packages/core-components/package.json
index 13d3785c4d..add79c01f5 100644
--- a/packages/core-components/package.json
+++ b/packages/core-components/package.json
@@ -73,6 +73,7 @@
"d3-shape": "^3.0.0",
"d3-zoom": "^3.0.0",
"dagre": "^0.8.5",
+ "js-yaml": "^4.1.0",
"linkify-react": "4.1.3",
"linkifyjs": "4.1.3",
"lodash": "^4.17.21",
diff --git a/packages/core-components/report.api.md b/packages/core-components/report.api.md
index c3f7cf9a6a..c706eef2bb 100644
--- a/packages/core-components/report.api.md
+++ b/packages/core-components/report.api.md
@@ -1307,6 +1307,7 @@ export interface StructuredMetadataTableProps {
// (undocumented)
options?: {
titleFormat?: (key: string) => string;
+ nestedValuesAsYaml?: boolean;
};
}
diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
index 4eb05e715e..8e6c4bbff0 100644
--- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
+++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.test.tsx
@@ -66,7 +66,7 @@ describe('', () => {
expect(getByText(startCase(value))).toBeInTheDocument();
});
metadata.arrayField.forEach(value => {
- expect(getByText(value)).toBeInTheDocument();
+ expect(getByText(new RegExp(value))).toBeInTheDocument();
});
});
@@ -124,12 +124,19 @@ describe('', () => {
};
it('should make keys human readable', async () => {
- const rendered = render();
+ const rendered = render(
+ ,
+ );
expect(rendered.queryByText(/^Test A/)).toBeInTheDocument();
expect(rendered.queryByText(/^Test B/)).toBeInTheDocument();
- expect(rendered.queryByText(/^Test C/)).toBeInTheDocument();
expect(rendered.queryByText(/^Test D/)).toBeInTheDocument();
- expect(rendered.queryByText(/^Test E/)).toBeInTheDocument();
+
+ // nested content is displayed as yaml, so not affected by formatting
+ expect(rendered.queryByText(/^testC/)).toBeInTheDocument();
+ expect(rendered.queryByText(/testE: stuff/)).toBeInTheDocument();
});
it('should be possible to disable it', async () => {
@@ -161,14 +168,16 @@ describe('', () => {
const rendered = render(
,
);
expect(rendered.queryByText(/^tEsTa/)).toBeInTheDocument();
expect(rendered.queryByText(/^tEsTb/)).toBeInTheDocument();
- expect(rendered.queryByText(/^tEsTc/)).toBeInTheDocument();
expect(rendered.queryByText(/^tEsTd/)).toBeInTheDocument();
- expect(rendered.queryByText(/^tEsTe/)).toBeInTheDocument();
+
+ // nested content is displayed as yaml, so not affected by formatting
+ expect(rendered.queryByText(/^testC/)).toBeInTheDocument();
+ expect(rendered.queryByText(/^testE/)).toBeInTheDocument();
});
});
});
diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
index 3099edf9d8..b839280cdd 100644
--- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
+++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx
@@ -15,21 +15,23 @@
*/
import React, { Fragment, ReactElement } from 'react';
-import {
- withStyles,
- createStyles,
- WithStyles,
- Theme,
-} from '@material-ui/core/styles';
import startCase from 'lodash/startCase';
import Typography from '@material-ui/core/Typography';
import {
- MetadataTable,
- MetadataTableItem,
MetadataList,
MetadataListItem,
+ MetadataTable,
+ MetadataTableItem,
} from './MetadataTable';
+import { CodeSnippet } from '../CodeSnippet';
+import jsyaml from 'js-yaml';
+import {
+ Theme,
+ createStyles,
+ WithStyles,
+ withStyles,
+} from '@material-ui/core/styles';
export type StructuredMetadataTableListClassKey = 'root';
@@ -41,7 +43,6 @@ const listStyle = createStyles({
});
export type StructuredMetadataTableNestedListClassKey = 'root';
-
const nestedListStyle = (theme: Theme) =>
createStyles({
root: {
@@ -110,9 +111,24 @@ function toValue(
if (React.isValidElement(value)) {
return {value};
}
-
- if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
- return renderMap(value, options, nested);
+ if (value !== null && typeof value === 'object') {
+ if (options.nestedValuesAsYaml) {
+ return (
+
+ );
+ }
+ if (!Array.isArray(value)) {
+ return renderMap(value, options, nested);
+ }
}
if (Array.isArray(value)) {
@@ -122,7 +138,6 @@ function toValue(
if (typeof value === 'boolean') {
return {value ? '✅' : '❌'};
}
-
return (
{value}
@@ -167,6 +182,7 @@ export interface StructuredMetadataTableProps {
* @returns Formatted key
*/
titleFormat?: (key: string) => string;
+ nestedValuesAsYaml?: boolean;
};
}
@@ -174,9 +190,10 @@ type Options = Required>;
/** @public */
export function StructuredMetadataTable(props: StructuredMetadataTableProps) {
- const { metadata, dense = true, options = {} } = props;
+ const { metadata, dense = true, options } = props;
const metadataItems = mapToItems(metadata, {
titleFormat: startCase,
+ nestedValuesAsYaml: options?.nestedValuesAsYaml ?? false,
...options,
});
return {metadataItems};
diff --git a/plugins/kubernetes-cluster/src/components/ClusterOverview/ClusterOverview.tsx b/plugins/kubernetes-cluster/src/components/ClusterOverview/ClusterOverview.tsx
index b77b2dff88..af741239e5 100644
--- a/plugins/kubernetes-cluster/src/components/ClusterOverview/ClusterOverview.tsx
+++ b/plugins/kubernetes-cluster/src/components/ClusterOverview/ClusterOverview.tsx
@@ -58,6 +58,7 @@ export const ClusterOverview = () => {
'OIDC Token Provider': value.oidcTokenProvider ?? 'N/A',
'Dashboard Link': value.dashboardUrl ?? 'N/A',
}}
+ options={{ nestedValuesAsYaml: true }}
/>
)}
diff --git a/plugins/kubernetes-cluster/src/components/Nodes/Nodes.tsx b/plugins/kubernetes-cluster/src/components/Nodes/Nodes.tsx
index 0b3f7ddb60..9307b11a6e 100644
--- a/plugins/kubernetes-cluster/src/components/Nodes/Nodes.tsx
+++ b/plugins/kubernetes-cluster/src/components/Nodes/Nodes.tsx
@@ -50,7 +50,10 @@ const defaultColumns: TableColumn[] = [
Node Info
-
+
Addresses
@@ -61,6 +64,7 @@ const defaultColumns: TableColumn[] = [
return accum;
}, {} as any) ?? {}
}
+ options={{ nestedValuesAsYaml: true }}
/>
@@ -72,6 +76,7 @@ const defaultColumns: TableColumn[] = [
return accum;
}, {} as any) ?? {}
}
+ options={{ nestedValuesAsYaml: true }}
/>
diff --git a/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx b/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx
index ee484ecda8..d34ba23f7b 100644
--- a/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx
+++ b/plugins/kubernetes-react/src/components/CustomResources/DefaultCustomResource.tsx
@@ -84,7 +84,10 @@ const DefaultCustomResourceAccordion = ({
{Object.prototype.hasOwnProperty.call(customResource, 'status') && (
-
+
)}
diff --git a/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx
index 1e8515f81a..002c4c8ff4 100644
--- a/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx
+++ b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx
@@ -40,13 +40,13 @@ describe('DeploymentDrawer', () => {
expect(getAllByText('Deployment')).toHaveLength(2);
expect(getByText('YAML')).toBeInTheDocument();
expect(getByText('Strategy')).toBeInTheDocument();
- expect(getByText('Rolling Update:')).toBeInTheDocument();
- expect(getByText(textContentMatcher('Max Surge: 25%'))).toBeInTheDocument();
+ expect(getByText('rollingUpdate:')).toBeInTheDocument();
+ expect(getByText(textContentMatcher('maxSurge: 25%'))).toBeInTheDocument();
expect(
- getByText(textContentMatcher('Max Unavailable: 25%')),
+ getByText(textContentMatcher('maxUnavailable: 25%')),
).toBeInTheDocument();
expect(
- getByText(textContentMatcher('Type: RollingUpdate')),
+ getByText(textContentMatcher('type: RollingUpdate')),
).toBeInTheDocument();
expect(getByText('Min Ready Seconds')).toBeInTheDocument();
expect(getByText('???')).toBeInTheDocument();
diff --git a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx
index cfacb24ee4..e504aefbb9 100644
--- a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx
+++ b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx
@@ -37,13 +37,13 @@ describe('IngressDrawer', () => {
expect(screen.getByText('YAML')).toBeInTheDocument();
expect(screen.getByText('Rules')).toBeInTheDocument();
expect(
- screen.getByText(textContentMatcher('Host: api.awesome-host.io')),
+ screen.getByText(textContentMatcher('host: api.awesome-host.io')),
).toBeInTheDocument();
expect(
- screen.getAllByText(textContentMatcher('Service Port: 80')),
+ screen.getAllByText(textContentMatcher('servicePort: 80')),
).toHaveLength(2);
expect(
- screen.getAllByText(textContentMatcher('Service Name: awesome-service')),
+ screen.getAllByText(textContentMatcher('serviceName: awesome-service')),
).toHaveLength(2);
});
});
diff --git a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx
index 5962e78f59..d2d674042b 100644
--- a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx
+++ b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressesAccordions.tsx
@@ -65,6 +65,9 @@ const IngressCard = ({ ingress }: IngressCardProps) => {
metadata={{
...ingress.spec,
}}
+ options={{
+ nestedValuesAsYaml: true,
+ }}
/>
);
};
diff --git a/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx
index b31d3f9aa7..0a5802ddc8 100644
--- a/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx
+++ b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx
@@ -237,6 +237,7 @@ const KubernetesStructuredMetadataTableDrawerContent = <
{!isYaml && (
)}
diff --git a/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx b/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx
index 1919bc112d..6aed2c75d7 100644
--- a/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx
+++ b/plugins/kubernetes-react/src/components/Pods/PodDrawer/ContainerCard.tsx
@@ -176,6 +176,7 @@ export const ContainerCard: React.FC = ({
containerSpec,
containerStatus,
)}
+ options={{ nestedValuesAsYaml: true }}
/>
{containerMetrics && (
diff --git a/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx
index 7eec2926c4..692c0a7c8c 100644
--- a/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx
+++ b/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx
@@ -39,10 +39,10 @@ describe('ServiceDrawer', () => {
expect(screen.getByText('Cluster IP')).toBeInTheDocument();
expect(screen.getByText('Ports')).toBeInTheDocument();
expect(
- screen.getByText(textContentMatcher('Target Port: 1997')),
+ screen.getByText(textContentMatcher('targetPort: 1997')),
).toBeInTheDocument();
expect(
- screen.getByText(textContentMatcher('App: awesome-service')),
+ screen.getByText(textContentMatcher('app: awesome-service')),
).toBeInTheDocument();
});
});
diff --git a/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx
index 71832fd35c..c44a1d158c 100644
--- a/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx
+++ b/plugins/kubernetes-react/src/components/ServicesAccordions/ServicesAccordions.tsx
@@ -77,6 +77,7 @@ const ServiceCard = ({ service }: ServiceCardProps) => {
ports: service.spec?.ports,
...metadata,
}}
+ options={{ nestedValuesAsYaml: true }}
/>
);
};
diff --git a/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx
index d69ab15f1a..3e4ff56a35 100644
--- a/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx
+++ b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx
@@ -40,20 +40,20 @@ describe('StatefulSetDrawer', () => {
expect(getByText('StatefulSet')).toBeInTheDocument();
expect(getByText('YAML')).toBeInTheDocument();
expect(
- getByText(textContentMatcher('Type: RollingUpdate')),
+ getByText(textContentMatcher('type: RollingUpdate')),
).toBeInTheDocument();
- expect(getByText('Rolling Update:')).toBeInTheDocument();
- expect(getByText(textContentMatcher('Max Surge: 25%'))).toBeInTheDocument();
+ expect(getByText('rollingUpdate:')).toBeInTheDocument();
+ expect(getByText(textContentMatcher('maxSurge: 25%'))).toBeInTheDocument();
expect(
- getByText(textContentMatcher('Max Unavailable: 25%')),
+ getByText(textContentMatcher('maxUnavailable: 25%')),
).toBeInTheDocument();
expect(getByText('Pod Management Policy')).toBeInTheDocument();
expect(getByText('Parallel')).toBeInTheDocument();
expect(getByText('Service Name')).toBeInTheDocument();
expect(getByText('Selector')).toBeInTheDocument();
- expect(getByText('Match Labels:')).toBeInTheDocument();
+ expect(getByText('matchLabels:')).toBeInTheDocument();
expect(
- getByText(textContentMatcher('App: dice-roller')),
+ getByText(textContentMatcher('app: dice-roller')),
).toBeInTheDocument();
expect(getByText('Revision History Limit')).toBeInTheDocument();
expect(getByText('10')).toBeInTheDocument();
diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx
index 2de5a17f25..91b97cbfc5 100644
--- a/plugins/kubernetes/dev/index.tsx
+++ b/plugins/kubernetes/dev/index.tsx
@@ -34,7 +34,10 @@ import fixture2 from '../src/__fixtures__/2-deployments.json';
import fixture3 from '../src/__fixtures__/1-cronjobs.json';
import fixture4 from '../src/__fixtures__/2-cronjobs.json';
import fixture5 from '../src/__fixtures__/1-rollouts.json';
+import fixture6 from '../src/__fixtures__/3-ingresses.json';
+import fixture7 from '../src/__fixtures__/2-statefulsets.json';
import { TestApiProvider } from '@backstage/test-utils';
+import { StructuredMetadataTable } from '@backstage/core-components';
const mockEntity: Entity = {
apiVersion: 'backstage.io/v1alpha1',
@@ -134,6 +137,12 @@ class MockKubernetesClient implements KubernetesApi {
}
}
+const metadata = {
+ testA: 'stuff',
+ testB: { testC: 'stuff' },
+ testD: [{ testE: 'stuff' }],
+};
+
createDevApp()
.addPage({
path: '/fixture-1',
@@ -200,5 +209,35 @@ createDevApp()
),
})
+ .addPage({
+ path: '/fixture-6',
+ title: 'Fixture 6',
+ element: (
+
+
+
+
+
+ ),
+ })
+ .addPage({
+ path: '/fixture-7',
+ title: 'Fixture 7',
+ element: (
+
+
+
+
+
+
+ ),
+ })
.registerPlugin(kubernetesPlugin)
.render();
diff --git a/plugins/kubernetes/src/__fixtures__/3-ingresses.json b/plugins/kubernetes/src/__fixtures__/3-ingresses.json
new file mode 100644
index 0000000000..94359c8239
--- /dev/null
+++ b/plugins/kubernetes/src/__fixtures__/3-ingresses.json
@@ -0,0 +1,372 @@
+{
+ "ingresses": [
+ {
+ "metadata": {
+ "name": "app-service-endpoint.dice-roller.backstage.io",
+ "namespace": "dice-roller",
+ "uid": "00000000-0000-0000-0000-000000000000",
+ "resourceVersion": "4749260703",
+ "generation": 1,
+ "creationTimestamp": "2023-08-16T14:52:16Z",
+ "labels": {
+ "backstage.io/kubernetes-id": "dice-roller",
+ "ingress-class": "istio-internal"
+ },
+ "annotations": {
+ "kubectl.kubernetes.io/last-applied-configuration": "spec",
+ "metacontroller.k8s.io/last-applied-configuration": "spec",
+ "nginx.ingress.kubernetes.io/auth-signin": "https://backstage.io/authenticate",
+ "nginx.ingress.kubernetes.io/configuration-snippet": "config",
+ "nginx.ingress.kubernetes.io/service-upstream": "true",
+ "nginx.ingress.kubernetes.io/upstream-vhost": "app-service-endpoint.dice-roller.backstage.services"
+ },
+ "ownerReferences": [
+ {
+ "apiVersion": "networking.backstage.com/v1beta1",
+ "kind": "MeshIntegration",
+ "name": "app-service-endpoint",
+ "uid": "00000000-0000-0000-0000-000000000000",
+ "controller": true,
+ "blockOwnerDeletion": true
+ }
+ ],
+ "managedFields": [
+ {
+ "manager": "nginx-ingress-controller",
+ "operation": "Update",
+ "apiVersion": "networking.k8s.io/v1",
+ "time": "2023-08-16T14:52:56Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:status": {
+ "f:loadBalancer": {
+ "f:ingress": {}
+ }
+ }
+ },
+ "subresource": "status"
+ },
+ {
+ "manager": "kubectl-client-side-apply",
+ "operation": "Update",
+ "apiVersion": "networking.k8s.io/v1",
+ "time": "2023-12-15T16:33:17Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ ".": {},
+ "f:kubectl.kubernetes.io/last-applied-configuration": {},
+ "f:nginx.ingress.kubernetes.io/auth-signin": {},
+ "f:nginx.ingress.kubernetes.io/configuration-snippet": {},
+ "f:nginx.ingress.kubernetes.io/service-upstream": {},
+ "f:nginx.ingress.kubernetes.io/upstream-vhost": {}
+ },
+ "f:labels": {
+ ".": {},
+ "f:backstage.io/kubernetes-id": {},
+ "f:ingress-class": {}
+ }
+ },
+ "f:spec": {
+ "f:ingressClassName": {},
+ "f:rules": {},
+ "f:tls": {}
+ }
+ }
+ },
+ {
+ "manager": "kubectl-label",
+ "operation": "Update",
+ "apiVersion": "networking.k8s.io/v1",
+ "time": "2024-02-21T15:00:44Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:labels": {
+ "f:controller-uid": {}
+ }
+ }
+ }
+ },
+ {
+ "manager": "metacontroller",
+ "operation": "Update",
+ "apiVersion": "networking.k8s.io/v1",
+ "time": "2024-02-21T15:01:01Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ "f:metacontroller.k8s.io/last-applied-configuration": {}
+ },
+ "f:ownerReferences": {
+ ".": {},
+ "k:{\"uid\":\"00000000-0000-0000-0000-000000000000\"}": {}
+ }
+ }
+ }
+ }
+ ]
+ },
+ "spec": {
+ "ingressClassName": "istio-internal",
+ "tls": {
+ "hosts": ["app-service-endpoint.dice-roller.backstage.io"],
+ "secretName": "dice-roller-wildcard-certificate"
+ },
+ "rules": [
+ {
+ "host": "app-service-endpoint.dice-roller.backstage.io",
+ "http": {
+ "paths": [
+ {
+ "pathType": "ImplementationSpecific",
+ "backend": {
+ "service": {
+ "name": "app-service-endpoint",
+ "port": {
+ "number": 8080
+ }
+ }
+ }
+ },
+ {
+ "pathType": "Second item in the list",
+ "backend": {
+ "service": {
+ "name": "app-service-endpoint",
+ "port": {
+ "number": 8080
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "status": {
+ "loadBalancer": {
+ "ingress": [
+ {
+ "ip": "1.2.3.4"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "deployments": [
+ {
+ "metadata": {
+ "annotations": {
+ "deployment.kubernetes.io/revision": "2",
+ "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"labels\":{\"backstage.io/kubernetes-id\":\"dice-roller\"},\"name\":\"dice-roller\",\"namespace\":\"default\"},\"spec\":{\"replicas\":10,\"selector\":{\"matchLabels\":{\"app\":\"dice-roller\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"dice-roller\",\"backstage.io/kubernetes-id\":\"dice-roller\"}},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]}]}}}}\n"
+ },
+ "creationTimestamp": "2020-09-23T12:00:55.000Z",
+ "generation": 3,
+ "labels": {
+ "backstage.io/kubernetes-id": "dice-roller"
+ },
+ "managedFields": [
+ {
+ "apiVersion": "apps/v1",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ ".": {},
+ "f:kubectl.kubernetes.io/last-applied-configuration": {}
+ },
+ "f:labels": {
+ ".": {},
+ "f:backstage.io/kubernetes-id": {}
+ }
+ },
+ "f:spec": {
+ "f:progressDeadlineSeconds": {},
+ "f:replicas": {},
+ "f:revisionHistoryLimit": {},
+ "f:selector": {
+ "f:matchLabels": {
+ ".": {},
+ "f:app": {}
+ }
+ },
+ "f:strategy": {
+ "f:rollingUpdate": {
+ ".": {},
+ "f:maxSurge": {},
+ "f:maxUnavailable": {}
+ },
+ "f:type": {}
+ },
+ "f:template": {
+ "f:metadata": {
+ "f:labels": {
+ ".": {},
+ "f:app": {},
+ "f:backstage.io/kubernetes-id": {}
+ }
+ },
+ "f:spec": {
+ "f:containers": {
+ "k:{\"name\":\"nginx\"}": {
+ ".": {},
+ "f:image": {},
+ "f:imagePullPolicy": {},
+ "f:name": {},
+ "f:ports": {
+ ".": {},
+ "k:{\"containerPort\":80,\"protocol\":\"TCP\"}": {
+ ".": {},
+ "f:containerPort": {},
+ "f:protocol": {}
+ }
+ },
+ "f:resources": {},
+ "f:terminationMessagePath": {},
+ "f:terminationMessagePolicy": {}
+ }
+ },
+ "f:dnsPolicy": {},
+ "f:restartPolicy": {},
+ "f:schedulerName": {},
+ "f:securityContext": {},
+ "f:terminationGracePeriodSeconds": {}
+ }
+ }
+ }
+ },
+ "manager": "kubectl",
+ "operation": "Update",
+ "time": "2020-09-25T09:58:50.000Z"
+ },
+ {
+ "apiVersion": "apps/v1",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ "f:deployment.kubernetes.io/revision": {}
+ }
+ },
+ "f:status": {
+ "f:availableReplicas": {},
+ "f:conditions": {
+ ".": {},
+ "k:{\"type\":\"Available\"}": {
+ ".": {},
+ "f:lastTransitionTime": {},
+ "f:lastUpdateTime": {},
+ "f:message": {},
+ "f:reason": {},
+ "f:status": {},
+ "f:type": {}
+ },
+ "k:{\"type\":\"Progressing\"}": {
+ ".": {},
+ "f:lastTransitionTime": {},
+ "f:lastUpdateTime": {},
+ "f:message": {},
+ "f:reason": {},
+ "f:status": {},
+ "f:type": {}
+ }
+ },
+ "f:observedGeneration": {},
+ "f:readyReplicas": {},
+ "f:replicas": {},
+ "f:updatedReplicas": {}
+ }
+ },
+ "manager": "kube-controller-manager",
+ "operation": "Update",
+ "time": "2020-09-25T09:58:55.000Z"
+ }
+ ],
+ "name": "dice-roller",
+ "namespace": "default",
+ "resourceVersion": "593230",
+ "selfLink": "/apis/apps/v1/namespaces/default/deployments/dice-roller",
+ "uid": "7551e949-42d1-4061-83c5-9da107186e47"
+ },
+ "spec": {
+ "progressDeadlineSeconds": 600,
+ "replicas": 10,
+ "revisionHistoryLimit": 10,
+ "selector": {
+ "matchLabels": {
+ "app": "dice-roller"
+ }
+ },
+ "strategy": {
+ "rollingUpdate": {
+ "maxSurge": "25%",
+ "maxUnavailable": "25%"
+ },
+ "type": "RollingUpdate"
+ },
+ "template": {
+ "metadata": {
+ "creationTimestamp": null,
+ "labels": {
+ "app": "dice-roller",
+ "backstage.io/kubernetes-id": "dice-roller"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "image": "nginx:1.14.2",
+ "imagePullPolicy": "IfNotPresent",
+ "name": "nginx",
+ "ports": [
+ {
+ "containerPort": 80,
+ "protocol": "TCP"
+ }
+ ],
+ "resources": {},
+ "terminationMessagePath": "/dev/termination-log",
+ "terminationMessagePolicy": "File"
+ }
+ ],
+ "dnsPolicy": "ClusterFirst",
+ "restartPolicy": "Always",
+ "schedulerName": "default-scheduler",
+ "securityContext": {},
+ "terminationGracePeriodSeconds": 30
+ }
+ }
+ },
+ "status": {
+ "availableReplicas": 10,
+ "conditions": [
+ {
+ "lastTransitionTime": "2020-09-23T12:00:55.000Z",
+ "lastUpdateTime": "2020-09-24T11:39:28.000Z",
+ "message": "ReplicaSet \"dice-roller-6c8646bfd\" has successfully progressed.",
+ "reason": "NewReplicaSetAvailable",
+ "status": "True",
+ "type": "Progressing"
+ },
+ {
+ "lastTransitionTime": "2020-09-25T09:58:55.000Z",
+ "lastUpdateTime": "2020-09-25T09:58:55.000Z",
+ "message": "Deployment has minimum availability.",
+ "reason": "MinimumReplicasAvailable",
+ "status": "True",
+ "type": "Available"
+ }
+ ],
+ "observedGeneration": 3,
+ "readyReplicas": 10,
+ "replicas": 10,
+ "updatedReplicas": 10
+ }
+ }
+ ]
+}
diff --git a/yarn.lock b/yarn.lock
index 7cd8bb3cdc..e212f245b1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4291,6 +4291,7 @@ __metadata:
d3-zoom: ^3.0.0
dagre: ^0.8.5
history: ^5.0.0
+ js-yaml: ^4.1.0
linkify-react: 4.1.3
linkifyjs: 4.1.3
lodash: ^4.17.21