1ec4d07939
Inject registry-egress-proxy into Kaniko and network init containers so npm/apk/composer/pip/git clone work on restricted egress clusters. Co-authored-by: Cursor <cursoragent@cursor.com>
166 lines
5.4 KiB
TypeScript
166 lines
5.4 KiB
TypeScript
import { Test, TestingModule } from '@nestjs/testing';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import * as path from 'path';
|
|
import { BuildService } from './build.service';
|
|
import { Application } from '../applications/entities/application.entity';
|
|
import { AppRuntime } from '../common/enums';
|
|
import { ClustersService } from '../clusters/clusters.service';
|
|
import { RegistryService } from '../kubernetes/registry.service';
|
|
import { BuildProgressStore } from './build-progress.store';
|
|
import { SourceStorageService } from '../storage/source-storage.service';
|
|
|
|
describe('BuildService', () => {
|
|
let service: BuildService;
|
|
|
|
beforeEach(async () => {
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
providers: [
|
|
BuildService,
|
|
{
|
|
provide: ConfigService,
|
|
useValue: {
|
|
get: jest.fn((key: string) => {
|
|
const map: Record<string, string> = {
|
|
'build.namespace': 'cloudhost-builds',
|
|
'build.serviceAccount': 'kaniko-builder',
|
|
'registry.url': 'registry.local:5000',
|
|
};
|
|
return map[key];
|
|
}),
|
|
},
|
|
},
|
|
{ provide: ClustersService, useValue: {} },
|
|
{
|
|
provide: BuildProgressStore,
|
|
useValue: { get: jest.fn(), set: jest.fn(), clear: jest.fn() },
|
|
},
|
|
{ provide: RegistryService, useValue: {} },
|
|
{
|
|
provide: SourceStorageService,
|
|
useValue: {
|
|
isObjectStorage: () => false,
|
|
materializeToTempFile: jest.fn(),
|
|
getSize: jest.fn(),
|
|
},
|
|
},
|
|
],
|
|
}).compile();
|
|
|
|
service = module.get(BuildService);
|
|
});
|
|
|
|
describe('generateDockerfile', () => {
|
|
it('generates Go Dockerfile with requested runtime version', () => {
|
|
const app = {
|
|
runtime: AppRuntime.GO,
|
|
runtimeVersion: '1.22',
|
|
port: 8080,
|
|
} as Application;
|
|
|
|
const dockerfile = (service as any).generateDockerfile(app) as string;
|
|
|
|
expect(dockerfile).toContain('FROM golang:1.22-alpine');
|
|
expect(dockerfile).toContain('EXPOSE 8080');
|
|
});
|
|
|
|
it('generates Go Dockerfile with cmd package when present in archive entries', () => {
|
|
const app = {
|
|
runtime: AppRuntime.GO,
|
|
runtimeVersion: '1.22',
|
|
port: 8080,
|
|
} as Application;
|
|
|
|
const dockerfile = (service as any).generateDockerfile(app, [
|
|
'go.mod',
|
|
'cmd/server/main.go',
|
|
]) as string;
|
|
|
|
expect(dockerfile).toContain('go build -a -installsuffix cgo -ldflags="-w -s" -o main ./cmd/server');
|
|
});
|
|
|
|
it('generates Node.js Dockerfile with default port', () => {
|
|
const app = {
|
|
runtime: AppRuntime.NODEJS,
|
|
runtimeVersion: '20',
|
|
} as Application;
|
|
|
|
const dockerfile = (service as any).generateDockerfile(app) as string;
|
|
|
|
expect(dockerfile).toContain('FROM node:20');
|
|
expect(dockerfile).toContain('EXPOSE 3000');
|
|
});
|
|
|
|
it('generates Laravel Dockerfile with artisan migrate', () => {
|
|
const app = {
|
|
runtime: AppRuntime.LARAVEL,
|
|
phpVersion: '8.3',
|
|
} as Application;
|
|
|
|
const dockerfile = (service as any).generateDockerfile(app) as string;
|
|
|
|
expect(dockerfile).toContain('php:8.3');
|
|
expect(dockerfile).toContain('artisan migrate');
|
|
});
|
|
|
|
it('generates WordPress Dockerfile with official image', () => {
|
|
const app = {
|
|
runtime: AppRuntime.WORDPRESS,
|
|
runtimeVersion: '6.4',
|
|
} as Application;
|
|
|
|
const dockerfile = (service as any).generateDockerfile(app) as string;
|
|
|
|
expect(dockerfile).toContain('wordpress:6.4');
|
|
});
|
|
|
|
it('generates Django Dockerfile with detected settings module', () => {
|
|
const app = {
|
|
runtime: AppRuntime.DJANGO,
|
|
runtimeVersion: '3.12',
|
|
} as Application;
|
|
|
|
const dockerfile = (service as any).generateDockerfile(app, ['myproject/settings.py']) as string;
|
|
|
|
expect(dockerfile).toContain('DJANGO_SETTINGS_MODULE=myproject.settings');
|
|
expect(dockerfile).toContain('gunicorn');
|
|
});
|
|
|
|
it('generates .NET Dockerfile that restores nested csproj', () => {
|
|
const app = {
|
|
runtime: AppRuntime.DOTNET,
|
|
runtimeVersion: '8.0',
|
|
} as Application;
|
|
|
|
const dockerfile = (service as any).generateDockerfile(app, ['src/App/App.csproj']) as string;
|
|
|
|
expect(dockerfile).toContain('CSPROJ="src/App/App.csproj"');
|
|
expect(dockerfile).toContain('dotnet publish "$CSPROJ"');
|
|
});
|
|
});
|
|
|
|
describe('egressProxyEnvFrom', () => {
|
|
it('returns secretRef when BUILD_EGRESS_PROXY_SECRET is set', () => {
|
|
const config = (service as any).configService as { get: jest.Mock };
|
|
config.get.mockImplementation((key: string) => {
|
|
if (key === 'build.egressProxySecret') return 'registry-egress-proxy';
|
|
return undefined;
|
|
});
|
|
|
|
expect((service as any).egressProxyEnvFrom()).toEqual([
|
|
{ secretRef: { name: 'registry-egress-proxy' } },
|
|
]);
|
|
});
|
|
|
|
it('returns undefined when egress proxy is disabled', () => {
|
|
const config = (service as any).configService as { get: jest.Mock };
|
|
config.get.mockImplementation((key: string) => {
|
|
if (key === 'build.egressProxySecret') return '';
|
|
return undefined;
|
|
});
|
|
|
|
expect((service as any).egressProxyEnvFrom()).toBeUndefined();
|
|
expect((service as any).withEgressProxy({ name: 'kaniko' })).toEqual({ name: 'kaniko' });
|
|
});
|
|
});
|
|
});
|