Skip to content

Commit

Permalink
feat: adding kind.cluster.creation.image configuration property for k…
Browse files Browse the repository at this point in the history
…ind cluster (#3508)

* Adding kind.cluster.creation.image configuration property for creating kind cluster

Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com>
Co-authored-by: Florent BENOIT <fbenoit@redhat.com>
  • Loading branch information
axel7083 and benoitf committed Aug 14, 2023
1 parent 595d6fa commit 475c31c
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 19 deletions.
7 changes: 7 additions & 0 deletions extensions/kind/package.json
Expand Up @@ -47,6 +47,13 @@
"default": true,
"scope": "KubernetesProviderConnectionFactory",
"description": "Setup an ingress controller (Contour https://projectcontour.io)"
},
"kind.cluster.creation.controlPlaneImage": {
"type": "string",
"default": "",
"scope": "KubernetesProviderConnectionFactory",
"placeholder": "Leave empty for using latest.",
"markdownDescription": "Node’s container image (Available image tags on [kind/releases](https://github.com/kubernetes-sigs/kind/releases))"
}
}
},
Expand Down
27 changes: 24 additions & 3 deletions extensions/kind/src/create-cluster.spec.ts
Expand Up @@ -117,15 +117,26 @@ test('expect error if Kubernetes reports error', async () => {
});

test('check cluster configuration generation', async () => {
const conf = getKindClusterConfig('k1', 80, 443);
const conf = getKindClusterConfig('k1', 80, 443, 'image:tag');
expect(conf).to.contains('name: k1');
expect(conf).to.contains('hostPort: 80');
expect(conf).to.contains('hostPort: 443');
expect(conf).to.contains('image: image:tag');
});

test('check cluster configuration empty string image', async () => {
const conf = getKindClusterConfig(undefined, undefined, undefined, '');
expect(conf).to.not.contains('image:');
});

test('check cluster configuration null string image', async () => {
const conf = getKindClusterConfig(undefined, undefined, undefined, undefined);
expect(conf).to.not.contains('image:');
});

test('check that consilience check returns warning message', async () => {
(getMemTotalInfo as Mock).mockReturnValue(3000000000);
const checks = await connectionAuditor('docker');
const checks = await connectionAuditor('docker', {});

expect(checks).toBeDefined();
expect(checks).toHaveProperty('records');
Expand All @@ -138,9 +149,19 @@ test('check that consilience check returns warning message', async () => {

test('check that consilience check returns no warning messages', async () => {
(getMemTotalInfo as Mock).mockReturnValue(6000000001);
const checks = await connectionAuditor('docker');
const checks = await connectionAuditor('docker', {});

expect(checks).toBeDefined();
expect(checks).toHaveProperty('records');
expect(checks.records.length).toBe(0);
});

test('check that consilience check returns warning message when image has no sha256 digest', async () => {
const checks = await connectionAuditor('docker', { 'kind.cluster.creation.controlPlaneImage': 'image:tag' });

expect(checks).toBeDefined();
expect(checks).toHaveProperty('records');
expect(checks.records.length).toBe(1);
expect(checks.records[0]).toHaveProperty('type');
expect(checks.records[0].type).toBe('warning');
});
46 changes: 32 additions & 14 deletions extensions/kind/src/create-cluster.ts
Expand Up @@ -24,14 +24,20 @@ import mustache from 'mustache';
import { parseAllDocuments } from 'yaml';

import createClusterConfTemplate from './templates/create-cluster-conf.mustache?raw';
import type { AuditRecord, AuditResult, CancellationToken } from '@podman-desktop/api';
import type { AuditRecord, AuditResult, CancellationToken, AuditRequestItems } from '@podman-desktop/api';
import ingressManifests from '/@/resources/contour.yaml?raw';

export function getKindClusterConfig(clusterName: string, httpHostPort: number, httpsHostPort: number) {
export function getKindClusterConfig(
clusterName: string,
httpHostPort: number,
httpsHostPort: number,
controlPlaneImage?: string,
) {
return mustache.render(createClusterConfTemplate, {
clusterName: clusterName,
httpHostPort: httpHostPort,
httpsHostPort: httpsHostPort,
controlPlaneImage: controlPlaneImage,
});
}

Expand All @@ -57,28 +63,37 @@ export async function setupIngressController(clusterName: string) {
);
}

export async function connectionAuditor(provider: string): Promise<AuditResult> {
export async function connectionAuditor(provider: string, items: AuditRequestItems): Promise<AuditResult> {
const records: AuditRecord[] = [];
const auditResult = {
records: records,
};

const image = items['kind.cluster.creation.controlPlaneImage'];
if (image && !image.includes('@sha256:')) {
records.push({
type: 'warning',
record: 'It is recommend to include the @sha256:{image digest} for the image used.',
});
}

const providerSocket = extensionApi.provider
.getContainerConnections()
.find(connection => connection.connection.type === provider);

if (!providerSocket) return undefined;
if (!providerSocket) return auditResult;

const memTotal = await getMemTotalInfo(providerSocket.connection.endpoint.socketPath);

// check if configured memory is less than 6GB
if (memTotal < 6000000000) {
return {
records: [
{
type: 'info',
record: 'It is recommend to install Kind on a virtual machine with at least 6GB of memory.',
} as AuditRecord,
],
} as AuditResult;
records.push({
type: 'info',
record: 'It is recommend to install Kind on a virtual machine with at least 6GB of memory.',
});
}

return { records: [] } as AuditResult;
return auditResult;
}

export async function createCluster(
Expand Down Expand Up @@ -124,8 +139,11 @@ export async function createCluster(
ingressController = params['kind.cluster.creation.ingress'] === 'on';
}

// grab custom kind node image if defined
const controlPlaneImage = params['kind.cluster.creation.controlPlaneImage'];

// create the config file
const kindClusterConfig = getKindClusterConfig(clusterName, httpHostPort, httpsHostPort);
const kindClusterConfig = getKindClusterConfig(clusterName, httpHostPort, httpsHostPort, controlPlaneImage);

// create a temporary file
const tmpDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'kind-cluster-config-'));
Expand Down
5 changes: 3 additions & 2 deletions extensions/kind/src/extension.ts
Expand Up @@ -60,8 +60,9 @@ async function registerProvider(
creationDisplayName: 'Kind cluster',
},
{
auditItems: async (items: AuditRequestItems) =>
await connectionAuditor(new ProviderNameExtractor(items).getProviderName()),
auditItems: async (items: AuditRequestItems) => {
return await connectionAuditor(new ProviderNameExtractor(items).getProviderName(), items);
},
},
);
extensionContext.subscriptions.push(disposable);
Expand Down
3 changes: 3 additions & 0 deletions extensions/kind/src/templates/create-cluster-conf.mustache
Expand Up @@ -3,6 +3,9 @@ apiVersion: kind.x-k8s.io/v1alpha4
name: {{{ clusterName }}}
nodes:
- role: control-plane
{{#controlPlaneImage}}
image: {{{ controlPlaneImage }}}
{{/controlPlaneImage}}
kubeadmConfigPatches:
- |
kind: InitConfiguration
Expand Down

0 comments on commit 475c31c

Please sign in to comment.