Skip to content

Commit

Permalink
feat: config sync is optional (#60)
Browse files Browse the repository at this point in the history
This change allows the UI to use clusters that Config Sync is not installed on.
  • Loading branch information
ChristopherFry committed Jun 29, 2022
1 parent 6ebf14f commit c4c1976
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 10 deletions.
6 changes: 6 additions & 0 deletions plugins/cad/src/apis/ConfigAsDataApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/

import { createApiRef } from '@backstage/core-plugin-api';
import { ListApiGroups } from '../types/ApiGroup';
import { ListConfigManagements } from '../types/ConfigManagement';
import { Function } from '../types/Function';
import { PackageRevision } from '../types/PackageRevision';
import {
Expand All @@ -28,6 +30,10 @@ import { ListSecrets, Secret } from '../types/Secret';
export type ConfigAsDataApi = {
getFeatures(): Promise<void>;

listApiGroups(): Promise<ListApiGroups>;

listConfigManagements(): Promise<ListConfigManagements>;

createSecret(secret: Secret): Promise<Secret>;

getSecret(name: string): Promise<Secret>;
Expand Down
16 changes: 16 additions & 0 deletions plugins/cad/src/apis/PorchRestApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import { DiscoveryApi, FetchApi, OAuthApi } from '@backstage/core-plugin-api';
import { ConfigAsDataApi } from '.';
import { ListApiGroups } from '../types/ApiGroup';
import { ListConfigManagements } from '../types/ConfigManagement';
import { Function } from '../types/Function';
import { KubernetesStatus } from '../types/KubernetesStatus';
import { PackageRevision } from '../types/PackageRevision';
Expand Down Expand Up @@ -141,6 +143,20 @@ export class PorchRestAPI implements ConfigAsDataApi {
this.authentication = features.authentication;
}

async listApiGroups(): Promise<ListApiGroups> {
const apiGroups = await this.cadFetch('apis');

return apiGroups;
}

async listConfigManagements(): Promise<ListConfigManagements> {
const configManagements = await this.cadFetch(
'apis/configmanagement.gke.io/v1/configmanagements',
);

return configManagements;
}

async createSecret(secret: Secret): Promise<Secret> {
const namespace = secret.metadata.namespace || 'default';

Expand Down
3 changes: 2 additions & 1 deletion plugins/cad/src/components/LandingPage/LandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
registerRepositoryRouteRef,
repositoryRouteRef,
} from '../../routes';
import { loadFeatures } from '../../utils/featureFlags';
import { AddPackagePage } from '../AddPackagePage';
import { PackageRevisionPage } from '../PackageRevisionPage';
import { PackageRevisionPageMode } from '../PackageRevisionPage/PackageRevisionPage';
Expand All @@ -39,7 +40,7 @@ import { RepositoryPage } from '../RepositoryPage';
export const LandingPage = () => {
const api = useApi(configAsDataApiRef);

const { loading, error } = useAsync(() => api.getFeatures(), []);
const { loading, error } = useAsync(() => loadFeatures(api), []);

const getContent = (): JSX.Element => {
if (loading) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
SyncStatus,
SyncStatusState,
} from '../../utils/configSync';
import { isConfigSyncEnabled } from '../../utils/featureFlags';
import {
filterPackageRevisions,
findLatestPublishedRevision,
Expand Down Expand Up @@ -145,6 +146,8 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {

const latestPublishedUpstream = useRef<PackageRevision>();

const configSyncEnabled = isConfigSyncEnabled();

const loadRepositorySummary = async (): Promise<void> => {
const thisRepositorySummary = await getRepositorySummary(
api,
Expand Down Expand Up @@ -286,7 +289,11 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {

useAsync(async () => {
if (!loading && packageRevision && repositorySummary) {
if (isLatestPublishedPackageRevision && isDeploymentPackage) {
if (
isLatestPublishedPackageRevision &&
isDeploymentPackage &&
configSyncEnabled
) {
const { items: allRootSyncs } = await api.listRootSyncs();

const thisRootSync = findRootSyncForPackage(
Expand Down Expand Up @@ -400,7 +407,7 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {

await api.approvePackageRevision(targetRevision);

if (isDeploymentPackage) {
if (isDeploymentPackage && configSyncEnabled) {
await updateRootSyncToLatestPackage(targetRevision);
}

Expand Down
18 changes: 11 additions & 7 deletions plugins/cad/src/components/RepositoryPage/RepositoryPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { addPackageRouteRef } from '../../routes';
import { Function } from '../../types/Function';
import { RepositorySummary } from '../../types/RepositorySummary';
import { RootSync } from '../../types/RootSync';
import { isConfigSyncEnabled } from '../../utils/featureFlags';
import {
getPackageSummaries,
PackageSummary,
Expand Down Expand Up @@ -64,6 +65,8 @@ export const RepositoryPage = () => {
);
const [functions, setFunctions] = useState<Function[]>([]);

const configSyncEnabled = isConfigSyncEnabled();

const { loading: repositoryLoading, error: repositoryError } =
useAsync(async (): Promise<void> => {
const thisRepositorySummary = await getRepositorySummary(
Expand All @@ -84,7 +87,8 @@ export const RepositoryPage = () => {

if (isPackageRepository(thisRepository)) {
const getRootSyncs = async (): Promise<RootSync[]> => {
if (!isDeploymentRepository(thisRepository)) return [];
if (!configSyncEnabled || !isDeploymentRepository(thisRepository))
return [];

const { items: rootSyncs } = await api.listRootSyncs();
return rootSyncs;
Expand Down Expand Up @@ -116,16 +120,16 @@ export const RepositoryPage = () => {
useEffect(() => {
if (
repositorySummary &&
isDeploymentRepository(repositorySummary.repository)
configSyncEnabled &&
isDeploymentRepository(repositorySummary.repository) &&
packageSummaries.length > 0
) {
const refreshRootSync = async (): Promise<void> => {
const { items: syncs } = await api.listRootSyncs();

const updatedPackageSummaries = updatePackageSummariesSyncStatus(
packageSummaries,
syncs,
setPackageSummaries(thisPackageSummaries =>
updatePackageSummariesSyncStatus(thisPackageSummaries, syncs),
);
setPackageSummaries(updatedPackageSummaries);
};

const refreshSeconds = 10;
Expand All @@ -140,7 +144,7 @@ export const RepositoryPage = () => {
}

return undefined;
}, [api, repositorySummary, packageSummaries]);
}, [api, repositorySummary, packageSummaries, configSyncEnabled]);

if (repositoryLoading || packagesLoading) {
return <Progress />;
Expand Down
32 changes: 32 additions & 0 deletions plugins/cad/src/types/ApiGroup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright 2022 Google LLC
*
* 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 type ListApiGroups = {
kind: string;
apiVersion: string;
groups: ApiGroup[];
};

export type ApiGroup = {
name: string;
preferredVersion: ApiGroupVersion;
versions: ApiGroupVersion[];
};

export type ApiGroupVersion = {
groupVersion: string;
version: string;
};
46 changes: 46 additions & 0 deletions plugins/cad/src/types/ConfigManagement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Copyright 2022 Google LLC
*
* 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 { KubernetesKeyValueObject } from './KubernetesResource';

export type ListConfigManagements = {
kind: string;
apiVersion: string;
items: ConfigManagement[];
};

export type ConfigManagement = {
apiVersion: string;
kind: string;
metadata: ConfigManagementMetadata;
spec: ConfigManagementSpec;
status?: ConfigManagementStatus;
};

export type ConfigManagementMetadata = {
name: string;
labels?: KubernetesKeyValueObject;
annotations?: KubernetesKeyValueObject;
};

export type ConfigManagementSpec = {
enableMultiRepo: boolean;
};

export type ConfigManagementStatus = {
configManagementVersion?: string;
healthy: boolean;
};
22 changes: 22 additions & 0 deletions plugins/cad/src/utils/featureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,28 @@
* limitations under the License.
*/

import { ConfigAsDataApi } from '../apis';

let isConfigSyncInstalled = false;

export const isConfigSyncEnabled = (): boolean => isConfigSyncInstalled;

export const allowFunctionRepositoryRegistration = (): boolean => false;

export const showRegisteredFunctionRepositories = (): boolean => false;

export const loadFeatures = async (api: ConfigAsDataApi): Promise<void> => {
await api.getFeatures();

const { groups } = await api.listApiGroups();

const configManagementGroupExists = !!groups.find(
apiGroup => apiGroup.name === 'configmanagement.gke.io',
);

if (configManagementGroupExists) {
const { items: configManagements } = await api.listConfigManagements();

isConfigSyncInstalled = configManagements.length > 0;
}
};

0 comments on commit c4c1976

Please sign in to comment.