Skip to content
5 changes: 3 additions & 2 deletions src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { BASEURL } from './constants'
import { GitPullError, HttpError, ValidationError } from './error'
import { DbMessage, getIo } from './middleware'
import { Core } from './otomi-models'
import { FileMap, getFilePath, renderManifest, renderManifestForSecrets } from './repo'
import { FileMap, getFilePath, getResourceName, renderManifest, renderManifestForSecrets } from './repo'
import { getSanitizedErrorMessage, removeBlankAttributes } from './utils'

const debug = Debug('otomi:repo')
Expand Down Expand Up @@ -283,7 +283,8 @@ export class Git {
const nodeValue = node.value
try {
const filePath = getFilePath(fileMap, nodePath, nodeValue, 'secrets.')
const manifest = renderManifestForSecrets(fileMap, nodeValue)
const resourceName = getResourceName(fileMap, nodePath, nodeValue)
const manifest = renderManifestForSecrets(fileMap, resourceName, nodeValue)
await this.writeFile(filePath, manifest, unsetBlankAttributes)
} catch (e) {
console.log(nodePath)
Expand Down
7 changes: 5 additions & 2 deletions src/openapi/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ info:
title: The otomi API
description: Holds the entire schema needed by console to autogenerate forms
version: 2.0.0b1
servers:
- url: '/'

externalDocs:
description: 'This is the base url of the external documentation'
Expand Down Expand Up @@ -1473,6 +1475,7 @@ paths:
schema:
type: array
items:
type: object
properties:
id:
$ref: '#/components/schemas/User/properties/id'
Expand Down Expand Up @@ -2218,7 +2221,7 @@ paths:

/v1/apiDocs:
get:
operationId: 'apiDocs'
operationId: 'v1apiDocs'
security: []
description: Get OpenAPIDoc document
responses:
Expand Down Expand Up @@ -2722,7 +2725,7 @@ components:
type: string
enum: [AplTeamProject]
spec:
$ref: 'project.yaml#/AplProjectSpec'
type: object
required:
- kind
- spec
Expand Down
7 changes: 0 additions & 7 deletions src/openapi/backup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@ Backup:
AplBackupSpec:
type: object
properties:
id:
type: string
teamId:
$ref: 'definitions.yaml#/idName'
name:
title: Name
$ref: 'definitions.yaml#/idName'
schedule:
$ref: 'definitions.yaml#/backupSchedule'
snapshotVolumes:
Expand Down
8 changes: 0 additions & 8 deletions src/openapi/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@ Build:
AplBuildSpec:
type: object
properties:
id:
type: string
teamId:
$ref: 'definitions.yaml#/idName'
name:
title: Name
$ref: 'definitions.yaml#/idName'
description: Results in image name harbor.<your-domain>/<team-name>/name.
tag:
$ref: 'definitions.yaml#/imageTag'
default: latest
Expand Down
6 changes: 0 additions & 6 deletions src/openapi/codeRepo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ CodeRepo:
AplCodeRepoSpec:
type: object
properties:
id:
type: string
teamId:
$ref: 'definitions.yaml#/idName'
name:
$ref: 'definitions.yaml#/idName'
gitService:
type: string
default: gitea
Expand Down
3 changes: 2 additions & 1 deletion src/openapi/internalRepoUrls.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ InternalRepoUrls:
platformAdmin: [read-any]
teamAdmin: [read-any]
teamMember: [read-any]
properties: {}
type: array
items:
type: string
9 changes: 1 addition & 8 deletions src/openapi/netpol.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@ Netpol:
AplNetpolSpec:
type: object
properties:
id:
type: string
teamId:
$ref: 'definitions.yaml#/idName'
name:
title: Name
$ref: 'definitions.yaml#/idName'
ruleType:
$ref: '#/ruleType'

Expand Down Expand Up @@ -115,7 +108,7 @@ ruleType:
protocol:
title: Protocol
type: string
enum: [ HTTPS, HTTP, TCP ]
enum: [HTTPS, HTTP, TCP]
default: HTTPS
required:
- number
Expand Down
11 changes: 0 additions & 11 deletions src/openapi/project.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,3 @@ Project:
$ref: 'service.yaml#/Service'
required:
- name

AplProjectSpec:
type: object
properties:
id:
type: string
teamId:
$ref: 'definitions.yaml#/idName'
name:
title: Name
$ref: 'definitions.yaml#/idName'
8 changes: 0 additions & 8 deletions src/openapi/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -206,14 +206,6 @@ AplServiceSpec:
allOf:
- type: object
properties:
id:
type: string
teamId:
$ref: 'definitions.yaml#/idName'
name:
title: Name
$ref: 'definitions.yaml#/idName'
example: some-service
namespace:
$ref: 'definitions.yaml#/idName'
description: A Kubernetes namespace.
Expand Down
9 changes: 1 addition & 8 deletions src/openapi/workload.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,6 @@ AplWorkloadSpec:
type: object
description: Define the location of the Workloads's manifests or Helm chart.
properties:
id:
type: string
teamId:
$ref: 'definitions.yaml#/idName'
name:
title: Name
$ref: 'definitions.yaml#/idName'
icon:
$ref: 'definitions.yaml#/wordCharacterPattern'
url:
Expand All @@ -203,7 +196,7 @@ AplWorkloadSpec:
$ref: 'definitions.yaml#/wordCharacterPattern'
default: HEAD
chartMetadata:
title: ''
title: Chart metadata
properties:
helmChartVersion:
type: string
Expand Down
2 changes: 0 additions & 2 deletions src/otomi-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { JSONSchema4 } from 'json-schema'
import { components, external, operations, paths } from 'src/generated-schema'
import OtomiStack from 'src/otomi-stack'

export type ResourceMetadata = components['schemas']['aplMetadata']['metadata']
export type ResourceTeamMetadata = components['schemas']['aplTeamMetadata']['metadata']
export type App = components['schemas']['App']
export type AppList = components['schemas']['AppList']
export type Backup = components['schemas']['Backup']
Expand Down
6 changes: 0 additions & 6 deletions src/otomi-stack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,6 @@ describe('Code repositories tests', () => {
},
},
spec: {
name: 'code-1',
gitService: 'github',
repositoryUrl: 'https://github.test.com',
},
Expand Down Expand Up @@ -585,7 +584,6 @@ describe('Code repositories tests', () => {
},
},
spec: {
name: 'code-1',
gitService: 'github',
repositoryUrl: 'https://github.test.com',
},
Expand Down Expand Up @@ -635,7 +633,6 @@ describe('Code repositories tests', () => {
},
},
spec: {
name: 'code-1-updated',
gitService: 'github',
repositoryUrl: 'https://github.test.com',
},
Expand Down Expand Up @@ -670,7 +667,6 @@ describe('Code repositories tests', () => {
kind: 'AplTeamCodeRepo',
metadata: { name: 'code-1-updated', labels: { 'apl.io/teamId': 'demo' } },
spec: {
name: 'code-1-updated',
gitService: 'github',
repositoryUrl: 'https://github.test.com',
},
Expand Down Expand Up @@ -780,7 +776,6 @@ describe('Code repositories tests', () => {
},
},
spec: {
name: 'code-1-updated',
gitService: 'github',
repositoryUrl: 'https://github.test.com',
private: true,
Expand Down Expand Up @@ -830,7 +825,6 @@ describe('Code repositories tests', () => {
},
},
spec: {
name: 'code-1-updated',
gitService: 'github',
repositoryUrl: 'https://github.test.com',
private: true,
Expand Down
2 changes: 1 addition & 1 deletion src/otomi-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2409,8 +2409,8 @@ export default class OtomiStack {
dns,
})
return removeBlankAttributes({
...serviceMeta,
...inService,
...serviceMeta,
ingress: {
...pick(serviceSpec, publicIngressFields),
domain: url.domain,
Expand Down
84 changes: 61 additions & 23 deletions src/repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { rmSync } from 'fs'
import { rm } from 'fs/promises'
import { globSync } from 'glob'
import jsonpath from 'jsonpath'
import { cloneDeep, get, merge, set } from 'lodash'
import { cloneDeep, get, merge, omit, set } from 'lodash'
import path from 'path'
import { getDirNames, loadYaml } from './utils'
import { AplKind } from './otomi-models'
import { getDirNames, loadYaml } from './utils'

export async function getTeamNames(envDir: string): Promise<Array<string>> {
const teamsDir = path.join(envDir, 'env', 'teams')
Expand Down Expand Up @@ -417,7 +417,7 @@ export function renderManifest(fileMap: FileMap, jsonPath: jsonpath.PathComponen
name: getResourceName(fileMap, jsonPath, data),
labels: {},
},
spec: data,
spec: omit(data, ['id', 'teamId', 'name']),
}
if (fileMap.resourceGroup === 'team') {
manifest.metadata.labels['apl.io/teamId'] = getTeamNameFromJsonPath(jsonPath)
Expand All @@ -426,10 +426,13 @@ export function renderManifest(fileMap: FileMap, jsonPath: jsonpath.PathComponen
return manifest
}

export function renderManifestForSecrets(fileMap: FileMap, data: Record<string, any>) {
export function renderManifestForSecrets(fileMap: FileMap, resourceName: string, data: Record<string, any>) {
return {
kind: fileMap.kind,
spec: data,
metadata: {
name: resourceName,
},
spec: omit(data, ['id', 'teamId', 'name']),
}
}

Expand All @@ -445,38 +448,73 @@ export function unsetValuesFileSync(envDir: string): string {
return valuesPath
}

function isKindValid(kind: string | undefined, fileMap: FileMap): boolean {
return (
kind === fileMap.kind ||
(kind === 'SealedSecret' && fileMap.kind === 'AplTeamSecret') ||
fileMap.kind === 'AplTeamWorkloadValues'
)
}

function isNameValid(data: Record<string, any>, fileMap: FileMap, fileName: string | undefined): boolean {
//TODO Remove users exception once name has been set in metadata consistently
return (
fileMap.resourceGroup === 'users' || fileMap.kind === 'AplTeamWorkloadValues' || data.metadata?.name === fileName
)
}

function isTeamValid(data: Record<string, any>, fileMap: FileMap, teamName: string | undefined): boolean {
return ['AplTeamWorkloadValues', 'AplTeamSecret'].includes(fileMap.kind) || data?.metadata?.labels?.['apl.io/teamId']
}

export async function loadFileToSpec(
filePath: string,
fileMap: FileMap,
spec: Record<string, any>,
deps = { loadYaml },
): Promise<void> {
const jsonPath = getJsonPath(fileMap, filePath)
const data = await deps.loadYaml(filePath)
if (fileMap.processAs === 'arrayItem') {
const ref: Record<string, any>[] = get(spec, jsonPath)
const name = filePath.match(/\/([^/]+)\.yaml$/)?.[1]
if (fileMap.kind === 'AplTeamWorkloadValues') {
//TODO remove this custom workaround for workloadValues as it has no spec
ref.push({ ...data, name })
} else if (fileMap.v2) {
if (data?.kind !== fileMap.kind && !(data?.kind === 'SealedSecret' && fileMap.kind === 'AplTeamSecret')) {
try {
const data = (await deps.loadYaml(filePath)) || {}
if (fileMap.processAs === 'arrayItem') {
const ref: Record<string, any>[] = get(spec, jsonPath)
const name = filePath.match(/\/([^/]+)\.yaml$/)?.[1]
if (!isKindValid(data?.kind, fileMap)) {
console.error(`Unexpected manifest kind in ${filePath}: ${data?.kind}`)
return
}
if (data.metadata.name !== name) {
console.error(`Unexpected name in ${filePath}: ${data.metadata.name}`)
if (!isNameValid(data, fileMap, name)) {
console.error(`Unexpected name in ${filePath}: ${data.metadata?.name}`)
return
}
ref.push(data)
if (fileMap.kind !== 'AplTeamWorkloadValues' && fileMap.resourceGroup === 'team') {
const teamName = filePath.match(/\/env\/teams\/([^/]+)\//)?.[1]
if (!isTeamValid(data, fileMap, teamName)) {
console.error(`Unexpected team in ${filePath}: ${data?.metadata?.labels?.['apl.io/teamId']}`)
return
}
}
if (fileMap.kind === 'AplUser') {
data.spec.id = data.metadata?.name
}
if (fileMap.kind === 'AplTeamWorkloadValues') {
//TODO remove this custom workaround for workloadValues as it has no spec
ref.push({ ...data, name })
} else if (fileMap.v2) {
ref.push(data)
} else {
ref.push(data?.spec)
}
} else {
ref.push(data?.spec)
const ref: Record<string, any> = get(spec, jsonPath)
// Decrypted secrets may need to be merged with plain text specs
const newRef = merge(cloneDeep(ref), data?.spec)
set(spec, jsonPath, newRef)
}
} else {
const ref: Record<string, any> = get(spec, jsonPath)
// Decrypted secrets may need to be merged with plain text specs
const newRef = merge(cloneDeep(ref), data?.spec)
set(spec, jsonPath, newRef)
} catch (e) {
console.log(filePath)
console.log(fileMap)
throw e
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/utils/manifests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ export function getAplObjectFromV1(kind: AplKind, spec: V1ApiObject | ServiceSpe
}

export function getV1ObjectFromApl(aplObject: AplResponseObject): V1ApiObject {
const teamId = aplObject.metadata.labels['apl.io/teamId']
return {
teamId: aplObject.metadata.labels['apl.io/teamId'],
name: aplObject.metadata.name,
...aplObject.spec,
...(teamId && { teamId }),
...omit(aplObject.spec, ['id', 'name', 'teamId']),
}
}

Expand Down
Loading