Skip to content
Closed
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
20 changes: 20 additions & 0 deletions src/api/internalRepoUrls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Debug from 'debug'
import { Operation, OperationHandlerArray } from 'express-openapi'
import { OpenApiRequestExt } from 'src/otomi-models'

const debug = Debug('otomi:api:internalRepoUrls')

export default function (): OperationHandlerArray {
const get: Operation = [
async ({ otomi }: OpenApiRequestExt, res): Promise<string[]> => {
debug('getInternalRepoUrls')
const v = await otomi.getInternalRepoUrls()
res.json(v)
return v
},
]
const api = {
get,
}
return api
}
17 changes: 17 additions & 0 deletions src/openapi/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,21 @@ paths:
schema:
type: object

'/internalRepoUrls':
get:
operationId: getInternalRepoUrls
x-aclSchema: InternalRepoUrls
responses:
<<: *DefaultGetResponses
'200':
description: Successfully obtained internal repo urls
content:
application/json:
schema:
type: array
items:
type: string

'/builds':
get:
operationId: getAllBuilds
Expand Down Expand Up @@ -1672,6 +1687,8 @@ components:
$ref: backup.yaml#/Backup
Build:
$ref: build.yaml#/Build
InternalRepoUrls:
$ref: internalRepoUrls.yaml#/InternalRepoUrls
Cloudtty:
$ref: cloudtty.yaml#/Cloudtty
Cluster:
Expand Down
29 changes: 21 additions & 8 deletions src/openapi/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,28 @@ Build:
$ref: 'definitions.yaml#/imageTag'
default: latest
description: Image tag
repoType:
title: Repository type
properties:
type:
title: ''
type: string
enum:
- internal
- external
default: internal
external:
title: ''
properties:
private:
type: boolean
description: Select when the external repository is private.
default: false
secretName:
description: The name of the secret with the credentials of the external private Git repository
type: string
mode:
$ref: '#/buildMode'
externalRepo:
type: boolean
description: Select when using an external private Git repository.
default: false
secretName:
description: The name of the secret with the credentials of the external private Git repository.
type: string
trigger:
type: boolean
default: false
Expand All @@ -51,7 +64,7 @@ Build:
- name

buildMode:
title: Mode
title: Build Mode
description: Choose between Docker or Buildpacks.
type: object
oneOf:
Expand Down
10 changes: 10 additions & 0 deletions src/openapi/internalRepoUrls.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
InternalRepoUrls:
x-acl:
platformAdmin:
- read-any
teamAdmin:
- read-any
teamMember:
- read-any
properties: {}
type: array
1 change: 1 addition & 0 deletions src/otomi-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type WorkloadValues = components['schemas']['WorkloadValues']
export type User = components['schemas']['User']
export type Project = components['schemas']['Project']
export type Build = components['schemas']['Build']
export type InternalRepoUrls = components['schemas']['InternalRepoUrls']
export type Policy = components['schemas']['Policy']
export type Policies = components['schemas']['Policies']
export type Cloudtty = components['schemas']['Cloudtty']
Expand Down
13 changes: 13 additions & 0 deletions src/otomi-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import {
watchPodUntilRunning,
} from './k8s_operations'
import { validateBackupFields } from './utils/backupUtils'
import { getGiteaRepoUrls } from './utils/buildUtils'
import { getPolicies } from './utils/policiesUtils'
import { encryptSecretItem } from './utils/sealedSecretUtils'
import { getKeycloakUsers } from './utils/userUtils'
Expand Down Expand Up @@ -841,6 +842,18 @@ export default class OtomiStack {
return inventory
}

async getInternalRepoUrls(): Promise<string[]> {
if (env.isDev) return []
const { cluster, otomi } = this.getSettings(['cluster', 'otomi'])
const gitea = this.getApp('admin', 'gitea')
const username = gitea?.values?.adminUsername as string
const password = otomi?.adminPassword
const orgName = 'otomi'
const domainSuffix = cluster?.domainSuffix
const internalRepoUrls = (await getGiteaRepoUrls(username, password, orgName, domainSuffix)) || []
return internalRepoUrls
}

getTeamBuilds(teamId: string): Array<Build> {
const ids = { teamId }
return this.db.getCollection('builds', ids) as Array<Build>
Expand Down
39 changes: 39 additions & 0 deletions src/utils/buildUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import axios from 'axios'
import { OtomiError } from 'src/error'

const axiosInstance = (adminUsername, adminPassword, domainSuffix) =>
axios.create({
baseURL: `https://gitea.${domainSuffix}/api/v1`,
auth: {
username: adminUsername,
password: adminPassword,
},
})

export async function getGiteaRepoUrls(adminUsername, adminPassword, orgName, domainSuffix) {
try {
const repoNames = new Set<string>()
const orgResponse = await axiosInstance(adminUsername, adminPassword, domainSuffix).get(`/orgs/${orgName}/repos`)
orgResponse.data.forEach((repo) => repoNames.add(repo.full_name as string))

const users = await axiosInstance(adminUsername, adminPassword, domainSuffix).get('/admin/users')
const usernames = users.data.map((user) => user.username)
for (const username of usernames) {
const response = await axiosInstance(adminUsername, adminPassword, domainSuffix).get(`/users/${username}/repos`)
response.data.forEach((repo) => repoNames.add(repo.full_name as string))
}
// filter out values, charts and team-<teamId>-argocd repositories
const regex = new RegExp(`^${orgName}\\/team-[\\w-]+-argocd$`)
const filteredRepoNames = Array.from(repoNames).filter(
(item: string) => item !== `${orgName}/values` && item !== `${orgName}/charts` && !regex.test(item),
)
const giteaRepoUrls = filteredRepoNames.map((name: string) => `https://gitea.${domainSuffix}/${name}.git`)
return giteaRepoUrls
} catch (err) {
console.log('err', err)
const error = new OtomiError('Error getting internal repository names')
error.code = 500
error.publicMessage = 'Error getting internal repository names'
throw error
}
}