Objectiu 🚀
El present document descriu les diferents capacitats tecnològiques que suporta actualment la plataforma GHEC.
Llenguates i tipus d’artefactes
A la següent matriu es poden observar els llenguatges i tipus d’artefactes suportats:
Desplegament a hiperescalars
Actualment, estan certificats els desplegaments als següents hiperescalars, sempre acotat als llenguatges i tipus d’artefactes indicats en la secció anterior:
Altres capacitats
Addicionalment, la plataforma suporta les següents capacitats :
Desplegaments a API Manager corporatiu (APIM)
Suport a les següents accions i operatives:
-
PUBLISH: publicació d’una nova versió d’un producte i APIs associades. El sistema permet redesplegar versions als catàlegs preproductius sempre que no hagin arribat a producció.
-
INFO: obtenció d’informació del producte dins d’un catàleg (versions, subscripcions i altres). Caldrà seleccionar el catàleg del qual es desitja informació.
-
Operatives:
- DELETE: eliminació del producte. Caldrà seleccionar el catàleg sobre el qual es desitja esborrar i indicar la versió del producte (CURRENT_PRODUCT_VERSION). Per exemple: 1.1.0.
- DEPRECATE: deprecació d’una versió del producte sense deixar cap versió vigent. Caldrà seleccionar el catàleg sobre el qual es desitja deprecar i indicar la versió del producte (CURRENT_PRODUCT_VERSION). Per exemple: 1.1.0.
- REPLACE: retirada d’una de les versions vigents del producte i migració de subscripcions. Caldrà seleccionar el catàleg sobre el qual es desitja reemplaçar, indicar la versió actual del producte (CURRENT_PRODUCT_VERSION) i la nova versió del producte (NEW_PRODUCT_VERSION). Per exemple: 1.1.0.
- RETIRE: retirada d’una versió del producte sense deixar cap versió vigent (les subscripcions es perden). Caldrà seleccionar el catàleg sobre el qual es desitja retirar i indicar la versió del producte (CURRENT_PRODUCT_VERSION). Per exemple: 1.1.0.
- SUPERSEDE: deprecació d’una de les versions vigents del producte i marcat de subscripcions “migrated”. Caldrà seleccionar el catàleg sobre el qual es desitja fer el supersede, indicar la versió actual del producte (CURRENT_PRODUCT_VERSION) i la nova versió del producte (NEW_PRODUCT_VERSION). Per exemple: 1.1.0.
En el següent enllaç, es pot revisar la definició de workflows per a totes les tecnologies incloent API’s: Workflows Reutilitzables.
Desplegaments per a tecnologies no suportades “custom” de contenidors, funcions i contingut estàtic
S’ha decidit desenvolupar un model de CI/CD per a contenidors, funcions i contingut estàtic més flexible per a les tecnologies que no estan suportades o estan fora de la fulla de ruta de la plataforma. Aquest model es basa en la definició, mitjançant paràmetres passats als workflows, de comandes personalitzades per obtenir la versió i el nom del projecte del fitxer descriptor on s’emmagatzemen aquestes metadades. Gràcies a l’ús d’aquestes comandes, i l’ús de comandes personalitzades per a la compilació, instal·lació de dependències o empaquetat, es pot adaptar el model de CI/CD a qualsevol tecnologia, podent ser aprofitats per realitzar instal·lacions d’eines o llibreries específiques de cada tecnologia prèviament a la compilació, execució dels tests o la generació d’artefactes. A continuació s’explica al detall el funcionament d’aquest model:
S’ha afegit un nou valor possible per a la tecnologia denominat “custom”. Aquest valor requereix comandes personalitzades per obtenir la versió i el nom del projecte del descriptor. Aquestes comandes es passen com a paràmetres als workflows de CI/CD. Les comandes s’utilitzen en el pas de set-project-vars, que és l’encarregat d’obtenir els valors de la versió i el nom del projecte.
#####################################################################################
# Specify both parameters if technology is custom. Comment in any other case #
# The parameters are used to get the project name and version from descriptor files #
#####################################################################################
# get_project_name_command: "jq '.name' composer.json"
# get_version_command: "jq '.version' composer.json"
La comanda “get_version_command” s’utilitzarà per extreure la versió del fitxer de configuració o descriptor del projecte, on es troben les metadades del projecte. Per exemple, es pot utilitzar jq -r ‘.version’ per extreure la versió del fitxer composer.json per al cas de PHP.
Quan la tecnologia sigui “custom”, es realitzarà el CI on PR també. Això assegura que el model de CI es mantingui igual que per a altres tecnologies suportades.
S’ha implementat una comanda similar denominada “get_project_name_command”, per obtenir el nom del projecte del descriptor. Per exemple, es pot utilitzar jq -r ‘.name’ per extreure el nom del fitxer composer.json per al cas de PHP.
En els workflows de CD de contenidors, funcions i estàtics, s’ha eliminat el paràmetre “get_version_command”, ja que no s’utilitza en aquests workflows. En el seu lloc, s’utilitza l’artifact_version passat per paràmetre en el formulari.
Per a més detalls sobre la configuració dels workflows i els paràmetres necessaris per a la tecnologia “custom”, es pot consultar la secció Configuració workflows.
Requisits
Addicionalment, dins la política de versions implantada, es detallen els requisits necessaris de configuració, depenent de la tecnologia. Respecte al versionat de l’ artefacte, el nom del lliurable i la seva version s’ obté automàticament dels fitxers de configuració del projecte. Aquest dependrà del tipus de tecnologia.
JAVA (Maven)
El nom del projecte i els artefactes que es generin i es vagin a pujar a GitHub Packages, han d’utilitzar únicament lletres minúscules i guions o guions baixos per separar paraules.
-
Versionat
- Fitxer : pom.xml
- Nom Lliurable : Tag artifactid
- Versió Lliurable : Tag version
-
Requisists Per a projectes Maven cal definir en el
pom.xml
la següent dependència per fer l’escaneig amb SonarQube:<plugin> <groupId>org.sonarsource.scanner.maven</groupId> <artifactId>sonar-maven-plugin</artifactId> <version>3.4.0.905</version> </plugin>
JAVA (Gradle)
El nom del projecte i els artefactes que es generin i es vagin a pujar a GitHub Packages, han d’utilitzar únicament lletres minúscules i guions o guions baixos per separar paraules.
-
Versionat
- Fitxer / Nom Lliurable : settings.gradle / Camp - rootProject.name
- Fitxer / Versió Lliurable : build.gradle / Camp - version i Camp - group
-
Requisits Per a projectes Maven cal definir en el
build.gradle
la següent dependència per fer l’escaneig amb SonarQube:plugins { id 'org.sonarqube' version '5.1.0.4882' }
I per publicar una biblioteca java:
plugins { id 'java-library' id 'maven-publish' }
I per publicar una biblioteca android:
- A nivell del mòdul de biblioteca i de l’arrel (build.gradle)
plugins { id 'com.android.library' id 'maven-publish' }
- A nivell del mòdul de biblioteca (build.gradle)
afterEvaluate { publishing { publications { uploadArchives(MavenPublication) { from components.findByName('release') artifactId = '<artifactId>' groupId = '<groupId>' } } } }
NODE
- Versionat
- Fitxer : package.json
- Nom Lliurable : name
- Versió Lliurable : version
.NET
-
Versionat En aquest cas hi ha dues casuistiques :
-
Nom Lliurable :
- Si només hi ha un unic projecte, només hi ha un .csproj i s’obtindra del camp name d’aquest fitxer.
- Si tenim en el repo més d’un projecte, hi ha diferents .csproj, s’obté de la variable Project_Name el valor del qual s’introdueix en el setup del projecte.
-
Versió Lliurable :
- Si només hi ha un unic projecte, només hi ha un .csproj i s’obtindra del camp version d’aquest fitxer
- Si tenim en el repo més d’un projecte, hi ha diferents .csproj, després hi hauria d’haver un fitxer centralitzat de versions anomenat Directory.Build.props i d’aquí s’obtindre del camp VERSION.
-
-
Requisits Per a projectes on la tecnologia sigui dotnet és necessària l’existència de l’arxiu
*.csproj
a l’arrel. Si existeixen dos arxius*.csproj
serà obligatori especificar elProject_Name
.
APIM
-
Versionat
- Fitxer : product.yaml
- Nom Lliurable : title
- Versió Lliurable : version
-
Requisits Els fitxers de producte i d’APIs han d’estar a l’arrel del repositori i no poden incloure la versió en el nom.
PYTHON
-
Versionat
- Fitxer : setup.py
- Nom Lliurable : name
- Versió Lliurable : version
-
Requisits Per a projectes Python és necessari que a l’arrel del repositori existeixin els fitxers de configuració
setup.py
irequirements.txt
.
Android (Gradle):
-
Versionat
- Fitxer / Nom Lliurable : app/build.gradle / Task - packageName
- Fitxer / Versió Lliurable : app/build.gradle / Task - versionName
- Fitxer / Build Lliurable : app/build.gradle / Task - versionCode
Exemple de codi:
tasks.register("versionCode"){ println(project.android.defaultConfig.versionCode) } tasks.register("versionName"){ println(project.android.defaultConfig.versionName) } tasks.register("packageName"){ def variant = android.applicationVariants.find { it.name == "${flavorName}${buildType.capitalize()}" } if (variant != null) { println "${variant.applicationId}" } else { println "" } }
iOS
- Fitxer / Nom Lliurable : Build Settings / Camp - PRODUCT_BUNDLE_IDENTIFIER
- Fitxer / Versió Lliurable : Build Settings / Camp - MARKETING_VERSION
- Fitxer / Build Lliurable : Build Settings / Camp - CURRENT_PROJECT_VERSION
Databricks
-
Versionat
- Fitxer / Nom Lliurable : databricks.yml / Camp - bundle.name
- Fitxer / Versió Lliurable : __init__.py / Camp - __version__
Si es vol ubicar en un altre lloc del projecte el nom del projecte o la versió, es poden obtenir a través d’aquests inputs amb comandes personalitzades: get_project_name_command i get_version_command.
Per defecte, el nom del projecte ha d’estar en el fitxer “databricks.yml” en la raiz, en el cmapo “bundle.name”. A més, la versió s’emmagatzema per defecte en el directori “src/project_name/__init__.py”. Si es vol situar en un altre lloc del projecte el nom del projecte o la versió, es poden obtenir a través d’aquests inputs amb comandos personalitzats: get_project_name_command i get_version_command.
Els noms dels “bundle target” deuran obligatòriament dir-se com “dev” (si existís), “pre” i “pro”.
-
Requisits
- Els workflows de CI on PR i CD han de córrer en un self-hosted runner.
Datafactory
-
Versionat El versionat en aquest cas es fa mitjançant un timestamp per obtenir la versió, i el project_name s’informa en els workflows que el criden.
-
Requisits És responsabilitat dels desenvolupadors mantenir aquest fitxer de variables que s’utilitzaran per a la construcció d’artefactes i es faran servir per al desplegament. Aquestes variables sobreescriuran els valors dels paràmetres del fitxer
ARMTemplateParametersForFactory.json
.Existirà una carpeta/env
a la carpeta arrel del projecte, amb una subcarpeta per a cada entorn (dev, pre i pro), i cadascuna tindrà un fitxer anomenatdatafactory.parameters
. Aquest fitxer tindrà un format clau-valor. Aquí tens un exemple:factoryName=<adf-name>
Desplegaments estesos
El model de GHEC està enfocat a noves aplicacions o migració d’aplicacions cap a arquitectures cloud-native desplegades a Cloud Públic, però també s’ha volgut donar cabuda a aplicacions amb tecnologies menys estratègiques dins del CTTI com puguin ser clusters de Kubernetes o màquines virtuals. També els desplegaments de canvis en bases de dades poden fer ús d’aquest model de desplegament ja sigui utilitzant frameworks com Liquibase, o bé executant directament scripts mitjançant les CLIs de PostgreSQL, MySQL o altres motors de bases de dades.
Les tecnlogies certificades actualment són les següents:
-
Desplegaments a AWS de:
- Scripts BBDD
- Kubernetes amb Helm Kubectl
- Màquines Virtuals (En roadmap)
-
Desplegaments a Azure de:
- Scripts BBDD
- Kubernetes amb Helm Kubectl
- Màquines Virtuals (En roadmap)
Per a desplegaments estesos seran necessaris certs recursos com a prerequisits al núvol, depenent del mateix, perquè funcioni correctament el model com es pot observar en Desplegaments Estesos. Aquests són tant recursos d’infraestructura com permisos necessaris perquè la lambda pugui accedir als recursos necessaris.
AWS
Per al desplegament de descriptors en AWS es requereix dels següents recursos d’infraestructura:
- Elastic Container Registry (ECR): Per a emmagatzemar les imatges de contenidors que es generin a partir dels Dockerfiles.
- Lambda basada en contenidors: Per a executar el contenidor que es generi a partir de la imatge pujada a ECR. Aquesta lambda serà una funció basada en contenidor (no en codi).
- Bucket S3: Per a emmagatzemar els descriptors (Helm Charts, manifestos, scripts de bases de dades, etc.) que es vulguin desplegar.
- Secrets Manager: Per a emmagatzemar les credencials d’accés als recursos que es vulguin modificar (clúster de kubernetes, base de dades, etc.).
- IAM Role: Per a donar permisos a la lambda perquè pugui accedir als recursos necessaris, tant per a descarregar els descriptors del bucket, com per a obtenir les credencials del Secrets Manager. A més, s’hauran de donar permisos a la lambda perquè pugui fer la connexió i el desplegament dels descriptors en els recursos.
- Endpoint gateway: Per a que la lambda pugui accedir als recursos de la VPC (S3).
Permisos requerits:
- ECR (Elastic Container Registry):
- ecr:CreateRepository
- ecr:PutImage
- ecr:GetDownloadUrlForLayer
- ecr:BatchCheckLayerAvailability
- ecr:CompleteLayerUpload
- ecr:InitiateLayerUpload
- ecr:UploadLayerPart
- Lambda:
- lambda:UpdateFunctionCode
- lambda:CreateFunction
- lambda:UpdateFunctionConfiguration
Exemple de codi terraform
resource "aws_iam_role" "lambda_role" {
name = "lambda_execution_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
resource "aws_iam_policy" "lambda_policy" {
name = "lambda_policy"
description = "IAM policy for Lambda to access Secrets Manager, S3, and DynamoDB"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"secretsmanager:GetSecretValue"
]
Resource = "arn:aws:secretsmanager:eu-south-2:123456789012㊙️your-secret-name"
},
{
Effect = "Allow"
Action = [
"s3:GetObject"
]
Resource = "arn:aws:s3:::my-bucket/*"
},
{
Effect = "Allow"
Action = [
"dynamodb:PutItem"
]
Resource = "arn:aws:dynamodb:eu-south-2:123456789012:table/my-table"
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" {
role = aws_iam_role.lambda_role.name
policy_arn = aws_iam_policy.lambda_policy.arn
}
resource "aws_lambda_function" "my_lambda" {
function_name = "my_lambda_function"
role = aws_iam_role.lambda_role.arn
handler = "lambda_function.handler"
runtime = "python3.8"
filename = "path/to/your/lambda_function.zip"
environment {
variables = {
SECRET_NAME = "your-secret-name"
}
}
}
resource "aws_iam_role" "lambda_role" {
name = "lambda_execution_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
resource "aws_iam_policy" "lambda_policy" {
name = "lambda_policy"
description = "IAM policy for Lambda to access ECR and update Lambda function"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"ecr:CreateRepository",
"ecr:PutImage",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"lambda:UpdateFunctionCode",
"lambda:CreateFunction",
"lambda:UpdateFunctionConfiguration"
]
Resource = "arn:aws:lambda:us-west-2:123456789012:function:your-lambda-function-name"
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" {
role = aws_iam_role.lambda_role.name
policy_arn = aws_iam_policy.lambda_policy.arn
}
resource "aws_lambda_function" "my_lambda" {
function_name = "my_lambda_function"
role = aws_iam_role.lambda_role.arn
handler = "lambda_function.handler"
runtime = "python3.8"
filename = "path/to/your/lambda_function.zip"
environment {
variables = {
ECR_REPOSITORY = "your-ecr-repository"
}
}
}
Azure
Per al desplegament de descriptors en Azure es requereix dels següents recursos d’infraestructura:
- Azure Container Registry (ACR): Per a emmagatzemar les imatges de contenidors que es generin a partir dels Dockerfiles.
- Storage Account i Blob Storage: Per a emmagatzemar els descriptors (Helm Charts, manifestos, scripts de bases de dades, etc.) que es vulguin desplegar.
- KeyVault: Per a emmagatzemar les credencials d’accés als recursos que es vulguin modificar (clúster de kubernetes, base de dades, etc.).