Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/environments/graphql/resolvers/flux_spec.js')
-rw-r--r--spec/frontend/environments/graphql/resolvers/flux_spec.js341
1 files changed, 267 insertions, 74 deletions
diff --git a/spec/frontend/environments/graphql/resolvers/flux_spec.js b/spec/frontend/environments/graphql/resolvers/flux_spec.js
index aa6f9e120f0..ea733c6e0e8 100644
--- a/spec/frontend/environments/graphql/resolvers/flux_spec.js
+++ b/spec/frontend/environments/graphql/resolvers/flux_spec.js
@@ -1,4 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
+import { WatchApi } from '@gitlab/cluster-client';
import axios from '~/lib/utils/axios_utils';
import { HTTP_STATUS_OK, HTTP_STATUS_UNAUTHORIZED } from '~/lib/utils/http_status';
import { resolvers } from '~/environments/graphql/resolvers';
@@ -27,114 +28,306 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
describe('fluxKustomizationStatus', () => {
+ const client = { writeQuery: jest.fn() };
const endpoint = `${configuration.basePath}/apis/kustomize.toolkit.fluxcd.io/v1beta1/namespaces/${namespace}/kustomizations/${environmentName}`;
const fluxResourcePath =
'kustomize.toolkit.fluxcd.io/v1beta1/namespaces/my-namespace/kustomizations/app';
const endpointWithFluxResourcePath = `${configuration.basePath}/apis/${fluxResourcePath}`;
- it('should request Flux Kustomizations for the provided namespace via the Kubernetes API if the fluxResourcePath is not specified', async () => {
- mock
- .onGet(endpoint, { withCredentials: true, headers: configuration.baseOptions.headers })
- .reply(HTTP_STATUS_OK, {
- status: { conditions: fluxKustomizationsMock },
- });
+ describe('when k8sWatchApi feature is disabled', () => {
+ it('should request Flux Kustomizations for the provided namespace via the Kubernetes API if the fluxResourcePath is not specified', async () => {
+ mock
+ .onGet(endpoint, { withCredentials: true, headers: configuration.baseOptions.headers })
+ .reply(HTTP_STATUS_OK, {
+ status: { conditions: fluxKustomizationsMock },
+ });
+
+ const fluxKustomizationStatus = await mockResolvers.Query.fluxKustomizationStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
- const fluxKustomizationStatus = await mockResolvers.Query.fluxKustomizationStatus(null, {
- configuration,
- namespace,
- environmentName,
+ expect(fluxKustomizationStatus).toEqual(fluxKustomizationsMock);
});
+ it('should request Flux Kustomization for the provided fluxResourcePath via the Kubernetes API', async () => {
+ mock
+ .onGet(endpointWithFluxResourcePath, {
+ withCredentials: true,
+ headers: configuration.baseOptions.headers,
+ })
+ .reply(HTTP_STATUS_OK, {
+ status: { conditions: fluxKustomizationsMock },
+ });
- expect(fluxKustomizationStatus).toEqual(fluxKustomizationsMock);
- });
- it('should request Flux Kustomization for the provided fluxResourcePath via the Kubernetes API', async () => {
- mock
- .onGet(endpointWithFluxResourcePath, {
- withCredentials: true,
- headers: configuration.baseOptions.headers,
- })
- .reply(HTTP_STATUS_OK, {
- status: { conditions: fluxKustomizationsMock },
- });
+ const fluxKustomizationStatus = await mockResolvers.Query.fluxKustomizationStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ fluxResourcePath,
+ },
+ { client },
+ );
- const fluxKustomizationStatus = await mockResolvers.Query.fluxKustomizationStatus(null, {
- configuration,
- namespace,
- environmentName,
- fluxResourcePath,
+ expect(fluxKustomizationStatus).toEqual(fluxKustomizationsMock);
});
+ it('should throw an error if the API call fails', async () => {
+ const apiError = 'Invalid credentials';
+ mock
+ .onGet(endpoint, { withCredentials: true, headers: configuration.base })
+ .reply(HTTP_STATUS_UNAUTHORIZED, { message: apiError });
+
+ const fluxKustomizationsError = mockResolvers.Query.fluxKustomizationStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
- expect(fluxKustomizationStatus).toEqual(fluxKustomizationsMock);
+ await expect(fluxKustomizationsError).rejects.toThrow(apiError);
+ });
});
- it('should throw an error if the API call fails', async () => {
- const apiError = 'Invalid credentials';
- mock
- .onGet(endpoint, { withCredentials: true, headers: configuration.base })
- .reply(HTTP_STATUS_UNAUTHORIZED, { message: apiError });
- const fluxKustomizationsError = mockResolvers.Query.fluxKustomizationStatus(null, {
- configuration,
- namespace,
- environmentName,
+ describe('when k8sWatchApi feature is enabled', () => {
+ const mockWatcher = WatchApi.prototype;
+ const mockKustomizationStatusFn = jest.fn().mockImplementation(() => {
+ return Promise.resolve(mockWatcher);
+ });
+ const mockOnDataFn = jest.fn().mockImplementation((eventName, callback) => {
+ if (eventName === 'data') {
+ callback(fluxKustomizationsMock);
+ }
+ });
+ const resourceName = 'custom-resource';
+
+ beforeEach(() => {
+ gon.features = { k8sWatchApi: true };
+ jest.spyOn(mockWatcher, 'subscribeToStream').mockImplementation(mockKustomizationStatusFn);
+ jest.spyOn(mockWatcher, 'on').mockImplementation(mockOnDataFn);
+ });
+
+ describe('when the Kustomization data is present', () => {
+ beforeEach(() => {
+ mock
+ .onGet(endpoint, { withCredentials: true, headers: configuration.baseOptions.headers })
+ .reply(HTTP_STATUS_OK, {
+ metadata: { name: resourceName },
+ status: { conditions: fluxKustomizationsMock },
+ });
+ });
+ it('should watch Kustomization by the metadata name from the cluster_client library when the data is present', async () => {
+ await mockResolvers.Query.fluxKustomizationStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
+
+ expect(mockKustomizationStatusFn).toHaveBeenCalledWith(
+ `/apis/kustomize.toolkit.fluxcd.io/v1beta1/namespaces/${namespace}/kustomizations`,
+ {
+ watch: true,
+ fieldSelector: `metadata.name=${decodeURIComponent(resourceName)}`,
+ },
+ );
+ });
+
+ it('should return data when received from the library', async () => {
+ const kustomizationStatus = await mockResolvers.Query.fluxKustomizationStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
+
+ expect(kustomizationStatus).toEqual(fluxKustomizationsMock);
+ });
});
- await expect(fluxKustomizationsError).rejects.toThrow(apiError);
+ it('should not watch Kustomization by the metadata name from the cluster_client library when the data is not present', async () => {
+ mock
+ .onGet(endpoint, { withCredentials: true, headers: configuration.baseOptions.headers })
+ .reply(HTTP_STATUS_OK, {});
+
+ await mockResolvers.Query.fluxKustomizationStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
+
+ expect(mockKustomizationStatusFn).not.toHaveBeenCalled();
+ });
});
});
describe('fluxHelmReleaseStatus', () => {
+ const client = { writeQuery: jest.fn() };
const endpoint = `${configuration.basePath}/apis/helm.toolkit.fluxcd.io/v2beta1/namespaces/${namespace}/helmreleases/${environmentName}`;
const fluxResourcePath =
'helm.toolkit.fluxcd.io/v2beta1/namespaces/my-namespace/helmreleases/app';
const endpointWithFluxResourcePath = `${configuration.basePath}/apis/${fluxResourcePath}`;
- it('should request Flux Helm Releases via the Kubernetes API', async () => {
- mock
- .onGet(endpoint, { withCredentials: true, headers: configuration.baseOptions.headers })
- .reply(HTTP_STATUS_OK, {
- status: { conditions: fluxKustomizationsMock },
- });
+ describe('when k8sWatchApi feature is disabled', () => {
+ it('should request Flux Helm Releases via the Kubernetes API', async () => {
+ mock
+ .onGet(endpoint, { withCredentials: true, headers: configuration.baseOptions.headers })
+ .reply(HTTP_STATUS_OK, {
+ status: { conditions: fluxKustomizationsMock },
+ });
+
+ const fluxHelmReleaseStatus = await mockResolvers.Query.fluxHelmReleaseStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
- const fluxHelmReleaseStatus = await mockResolvers.Query.fluxHelmReleaseStatus(null, {
- configuration,
- namespace,
- environmentName,
+ expect(fluxHelmReleaseStatus).toEqual(fluxKustomizationsMock);
});
+ it('should request Flux HelmRelease for the provided fluxResourcePath via the Kubernetes API', async () => {
+ mock
+ .onGet(endpointWithFluxResourcePath, {
+ withCredentials: true,
+ headers: configuration.baseOptions.headers,
+ })
+ .reply(HTTP_STATUS_OK, {
+ status: { conditions: fluxKustomizationsMock },
+ });
- expect(fluxHelmReleaseStatus).toEqual(fluxKustomizationsMock);
- });
- it('should request Flux HelmRelease for the provided fluxResourcePath via the Kubernetes API', async () => {
- mock
- .onGet(endpointWithFluxResourcePath, {
- withCredentials: true,
- headers: configuration.baseOptions.headers,
- })
- .reply(HTTP_STATUS_OK, {
- status: { conditions: fluxKustomizationsMock },
- });
+ const fluxHelmReleaseStatus = await mockResolvers.Query.fluxHelmReleaseStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ fluxResourcePath,
+ },
+ { client },
+ );
- const fluxHelmReleaseStatus = await mockResolvers.Query.fluxHelmReleaseStatus(null, {
- configuration,
- namespace,
- environmentName,
- fluxResourcePath,
+ expect(fluxHelmReleaseStatus).toEqual(fluxKustomizationsMock);
});
+ it('should throw an error if the API call fails', async () => {
+ const apiError = 'Invalid credentials';
+ mock
+ .onGet(endpoint, { withCredentials: true, headers: configuration.base })
+ .reply(HTTP_STATUS_UNAUTHORIZED, { message: apiError });
+
+ const fluxHelmReleasesError = mockResolvers.Query.fluxHelmReleaseStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
- expect(fluxHelmReleaseStatus).toEqual(fluxKustomizationsMock);
+ await expect(fluxHelmReleasesError).rejects.toThrow(apiError);
+ });
});
- it('should throw an error if the API call fails', async () => {
- const apiError = 'Invalid credentials';
- mock
- .onGet(endpoint, { withCredentials: true, headers: configuration.base })
- .reply(HTTP_STATUS_UNAUTHORIZED, { message: apiError });
- const fluxHelmReleasesError = mockResolvers.Query.fluxHelmReleaseStatus(null, {
- configuration,
- namespace,
- environmentName,
+ describe('when k8sWatchApi feature is enabled', () => {
+ const mockWatcher = WatchApi.prototype;
+ const mockHelmReleaseStatusFn = jest.fn().mockImplementation(() => {
+ return Promise.resolve(mockWatcher);
+ });
+ const mockOnDataFn = jest.fn().mockImplementation((eventName, callback) => {
+ if (eventName === 'data') {
+ callback(fluxKustomizationsMock);
+ }
+ });
+ const resourceName = 'custom-resource';
+
+ beforeEach(() => {
+ gon.features = { k8sWatchApi: true };
+ jest.spyOn(mockWatcher, 'subscribeToStream').mockImplementation(mockHelmReleaseStatusFn);
+ jest.spyOn(mockWatcher, 'on').mockImplementation(mockOnDataFn);
+ });
+
+ describe('when the HelmRelease data is present', () => {
+ beforeEach(() => {
+ mock
+ .onGet(endpoint, { withCredentials: true, headers: configuration.baseOptions.headers })
+ .reply(HTTP_STATUS_OK, {
+ metadata: { name: resourceName },
+ status: { conditions: fluxKustomizationsMock },
+ });
+ });
+ it('should watch HelmRelease by the metadata name from the cluster_client library when the data is present', async () => {
+ await mockResolvers.Query.fluxHelmReleaseStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
+
+ expect(mockHelmReleaseStatusFn).toHaveBeenCalledWith(
+ `/apis/helm.toolkit.fluxcd.io/v2beta1/namespaces/${namespace}/helmreleases`,
+ {
+ watch: true,
+ fieldSelector: `metadata.name=${decodeURIComponent(resourceName)}`,
+ },
+ );
+ });
+
+ it('should return data when received from the library', async () => {
+ const fluxHelmReleaseStatus = await mockResolvers.Query.fluxHelmReleaseStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
+
+ expect(fluxHelmReleaseStatus).toEqual(fluxKustomizationsMock);
+ });
});
- await expect(fluxHelmReleasesError).rejects.toThrow(apiError);
+ it('should not watch Kustomization by the metadata name from the cluster_client library when the data is not present', async () => {
+ mock
+ .onGet(endpoint, { withCredentials: true, headers: configuration.baseOptions.headers })
+ .reply(HTTP_STATUS_OK, {});
+
+ await mockResolvers.Query.fluxHelmReleaseStatus(
+ null,
+ {
+ configuration,
+ namespace,
+ environmentName,
+ },
+ { client },
+ );
+
+ expect(mockHelmReleaseStatusFn).not.toHaveBeenCalled();
+ });
});
});
});