Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@
"^.+\\.(t|j)s$": "ts-jest"
},
"moduleNameMapper": {
"^@octokit/core$": "<rootDir>/__mocks__/@octokit/core.js"
"^@octokit/core$": "<rootDir>/__mocks__/@octokit/core.js",
"^jose$": "<rootDir>/__mocks__/jose/core.js"
},
"setupFilesAfterEnv": [
"<rootDir>/../jest-setup.js"
Expand Down
11 changes: 11 additions & 0 deletions server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,15 @@ enum NotificationType {
slack
webhook
discord
}

model RegistryUser {
id String @id @default(cuid())
username String
password String
scope Json

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
expiresAt DateTime?
}
17 changes: 17 additions & 0 deletions server/src/__mocks__/jose/core.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
importJWK: jest.fn().mockResolvedValue('mock-key'),
exportJWK: jest.fn().mockImplementation((v) => v),
SignJWT: jest.fn().mockImplementation((claims) => ({
setProtectedHeader: jest.fn().mockReturnThis(),
setIssuedAt: jest.fn().mockReturnThis(),
setIssuer: jest.fn().mockReturnThis(),
setSubject: jest.fn().mockReturnThis(),
setAudience: jest.fn().mockReturnThis(),
setExpirationTime: jest.fn().mockReturnThis(),
sign: jest.fn().mockResolvedValue('mock-jwt-token'),
})),
generateKeyPair: jest.fn().mockResolvedValue({
privateKey: {"kty":"EC","x":"fake","y":"fake","crv":"P-256","d":"fake"},
publicKey: {"kty":"EC","x":"fake","y":"fake","crv":"P-256"},
})
};
2 changes: 2 additions & 0 deletions server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { GroupModule } from './groups/groups.module';
import { RolesModule } from './roles/roles.module';
import { TokenModule } from './token/token.module';
import { CliModule } from './cli/cli.module';
import { RegistryModule } from './registry/registry.module';

@Module({
imports: [
Expand All @@ -51,6 +52,7 @@ import { CliModule } from './cli/cli.module';
RolesModule,
TokenModule,
CliModule,
RegistryModule
],
controllers: [AppController, TemplatesController],
providers: [AppService, TemplatesService],
Expand Down
2 changes: 2 additions & 0 deletions server/src/apps/apps.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { AppsService } from './apps.service';
import { KubernetesModule } from '../kubernetes/kubernetes.module';
import { AppsController } from './apps.controller';
import { PipelinesService } from '../pipelines/pipelines.service';
import { RegistryModule } from '../registry/registry.module';

@Module({
providers: [AppsService, KubernetesModule, PipelinesService],
exports: [AppsService],
controllers: [AppsController],
imports: [RegistryModule]
})
export class AppsModule {}
17 changes: 17 additions & 0 deletions server/src/apps/apps.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { IApp } from './apps.interface';
import { IPodSize, ISecurityContext } from 'src/config/config.interface';
import { IUser } from 'src/auth/auth.interface';
import { IKubectlApp } from 'src/kubernetes/kubernetes.interface';
import { RegistryService } from '../registry/registry.service';

const podsize: IPodSize = {
name: 'small',
Expand Down Expand Up @@ -122,6 +123,7 @@ describe('AppsService', () => {
let notificationsService: jest.Mocked<NotificationsService>;
let configService: jest.Mocked<ConfigService>;
let eventsGateway: jest.Mocked<EventsGateway>;
let registryService: jest.Mocked<RegistryService>;
const user: IUser = { id: '1', username: 'testuser' } as IUser;

beforeEach(async () => {
Expand Down Expand Up @@ -153,6 +155,10 @@ describe('AppsService', () => {
provide: EventsGateway,
useValue: { execStreams: {}, sendTerminalLine: jest.fn() },
},
{
provide: RegistryService,
useValue: { makeTemporaryPushCredentialsForImage: jest.fn() }
}
],
}).compile();

Expand All @@ -162,6 +168,7 @@ describe('AppsService', () => {
notificationsService = module.get(NotificationsService);
configService = module.get(ConfigService);
eventsGateway = module.get(EventsGateway);
registryService = module.get(RegistryService);
});

it('should be defined', () => {
Expand Down Expand Up @@ -225,6 +232,7 @@ describe('AppsService', () => {
describe('triggerImageBuild', () => {
it('should call createBuildJob', async () => {
(pipelinesService.getContext as jest.Mock).mockResolvedValue('ctx');
(registryService.makeTemporaryPushCredentialsForImage as jest.Mock).mockResolvedValue({ username: 'fake', password: 'fake'});
jest.spyOn(service, 'getApp').mockResolvedValue({
spec: {
gitrepo: { admin: true, ssh_url: 'repo' },
Expand All @@ -234,6 +242,7 @@ describe('AppsService', () => {
} as any);
await service.triggerImageBuild('p', 'ph', 'a', mockUSerGroups);
expect(kubectl.createBuildJob).toHaveBeenCalled();
expect(registryService.makeTemporaryPushCredentialsForImage).toHaveBeenCalled();
});
});

Expand Down Expand Up @@ -334,6 +343,7 @@ describe('AppsService', () => {
{} as any, // NotificationsService
{} as any, // ConfigService
mockEventsGateway,
{} as any, // RegistryService
);
});

Expand Down Expand Up @@ -450,6 +460,7 @@ describe('AppsService', () => {
{} as any, // NotificationsService
{} as any, // ConfigService
{} as any, // EventsGateway
{} as any, // RegistryService
);
});

Expand Down Expand Up @@ -489,6 +500,7 @@ describe('AppsService', () => {
{} as any, // NotificationsService
{} as any, // configService
{} as any, // eventsGateway
{} as any, // RegistryService
);
jest.spyOn(service, 'triggerImageBuild').mockResolvedValue({
status: 'ok',
Expand Down Expand Up @@ -550,6 +562,7 @@ describe('AppsService', () => {
{} as any, // NotificationsService
{} as any, // configService
{} as any, // eventsGateway
{} as any, // RegistryService
);
// Methoden ersetzen
service.getAllAppsList = mockGetAllAppsList;
Expand Down Expand Up @@ -672,6 +685,7 @@ describe('AppsService', () => {
mockNotificationsService,
mockConfigService,
{} as any,
{} as any, // RegistryService
);

service.createApp = jest.fn().mockResolvedValue(undefined);
Expand Down Expand Up @@ -893,6 +907,7 @@ describe('AppsService', () => {
{} as any, // NotificationsService
{} as any, // ConfigService
{} as any, // eventsGateway
{} as any, // RegistryService
);

// Override the methods and properties
Expand Down Expand Up @@ -939,6 +954,7 @@ describe('AppsService', () => {
mockNotificationsService,
{} as any, // configService
{} as any, // eventsGateway
{} as any, // RegistryService
);
service['logger'] = mockLogger;
});
Expand Down Expand Up @@ -1026,6 +1042,7 @@ describe('AppsService', () => {
{} as any, // NotificationsService
{} as any, // ConfigService
{} as any, // EventsGateway
{} as any, // RegistryService
);
});

Expand Down
9 changes: 8 additions & 1 deletion server/src/apps/apps.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ConfigService } from '../config/config.service';
import { KubectlTemplate } from '../templates/template';
import { Stream } from 'stream';
import { EventsGateway } from '../events/events.gateway';
import { RegistryService } from '../registry/registry.service';

@Injectable()
export class AppsService {
Expand All @@ -23,6 +24,7 @@ export class AppsService {
private NotificationsService: NotificationsService,
private configService: ConfigService,
private eventsGateway: EventsGateway,
private registryService: RegistryService
) {
//this.logger.log('AppsService initialized');
}
Expand Down Expand Up @@ -160,7 +162,9 @@ export class AppsService {

const timestamp = new Date().getTime();
if (contextName) {
const image = pipeline + '-' + appName;
this.kubectl.setCurrentContext(contextName);
const registryCredentials = await this.registryService.makeTemporaryPushCredentialsForImage(image);

this.kubectl.createBuildJob(
namespace,
Expand All @@ -173,8 +177,11 @@ export class AppsService {
ref: app.spec.branch, //git commit reference
},
{
image: `${process.env.KUBERO_BUILD_REGISTRY}/${pipeline}-${appName}`,
registry: process.env.KUBERO_BUILD_REGISTRY || "",
image: image,
tag: app.spec.branch + '-' + timestamp,
registryUsername: registryCredentials.username,
registryPassword: registryCredentials.password
},
);
}
Expand Down
8 changes: 5 additions & 3 deletions server/src/deployments/deployments.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Module } from '@nestjs/common';
import { DeploymentsController } from './deployments.controller';
import { DeploymentsService } from './deployments.service';
import { AppsService } from '../apps/apps.service';
import { LogsService } from '../logs/logs.service';
import { AppsModule } from '../apps/apps.module';
import { LogsModule } from '../logs/logs.module';
import { RegistryModule } from '../registry/registry.module';

@Module({
controllers: [DeploymentsController],
providers: [DeploymentsService, AppsService, LogsService],
imports: [AppsModule, LogsModule, RegistryModule],
providers: [DeploymentsService],
})
export class DeploymentsModule {}
7 changes: 7 additions & 0 deletions server/src/deployments/deployments.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { LogsService } from '../logs/logs.service';
import { IUser } from '../auth/auth.interface';
import { ILoglines } from 'src/logs/logs.interface';
import { mockKubectlApp as app } from '../apps/apps.controller.spec';
import { RegistryService } from 'src/registry/registry.service';

const mockUserGroups = ['group1', 'group2'];

Expand All @@ -26,6 +27,7 @@ describe('DeploymentsService', () => {
let pipelinesService: jest.Mocked<PipelinesService>;
let logsService: jest.Mocked<LogsService>;
let logLine: jest.Mocked<ILoglines>;
let registryService: jest.Mocked<RegistryService>;

beforeEach(() => {
kubectl = {
Expand All @@ -51,12 +53,17 @@ describe('DeploymentsService', () => {
fetchLogs: jest.fn(),
} as any;

registryService = {
makeTemporaryPushCredentialsForImage: jest.fn().mockResolvedValue({ username: 'fake', password: 'fake' }),
} as any;

service = new DeploymentsService(
kubectl,
appsService,
notificationsService,
pipelinesService,
logsService,
registryService
);

logLine = {
Expand Down
12 changes: 10 additions & 2 deletions server/src/deployments/deployments.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AppsService } from '../apps/apps.service';
import { PipelinesService } from '../pipelines/pipelines.service';
import { ILoglines } from '../logs/logs.interface';
import { LogsService } from '../logs/logs.service';
import { RegistryService } from '../registry/registry.service';
import { V1JobList } from '@kubernetes/client-node';

@Injectable()
Expand All @@ -22,6 +23,7 @@ export class DeploymentsService {
private notificationService: NotificationsService,
private pipelinesService: PipelinesService,
private LogsService: LogsService,
private registryService: RegistryService,
) {
//this.kubectl = options.kubectl
//this._io = options.io
Expand All @@ -35,7 +37,7 @@ export class DeploymentsService {
pipelineName: string,
phaseName: string,
appName: string,
userGroups: string[]
userGroups: string[],
): Promise<any> {
const namespace = pipelineName + '-' + phaseName;
const jobs = (await this.kubectl.getJobs(namespace)) as V1JobList;
Expand Down Expand Up @@ -139,6 +141,9 @@ export class DeploymentsService {

// Create the Build CRD
try {
const image = pipeline + '-' + app;
const registryCredentials =
await this.registryService.makeTemporaryPushCredentialsForImage(image);
await this.kubectl.createBuildJob(
namespace,
app,
Expand All @@ -150,8 +155,11 @@ export class DeploymentsService {
url: gitrepo,
},
{
image: process.env.KUBERO_BUILD_REGISTRY + '/' + pipeline + '-' + app,
registry: process.env.KUBERO_BUILD_REGISTRY || '',
image: image,
tag: reference,
registryUsername: registryCredentials.username,
registryPassword: registryCredentials.password,
},
);
} catch (error) {
Expand Down
5 changes: 3 additions & 2 deletions server/src/deployments/templates/buildpacks.yaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ spec:
value: "123456"
- name: APP
value: example
- name: PATCH_JSON
value: '{"spec":{"image":{"repository":"$REPOSITORY","tag": "$TAG"}}}'
command:
- sh
- -c
- 'kubectl patch kuberoapps $APP --type=merge -p "{\"spec\":{\"image\":{\"repository\":
\"$REPOSITORY\",\"tag\": \"$TAG\"}}}"'
- 'kubectl patch kuberoapps $APP --type=merge -p "$PATCH_JSON"'
image: bitnami/kubectl:latest
imagePullPolicy: Always
resources: {}
Expand Down
5 changes: 3 additions & 2 deletions server/src/deployments/templates/dockerfile.yaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ spec:
value: 123456
- name: APP
value: example
- name: PATCH_JSON
value: '{"spec":{"image":{"repository":"$REPOSITORY","tag": "$TAG"}}}'
command:
- sh
- -c
- 'kubectl patch kuberoapps $APP --type=merge -p "{\"spec\":{\"image\":{\"repository\":
\"$REPOSITORY\",\"tag\": \"$TAG\"}}}"'
- 'kubectl patch kuberoapps $APP --type=merge -p "$PATCH_JSON"'
image: bitnami/kubectl:latest
imagePullPolicy: Always
name: deploy
Expand Down
5 changes: 3 additions & 2 deletions server/src/deployments/templates/nixpacks.yaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ spec:
value: 123456
- name: APP
value: example
- name: PATCH_JSON
value: '{"spec":{"image":{"repository":"$REPOSITORY","tag": "$TAG"}}}'
command:
- sh
- -c
- 'kubectl patch kuberoapps $APP --type=merge -p "{\"spec\":{\"image\":{\"repository\":
\"$REPOSITORY\",\"tag\": \"$TAG\"}}}"'
- 'kubectl patch kuberoapps $APP --type=merge -p "$PATCH_JSON"'
image: bitnami/kubectl:latest
imagePullPolicy: Always
name: deploy
Expand Down
Loading