-
-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
321 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { HttpModule, Module } from '@nestjs/common'; | ||
import { SharedModule } from '../shared'; | ||
import { KubernetesService } from './kubernetes/kubernetes.service'; | ||
import { KubernetesController } from './kubernetes/kubernetes.controller'; | ||
|
||
@Module({ | ||
imports: [SharedModule, HttpModule.register({ timeout: 5000 })], | ||
providers: [KubernetesService], | ||
controllers: [KubernetesController], | ||
}) | ||
export class ExternalModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './external.module'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { IsEnum } from 'class-validator'; | ||
import { ApiModelProperty } from '@nestjs/swagger'; | ||
|
||
export enum EnvironmentType { | ||
Prod, | ||
NonProd, | ||
} | ||
export enum ZoneType { | ||
DMZ, | ||
Core, | ||
} | ||
|
||
export enum DCType { | ||
CLUSTER1, | ||
CLUSTER2, | ||
CLUSTER3, | ||
CLUSTER4, | ||
} | ||
|
||
export class Labels { | ||
@ApiModelProperty({ enum: ['Prod', 'NonProd'] }) | ||
@IsEnum(EnvironmentType) | ||
env: EnvironmentType; | ||
|
||
@ApiModelProperty({ required: false, enum: ['Core', 'DMZ'] }) | ||
@IsEnum(ZoneType) | ||
zone?: ZoneType; | ||
|
||
@ApiModelProperty({ required: false, enum: ['CLUSTER1', 'CLUSTER2', 'CLUSTER3', 'CLUSTER4'] }) | ||
@IsEnum(DCType) | ||
dc?: DCType; | ||
} |
36 changes: 36 additions & 0 deletions
36
apps/api/src/app/external/kubernetes/dto/search-project.dto.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { IsArray, IsAscii, IsOptional, IsString, Length, Matches, ValidateNested } from 'class-validator'; | ||
import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger'; | ||
import { Labels } from './labels.dto'; | ||
import { Type } from 'class-transformer'; | ||
|
||
export class SearchProjectDto { | ||
@ApiModelProperty({ type: [String] }) | ||
@IsArray() | ||
@IsOptional() | ||
readonly groups?: string[]; | ||
|
||
@ApiModelProperty({ type: String }) | ||
@IsString() | ||
@IsOptional() | ||
readonly userId?: string; | ||
|
||
@ApiModelPropertyOptional({ type: String }) | ||
@IsAscii() | ||
@IsOptional() | ||
@Length(5, 100) | ||
@Matches(/^[a-z\d-]+$/) | ||
readonly namespace?: string; | ||
|
||
@ApiModelPropertyOptional({ type: String, minLength: 5, maxLength: 100 }) | ||
@IsAscii() | ||
@IsOptional() | ||
@Length(5, 100) | ||
@Matches(/^[a-z\d-]+$/) | ||
readonly serviceAccountName: string; | ||
|
||
@ApiModelPropertyOptional({ type: Labels }) | ||
@IsOptional() | ||
@ValidateNested() | ||
@Type(() => Labels) | ||
readonly labels?: Labels; | ||
} |
15 changes: 15 additions & 0 deletions
15
apps/api/src/app/external/kubernetes/kubernetes.controller.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { KubernetesController } from './kubernetes.controller'; | ||
|
||
describe('Kubernetes Controller', () => { | ||
let module: TestingModule; | ||
beforeAll(async () => { | ||
module = await Test.createTestingModule({ | ||
controllers: [KubernetesController], | ||
}).compile(); | ||
}); | ||
it('should be defined', () => { | ||
const controller: KubernetesController = module.get<KubernetesController>(KubernetesController); | ||
expect(controller).toBeDefined(); | ||
}); | ||
}); |
28 changes: 28 additions & 0 deletions
28
apps/api/src/app/external/kubernetes/kubernetes.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Controller, Get, HttpStatus, Logger, Param } from '@nestjs/common'; | ||
import { ApiOAuth2Auth, ApiOperation, ApiResponse, ApiUseTags } from '@nestjs/swagger'; | ||
import { KubernetesService } from './kubernetes.service'; | ||
|
||
@ApiOAuth2Auth(['read']) | ||
@ApiUseTags('External', 'Kubernetes') | ||
@ApiResponse({ status: HttpStatus.OK, description: 'Found' }) | ||
@ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Not Found' }) | ||
@ApiResponse({ status: HttpStatus.UNAUTHORIZED, description: 'Unauthorized' }) | ||
@ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden' }) | ||
@Controller('kubernetes') | ||
export class KubernetesController { | ||
public readonly logger = new Logger(KubernetesController.name); | ||
|
||
constructor(private readonly kubernetesService: KubernetesService) {} | ||
|
||
@ApiOperation({ title: 'Get all namespaces im a cluster' }) | ||
@Get(':cluster') | ||
getAll(@Param('cluster') cluster: string): Promise<any> { | ||
return this.kubernetesService.listNamespaces(cluster); | ||
} | ||
|
||
@ApiOperation({ title: 'Find one namespace in a cluster by namespace' }) | ||
@Get(':cluster/:namespace') | ||
findOne(@Param('cluster') cluster: string, @Param('namespace') namespace: string): Promise<any> { | ||
return this.kubernetesService.getNamespace(cluster, namespace); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
apps/api/src/app/external/kubernetes/kubernetes.service.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { KubernetesService } from './kubernetes.service'; | ||
|
||
describe('KubernetesService', () => { | ||
let service: KubernetesService; | ||
beforeAll(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
providers: [KubernetesService], | ||
}).compile(); | ||
service = module.get<KubernetesService>(KubernetesService); | ||
}); | ||
it('should be defined', () => { | ||
expect(service).toBeDefined(); | ||
}); | ||
}); |
127 changes: 127 additions & 0 deletions
127
apps/api/src/app/external/kubernetes/kubernetes.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { | ||
BadRequestException, | ||
ConflictException, | ||
HttpException, | ||
HttpStatus, | ||
Injectable, | ||
Logger, | ||
NotFoundException, | ||
OnModuleInit, | ||
UnauthorizedException, | ||
} from '@nestjs/common'; | ||
import * as Api from 'kubernetes-client'; | ||
import { ConfigService } from '../../config'; | ||
import { environment as env } from '@env-api/environment'; | ||
|
||
const Client = Api.Client1_10; | ||
const config = Api.config; | ||
|
||
@Injectable() | ||
export class KubernetesService implements OnModuleInit { | ||
private readonly logger = new Logger(KubernetesService.name); | ||
|
||
private readonly clients = new Map( | ||
Object.entries(env.kubernetes).map<[string, Api.Api]>(([key, value]) => [ | ||
key, | ||
new Client({ | ||
config: { | ||
url: value.baseUrl, | ||
auth: { | ||
bearer: value.token, | ||
}, | ||
insecureSkipTlsVerify: true, | ||
version: 'v1', | ||
promises: true, | ||
}, | ||
version: value.version || '1.10', | ||
}), | ||
]), | ||
); | ||
|
||
constructor(private readonly appConfig: ConfigService) {} | ||
|
||
async onModuleInit() { | ||
// @ts-ignore | ||
// for (const [key, client] of this.clients.entries()) { | ||
// try { | ||
// await client.loadSpec(); | ||
// } catch (err) { | ||
// console.error(`Unable to connect to ${key}`, err); | ||
// } | ||
// } | ||
} | ||
|
||
public async listNamespaces(cluster: string) { | ||
try { | ||
const namespaces = await this.clients.get(cluster).api.v1.namespaces.get(); | ||
return namespaces.body.items; | ||
} catch (error) { | ||
KubernetesService.handleError(error); | ||
} | ||
} | ||
|
||
public async myNamespaces(cluster: string, token: string) { | ||
try { | ||
// this.client.get(cluster).setToken(token) | ||
const namespaces = await this.clients.get(cluster).api.v1.namespaces.get(); | ||
return namespaces.items; | ||
} catch (error) { | ||
KubernetesService.handleError(error); | ||
} | ||
} | ||
|
||
public async getNamespace(cluster: string, namespace: string) { | ||
try { | ||
const namespace1 = await this.clients | ||
.get(cluster) | ||
.api.v1.namespaces(namespace) | ||
.get(); | ||
return namespace1.body; | ||
} catch (error) { | ||
KubernetesService.handleError(error); | ||
} | ||
} | ||
|
||
public async myServiceAccounts(cluster: string, namespace: string) { | ||
try { | ||
const namespaces = await this.clients | ||
.get(cluster) | ||
.api.v1.namespaces(namespace) | ||
.serviceaccounts.get(); | ||
return namespaces.body.items; | ||
} catch (error) { | ||
KubernetesService.handleError(error); | ||
} | ||
} | ||
|
||
public async hasNamespace(cluster: string, namespace: string) { | ||
try { | ||
const foundNamespace = await this.clients | ||
.get(cluster) | ||
.api.v1.namespaces(namespace) | ||
.get(); | ||
return !!foundNamespace; | ||
} catch (error) { | ||
if (error.code === 404) return false; | ||
KubernetesService.handleError(error); | ||
} | ||
} | ||
|
||
static handleError(error: Error & { code?: number; statusCode?: number }) { | ||
const message = error.message || 'unknown error'; | ||
const statusCode = error.statusCode || error.code || HttpStatus.I_AM_A_TEAPOT; | ||
console.log(message, statusCode); | ||
switch (statusCode) { | ||
case HttpStatus.CONFLICT: | ||
throw new ConflictException(error.message); | ||
case HttpStatus.UNAUTHORIZED: | ||
throw new UnauthorizedException(error.message); | ||
case HttpStatus.NOT_FOUND: | ||
throw new NotFoundException(error.message); | ||
case HttpStatus.BAD_REQUEST: | ||
throw new BadRequestException(error.message); | ||
default: | ||
throw new HttpException(message, statusCode); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters