diff --git a/operator-guide/container-registry-harbor-integration-tekton-ci/index.html b/operator-guide/container-registry-harbor-integration-tekton-ci/index.html index 5aeb656c7..881ef60b6 100644 --- a/operator-guide/container-registry-harbor-integration-tekton-ci/index.html +++ b/operator-guide/container-registry-harbor-integration-tekton-ci/index.html @@ -6,7 +6,7 @@ namespace: edp labels: app.edp.epam.com/secret-type: registry - app.edp.epam.com/integration-secret: true + app.edp.epam.com/integration-secret: "true" type: kubernetes.io/dockerconfigjson stringData: .dockerconfigjson: | @@ -36,7 +36,7 @@ namespace: edp labels: app.edp.epam.com/secret-type: registry - app.edp.epam.com/integration-secret: true + app.edp.epam.com/integration-secret: "true" type: kubernetes.io/dockerconfigjson stringData: .dockerconfigjson: | diff --git a/operator-guide/dependency-track/index.html b/operator-guide/dependency-track/index.html index edea038cd..7d4e6ed96 100644 --- a/operator-guide/dependency-track/index.html +++ b/operator-guide/dependency-track/index.html @@ -8,7 +8,7 @@ namespace: <edp> labels: app.edp.epam.com/secret-type: dependency-track - app.edp.epam.com/integration-secret: true + app.edp.epam.com/integration-secret: "true" stringData: token: <dependency-track-token> url: <dependency-track-api-url> diff --git a/operator-guide/install-defectdojo/index.html b/operator-guide/install-defectdojo/index.html index 352094f00..3589b83bd 100644 --- a/operator-guide/install-defectdojo/index.html +++ b/operator-guide/install-defectdojo/index.html @@ -114,7 +114,7 @@ namespace: edp labels: app.edp.epam.com/secret-type: defectdojo - app.edp.epam.com/integration-secret: true + app.edp.epam.com/integration-secret: "true" stringData: url: https://defectdojo.example.com token: <token> diff --git a/operator-guide/nexus-sonatype/index.html b/operator-guide/nexus-sonatype/index.html index 7ff8ae67c..f6013a910 100644 --- a/operator-guide/nexus-sonatype/index.html +++ b/operator-guide/nexus-sonatype/index.html @@ -5,7 +5,7 @@ namespace: edp labels: app.edp.epam.com/secret-type: nexus - app.edp.epam.com/integration-secret: true + app.edp.epam.com/integration-secret: "true" type: Opaque stringData: url: https://nexus.example.com diff --git a/operator-guide/sonarqube/index.html b/operator-guide/sonarqube/index.html index 4a079b4d7..ed44d8d27 100644 --- a/operator-guide/sonarqube/index.html +++ b/operator-guide/sonarqube/index.html @@ -5,7 +5,7 @@ namespace: edp labels: app.edp.epam.com/secret-type: sonar - app.edp.epam.com/integration-secret: true + app.edp.epam.com/integration-secret: "true" type: Opaque stringData: url: https://sonarqube.example.com diff --git a/search/search_index.json b/search/search_index.json index 4d560a5a4..1ee0d792c 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#welcome-to-the-epam-delivery-platform","title":"Welcome to the EPAM Delivery Platform","text":""},{"location":"faq/","title":"FAQ","text":""},{"location":"faq/#faq","title":"FAQ","text":""},{"location":"faq/#how-do-i-set-parallel-reconciliation-for-a-number-of-codebase-branches","title":"How Do I Set Parallel Reconciliation for a Number of Codebase Branches?","text":"
Set the CODEBASE_BRANCH_MAX_CONCURRENT_RECONCILES Env variable in codebase-operator by updating Deployment template. For example:
...\n env:\n - name: WATCH_NAMESPACE\n ...\n\n - name: CODEBASE_BRANCH_MAX_CONCURRENT_RECONCILES\n value: 10\n ...\n
It's not recommended to set the value above 10.
"},{"location":"faq/#how-to-change-the-lifespan-of-an-access-token-that-is-used-for-edp-portal-and-oidc-login-plugin","title":"How To Change the Lifespan of an Access Token That Is Used for EDP Portal and 'oidc-login' Plugin?","text":"Change the Access Token Lifespan: go to your Keycloak and select Openshift realm > Realm settings > Tokens > Access Token Lifespan > set a new value to the field and save this change.
By default, \"Access Token Lifespan\" value is 5 minutes.
Access Token Lifespan
"},{"location":"features/","title":"Basic Concepts","text":""},{"location":"features/#basic-concepts","title":"Basic Concepts","text":"Consult EDP Glossary section for definitions mentioned on this page and EDP Toolset to have a full list of tools used with the Platform. The below table contains a full list of features provided by EDP.
Features Description Cloud Agnostic EDP runs on Kubernetes cluster, so any Public Cloud Provider which provides Kubernetes can be used. Kubernetes clusters deployed on-premises work as well CI/CD for Microservices EDP is initially designed to support CI/CD for Microservices running as containerized applications inside Kubernetes Cluster. EDP also supports CI for:- Terraform Modules, - Open Policy Rules,- Workflows for Java (8,11,17), JavaScript (React, Vue, Angular, Express, Antora), C# (.NET 6.0), Python (FastAPI, Flask, 3.8), Go (Beego, Operator SDK) Version Control System (VCS) EDP installs Gerrit as a default Source Code Management (SCM) tool. EDP also supports GitHub and GitLab integration Branching Strategy EDP supports Trunk-based development as well as GitHub/GitLab flow. EDP creates two Pipelines per each codebase branch (see Pipeline Framework): Code Review and Build Repository Structure EDP provides separate Git repository per each Codebase and doesn't work with Monorepo. However, EDP does support customization and runs helm-lint, dockerfile-lint steps using Monorepo approach. Artifacts Versioning EDP supports two approaches for Artifacts versioning: - default (BRANCH-[TECH_STACK_VERSION]-BUILD_ID)- EDP (MAJOR.MINOR.PATCH-BUILD_ID), which is SemVer.Custom versioning can be created by implementing get-version stage Application Library EDP provides baseline codebase templates for Microservices, Libraries, within create strategy while onboarding new Codebase Stages Library Each EDP Pipeline consists of pre-defined steps (stages). Consult library documentation for more details CI Pipelines EDP provides CI Pipelines for first-class citizens: - Applications (Microservices) based on Java (8,11,17), JavaScript (React, Vue, Angular, Express, Antora, Next.js), C# (.NET 3.1, .NET 6.0), Python (FastAPI, Flask, 3.8), Go (Beego, Gin, Operator SDK), Helm (Charts, Pipeline)- Libraries based on Java (8,11,17), JavaScript (React, Vue, Angular, Express), Python (FastAPI, Flask, 3.8), Groovy Pipeline (Codenarc), HCL (Terraform), Rego (OPA), Container (Docker), Helm (Charts, Pipeline), C#(.NET 3.1, .NET 6.0) - Autotests based on Java8, Java11, Java17 CD Pipelines EDP provides capabilities to design CD Pipelines (in EDP Portal UI) for Microservices and defines logic for artifacts flow (promotion) from env to env. Artifacts promotion is performed automatically (Autotests), manually (User Approval) or combining both approaches Autotests EDP provides CI pipeline for autotest implemented in Java. Autotests can be used as Quality Gates in CD Pipelines Custom Pipeline Library EDP can be extended by introducing Custom Pipeline Library Dynamic Environments Each EDP CD Pipeline creates/destroys environment upon user requests"},{"location":"getting-started/","title":"Quick Start","text":""},{"location":"getting-started/#quick-start","title":"Quick Start","text":""},{"location":"getting-started/#software-requirements","title":"Software Requirements","text":"The system should have the following specifications to run properly:
EPAM Delivery Platform supports the following tools:
Domain Related Tools/Solutions Artifacts Management Nexus Repository, Jfrog Artifactory AWS IRSA, AWS ECR, AWS EFS, Parameter Store, S3, ALB/NLB, Route53 Build .NET, Go, Apache Gradle, Apache Maven, NPM Cluster Backup Velero Code Review Gerrit, GitLab, GitHub Container Registry AWS ECR, OpenShift Registry, Harbor, DockerHub Containers Hadolint, Kaniko, Crane Documentation as Code MkDocs, Antora (AsciiDoc) Infrastructure as Code Terraform, TFLint, Terraform Docs, Crossplane, AWS Controllers for Kubernetes Kubernetes Deployment Kubectl, Helm, Helm Docs, Chart Testing, Argo CD, Argo Rollout Kubernetes Multitenancy Kiosk, Capsule Logging OpenSearch, EFK, ELK, Loki, Splunk Monitoring Prometheus, Grafana, VictoriaMetrics Pipeline Orchestration Tekton Policies/Rules Open Policy Agent Secrets Management External Secret Operator, Vault, AWS Parameter Store Secure Development SonarQube, DefectDojo, Dependency Track, Semgrep, Grype, Trivy, Clair, GitLeaks, CycloneDX Generator, tfsec, checkov SSO Keycloak, oauth2-proxy Test Report Tool ReportPortal, Allure Tracing OpenTelemetry, Jaeger"},{"location":"getting-started/#install-edp","title":"Install EDP","text":"To install EDP with the necessary parameters, please refer to the Install EDP section of the Operator Guide. Mind the parameters in the EDP installation chart. For details, please refer to the values.yaml.
Find below the example of the installation command:
helm install edp epamedp/edp-install --wait --timeout=900s \\\n --set global.dnsWildCard=<cluster_DNS_wildcard> \\\n --set global.platform=<platform_type> \\\n --set awsRegion=<region> \\\n --namespace edp\n
Warning
Please be aware that the command above is an example.
"},{"location":"getting-started/#related-articles","title":"Related Articles","text":"Getting Started
"},{"location":"glossary/","title":"Glossary","text":""},{"location":"glossary/#glossary","title":"Glossary","text":"Get familiar with the definitions and context for the most useful EDP terms presented in table below.
Terms Details EDP Component - an item used in CI/CD process EDP Portal UI - an EDP component that helps to manage, set up, and control the business entities. Artifactory - an EDP component that stores all the binary artifacts. NOTE: Nexus is used as a possible implementation of a repository. CI/CD Server - an EDP component that launches pipelines that perform the build, QA, and deployment code logic. NOTE: Tekton is used as a possible implementation of a CI/CD server. Code Review tool - an EDP component that collaborates with the changes in the codebase. NOTE: Gerrit is used as a possible implementation of a code review tool. Identity Server - an authentication server providing a common way to verify requests to all of the applications. NOTE: Keycloak is used as a possible implementation of an identity server. Security Realm Tenant - a realm in identity server (e.g Keycloak) where all users' accounts and their access permissions are managed. The realm is unique for the identity server instance. Static Code Analyzer - an EDP component that inspects continuously a code quality before the necessary changes appear in a master branch. NOTE: SonarQube is used as a possible implementation of a static code analyzer. VCS (Version Control System) - a replication of the Gerrit repository that displays all the changes made by developers. NOTE: GitHub and GitLab are used as the possible implementation of a repository with the version control system. EDP Business Entity - a part of the CI/CD process (the integration, delivery, and deployment of any codebase changes) Application - a codebase type that is built as the binary artifact and deployable unit with the code that is stored in VCS. As a result, the application becomes a container and can be deployed in an environment. Autotests - a codebase type that inspects a product (e.g. an application set) on a stage. Autotests are not deployed to any container and launched from the respective code stage. CD Pipeline (Continuous Delivery Pipeline) - an EDP business entity that describes the whole delivery process of the selected application set via the respective stages. The main idea of the CD pipeline is to promote the application version between the stages by applying the sequential verification (i.e. the second stage will be available if the verification on the first stage is successfully completed). NOTE: The CD pipeline can include the essential set of applications with its specific stages as well. CD Pipeline Stage - an EDP business entity that is presented as the logical gate required for the application set inspection. Every stage has one OpenShift project where the selected application set is deployed. All stages are sequential and promote applications one-by-one. Codebase - an EDP business entity that possesses a code. Codebase Branch - an EDP business entity that represents a specific version in a Git branch. Every codebase branch has a Codebase Docker Stream entity. Codebase Docker Stream - a deployable component that leads to the application build and displays that the last build was verified on the specific stage. Every CD pipeline stage accepts a set of Codebase Docker Streams (CDS) that are input and output. SAMPLE: if an application1 has a master branch, the input CDS will be named as [app name]-[pipeline name]-[stage name]-[master] and the output after the passing of the DEV stage will be as follows: [app name]-[pipeline name]-[stage name]-[dev]-[verified]. Git Server - a custom resource that is responsible for integration with Version Control System (VCS), whether it is GitHub, GitLab or Gerrit. Infrastructure - a codebase type that is used to define and manage the underlying infrastructure of projects using the Infrastructure as Code (IaC) approach, ensuring consistency and reproducibility. Library - a codebase type that is built as the binary artifact, i.e. it`s stored in the Artifactory and can be uploaded by other applications, autotests or libraries. Quality Gate - an EDP business entity that represents the minimum acceptable results after the testing. Every stage has a quality gate that should be passed to promote the application. The stage quality gate can be a manual approve from a QA specialist OR a successful autotest launch. Quality Gate Type - this value defines trigger type that promotes artifacts (images) to the next environment in CD Pipeline. There are manual and automatic types of quality gates. The manual type means that the promoting process should be confirmed in Tekton. The automatic type promotes the images automatically in case there are no errors in the Allure Report. NOTE: If any of the test types is not passed, the CD pipeline will fail. Trigger Type - a value that defines a trigger type used for the CD pipeline triggering. There are manual and automatic types of triggering. The manual type means that the CD pipeline should be triggered manually. The automatic type triggers the CD pipeline automatically as soon as the Codebase Docker Stream was changed. Automated Tests - different types of automated tests that can be run on the environment for a specific stage. Build Pipeline - a Tekton pipeline that builds a corresponding codebase branch in the Codebase. Build Stage - a stage that takes place after the code has been submitted/merged to the repository of the main branch (the pull request from the feature branch is merged to the main one, the Patch set is submitted in Gerrit). Code Review Pipeline - a Tekton pipeline that inspects the code candidate in the Code Review tool. Code Review Stage - a stage where code is reviewed before it goes to the main branch repository of the version control system (the commit to the feature branch is pushed, the Patch set is created in Gerrit). Deploy Pipeline - a Tekton pipeline that is responsible for the CD Pipeline Stage deployment with the full set of applications and autotests. Deployment Stage - a part of the Continuous Delivery where artifacts are being deployed to environments. EDP CI Pipelines - an orchestrator for stages that is responsible for the common technical events, e.g. initialization, in Tekton pipeline. Environment - a part of the stage where the built and packed into an image application are deployed for further testing. It`s possible to deploy several applications to several environments (Team and Integration environments) within one stage. Team Environment - an environment type that can be deployed at any time by the manual trigger of the Deploy pipeline where team or developers can check out their applications. NOTE: The promotion from such kind of environment is prohibited and developed only for the local testing. OpenShift / Kubernetes (K8S) ConfigMap - a resource that stores configuration data and processes the strings that do not contain sensitive information. Docker Container - is a lightweight, standalone, and executable package. Docker Registry - a store for the Docker Container that is created for the application after the Build pipeline performance. OpenShift Web Console - a web console that enables to view, manage, and change OpenShift / K8S resources using browser. Operator Framework - a deployable unit in OpenShift that is responsible for one or a set of resources and performs its life circle (adding, displaying, and provisioning). Path - a route component that helps to find a specified path (e.g. /api) at once and skip the other. Pod - the smallest deployable unit of the large microservice application that is responsible for the application launch. The pod is presented as the one launched Docker container. When the Docker container is collected, it will be kept in Docker Registry and then saved as Pod in the OpenShift project. NOTE: The Deployment Config is responsible for the Pod push, restart, and stop processes. PV (Persistent Volume) - a cluster resource that captures the details of the storage implementation and has an independent lifecycle of any individual pod. PVC (Persistent Volume Claim) - a user request for storage that can request specific size and access mode. PV resources are consumed by PVCs. Route - a resource in OpenShift that allows getting the external access to the pushed application. Secret - an object that stores and manages all the sensitive information (e.g. passwords, tokens, and SSH keys). Service - an external connection point with Pod that is responsible for the network. A specific Service is connected to a specific Pod using labels and redirects all the requests to Pod as well. Site - a route component (link name) that is created from the indicated application name and applies automatically the project name and a wildcard DNS record."},{"location":"overview/","title":"Overview","text":""},{"location":"overview/#overview","title":"Overview","text":"EPAM Delivery Platform (EDP) is an open-source cloud-agnostic SaaS/PaaS solution for software development, licensed under Apache License 2.0. It provides a pre-defined set of CI/CD patterns and tools, which allow a user to start product development quickly with established code review, release, versioning, branching, build processes. These processes include static code analysis, security checks, linters, validators, dynamic feature environments provisioning. EDP consolidates the top Open-Source CI/CD tools by running them on Kubernetes/OpenShift, which enables web/app development either in isolated (on-prem) or cloud environments.
EPAM Delivery Platform, which is also called \"The Rocket\", is a platform that allows shortening the time that is passed before an active development can be started from several months to several hours.
EDP consists of the following:
CI pipelines
Language Framework Build Tool Application Library Autotest Java Java 8, Java 11, Java 17 Gradle, Maven Python Python 3.8, FastAPI, Flask Python C# .Net 3.1, .Net 6.0 .Net Go Beego, Gin, Operator SDK Go JavaScript React, Vue, Angular, Express, Next.js, Antora NPM HCL Terraform Terraform Helm Helm, Pipeline Helm Groovy Codenarc Codenarc Rego OPA OPA Container Docker KanikoEPAM Delivery Platform (EDP) is suitable for all aspects of delivery starting from development including the capability to deploy production environment. EDP architecture is represented on a diagram below.
Architecture
EDP consists of four cross-cutting concerns:
On the top of these indicated concerns, EDP adds several blocks that include:
Artifact samples: frontend, backend, mobile, applications, functional and non-functional autotests, workloads for 3rd party components that can be deployed together with applications.
Explore the EDP technology stack diagram
Technology stack
The EDP IaaS layer supports most popular public clouds AWS, Azure and GCP keeping the capability to be deployed on private/hybrid clouds based on OpenStack. EDP containers are based on Docker technology, orchestrated by Kubernetes compatible solutions.
There are two main options for Kubernetes provided by EDP:
There is no limitation to run EDP on vanilla Kubernetes.
"},{"location":"overview/#related-articles","title":"Related Articles","text":"RoadMap consists of three streams:
Goals:
OperatorHub is a defacto leading solution which consolidates Kubernetes Community around Operators. EDP follows the best practices of delivering Operators in a quick and reliable way. We want to improve Deployment and Management experience for our Customers by publishing all EDP operators on this HUB.
Another artifact aggregator which is used by EDP - ArtifactHub, that holds description for both components: stable and under-development.
OperatorHub. Keycloak Operator
EDP Keycloak Operator is now available from OperatorHub both for Upstream (Kubernetes) and OpenShift deployments.
"},{"location":"roadmap/#ii-architecture","title":"II. Architecture","text":"Goals:
Multiple instances of EDP are run in a single Kubernetes cluster. One way to achieve this is to use Multitenancy. Initially, Kiosk was selected as tools that provides this capability. An alternative option that EDP Team took into consideration is Capsule. Another tool which goes far beyond multitenancy is vcluster going a good candidate for e2e testing scenarios where one needs simple lightweight kubernetes cluster in CI pipelines.
EDP Release 3.5.3
The EPAM Delivery Platform (EDP) has added Capsule as a general tenant management solution for Kubernetes. Capsule is an open-source operator that enables you to create and manage multiple tenants on a shared Kubernetes cluster, while ensuring resource isolation, security, and governance.
EDP Release 3.5.3
Vcluster is actively used in EDP for e2e testing purposes.
"},{"location":"roadmap/#microservice-reference-architecture-framework","title":"Microservice Reference Architecture Framework","text":"EDP provides basic Application Templates for a number of technology stacks (Java, .Net, NPM, Python) and Helm is used as a deployment tool. The goal is to extend this library and provide: Application Templates which are built on pre-defined architecture patterns (e.g., Microservice, API Gateway, Circuit Breaker, CQRS, Event Driven) and Deployment Approaches: Canary, Blue/Green. This requires additional tools installation on cluster as well.
"},{"location":"roadmap/#policy-enforcement-for-kubernetes","title":"Policy Enforcement for Kubernetes","text":"Running workload in Kubernetes calls for extra effort from Cluster Administrators to ensure those workloads do follow best practices or specific requirements defined on organization level. Those requirements can be formalized in policies and integrated into: CI Pipelines and Kubernetes Cluster (through Admission Controller approach) - to guarantee proper resource management during development and runtime phases. EDP uses Open Policy Agent (from version 2.8.0), since it supports compliance check for more use-cases: Kubernetes Workloads, Terraform and Java code, HTTP APIs and many others. Kyverno is another option being checked in scope of this activity.
"},{"location":"roadmap/#secrets-management","title":"Secrets Management","text":"EDP should provide secrets management as a part of platform. There are multiple tools providing secrets management capabilities. The aim is to be aligned with GitOps and Operator Pattern approaches so HashiCorp Vault, Banzaicloud Bank Vaults, Bitnami Sealed Secrets are currently used for internal projects and some of them should be made publicly available - as a part of EDP Deployment.
EDP Release 2.12.x
External Secret Operator is a recommended secret management tool for the EDP components.
"},{"location":"roadmap/#release-management","title":"Release Management","text":"Conventional Commits and Conventional Changelog are two approaches to be used as part of release process. Today EDP provides only capabilities to manage Release Branches. This activity should address this gap by formalizing and implementing Release Process as a part of EDP. Topics to be covered: Versioning, Tagging, Artifacts Promotion.
"},{"location":"roadmap/#kubernetes-native-cicd-pipelines","title":"Kubernetes Native CI/CD Pipelines","text":"EDP has deprecated Jenkins in favour of Tekton. Jenkins is no longer available since EDP v3.4.4.
EDP Release 2.12.x
Argo CD is suggested as a solution providing the Continuous Delivery
capabilities.
EDP Release 3.0
Tekton is used as a CI/CD pipelines orchestration tool on the platform. Review edp-tekton GitHub repository that keeps all the logic behind this solution on the EDP (Pipelines, Tasks, TriggerTemplates, Interceptors, etc). Get acquainted with the series of publications on our Medium Page.
"},{"location":"roadmap/#advanced-edp-role-based-model","title":"Advanced EDP Role-based Model","text":"EDP has a number of base roles which are used across EDP. In some cases it is necessary to provide more granular permissions for specific users. It is possible to do this using Kubernetes Native approach.
"},{"location":"roadmap/#notifications-framework","title":"Notifications Framework","text":"EDP has a number of components which need to report their statuses: Build/Code Review/Deploy Pipelines, changes in Environments, updates with artifacts. The goal for this activity is to onboard Kubernetes Native approach which provides Notification capabilities with different sources/channels integration (e.g. Email, Slack, MS Teams). Some of these tools are Argo Events, Botkube.
"},{"location":"roadmap/#reconciler-component-retirement","title":"Reconciler Component Retirement","text":"Persistent layer, which is based on edp-db (PostgreSQL) and reconciler component should be retired in favour of Kubernetes Custom Resource (CR). The latest features in EDP are implemented using CR approach.
EDP Release 3.0
Reconciler component is deprecated and is no longer supported. All the EDP components are migrated to Kubernetes Custom Resources (CR).
"},{"location":"roadmap/#iii-building-blocks","title":"III. Building Blocks","text":"Goals:
EDP Release 2.12.x
SAST is introduced as a mandatory part of the CI Pipelines. The list of currently supported SAST scanners and the instruction on how to add them are also available.
"},{"location":"roadmap/#infrastructure-as-code","title":"Infrastructure as Code","text":"EDP Target tool for Infrastructure as Code (IaC) is Terraform. EDP sees two CI/CD scenarios while working with IaC: Module Development and Live Environment Deployment. Today, EDP provides basic capabilities (CI Pipelines) for Terraform Module Development. At the same time, currently EDP doesn't provide Deployment pipelines for Live Environments and the feature is under development. Terragrunt is an option to use in Live Environment deployment. Another Kubernetes Native approach to provision infrastructure components is Crossplane.
"},{"location":"roadmap/#database-schema-management","title":"Database Schema Management","text":"One of the challenges for Application running in Kubernetes is to manage database schema. There are a number of tools which provides such capabilities, e.g. Liquibase, Flyway. Both tools provide versioning control for database schemas. There are different approaches on how to run migration scripts in Kubernetes: in init container, as separate Job or as a separate CD stage. Purpose of this activity is to provide database schema management solution in Kubernetes as a part of EDP. EDP Team investigates SchemaHero tool and use-cases which suits Kubernetes native approach for database schema migrations.
"},{"location":"roadmap/#open-policy-agent","title":"Open Policy Agent","text":"Open Policy Agent is introduced in version 2.8.0. EDP now supports CI for Rego Language, so you can develop your own policies. The next goal is to provide pipeline steps for running compliance policies check for Terraform, Java, Helm Chart as a part of CI process.
"},{"location":"roadmap/#report-portal","title":"Report Portal","text":"EDP uses Allure Framework as a Test Report tool. Another option is to integrate Report Portal into EDP ecosystem.
EDP Release 3.0
Use ReportPortal to consolidate and analyze your Automation tests results. Consult our pages on how to perform reporting and Keycloak integration.
"},{"location":"roadmap/#carrier","title":"Carrier","text":"Carrier provides Non-functional testing capabilities.
"},{"location":"roadmap/#java-17","title":"Java 17","text":"EDP supports two LTS versions of Java: 8 and 11. The goal is to provide Java 17 (LTS) support.
EDP Release 3.2.1
CI Pipelines for Java 17 is available in EDP.
"},{"location":"roadmap/#velero","title":"Velero","text":"Velero is used as a cluster backup tool and is deployed as a part of Platform. Currently, Multitenancy/On-premise support for backup capabilities is in process.
"},{"location":"roadmap/#istio","title":"Istio","text":"Istio is to be used as a Service Mesh and to address challenges for Microservice or Distributed Architectures.
"},{"location":"roadmap/#kong","title":"Kong","text":"Kong is one of tools which is planned to use as an API Gateway solution provider. Another possible candidate for investigation is Ambassador API Gateway
"},{"location":"roadmap/#openshift-4x","title":"OpenShift 4.X","text":"EDP supports the OpenShift 4.9 platform.
EDP Release 2.12.x
EDP Platform runs on the latest OKD versions: 4.9 and 4.10. Creating the IAM Roles for Service Account is a recommended way to work with AWS Resources from the OKD cluster.
"},{"location":"roadmap/#iv-admin-console-ui","title":"IV. Admin Console (UI)","text":"Goals:
EDP Release 2.12.x
EDP Team has introduced a new UI component called EDP Headlamp, which will replace the EDP Admin Console in future releases. EDP Headlamp is based on the Kinvolk Headlamp UI Client.
EDP Release 3.0
EDP Headlamp is used as a Control Plane UI on the platform.
EDP Release 3.4
Since EDP v3.4.0, Headlamp UI has been renamed to EDP Portal.
"},{"location":"roadmap/#users-management","title":"Users Management","text":"EDP uses Keycloak as an Identity and Access provider. EDP roles/groups are managed inside the Keycloak realm, then these changes are propagated across the EDP Tools. We plan to provide this functionality in EDP Portal using the Kubernetes-native approach (Custom Resources).
"},{"location":"roadmap/#the-delivery-pipelines-dashboard","title":"The Delivery Pipelines Dashboard","text":"The CD Pipeline section in EDP Portal provides basic information, such as environments, artifact versions deployed per each environment, and direct links to the namespaces. One option is to enrich this panel with metrics from the Prometheus, custom resources, or events. Another option is to use the existing dashboards and expose EDP metrics to them, for example, plugin for Lens or OpenShift UI Console.
"},{"location":"roadmap/#split-jira-and-commit-validation-sections","title":"Split Jira and Commit Validation Sections","text":"Commit Validate step was initially designed to be aligned with Jira Integration and cannot be used as single feature. Target state is to ensure features CommitMessage Validation and Jira Integration both can be used independently. We also want to add support for Conventional Commits.
EDP Release 3.2.0
EDP Portal has separate sections for Jira Integration and CommitMessage Validation step.
"},{"location":"roadmap/#v-documentation-as-code","title":"V. Documentation as Code","text":"Goal:
Consolidate documentation in a single repository edp-install, use mkdocs
tool to generate docs and GitHub Pages as a hosting solution.
EPAM Delivery Platform supports only the three last versions. For a stable performance, the EDP team recommends installing the corresponding Kubernetes and OpenShift versions as indicated in the table below.
Get acquainted with the list of the latest releases and component versions on which the platform is tested and verified:
EDP Release Version Release Date EKS Version OpenShift Version 3.6 Nov 03, 2023 1.26 4.12 3.5 Sep 21, 2023 1.26 4.12 3.4 Aug 18, 2023 1.26 4.12 3.3 May 25, 2023 1.26 4.12 3.2 Mar 26, 2023 1.23 4.10 3.1 Jan 24, 2023 1.23 4.10 3.0 Dec 19, 2023 1.23 4.10 2.12 Aug 30, 2023 1.23 4.10"},{"location":"developer-guide/","title":"Overview","text":""},{"location":"developer-guide/#overview","title":"Overview","text":"The EPAM Delivery Platform (EDP) Developer Guide serves as a comprehensive technical resource specifically designed for developers. It offers detailed insights into expanding the functionalities of EDP. This section focuses on explaining the development approach and fundamental architectural blueprints that form the basis of the platform's ecosystem.
Within these pages, you'll find architectural diagrams, component schemas, and deployment strategies essential for grasping the structural elements of EDP. These technical illustrations serve as references, providing a detailed understanding of component interactions and deployment methodologies. Understanding the architecture of EDP and integrating third-party solutions into its established framework enables the creation of efficient, scalable, and customizable solutions within the EPAM Delivery Platform.
"},{"location":"developer-guide/aws-deployment-diagram/","title":"AWS Deployment Diagram","text":""},{"location":"developer-guide/aws-deployment-diagram/#edp-deployment-on-aws","title":"EDP Deployment on AWS","text":"This document describes the EPAM Delivery Platform (EDP) deployment architecture on AWS. It utilizes various AWS services such as Amazon Elastic Kubernetes Service (EKS), Amazon EC2, Amazon Route 53, and others to build and deploy software in a repeatable, automated way.
"},{"location":"developer-guide/aws-deployment-diagram/#overview","title":"Overview","text":"The EDP deployment architecture consists of two AWS accounts: Shared and Explorer. The Shared account hosts shared services, while the Explorer account runs the development team workload and EDP services. Both accounts have an AWS EKS cluster deployed in multiple Availability Zones (AZs). The EKS cluster runs the EDP Services, development team workload, and shared services in the case of the Shared account.
EPAM Delivery Platform Deployment Diagram on AWS
"},{"location":"developer-guide/aws-deployment-diagram/#key-components","title":"Key Components","text":"The EKS cluster is deployed across multiple AZs to ensure high availability and fault tolerance. This allows for automatic failover in case of an AZ outage or instance failure. Autoscaling Groups automatically adjust the number of EC2 instances based on demand, ensuring scalability while maintaining availability.
"},{"location":"developer-guide/aws-deployment-diagram/#design-considerations","title":"Design Considerations","text":""},{"location":"developer-guide/aws-deployment-diagram/#reliability","title":"Reliability","text":"The EPAM Delivery Platform (EDP) deployment architecture on AWS follows best practices and patterns from the Well-Architected Framework. By leveraging AWS services such as EKS, EC2, Route 53, ALB, WAF, ACM, and Parameter Store, the EDP provides a robust and scalable CI/CD system that enables developers to deploy and manage infrastructure and applications quickly. The architecture ensures high availability, fault tolerance, reliability, performance efficiency, security, and cost optimization for the EDP deployment.
"},{"location":"developer-guide/aws-reference-architecture/","title":"AWS Reference Architecture","text":""},{"location":"developer-guide/aws-reference-architecture/#edp-reference-architecture-on-aws","title":"EDP Reference Architecture on AWS","text":"The reference architecture of the EPAM Delivery Platform (EDP) on AWS is designed to provide a robust and scalable CI/CD system for developing and deploying software in a repeatable and automated manner. The architecture leverages AWS Managed Services to enable developers to quickly deploy and manage infrastructure and applications. EDP recommends to follow the best practices and patterns from the Well-Architected Framework, the AWS Architecture Center, and EKS Best Practices Guide.
"},{"location":"developer-guide/aws-reference-architecture/#architecture-details","title":"Architecture Details","text":"The AWS Cloud comprises three accounts: Production, Shared, and Development.
Note
AWS Account management is out of scope for this document.
Each account serves specific purposes:
EPAM Delivery Platform Reference Architecture on AWS
"},{"location":"developer-guide/aws-reference-architecture/#infrastructure-as-code","title":"Infrastructure as Code","text":"Infrastructure as Code (IaC) is a key principle in the EPAM Delivery Platform architecture. Terraform is the IaC tool to provision and manage all services in each account. AWS S3 and AWS DynamoDB serve as the backend for Terraform state, ensuring consistency and reliability in the deployment process. This approach enables the architecture to be version-controlled and allows for easy replication and reproducibility of environments.
"},{"location":"developer-guide/aws-reference-architecture/#docker-registry","title":"Docker Registry","text":"The architecture utilizes AWS Elastic Container Registry (ECR) as a Docker Registry for container image management. ECR offers a secure, scalable, and reliable solution for storing and managing container images. It integrates seamlessly with other AWS services and provides a highly available and durable storage solution for containers in the CI/CD pipeline.
"},{"location":"developer-guide/aws-reference-architecture/#iam-roles-for-service-accounts-irsa","title":"IAM Roles for Service Accounts (IRSA)","text":"The EPAM Delivery Platform implements IAM Roles for Service Accounts (IRSA) to provide secure access to AWS services from Kubernetes Clusters. This feature enables fine-grained access control with individual Kubernetes pods assuming specific IAM roles for authenticated access to AWS resources. IRSA eliminates the need for managing and distributing access keys within the cluster, significantly enhancing security and reducing operational complexity.
"},{"location":"developer-guide/aws-reference-architecture/#ssl-certificates","title":"SSL Certificates","text":"The architecture uses the AWS Certificate Manager (ACM) to secure communication between services to provide SSL certificates. ACM eliminates the need to manually manage SSL/TLS certificates, automating the renewal and deployment process. The EPAM Delivery Platform ensures secure and encrypted traffic within its environment by leveraging ACM.
"},{"location":"developer-guide/aws-reference-architecture/#aws-waf","title":"AWS WAF","text":"The architecture's external Application Load Balancer (ALB) endpoint is protected by the AWS Web Application Firewall (WAF). WAF protects against common web exploits and ensures the security and availability of the applications hosted within the EPAM Delivery Platform. It offers regular rule updates and easy integration with other AWS services.
"},{"location":"developer-guide/aws-reference-architecture/#parameter-store-and-secrets-manager","title":"Parameter Store and Secrets Manager","text":"The architecture leverages the AWS Systems Manager Parameter Store and Secrets Manager to securely store and manage all secrets and parameters utilized within the EKS clusters\u2014parameter Store stores general configuration information, such as database connection strings and API keys. In contrast, Secrets Manager securely stores sensitive information, such as passwords and access tokens. By centralizing secrets management, the architecture ensures proper access control and reduces the risk of unauthorized access.
"},{"location":"developer-guide/aws-reference-architecture/#summary","title":"Summary","text":"The reference architecture of the EPAM Delivery Platform on AWS provides a comprehensive and scalable environment for building and deploying software applications. With a strong focus on automation, security, and best practices, this architecture enables developers to leverage the full potential of AWS services while following industry-standard DevOps practices.
"},{"location":"developer-guide/edp-workflow/","title":"Contribution Guide","text":""},{"location":"developer-guide/edp-workflow/#edp-project-rules-working-process","title":"EDP Project Rules. Working Process","text":"This page contains the details on the project rules and working process for EDP team and contributors. Explore the main points about working with Gerrit, following the main commit flow, as well as the details about commit types and message below.
"},{"location":"developer-guide/edp-workflow/#project-rules","title":"Project Rules","text":"Before starting the development, please check the project rules:
It is highly recommended to become familiar with the Gerrit flow. For details, please refer to the Gerrit official documentation and pay attention to the main points:
a. Voting in Gerrit.
b. Resolution of Merge Conflict.
c. Comments resolution.
d. One Jira task should have one Merge Request (MR). If there are many changes within one MR, add the next patch set to the open MR by selecting the Amend commit check box.
Only the Assignee is responsible for the MR merge and Jira task status.
Every MR should be merged in a timely manner.
Log time to Jira ticket.
With EDP, the main workflow is based on the getting a Jira task and creating a Merge Request according to the rules described below.
Workflow
Get Jira task \u2192 implement, verify by yourself the results \u2192 create Merge Request (MR) \u2192 send for review \u2192 resolve comments/add changes, ask colleagues for the final review \u2192 track the MR merge \u2192 verify by yourself the results \u2192 change the status in the Jira ticket to CODE COMPLETE or RESOLVED \u2192 share necessary links with a QA specialist in the QA Verification channel \u2192 QA specialist closes the Jira task after his verification \u2192 Jira task should be CLOSED.
Commit Flow
Get a task in the Jira/GitHub dashboard. Please be aware of the following points:
JiraGitHuba. Every task has a reporter who can provide more details in case something is not clear.
b. The responsible person for the task and code implementation is the assignee who tracks the following:
c. Pay attention to the task Status that differs in different entities, the workflow will help to see the whole task processing:
View Jira workflow
d. There are several entities that are used on the EDP project: Story, Improvement, Task, Bug.
a. Every task has a reporter who can provide more details in case something is not clear.
b. The responsible person for the task and code implementation is the assignee who tracks the following:
c. If the task is created on your own, make sure it is populated completely. See an example below:
GitHub issue
Implement feature, improvement, fix and check the results on your own. If it is impossible to check the results of your work before the merge, verify all later.
Create a Merge Request, for details, please refer to the Code Review Process.
When committing, use the pattern: commit type: Commit message (#GitHub ticket number).
a. commit type:
feat
: (new feature for the user, not a new feature for build script)
fix
: (bug fix for the user, not a fix to a build script)
docs
: (changes to the documentation)
style
: (formatting, missing semicolons, etc; no production code change)
refactor
: (refactoring production code, eg. renaming a variable)
test
: (adding missing tests, refactoring tests; no production code change)
chore
: (updating grunt tasks etc; no production code change)
!
: (added to other commit types to mark breaking changes) For example:
feat!: Add ingress links column into Applications table on stage page (#77)\n\nBREAKING CHANGE: Ingress links column has been added into the Applications table on the stage details page\n
b. Commit message:
brief, for example:
fix: Remove secretKey duplication from registry secrets (#63)
or
descriptive, for example:
feat: Provide the ability to configure hadolint check (#88)\n\n*Add configuration files .hadolint.yaml and .hadolint.yml to stash\n
Note
It is mandatory to start a commit message from a capital letter.
c. GitHub tickets are typically identified using a number preceded by the # sign and enclosed in parentheses.
Note
Make sure there is a descriptive commit message for a breaking change Merge Request. For example:
feat!: Add ingress links column into Applications table on stage page (#77)
BREAKING CHANGE: Ingress links column has been added into the Applications table on the stage details page
Note
If a Merge Request contains both new functionality and breaking changes, make sure the functionality description is placed before the breaking changes. For example:
feat!: Update Gerrit to improve access
BREAKING CHANGES: Update Gerrit config according to groups
"},{"location":"developer-guide/edp-workflow/#related-articles","title":"Related Articles","text":"This section provides a comprehensive overview of the EDP deployment approach on a Kubernetes cluster. EDP is designed and functions based on a set of key guiding principles:
Loosely Coupling: EDP comprises several loosely coupled operators responsible for different platform parts. These operators can be deployed independently, enabling the most straightforward platform customization and delivery approach.
Kubernetes Operator
The following deployment diagram illustrates the platform's core components, which provide the minimum functional capabilities required for the platform operation: build, push, deploy, and run applications. The platform relies on several mandatory dependencies:
EPAM Delivery Platform Deployment Diagram
Business applications are deployed on the platform using the CD Pipeline Operator and Argo CD. By default, the CD Pipeline Operator uses Argo CD as a deployment tool. However, it can be replaced with any other tool, like FluxCD, Spinnaker, etc. The target environment for the application deployment is a Kubernetes cluster where EDP is deployed, but it can be any other Kubernetes cluster.
"},{"location":"developer-guide/local-development/","title":"Operator Development","text":""},{"location":"developer-guide/local-development/#workspace-setup-manual","title":"Workspace Setup Manual","text":"This page is intended for developers with the aim to share details on how to set up the local environment and start coding in Go language for EPAM Delivery Platform.
"},{"location":"developer-guide/local-development/#prerequisites","title":"Prerequisites","text":"Note
Make sure GOPATH and GOROOT environment variables are added in PATH.
"},{"location":"developer-guide/local-development/#environment-setup","title":"Environment Setup","text":"Set up your environment by following the steps below.
"},{"location":"developer-guide/local-development/#set-up-your-ide","title":"Set Up Your IDE","text":"We recommend using GoLand and enabling the Kubernetes plugin. Before installing plugins, make sure to save your work because IDE may require restarting.
"},{"location":"developer-guide/local-development/#set-up-your-operator","title":"Set Up Your Operator","text":"To set up the cloned operator, follow the three steps below:
Configure Go Build Option. Open folder in GoLand, click the button and select the Go Build
option:
Add configuration
Fill in the variables in Configuration tab:
Files
field, indicate the path to the main.go file;Working directory
field, indicate the path to the operator;Environment field
, specify the namespace to watch by setting WATCH_NAMESPACE
variable. It should equal default
but it can be any other if required by the cluster specifications.Environment field
, also specify the platform type by setting PLATFORM_TYPE
. It should equal either kubernetes
or openshift
.Build config
Check cluster connectivity and variables. Local development implies working within local Kubernetes clusters. Kind (Kubernetes in Docker) is recommended so set this or another environment first before running code.
Before making commit and sending pull request, take care of precautionary measures to avoid crashing some other parts of the code.
"},{"location":"developer-guide/local-development/#testing-and-linting","title":"Testing and Linting","text":"Testing and linting must be used before every single commit with no exceptions. The instructions for the commands below are written here.
It is mandatory to run test and lint to make sure the code passes the tests and meets acceptance criteria. Most operators are covered by tests so just run them by issuing the commands \"make test\" and \"make lint\":
make test\n
The command \"make test\" should give the output similar to the following:
\"make test\" command
make lint\n
The command \"make lint\" should give the output similar to the following:
\"make lint\" command
"},{"location":"developer-guide/local-development/#observe-auto-generated-docs-api-and-manifests","title":"Observe Auto-Generated Docs, API and Manifests","text":"The commands below are especially essential when making changes to API. The code is unsatisfactory if these commands fail.
Generate documentation in the .MD file format so the developer can read it:
make api-docs\n
The command \"make api-docs\" should give the output similar to the following:
\"make api-docs\" command with the file contents
There are also manifests within the operator that generate zz_generated.deepcopy.go file in /api/v1 directory. This file is necessary for the platform to work but it's time-consuming to fill it by yourself so there is a mechanism that does it automatically. Update it using the following command and check if it looks properly:
make generate\n
The command \"make generate\" should give the output similar to the following:
\"make generate\" command
Refresh custom resource definitions for Kubernetes, thus allowing the cluster to know what resources it deals with.
make manifests\n
The command \"make manifests\" should give the output similar to the following:
\"make manifests\" command
At the end of the procedure, you can push your code confidently to your branch and create a pull request.
That's it, you're all set! Good luck in coding!
"},{"location":"developer-guide/local-development/#related-articles","title":"Related Articles","text":"This section defines necessary steps to start developing the EDP documentation in the MkDocs Framework. The framework presents a static site generator with documentation written in Markdown. All the docs are configured with a YAML configuration file.
Note
For more details on the framework, please refer to the MkDocs official website.
There are two options for working with MkDocs:
Please see below the detailed description of each options and choose the one that suits you.
"},{"location":"developer-guide/mk-docs-development/#mkdocs-with-docker","title":"MkDocs With Docker","text":"Prerequisites:
make
utility is installed.To work with MkDocs, take the following steps:
Clone the edp-install repository to your local folder.
Run the following command:
make docs
Enter the localhost:8000 address in the browser and check that documentation pages are available.
Open the file editor, navigate to edp-install->docs and make necessary changes. Check all the changes at localhost:8000.
Create a merge request with changes.
Prerequisites:
To work with MkDocs without Docker, take the following steps:
Clone the edp-install repository to your local folder.
Run the following command:
pip install -r hack/mkdocs/requirements.txt\n
Run the local development command:
mkdocs serve --dev-addr 0.0.0.0:8000\n
Note
This command may not work on Windows, so a quick solution is:
python -m mkdocs serve --dev-addr 0.0.0.0:8000\n
Enter the localhost:8000 address in the browser and check that documentation pages are available.
Open the file editor, navigate to edp-install->docs and make necessary changes. Check all the changes at localhost:8000.
Create a merge request with changes.
The EPAM Delivery Platform\u2019s (EDP) Reference Architecture serves as a blueprint for software delivery, outlining the best practices, tools, and technologies leveraged by the platform to ensure efficient and high-quality software development. It provides a comprehensive guide to navigate the complexities of software delivery, from code to deployment.
EDP operates on Kubernetes, a leading open-source system for automating deployment, scaling, and management of containerized applications. It consolidates a variety of open-source tools, ensuring a flexible and adaptable system that can seamlessly run on any public cloud or on-premises infrastructure. This versatility allows for a wide range of deployment options, catering to diverse business needs and operational requirements.
"},{"location":"developer-guide/reference-architecture/#key-principles","title":"Key Principles","text":"The EPAM Delivery Platform (EDP) is built on a set of key principles that guide its design and functionality:
EDP encompasses a comprehensive CI/CD ecosystem integrating essential tools such as the Tekton and Argo CD, augmented by additional functionalities. Within this robust framework, EDP seamlessly integrates SonarQube for continuous code quality assessment, enabling thorough analysis and ensuring adherence to coding standards. Additionally, incorporating Static Application Security Testing (SAST) toolset fortifies platform's security posture by proactively identifying vulnerabilities within the codebase. EDP leverages dedicated artifact storage solutions to manage and version application artifacts securely, ensuring streamlined deployment processes and traceability throughout the software development lifecycle. See the reference architecture diagram below.
EPAM Delivery Platform Reference Architecture
Developers access the platform by authenticating with their corporate credentials. The platform utilizes OpenID Connect (OIDC) for authentication and authorization across all tools and Kubernetes clusters. Using OIDC, EDP establishes a unified and secure authentication mechanism, ensuring seamless access control and user authentication for all integrated tools. This standardized approach upholds strict security protocols, ensuring consistency in authentication and authorization policies across the platform ecosystem. To integrate existing Identity Providers (IdPs), Keycloak serves as an identity broker on the platform. EDP offers the keycloak-operator to streamline Keycloak integration within the platform.
Developers engage with the platform via the EDP Portal, an intuitive interface offering a comprehensive overview of the platform\u2019s capabilities. This centralized hub facilitates seamless navigation and access to various platform tools and components. Within the EDP Portal, developers can generate new components (codebases). The platform integrates with version control systems, optimizing source code management, fostering collaboration, and streamlining code review processes. To create new codebases, developers utilize Application Templates, ensuring a standardized approach to application development. The platform accommodates a range of application templates such as Java, Node.js, .NET, Python, and more. Additionally, developers can design custom templates via the EDP Marketplace to cater to their specific requirements.
Tekton is a potent, adaptable, and cloud-native framework designed for crafting CI/CD systems. It offers a collection of shared, reusable components that empower developers to construct, test, and deploy applications across various cloud providers or on-premises systems. As a foundational element within the EDP CI/CD ecosystem, Tekton seamlessly integrates with other tools and services, providing a robust and adaptable framework for constructing CI/CD pipelines. Tekton Pipelines allow developers to efficiently build, test, and deploy applications, while Tekton Triggers initiate pipelines based on specific events.
The codebase operator is a crucial part of the platform ecosystem. It manages codebases, their creation, deletion, and scaffolding, as well as their associated resources. It provides versioning, branching, and release capabilities and enables seamless integration with Git servers and Jira.
The platform has various cloud-agnostic tools that offer different functionalities, such as artifact storage, static security analysis, and code quality assessment. These tools are accessible through pipelines and codebase controllers. Additionally, the platform supports integration with managed services from cloud providers to deliver its core functionality\u2014for instance, AWS Parameter Store stores secrets and AWS ECR - container images. AzureDevops Artifacts is an option to store artifacts leveraging Azure Cloud capabilities. SonarCloud, a cloud-based version of SonarQube, can be integrated to conduct static code analysis.
The CD Pipeline Operator oversees CD pipelines and their related resources. It offers a collection of shared, reusable components for constructing CD pipelines. Integrated with Tekton and Argo CD, the CD Pipeline Operator harnesses their capabilities, ensuring a robust and dependable software delivery process. With a Kubernetes API interface, the CD Pipeline Operator facilitates the management of CD pipelines. It enables artifact promotion logic and the triggering of CD pipelines based on specific events, further enhancing the efficiency and adaptability of the software delivery workflow.
Argo CD is a pivotal deployment tool adopted within the platform, embracing the GitOps delivery approach. It serves as the foundation for deploying both operational and business workloads. EDP recommends running a dedicated Argo CD instance to manage operational workloads, employing the Kubernetes add-ons approach for streamlined management.
Production workloads operate in isolation within dedicated Kubernetes clusters to uphold stringent standards and ensure the utmost security and resource allocation. This approach guarantees the highest isolation and operational integrity levels for critical production systems, aligning with industry best practices. EDP strongly recommends utilizing a pull model for production deployment. In this model, production deployment is initiated by the Argo CD instance explicitly deployed for the production environment.
The Platform is meticulously engineered to uphold best practices in workload distribution across various environments, including development, testing (manual/automation), user acceptance (UAT), staging, and production. While lower environments like development and testing may feasibly share clusters for workload efficiency, EDP strongly advocates and enforces the necessity of segregating production workloads into dedicated clusters. This segregation ensures the highest isolation, security, and resource allocation levels for mission-critical production systems, adhering to industry standards and ensuring optimal operational integrity.
EDP harnesses the robust capabilities of Kubernetes in conjunction with a suite of powerful tools tailored for monitoring, logging, and tracing. It integrates the Prometheus stack within ecosystem, leveraging its metrics collection, storage, and querying capabilities to enable comprehensive monitoring of system performance and health. EDP runs OpenSearch for centralized logging, enabling efficient log aggregation, analysis, and management across the platform. Incorporating OpenTelemetry enables standardized and seamless observability data collection, facilitating deep insights into platform behavior and performance. Additionally, it allows for connection with external aggregators and tools that support the OpenTelemetry protocol (OTLP).
Platform and Tools
EDP integrates with GitLab, GitHub, and Gerrit for version control. These systems are foundational components enabling efficient source code management, collaboration, and code review processes.
Platform ensures robust security measures by leveraging OpenID Connect (OIDC) for authentication and authorization across all platform tools and Kubernetes clusters. By employing OIDC, EDP establishes a unified and secure authentication mechanism, enabling seamless access control and user authentication for all tools integrated into the platform. This standardized approach ensures stringent security protocols, maintaining authentication consistency and authorization policies across the platform ecosystem.
"},{"location":"developer-guide/reference-cicd-pipeline/","title":"Reference CI/CD Pipeline","text":""},{"location":"developer-guide/reference-cicd-pipeline/#reference-cicd-pipeline","title":"Reference CI/CD Pipeline","text":"This document provides an in-depth overview of the Continuous Integration and Continuous Delivery (CI/CD) pipeline reference architecture implemented within the EPAM Delivery Platform (EDP). The pipeline is designed to facilitate efficient and automated software deployment across diverse environments, leveraging a suite of tools and methodologies for enhanced reliability, scalability, and security.
"},{"location":"developer-guide/reference-cicd-pipeline/#cicd-pipeline-architecture","title":"CI/CD Pipeline Architecture","text":"The CI/CD pipeline within EDP orchestrates the software delivery process, encompassing several sequential stages to ensure robustness and reliability.
EPAM Delivery Platform Reference CI/CD Pipeline
The CI/CD Pipeline follows a modular and scalable architecture that leverages various tools to ensure the reliability and efficiency of the software delivery process. The architecture can be divided into stages, each responsible for specific tasks. Explore the key components involved in the pipeline and their functionalities.
Source Code: The pipeline starts with the source code, representing the application's codebase. Developers commit their changes to the source code repository, triggering the pipeline.
Validate Commit Message: The commit message validation component checks the format and content of the commit message. It ensures the commit message follows the correct format and includes a valid Tracking Issue key. It helps maintain a standardized commit message format throughout the application development.
Build: The Build component compiles the source code, runs unit tests, and generates the application artifact. It consumes the artifact from the Artifact Repository (Nexus), ensuring consistent and reliable builds.
SAST with SonarQube: The Static Analysis Security Testing (SAST) component utilizes SonarQube to analyze the source code for potential security vulnerabilities, code smells, and quality issues. This step helps identify and address security or code quality issues early in development.
SCA: The Software Composition Analysis (SCA) component performs dependency analysis using cdxgen, Dependency-Track, semgrep, and DefectDojo. It checks for known vulnerabilities or license compliance issues in the application's dependencies. By identifying and resolving these issues, it ensures the security and stability of the software.
Publish: The Publish component publishes the application artifact to the Artifact Repository. It posts Docker images to the Docker Registry and stores binary artifacts in the Nexus Repository. This process ensures that the artifacts are securely stored and easily accessed for future deployments.
Deploy: The Deploy component uses Argo CD or Tekton to deploy applications to target environments in Kubernetes, leveraging Helm charts to ensure seamless deployment. Deploy to Test/Quality Assurance/Performance Environments: The final stages of the pipeline involve deploying the application to different environments for testing and quality assurance purposes. The results of the tests are consolidated and reported to the Report Portal, facilitating efficient test reporting and analysis.
The overall architecture of the CI/CD Pipeline ensures a streamlined and automated software delivery process, from source code to deployment. It provides developers with the necessary tools and processes to ensure their applications' quality, security, and scalability. Furthermore, Tekton Chains enhances supply chain security by signing and generating in-toto metadata that verifies the integrity of artifacts and the CI/CD Pipeline.
Note
The tools mentioned in this document are just examples and can be replaced with other tools that offer similar functionality. For instance, instead of Harbor for the Docker Registry, it is possible to use AWS ECR. Consider using Azure Artefacts or JFrog Artifactory instead of Nexus for the artifact repository. Instead of setting up an self-managed instance of SonarQube, leverage SonarCloud, the cloud-based version of SonarQube, as an alternative. The CI/CD Pipeline architecture is flexible and adaptable, allowing the use of different tools based on specific project requirements and platform preferences.
"},{"location":"operator-guide/","title":"Overview","text":""},{"location":"operator-guide/#overview","title":"Overview","text":"The EDP Operator guide is intended for DevOps and provides information on EDP installation, configuration and customization, as well as the platform support. Inspect the documentation to adjust the EPAM Delivery Platform according to your business needs:
Inspect the main steps to add and update Jenkins agent.
"},{"location":"operator-guide/add-jenkins-agent/#createupdate-jenkins-agent","title":"Create/Update Jenkins Agent","text":"Every Jenkins agent is based on epamedp/edp-jenkins-base-agent. Check DockerHub for the latest version. Use it to create a new agent (or update an old one). See the example with Dockerfile of gradle-java11-agent below:
View: Dockerfile # Copyright 2021 EPAM Systems.\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n # http://www.apache.org/licenses/LICENSE-2.0\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n\n FROM epamedp/edp-jenkins-base-agent:1.0.1\n SHELL [\"/bin/bash\", \"-o\", \"pipefail\", \"-c\"]\n ENV GRADLE_VERSION=7.1 \\\n PATH=$PATH:/opt/gradle/bin\n\n # Install Gradle\n RUN curl -skL -o /tmp/gradle-bin.zip https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip && \\\n mkdir -p /opt/gradle && \\\n unzip -q /tmp/gradle-bin.zip -d /opt/gradle && \\\n ln -sf /opt/gradle/gradle-$GRADLE_VERSION/bin/gradle /usr/local/bin/gradle\n\n RUN yum install java-11-openjdk-devel.x86_64 -y && \\\n rpm -V java-11-openjdk-devel.x86_64 && \\\n yum clean all -y\n\n WORKDIR $HOME/.gradle\n\n RUN chown -R \"1001:0\" \"$HOME\" && \\\n chmod -R \"g+rw\" \"$HOME\"\n\n USER 1001\n
After the Docker agent update/creation, build and load the image into the project registry (e.g. DockerHub, AWS ECR, etc.).
"},{"location":"operator-guide/add-jenkins-agent/#add-jenkins-agent-configuration","title":"Add Jenkins Agent Configuration","text":"To add a new Jenkins agent, take the steps below:
Run the following command. Please be aware that edp
is the name of the EDP tenant.
kubectl edit configmap jenkins-slaves -n edp\n
Note
On an OpenShift cluster, run the oc
command instead of kubectl
one.
Add new agent template. View: ConfigMap jenkins-slaves
data:\n docker-template: |-\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>docker</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>docker</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>IMAGE_NAME:IMAGE_TAG</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n
Note
The name and label properties should be unique(docker in the example above). Insert image name and tag instead of IMAGE_NAME:IMAGE_TAG.
Open Jenkins to ensure that everything is added correctly. Click the Manage Jenkins option, navigate to the Manage Nodes and Clouds->Configure Clouds->Kubernetes->Pod Templates..., and scroll down to find new Jenkins agent Pod Template details...:
Jenkins pod template
As a result, the newly added Jenkins agent will be available in the Advanced Settings block of the Admin Console tool during the codebase creation:
Advanced settings
If your application is integrated with EDP, take the steps below to change an existing agent configuration:
Run the following command. Please be aware that edp
is the name of the EDP tenant.
kubectl edit configmap jenkins-slaves -n edp\n
Note
On an OpenShift cluster, run the oc
command instead of kubectl
one.
Find the agent template in use and change and change the parameters.
Open Jenkins and check the correct addition. Click the Manage Jenkins option, navigate to the Manage Nodes and Clouds->Configure Clouds->Kubernetes->Pod Templates..., and scroll down to Pod Template details... with the necessary data.
This page describes the entity of Cluster Add-Ons for EPAM Delivery Platform, as well as their purpose, benefits and usage.
"},{"location":"operator-guide/add-ons-overview/#what-are-add-ons","title":"What Are Add-Ons","text":"EDP Add-Ons is basically a Kubernetes-based structure that enables users to quickly install additional components for the platform using Argo CD applications.
Add-Ons have been introduced into EDP starting from version 3.4.0. They empower users to seamlessly incorporate the platform with various additional components, such as SonarQube, Nexus, Keycloak, Jira, and more. This eliminates the need for manual installations, as outlined in the Install EDP page.
In a nutshell, Add-Ons represent separate Helm Charts that imply to be installed by one click using the Argo CD tool.
"},{"location":"operator-guide/add-ons-overview/#add-ons-repository-structure","title":"Add-Ons Repository Structure","text":"All the Add-Ons are stored in our public GitHub repository adhering to the GitOps approach. Apart from default Helm and Git files, it contains both custom resources called Applications for Argo CD and application source code. The repository follows the GitOps approach to enable Add-Ons with the capability to rollback changes when needed. The repository structure is the following:
\u251c\u2500\u2500 CHANGELOG.md\n \u251c\u2500\u2500 LICENSE\n \u251c\u2500\u2500 Makefile\n \u251c\u2500\u2500 README.md\n \u251c\u2500\u2500 add-ons\n \u2514\u2500\u2500 chart\n
To enable EDP Add-Ons, it is necessary to have the configured Argo CD, and connect and synchronize the forked repository. To do this, follow the guidelines below:
Fork the Add-Ons repository to your personal account.
Provide the parameter values for the values.yaml files of the desired Add-Ons you are going to install.
Navigate to Argo CD -> Settings -> Repositories. Connect your forked repository where you have the values.yaml files changed by clicking the + Connect repo button:
Connect the forked repository
In the appeared window, fill in the following fields and click the Connect button:
Repository parameters
As soon as the repository is connected, the new item in the repository list will appear:
Connected repository
Navigate to Argo CD -> Applications. Click the + New app button:
Adding Argo CD application
Fill in the required fields:
As soon as the repository is synchronized, the list of applications that can be installed by Add-Ons will be shown:
Add-Ons list
Now that Add-Ons are enabled in Argo CD, they can be installed by following the steps below:
Choose the Add-On to install.
On the chosen Add-On, click the \u22ee button and then Details:
Open Add-Ons
To install the Add-On, click the \u22ee button -> Sync:
Install Add-Ons
Once the Add-On is installed, the Sync OK message will appear in the Add-On status bar:
Sync OK message
Open the application details by clicking on the little square with an arrow underneath the Add-On name:
Open details
Track application resources and status in the App details menu:
Application details
As we see, Argo CD offers great observability and monitoring tools for its resources which comes in handy when using EDP Add-Ons.
"},{"location":"operator-guide/add-ons-overview/#available-add-ons-list","title":"Available Add-Ons List","text":"The list of the available Add-Ons:
Name Description Default Argo CD A GitOps continuous delivery tool that helps automate the deployment, configuration, and lifecycle management of applications in Kubernetes clusters. false AWS EFS CSI Driver A Container Storage Interface (CSI) driver that enables the dynamic provisioning of Amazon Elastic File System (EFS) volumes in Kubernetes clusters. true Cert Manager A native Kubernetes certificate management controller that automates the issuance and renewal of TLS certificates. true DefectDojo A security vulnerability management tool that allows tracking and managing security findings in applications. true DependencyTrack A Software Composition Analysis (SCA) platform that helps identify and manage open-source dependencies and their associated vulnerabilities. true EDP An internal platform created by EPAM to enhance software delivery processes using DevOps principles and tools. false Extensions OIDC EDP Helm chart to provision OIDC clients for different Add-Ons using EDP Keycloak Operator. true External Secrets A Kubernetes Operator that fetches secrets from external secret management systems and injects them as Kubernetes Secrets. true Fluent Bit A lightweight and efficient log processor and forwarder that collects and routes logs from various sources in Kubernetes clusters. false Harbor A cloud-native container image registry that provides support for vulnerability scanning, policy-based image replication, and more. true Nginx ingress An Ingress controller that provides external access to services running within a Kubernetes cluster using Nginx as the underlying server. true Jaeger Operator An operator for deploying and managing Jaeger, an end-to-end distributed tracing system, in Kubernetes clusters. true Keycloak An open-source Identity and Access Management (IAM) solution that enables authentication, authorization, and user management in Kubernetes clusters. true Keycloak PostgreSQL A PostgreSQL database operator that simplifies the deployment and management of PostgreSQL instances in Kubernetes clusters. false MinIO Operator An operator that simplifies the deployment and management of MinIO, a high-performance object storage server compatible with Amazon S3, in Kubernetes clusters. true OpenSearch A community-driven, open-source search and analytics engine that provides scalable and distributed search capabilities for Kubernetes clusters. true OpenTelemetry Operator An operator for automating the deployment and management of OpenTelemetry, a set of observability tools for capturing, analyzing, and exporting telemetry data. true PostgreSQL Operator An operator for running and managing PostgreSQL databases in Kubernetes clusters with high availability and scalability. true Prometheus Operator An operator that simplifies the deployment and management of Prometheus, a monitoring and alerting toolkit, in Kubernetes clusters. true Redis Operator An operator for managing Redis, an in-memory data structure store, in Kubernetes clusters, providing high availability and horizontal scalability. true StorageClass A Kubernetes resource that provides a way to define different classes of storage with different performance characteristics for persistent volumes. true Tekton A flexible and cloud-native framework for building, testing, and deploying applications using Kubernetes-native workflows. true Vault An open-source secrets management solution that provides secure storage, encryption, and access control for sensitive data in Kubernetes clusters. true"},{"location":"operator-guide/add-other-code-language/","title":"Add Other Code Language","text":""},{"location":"operator-guide/add-other-code-language/#add-other-code-language","title":"Add Other Code Language","text":"There is an ability to extend the default code languages when creating a codebase with the Clone or Import strategy.
Other code language
Warning
The Create strategy does not allow to customize the default code language set.
To customize the Build Tool list, perform the following:
Edit the edp-admin-console deployment by adding the necessary code language into the BUILD TOOLS field:
kubectl edit deployment edp-admin-console -n edp\n
Note
Using an OpenShift cluster, run the oc
command instead of kubectl
one.
Info
edp
is the name of the EDP tenant here and in all the following steps.
...\nspec:\n containers:\n - env:\n ...\n - name: BUILD_TOOLS\n value: docker # List of custom build tools in Admin Console, e.g. 'docker,helm';\n ...\n...\n
As a result, the newly added Jenkins agent will be available in the Select Jenkins Slave dropdown list of the Advanced Settings block during the codebase creation:
Advanced settings
If it is necessary to create Code Review and Build pipelines, add corresponding entries (e.g. stages[Build-application-docker], [Code-review-application-docker]). See the example below:
...\nstages['Code-review-application-docker'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + ',{\"name\": \"sonar\"}]'\nstages['Build-application-docker'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build-image-kaniko\"}' + ',{\"name\": \"git-tag\"}]'\n...\n
Jenkins job provisioner
Note
Application is one of the available options. Another option might be to add a library. Please refer to the Add Library page for details.
"},{"location":"operator-guide/add-other-code-language/#related-articles","title":"Related Articles","text":"In order to add a new security scanner, perform the steps below:
Select a pipeline customization option from the Customize CI Pipeline article. Follow the steps described in this article, to create a new repository.
Note
This tutorial will focus on adding a new stage using shared library via the custom global pipeline libraries.
Open the new repository and create a directory with the /src/com/epam/edp/customStages/impl/ci/impl/stageName/
name in the library repository, for example: /src/com/epam/edp/customStages/impl/ci/impl/security/
. After that, add a Groovy file with another name to the same stages catalog, for example: CustomSAST.groovy
.
Copy the logic from SASTMavenGradleGoApplication.groovy
stage into the new CustomSAST.groovy
stage.
Add a new runGoSecScanner
function to the stage:
@Stage(name = \"sast-custom\", buildTool = [\"maven\",\"gradle\",\"go\"], type = [ProjectType.APPLICATION])\nclass CustomSAST {\n...\n def runGoSecScanner(context) {\n def edpName = context.platform.getJsonPathValue(\"cm\", \"edp-config\", \".data.edp_name\")\n def reportData = [:]\n reportData.active = \"true\"\n reportData.verified = \"false\"\n reportData.path = \"sast-gosec-report.json\"\n reportData.type = \"Gosec Scanner\"\n reportData.productTypeName = \"Tenant\"\n reportData.productName = \"${edpName}\"\n reportData.engagementName = \"${context.codebase.name}-${context.git.branch}\"\n reportData.autoCreateContext = \"true\"\n reportData.closeOldFindings = \"true\"\n reportData.pushToJira = \"false\"\n reportData.environment = \"Development\"\n reportData.testTitle = \"SAST\"\n script.sh(script: \"\"\"\n set -ex\n gosec -fmt=json -out=${reportData.path} ./...\n \"\"\")\n return reportData\n }\n...\n}\n
Add function calls for the runGoSecScanner
and publishReport
functions:
...\nscript.node(\"sast\") {\n script.dir(\"${testDir}\") {\n script.unstash 'all-repo'\n...\n def dataFromGoSecScanner = runGoSecScanner(context)\n publishReport(defectDojoCredentials, dataFromGoSecScanner)\n }\n}\n...\n
Gosec scanner will be installed on the Jenkins SAST agent. It is based on the epamedp/edp-jenkins-base-agent
. Please check DockerHub for its latest version.
See below an example of the edp-jenkins-sast-agent
Dockerfile:
# Copyright 2022 EPAM Systems.\n\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n # http://www.apache.org/licenses/LICENSE-2.0\n\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\n # See the License for the specific language governing permissions and\n # limitations under the License.\n\n FROM epamedp/edp-jenkins-base-agent:1.0.31\n\n SHELL [\"/bin/bash\", \"-o\", \"pipefail\", \"-c\"]\n\n USER root\n\n ENV SEMGREP_SCANNER_VERSION=0.106.0 \\\n GOSEC_SCANNER_VERSION=2.12.0\n\n RUN apk --no-cache add \\\n curl=7.79.1-r2 \\\n build-base=0.5-r3 \\\n python3-dev=3.9.5-r2 \\\n py3-pip=20.3.4-r1 \\\n go=1.16.15-r0\n\n # hadolint ignore=DL3059\n RUN pip3 install --no-cache-dir --upgrade --ignore-installed \\\n pip==22.2.1 \\\n ruamel.yaml==0.17.21 \\\n semgrep==${SEMGREP_SCANNER_VERSION}\n\n # Install GOSEC\n RUN curl -Lo /tmp/gosec.tar.gz https://github.com/securego/gosec/releases/download/v${GOSEC_SCANNER_VERSION}/gosec_${GOSEC_SCANNER_VERSION}_linux_amd64.tar.gz && \\\n tar xf /tmp/gosec.tar.gz && \\\n rm -f /tmp/gosec.tar.gz && \\\n mv gosec /bin/gosec\n\n RUN chown -R \"1001:0\" \"$HOME\" && \\\n chmod -R \"g+rw\" \"$HOME\"\n\n USER 1001\n
EDP uses Argo CD as a part of the Continues Delivery/Continues Deployment implementation. Argo CD follows the best GitOps practices, uses Kubernetes native approach for the Deployment Management, has rich UI and required RBAC capabilities.
"},{"location":"operator-guide/argocd-integration/#argo-cd-deployment-approach-in-edp","title":"Argo CD Deployment Approach in EDP","text":"Argo CD can be installed using two different approaches:
Both approaches can be deployed with High Availability (HA) or Non High Availability (non HA) installation manifests.
EDP uses the HA deployment with the cluster-admin permissions, to minimize cluster resources consumption by sharing single Argo CD instance across multiple EDP Tenants. Please follow the installation instructions to deploy Argo CD.
"},{"location":"operator-guide/argocd-integration/#edp-argo-cd-integration","title":"EDP Argo CD Integration","text":"See a diagram below for the details:
Argo CD Diagram
argocd
namespace.cluster-admin
role for managing cluster-scope resources.control-plane
application is created using the App of Apps approach, and its code is managed by the control-plane
members.control-plane
is used to onboard new Argo CD Tenants (Argo CD Projects - AppProject).EDP Tenant Member
manages Argo CD Applications
using kind: Application
in the edpTenant
namespace.The App Of Apps approach is used to manage the EDP Tenants
. Inspect the edp-grub repository structure that is used to provide the EDP Tenants for the Argo CD Projects:
edp-grub\n\u251c\u2500\u2500 LICENSE\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 apps ### All Argo CD Applications are stored here\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 grub-argocd.yaml # Application that provisions Argo CD Resources - Argo Projects (EDP Tenants)\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 grub-keycloak.yaml # Application that provisions Keycloak Resources - Argo CD Groups (EDP Tenants)\n\u251c\u2500\u2500 apps-configs\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 grub\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 argocd ### Argo CD resources definition\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 team-bar.yaml\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 team-foo.yaml\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 keycloak ### Keycloak resources definition\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 team-bar.yaml\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 team-foo.yaml\n\u251c\u2500\u2500 bootstrap\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 root.yaml ### Root application in App of Apps, which provision Applications from /apps\n\u2514\u2500\u2500 examples ### Examples\n \u2514\u2500\u2500 tenant\n \u2514\u2500\u2500 foo-petclinic.yaml\n
The Root Application must be created under the control-plane
scope.
Note
Make sure that both EDP and Argo CD are installed, and that SSO is enabled.
To start using Argo CD with EDP, perform the following steps:
"},{"location":"operator-guide/argocd-integration/#keycloak","title":"Keycloak","text":"Create a Keycloak Group.
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmGroup\nmetadata:\n name: argocd-team-foo-users\nspec:\n name: ArgoCD-team-foo-users\n realm: main\n
In Keycloak, add users to the ArgoCD-team-foo-users
Keycloak Group.
Add a credential template for Gerrit, GitHub, GitLab integrations. The credential template must be created for each Git server.
GerritGitHub/GitLabCopy existing SSH private key for Gerrit to Argo CD namespace
EDP_NAMESPACE=<EPD_NAMESPACE>\nGERRIT_PORT=$(kubectl get gerrit gerrit -n ${EDP_NAMESPACE} -o jsonpath='{.spec.sshPort}')\nGERRIT_ARGOCD_SSH_KEY_NAME=\"gerrit-argocd-sshkey\"\nGERRIT_URL=$(echo \"ssh://argocd@gerrit.${EDP_NAMESPACE}:${GERRIT_PORT}\" | base64)\nkubectl get secret ${GERRIT_ARGOCD_SSH_KEY_NAME} -n ${EDP_NAMESPACE} -o json | jq 'del(.data.username,.metadata.annotations,.metadata.creationTimestamp,.metadata.labels,.metadata.resourceVersion,.metadata.uid,.metadata.ownerReferences)' | jq '.metadata.namespace = \"argocd\"' | jq --arg name \"${EDP_NAMESPACE}\" '.metadata.name = $name' | jq --arg url \"${GERRIT_URL}\" '.data.url = $url' | jq '.data.sshPrivateKey = .data.id_rsa' | jq 'del(.data.id_rsa,.data.\"id_rsa.pub\")' | kubectl apply -f -\nkubectl label --overwrite secret ${EDP_NAMESPACE} -n argocd \"argocd.argoproj.io/secret-type=repo-creds\"\n
Generate an SSH key pair and add a public key to GitLab or GitHub account.
Warning
Use an additional GitHub/GitLab User to access a repository. For example: - GitHub, add a User to a repository with a \"Read\" role. - GitLab, add a User to a repository with a \"Guest\" role.
ssh-keygen -t ed25519 -C \"email@example.com\" -f argocd\n
Copy SSH private key to Argo CD namespace
EDP_NAMESPACE=<EDP_NAMESPACE>\nVCS_HOST=\"<github.com_or_gitlab.com>\"\nACCOUNT_NAME=\"<ACCOUNT_NAME>\"\nURL=\"ssh://git@${VCS_HOST}:22/${ACCOUNT_NAME}\"\n\nkubectl create secret generic ${EDP_NAMESPACE} -n argocd \\\n--from-file=sshPrivateKey=argocd \\\n--from-literal=url=\"${URL}\"\nkubectl label --overwrite secret ${EDP_NAMESPACE} -n argocd \"argocd.argoproj.io/secret-type=repo-creds\"\n
Add public SSH key to GitHub/GitLab account.
Add SSH Known hosts for Gerrit, GitHub, GitLab integration.
GerritGitHub/GitLabAdd Gerrit host to Argo CD config map with known hosts
EDP_NAMESPACE=<EDP_NAMESPACE>\nKNOWN_HOSTS_FILE=\"/tmp/ssh_known_hosts\"\nARGOCD_KNOWN_HOSTS_NAME=\"argocd-ssh-known-hosts-cm\"\nGERRIT_PORT=$(kubectl get gerrit gerrit -n ${EDP_NAMESPACE} -o jsonpath='{.spec.sshPort}')\n\nrm -f ${KNOWN_HOSTS_FILE}\nkubectl get cm ${ARGOCD_KNOWN_HOSTS_NAME} -n argocd -o jsonpath='{.data.ssh_known_hosts}' > ${KNOWN_HOSTS_FILE}\nkubectl exec -it deployment/gerrit -n ${EDP_NAMESPACE} -- ssh-keyscan -p ${GERRIT_PORT} gerrit.${EDP_NAMESPACE} >> ${KNOWN_HOSTS_FILE}\nkubectl create configmap ${ARGOCD_KNOWN_HOSTS_NAME} -n argocd --from-file ${KNOWN_HOSTS_FILE} -o yaml --dry-run=client | kubectl apply -f -\n
Add GitHub/GitLab host to Argo CD config map with known hosts
EDP_NAMESPACE=<EPD_NAMESPACE>\nVCS_HOST=\"<VCS_HOST>\"\nKNOWN_HOSTS_FILE=\"/tmp/ssh_known_hosts\"\nARGOCD_KNOWN_HOSTS_NAME=\"argocd-ssh-known-hosts-cm\"\n\nrm -f ${KNOWN_HOSTS_FILE}\nkubectl get cm ${ARGOCD_KNOWN_HOSTS_NAME} -n argocd -o jsonpath='{.data.ssh_known_hosts}' > ${KNOWN_HOSTS_FILE}\nssh-keyscan ${VCS_HOST} >> ${KNOWN_HOSTS_FILE}\nkubectl create configmap ${ARGOCD_KNOWN_HOSTS_NAME} -n argocd --from-file ${KNOWN_HOSTS_FILE} -o yaml --dry-run=client | kubectl apply -f -\n
Create an Argo CD Project (EDP Tenant), for example, with the team-foo
name:
apiVersion: argoproj.io/v1alpha1\nkind: AppProject\nmetadata:\n name: team-foo\n namespace: argocd\n # Finalizer that ensures that project is not deleted until it is not referenced by any application\n finalizers:\n - resources-finalizer.argocd.argoproj.io\nspec:\n description: CD pipelines for team-foo\n roles:\n - name: developer\n description: Users for team-foo tenant\n policies:\n - p, proj:team-foo:developer, applications, create, team-foo/*, allow\n - p, proj:team-foo:developer, applications, delete, team-foo/*, allow\n - p, proj:team-foo:developer, applications, get, team-foo/*, allow\n - p, proj:team-foo:developer, applications, override, team-foo/*, allow\n - p, proj:team-foo:developer, applications, sync, team-foo/*, allow\n - p, proj:team-foo:developer, applications, update, team-foo/*, allow\n - p, proj:team-foo:developer, repositories, create, team-foo/*, allow\n - p, proj:team-foo:developer, repositories, delete, team-foo/*, allow\n - p, proj:team-foo:developer, repositories, update, team-foo/*, allow\n - p, proj:team-foo:developer, repositories, get, team-foo/*, allow\n groups:\n # Keycloak Group name\n - ArgoCD-team-foo-users\n destinations:\n # ensure we can deploy to ns with tenant prefix\n - namespace: 'team-foo-*'\n # allow to deploy to specific server (local in our case)\n server: https://kubernetes.default.svc\n # Deny all cluster-scoped resources from being created, except for Namespace\n clusterResourceWhitelist:\n - group: ''\n kind: Namespace\n # Allow all namespaced-scoped resources to be created, except for ResourceQuota, LimitRange, NetworkPolicy\n namespaceResourceBlacklist:\n - group: ''\n kind: ResourceQuota\n - group: ''\n kind: LimitRange\n - group: ''\n kind: NetworkPolicy\n # we are ok to create any resources inside namespace\n namespaceResourceWhitelist:\n - group: '*'\n kind: '*'\n # enable access only for specific git server. The example below 'team-foo' - it is namespace where EDP deployed\n sourceRepos:\n - ssh://argocd@gerrit.team-foo:30007/*\n # enable capability to deploy objects from namespaces\n sourceNamespaces:\n - team-foo\n
Optional: if the Argo CD controller has not been enabled to manage the Application resources in the specific namespaces (team-foo
, in our case) in the Install Argo CD, modify the argocd-cmd-params-cm
ConfigMap in the Argo CD namespace and add the application.namespaces
parameter to the subsection data:
...\ndata:\n application.namespaces: team-foo\n...\n
values.yaml file...\nconfigs:\n params:\n application.namespaces: team-foo\n...\n
Check that your new Repository, Known Hosts, and AppProject are added to the Argo CD UI.
Once Argo CD is successfully integrated, EDP user can utilize Argo CD to deploy CD pipelines.
"},{"location":"operator-guide/argocd-integration/#check-argo-cd-integration-optional","title":"Check Argo CD Integration (Optional)","text":"This section provides the information on how to test the integration with Argo CD and is not mandatory to be followed.
Follow the Add Application instruction to deploy a test EDP application with the demo
name, which should be stored in a Gerrit private repository:
apiVersion: argoproj.io/v1alpha1\nkind: Application\nmetadata:\n name: demo\nspec:\n project: team-foo\n destination:\n namespace: team-foo-demo\n server: https://kubernetes.default.svc\n source:\n helm:\n parameters:\n - name: image.tag\n value: master-0.1.0-1\n - name: image.repository\n value: image-repo\n path: deploy-templates\n repoURL: ssh://argocd@gerrit.team-foo:30007/demo.git\n targetRevision: master\n syncPolicy:\n syncOptions:\n - CreateNamespace=true\n automated:\n selfHeal: true\n prune: true\n
Check that your new Application is added to the Argo CD UI under the team-foo
Project scope.
This documentation outlines platform SLSA integration and guides verifying image authenticity and provenance.
Supply Chain Levels of Software Assurance (SLSA) is a framework for assessing and enhancing software supply chain security. Software Supply Chain Security is a critical aspect of modern software development and deployment. Supply Chain Levels of Software Assurance (SLSA) provides a framework for assessing and enhancing the security of your software supply chain.
"},{"location":"operator-guide/artifacts-verification/#prerequisites","title":"Prerequisites","text":"Ensure you have installed rekor-cli and cosign on your environment before proceeding.
"},{"location":"operator-guide/artifacts-verification/#release-assets","title":"Release Assets","text":"The table below represents a list of EDP components with corresponding images that are signed and pushed to DockerHub:
Asset Description codebase-operator Docker Image edp-headlamp Docker Image edp-tekton Docker Image cd-pipeline-operator Docker Image gerrit-operator Docker Image edp-gerrit Docker Image"},{"location":"operator-guide/artifacts-verification/#verify-container-images","title":"Verify Container Images","text":"EPAM Delivery Platform's container images are signed using cosign with the cosign.pub key for signing and transparency. You can verify a container image's signature by executing the cosign verify
command.
To confirm the authenticity of the image, run the cosign verify
command. See the example below:
cosign verify --key https://raw.githubusercontent.com/epam/edp-install/master/cosign.pub epamedp/codebase-operator:2.20.0 | jq .\n
Verification for epamedp/codebase-operator:2.20.0:
Verification for index.docker.io/epamedp/codebase-operator:2.20.0\nThe following checks were performed on each of these signatures:\n - The cosign claims were validated\n - The claims were present in the transparency log\n - The signatures were integrated into the transparency log when the certificate was valid\n - The signatures were verified against the specified public key\n[\n {\n \"critical\": {\n \"identity\": {\n \"docker-reference\": \"index.docker.io/epamedp/codebase-operator\"\n },\n \"image\": {\n \"docker-manifest-digest\": \"sha256:36585a13b5b5ff5a15138e9d16cc74eb3aac4560b77be15161d3b3db25b89e1d\"\n },\n \"type\": \"cosign container image signature\"\n },\n \"optional\": null\n }\n]\n
"},{"location":"operator-guide/artifacts-verification/#verify-container-image-with-slsa-attestations","title":"Verify Container Image With SLSA Attestations","text":"An SLSA Level 3 provenance is verified using. The following command will verify the signature of an attestation and how it was issued. It will contain the payloadType, payload, and signature.
Run the cosign verify-attestation
command using the cosign.pub:
cosign verify-attestation --key https://raw.githubusercontent.com/epam/edp-install/master/cosign.pub --type slsaprovenance epamedp/codebase-operator:2.20.0 | jq .\n
Verification for epamedp/codebase-operator:2.20.0:
Verification for epamedp/codebase-operator:2.20.0\nThe following checks were performed on each of these signatures:\n - The cosign claims were validated\n - The claims were present in the transparency log\n - The signatures were integrated into the transparency log when the certificate was valid\n - The signatures were verified against the specified public key\n{\n \"payloadType\": \"application/vnd.in-toto+json\",\n \"payload\": \"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsInN1YmplY3QiOlt7Im5hbWUiOiJpbmRleC5kb2NrZXIuaW8vZXBhbWVkcC9jb2RlYmFzZS1vcGVyYXRvciIsImRpZ2VzdCI6eyJzaGEyNTYiOiIzNjU4NWExM2I1YjVmZjVhMTUxMzhlOWQxNmNjNzRlYjNhYWM0NTYwYjc3YmUxNTE2MWQzYjNkYjI1Yjg5ZTFkIn19XSwicHJlZGljYXRlIjp7ImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL3Rla3Rvbi5kZXYvY2hhaW5zL3YyIn0sImJ1aWxkVHlwZSI6InRla3Rvbi5kZXYvdjFiZXRhMS9UYXNrUnVuIiwiaW52b2NhdGlvbiI6eyJjb25maWdTb3VyY2UiOnt9LCJwYXJhbWV0ZXJzIjp7IkJVSUxERVJfSU1BR0UiOiJnY3IuaW8va2FuaWtvLXByb2plY3QvZXhlY3V0b3I6djEuMTIuMS1kZWJ1ZyIsIkNPTlRFWFQiOiIuLyIsIkRPQ0tFUkZJTEUiOiJEb2NrZXJmaWxlIiwiSU1BR0UiOiJlcGFtZWRwL2NvZGViYXNlLW9wZXJhdG9yOjIuMjAuMCIsIklNQUdFX1RBUiI6ImNvZGViYXNlLW9wZXJhdG9yXzIuMjAuMCJ9LCJlbnZpcm9ubWVudCI6eyJhbm5vdGF0aW9ucyI6eyJtZXRhLmhlbG0uc2gvcmVsZWFzZS1uYW1lIjoiZWRwLWN1c3RvbS1waXBlbGluZXMiLCJtZXRhLmhlbG0uc2gvcmVsZWFzZS1uYW1lc3BhY2UiOiJlZHAtZGVsaXZlcnkiLCJwaXBlbGluZS50ZWt0b24uZGV2L2FmZmluaXR5LWFzc2lzdGFudCI6ImFmZmluaXR5LWFzc2lzdGFudC1iZjRkNzRkMWM0IiwicGlwZWxpbmUudGVrdG9uLmRldi9yZWxlYXNlIjoiMjI5OWIxNSIsInRla3Rvbi5kZXYvY2F0ZWdvcmllcyI6IkltYWdlIEJ1aWxkIiwidGVrdG9uLmRldi9kaXNwbGF5TmFtZSI6IkJ1aWxkIGFuZCB1cGxvYWQgY29udGFpbmVyIGltYWdlIHVzaW5nIEthbmlrbyIsInRla3Rvbi5kZXYvcGlwZWxpbmVzLm1pblZlcnNpb24iOiIwLjE3LjAiLCJ0ZWt0b24uZGV2L3BsYXRmb3JtcyI6ImxpbnV4L2FtZDY0IiwidGVrdG9uLmRldi90YWdzIjoiaW1hZ2UtYnVpbGQifSwibGFiZWxzIjp7ImFwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnkiOiJIZWxtIiwiYXBwLmt1YmVybmV0ZXMuaW8vdmVyc2lvbiI6IjAuOC4wIiwiaGVsbS5zaC9jaGFydCI6ImVkcC1jdXN0b20tcGlwZWxpbmVzLTAuOC4wIiwiazhzbGVucy1lZGl0LXJlc291cmNlLXZlcnNpb24iOiJ2MSIsInRla3Rvbi5kZXYvbWVtYmVyT2YiOiJ0YXNrcyIsInRla3Rvbi5kZXYvcGlwZWxpbmUiOiJnZXJyaXQtb3BlcmF0b3JzLWFwcC1yZWxlYXNlLWVkcCIsInRla3Rvbi5kZXYvcGlwZWxpbmVSdW4iOiJlZHAtY29kZWJhc2Utb3BlcmF0b3ItcmVsZWFzZSIsInRla3Rvbi5kZXYvcGlwZWxpbmVUYXNrIjoia2FuaWtvLWJ1aWxkIiwidGVrdG9uLmRldi90YXNrIjoia2FuaWtvLXJlbGVhc2UifX19LCJidWlsZENvbmZpZyI6eyJzdGVwcyI6W3siZW50cnlQb2ludCI6Ii9rYW5pa28vZXhlY3V0b3IgXFxcbiAgLS1kb2NrZXJmaWxlPS93b3Jrc3BhY2Uvc291cmNlL0RvY2tlcmZpbGUgXFxcbiAgLS1jb250ZXh0PS93b3Jrc3BhY2Uvc291cmNlLy4vIFxcXG4gIC0tZGVzdGluYXRpb249ZXBhbWVkcC9jb2RlYmFzZS1vcGVyYXRvcjoyLjIwLjAgXFxcbiAgLS1kaWdlc3QtZmlsZT0vdGVrdG9uL3Jlc3VsdHMvSU1BR0VfRElHRVNUIFxcXG4gIC0tdGFyLXBhdGg9Y29kZWJhc2Utb3BlcmF0b3JfMi4yMC4wLnRhciBcXFxuIiwiYXJndW1lbnRzIjpudWxsLCJlbnZpcm9ubWVudCI6eyJjb250YWluZXIiOiJidWlsZC1hbmQtcHVzaCIsImltYWdlIjoib2NpOi8vZ2NyLmlvL2thbmlrby1wcm9qZWN0L2V4ZWN1dG9yQHNoYTI1NjphN2VhOWY2OWQ3N2Q3ZTdhMGVhODIxZjE1MDY5YmU0NTQyMGE1MzZmODFhYjU3ODdhOTg4NjU5ZTQ4YzI1Mzc3In0sImFubm90YXRpb25zIjpudWxsfSx7ImVudHJ5UG9pbnQiOiJzZXQgLWVcbmltYWdlPVwiZXBhbWVkcC9jb2RlYmFzZS1vcGVyYXRvcjoyLjIwLjBcIlxuZWNobyAtbiBcIiR7aW1hZ2V9XCIgfCB0ZWUgXCIvdGVrdG9uL3Jlc3VsdHMvSU1BR0VfVVJMXCJcbiIsImFyZ3VtZW50cyI6bnVsbCwiZW52aXJvbm1lbnQiOnsiY29udGFpbmVyIjoid3JpdGUtdXJsIiwiaW1hZ2UiOiJvY2k6Ly9kb2NrZXIuaW8vbGlicmFyeS9hbHBpbmVAc2hhMjU2OjcxNDRmN2JhYjNkNGMyNjQ4ZDdlNTk0MDlmMTVlYzUyYTE4MDA2YTEyOGM3MzNmY2ZmMjBkM2E0YTU0YmE0NGEifSwiYW5ub3RhdGlvbnMiOm51bGx9XX0sIm1ldGFkYXRhIjp7ImJ1aWxkU3RhcnRlZE9uIjoiMjAyMy0xMS0wM1QxMzozMDo1NVoiLCJidWlsZEZpbmlzaGVkT24iOiIyMDIzLTExLTAzVDEzOjMxOjE1WiIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoib2NpOi8vZ2NyLmlvL2thbmlrby1wcm9qZWN0L2V4ZWN1dG9yIiwiZGlnZXN0Ijp7InNoYTI1NiI6ImE3ZWE5ZjY5ZDc3ZDdlN2EwZWE4MjFmMTUwNjliZTQ1NDIwYTUzNmY4MWFiNTc4N2E5ODg2NTllNDhjMjUzNzcifX0seyJ1cmkiOiJvY2k6Ly9kb2NrZXIuaW8vbGlicmFyeS9hbHBpbmUiLCJkaWdlc3QiOnsic2hhMjU2IjoiNzE0NGY3YmFiM2Q0YzI2NDhkN2U1OTQwOWYxNWVjNTJhMTgwMDZhMTI4YzczM2ZjZmYyMGQzYTRhNTRiYTQ0YSJ9fV19fQ==\",\n \"signatures\": [\n {\n \"keyid\": \"SHA256:7E2nAQnycq4vfPlzmLZGzpK/Vr6oXKqqGokDyrBSLck\",\n \"sig\": \"MEUCIAZLrA/wTkqmnCZXh85R9Y/Ue5f8wuGgjLMYdoFw9GRLAiEA/sE598EX5fppqbry+xvE+aap8+qHPioOin8t6Ttzx3k=\"\n }\n ]\n}\n
For more details about attestation, please refer to the official cosign documentation page.
"},{"location":"operator-guide/artifacts-verification/#verify-release-pipeline","title":"Verify Release Pipeline","text":"Within each release component, you will discover a Rekor UUID, which serves to validate the flow of the release pipeline. Execute the following command to obtain comprehensive information about the release pipeline of codebase-operator with UUID:
24296fb24b8ad77a671b24f6b83f79e46fe5214cde46ed045ceba35d640a7e017cbc5524e90329ff
:
rekor-cli get --uuid 24296fb24b8ad77a671b24f6b83f79e46fe5214cde46ed045ceba35d640a7e017cbc5524e90329ff --format json | jq -r .Attestation | jq .\n
The result:
{\n \"_type\": \"https://in-toto.io/Statement/v0.1\",\n \"predicateType\": \"https://slsa.dev/provenance/v0.2\",\n \"subject\": [\n {\n \"name\": \"index.docker.io/epamedp/codebase-operator\",\n \"digest\": {\n \"sha256\": \"36585a13b5b5ff5a15138e9d16cc74eb3aac4560b77be15161d3b3db25b89e1d\"\n }\n }\n ],\n \"predicate\": {\n \"builder\": {\n \"id\": \"https://tekton.dev/chains/v2\"\n },\n \"buildType\": \"tekton.dev/v1beta1/TaskRun\",\n \"invocation\": {\n \"configSource\": {},\n \"parameters\": {\n \"BUILDER_IMAGE\": \"gcr.io/kaniko-project/executor:v1.12.1-debug\",\n \"CONTEXT\": \"./\",\n \"DOCKERFILE\": \"Dockerfile\",\n \"IMAGE\": \"epamedp/codebase-operator:2.20.0\",\n \"IMAGE_TAR\": \"codebase-operator_2.20.0\"\n },\n \"environment\": {\n \"annotations\": {\n ...\n },\n \"labels\": {\n ...\n }\n }\n },\n \"buildConfig\": {\n \"steps\": [\n {\n \"entryPoint\": \"/kaniko/executor \\\\\\n --dockerfile=/workspace/source/Dockerfile \\\\\\n --context=/workspace/source/./ \\\\\\n --destination=epamedp/codebase-operator:2.20.0 \\\\\\n --digest-file=/tekton/results/IMAGE_DIGEST \\\\\\n --tar-path=codebase-operator_2.20.0.tar \\\\\\n\",\n \"arguments\": null,\n \"environment\": {\n \"container\": \"build-and-push\",\n \"image\": \"oci://gcr.io/kaniko-project/executor@sha256:a7ea9f69d77d7e7a0ea821f15069be45420a536f81ab5787a988659e48c25377\"\n },\n \"annotations\": null\n },\n {\n \"entryPoint\": \"set -e\\nimage=\\\"epamedp/codebase-operator:2.20.0\\\"\\necho -n \\\"${image}\\\" | tee \\\"/tekton/results/IMAGE_URL\\\"\\n\",\n \"arguments\": null,\n \"environment\": {\n \"container\": \"write-url\",\n \"image\": \"oci://docker.io/library/alpine@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a\"\n },\n \"annotations\": null\n }\n ]\n },\n \"metadata\": {\n ...\n },\n \"materials\": [\n {\n \"uri\": \"oci://gcr.io/kaniko-project/executor\",\n \"digest\": {\n \"sha256\": \"a7ea9f69d77d7e7a0ea821f15069be45420a536f81ab5787a988659e48c25377\"\n }\n },\n {\n \"uri\": \"oci://docker.io/library/alpine\",\n \"digest\": {\n \"sha256\": \"7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a\"\n }\n }\n ]\n }\n}\n
By signing all our artifacts, we assure you that they are trustworthy. This guide is indispensable for developers and administrators to enhance their software's reliability and meet modern security standards. The adoption of SLSA will bring you confidence while using the platform.
"},{"location":"operator-guide/artifacts-verification/#related-articles","title":"Related Articles","text":"This documentation provides the detailed instructions on how to install the EPAM Delivery Platform via the AWS Marketplace.
To initiate the installation process, navigate to our dedicated AWS Marketplace page and commence the deployment of EPAM Delivery Platform.
Disclaimer
EDP is aligned with industry standards for storing and managing sensitive data, ensuring optimal security. However, the use of custom solutions introduces uncertainties, thus the responsibility for the safety of your data is totally covered by platform administrator.
"},{"location":"operator-guide/aws-marketplace-install/#prerequisites","title":"Prerequisites","text":"Please familiarize yourself with the Prerequisites page before deploying the product. To perform a minimal installation, ensure that you meet the following requirements:
To deploy the platform, follow the steps below:
To apply Tekton stack, deploy Tekton resources by executing the command below:
kubectl create ns tekton-pipelines\n kubectl create ns tekton-chains\n kubectl create ns tekton-pipelines-resolvers\n kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml\n kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml\n kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml\n kubectl apply --filename https://storage.googleapis.com/tekton-releases/chains/latest/release.yaml\n
Define the mandatory parameters you would like to use for installation using the following command:
kubectl create ns edp\n helm install edp-install \\\n --namespace edp ./* \\\n --set global.dnsWildCard=example.com \\\n --set awsRegion=<AWS_REGION>\n
(Optional) Provide token to sign in to EDP Portal. Run the following command to create Service Account with cluster admin permissions:
kubectl create serviceaccount edp-admin -n edp\nkubectl create clusterrolebinding edp-cluster-admin --clusterrole=cluster-admin --serviceaccount=edp:edp-admin\nkubectl apply -f - <<EOF\napiVersion: v1\nkind: Secret\nmetadata:\n name: edp-admin-token\n namespace: edp\n annotations:\n kubernetes.io/service-account.name: edp-admin\ntype: kubernetes.io/service-account-token\nEOF\n
(Optional) To get access to EDP Portal, run the port-forwarding command:
kubectl port-forward service/edp-headlamp 59480:80 -n edp\n
(Optional) To open EDP Portal, navigate to the http://localhost:59480
.
(Optional) To get admin token to sign in to EDP Portal:
kubectl get secrets -o jsonpath=\"{.items[?(@.metadata.annotations['kubernetes\\.io/service-account\\.name']=='edp-admin')].data.token}\" -n edp|base64 --decode\n
As a result, you will get access to EPAM Delivery Platform components via EDP Portal UI. Navigate to our Use Cases to try out EDP functionality. Visit other subsections of the Operator Guide to figure out how to configure EDP and integrate it with various tools.
"},{"location":"operator-guide/aws-marketplace-install/#related-articles","title":"Related Articles","text":"This documentation guide provides comprehensive instructions of integrating Capsule with the EPAM Delivery Platform to enhance security and resource management.
Note
When integrating the EPAM Delivery Platform with Capsule, it's essential to understand that the platform needs administrative rights to make and oversee resources. This requirement might raise security concerns, but it's important to clarify that it only pertains to the deployment process within the platform. There is an alternative approach available. You can manually create permissions for each deployment flow. This alternative method can be used to address and lessen these security concerns.
"},{"location":"operator-guide/capsule/#installation","title":"Installation","text":"To install the Capsule tool, use the Cluster Add-Ons approach. For more details, please refer to the Capsule official page.
"},{"location":"operator-guide/capsule/#configuration","title":"Configuration","text":"To use Capsule in EDP, follow the steps below:
Run the command below to upgrade EDP with Capsule capabilities:
helm upgrade --install edp epamedp/edp-install -n edp --values values.yaml --set cd-pipeline-operator.tenancyEngine=capsule\n
Open the CapsuleConfiguration
custom resource called default
:
kubectl edit CapsuleConfiguration default\n
Add the tenant name (by default, it's the EDP namespace name) to the manifest's spec section as follows:
spec:\n userGroups:\n - system:serviceaccounts:edp\n
As a result, EDP will be using Capsule capabilities to manage tenants, thus providing better access management.
"},{"location":"operator-guide/capsule/#related-articles","title":"Related Articles","text":"This article provides the instruction of configuring Keycloak as OIDC Identity Provider for EKS. The example is written on Terraform (HCL).
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#prerequisites","title":"Prerequisites","text":"To follow the instruction, check the following prerequisites:
Note
To connect OIDC with a cluster, install and configure the kubelogin plugin. For Windows, it is recommended to download the kubelogin as a binary and add it to your PATH.
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#solution-overview","title":"Solution Overview","text":"The solution includes three types of the resources - AWS (EKS), Keycloak, Kubernetes. The left part of Keycloak resources remain unchanged after creation, thus allowing us to associate a claim for a user group membership. Other resources can be created, deleted or changed if needed. The most crucial from Kubernetes permissions are Kubernetes RoleBindings and ClusterRoles/Roles. Roles present a set of permissions, in turn RoleBindings map Kubernetes Role to representative Keycloak groups, so a group member can have just appropriate permissions.
EKS Keycloak OIDC
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#keycloak-configuration","title":"Keycloak Configuration","text":"To configure Keycloak, follow the steps described below.
resource \"keycloak_openid_client\" \"openid_client\" {\n realm_id = \"openshift\"\n client_id = \"kubernetes\"\n access_type = \"CONFIDENTIAL\"\n standard_flow_enabled = true\n implicit_flow_enabled = false\n direct_access_grants_enabled = true\n service_accounts_enabled = true\n oauth2_device_authorization_grant_enabled = true\n backchannel_logout_session_required = true\n\n root_url = \"http://localhost:8000/\"\n base_url = \"http://localhost:8000/\"\n admin_url = \"http://localhost:8000/\"\n web_origins = [\"*\"]\n\n valid_redirect_uris = [\n \"http://localhost:8000/*\"\n ]\n}\n
resource \"keycloak_openid_client_scope\" \"openid_client_scope\" {\n realm_id = <realm_id>\n name = \"groups\"\n description = \"When requested, this scope will map a user's group memberships to a claim\"\n include_in_token_scope = true\n consent_screen_text = false\n}\n
resource \"keycloak_openid_client_default_scopes\" \"client_default_scopes\" {\n realm_id = <realm_id>\n client_id = keycloak_openid_client.openid_client.id\n\n default_scopes = [\n \"profile\",\n \"email\",\n \"roles\",\n \"web-origins\",\n keycloak_openid_client_scope.openid_client_scope.name,\n ]\n}\n
resource \"keycloak_openid_group_membership_protocol_mapper\" \"group_membership_mapper\" {\n realm_id = <realm_id>\n client_scope_id = keycloak_openid_client_scope.openid_client_scope.id\n name = \"group-membership-mapper\"\n add_to_id_token = true\n add_to_access_token = true\n add_to_userinfo = true\n full_path = false\n\n claim_name = \"groups\"\n}\n
...\n \"email_verified\": false,\n \"name\": \"An User\",\n \"groups\": [\n \"<env_prefix_name>-oidc-viewers\",\n \"<env_prefix_name>-oidc-cluster-admins\"\n ],\n \"preferred_username\": \"an_user@example.com\",\n \"given_name\": \"An\",\n \"family_name\": \"User\",\n \"email\": \"an_user@example.com\"\n ...\n
resource \"keycloak_group\" \"oidc_tenant_admin\" {\n realm_id = <realm_id>\n name = \"kubernetes-oidc-admins\"\n}\n
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#eks-configuration","title":"EKS Configuration","text":"To configure EKS, follow the steps described below. In AWS Console, open EKS home page -> Choose a cluster -> Configuration tab -> Authentication tab.
The Terraform code for association with Keycloak:
...\ncluster_identity_providers = {\n keycloak = {\n client_id = <keycloak_client_id>\n identity_provider_config_name = \"Keycloak\"\n issuer_url = \"https://<keycloak_url>/auth/realms/<realm_name>\"\n groups_claim = \"groups\"\n }\n...\n
resource \"aws_eks_identity_provider_config\" \"keycloak\" {\n for_each = { for k, v in var.cluster_identity_providers : k => v if true }\n\n cluster_name = var.platform_name\n\n oidc {\n client_id = each.value.client_id\n groups_claim = lookup(each.value, \"groups_claim\", null)\n groups_prefix = lookup(each.value, \"groups_prefix\", null)\n identity_provider_config_name = try(each.value.identity_provider_config_name, each.key)\n issuer_url = each.value.issuer_url\n required_claims = lookup(each.value, \"required_claims\", null)\n username_claim = lookup(each.value, \"username_claim\", null)\n username_prefix = lookup(each.value, \"username_prefix\", null)\n }\n\n tags = var.tags\n}\n
Note
The resource creation takes around 20-30 minutes. The resource doesn't support updating, so each change will lead to deletion of the old instance and creation of a new instance instead.
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#kubernetes-configuration","title":"Kubernetes Configuration","text":"To connect the created Keycloak resources with permissions, it is necessary to create Kubernetes Roles and RoleBindings:
resource \"kubernetes_cluster_role_v1\" \"oidc_tenant_admin\" {\n metadata {\n name = \"oidc-admin\"\n }\n rule {\n api_groups = [\"*\"]\n resources = [\"*\"]\n verbs = [\"*\"]\n }\n}\n
resource \"kubernetes_cluster_role_binding_v1\" \"oidc_cluster_rb\" {\n metadata {\n name = \"oidc-cluster-admin\"\n }\n role_ref {\n api_group = \"rbac.authorization.k8s.io\"\n kind = \"ClusterRole\"\n name = kubernetes_cluster_role_v1.oidc_tenant_admin.metadata[0].name\n }\n subject {\n kind = \"Group\"\n name = keycloak_group.oidc_tenant_admin.name\n api_group = \"rbac.authorization.k8s.io\"\n # work-around due https://github.com/hashicorp/terraform-provider-kubernetes/issues/710\n namespace = \"\"\n }\n}\n
Note
When creating the Keycloak group, ClusterRole, and ClusterRoleBinding, a user receives cluster admin permissions. There is also an option to provide admin permissions just to a particular namespace or another resources set in another namespace. For details, please refer to the Mixing Kubernetes Roles page.
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#kubeconfig","title":"Kubeconfig","text":"Template for kubeconfig:
apiVersion: v1\npreferences: {}\nkind: Config\n\nclusters:\n- cluster:\n server: https://<eks_url>.eks.amazonaws.com\n certificate-authority-data: <certificate_authority_data>\n name: <cluster_name>\n\ncontexts:\n- context:\n cluster: <cluster_name>\n user: <keycloak_user_email>\n name: <cluster_name>\n\ncurrent-context: <cluster_name>\n\nusers:\n- name: <keycloak_user_email>\n user:\n exec:\n apiVersion: client.authentication.k8s.io/v1beta1\n command: kubectl\n args:\n - oidc-login\n - get-token\n - -v1\n - --oidc-issuer-url=https://<keycloak_url>/auth/realms/<realm>\n - --oidc-client-id=<keycloak_client_id>\n - --oidc-client-secret=<keycloak_client_secret>\n
Flag -v1 can be used for debug, in a common case it's not needed and can be deleted. To find the client secret:
Before testing, ensure that a user is a member of the correct Keycloak group. To add a user to a Keycloak group:
Follow the steps below to test the configuration:
KUBECONFIG=<path_to_oidc_kubeconfig> kubectl get ingresses -n <namespace_name>\n
OIDC Successful Login
Error from server (Forbidden): ingresses.networking.k8s.io is forbidden:\nUser \"https://<keycloak_url>/auth/realms/<realm>#<keycloak_user_id>\"\ncannot list resource \"ingresses\" in API group \"networking.k8s.io\" in the namespace \"<namespace_name>\"\n
To update the session, clear cache. The default location for the login cache:
rm -rf ~/.kube/cache\n
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#access-cluster-via-lens","title":"Access Cluster via Lens","text":"To access the Kubernetes cluster via Lens, follow the steps below to configure it:
Note
Lens does not add namespaces of the project automatically, so it is necessary to add them manually, simply go to Settings -> Namespaces and add the namespaces of a project.
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#related-articles","title":"Related Articles","text":"Harbor serves as a tool for storing images and artifacts. This documentation contains instructions on how to create a project in Harbor and set up a robot account for interacting with the registry from CI pipelines.
"},{"location":"operator-guide/container-registry-harbor-integration-tekton-ci/#overview","title":"Overview","text":"Harbor integration with Tekton enables the centralized storage of container images within the cluster, eliminating the need for external services. By leveraging Harbor as the container registry, users can manage and store their automation results and reports in one place.
"},{"location":"operator-guide/container-registry-harbor-integration-tekton-ci/#integration-procedure","title":"Integration Procedure","text":"The integration process involves two steps:
Creating a project to store application images.
Creating two accounts with different permissions to push (read/write) and pull (read-only) project images.
The process of creating new projects is the following:
Navigate to the Projects menu, click the New Project button:
Projects menu
On the New Project menu, enter a project name that matches your EDP namespace in the Project Name field. Keep other fields as default and click OK to continue:
New Project menu
To make EDP and Harbor project interact with each other, set up a robot account:
Navigate to your newly created project, select Robot Accounts menu and choose New Robot Account:
Create Robot Account menu
In the pop-up window, fill in the fields as follows:
edp-push
;read/write permissions
;Pull Repository
and Push Repository
.To proceed, click the ADD button:
Robot Accounts menu
In the appeared window, copy the robot account credentials or click the Export to file button to save the secret and account name locally:
New credentials for Robot Account
Provision the kaniko-docker-config secrets using kubectl, EDP Portal or with the externalSecrets operator:
Example
The auth
string can be generated by this command:
echo -n \"robot\\$edp-project+edp:secret\" | base64\n
kubectlManual SecretExternal Secrets Operator apiVersion: v1\n kind: Secret\n metadata:\n name: kaniko-docker-config\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: registry\n app.edp.epam.com/integration-secret: true\n type: kubernetes.io/dockerconfigjson\n stringData:\n .dockerconfigjson: |\n {\n \"auths\" : {\n \"harbor-registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"secret-string\"\n }\n }\n }\n
Navigate to EDP Portal UI
-> EDP
-> Configuration
-> Registry
. Fill in the required fields and click Save
.
Registry update manual secret
\"kaniko-docker-config\":\n {\"auths\" : \"harbor-registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"secret-string\"\n }\n }\n
Navigate to EDP Portal UI
-> EDP
-> Configuration
-> Registry
. Here, you will observe the Managed by ExternalSecret
message:
Registry managed by external secret operator
Note
More details of External Secrets Operator Integration can be found in the External Secrets Operator Integration page.
Repeat steps 2-3 with values below:
edp-pull
;read-only permissions
;Pull Repository
.Provision the regcred secrets using kubectl, EDP Portal or with the externalSecrets operator:
Example
The auth
string can be generated by this command:
echo -n \"robot\\$edp-project+edp-push:secret\" | base64\n
kubectlManual SecretExternal Secrets Operator apiVersion: v1\nkind: Secret\nmetadata:\n name: regcred\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: registry\n app.edp.epam.com/integration-secret: true\ntype: kubernetes.io/dockerconfigjson\nstringData:\n .dockerconfigjson: |\n {\n \"auths\" : {\n \"harbor-registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"secret-string\"\n }\n }\n }\n
Navigate to EDP Portal UI
-> EDP
-> Configuration
-> Registry
. Fill in the required fields and click Save.
Registry update manual secret
\"regcred\":\n {\"auths\" : \"harbor-registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"secret-string\"\n }\n }\n
Navigate to EDP Portal UI
-> EDP
-> Configuration
-> Registry
. Here, you will observe the Managed by ExternalSecret
message:
Registry managed by external secret operator
Note
More details of External Secrets Operator Integration can be found in the External Secrets Operator Integration page.
In the values.yaml file for the edp-install Helm chart, set the following values for the specified fields:
Manual SecretExternal Secrets OperatorIf the kaniko-docker-config
secret has been created manually:
...\nkaniko:\n existingDockerConfig: \"kaniko-docker-config\"\nglobal:\n dockerRegistry:\n url: harbor-registry.com\n type: \"harbor\"\n...\n
If the kaniko-docker-config
secret has been created via External Secrets Operator:
...\nkaniko:\n existingDockerConfig: \"kaniko-docker-config\"\nexternalSecrets:\n enabled: true\nglobal:\n dockerRegistry:\n url: harbor-registry.com\n type: \"harbor\"\n...\n
(Optional) If you've already deployed the EDP Helm chart, you can update it using the following command:
helm update --install edp epamedp/edp-install \\\n--values values.yaml \\\n--namespace edp\n
As a result, application images built in EDP Portal will be stored in Harbor project and will be deployed from the harbor registry.
Harbor projects can be added and retained with a retention policy generated through the EDP script in edp-cluster-add-ons.
"},{"location":"operator-guide/container-registry-harbor-integration-tekton-ci/#related-articles","title":"Related Articles","text":"This tutorial provides detailed instructions on the optimal method to uninstall the EPAM Delivery Platform.
"},{"location":"operator-guide/delete-edp/#deletion-procedure","title":"Deletion Procedure","text":"To uninstall EDP, perform the following steps:
It is highly recommended to delete all the resources created via EDP Portal UI first. It can be:
We recommend deleting them via EDP Portal UI respectively, although it is also possible to delete all the EDP Portal resources using the kubectl delete
command.
Delete application namespaces. They should be called according to the edp-<cd-pipeline>-<stage-name>
pattern.
Uninstall EDP the same way it was installed.
Run the script that deletes the rest of the custom resources:
View: CleanEDP.sh#!/bin/sh\n\n###################################################################\n# A POSIX script to remove EDP Kubernetes Custom Resources #\n# #\n# PREREQUISITES #\n# kubectl>=1.23.x, awscli (for EKS authentication) #\n# #\n# TESTED #\n# OS: Ubuntu, FreeBSD, Windows (GitBash) #\n# Shells: zsh, bash, dash #\n###################################################################\n\n[ -n \"${DEBUG}\" ] && set -x\n\nset -e\n\nexit_err() {\nprintf '%s\\n' \"$1\" >&2\nexit 1\n}\n\ncheck_kubectl() {\nif ! hash kubectl; then\nexit_err \"Error: kubectl is not installed\"\nfi\n}\n\nget_script_help() {\nself_name=\"$(basename \"$0\")\"\necho \"\\\n${self_name} deletes EDP Kubernetes Custom Resources\n\nUsage: ${self_name}\n\nOptions:\n${self_name} [OPTION] [FILE]\n\n-h, --help Print Help\n-k, --kubeconfig Pass Kubeconfig file\n\nDebug:\nDEBUG=true ${self_name}\n\nExamples:\n${self_name} --kubeconfig ~/.kube/custom_config\"\n}\n\nyellow_fg() {\ntput setaf 3 || true\n}\n\nno_color_out() {\ntput sgr0 || true\n}\n\nget_current_context() {\nkubectl config current-context\n}\n\nget_context_ns() {\nkubectl config view \\\n--minify --output jsonpath='{..namespace}' 2> /dev/null\n}\n\nget_ns() {\nkubectl get ns \"${edp_ns}\" --output name --request-timeout='5s'\n}\n\ndelete_ns() {\nkubectl delete ns \"${edp_ns}\" --timeout='30s'\n}\n\nget_edp_crds() {\nkubectl get crds --no-headers=true | awk '/edp.epam.com/ {print $1}'\n}\n\nget_all_edp_crs_manif() {\nkubectl get \"${edp_crds_comma_list}\" -n \"${edp_ns}\" \\\n--output yaml --ignore-not-found --request-timeout='15s'\n}\n\ndel_all_edp_crs() {\nkubectl delete --all \"${edp_crds_comma_list}\" -n \"${edp_ns}\" \\\n--ignore-not-found --timeout='15s'\n}\n\niterate_edp_crs() {\nedp_crds_comma_list=\"$(printf '%s' \"${edp_crds}\" | tr -s '\\n' ',')\"\nget_all_edp_crs_manif \\\n| sed '/finalizers:/,/.*:/{//!d;}' \\\n| kubectl replace -f - || true\ndel_all_edp_crs || true\n}\n\niterate_edp_crds() {\nn=0\nwhile [ \"$n\" -lt 2 ]; do\nn=$((n + 1))\n\nif [ \"$n\" -eq 2 ]; then\n# Delete remaining resources\nedp_crds=\"keycloakclients,codebasebranches,jenkinsfolders\"\niterate_edp_crs\necho \"EDP Custom Resources in NS ${color_ns} have been deleted.\"\nbreak\nfi\n\necho \"Replacing EDP CR Manifests. Wait for output (may take 2min)...\"\nedp_crds=\"$(get_edp_crds)\"\niterate_edp_crs\ndone\n}\n\nselect_ns() {\nis_context=\"$(get_current_context)\" || exit 1\nprintf '%s' \"Current cluster: \"\nprintf '%s\\n' \"$(yellow_fg)${is_context}$(no_color_out)\"\n\ncurrent_ns=\"$(get_context_ns)\" || true\n\nprintf '%s\\n' \"Enter EDP namespace\"\nprintf '%s' \"Skip to use [$(yellow_fg)${current_ns}$(no_color_out)]: \"\nread -r edp_ns\n\nif [ -z \"${edp_ns}\" ]; then\nedp_ns=\"${current_ns}\"\necho \"${edp_ns}\"\nif [ -z \"${edp_ns}\" ]; then\nexit_err \"Error: namespace is not specified\"\nfi\nelse\nget_ns || exit 1\nfi\n\ncolor_ns=\"$(yellow_fg)${edp_ns}$(no_color_out)\"\n}\n\nchoose_delete_ns() {\nprintf '%s\\n' \"Do you want to delete namespace ${color_ns} as well? (y/n)?\"\nprintf '%s' \"Skip or enter [N/n] to keep the namespace: \"\nread -r answer\nif [ \"${answer}\" != \"${answer#[Yy]}\" ]; then\ndelete_edp_ns=true\necho \"Namespace ${color_ns} is marked for deletion.\"\nelse\necho \"Skipped. Deleting EDP Custom Resources only.\"\nfi\n}\n\ndelete_ns_if_true() {\nif [ \"${delete_edp_ns}\" = true ]; then\necho \"Deleting ${color_ns} namespace...\"\ndelete_ns || exit 1\nfi\n}\n\ninvalid_option() {\nexit_err \"Invalid option '$1'. Use -h, --help for details\"\n}\n\nmain_func() {\ncheck_kubectl\nselect_ns\nchoose_delete_ns\niterate_edp_crds\ndelete_ns_if_true\n}\n\nwhile [ \"$#\" -gt 0 ]; do\ncase \"$1\" in\n-h | --help)\nget_script_help\nexit 0\n;;\n-k | --kubeconfig)\nshift\n[ $# = 0 ] && exit_err \"No Kubeconfig file specified\"\nexport KUBECONFIG=\"$1\"\n;;\n--)\nbreak\n;;\n-k* | --k*)\necho \"Did you mean '--kubeconfig'?\"\ninvalid_option \"$1\"\n;;\n-* | *)\ninvalid_option \"$1\"\n;;\nesac\nshift\ndone\n\nmain_func\n
The script will prompt user to specify the namespace where EDP was deployed in and choose if the namespace is going to be deleted. This script will delete EDP custom resources in the namespace specified by user.
In Keycloak, delete the edp-main
realm, also delete client which is supposed to be called by the edp-main
pattern in the openshift realm.
To delete the job provisioner, take the following steps:
Delete the job provisioner from Jenkins. Navigate to Admin Console->Jenkins->jobs->job-provisions folder, select the necessary provisioner and click the drop-down right to the provisioner name. Select Delete project.
Delete job provisioner
This documentation guide provides comprehensive instructions for installing and integrating DependencyTrack with the EPAM Delivery Platform.
"},{"location":"operator-guide/dependency-track/#prerequisites","title":"Prerequisites","text":"To install DependencyTrack use EDP addons approach.
"},{"location":"operator-guide/dependency-track/#configuration","title":"Configuration","text":"Open Administration
-> Access Management
-> Teams
. Click Create Team
-> Automation
and click Create
.
Click +
in Permissions
and add:
BOM_UPLOAD\nPROJECT_CREATION_UPLOAD\nVIEW_PORTFOLIO\n
Click +
in API keys
to create token:
DependencyTrack settings
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-dependency-track\n namespace: <edp>\n labels:\n app.edp.epam.com/secret-type: dependency-track\n app.edp.epam.com/integration-secret: true\nstringData:\n token: <dependency-track-token>\n url: <dependency-track-api-url>\ntype: Opaque\n
Go to the EDP Portal UI
open EDP
-> Configuration
-> DependencyTrack
apply Token
and URL
click the save
button.
DependencyTrack update manual secret
Store DependencyTrack URL and Token in the AWS Parameter Store with the following format:
\"ci-dependency-track\":\n{\n \"token\": \"XXXXXXXXXXXX\",\n \"url\": \"https://dependency-track.example.com\"\n}\n
Go to the EDP Platform UI
open EDP
-> Configuration
-> DependencyTrack
see the Managed by External Secret
.
DependencyTrack managed by external secret operator
More detail on External Secrets Operator Integration can be found on the following page
After following the instructions provided, you should be able to integrate your DependencyTrack with the EPAM Delivery Platform.
"},{"location":"operator-guide/dependency-track/#related-articles","title":"Related Articles","text":"This instruction provides detailed information on the Amazon Elastic Kubernetes Service cluster deployment and contains the additional setup such as Argo CD installation and EDP addons usage for the infrastructure management.
"},{"location":"operator-guide/deploy-aws-eks/#prerequisites","title":"Prerequisites","text":"Before the EKS cluster deployment and configuration, make sure to check the prerequisites. Install the required tools listed below:
To check the correct tools installation, run the following commands:
git --version\nterraform version\naws --version\ntfenv --version\n
"},{"location":"operator-guide/deploy-aws-eks/#terraform-backend","title":"Terraform Backend","text":"This step will do the following:
To create the required resources, do the following:
Fork and clone git repo with project edp-terraform-aws-platform, rename it in the correspondence with project name.
git clone https://github.com/epmd-edp/edp-terraform-aws-platform.git\nmv edp-terraform-aws-platform edp-terraform-aws-platform-edp\ncd edp-terraform-aws-platform-edp/s3-backend\n
Fill the input variables for Terraform run in the s3-backend/template.tfvars
file, refer to the s3-backend/example.tfvars as an example.
# -- e.g eu-central-1\nregion = \"<REGION>\" # mandatory\n\ntags = {\n \"SysName\" = \"Terraform-Backend\"\n \"SysOwner\" = \"owner@example.com\"\n \"Environment\" = \"EKS-TEST-CLUSTER\"\n} # isn't required\n
Find the detailed description of the variables in the s3-backend/variables.tf file. Run Terraform apply. Initialize the backend and apply the changes.
terraform init\nterraform apply -var-file=./template.tfvars\n
View: Terraform output example Outputs:\n\nterraform_lock_table_dynamodb_id = \"terraform_locks\"\nterraform_states_s3_bucket_name = \"terraform-states-012345678910\"\n
(Optional) Commit the local state.
git add s3-backend/terraform.tfstate\ngit commit -m \"Terraform state for s3-backend\"\n
This step will do the following:
Take the following steps:
Navigate to IAM module directory.
cd ../iam\n
(Optional) Setup backend for store Terraform states remotely and support state locking and consistency checking via DynamoDB. Insert the missing fields in the file iam/providers.tf
.
...\n backend \"s3\" {\n bucket = \"terraform-states-<ACCOUNT_ID>\"\n key = \"<REGION>/<CLUSTER_NAME>/iam/terraform.tfstate\"\n region = \"<REGION>\"\n acl = \"bucket-owner-full-control\"\n dynamodb_table = \"terraform_locks\"\n encrypt = true\n }\n...\n
Note
If you plan to work with a local state, then comment out this block (the EDP team does not recommend this approach)
Fill in the input variables for Terraform run in the iam/template.tfvars
file. Use the iam/example.tfvars as an example. Please find the detailed description of the variables in the iam/variables.tf file.
# Template file to use as an example to create terraform.tfvars file. Fill the gaps instead of <...>\n# More details on each variable can be found in the variables.tf file\n\n# -- Condition to create or not IAM role for cluster deploy\ncreate_iam_deployer = true\n\n# -- Condition to create or not IAM role for Kaniko deploy\n# -- Need in case if used ECR registry. Create it after deploy EKS CLuster\ncreate_iam_kaniko = false\n\n# -- Worker and Deployer role variables\n\n# -- e.g eu-central-1\nregion = \"<REGION>\" # mandatory\n\n# -- Information about boundary policies\n# -- https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html\niam_permissions_boundary_policy_arn = \"arn:aws:iam::<AWS_ACCOUNT_ID>:policy/eo_role_boundary\" # mandatory\n\ntags = \"\" # isn't mandatory\n\n# -- Kaniko role variables\n\n# -- More information\n# -- https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html\ncluster_oidc_issuer_url = \"https://oidc.eks.<AWS_REGION>.amazonaws.com/id/<AWS_OIDC_ID>\"\n\noidc_provider_arn = \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.eks.<AWS_REGION>.amazonaws.com/id/<AWS_OIDC_ID>\"\n\nnamespace = \"edp\"\n
Initialize the backend and apply the changes.
terraform init\nterraform apply -var-file=./template.tfvars\n
View: Terraform output example Outputs:\n\nkaniko_iam_role_arn = []\nkaniko_iam_role_name = []\ndeployer_iam_role_arn = [\n \"arn:aws:iam::012345678910:role/EKSDeployerRole\",\n]\ndeployer_iam_role_name = [\n \"EKSDeployerRole\",\n]\n
This step will do the following:
Take the following steps:
Navigate to VPC module directory.
cd ../vpc\n
(Optional) Setup backend for store Terraform states remotely and support state locking and consistency checking via DynamoDB. Insert the missing fields in the file vpc/providers.tf
.
...\n backend \"s3\" {\n bucket = \"terraform-states-<ACCOUNT_ID>\"\n key = \"<REGION>/<CLUSTER_NAME>/vpc/terraform.tfstate\"\n region = \"<REGION>\"\n acl = \"bucket-owner-full-control\"\n dynamodb_table = \"terraform_locks\"\n encrypt = true\n }\n...\n
Note
If you plan to work with a local state, then comment out this block (the EDP team does not recommend this approach)
Fill in the input variables for Terraform run in the vpc/template.tfvars
file. Use the vpc/example.tfvars as an example. Please find the detailed description of the variables in the vpc/variables.tf file.
# -- e.g eu-central-1\nregion = \"<REGION>\"\n\nrole_arn = \"arn:aws:iam::<ACCOUNT_ID>:role/EKSDeployerRole\"\n\nplatform_name = \"<PLATFORM_NAME>\"\n\n# -- VPC CIDR, e.g. \"10.0.0.0/16\"\nplatform_cidr = \"<PLATFORM_CIDR>\"\n\n# -- VPC Subnets AZs, e.g. [\"eu-central-1a\", \"eu-central-1b\", \"eu-central-1c\"]\nsubnet_azs = [\"<SUBNET_AZS1>\", \"<SUBNET_AZS2>\"]\n\n# -- Private Subnets CIDR, e.g. [\"10.0.1.0/24\", \"10.0.2.0/24\", \"10.0.3.0/24\"]\nprivate_cidrs = [\"<PRIVATE_CIDRS1>\", \"<PRIVATE_CIDRS2>\"]\n\n# -- Private Subnets CIDR, e.g. [\"10.0.101.0/24\", \"10.0.102.0/24\", \"10.0.103.0/24\"]\npublic_cidrs = [\"<PUBLIC_CIDRS1>\", \"<PUBLIC_CIDRS2>\"]\n\n# -- Tags for resources, isn't mandatory\ntags = \"\"\n
Initialize the backend and apply the changes.
terraform init\nterraform apply -var-file=./template.tfvars\n
View: Terraform output example Outputs:\n\nprivate_subnets = [\n \"subnet-012345678910\",\n \"subnet-012345678910\",\n \"subnet-012345678910\",\n]\npublic_subnets = [\n \"subnet-012345678910\",\n \"subnet-012345678910\",\n \"subnet-012345678910\",\n]\nvpc_id = \"vpc-012345678910\"\n
This step will do the following:
Take the following steps:
Navigate to EKS module directory.
cd ../eks\n
(Optional) Setup backend for store Terraform states remotely and support state locking and consistency checking via DynamoDB. Insert the missing fields in the file eks/providers.tf
.
...\n backend \"s3\" {\n bucket = \"terraform-states-<ACCOUNT_ID>\"\n key = \"<REGION>/<CLUSTER_NAME>/eks/terraform.tfstate\"\n region = \"<REGION>\"\n acl = \"bucket-owner-full-control\"\n dynamodb_table = \"terraform_locks\"\n encrypt = true\n }\n...\n
Note
If you plan to work with a local state, then comment out this block (the EDP team does not recommend this approach)
Fill in the input variables for Terraform run in the eks/template.tfvars
file. Use the eks/example.tfvars as an example. Please find the detailed description of the variables in the eks/variables.tf file.
# -- e.g eu-central-1\nregion = \"<REGION>\"\nplatform_name = \"<PLATFORM_NAME>\"\nplatform_domain_name = \"<PLATFORM_DNS>\"\n\nrole_arn = \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/EKSDeployerRole\"\nrole_permissions_boundary_arn = \"arn:aws:iam::<AWS_ACCOUNT_ID>:policy/eo_role_boundary\"\n\nvpc_id = \"<VPC_ID>\" # VPC ID\nprivate_subnets_id = [] # EKS must have two subnets.\npublic_subnets_id = [] # ALB must have two subnets.\n\ninfra_public_security_group_ids = [] # List with security groups\n\n# -- Parameter in AWS Parameter Store that contain data in format \"account:token\" in base64 format\nadd_userdata = <<EOF\nexport TOKEN=$(aws ssm get-parameter --name <PARAMETER_NAME> --query 'Parameter.Value' --region <REGION> --output text)\ncat <<DATA > /var/lib/kubelet/config.json\n{\n \"auths\":{\n \"https://index.docker.io/v1/\":{\n \"auth\":\"$TOKEN\"\n }\n }\n}\nDATA\nEOF\n\nspot_instance_types = [] # list with instance types\n\naws_auth_users = [] # -- AWS List users\ntags = \"\"\n\nenable_argocd = true\n\nargocd_manage_add_ons = true\n\neks_addons_repo_ssh_key_secret_name = \"<AWS_SECRET_MANAGER_KEY>\" # ssh key with add-ons repository\n\nrepo_url = \"<SSH_REPO_URL>\" # repository with add-ons\n\naddons_path = \"<ADD_ONS_FOLDER>\" # path to add-ons folder at repository\n\n# OIDC Identity provider\ncluster_identity_providers = {}\n
This section contains variables to configure addons approach. Please find the detailed description about EDP addons.
Setup Argo CD for work with addons and store and management cluster applications using the GitOps approach. Fill in the input variables in the file eks/values/argocd-values.yaml.
configs:\n ssh:\n knownHosts: |\n # -- list of known host in format:\n # [host]:port key-type key\n # Example\n # [ssh.github.com]:443 ssh-rsa qgSdfOuiYhew/+afhQnvjfjhnhnqgSdfOuiYhew/+afhQnvjfjhnhn\n...\nserver:\n ingress:\n hosts:\n - \"argocd.example.com\"\n
Update local Kubernetes configuration:
aws eks update-kubeconfig --region <REGION> --name <CLUSTER_NAME>\n
After following the instructions provided, you should be able to configure AWS and create an EKS cluster with installed base utilities.
"},{"location":"operator-guide/deploy-aws-eks/#related-articles","title":"Related Articles","text":"This instruction provides detailed information on the OKD 4.10 cluster deployment in the AWS Cloud and contains the additional setup necessary for the managed infrastructure.
A full description of the cluster deployment can be found in the official documentation.
"},{"location":"operator-guide/deploy-okd-4.10/#prerequisites","title":"Prerequisites","text":"Before the OKD cluster deployment and configuration, make sure to check the prerequisites.
"},{"location":"operator-guide/deploy-okd-4.10/#required-tools","title":"Required Tools","text":"Install the following tools listed below:
Create the AWS IAM user with the required permissions. Make sure the AWS account is active, and the user doesn't have a permission boundary. Remove any Service Control Policy (SCP) restrictions from the AWS account.
Generate a key pair for cluster node SSH access. Please perform the steps below:
ssh-keygen -t ed25519 -N '' -f <path>/<file_name>\n
eval \"$(ssh-agent -s)\"\n
ssh-add <path>/<file_name>\n
Build the ccoctl
tool:
cloud-credential-operator
repository.git clone https://github.com/openshift/cloud-credential-operator.git\n
cloud-credential-operator
folder and build the ccoctl
tool.cd cloud-credential-operator && git checkout release-4.10\nGO_PACKAGE='github.com/openshift/cloud-credential-operator'\ngo build -ldflags \"-X $GO_PACKAGE/pkg/version.versionFromGit=$(git describe --long --tags --abbrev=7 --match 'v[0-9]*')\" ./cmd/ccoctl\n
Before deploying the OKD cluster, please perform the steps below:
"},{"location":"operator-guide/deploy-okd-4.10/#create-aws-resources","title":"Create AWS Resources","text":"Create the AWS resources with the Cloud Credential Operator utility (the ccoctl
tool):
Generate the public and private RSA key files that are used to set up the OpenID Connect identity provider for the cluster:
./ccoctl aws create-key-pair\n
Create an OpenID Connect identity provider and an S3 bucket on AWS:
./ccoctl aws create-identity-provider \\\n--name=<NAME> \\\n--region=<AWS_REGION> \\\n--public-key-file=./serviceaccount-signer.public\n
where:
Create the IAM roles for each component in the cluster:
Extract the list of the CredentialsRequest
objects from the OpenShift Container Platform release image:
oc adm release extract \\\n--credentials-requests \\\n--cloud=aws \\\n--to=./credrequests \\\n--quay.io/openshift-release-dev/ocp-release:4.10.25-x86_64\n
Note
A version of the openshift-release-dev docker image can be found in the Quay registry.
ccoctl
tool to process all CredentialsRequest
objects in the credrequests
directory:ccoctl aws create-iam-roles \\\n--name=<NAME> \\\n--region=<AWS_REGION> \\\n--credentials-requests-dir=./credrequests\n--identity-provider-arn=arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<NAME>-oidc.s3.<AWS_REGION>.amazonaws.com\n
Before deploying the OKD cluster, please perform the steps below:
Download the OKD installer.
Extract the installation program:
tar -xvf openshift-install-linux.tar.gz\n
Download the installation pull secret for any private registry. This pull secret allows to authenticate with the services that are provided by the authorities, including Quay.io, serving the container images for OKD components. For example, here is a pull secret for Docker Hub:
The pull secret for the private registry{\n \"auths\":{\n \"https://index.docker.io/v1/\":{\n \"auth\":\"$TOKEN\"\n }\n }\n}\n
Create a deployment directory and the install-config.yaml file:
mkdir okd-deployment\ntouch okd-deployment/install-config.yaml\n
To specify more details about the OKD cluster platform or to modify the values of the required parameters, customize the install-config.yaml file for the AWS. Please see below an example of the customized file:
install-config.yaml - OKD cluster\u2019s platform installation configuration fileapiVersion: v1\nbaseDomain: <YOUR_DOMAIN>\ncredentialsMode: Manual\ncompute:\n- architecture: amd64\n hyperthreading: Enabled\n name: worker\n platform:\n aws:\n rootVolume:\n size: 30\n zones:\n - eu-central-1a\n type: r5.large\n replicas: 3\ncontrolPlane:\n architecture: amd64\n hyperthreading: Enabled\n name: master\n platform:\n aws:\n rootVolume:\n size: 50\n zones:\n - eu-central-1a\n type: m5.xlarge\n replicas: 3\nmetadata:\n creationTimestamp: null\n name: 4-10-okd-sandbox\nnetworking:\n clusterNetwork:\n - cidr: 10.128.0.0/14\n hostPrefix: 23\n machineNetwork:\n - cidr: 10.0.0.0/16\n networkType: OVNKubernetes\n serviceNetwork:\n - 172.30.0.0/16\nplatform:\n aws:\n region: eu-central-1\n userTags:\n user:tag: 4-10-okd-sandbox\npublish: External\npullSecret: <PULL_SECRET>\nsshKey: |\n <SSH_KEY>\n
where:
Create the required OpenShift Container Platform installation manifests:
./openshift-install create manifests --dir okd-deployment\n
Copy the manifests generated by the ccoctl
tool to the manifests
directory created by the installation program:
cp ./manifests/* ./okd-deployment/manifests/\n
Copy the private key generated in the tls
directory by the ccoctl
tool to the installation directory:
cp -a ./tls ./okd-deployment\n
To initialize the cluster deployment, run the following command:
./openshift-install create cluster --dir okd-deployment --log-level=info\n
Note
If the cloud provider account configured on the host does not have sufficient permissions to deploy the cluster, the installation process stops, and the missing permissions are displayed.
When the cluster deployment is completed, directions for accessing the cluster are displayed in the terminal, including a link to the web console and credentials for the kubeadmin user. The kubeconfig
for the cluster will be located in okd-deployment/auth/kubeconfig.
...\nINFO Install complete!\nINFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/home/myuser/install_dir/auth/kubeconfig'\nINFO Access the OpenShift web-console here: https://console-openshift-console.apps.mycluster.example.com\nINFO Login to the console with the user: \"kubeadmin\", and password: \"4vYBz-Ee6gm-ymBZj-Wt5AL\"\nINFO Time elapsed: 36m22s:\n
Warning
The Ignition config files contain certificates that expire after 24 hours, which are then renewed at that time. Do not turn off the cluster for this time, or you will have to update the certificates manually. See OpenShift Container Platform documentation for more information.
"},{"location":"operator-guide/deploy-okd-4.10/#log-into-the-cluster","title":"Log Into the Cluster","text":"To log into the cluster, export the kubeconfig
:
export KUBECONFIG=<installation_directory>/auth/kubeconfig\n
Optionally, use the Lens tool for further work with the Kubernetes cluster.
Note
To install and manage the cluster, refer to Lens documentation.
"},{"location":"operator-guide/deploy-okd-4.10/#manage-okd-cluster-without-the-inbound-rules","title":"Manage OKD Cluster Without the Inbound Rules","text":"In order to manage the OKD cluster without the 0.0.0.0/0
inbound rules, please perform the steps below:
Create a Security Group with a list of your external IPs:
aws ec2 create-security-group --group-name <SECURITY_GROUP_NAME> --description \"<DESCRIPTION_OF_SECURITY_GROUP>\" --vpc-id <VPC_ID>\naws ec2 authorize-security-group-ingress \\\n--group-id '<SECURITY_GROUP_ID>' \\\n--ip-permissions 'IpProtocol=all,PrefixListIds=[{PrefixListId=<PREFIX_LIST_ID>}]'\n
Manually attach this new Security Group to all master nodes of the cluster.
Create another Security Group with an Elastic IP of the Cluster VPC:
aws ec2 create-security-group --group-name custom-okd-4-10 --description \"Cluster Ip to 80, 443\" --vpc-id <VPC_ID>\naws ec2 authorize-security-group-ingress \\\n --group-id '<SECURITY_GROUP_ID>' \\\n --protocol all \\\n --port 80 \\\n --cidr <ELASTIC_IP_OF_CLUSTER_VPC>\naws ec2 authorize-security-group-ingress \\\n --group-id '<SECURITY_GROUP_ID>' \\\n --protocol all \\\n --port 443 \\\n --cidr <ELASTIC_IP_OF_CLUSTER_VPC>\n
Modify the cluster load balancer via the router-default
svc in the openshift-ingress
namespace, paste two Security Groups created on previous steps:
apiVersion: v1\nkind: Service\nmetadata:\n name: router-default\n namespace: openshift-ingress\n annotations:\n service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: \"tag_name=some_value\"\n service.beta.kubernetes.io/aws-load-balancer-security-groups: \"<SECURITY_GROUP_IDs>\"\n ...\n
In order to optimize the usage of Spot Instances on the AWS, add the following line under the providerSpec
field in the MachineSet of Worker Nodes:
providerSpec:\n value:\n spotMarketOptions: {}\n
"},{"location":"operator-guide/deploy-okd-4.10/#related-articles","title":"Related Articles","text":"This instruction provides detailed information on the OKD 4.9 cluster deployment in the AWS Cloud and contains the additional setup necessary for the managed infrastructure.
A full description of the cluster deployment can be found in the official documentation.
"},{"location":"operator-guide/deploy-okd/#prerequisites","title":"Prerequisites","text":"Before the OKD cluster deployment and configuration, make sure to check the prerequisites.
"},{"location":"operator-guide/deploy-okd/#required-tools","title":"Required Tools","text":"Install the following tools listed below:
Create the AWS IAM user with the required permissions. Make sure the AWS account is active, and the user doesn't have a permission boundary. Remove any Service Control Policy (SCP) restrictions from the AWS account.
Generate a key pair for cluster node SSH access. Please perform the steps below:
ssh-keygen -t ed25519 -N '' -f <path>/<file_name>\n
eval \"$(ssh-agent -s)\"\n
ssh-add <path>/<file_name>\n
Before deploying the OKD cluster, please perform the steps below:
Download the OKD installer.
Extract the installation program:
tar -xvf openshift-install-linux.tar.gz\n
Download the installation pull secret for any private registry.
This pull secret allows to authenticate with the services that are provided by the included authorities, including Quay.io serving container images for OKD components. For example, here is a pull secret for Docker Hub:
The pull secret for the private registry{\n \"auths\":{\n \"https://index.docker.io/v1/\":{\n \"auth\":\"$TOKEN\"\n }\n }\n}\n
Create the deployment directory and the install-config.yaml file:
mkdir okd-deployment\ntouch okd-deployment/install-config.yaml\n
To specify more details about the OKD cluster platform or to modify the values of the required parameters, customize the install-config.yaml file for AWS. Please see an example of the customized file below:
install-config.yaml - OKD cluster\u2019s platform installation configuration fileapiVersion: v1\nbaseDomain: <YOUR_DOMAIN>\ncompute:\n- architecture: amd64\n hyperthreading: Enabled\n name: worker\n platform:\n aws:\n zones:\n - eu-central-1a\n rootVolume:\n size: 50\n type: r5.large\n replicas: 3\ncontrolPlane:\n architecture: amd64\n hyperthreading: Enabled\n name: master\n platform:\n aws:\n rootVolume:\n size: 50\n zones:\n - eu-central-1a\n type: m5.xlarge\n replicas: 3\nmetadata:\n creationTimestamp: null\n name: 4-9-okd-sandbox\nplatform:\n aws:\n region: eu-central-1\n userTags:\n user:tag: 4-9-okd-sandbox\npublish: External\npullSecret: <PULL_SECRET>\nsshKey: |\n <SSH_KEY>\n
where:
To initialize the cluster deployment, run the following command:
./openshift-install create cluster --dir <installation_directory> --log-level=info\n
Note
If the cloud provider account configured on the host does not have sufficient permissions to deploy the cluster, the installation process stops, and the missing permissions are displayed.
When the cluster deployment is completed, directions for accessing the cluster are displayed in the terminal, including a link to the web console and credentials for the kubeadmin user. The kubeconfig
for the cluster will be located in okd-deployment/auth/kubeconfig.
...\nINFO Install complete!\nINFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/home/myuser/install_dir/auth/kubeconfig'\nINFO Access the OpenShift web-console here: https://console-openshift-console.apps.mycluster.example.com\nINFO Login to the console with the user: \"kubeadmin\", and password: \"4vYBz-Ee6gm-ymBZj-Wt5AL\"\nINFO Time elapsed: 36m22s:\n
Warning
The Ignition config files contain certificates that expire after 24 hours, which are then renewed at that time. Do not turn off the cluster for this time, or you will have to update the certificates manually. See OpenShift Container Platform documentation for more information.
"},{"location":"operator-guide/deploy-okd/#log-into-the-cluster","title":"Log Into the Cluster","text":"To log into the cluster, export the kubeconfig
:
export KUBECONFIG=<installation_directory>/auth/kubeconfig\n
Optionally, use the Lens tool for further work with the Kubernetes cluster.
Note
To install and manage the cluster, refer to Lens documentation.
"},{"location":"operator-guide/deploy-okd/#related-articles","title":"Related Articles","text":"The Amazon Elastic Block Store (Amazon EBS) Container Storage Interface (CSI) driver allows Amazon Elastic Kubernetes Service (Amazon EKS) clusters to manage the lifecycle of Amazon EBS volumes for Kubernetes Persistent Volumes.
"},{"location":"operator-guide/ebs-csi-driver/#prerequisites","title":"Prerequisites","text":"An existing AWS Identity and Access Management (IAM) OpenID Connect (OIDC) provider for your cluster. To determine whether you already have an OIDC provider or to create a new one, see Creating an IAM OIDC provider for your cluster.
To add an Amazon EBS CSI add-on, please follow the steps below:
Check your cluster details (the random value in the cluster name will be required in the next step):
kubectl cluster-info\n
Create Kubernetes IAM Trust Policy for Amazon EBS CSI Driver. Replace AWS_ACCOUNT_ID
with your account ID, AWS_REGION
with your AWS Region, and EXAMPLED539D4633E53DE1B71EXAMPLE
with the value that was returned in the previous step. Save this Trust Policy into a file aws-ebs-csi-driver-trust-policy.json
.
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::AWS_ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud\": \"sts.amazonaws.com\",\n \"oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub\": \"system:serviceaccount:kube-system:ebs-csi-controller-sa\"\n }\n }\n }\n ]\n }\n
To get the notion of the IAM Role creation, please refer to the official documentation.
Create the IAM role, for example:
aws iam create-role \\\n --role-name AmazonEKS_EBS_CSI_DriverRole \\\n --assume-role-policy-document file://\"aws-ebs-csi-driver-trust-policy.json\"\n
Attach the required AWS Managed Policy AmazonEBSCSIDriverPolicy
to the role with the following command:
aws iam attach-role-policy \\\n --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \\\n --role-name AmazonEKS_EBS_CSI_DriverRole\n
Add the Amazon EBS CSI add-on using the AWS CLI. Replace my-cluster
with the name of your cluster, AWS_ACCOUNT_ID
with your account ID, and AmazonEKS_EBS_CSI_DriverRole
with the name of the role that was created earlier:
aws eks create-addon --cluster-name my-cluster --addon-name aws-ebs-csi-driver \\\n --service-account-role-arn arn:aws:iam::AWS_ACCOUNT_ID:role/AmazonEKS_EBS_CSI_DriverRole\n
Note
When the plugin is deployed, it creates the ebs-csi-controller-sa
service account. The service account is bound to a Kubernetes ClusterRole
with the required Kubernetes permissions. The ebs-csi-controller-sa
service account should already be annotated with arn:aws:iam::AWS_ACCOUNT_ID:role/AmazonEKS_EBS_CSI_DriverRole
. To check the annotation, please run:
kubectl get sa ebs-csi-controller-sa -n kube-system -o=jsonpath='{.metadata.annotations}'\n
In case pods have errors, restart the ebs-csi-controller
deployment:
kubectl rollout restart deployment ebs-csi-controller -n kube-system\n
EDP uses two different methods to regulate access to resources, each tailored to specific scenarios:
roles
and groups
in Keycloak and is used for SonarQube and partly for Nexus.EDP custom resources
. This approach requires modifying custom resources that outline the required access privileges for every user or group and is used to govern access to Gerrit, Nexus, EDP Portal, EKS Cluster and Argo CD.Info
These two approaches are not interchangeable, as each has its unique capabilities.
"},{"location":"operator-guide/edp-access-model/#keycloak","title":"Keycloak","text":"This section explains what realm roles and realm groups are and how they function within Keycloak.
"},{"location":"operator-guide/edp-access-model/#realm-roles","title":"Realm Roles","text":"The Keycloak realm of edp
has two realm roles with a composite types named administrator
and developer
:
administrator
realm role is designed for users who need administrative access to the tools used in the project. This realm role contains the sonar-administrators
role. Users who are assigned the administrator
realm role will be granted these two roles automatically.developer
realm role, on the other hand, is designed for users who need access to the development tools used in the project. This realm role also contains the sonar-developers
role. Users who are assigned the developer
realm role will be granted these two roles automatically.These realm roles have been defined to make it easier to assign groups of rights to users.
The table below shows the realm roles and the composite types they relate to.
Realm Role Name Regular Role Composite role administrator developer sonar-administrators sonar-developers"},{"location":"operator-guide/edp-access-model/#realm-groups","title":"Realm Groups","text":"EDP uses two different realms for group management, edp
and openshift
:
edp
realm contains two groups that are specifically used for controlling access to Argo CD. These groups are named ArgoCDAdmins
and ArgoCD-edp-users
.openshift
realm contains five groups that are used for access control in both the EDP Portal and EKS cluster. These groups are named edp-oidc-admins
, edp-oidc-builders
, edp-oidc-deployers
,edp-oidc-developers
and edp-oidc-viewers
.edp
ArgoCD-edp-users
edp
edp-oidc-admins
openshift edp-oidc-builders
openshift edp-oidc-deployers
openshift edp-oidc-developers
openshift edp-oidc-viewers
openshift"},{"location":"operator-guide/edp-access-model/#sonarqube","title":"SonarQube","text":"In the case of SonarQube, there are two ways to manage access: via Keycloak and via EDP approach. This sections describes both of the approaches.
"},{"location":"operator-guide/edp-access-model/#manage-access-via-keycloak","title":"Manage Access via Keycloak","text":"SonarQube access is managed using Keycloak roles in the edp
realm. The sonar-developers
and sonar-administrators
realm roles are the two available roles that determine user access levels. To grant access, the corresponding role must be added to the user in Keycloak.
For example, a user who needs developer access to SonarQube should be assigned the sonar-developers
or developer
composite role in Keycloak.
EDP provides its own SonarQube Permission Template, which is used to manage user access and permissions for SonarQube projects.
The template is stored in the custom SonarQube resource of the operator, an example of a custom resource can be found below.
SonarPermissionTemplate
apiVersion: v2.edp.epam.com/v1\nkind: SonarPermissionTemplate\nmetadata:\n name: edp-default\nspec:\n description: EDP permission templates (DO NOT REMOVE)\n groupPermissions:\n - groupName: non-interactive-users\n permissions:\n - user\n - groupName: sonar-administrators\n permissions:\n - admin\n - user\n - groupName: sonar-developers\n permissions:\n - codeviewer\n - issueadmin\n - securityhotspotadmin\n - user\n name: edp-default\n projectKeyPattern: .+\n sonarOwner: sonar\n
The SonarQube Permission Template contains three groups: non-interactive-users
, sonar-administrators
and sonar-developers
:
non-interactive-users
are users who do not require direct access to the SonarQube project but need to be informed about the project's status and progress. This group has read-only access to the project, which means that they can view the project's data and metrics but cannot modify or interact with it in any way.sonar-administrators
are users who have full control over the SonarQube project. They have the ability to create, modify, and delete projects, as well as manage user access and permissions. This group also has the ability to configure SonarQube settings and perform other administrative tasks.sonar-developers
are users who are actively working on the SonarQube project. They have read and write access to the project, which means that they can modify the project's data and metrics. This group also has the ability to configure project-specific settings and perform other development tasks.These groups are designed to provide different levels of access to the SonarQube project, depending on the user's role and responsibilities.
Info
If a user has no group, it will have the sonar-users
group by default. This group does not have any permissions in the edp-default
Permission Template.
The permissions that are attached to each of the groups are described below in the table:
Group Name Permissionsnon-interactive-users
user sonar-administrators
admin, user sonar-developers
codeviewer, issueadmin, securityhotspotadmin, user sonar-users
-"},{"location":"operator-guide/edp-access-model/#nexus","title":"Nexus","text":"Users authenticate to Nexus using their Keycloak credentials.
During the authentication process, the OAuth2-Proxy receives the user's role from Keycloak.
Info
Only users with either the administrator
or developer
role in Keycloak can access Nexus.
Nexus has four distinct roles available, including edp-admin
, edp-viewer
, nx-admin
and nx-anonymous
. To grant the user access to one or more of these roles, an entry must be added to the custom Nexus resource.
For instance, in the context of the custom Nexus resource, the user \"user_1@example.com\" has been assigned the \"nx-admin\" role. An example can be found below:
Nexus
apiVersion: v2.edp.epam.com/v1\nkind: Nexus\nmetadata:\n name: nexus\nspec:\n basePath: /\n edpSpec:\n dnsWildcard: example.com\n keycloakSpec:\n enabled: false\n roles:\n - developer\n - administrator\n users:\n - roles:\n - nx-admin\n username: user_1@example.com\n
"},{"location":"operator-guide/edp-access-model/#gerrit","title":"Gerrit","text":"The user should use their credentials from Keycloak when authenticating to Gerrit.
After logging into Gerrit, the user is not automatically attached to any groups. To add a user to a group, the GerritGroupMember
custom resource must be created. This custom resource specifies the user's email address and the name of the group to which they should be added.
The ConfigMap below is an example of the GerritGroupMember
resource:
GerritGroupMember
apiVersion: v2.edp.epam.com/v1\nkind: GerritGroupMember\nmetadata:\n name: user-admins\nspec:\n accountId: user@user.com\n groupId: Administrators\n
After the GerritGroupMember
resource is created, the user will have the permissions and access levels associated with that group.
Both Portal and EKS Cluster use Keycloak groups for controlling access. Users need to be added to the required group in Keycloak to get access. The groups that are used for access control are in the openshift
realm.
Note
The openshift
realm is used because a Keycloak client for OIDC is in this realm.
There are two types of groups provided for users:
For example, the edp-oidc-viewers
group can be extended with rights from the edp-oidc-builders
group.
edp-oidc-admins
edp-oidc-developers
edp-oidc-viewers
edp-oidc-builders
edp-oidc-deployers
Name Action List View Getting of all namespaced resources Build Starting a PipelineRun from EDP Portal UI Deploy Deploying a new version of application via Argo CD Application Group Name View Build Deploy Full Namespace Access edp-oidc-admins
edp-oidc-developers
edp-oidc-viewers
edp-oidc-builders
edp-oidc-deployers
"},{"location":"operator-guide/edp-access-model/#cluster-rbac-resources","title":"Cluster RBAC Resources","text":"The edp
namespace has five role bindings that provide the necessary permissions for the Keycloak groups described above.
edp-oidc-admins
tenant-builder tenant-builder edp-oidc-builders
tenant-deployer tenant-deployer edp-oidc-deployers
tenant-developer tenant-developer edp-oidc-developers
tenant-viewer view edp-oidc-viewers
, edp-oidc-developers
Note
EDP provides an aggregate ClusterRole with permissions to view custom EDP resources. ClusterRole is named edp-aggregate-view-edp
Info
The tenant-admin
RoleBinding will be created in a created namespace by cd-pipeline-operator
. tenant-admin
RoleBinding assign the admin
role to edp-oidc-admins
and edp-oidc-developers
groups.
To provide users with admin or developer privileges for project namespaces, they need to be added to the edp-oidc-admins
and edp-oidc-developers
groups in Keycloak.
In Argo CD, groups are specified when creating an AppProject to restrict access to deployed applications. To gain access to deployed applications within a project, the user must be added to their corresponding Argo CD group in Keycloak. This ensures that only authorized users can access and modify applications within the project.
Info
By default, only the ArgoCDAdmins
group is automatically created in Keycloak.
Explore the way Kiosk, a multi-tenancy extension for Kubernetes, is used in EDP.
"},{"location":"operator-guide/edp-kiosk-usage/#prerequisites","title":"Prerequisites","text":"Kiosk usage
Agenda
edp
installation of EDP generates new Kiosk Space resource that is linked to edp Kiosk Account;This page is a detailed guide on integrating Keycloak with the edp-keycloak-operator to serve as an identity provider for AWS Elastic Kubernetes Service (EKS). It provides step-by-step instructions for creating necessary realms, users, roles, and client configurations for a seamless Keycloak-EKS collaboration. Additionally, it includes guidelines on installing the edp-keycloak-operator using Helm charts.
"},{"location":"operator-guide/eks-oidc-integration/#prerequisites","title":"Prerequisites","text":"To prepare Keycloak for integration with the edp-keycloak-operator, follow the steps below:
Ensure that the openshift realm is created.
Create the orchestrator user and set the password in the Master realm.
In the Role Mapping tab, assign the proper roles to the user:
Realm Roles:
Client Roles openshift-realm
:
Role mappings
"},{"location":"operator-guide/eks-oidc-integration/#install-keycloak-operator","title":"Install Keycloak Operator","text":"To install the Keycloak operator, follow the steps below:
Add the epamedp
Helm chart to a local client:
helm repo add epamedp https://epam.github.io/edp-helm-charts/stable\nhelm repo update\n
Install the Keycloak operator:
helm install keycloak-operator epamedp/keycloak-operator --namespace security --set name=keycloak-operator\n
The next stage after installing Keycloak is to integrate it with the Keycloak operator. It can be implemented with the following steps:
Create the keycloak secret that will contain username and password to perform the integration. Set your own password. The username must be orchestrator:
kubectl -n security create secret generic keycloak \\\n --from-literal=username=orchestrator \\\n --from-literal=password=<password>\n
Create the Keycloak Custom Resource with the Keycloak instance URL and the secret created in the previous step:
apiVersion: v1.edp.epam.com/v1\nkind: Keycloak\nmetadata:\n name: main\n namespace: security\nspec:\n secret: keycloak # Secret name\n url: https://keycloak.example.com # Keycloak URL\n
Create the KeycloakRealm Custom Resource:
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealm\nmetadata:\n name: control-plane\n namespace: security\nspec:\n realmName: control-plane\n keycloakOwner: main\n
Create the KeycloakRealmGroup Custom Resource for both administrators and developers:
administratorsdevelopersapiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmGroup\nmetadata:\n name: administrators\n namespace: security\nspec:\n realm: control-plane\n name: eks-oidc-administrator\n
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmGroup\nmetadata:\n name: developers\n namespace: security\nspec:\n realm: control-plane\n name: eks-oidc-developers\n
Create the KeycloakClientScope Custom Resource:
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakClientScope\nmetadata:\n name: groups-keycloak-eks\n namespace: security\nspec:\n name: groups\n realm: control-plane\n description: \"Group Membership\"\n protocol: openid-connect\n protocolMappers:\n - name: groups\n protocol: openid-connect\n protocolMapper: \"oidc-group-membership-mapper\"\n config:\n \"access.token.claim\": \"true\"\n \"claim.name\": \"groups\"\n \"full.path\": \"false\"\n \"id.token.claim\": \"true\"\n \"userinfo.token.claim\": \"true\"\n
Create the KeycloakClient Custom Resource:
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakClient\nmetadata:\n name: eks\n namespace: security\nspec:\n advancedProtocolMappers: true\n clientId: eks\n directAccess: true\n public: false\n defaultClientScopes:\n - groups\n targetRealm: control-plane\n webUrl: \"http://localhost:8000\"\n
Create the KeycloakRealmUser Custom Resource for both administrator and developer roles:
administrator roledeveloper roleapiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmUser\nmetadata:\n name: keycloakrealmuser-sample\n namespace: security\nspec:\n realm: control-plane\n username: \"administrator\"\n firstName: \"John\"\n lastName: \"Snow\"\n email: \"administrator@example.com\"\n enabled: true\n emailVerified: true\n password: \"12345678\"\n keepResource: true\n requiredUserActions:\n - UPDATE_PASSWORD\n groups:\n - eks-oidc-administrator\n
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmUser\nmetadata:\n name: keycloakrealmuser-sample\n namespace: security\nspec:\n realm: control-plane\n username: \"developers\"\n firstName: \"John\"\n lastName: \"Snow\"\n email: \"developers@example.com\"\n enabled: true\n emailVerified: true\n password: \"12345678\"\n keepResource: true\n requiredUserActions:\n - UPDATE_PASSWORD\n groups:\n - eks-oidc-developers\n
As a result, Keycloak is integrated with the AWS Elastic Kubernetes Service. This integration enables users to log in to the EKS cluster effortlessly using their kubeconfig files while managing permissions through Keycloak.
This page contains accurate information on how to associate an IAM role with the service account (IRSA) in EPAM Delivery Platform.
Get acquainted with the AWS Official Documentation on the subject before proceeding.
"},{"location":"operator-guide/enable-irsa/#common-configuration-of-iam-roles-with-service-accounts","title":"Common Configuration of IAM Roles With Service Accounts","text":"To successfully associate the IAM role with the service account, follow the steps below:
Create an IAM role that will further be associated with the service account. This role must have the following trust policy:
IAM Role
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER>\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"<OIDC_PROVIDER>:sub\": \"system:serviceaccount:<SERVICE_ACCOUNT_NAMESPACE>:<SERVICE_ACCOUNT_NAME>\"\n }\n }\n }\n ]\n}\n
View cluster's \u2039OIDC_PROVIDER\u203a URL.
aws eks describe-cluster --name <CLUSTER_NAME> --query \"cluster.identity.oidc.issuer\" --output text\n
Example output:
https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E\n
\u2039OIDC_PROVIDER\u203a in this example will be:
oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E\n
Deploy the amazon-eks-pod-identity-webhook v0.2.0.
Note
The amazon-eks-pod-identity-webhook functionality is provided out of the box in EKS v1.21 and higher. This does not apply if the cluster has been upgraded from older versions. Therefore, skip step 2 and continue from step 3 in this documentation.
2.1. Provide the stable(ed8c41f) version of the Docker image in the deploy/deployment-base.yaml file.
2.2. Provide ${CA_BUNDLE}_in the_deploy/mutatingwebhook.yaml file:
secret_name=$(kubectl -n default get sa default -o jsonpath='{.secrets[0].name}') \\\n CA_BUNDLE=$(kubectl -n default get secret/$secret_name -o jsonpath='{.data.ca\\.crt}' | tr -d '\\n')\n
2.3. Deploy the Webhook:
kubectl apply -f deploy/\n
2.4. Approve the csr:
csr_name=$(kubectl get csr -o jsonpath='{.items[?(@.spec.username==\"system:serviceaccount:default:pod-identity-webhook\")].metadata.name}')\n kubectl certificate approve $csr_name\n
Annotate the created service account with the IAM role:
Service Account
apiVersion: v1\n kind: ServiceAccount\n metadata:\n name: <SERVICE_ACCOUNT_NAME>\n namespace: <NAMESPACE>\n annotations:\n eks.amazonaws.com/role-arn: \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>\"\n
All newly launched pods with this service account will be modified and then use the associated IAM role. Find below the pod specification template:
Pod Template
apiVersion: v1\n kind: Pod\n metadata:\n name: irsa-test\n namespace: <POD_NAMESPACE>\n spec:\n serviceAccountName: <SERVICE_ACCOUNT_NAME>\n securityContext:\n fsGroup: 65534\n containers:\n - name: terraform\n image: epamedp/edp-jenkins-terraform-agent:3.0.9\n command: ['sh', '-c', 'aws sts \"get-caller-identity\" && sleep 3600']\n
Check the logs of the created pod from the template above.
Example output:
{\n \"UserId\": \"XXXXXXXXXXXXXXXXXXXXX:botocore-session-XXXXXXXXXX\",\n \"Account\": \"XXXXXXXXXXXX\",\n \"Arn\": \"arn:aws:sts::XXXXXXXXXXXX:assumed-role/AWSIRSATestRole/botocore-session-XXXXXXXXXX\"\n }\n
As a result, it is possible to perform actions in AWS under the AWSIRSATestRole role.
External Secrets Operator (ESO) can be integrated with EDP.
There are multiple Secrets Providers that can be used within ESO. EDP is integrated with two major providers:
EDP uses various secrets to integrate various applications. Below is a list of secrets that are used in the EPAM Delivery Platform and their description. All the secrets are encoded in Base64 format.
Secret Name Fields Description Used by keycloak usernamepassword Username and password with specific rights for EDP tenant in Keycloak keycloak-operator ci-defectdojo tokenurl DefectDojo tokenDefectDojo URL edp-tekton kaniko-docker-config .dockerconfigjson Serialized JSON that follows docker config patterns edp-tekton regcred .dockerconfigjson Serialized JSON that follows docker config patterns cd-pipeline-operator ci-github id_rsatokensecretString Private key from github repo API tokenRandom string edp-tekton ci-gitlab id_rsatokensecretString Private key from gitlab repo API tokenRandom string edp-tekton ci-jira usernamepassword Jira username Jira password edp-codebase-operator ci-sonarqube tokenurl SonarQube tokenSonarQube URL edp-tekton ci-nexus usernamepasswordurl Nexus usernameNexus passwordNexus URL edp-tekton ci-dependency-track tokenurl Dependency-Track tokenDependency-Track URL edp-tekton oauth2-proxy-cookie-secret cookie-secret Secret key for oauth2-proxy edp-install keycloak-client-headlamp-secret clientSecret Secret key for keycloak client keycloak-operator"},{"location":"operator-guide/external-secrets-operator-integration/#edp-core-secrets","title":"EDP Core Secrets","text":"The list below represents the baseline required for full operation within EDP:
These secrets are mandatory for Tekton pipelines to work properly.
"},{"location":"operator-guide/external-secrets-operator-integration/#kubernetes-provider","title":"Kubernetes Provider","text":"All secrets are stored in Kubernetes in pre-defined namespaces. EDP suggests using the following approach for secrets management:
EDP_NAMESPACE-vault
, where EDP_NAMESPACE is a name of the namespace where EDP is deployed, such as edp-vault
. This namespace is used by EDP platform. Access to secrets in the edp-vault
is permitted only for EDP Administrators
.EDP_NAMESPACE-cicd-vault
, where EDP_NAMESPACE is a name of the namespace where EDP is deployed, such as edp-cicd-vault
. Development team uses access to secrets in the edp-cicd-vault
for microservices development.See a diagram below for more details:
In order to install EDP, a list of passwords must be created. Secrets are provided automatically when using ESO.
Create a common namespace for secrets and EDP:
kubectl create namespace edp-vault\nkubectl create namespace edp\n
Create secrets in the edp-vault
namespace:
apiVersion: v1\nkind: Secret\nmetadata:\n name: keycloak\n namespace: edp-vault\ndata:\n password: cGFzcw== # pass in base64\n username: dXNlcg== # user in base64\ntype: Opaque\n
In the edp-vault
namespace, create a Role with a permission to read secrets:
apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n namespace: edp-vault\n name: external-secret-store\nrules:\n- apiGroups: [\"\"]\n resources:\n - secrets\n verbs:\n - get\n - list\n - watch\n- apiGroups:\n - authorization.k8s.io\n resources:\n - selfsubjectrulesreviews\n verbs:\n - create\n
In the edp-vault
namespace, create a ServiceAccount used by SecretStore
:
apiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: secret-manager\n namespace: edp\n
Connect the Role from the edp-vault
namespace with the ServiceAccount in the edp
namespace:
apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n name: eso-from-edp\n namespace: edp-vault\nsubjects:\n - kind: ServiceAccount\n name: secret-manager\n namespace: edp\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: Role\n name: external-secret-store\n
Create a SecretStore in the edp
namespace, and use ServiceAccount for authentication:
apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: edp-vault\n namespace: edp\nspec:\n provider:\n kubernetes:\n remoteNamespace: edp-vault # namespace with secrets\n auth:\n serviceAccount:\n name: secret-manager\n server:\n caProvider:\n type: ConfigMap\n name: kube-root-ca.crt\n key: ca.crt\n
Each secret must be defined by the ExternalSecret
object. A code example below creates the keycloak
secret in the edp
namespace based on a secret with the same name in the edp-vault
namespace:
apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: keycloak\n namespace: edp\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: edp-vault\n # target:\n # name: secret-to-be-created # name of the k8s Secret to be created. metadata.name used if not defined\n data:\n - secretKey: username # key to be created\n remoteRef:\n key: keycloak # remote secret name\n property: username # value will be fetched from this field\n - secretKey: password # key to be created\n remoteRef:\n key: keycloak # remote secret name\n property: password # value will be fetched from this field\n
Apply the same approach for enabling secrets management in the namespaces used for microservices development, such as sit
and qa
on the diagram above.
AWS SSM Parameter Store can be used as a Secret Provider for ESO. For EDP, it is recommended to use the IAM Roles For Service Accounts approach (see a diagram below).
"},{"location":"operator-guide/external-secrets-operator-integration/#aws-parameter-store-in-edp-scenario","title":"AWS Parameter Store in EDP Scenario","text":"In order to install EDP, a list of passwords must be created. Follow the steps below, to get secrets from the SSM:
In the AWS, create an AWS IAM policy and an IAM role used by ServiceAccount
in SecretStore
. The IAM role must have permissions to get values from the SSM Parameter Store.
a. Create an IAM policy that allows to get values from the Parameter Store with the edp/
path. Use your AWS Region
and AWS Account Id
:
{\n\"Version\": \"2012-10-17\",\n\"Statement\": [\n {\n \"Sid\": \"VisualEditor0\",\n \"Effect\": \"Allow\",\n \"Action\": \"ssm:GetParameter*\",\n \"Resource\": \"arn:aws:ssm:eu-central-1:012345678910:parameter/edp/*\"\n }\n]\n}\n
b. Create an AWS IAM role with trust relationships (defined below) and attach the IAM policy. Put your string for Federated
value (see more on IRSA enablement for EKS Cluster) and AWS region.
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::012345678910:oidc-provider/oidc.eks.eu-central-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXX\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringLike\": {\n \"oidc.eks.eu-central-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXX:sub\": \"system:serviceaccount:edp:*\"\n }\n }\n }\n ]\n}\n
Create a secret in the AWS Parameter Store with the name /edp/my-json-secret
. This secret is represented as a parameter of type string within the AWS Parameter Store:
{\n \"keycloak\":\n {\n \"username\": \"keycloak-username\",\n \"password\": \"keycloak-password\"\n },\n \"defectdojo-ciuser-token\":\n {\n \"token\": \"XXXXXXXXXXXX\",\n \"url\": \"https://defectdojo.example.com\"\n },\n \"kaniko-docker-config\":\n {\n \"auths\" :\n {\n \"registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"<base64 encoded 'user:secret' string>\"\n }\n }},\n \"regcred\":\n {\n \"auths\":\n {\n \"registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\":\"<base64 encoded 'user:secret' string>\"\n }\n }},\n \"github-config\":\n {\n \"id_rsa\": \"id-rsa-key\",\n \"token\": \"github-token\",\n \"secretString\": \"XXXXXXXXXXXX\"\n },\n \"gitlab-config\":\n {\n \"id_rsa\": \"id-rsa-key\",\n \"token\": \"gitlab-token\",\n \"secretString\": \"XXXXXXXXXXXX\"\n },\n \"jira-user\":\n {\n \"username\": \"jira-username\",\n \"password\": \"jira-password\"\n },\n \"sonar-ciuser-token\": { \"username\": \"<ci-user>\", \"secret\": \"<secret>\" },\n \"nexus-ci-user\": { \"username\": \"<ci.user>\", \"password\": \"<secret>\" },\n \"oauth2-proxy-cookie-secret\": { \"cookie-secret\": \"XXXXXXXXXXXX\" },\n \"nexus-proxy-cookie-secret\": { \"cookie-secret\": \"XXXXXXXXXXXX\" },\n \"keycloak-client-headlamp-secret\": \"XXXXXXXXXXXX\",\n \"keycloak-client-argo-secret\": \"XXXXXXXXXXXX\"\n}\n
Set External Secret operator enabled by updating the values.yaml file:
EDP install values.yamlexternalSecrets:\n enabled: true\n
Install/upgrade edp-install:
helm upgrade --install edp epamedp/edp-install --wait --timeout=900s \\\n--version <edp_version> \\\n--values values.yaml \\\n--namespace edp \\\n--atomic\n
A webhook enables third-party services like GitHub to send real-time updates to an application. Updates are triggered by an event or an action by the webhook provider (for example, a push to a repository, a Pull Request creation), and pushed to the application via HTTP requests, namely, Jenkins. The GitHub Jenkins job provisioner creates a webhook in the GitHub repository during the Create release pipeline once the Integrate GitHub/GitLab in Jenkins is enabled and the GitHub Webhook Configuration is completed.
The Jenkins setup in EDP uses the following plugins responsible for listening on GitHub webhooks:
In case of any issues with webhooks, try the following solutions:
Check that the firewalls are configured to accept the incoming traffic from the IP address range that is described in the GitHub documentation.
Check that GitHub Personal Access Token is correct and has sufficient scope permissions.
Check that the job has run at least once before using the hook (once an application is created in EDP, the build job should be run automatically in Jenkins).
Check that both Push and issue comment and Pull Request webhooks are created on the GitHub side (unlike GitLab, GitHub does not need separate webhooks for each branch):
Webhooks settings
Click each webhook and check if the event delivery is successful:
https://jenkins-the-host.com/github-webhook/
for the GitHub plugin and https://jenkins-the-host.com/ghprbhook/
for the GitHub Pull Request Builder.Check that the X-Hub-Signature secret is verified. It is provided by the Jenkins GitHub plugin for Push events and by the GitHub Pull Request Builder plugin for Pull Request events. The Secret field is optional. Nevertheless, if incorrect, it can prevent webhook events.
For the GitHub plugin (Push events):
For the GitHub Pull Request Builder (Pull Request events):
Redeliver events by clicking the Redeliver button and check the Response body.
Manage webhook
Note
Use Postman to debug webhooks. Add all headers to Postman from the webhook Request -> Headers field and send the payload (Request body) using the appropriate content type.
Examples for Push and Pull Request events:
Postman push event payload headers GitHub plugin push events
The response in the Jenkins log:
Jan 17, 2022 8:51:14 AM INFO org.jenkinsci.plugins.github.webhook.subscriber.PingGHEventSubscriber onEvent\nPING webhook received from repo <https://github.com/user-profile/user-repo>!\n
Postman pull request event payload headers GitHub pull request builder
The response in the Jenkins log:
Jan 17, 2022 8:17:53 AM FINE org.jenkinsci.plugins.ghprb.GhprbRootAction\nGot payload event: ping\n
Check that the repo pushing to Jenkins, the GitHub project URL in the project configuration, and the repos in the pipeline Job must be lined up.
Enable the GitHub hook trigger for GITScm polling for the Build job.
GitHub hook trigger
Enable the GitHub Pull Request Builder for the Code Review job.
GitHub pull request builder
Filter through Jenkins log by using Jenkins custom log recorder:
The Push events for the GitHub:
Logger Log Level org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventSubscriber ALL com.cloudbees.jenkins.GitHubPushTrigger ALL com.cloudbees.jenkins.GitHubWebHook ALL org.jenkinsci.plugins.github.webhook.WebhookManager ALL org.jenkinsci.plugins.github.webhook.subscriber.PingGHEventSubscriber ALLThe Pull Request events for the GitHub Pull Request Builder:
Logger Log Level org.jenkinsci.plugins.ghprb.GhprbRootAction ALL org.jenkinsci.plugins.ghprb.GhprbTrigger ALL org.jenkinsci.plugins.ghprb.GhprbPullRequest ALL org.jenkinsci.plugins.ghprb.GhprbRepository ALLNote
Below is an example of using the Pipeline script with webhooks for the GitHub plugin implemented in the EDP pipelines:
properties([pipelineTriggers([githubPush()])])\n\nnode {\n git credentialsId: 'github-sshkey', url: 'https://github.com/someone/something.git', branch: 'master'\n}\n
Push events may not work correctly with the Job Pipeline script from SCM option in the current version of the GitHub plugin 1.34.1.
Follow the steps below to automatically integrate Jenkins with GitHub webhooks.
Note
Before applying the GitHub integration, make sure you have already visited the Integrate GitHub/GitLab in Jenkins page.
Ensure the new job provisioner is created, as well as Secret with SSH key and GitServer custom resources.
Ensure the access token for GitHub is created.
Navigate to Dashboard -> Manage Jenkins -> Manage Credentials -> Global -> Add Credentials, and create new credentials with the Secret text kind. In the Secret field, provide the GitHub API token, fill in the ID field with the github-access-token
value:
Jenkins github credentials
Navigate to Jenkins -> Manage Jenkins -> Configure system -> GitHub, and configure the GitHub server:
GitHub plugin config GitHub plugin Shared secrets config
Note
Keep the Manage hooks checkbox clear since the Job Provisioner automatically creates webhooks in the repository regardless of the checkbox selection. Select Advanced to see the shared secrets that can be used in a webhook Secret field to authenticate payloads from GitHub to Jenkins. The Secret field is optional.
Configure the GitHub Pull Request Builder plugin. This plugin is responsible for listening on Pull Request webhook events and triggering Code Review jobs:
Note
The Secret field is optional and is used in a webhook Secret field to authenticate payloads from GitHub to Jenkins. For details, please refer to the official GitHub pull request builder plugin documentation.
GitHub pull plugin config
A webhook enables third-party services like GitLab to send real-time updates to the application. Updates are triggered by an event or action by the webhook provider (for example, a push to a repository, a Merge Request creation), and pushed to the application via the HTTP requests, namely, Jenkins. The GitLab Jenkins job provisioner creates a webhook in the GitLab repository during the Create release pipeline once the Integrate GitHub/GitLab in Jenkins is enabled and the GitLab Integration is completed.
The Jenkins setup in EDP uses the GitLab plugin responsible for listening on GitLab webhook Push and Merge Request events.
In case of any issues with webhooks, try the following solutions:
Check that the firewalls are configured to accept incoming traffic from the IP address range that is described in the GitLab documentation.
Check that GitLab Personal Access Token is correct and has the api scope. If you have used the Project Access Token, make sure that the role is Owner or Maintainer, and it has the api scope.
Check that the job has run at least once before using the hook (once an application is created in EDP, the build job should be run automatically in Jenkins).
Check that both Push Events, Note Events and Merge Requests Events, Note Events webhooks are created on the GitLab side for each branch (unlike GitHub, GitLab must have separate webhooks for each branch).
Webhooks list
Click Edit next to each webhook and check if the event delivery is successful. If the webhook is sent, the Recent Deliveries list becomes available. Click View details.
Webhooks settings
https://jenkins-server.com/project/project-name/MAIN-Build-job
is for the Push events. https://jenkins-server.com/project/project-name/MAIN-Code-review-job
is for the Merge Request events.Verify the Secret token (X-Gitlab-Token). This token comes from the Jenkins job due to the Jenkins GitLab Plugin and is created by our Job Provisioner:
Secret token is optional and can be empty. Nevertheless, if incorrect, it can prevent webhook events.
Redeliver events by clicking the Resend Request button and check the Response body.
Note
Use Postman to debug webhooks. Add all headers to Postman from the webhook Request Headers field and send the payload (Request body) using the appropriate content type.
Examples for Push and Merge Request events:
Postman push request payload headers Push request build pipeline
The response in the Jenkins log:
Jan 17, 2022 11:26:34 AM INFO com.dabsquared.gitlabjenkins.webhook.GitLabWebHook getDynamic\nWebHook call ed with url: /project/project-name/MAIN-Build-job\nJan 17, 2022 11:26:34 AM INFO com.dabsquared.gitlabjenkins.trigger.handler.AbstractWebHookTriggerHandler handle\nproject-name/MAIN-Build-job triggered for push.\n
Postman merge request payload headers Merge request code review pipeline
The response in the Jenkins log:
Jan 17, 2022 11:14:58 AM INFO com.dabsquared.gitlabjenkins.webhook.GitLabWebHook getDynamic\nWebHook called with url: /project/project-name/MAIN-Code-review-job\n
Check that the repository pushing to Jenkins and the repository(ies) in the pipeline Job are lined up. GitLab Connection must be defined in the job settings.
Check that the settings in the Build Triggers for the Build job are as follows:
Build triggers build pipeline
Check that the settings in the Build Triggers for the Code Review job are as follows:
Build triggers code review pipeline
Filter through Jenkins log by using Jenkins custom log recorder:
The Push and Merge Request events for the GitLab:
Logger Log Level com.dabsquared.gitlabjenkins.webhook.GitLabWebHook ALL com.dabsquared.gitlabjenkins.trigger.handler.AbstractWebHookTriggerHandler ALL com.dabsquared.gitlabjenkins.trigger.handler.merge.MergeRequestHookTriggerHandlerImpl ALL com.dabsquared.gitlabjenkins.util.CommitStatusUpdater ALLFollow the steps below to automatically create and integrate Jenkins GitLab webhooks.
Note
Before applying the GitLab integration, make sure to enable Integrate GitHub/GitLab in Jenkins. For details, please refer to the Integrate GitHub/GitLab in Jenkins page.
Ensure the new job provisioner is created, as well as Secret with SSH key and GitServer custom resources.
Ensure the access token for GitLab is created.
Create the Jenkins Credential ID by navigating to Dashboard -> Manage Jenkins -> Manage Credentials -> Global -> Add Credentials:
Jenkins credential
Warning
When using the GitLab integration, a webhook is automatically created. After the removal of the application, the webhook stops working but is not deleted. If necessary, it must be deleted manually.
Note
The next step is necessary if it is needed to see the status of Jenkins Merge Requests builds in the GitLab CI/CD Pipelines section.
In order to see the status of Jenkins Merge Requests builds in the GitLab CI/CD Pipelines section, configure the GitLab plugin by navigating to Manage Jenkins -> Configure System and filling in the GitLab plugin settings:
GitLab plugin configuration
Find below an example of the Merge Requests build statuses in the GitLab CI/CD Pipelines section:
GitLab pipelines statuses
This page provides instructions for configuring OIDC authorization for Harbor. This enables the use of Single Sign-On (SSO) for authorization in Harbor and allows centralized control over user access and rights through a single configuration point.
"},{"location":"operator-guide/harbor-oidc/#prerequisites","title":"Prerequisites","text":"Before the beginning, ensure your cluster meets the following requirements:
To start from, configure Keycloak by creating two Kubernetes resources. Follow the steps below to succeed:
Generate the keycloak-client-harbor-secret for Keycloak using either the commands below or using the External Secrets Operator:
keycloak_client_harbor_secret=$(openssl rand -base64 32 | head -c 32)\n
kubectl -n edp create secret generic keycloak-client-harbor-secret \\\n --from-literal=cookie-secret=${keycloak_client_harbor_secret}\n
Create the KeycloakClient custom resource by applying the HarborKeycloakClient.yaml file in the edp namespace. This custom resource will use the keycloak-client-harbor-secret
to include the harbor client. After the download, you will receive the created harbor client, and the password that is actually the value of the Kubernetes secret from the step 1:
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakClient\nmetadata:\n name: harbor\nspec:\n advancedProtocolMappers: true\n clientId: harbor\n directAccess: true\n public: false\n secret: keycloak-client-harbor-secret\n defaultClientScopes:\n - profile\n - email\n - roles\n targetRealm: control-plane\n webUrl: <harbor_endpoint>\n protocolMappers:\n - name: roles\n protocol: openid-connect\n protocolMapper: oidc-usermodel-realm-role-mapper\n config:\n access.token.claim: true\n claim.name: roles\n id.token.claim: true\n userinfo.token.claim: true\n multivalued: true\n
The next stage is to configure Harbor. Proceed with following the steps below:
Log in to Harbor UI with an account that has Harbor system administrator privileges. To get the administrator password, execute the command below:
kubectl get secret harbor -n harbor -o jsonpath='{.data.HARBOR_ADMIN_PASSWORD}' | base64 --decode\n
Navigate to Administration -> Configuration -> Authentication. Configure OIDC using the parameters below:
auth_mode: oidc_auth\noidc_name: keycloak\noidc_endpoint: <keycloak_endpoint>/auth/realms/control-plane\noidc_client_id: harbor\noidc_client_secret: <keycloak-client-harbor-secret>\noidc_groups_claim: roles\noidc_admin_group: administrator\noidc_scope: openid,email,profile,roles\nverify_certificate: true\noidc_auto_onboard: true\noidc_user_claim: preferred_username\n
Harbor Authentication Configuration
As a result, users will be prompted to authenticate themselves when logging in to Harbor UI.
"},{"location":"operator-guide/harbor-oidc/#related-articles","title":"Related Articles","text":"This page provides the instructions of configuring the OIDC authorization for EDP Portal UI, thus allowing using SSO for authorization in Portal and controlling user access and rights from one configuration point.
"},{"location":"operator-guide/headlamp-oidc/#prerequisites","title":"Prerequisites","text":"Ensure the following values are set first before starting the Portal OIDC configuration:
realm_id
= openshift
client_id
= kubernetes
keycloak_client_key
= keycloak_client_secret_key (received from: Openshift realm
-> clients
-> kubernetes
-> Credentials
-> Client secret
)
group
= edp-oidc-admins
, edp-oidc-builders
, edp-oidc-deployers
, edp-oidc-developers
, edp-oidc-viewers
(Should be created manually in the realm from point 1)
Note
The values indicated above are the result of the Keycloak configuration as an OIDC identity provider. To receive them, follow the instructions on the Keycloak OIDC EKS Configuration page.
"},{"location":"operator-guide/headlamp-oidc/#configure-keycloak","title":"Configure Keycloak","text":"To proceed with the Keycloak configuration, perform the following:
Add the URL of the Headlamp to the valid_redirect_uris
variable in Keycloak:
valid_redirect_uris = [\n \"https://edp-headlamp-edp.<dns_wildcard>/*\"\n \"http://localhost:8000/*\"\n ]\n
Make sure to define the following Keycloak client values as indicated:
Keycloak client configuration
Configure the Keycloak client key in Kubernetes using the Kubernetes secrets or the External Secrets Operator:
apiVersion: v1\nkind: Secret\nmetadata:\n name: keycloak-client-headlamp-secret\n namespace: edp\ntype: Opaque\nstringData:\n clientSecret: <keycloak_client_secret_key>\n
Assign user to one or more groups in Keycloak.
Headlamp can be integrated in Kubernetes in three steps:
Update the values.yaml file by enabling OIDC:
View: values.yamledp-headlamp:\n config:\n oidc:\n enabled: true\n
Navigate to Headlamp and log in by clicking the Sign In
button:
Headlamp login page
Go to EDP
section -> Account
-> Settings
, and set up a namespace:
Headlamp namespace settings
As a result, it is possible to control access and rights from the Keycloak endpoint.
"},{"location":"operator-guide/headlamp-oidc/#related-articles","title":"Related Articles","text":"This page describes how to integrate EDP with GitLab or GitHub in case of following the Jenkins deploy scenario.
"},{"location":"operator-guide/import-strategy-jenkins/#integration-procedure","title":"Integration Procedure","text":"To start from, it is required to add both Secret with SSH key and GitServer custom resources by taking the steps below:
Generate an SSH key pair and add a public key to GitLab or GitHub account.
ssh-keygen -t ed25519 -C \"email@example.com\"\n
Generate access token for GitLab or GitHub account with read/write access to the API. Both personal and project access tokens are applicable.
GitHubGitLabTo create access token in GitHub, follow the steps below:
Repo permission
Note
The access below is required for the GitHub Pull Request Builder plugin to get Pull Request commits, their status, and author info.
Admin permission User permission
Warning
Make sure to save a new personal access token because it won`t be displayed later.
To create access token in GitLab, follow the steps below:
Personal access tokens
Note
Make sure to save the access token as there will not be any ability to access it once again.
In case you want to create a project access token instead of a personal one, the GitLab Jenkins plugin will be able to accept payloads from webhooks for the project only:
Project access tokens
Create secret in the edp
namespace for the Git account with the id_rsa, username, and token fields. We recommend using EDP Portal to implement this:
Open EDP Portal URL. Use the Sign-In option:
Logging screen
In the top right corner, enter the Cluster settings
and set the Default namespace
. The Allowed namespaces
field is optional. All the resources created via EDP Portal are created in the Default namespace
whereas Allowed namespaces
means the namespaces you are allowed to access in this cluster:
Cluster settings
Log into EDP Portal UI, select EDP
-> Git Servers
-> +
to see the Create Git Server
menu:
Git Servers overview
Choose your Git provider, insert Host, Access token, Private SSH key. Adjust SSH port, User and HTTPS port if needed and click Apply
:
Note
Do not forget to press enter at the very end of the private key to have the last row empty.
Create Git Servers menu
After performing the steps above, two Kubernetes custom resources will be created in the default namespace: secret and GitServer. EDP Portal appends random symbols to both the secret and the GitServer to provide names with uniqueness. Also, the attempt to connect to your actual Git server will be performed. If the connection with the server is established, the Git server status should be green:
Git server status
Note
The value of the nameSshKeySecret property is the name of the Secret that is indicated in the first step above.
Create the JenkinsServiceAccount
custom resource with the credentials field that corresponds to the nameSshKeySecret property above:
apiVersion: v2.edp.epam.com/v1\nkind: JenkinsServiceAccount\nmetadata:\n name: gitlab # It can also be github.\n namespace: edp\nspec:\n credentials: <nameSshKeySecret>\n ownerName: ''\n type: ssh\n
Double-check that the new SSH credentials called gitlab
/github
are created in Jenkins using the SSH key. Navigate to Jenkins
-> Manage Jenkins
-> Manage Credentials
-> (global)
:
Jenkins credentials
Create a new job provisioner by following the instructions for GitHub or GitLab. The job provisioner will create a job suite for an application added to EDP. The job provisioner will also create webhooks for the project in GitLab using a GitLab token.
Configure GitHub or GitLab plugins in Jenkins.
This page describes how to integrate EDP with GitLab or GitHub Version Control System.
"},{"location":"operator-guide/import-strategy-tekton/#integration-procedure","title":"Integration Procedure","text":"To start from, it is required to add both Secret with SSH key, API token, and GitServer resources by taking the steps below.
Generate an SSH key pair and add a public key to GitLab or GitHub account.
ssh-keygen -t ed25519 -C \"email@example.com\"\n
Generate access token for GitLab or GitHub account with read/write access to the API. Both personal and project access tokens are applicable.
GitHubGitLabTo create access token in GitHub, follow the steps below:
Repo permission
Note
The access below is required for the GitHub Pull Request Builder plugin to get Pull Request commits, their status, and author info.
Admin:repo permission Admin:org permission User permission
Warning
Make sure to save a new personal access token because it won`t be displayed later.
To create access token in GitLab, follow the steps below:
Personal access tokens
Note
Make sure to save the access token as there will not be any ability to access it once again.
In case you want to create a project access token instead of a personal one, take the following steps:
Project access tokens
Create a secret in the edp
namespace for the Git account with the id_rsa, username, and token fields. Take the following template as an example (use ci-gitlab instead of ci-github for GitLab):
Navigate to EDP Portal
-> EDP
-> Configuration
-> Git Servers
. Fill in the required fields:
Project access tokens
Create a manifest file called secret.yaml with the following content filled in:
kubectl apply -f - <<EOF\n apiVersion: v1\n kind: Secret\n metadata:\n name: ci-github\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: repository\n type: Opaque\n stringData:\n id_rsa: <id_rsa_data>\n username: git\n token: <your_github_access_token>\nEOF\n
As a result, you will be able to create codebases using an integrated Version Control System.
"},{"location":"operator-guide/import-strategy-tekton/#related-articles","title":"Related Articles","text":"Enabling the VCS Import strategy is a prerequisite to integrate EDP with GitLab or GitHub.
"},{"location":"operator-guide/import-strategy/#general-steps","title":"General Steps","text":"In order to use the Import strategy, it is required to add both Secret with SSH key and GitServer custom resources by taking the steps below.
Generate an SSH key pair and add a public key to GitLab or GitHub account.
ssh-keygen -t ed25519 -C \"email@example.com\"\n
Generate access token for GitLab or GitHub account with read/write access to the API. Both personal and project access tokens are applicable.
To create access token in GitHub, follow the steps below:
Repo permission
Note
The access below is required for the GitHub Pull Request Builder plugin to get Pull Request commits, their status, and author info.
Admin permission User permission
Warning
Make sure to save a new personal access token because it won`t be displayed later.
To create access token in GitLab, follow the steps below:
Personal access tokens
Note
Make sure to save the access token as there will not be any ability to access it once again.
In case you want to create a project access token instead of a personal one, the GitLab Jenkins plugin will be able to accept payloads from webhooks for the project only:
Project access tokens
The further steps depend on the CI tool used.
Tekton CI toolJenkins CI toolCreate a secret in the edp-project
namespace for the Git account with the id_rsa, username, and token fields. Take the following template as an example (use github instead of gitlab for GitHub):
kubectl create secret generic gitlab -n edp \\\n--from-file=id_rsa=id_rsa \\\n--from-literal=username=git \\\n--from-literal=token=your_gitlab_access_token\n
After completing the steps above, you can get back and continue installing EDP.
Create secret in the edp
namespace for the Git account with the id_rsa, username, and token fields. We recommend using EDP Portal to implement this:
Open EDP Portal URL. Use the Sign-In option:
Logging screen
In the top right corner, enter the Cluster settings
and set the Default namespace
. The Allowed namespaces
field is optional. All the resources created via EDP Portal are created in the Default namespace
whereas Allowed namespaces
means the namespaces you are allowed to access in this cluster:
Cluster settings
Log into EDP Portal UI, select EDP
-> Git Servers
-> +
to see the Create Git Server
menu:
Git Servers overview
Choose your Git provider, insert Host, Access token, Private SSH key. Adjust SSH port, User and HTTPS port if needed and click Apply
:
Note
Do not forget to press enter at the very end of the private key to have the last row empty.
Create Git Servers menu
When everything is done, two custom resources will be created in the default namespace: secret and Git server. EDP Portal appends random symbols to both the secret and the server to provide names with uniqueness. Also, the attempt to connect to your Git server will be performed. If everything is correct, the Git server status should be green:
Git server status
Note
The value of the nameSshKeySecret property is the name of the Secret that is indicated in the first step above.
Create the JenkinsServiceAccount
custom resource with the credentials field that corresponds to the nameSshKeySecret property above:
apiVersion: v2.edp.epam.com/v1\nkind: JenkinsServiceAccount\nmetadata:\n name: gitlab # It can also be github.\n namespace: edp\nspec:\n credentials: <nameSshKeySecret>\n ownerName: ''\n type: ssh\n
Double-check that the new SSH credentials called gitlab
/github
are created in Jenkins using the SSH key. Navigate to Jenkins
-> Manage Jenkins
-> Manage Credentials
-> (global)
:
Jenkins credentials
The next step is to create a new job provisioner by following the instructions for GitHub or GitLab. The job provisioner will create a job suite for an application added to EDP. It will also create webhooks for the project in GitLab using a GitLab token.
The next step is to integrate Jenkins with GitHub or GitLab by setting their plugins.
Inspect the prerequisites and the main steps to perform for enabling Argo CD in EDP.
"},{"location":"operator-guide/install-argocd/#prerequisites","title":"Prerequisites","text":"The following tools must be installed:
Argo CD enablement for EDP consists of two major steps:
Info
It is also possible to install Argo CD using the Helmfile. For details, please refer to the Install via Helmfile page.
"},{"location":"operator-guide/install-argocd/#integrate-with-edp","title":"Integrate With EDP","text":"To enable Argo CD integration, ensure that the argocd.enabled
flag values.yaml is set to true
Argo CD can be installed in several ways, please follow the official documentation for more details.
Follow the steps below to install Argo CD using Helm:
For the OpenShift users:
When using the OpenShift platform, apply the SecurityContextConstraints
resource. Change the namespace in the users
section if required.
View: argocd-scc.yaml
allowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\napiVersion: security.openshift.io/v1\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 99\n max: 65543\ngroups: []\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: argo-redis-ha\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n- KILL\n- MKNOD\n- SETUID\n- SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nseccompProfiles:\n - '*'\nusers:\n- system:serviceaccount:argocd:argo-redis-ha\n- system:serviceaccount:argocd:argo-redis-ha-haproxy\n- system:serviceaccount:argocd:argocd-notifications-controller\n- system:serviceaccount:argocd:argo-argocd-repo-server\n- system:serviceaccount:argocd:argocd-server\nvolumes:\n- configMap\n- downwardAPI\n- emptyDir\n- persistentVolumeClaim\n- projected\n- secret\n
Check out the values.yaml file sample of the Argo CD customization, which is based on the HA mode without autoscaling
:
redis-ha:\n enabled: true\n\ncontroller:\n enableStatefulSet: true\n\nserver:\n replicas: 2\n extraArgs:\n - \"--insecure\"\n env:\n - name: ARGOCD_API_SERVER_REPLICAS\n value: '2'\n ingress:\n enabled: true\n hosts:\n - \"argocd.<Values.global.dnsWildCard>\"\n config:\n # required when SSO is enabled\n url: \"https://argocd.<.Values.global.dnsWildCard>\"\n application.instanceLabelKey: argocd.argoproj.io/instance-edp\n oidc.config: |\n name: Keycloak\n issuer: https://<.Values.global.keycloakEndpoint>/auth/realms/edp-main\n clientID: argocd\n clientSecret: $oidc.keycloak.clientSecret\n requestedScopes:\n - openid\n - profile\n - email\n - groups\n rbacConfig:\n # users may be still be able to login,\n # but will see no apps, projects, etc...\n policy.default: ''\n scopes: '[groups]'\n policy.csv: |\n # default global admins\n g, ArgoCDAdmins, role:admin\n\nconfigs:\n params:\n application.namespaces: edp\n\nrepoServer:\n replicas: 2\n\n# we use Keycloak so no DEX is required\ndex:\n enabled: false\n\n# Disabled for multitenancy env with single instance deployment\napplicationSet:\n enabled: false\n
View: openshift-values.yaml redis-ha:\n enabled: true\n\ncontroller:\n enableStatefulSet: true\n\nserver:\n replicas: 2\n extraArgs:\n - \"--insecure\"\n env:\n - name: ARGOCD_API_SERVER_REPLICAS\n value: '2'\n route:\n enabled: true\n hostname: \"argocd.<.Values.global.dnsWildCard>\"\n termination_type: edge\n termination_policy: Redirect\n config:\n # required when SSO is enabled\n url: \"https://argocd.<.Values.global.dnsWildCard>\"\n application.instanceLabelKey: argocd.argoproj.io/instance-edp\n oidc.config: |\n name: Keycloak\n issuer: https://<.Values.global.keycloakEndpoint>/auth/realms/edp-main\n clientID: argocd\n clientSecret: $oidc.keycloak.clientSecret\n requestedScopes:\n - openid\n - profile\n - email\n - groups\n rbacConfig:\n # users may be still be able to login,\n # but will see no apps, projects, etc...\n policy.default: ''\n scopes: '[groups]'\n policy.csv: |\n # default global admins\n g, ArgoCDAdmins, role:admin\n\nconfigs:\n params:\n application.namespaces: edp\n\nrepoServer:\n replicas: 2\n\n# we use Keycloak so no DEX is required\ndex:\n enabled: false\n\n# Disabled for multitenancy env with single instance deployment\napplicationSet:\n enabled: false\n
Populate Argo CD values with the values from the EDP values.yaml:
edp
namespace.Run the installation:
kubectl create ns argocd\nhelm repo add argo https://argoproj.github.io/argo-helm\nhelm install argo --version 5.33.1 argo/argo-cd -f values.yaml -n argocd\n
Update the argocd-secret
secret in the argocd
namespace by providing the correct Keycloak client secret (oidc.keycloak.clientSecret
) with the value from the keycloak-client-argocd-secret
secret in the EDP namespace. Then restart the deployment:
ARGOCD_CLIENT=$(kubectl -n edp get secret keycloak-client-argocd-secret -o jsonpath='{.data.clientSecret}')\nkubectl -n argocd patch secret argocd-secret -p=\"{\\\"data\\\":{\\\"oidc.keycloak.clientSecret\\\": \\\"${ARGOCD_CLIENT}\\\"}}\" -v=1\nkubectl -n argocd rollout restart deployment argo-argocd-server\n
Inspect the main steps to perform for installing DefectDojo via Helm Chart.
Info
It is also possible to install DefectDojo using the EDP addons approach. For details, please refer to the EDP addons approach.
"},{"location":"operator-guide/install-defectdojo/#prerequisites","title":"Prerequisites","text":"Info
Please refer to the DefectDojo Helm Chart and Deploy DefectDojo into the Kubernetes cluster sections for details.
To install DefectDojo, follow the steps below:
Check that a security namespace is created. If not, run the following command to create it:
kubectl create namespace defectdojo\n
For the OpenShift users:
When using the OpenShift platform, install the SecurityContextConstraints
resource. In case of using a custom namespace for defectdojo
, change the namespace in the users
section.
View: defectdojo-scc.yaml
allowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\napiVersion: security.openshift.io/v1\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 999\n max: 65543\ngroups: []\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: defectdojo\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n- KILL\n- MKNOD\n- SETUID\n- SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n- system:serviceaccount:defectdojo:defectdojo\n- system:serviceaccount:defectdojo:defectdojo-rabbitmq\n- system:serviceaccount:defectdojo:default\nvolumes:\n- configMap\n- downwardAPI\n- emptyDir\n- persistentVolumeClaim\n- projected\n- secret\n
Add a chart repository:
helm repo add defectdojo 'https://raw.githubusercontent.com/DefectDojo/django-DefectDojo/helm-charts'\nhelm repo update\n
Create PostgreSQL admin secret:
kubectl -n defectdojo create secret generic defectdojo-postgresql-specific \\\n--from-literal=postgresql-password=<postgresql_password> \\\n--from-literal=postgresql-postgres-password=<postgresql_postgres_password>\n
Note
The postgresql_password
and postgresql_postgres_password
passwords must be 16 characters long.
Create Rabbitmq admin secret:
kubectl -n defectdojo create secret generic defectdojo-rabbitmq-specific \\\n--from-literal=rabbitmq-password=<rabbitmq_password> \\\n--from-literal=rabbitmq-erlang-cookie=<rabbitmq_erlang_cookie>\n
Note
The rabbitmq_password
password must be 10 characters long.
The rabbitmq_erlang_cookie
password must be 32 characters long.
Create DefectDojo admin secret:
kubectl -n defectdojo create secret generic defectdojo \\\n--from-literal=DD_ADMIN_PASSWORD=<dd_admin_password> \\\n--from-literal=DD_SECRET_KEY=<dd_secret_key> \\\n--from-literal=DD_CREDENTIAL_AES_256_KEY=<dd_credential_aes_256_key> \\\n--from-literal=METRICS_HTTP_AUTH_PASSWORD=<metric_http_auth_password>\n
Note
The dd_admin_password
password must be 22 characters long.
The dd_secret_key
password must be 128 characters long.
The dd_credential_aes_256_key
password must be 128 characters long.
The metric_http_auth_password
password must be 32 characters long.
Install DefectDojo v.2.22.4 using defectdojo/defectdojo Helm chart v.1.6.69:
helm upgrade --install \\\ndefectdojo \\\n--version 1.6.69 \\\ndefectdojo/defectdojo \\\n--namespace defectdojo \\\n--values values.yaml\n
Check out the values.yaml file sample of the DefectDojo customization:
View: values.yamltag: 2.22.4\nfullnameOverride: defectdojo\nhost: defectdojo.<ROOT_DOMAIN>\nsite_url: https://defectdojo.<ROOT_DOMAIN>\nalternativeHosts:\n - defectdojo-django.defectdojo\n\ninitializer:\n # should be false after initial installation was performed\n run: true\ndjango:\n ingress:\n enabled: true # change to 'false' for OpenShift\n activateTLS: false\n uwsgi:\n livenessProbe:\n # Enable liveness checks on uwsgi container. Those values are use on nginx readiness checks as well.\n # default value is 120, so in our case 20 is just fine\n initialDelaySeconds: 20\n
For the OpenShift platform, install a Route:
View: defectdojo-route.yamlkind: Route\napiVersion: route.openshift.io/v1\nmetadata:\n name: defectdojo\n namespace: defectdojo\nspec:\n host: defectdojo.<ROOT_DOMAIN>\n path: /\n tls:\n insecureEdgeTerminationPolicy: Redirect\n termination: edge\n to:\n kind: Service\n name: defectdojo-django\n port:\n targetPort: http\n wildcardPolicy: None\n
To prepare DefectDojo for integration with EDP, follow the steps below:
Create ci user in DefectDojo UI:
echo \"DefectDojo admin password: $(kubectl \\\nget secret defectdojo \\\n--namespace=defectdojo \\\n--output jsonpath='{.data.DD_ADMIN_PASSWORD}' \\\n| base64 --decode)\"\n
Get a token of the DefectDojo user:
Provision the secret using EDP Portal
, Manifest
or with the externalSecrets
operator:
Go to EDP Portal -> EDP -> Configuration -> DefectDojo. Update or fill in the URL and Token and click the Save button.
DefectDojo update manual secret
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-defectdojo\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: defectdojo\n app.edp.epam.com/integration-secret: true\nstringData:\n url: https://defectdojo.example.com\n token: <token>\n
Store defectdojo URL and Token in AWS Parameter Store with following format:
\"ci-defectdojo\":\n{\n \"url\": \"https://defectdojo.example.com\",\n \"token\": \"XXXXXXXXXXXX\"\n}\n
Go to EDP Portal -> EDP -> Configuration -> DefectDojo and see the Managed by External Secret
message. More details about the External Secrets Operator integration procedure can be found in the External Secrets Operator Integration page.
After following the instructions provided, you should be able to integrate your DefectDojo with the EPAM Delivery Platform using one of the few available scenarios.
"},{"location":"operator-guide/install-defectdojo/#related-articles","title":"Related Articles","text":"Inspect the main steps to install EPAM Delivery Platform. Please check the Prerequisites Overview page before starting the installation. Also to authenticate each of the release artifacts, please refer to the Verification of EDP Artifacts guide. There are two recommended ways to deploy EPAM Delivery Platform:
Note
The installation process below is given for a Kubernetes cluster. The steps that differ for an OpenShift cluster are indicated in the notes.
Disclaimer
EDP is aligned with industry standards for storing and managing sensitive data, ensuring optimal security. However, the use of custom solutions introduces uncertainties, thus the responsibility for the safety of your data is totally covered by platform administrator.
EDP manages secrets via External Secret Operator to integrate with a multitude of utilities. For insights into the secrets in use and their utilization, refer to the provided External Secrets Operator Integration.
Create an edp namespace or a Kiosk space depending on whether Kiosk is used or not.
Without Kiosk, create a namespace:
kubectl create namespace edp\n
Note
For an OpenShift cluster, run the oc
command instead of the kubectl
one.
With Kiosk, create a relevant space:
apiVersion: tenancy.kiosk.sh/v1alpha1\nkind: Space\nmetadata:\n name: edp\nspec:\n account: edp-admin\n
Note
Kiosk is mandatory for EDP v.2.8.x. It is not implemented for the previous versions, and is optional for EDP since v.2.9.x.
(Optional) Deploy and configure Keycloak to enable Single Sign-On approach. To see the details on how to configure Keycloak correctly, please refer to the Install Keycloak page.
Add the Helm charts repository:
helm repo add epamedp https://epam.github.io/edp-helm-charts/stable\n
Choose the required Helm chart version:
helm search repo epamedp/edp-install\nNAME CHART VERSION APP VERSION DESCRIPTION\nepamedp/edp-install 3.5.3 3.5.3 A Helm chart for EDP Install\n
Note
It is highly recommended to use the latest released version.
EDP can be integrated with the following version control systems:
This integration implies in what system the development of the application will be or is already being carried out. The global.gitProvider
flag in the edp-install controls this integration:
...\nglobal:\n gitProvider: gerrit\n...\n
values.yaml...\nglobal:\n gitProvider: github\n...\n
values.yaml...\nglobal:\n gitProvider: gitlab\n...\n
Internal Gerrit server can be deployed as a result of EDP deployment. For more details on how to integrate EDP with GitLab or GitHub instead of Gerrit, please refer to the Integrate GitHub/GitLab in Tekton page.
(Optional) Integrate platform with SonarQube:
...\nsonar-operator:\n enabled: true\n...\n
(Optional) Integrate platform with Nexus:
...\nnexus-operator:\n enabled: true\n...\n
(Optional) Configure Container Registry for image storage.
Since EDP v3.4.0, we enabled users to configure Harbor registry instead of AWS ECR and Openshift-registry. We recommend installing Harbor using our edp-cluster-add-ons although you can install it any other way. To integrate EDP with Harbor, see Harbor integration page.
To enable Harbor as a registry storage, use the values below:
global:\n dockerRegistry:\n type: \"harbor\"\n url: \"harbor.example.com\"\n
Check the parameters in the EDP installation chart. For details, please refer to the values.yaml file.
Install EDP in the edp namespace with the Helm tool:
helm install edp epamedp/edp-install --wait --timeout=900s \\\n--version <edp_version> \\\n--values values.yaml \\\n--namespace edp\n
See the details on the parameters below:
Example values.yaml fileglobal:\n # -- platform type that can be either \"kubernetes\" or \"openshift\"\n platform: \"kubernetes\"\n # DNS wildcard for routing in the Kubernetes cluster;\n dnsWildCard: \"example.com\"\n # -- Administrators of your tenant\n # -- Can be gerrit, github or gitlab. By default: github\n gitProvider: github\n dockerRegistry:\n # -- Docker Registry endpoint\n url: \"<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com\"\n type: \"ecr\"\n\nsso:\n enabled: false\n # Keycloak address with which the platform will be integrated\n keycloakUrl: \"https://keycloak.example.com\"\n admins:\n - \"stub_user_one@example.com\"\n developers:\n - \"stub_user_one@example.com\"\n - \"stub_user_two@example.com\"\n\n# AWS Region, e.g. \"eu-central-1\"\nawsRegion:\n\nargocd:\n # -- Enable ArgoCD integration\n enabled: true\n # -- ArgoCD URL in format schema://URI\n # -- By default, https://argocd.{{ .Values.global.dnsWildCard }}\n url: \"\"\n\nedp-tekton:\n # Tekton Kaniko configuration section\n kaniko:\n # -- AWS IAM role to be used for kaniko pod service account (IRSA). Format: arn:aws:iam::<AWS_ACCOUNT_ID>:role/<AWS_IAM_ROLE_NAME>\n roleArn:\n\nedp-headlamp:\n config:\n oidc:\n enabled: false\n
Note
Set global.platform=openshift
while deploying EDP in OpenShift.
Info
The full installation with integration between tools will take at least 10 minutes.
To check if the installation is successful, run the command below:
helm status edp -n edp\n
You can also check ingress endpoints to get EDP Portal endpoint to enter EDP Portal UI:
kubectl describe ingress -n edp\n
Once EDP is successfully installed, you can navigate to our Use Cases to try out EDP functionality.
Inspect the prerequisites and the main steps to perform for enabling External Secrets Operator in EDP.
"},{"location":"operator-guide/install-external-secrets-operator/#prerequisites","title":"Prerequisites","text":"To install External Secrets Operator with Helm, run the following commands:
helm repo add external-secrets https://charts.external-secrets.io\n\nhelm install external-secrets \\\n external-secrets/external-secrets \\\n --version 0.8.3 \\\n -n external-secrets \\\n --create-namespace\n
Info
It is also possible to install External Secrets Operator using the Helmfile or Operator Lifecycle Manager (OLM).
"},{"location":"operator-guide/install-external-secrets-operator/#related-articles","title":"Related Articles","text":"EPAM Delivery Platform uses Harbor as a storage for application images that are created when building applications.
Inspect the prerequisites and the main steps to perform for enabling Harbor in EDP.
"},{"location":"operator-guide/install-harbor/#prerequisites","title":"Prerequisites","text":"To install Harbor with Helm, follow the steps below:
Create a namespace for Harbor:
kubectl create namespace harbor\n
Create a secret for administrator user and registry:
ManuallyExternal Secret Operatorkubectl create secret generic harbor \\\n --from-literal=HARBOR_ADMIN_PASSWORD=<secret> \\\n --from-literal=REGISTRY_HTPASSWD=<secret> \\\n --from-literal=REGISTRY_PASSWD=<secret> \\\n --from-literal=secretKey=<secret> \\\n --namespace harbor\n
apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: harbor\n namespace: harbor\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: aws-parameterstore\ndata:\n- secretKey: HARBOR_ADMIN_PASSWORD\n remoteRef:\n conversionStrategy: Default\n decodingStrategy: None\n key: /control-plane/deploy-secrets\n property: harbor.HARBOR_ADMIN_PASSWORD\n- secretKey: secretKey\n remoteRef:\n conversionStrategy: Default\n decodingStrategy: None\n key: /control-plane/deploy-secrets\n property: harbor.secretKey\n- secretKey: REGISTRY_HTPASSWD\n remoteRef:\n conversionStrategy: Default\n decodingStrategy: None\n key: /control-plane/deploy-secrets\n property: harbor.REGISTRY_HTPASSWD\n- secretKey: REGISTRY_PASSWD\n remoteRef:\n conversionStrategy: Default\n decodingStrategy: None\n key: /control-plane/deploy-secrets\n property: harbor.REGISTRY_PASSWD\n
Note
The HARBOR_ADMIN_PASSWORD
is the initial password of Harbor admin. The secretKey
is the secret key that is used for encryption. Must be 16 characters long. The REGISTRY_PASSWD
is Harbor registry password. The REGISTRY_HTPASSWD
is login and password in htpasswd string format. This value is the string in the password file generated by the htpasswd
command where the username is harbor_registry_user
and the encryption type is bcrypt
. See the example below:
htpasswd -bBc passwordfile harbor_registry_user harbor_registry_password\n
The username must be harbor_registry_user
. The password must be the value from REGISTRY_PASSWD
. Add the Helm Harbor Charts for the local client.
helm repo add harbor https://helm.goharbor.io\n
Check the parameters in the Harbor installation chart. For details, please refer to the values.yaml file.
Install Harbor in the \u2039harbor\u203a namespace with the Helm tool.
helm install harbor harbor/harbor\n --version 1.12.2 \\\n --namespace harbor \\\n --values values.yaml\n
See the details on the parameters below:
Example values.yaml file
# we use Harbor secret to consolidate all the Harbor secrets\nexistingSecretAdminPassword: harbor\nexistingSecretAdminPasswordKey: HARBOR_ADMIN_PASSWORD\nexistingSecretSecretKey: harbor\n\ncore:\n # The XSRF key. Will be generated automatically if it isn't specified\n xsrfKey: \"\"\njobservice:\n # Secret is used when job service communicates with other components.\n # If a secret key is not specified, Helm will generate one.\n # Must be a string of 16 chars.\n secret: \"\"\nregistry:\n # Secret is used to secure the upload state from client\n # and registry storage backend.\n # If a secret key is not specified, Helm will generate one.\n # Must be a string of 16 chars.\n secret: \"\"\n credentials:\n username: harbor_registry_user\n existingSecret: harbor\nfullnameOverride: harbor\n# If Harbor is deployed behind the proxy, set it as the URL of proxy\nexternalURL: https://core.harbor.domain\nipFamily:\n ipv6:\n enabled: false\nexpose:\n tls:\n enabled: false\n ingress:\n hosts:\n core: core.harbor.domain\n notary: notary.harbor.domain\nupdateStrategy:\n type: Recreate\npersistence:\n persistentVolumeClaim:\n registry:\n size: 30Gi\n jobservice:\n jobLog:\n size: 1Gi\n database:\n size: 2Gi\n redis:\n size: 1Gi\n trivy:\n size: 5Gi\ndatabase:\n internal:\n # The initial superuser password for internal database\n password: \"changeit\"\n
To check if the installation is successful, run the command below:
helm status <harbor-release> -n harbor\n
You can also check ingress endpoints to get Harbor endpoint to enter Harbor UI: kubectl describe ingress <harbor_ingress> -n harbor\n
Inspect the prerequisites and the main steps to perform for installing Install NGINX Ingress Controller on Kubernetes.
"},{"location":"operator-guide/install-ingress-nginx/#prerequisites","title":"Prerequisites","text":"Info
It is also possible to install NGINX Ingress Controller using the Helmfile. For details, please refer to the Install via Helmfile page.
To install the ingress-nginx chart, follow the steps below:
Create an ingress-nginx namespace:
kubectl create namespace ingress-nginx\n
Add a chart repository:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx\nhelm repo update\n
Install the ingress-nginx chart:
helm install ingress ingress-nginx/ingress-nginx \\\n--version 4.7.0 \\\n--values values.yaml \\\n--namespace ingress-nginx\n
Check out the values.yaml file sample of the ingress-nginx chart customization:
controller:\n addHeaders:\n X-Content-Type-Options: nosniff\n X-Frame-Options: SAMEORIGIN\n resources:\n limits:\n memory: \"256Mi\"\n requests:\n cpu: \"50m\"\n memory: \"128M\"\n config:\n ssl-redirect: 'true'\n client-header-buffer-size: '64k'\n http2-max-field-size: '64k'\n http2-max-header-size: '64k'\n large-client-header-buffers: '4 64k'\n upstream-keepalive-timeout: '120'\n keep-alive: '10'\n use-forwarded-headers: 'true'\n proxy-real-ip-cidr: '172.32.0.0/16'\n proxy-buffer-size: '8k'\n\n # To watch Ingress objects without the ingressClassName field set parameter value to true.\n # https://kubernetes.github.io/ingress-nginx/#i-have-only-one-ingress-controller-in-my-cluster-what-should-i-do\n watchIngressWithoutClass: true\n\n service:\n type: NodePort\n nodePorts:\n http: 32080\n https: 32443\n updateStrategy:\n rollingUpdate:\n maxUnavailable: 1\n type: RollingUpdate\n metrics:\n enabled: true\ndefaultBackend:\n enabled: true\nserviceAccount:\n create: true\n name: nginx-ingress-service-account\n
Warning
Align value controller.config.proxy-real-ip-cidr with AWS VPC CIDR.
"},{"location":"operator-guide/install-keycloak/","title":"Install Keycloak","text":""},{"location":"operator-guide/install-keycloak/#install-keycloak","title":"Install Keycloak","text":"Inspect the prerequisites and the main steps to perform for installing Keycloak.
Info
The installation process below is given for a Kubernetes cluster. The steps that differ for an OpenShift cluster are indicated in the warnings blocks.
"},{"location":"operator-guide/install-keycloak/#prerequisites","title":"Prerequisites","text":"Info
EDP team is using a Keycloakx helm chart from the codecentric repository, but other repositories can be used as well (e.g. Bitnami). Before installing Keycloak, it is necessary to install a PostgreSQL database.
Info
It is also possible to install Keycloak using the Helmfile. For details, please refer to the Install via Helmfile page.
"},{"location":"operator-guide/install-keycloak/#postgresql-installation","title":"PostgreSQL Installation","text":"To install PostgreSQL, follow the steps below:
Check that a security namespace is created. If not, run the following command to create it:
kubectl create namespace security\n
Warning
On the OpenShift platform, apply the SecurityContextConstraints
resource. Change the namespace in the users
section if required.
allowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\napiVersion: security.openshift.io/v1\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 999\n max: 65543\ngroups: []\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: keycloak\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n - KILL\n - MKNOD\n - SETUID\n - SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n - system:serviceaccount:security:keycloakx\nvolumes:\n - configMap\n - downwardAPI\n - emptyDir\n - persistentVolumeClaim\n - projected\n - secret\n
View: postgresql-keycloak-scc.yaml allowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\napiVersion: security.openshift.io/v1\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 999\n max: 65543\ngroups: []\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: postgresql-keycloak\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n- KILL\n- MKNOD\n- SETUID\n- SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n- system:serviceaccount:security:default\nvolumes:\n- configMap\n- downwardAPI\n- emptyDir\n- persistentVolumeClaim\n- projected\n- secret\n
Create PostgreSQL admin secret:
kubectl -n security create secret generic keycloak-postgresql \\\n--from-literal=password=<postgresql_password> \\\n--from-literal=postgres-password=<postgresql_postgres_password>\n
Add a helm chart repository:
helm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n
Install PostgreSQL v15.2.0 using bitnami/postgresql Helm chart v12.1.15:
Info
The PostgreSQL can be deployed in production ready mode. For example, it may include multiple replicas, persistent storage, autoscaling, and monitoring. For details, please refer to the official Chart documentation.
helm install postgresql bitnami/postgresql \\\n--version 12.1.15 \\\n--values values.yaml \\\n--namespace security\n
Check out the values.yaml file sample of the PostgreSQL customization:
View: values.yaml# PostgreSQL read only replica parameters\nreadReplicas:\n # Number of PostgreSQL read only replicas\n replicaCount: 1\n\nimage:\n tag: 15.2.0-debian-11-r0\n\nglobal:\n postgresql:\n auth:\n username: admin\n existingSecret: keycloak-postgresql\n database: keycloak\n\nprimary:\n persistence:\n enabled: true\n size: 3Gi\n
To install Keycloak, follow the steps below:
Use security
namespace from the PostgreSQL installation.
Add a chart repository:
helm repo add codecentric https://codecentric.github.io/helm-charts\nhelm repo update\n
Create Keycloak admin secret:
kubectl -n security create secret generic keycloak-admin-creds \\\n--from-literal=username=<keycloak_admin_username> \\\n--from-literal=password=<keycloak_admin_password>\n
Install Keycloak 20.0.3 using codecentric/keycloakx Helm chart:
Info
Keycloak can be deployed in production ready mode. For example, it may include multiple replicas, persistent storage, autoscaling, and monitoring. For details, please refer to the official Chart documentation.
helm install keycloakx codecentric/keycloakx \\\n--version 2.2.1 \\\n--values values.yaml \\\n--namespace security\n
Check out the values.yaml file sample of the Keycloak customization:
View: values.yamlreplicas: 1\n\n# Deploy the latest version\nimage:\n tag: \"20.0.3\"\n\n# start: create OpenShift realm which is required by EDP\nextraInitContainers: |\n - name: realm-provider\n image: busybox\n imagePullPolicy: IfNotPresent\n command:\n - sh\n args:\n - -c\n - |\n echo '{\"realm\": \"openshift\",\"enabled\": true}' > /opt/keycloak/data/import/openshift.json\n volumeMounts:\n - name: realm\n mountPath: /opt/keycloak/data/import\n\n# The following parameter is unrecommended to expose. Exposed health checks lead to an unnecessary attack vector.\nhealth:\n enabled: false\n# The following parameter is unrecommended to expose. Exposed metrics lead to an unnecessary attack vector.\nmetrics:\n enabled: false\n\nextraVolumeMounts: |\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumes: |\n - name: realm\n emptyDir: {}\n\ncommand:\n - \"/opt/keycloak/bin/kc.sh\"\n - \"--verbose\"\n - \"start\"\n - \"--auto-build\"\n - \"--http-enabled=true\"\n - \"--http-port=8080\"\n - \"--hostname-strict=false\"\n - \"--hostname-strict-https=false\"\n - \"--spi-events-listener-jboss-logging-success-level=info\"\n - \"--spi-events-listener-jboss-logging-error-level=warn\"\n - \"--import-realm\"\n\nextraEnv: |\n - name: KC_PROXY\n value: \"passthrough\"\n - name: KEYCLOAK_ADMIN\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: username\n - name: KEYCLOAK_ADMIN_PASSWORD\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: password\n - name: JAVA_OPTS_APPEND\n value: >-\n -XX:+UseContainerSupport\n -XX:MaxRAMPercentage=50.0\n -Djava.awt.headless=true\n -Djgroups.dns.query={{ include \"keycloak.fullname\" . }}-headless\n\n# This block should be uncommented if you install Keycloak on Kubernetes\ningress:\n enabled: true\n annotations:\n kubernetes.io/ingress.class: nginx\n ingress.kubernetes.io/affinity: cookie\n # The following parameter is unrecommended to expose. Admin paths lead to an unnecessary attack vector.\n console:\n enabled: false\n rules:\n - host: keycloak.<ROOT_DOMAIN>\n paths:\n - path: '{{ tpl .Values.http.relativePath $ | trimSuffix \"/\" }}/'\n pathType: Prefix\n\n# This block should be uncommented if you set Keycloak to OpenShift and change the host field\n# route:\n# enabled: false\n# # Path for the Route\n# path: '/'\n# # Host name for the Route\n# host: \"keycloak.<ROOT_DOMAIN>\"\n# # TLS configuration\n# tls:\n# enabled: true\n\nresources:\n limits:\n memory: \"2048Mi\"\n requests:\n cpu: \"50m\"\n memory: \"512Mi\"\n\n# Check database readiness at startup\ndbchecker:\n enabled: true\n\ndatabase:\n vendor: postgres\n existingSecret: keycloak-postgresql\n hostname: postgresql\n port: 5432\n username: admin\n database: keycloak\n
To prepare Keycloak for integration with EDP, follow the steps below:
Ensure that the openshift
realm is created.
Create the edp_<EDP_PROJECT>
user and set the password in the Master
realm.
Note
This user should be used by EDP to access Keycloak. Please refer to the Install EDP and Install EDP via Helmfile sections for details.
In the Role Mapping
tab, assign the proper roles to the user:
Realm Roles:
Client Roles openshift-realm
:
Role mappings
Kiosk is a multi-tenancy extension for managing tenants and namespaces in a shared Kubernetes cluster. Within EDP, Kiosk is used to separate resources and enables the following options (see more details):
Inspect the main steps to set up Kiosk for the proceeding EDP installation.
Note
Kiosk deploy is mandatory for EDP v.2.8. In earlier versions, Kiosk is not implemented. Since EDP v.2.9.0, integration with Kiosk is an optional feature. You may not want to use it, so just skip those steps and disable in Helm parameters during EDP deploy.
# global.kioskEnabled: <true/false>\n
"},{"location":"operator-guide/install-kiosk/#prerequisites","title":"Prerequisites","text":" # Install kiosk with helm v3\n\n helm repo add kiosk https://charts.devspace.sh/\n kubectl create namespace kiosk\n helm install kiosk --version 0.2.11 kiosk/kiosk -n kiosk --atomic\n
For more details, please refer to the Kiosk page on the GitHub.
"},{"location":"operator-guide/install-kiosk/#configuration","title":"Configuration","text":"To provide access to the EDP tenant, follow the steps below.
kubectl create namespace security\n
Note
On an OpenShift cluster, run the oc
command instead of kubectl
one.
kubectl -n security create sa edp\n
Info
Please note that edp
is the name of the EDP tenant here and in all the following steps.
apiVersion: tenancy.kiosk.sh/v1alpha1\nkind: Account\nmetadata:\n name: edp-admin\nspec:\n space:\n clusterRole: kiosk-space-admin\n subjects:\n - kind: ServiceAccount\n name: edp\n namespace: security\n
apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n name: edp-kiosk-edit\nsubjects:\n- kind: ServiceAccount\n name: edp\n namespace: security\nroleRef:\n kind: ClusterRole\n name: kiosk-edit\n apiGroup: rbac.authorization.k8s.io\n
EDP configures the logging with the help of Grafana Loki aggregation system.
"},{"location":"operator-guide/install-loki/#installation","title":"Installation","text":"To install Loki, follow the steps below:
Create logging namespace:
kubectl create namespace logging\n
Note
On the OpenShift cluster, run the oc
command instead of the kubectl
command.
Add a chart repository:
helm repo add grafana https://grafana.github.io/helm-charts\n helm repo update\n
Note
It is possible to use Amazon Simple Storage Service Amazon S3 as an object storage for Loki. To configure access, please refer to the IRSA for Loki documentation.
Install Loki v.2.6.0:
helm install loki grafana/loki \\\n --version 2.6.0 \\\n --values values.yaml \\\n --namespace logging\n
Check out the values.yaml file sample of the Loki customization:
View: values.yamlimage:\n repository: grafana/loki\n tag: 2.3.0\nconfig:\n auth_enabled: false\n schema_config:\n configs:\n - from: 2021-06-01\n store: boltdb-shipper\n object_store: s3\n schema: v11\n index:\n prefix: loki_index_\n period: 24h\n storage_config:\n aws:\n s3: s3://<AWS_REGION>/loki-<CLUSTER_NAME>\n boltdb_shipper:\n active_index_directory: /data/loki/index\n cache_location: /data/loki/boltdb-cache\n shared_store: s3\n chunk_store_config:\n max_look_back_period: 24h\nresources:\n limits:\n memory: \"128Mi\"\n requests:\n cpu: \"50m\"\n memory: \"128Mi\"\nserviceAccount:\n create: true\n name: edp-loki\n annotations:\n eks.amazonaws.com/role-arn: \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki\npersistence:\n enabled: false\n
Note
In case of using cluster scheduling and amazon-eks-pod-identity-webhook, it is necessary to restart the Loki pod after the cluster is up and running. Please refer to the Schedule Pods Restart documentation.
Configure custom bucket policy to delete the old data.
Inspect the prerequisites and the main steps to perform for installing ReportPortal.
Info
It is also possible to install ReportPortal using the Helmfile. For details, please refer to the Install via Helmfile page.
"},{"location":"operator-guide/install-reportportal/#prerequisites","title":"Prerequisites","text":"Info
Please refer to the ReportPortal Helm Chart section for details.
"},{"location":"operator-guide/install-reportportal/#minio-installation","title":"MinIO Installation","text":"To install MinIO, follow the steps below:
Check that edp
namespace is created. If not, run the following command to create it:
kubectl create namespace edp\n
For the OpenShift users:
When using the OpenShift platform, install the SecurityContextConstraints
resources. In case of using a custom namespace for the reportportal
, change the namespace in the users
section.
apiVersion: security.openshift.io/v1\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: report-portal-minio-rabbitmq-postgresql\nallowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 999\n max: 65543\ngroups: []\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n - KILL\n - MKNOD\n - SETUID\n - SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n - system:serviceaccount:report-portal:minio\n - system:serviceaccount:report-portal:rabbitmq\n - system:serviceaccount:report-portal:postgresql\nvolumes:\n - configMap\n - downwardAPI\n - emptyDir\n - persistentVolumeClaim\n - projected\n - secret\n
View: report-portal-elasticsearch-scc.yaml apiVersion: security.openshift.io/v1\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: report-portal-elasticsearch\nallowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegedContainer: true\nallowedCapabilities: []\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - max: 1000\n min: 1000\ngroups: []\npriority: 0\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities: []\nrunAsUser:\n type: MustRunAsRange\n uidRangeMax: 1000\n uidRangeMin: 0\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n - system:serviceaccount:report-portal:elasticsearch-master\nvolumes:\n - configMap\n - downwardAPI\n - emptyDir\n - persistentVolumeClaim\n - projected\n - secret\n
Add a chart repository:
helm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n
Create MinIO admin secret:
kubectl -n edp create secret generic reportportal-minio-creds \\\n--from-literal=root-password=<root_password> \\\n--from-literal=root-user=<root_user>\n
Install MinIO v.11.10.3 using bitnami/minio Helm chart v.11.10.3:
helm install minio bitnami/minio \\\n--version 11.10.3 \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the MinIO customization:
View: values.yamlauth:\n existingSecret: reportportal-minio-creds\npersistence:\n size: 1Gi\n
To install RabbitMQ, follow the steps below:
Use edp
namespace from the MinIO installation.
Use bitnami
chart repository from the MinIO installation.
Create RabbitMQ admin secret:
kubectl -n edp create secret generic reportportal-rabbitmq-creds \\\n--from-literal=rabbitmq-password=<rabbitmq_password> \\\n--from-literal=rabbitmq-erlang-cookie=<rabbitmq_erlang_cookie>\n
Warning
The rabbitmq_password
password must be 10 characters long. The rabbitmq_erlang_cookie
password must be 32 characters long.
Install RabbitMQ v.10.3.8 using bitnami/rabbitmq Helm chart v.10.3.8:
helm install rabbitmq bitnami/rabbitmq \\\n--version 10.3.8 \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the RabbitMQ customization:
View: values.yamlauth:\n existingPasswordSecret: reportportal-rabbitmq-creds\n existingErlangSecret: reportportal-rabbitmq-creds\npersistence:\n size: 1Gi\n
After the rabbitmq pod gets the status Running, you need to configure the RabbitMQ memory threshold
kubectl -n edp exec -it rabbitmq-0 -- rabbitmqctl set_vm_memory_high_watermark 0.8\n
To install Elasticsearch, follow the steps below:
Use edp
namespace from the MinIO installation.
Add a chart repository:
helm repo add elastic https://helm.elastic.co\nhelm repo update\n
Install Elasticsearch v.7.17.3 using elastic/elasticsearch Helm chart v.7.17.3:
helm install elasticsearch elastic/elasticsearch \\\n--version 7.17.3 \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the Elasticsearch customization:
View: values.yamlreplicas: 1\n\nextraEnvs:\n - name: discovery.type\n value: single-node\n - name: cluster.initial_master_nodes\n value: \"\"\n\nrbac:\n create: true\n\nresources:\n requests:\n cpu: \"100m\"\n memory: \"2Gi\"\n\nvolumeClaimTemplate:\n resources:\n requests:\n storage: 3Gi\n
To install PostgreSQL, follow the steps below:
Use edp
namespace from the MinIO installation.
Add a chart repository:
helm repo add bitnami-archive https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami\nhelm repo update\n
Create PostgreSQL admin secret:
kubectl -n edp create secret generic reportportal-postgresql-creds \\\n--from-literal=postgresql-password=<postgresql_password> \\\n--from-literal=postgresql-postgres-password=<postgresql_postgres_password>\n
Warning
The postgresql_password
and postgresql_postgres_password
passwords must be 16 characters long.
Install PostgreSQL v.10.9.4 using Helm chart v.10.9.4:
helm install postgresql bitnami-archive/postgresql \\\n--version 10.9.4 \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the PostgreSQL customization:
View: values.yamlpersistence:\n size: 1Gi\nresources:\n requests:\n cpu: \"100m\"\nserviceAccount:\n enabled: true\npostgresqlUsername: \"rpuser\"\npostgresqlDatabase: \"reportportal\"\nexistingSecret: \"reportportal-postgresql-creds\"\ninitdbScripts:\n init_postgres.sh: |\n #!/bin/sh\n /opt/bitnami/postgresql/bin/psql -U postgres -d ${POSTGRES_DB} -c 'CREATE EXTENSION IF NOT EXISTS ltree; CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE EXTENSION IF NOT EXISTS pg_trgm;'\n
To install ReportPortal, follow the steps below:
Use edp
namespace from the MinIO installation.
For the OpenShift users:
When using the OpenShift platform, install the SecurityContextConstraints
resource. In case of using a custom namespace for the reportportal
, change the namespace in the users
section.
apiVersion: security.openshift.io/v1\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: report-portal\nallowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegedContainer: true\nallowedCapabilities: []\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - max: 1000\n min: 1000\ngroups: []\npriority: 0\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities: []\nrunAsUser:\n type: MustRunAsRange\n uidRangeMax: 1000\n uidRangeMin: 0\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n - system:serviceaccount:report-portal:reportportal\nvolumes:\n - configMap\n - downwardAPI\n - emptyDir\n - persistentVolumeClaim\n - projected\n - secret\n
Add a chart repository:
helm repo add report-portal \"https://reportportal.github.io/kubernetes\"\nhelm repo update\n
Install ReportPortal v.5.8.0 using Helm chart v.5.8.0:
helm install report-portal report-portal/reportportal \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the ReportPortal customization:
View: values.yamlserviceindex:\n resources:\n requests:\n cpu: 50m\nuat:\n resources:\n requests:\n cpu: 50m\nserviceui:\n resources:\n requests:\n cpu: 50m\n serviceAccountName: \"reportportal\"\n securityContext:\n runAsUser: 0\nserviceapi:\n resources:\n requests:\n cpu: 50m\nserviceanalyzer:\n resources:\n requests:\n cpu: 50m\nserviceanalyzertrain:\n resources:\n requests:\n cpu: 50m\n\nrabbitmq:\n SecretName: \"reportportal-rabbitmq-creds\"\n endpoint:\n address: rabbitmq.<EDP_PROJECT>.svc.cluster.local\n user: user\n apiuser: user\n\npostgresql:\n SecretName: \"reportportal-postgresql-creds\"\n endpoint:\n address: postgresql.<EDP_PROJECT>.svc.cluster.local\n\nelasticsearch:\n endpoint: http://elasticsearch-master.<EDP_PROJECT>.svc.cluster.local:9200\n\nminio:\n secretName: \"reportportal-minio-creds\"\n endpoint: http://minio.<EDP_PROJECT>.svc.cluster.local:9000\n endpointshort: minio.<EDP_PROJECT>.svc.cluster.local:9000\n accesskeyName: \"root-user\"\n secretkeyName: \"root-password\"\n\ningress:\n # IF YOU HAVE SOME DOMAIN NAME SET INGRESS.USEDOMAINNAME to true\n usedomainname: true\n hosts:\n - report-portal-<EDP_PROJECT>.<ROOT_DOMAIN>\n
For the OpenShift platform, install a Gateway with Route:
View: gateway-config-cm.yamlkind: ConfigMap\nmetadata:\n name: gateway-config\n namespace: report-portal\napiVersion: v1\ndata:\n traefik-dynamic-config.yml: |\n http:\n middlewares:\n strip-ui:\n stripPrefix:\n prefixes:\n - \"/ui\"\n forceSlash: false\n strip-api:\n stripPrefix:\n prefixes:\n - \"/api\"\n forceSlash: false\n strip-uat:\n stripPrefix:\n prefixes:\n - \"/uat\"\n forceSlash: false\n\n routers:\n index-router:\n rule: \"Path(`/`)\"\n service: \"index\"\n ui-router:\n rule: \"PathPrefix(`/ui`)\"\n middlewares:\n - strip-ui\n service: \"ui\"\n uat-router:\n rule: \"PathPrefix(`/uat`)\"\n middlewares:\n - strip-uat\n service: \"uat\"\n api-router:\n rule: \"PathPrefix(`/api`)\"\n middlewares:\n - strip-api\n service: \"api\"\n\n services:\n uat:\n loadBalancer:\n servers:\n - url: \"http://report-portal-reportportal-uat:9999/\"\n\n index:\n loadBalancer:\n servers:\n - url: \"http://report-portal-reportportal-index:8080/\"\n\n api:\n loadBalancer:\n servers:\n - url: \"http://report-portal-reportportal-api:8585/\"\n\n ui:\n loadBalancer:\n servers:\n - url: \"http://report-portal-reportportal-ui:8080/\"\n traefik.yml: |\n entryPoints:\n http:\n address: \":8081\"\n metrics:\n address: \":8082\"\n\n metrics:\n prometheus:\n entryPoint: metrics\n addEntryPointsLabels: true\n addServicesLabels: true\n buckets:\n - 0.1\n - 0.3\n - 1.2\n - 5.0\n\n providers:\n file:\n filename: /etc/traefik/traefik-dynamic-config.yml\n
View: gateway-deployment.yaml apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: reportportal\n name: gateway\n namespace: report-portal\nspec:\n replicas: 1\n selector:\n matchLabels:\n component: gateway\n template:\n metadata:\n labels:\n component: gateway\n spec:\n containers:\n - image: quay.io/waynesun09/traefik:2.3.6\n name: traefik\n ports:\n - containerPort: 8080\n protocol: TCP\n resources: {}\n volumeMounts:\n - mountPath: /etc/traefik/\n name: config\n readOnly: true\n volumes:\n - name: config\n configMap:\n defaultMode: 420\n name: gateway-config\n
View: gateway-route.yaml kind: Route\napiVersion: route.openshift.io/v1\nmetadata:\n labels:\n app: reportportal\n name: reportportal\n namespace: report-portal\nspec:\n host: report-portal.<CLUSTER_DOMAIN>\n port:\n targetPort: http\n tls:\n insecureEdgeTerminationPolicy: Redirect\n termination: edge\n to:\n kind: Service\n name: gateway\n weight: 100\n wildcardPolicy: None\n
View: gateway-service.yaml apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: reportportal\n component: gateway\n name: gateway\n namespace: report-portal\nspec:\n ports:\n # use 8081 to allow for usage of the dashboard which is on port 8080\n - name: http\n port: 8081\n protocol: TCP\n targetPort: 8081\n selector:\n component: gateway\n sessionAffinity: None\n type: ClusterIP\n
Note
For user access: default/1q2w3e For admin access: superadmin/erebus Please refer to the ReportPortal.io page for details.
"},{"location":"operator-guide/install-reportportal/#related-articles","title":"Related Articles","text":"EPAM Delivery Platform uses Tekton resources, such as Tasks, Pipelines, Triggers, Interceptors and Chains for running the CI/CD pipelines.
Inspect the main steps to perform for installing the Tekton resources via the Tekton release files.
"},{"location":"operator-guide/install-tekton/#prerequisites","title":"Prerequisites","text":"oc
utility is required. Please refer to the OKD page on GitHub for details.kaniko-cache
and this parameter is located in our Tekton common-library
.To install Tekton resources, follow the steps below:
Info
Please refer to the Install Tekton Pipelines and Install and set up Tekton Triggers sections for details.
Install Tekton pipelines v0.53.0 using the release file:
Note
Tekton Pipeline resources are used for managing and running EDP Tekton Pipelines and Tasks. Please refer to the EDP Tekton Pipelines and EDP Tekton Tasks pages for details.
kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.53.0/release.yaml\n
Install Tekton Triggers v0.25.2 using the release file:
Note
Tekton Trigger resources are used for managing and running EDP Tekton EventListeners, Triggers, TriggerBindings and TriggerTemplates. Please refer to the EDP Tekton Triggers page for details.
kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/previous/v0.25.2/release.yaml\n
Install Tekton Interceptors v0.25.2 using the release file:
Note
EPAM Delivery Platform uses GitLab, GitHub and Cel ClusterInterceptors for managing requests from webhooks.
kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/previous/v0.25.2/interceptors.yaml\n
Install Tekton Chains v0.19.0 using the release file:
kubectl apply -f https://storage.googleapis.com/tekton-releases/chains/previous/v0.19.0/release.yaml\n
To install Tekton resources, follow the steps below:
Info
Please refer to the Install Tekton Operator documentation for details.
Note
Tekton Operator also deploys Pipelines as Code CI that requires OpenShift v4.11 (based on Kubernetes v1.24) or higher. This feature is optional and its deployments can be scaled to zero replicas.
Install Tekton Operator v0.67.0 using the release file:
kubectl apply -f https://github.com/tektoncd/operator/releases/download/v0.67.0/openshift-release.yaml\n
After the installation, the Tekton Operator will install the following components: Pipeline, Trigger, and Addons.
Note
If there is the following error in the openshift-operators
namespace for openshift-pipelines-operator
and tekton-operator-webhook
deployments:
Error: container has runAsNonRoot and image will run as root\n
Patch the deployments with the following commands:
kubectl -n openshift-operators patch deployment openshift-pipelines-operator -p '{\"spec\": {\"template\": {\"spec\": {\"securityContext\": {\"runAsUser\": 1000}}}}}'\nkubectl -n openshift-operators patch deployment tekton-operator-webhook -p '{\"spec\": {\"template\": {\"spec\": {\"securityContext\": {\"runAsUser\": 1000}}}}}'\n
Grant access for Tekton Service Accounts in the openshift-pipelines
namespace to the Privileged SCC:
oc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-operators-proxy-webhook\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-pipelines-controller\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-pipelines-resolvers\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-pipelines-webhook\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-triggers-controller\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-triggers-core-interceptors\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-triggers-webhook\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:pipelines-as-code-controller\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:pipelines-as-code-watcher\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:pipelines-as-code-webhook\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:default\n
"},{"location":"operator-guide/install-tekton/#related-articles","title":"Related Articles","text":"Velero is an open source tool to safely back up, recover, and migrate Kubernetes clusters and persistent volumes. It works both on premises and in a public cloud. Velero consists of a server process running as a deployment in your Kubernetes cluster and a command-line interface (CLI) with which DevOps teams and platform operators configure scheduled backups, trigger ad-hoc backups, perform restores, and more.
"},{"location":"operator-guide/install-velero/#installation","title":"Installation","text":"To install Velero, follow the steps below:
Create velero namespace:
kubectl create namespace velero\n
Note
On an OpenShift cluster, run the oc
command instead of kubectl
one.
Add a chart repository:
helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts\n helm repo update\n
Note
Velero AWS Plugin requires access to AWS resources. To configure access, please refer to the IRSA for Velero documentation.
Install Velero v.2.14.13:
helm install velero vmware-tanzu/velero \\\n --version 2.14.13 \\\n --values values.yaml \\\n --namespace velero\n
Check out the values.yaml file sample of the Velero customization:
View: values.yamlimage:\n repository: velero/velero\n tag: v1.5.3\nsecurityContext:\n fsGroup: 65534\nrestic:\n securityContext:\n fsGroup: 65534\nserviceAccount:\n server:\n create: true\n name: edp-velero\n annotations:\n eks.amazonaws.com/role-arn: \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero\"\ncredentials:\n useSecret: false\nconfiguration:\n provider: aws\n backupStorageLocation:\n name: default\n bucket: velero-<CLUSTER_NAME>\n config:\n region: eu-central-1\n volumeSnapshotLocation:\n name: default\n config:\n region: <AWS_REGION>\ninitContainers:\n - name: velero-plugin-for-aws\n image: velero/velero-plugin-for-aws:v1.1.0\n volumeMounts:\n - mountPath: /target\n name: plugins\n
Note
In case of using cluster scheduling and amazon-eks-pod-identity-webhook, it is necessary to restart the Velero pod after the cluster is up and running. Please refer to the Schedule Pods Restart documentation.
Install the client side (velero cli) according to the official documentation.
Create backup for all components in the namespace:
velero backup create <BACKUP_NAME> --include-namespaces <NAMESPACE>\n
Create a daily backup of the namespace:
velero schedule create <BACKUP_NAME> --schedule \"0 10 * * MON-FRI\" --include-namespaces <NAMESPACE> --ttl 120h0m0s\n
To restore from backup, use the following command:
velero restore create <RESTORE_NAME> --from-backup <BACKUP_NAME>\n
This article provides the instruction on how to deploy EDP and components in Kubernetes using Helmfile that is intended for deploying Helm charts. Helmfile templates are available in GitHub repository.
Important
The Helmfile installation method for EPAM Delivery Platform (EDP) is currently not actively maintained. We strongly recommend exploring alternative installation options for the most up-to-date and well-supported deployment experience. You may consider using the Add-Ons approach or opting for installation via the AWS Marketplace to ensure a reliable and secure deployment of EDP.
"},{"location":"operator-guide/install-via-helmfile/#prerequisites","title":"Prerequisites","text":"The following tools and plugins must be installed:
envs/common.yaml
file contains the specification for environments pattern, list of helm repositories from which it is necessary to fetch the helm charts and additional Helm parameters.envs/platform.yaml
file contains global parameters that are used in various Helmfiles.releases/envs/
contains symbol links to environments files.releases/*.yaml
file contains description of parameters that is used when deploying a Helm chart.helmfile.yaml
file defines components to be installed by defining a path to Helm releases files.envs/ci.yaml
file contains stub parameters for CI linter.test/lint-ci.sh
script for running CI linter with debug loglevel and stub parameters.resources/*.yaml
file contains additional resources for the OpenShift platform.Before applying the Helmfile, please fill in the global parameters in the envs/platform.yaml
(check the examples in the envs/ci.yaml
) and releases/*.yaml
files for every Helm deploy.
Pay attention to the following recommendations while working with the Helmfile:
test/lint-ci.sh
script.helm diff
):helmfile --environment platform -f helmfile.yaml diff\n
helmfile --selector component=ingress --environment platform -f helmfile.yaml apply\n
helmfile --selector component=ingress --environment platform -f helmfile.yaml sync\n
nginx-ingress
file, use the following command:helmfile --selector component=ingress --environment platform -f helmfile.yaml diff\n
helmfile --selector component=ingress --environment platform -f helmfile.yaml destroy\n
Using the Helmfile, the following components can be installed:
Info
Skip this step for the OpenShift platform, because it has its own Ingress Controller.
To install NGINX Ingress controller, follow the steps below:
In the releases/nginx-ingress.yaml
file, set the proxy-real-ip-cidr
parameter according to the value with AWS VPC IPv4 CIDR.
Install NGINX Ingress controller:
helmfile --selector component=ingress --environment platform -f helmfile.yaml apply\n
Keycloak requires a database deployment, so it has two charts: releases/keycloak.yaml
and releases/postgresql-keycloak.yaml
.
To install Keycloak, follow the steps below:
Create a security
namespace:
Note
For the OpenShift users: This namespace is also indicated as users
in the following custom SecurityContextConstraints
resources: resources/keycloak-scc.yaml
and resources/postgresql-keycloak-scc.yaml
. Change the namespace name when using a custom namespace.
kubectl create namespace security\n
Create PostgreSQL admin secret:
kubectl -n security create secret generic keycloak-postgresql \\\n--from-literal=password=<postgresql_password> \\\n--from-literal=postgres-password=<postgresql_postgres_password>\n
In the envs/platform.yaml
file, set the dnsWildCard
parameter.
Create Keycloak admin secret:
kubectl -n security create secret generic keycloak-admin-creds \\\n--from-literal=username=<keycloak_admin_username> \\\n--from-literal=password=<keycloak_admin_password>\n
Install Keycloak:
helmfile --selector component=sso --environment platform -f helmfile.yaml apply\n
To install External Secrets Operator, follow the steps below:
helmfile --selector component=secrets --environment platform -f helmfile.yaml apply\n
"},{"location":"operator-guide/install-via-helmfile/#deploy-kiosk","title":"Deploy Kiosk","text":"To install Kiosk, follow the steps below:
helmfile --selector component=kiosk --environment platform -f helmfile.yaml apply\n
"},{"location":"operator-guide/install-via-helmfile/#deploy-epam-delivery-platform","title":"Deploy EPAM Delivery Platform","text":"To install EDP, follow the steps below:
Create a platform
namespace:
kubectl create namespace platform\n
For EDP, it is required to have Keycloak access to perform the integration. Create a secret with the user and password provisioned in the step 2 of the Keycloak Configuration section.
kubectl -n platform create secret generic keycloak \\\n --from-literal=username=<username> \\\n --from-literal=password=<password>\n
In the envs/platform.yaml
file, set the edpName
and keycloakEndpoint
parameters.
In the releases/edp-install.yaml
file, check and fill in all values.
Install EDP:
helmfile --selector component=edp --environment platform -f helmfile.yaml apply\n
Before Argo CD deployment, install the following tools:
To install Argo CD, follow the steps below:
Install Argo CD:
For the OpenShift users:
When using a custom namespace for Argo CD, the `argocd` namespace is also indicated as `users` in the `resources/argocd-scc.yaml` custom `SecurityContextConstraints` resource. Change it there as well.\n
helmfile --selector component=argocd --environment platform -f helmfile.yaml apply\n
Update the argocd-secret
secret in the Argo CD namespace by providing the correct Keycloak client secret (oidc.keycloak.clientSecret
) with the value from the keycloak-client-argocd-secret
secret in EDP namespace. Then restart the deployment:
ARGOCD_CLIENT=$(kubectl -n platform get secret keycloak-client-argocd-secret -o jsonpath='{.data.clientSecret}')\nkubectl -n argocd patch secret argocd-secret -p=\"{\\\"data\\\":{\\\"oidc.keycloak.clientSecret\\\": \\\"${ARGOCD_CLIENT}\\\"}}\" -v=1\nkubectl -n argocd rollout restart deployment argo-argocd-server\n
Prerequisites
Info
It is also possible to install DefectDojo via Helm Chart. For details, please refer to the Install DefectDojo page.
To install DefectDojo via Helmfile, follow the steps below:
Create a DefectDojo namespace:
For the OpenShift users:
This namespace is also indicated as users
in the resources/defectdojo-scc.yaml
custom SecurityContextConstraints
resource. Change it when using a custom namespace. Also, change the namespace in the resources/defectdojo-route.yaml
file.
kubectl create namespace defectdojo\n
Modify the host
in resources/defectdojo-route.yaml
(only for OpenShift).
Create a PostgreSQL admin secret:
kubectl -n defectdojo create secret generic defectdojo-postgresql-specific \\\n--from-literal=postgresql-password=<postgresql_password> \\\n--from-literal=postgresql-postgres-password=<postgresql_postgres_password>\n
Note
The postgresql_password
and postgresql_postgres_password
passwords must be 16 characters long.
Create a RabbitMQ admin secret:
kubectl -n defectdojo create secret generic defectdojo-rabbitmq-specific \\\n--from-literal=rabbitmq-password=<rabbitmq_password> \\\n--from-literal=rabbitmq-erlang-cookie=<rabbitmq_erlang_cookie>\n
Note
The rabbitmq_password
password must be 10 characters long.
The rabbitmq_erlang_cookie
password must be 32 characters long.
Create a DefectDojo admin secret:
kubectl -n defectdojo create secret generic defectdojo \\\n--from-literal=DD_ADMIN_PASSWORD=<dd_admin_password> \\\n--from-literal=DD_SECRET_KEY=<dd_secret_key> \\\n--from-literal=DD_CREDENTIAL_AES_256_KEY=<dd_credential_aes_256_key> \\\n--from-literal=METRICS_HTTP_AUTH_PASSWORD=<metric_http_auth_password>\n
Note
The dd_admin_password
password must be 22 characters long.
The dd_secret_key
password must be 128 characters long.
The dd_credential_aes_256_key
password must be 128 characters long.
The metric_http_auth_password
password must be 32 characters long.
Create a Keycloak client secret for DefectDojo:
Note
The keycloak_client_secret
value received from: edpName
-main realm -> clients -> defectdojo -> Credentials -> Client secret
kubectl -n defectdojo create secret generic defectdojo-extrasecrets \\\n--from-literal=DD_SOCIAL_AUTH_KEYCLOAK_SECRET=<keycloak_client_secret>\n
In the envs/platform.yaml
file, set the dnsWildCard
parameter.
In the releases/defectdojo.yaml file, check and fill in all values.
Install DefectDojo:
helmfile --selector component=defectdojo --environment platform -f helmfile.yaml apply\n
Info
It is also possible to install ReportPortal via Helm Chart. For details, please refer to the Install ReportPortal page.
ReportPortal requires third-party deployments: RabbitMQ, ElasticSearch, PostgreSQL, MinIO.
To install third-party resources, follow the steps below:
Create a RabbitMQ admin secret:
kubectl -n report-portal create secret generic reportportal-rabbitmq-creds \\\n--from-literal=rabbitmq-password=<rabbitmq_password> \\\n--from-literal=rabbitmq-erlang-cookie=<rabbitmq_erlang_cookie>\n
Warning
The rabbitmq_password
password must be 10 characters long.
The rabbitmq_erlang_cookie
password must be 32 characters long.
Create a PostgreSQL admin secret:
kubectl -n report-portal create secret generic reportportal-postgresql-creds \\\n--from-literal=postgresql-password=<postgresql_password> \\\n--from-literal=postgresql-postgres-password=<postgresql_postgres_password>\n
Warning
The postgresql_password
and postgresql_postgres_password
passwords must be 16 characters long.
Create a MinIO admin secret:
kubectl -n report-portal create secret generic reportportal-minio-creds \\\n--from-literal=root-password=<root_password> \\\n--from-literal=root-user=<root_user>\n
In the envs/platform.yaml
file, set the dnsWildCard
and edpName
parameters.
For the OpenShift users:
The namespace is also indicated as users
in the following custom SecurityContextConstraints
resources: resources/report-portal-elasticsearch-scc.yaml
and resources/report-portal-third-party-resources-scc.yaml
. Change the namespace name when using a custom namespace.
Install third-party resources:
helmfile --selector component=report-portal-third-party-resources --environment platform -f helmfile.yaml apply\n
After the rabbitmq pod gets the status Running, you need to configure the RabbitMQ memory threshold
kubectl -n report-portal exec -it rabbitmq-0 -- rabbitmqctl set_vm_memory_high_watermark 0.8\n
To install ReportPortal via Helmfile, follow the steps below:
For the OpenShift users:
users
in the resources/report-portal-reportportal-scc.yaml
custom SecurityContextConstraints
resource. Change it when using a custom namespace.resources/report-portal-gateway/gateway-config-cm
, resources/report-portal-gateway/gateway-deployment
, resources/report-portal-gateway/gateway-route
, and resources/report-portal-gateway/gateway-service
.host
in resources/report-portal-gateway/gateway-route
helmfile --selector component=report-portal --environment platform -f helmfile.yaml apply\n
Note
For user access: default/1q2w3e For admin access: superadmin/erebus Please refer to the ReportPortal.io page for details.
"},{"location":"operator-guide/install-via-helmfile/#deploy-moon","title":"Deploy Moon","text":"Moon is a browser automation solution compatible with Selenium, Cypress, Playwright, and Puppeteer using Kubernetes or Openshift to launch browsers.
Note
Aerokube/Moon does not require third-party deployments.
Follow the steps below to deploy Moon:
Use the following command to install Moon:
helmfile --selector component=moon --environment platform -f helmfile.yaml apply\n
After the installation, open the Ingress Dashboard and check that SELENOID
and SSE
have the CONNECTED
status.
Main board
In Moon, use the following command with the Ingress rule, for example, wd/hub
:
curl -X POST 'http://<INGRESS_LINK>/wd/hub/session' -d '{\n \"desiredCapabilities\":{\n \"browserName\":\"firefox\",\n \"version\": \"79.0\",\n \"platform\":\"ANY\",\n \"enableVNC\": true,\n \"name\": \"edp\",\n \"sessionTimeout\": \"480s\"\n }\n }'\n
See below the list of Moon Dashboard Ingress rules:
Moon Dashboard Ingress rules
After using the command above, the container will start, and the VNC viewer will be displayed on the Moon Dashboard:
VNC viewer with the container starting
The monitoring stack includes Grafana, Prometheus, Alertmanager, and Karma-dashboard. To deploy it follow the steps:
Generate a token for Keycloak client:
Note
The token must be 32-character and include alphabetic and numeric symbols. For example, use the following command:
keycloak_client_secret=$(date +%s | sha256sum | base64 | head -c 32 ; echo)\n
Create a secret for the Keycloak client:
kubectl -n platform create secret generic keycloak-client-grafana \\\n --from-literal=clientSecret=<keycloak_client_secret>\n
Create a secret for the Grafana:
kubectl -n monitoring create secret generic keycloak-client-grafana \\\n --from-literal=GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=<keycloak_client_secret> \\\n
Create a custom resource for the Keycloak client:
View: keycloak_clientapiVersion: v1.edp.epam.com/v1\nkind: KeycloakClient\nmetadata:\n name: grafana\n namespace: platform\nspec:\n clientId: grafana\n directAccess: true\n serviceAccount:\n enabled: true\n targetRealm: platform-main\n webUrl: https://grafana-monitoring.<dnsWildCard>\n secret: keycloak-client.grafana\n
Run command:
helmfile --selector component=monitoring --environment platform -f helmfile.yaml apply\n
To install Elasticsearch, Kibana and Fluentbit, run command:
helmfile --selector component=logging-elastic --environment platform -f helmfile.yaml apply\n
To install Grafana, Loki, Promtail, follow the steps below:
Make sure that appropriate resources are created:
Create a custom resource for the Keycloak client:
View: keycloak_clientapiVersion: v1.edp.epam.com/v1\nkind: KeycloakClient\nmetadata:\n name: grafana\n namespace: platform\nspec:\n clientId: grafana-logging\n directAccess: true\n serviceAccount:\n enabled: true\n targetRealm: platform-main\n webUrl: https://grafana-logging.<dnsWildCard>\n secret: keycloak-client.grafana\n
Run command:
helmfile --selector component=logging --environment platform -f helmfile.yaml apply\n
In order to adjust the Version Control System integration with Jira Server, first make sure you have the following prerequisites:
When checked the prerequisites, follow the steps below to proceed with the integration:
Integrate every project in VCS Server with every project in Crucible by creating a corresponding request in EPAM Support Portal. Add the repositories links and fill in the Keep Informed field as this request must be approved.
Request example
Provide additional details to the support team. If the VCS is Gerrit, inspect the sample below of its integration:
2.1 Create a new \"crucible-\" user in Gerrit with SSH key and add a new user to the \"Non-Interactive Users\" Gerrit group;
2.2 Create a new group in Gerrit \"crucible-watcher-group\" and add the \"crucible-\" user;
2.3 Provide access to All-Projects for the \"crucible-watcher-group\" group:
Gerrit All-Projects configuration
Gerrit All-Projects configuration
To link commits with Jira ticket, being in Gerrit, enter a Jira ticket ID in a commit message using the specific format:
[PROJECT-CODE-1234]: commit message
where PROJECT-CODE is a specific code of a project, 1234 is an ID number, and a commit message.
As a result, all Gerrit commits will be displayed on Crucible:
Crucible project
This documentation guide provides step-by-step instructions for enabling the Jira integration option in the EDP Portal UI for EPAM Delivery Platform. Jira integration allows including useful metadata in Jira tickets.
"},{"location":"operator-guide/jira-integration/#overview","title":"Overview","text":"Integrating Jira can provide a number of benefits, such as increased visibility and traceability, automatic linking code changes to relevant Jira issues, streamlining the management and tracking of development progress.
By linking CI pipelines to Jira issues, teams can get a better understanding of the status of their work and how it relates to the overall development process. This can help to improve communication and collaboration, and ultimately lead to faster and more efficient delivery of software.
Enabling Jira integration allows for the automatic population of three fields in Jira tickets: Fix Versions, Components, and Labels. Each of these fields provides distinct benefits:
Teams can utilize these fields to enhance their work prioritization, identify dependencies, improve collaboration, and ultimately achieve faster software delivery.
"},{"location":"operator-guide/jira-integration/#integration-procedure","title":"Integration Procedure","text":"In order to adjust the Jira server integration, add the JiraServer CR by performing the following:
Provision the ci-jira secret using EDP Portal
, Manifest
or with the externalSecrets
operator:
Go to EDP Portal -> EDP -> Configuration -> Jira. Update or fill in the URL, User, Password fields and click the Save button:
Jira update manual secret
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-jira\n namespace: edp\n labels:\n app.edp.epam.com/secret-type=jira\nstringData:\n username: username\n password: password\n
\"ci-jira\":\n{\n \"username\": \"username\",\n \"password\": \"password\"\n}\n
Required Permissions for Issue Management
To manage issue labels, components, and add links in Jira, please make sure the user has the following permissions:
Edit Issues: This permission is necessary to modify issue fields, including adding or removing labels and components.
Link Issues: You must have this permission to create and manage links between issues.
Add Comments: Required for adding external links and comments to issues.
Create JiraServer CR in the OpenShift/Kubernetes namespace with the apiUrl, credentialName and rootUrl fields:
apiVersion: v2.edp.epam.com/v1\nkind: JiraServer\nmetadata:\n name: jira-server\nspec:\n apiUrl: 'https://jira-api.example.com'\n credentialName: ci-jira\n rootUrl: 'https://jira.example.com'\n
Note
The value of the credentialName property is the name of the Secret, which is indicated in the first point above.
There is also a possibility to set up Jira integration when deploying EPAM Delivery Platform. To follow this approach, please familiarize yourself with the following parameters of the values.yaml file in the EDP installer. Enabling the jira.integration
parameter creates the following custom resources:
To set up Jira integration along with EDP, follow the steps below:
Create the ci-jira secret in the edp
namespace as it's described above.
Deploy the platform with the jira.integration
parameter set to true
in the values.yaml file.
To use Jira integration, you need to set up your codebases accordingly.
When creating a codebase, navigate to the Advanced Settings tab. Select the Integrate with Jira server check box and fill in the required fields:
Advanced settings
There are four predefined variables with the respective values that can be specified singly or as a combination. These variables show different data depending on which versioning type is currently used:
If the EDP versioning type is used:
If the default versioning type is used:
Note
There are no character restrictions when combining the variables. You can concatenate them using the dash sign. Combination samples: EDP_SEM_VERSION-EDP_COMPONENT; EDP_COMPONENT-hello-world/EDP_VERSION; etc.
If the Jira integration is set up correctly, you will start seeing additional metadata in the tickets:
Supplemental information
If metadata is not visible in a Jira ticket, check the status field of the JiraIssueMetadata Custom Resources in the edp namespace. The codebase operator deletes this resource after successful processing, but in case of an error, the 'JiraIssueMetadata' resource may still exist within the namespace.
"},{"location":"operator-guide/jira-integration/#related-articles","title":"Related Articles","text":"Note
The information below is relevant in case ECR is used as Docker container registry. Make sure that IRSA is enabled and amazon-eks-pod-identity-webhook is deployed according to the Associate IAM Roles With Service Accounts documentation.
The \"build-image-kaniko\" stage manages ECR through IRSA that should be available on the cluster. Follow the steps below to create a required role:
Create AWS IAM Policy \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko_policy\":
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"ecr:*\",\n \"cloudtrail:LookupEvents\"\n ],\n \"Resource\": \"arn:aws:ecr:<AWS_REGION>:<AWS_ACCOUNT_ID>:repository/<EDP_NAMESPACE>/*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": \"ecr:GetAuthorizationToken\",\n \"Resource\": \"*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"ecr:DescribeRepositories\",\n \"ecr:CreateRepository\"\n ],\n \"Resource\": \"arn:aws:ecr:<AWS_REGION>:<AWS_ACCOUNT_ID>:repository/*\"\n }\n ]\n}\n
Create AWS IAM Role \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko\" with trust relationships:
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER>\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"<OIDC_PROVIDER>:sub\": \"system:serviceaccount:edp:edp-kaniko\"\n }\n }\n }\n ]\n}\n
Attach the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko_policy\" policy to the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko\" role.
Define the resulted arn role value into the kaniko.roleArn parameter in values.yaml during the EDP installation.
This documentation describes the advantages of EFK stack over the traditional ELK stack, explains the value that this stack brings to EDP and instructs how to set up the EFK stack to integrate the advanced logging system with your application.
"},{"location":"operator-guide/kibana-ilm-rollover/#elk-stack-overview","title":"ELK Stack Overview","text":"The ELK (Elasticsearch, Logstash and Kibana) stack gives the ability to aggregate logs from all the managed systems and applications, analyze these logs and create visualizations for application and infrastructure monitoring, faster troubleshooting, security analytics and more.
Here is a brief description of the ELK stack default components:
ELK Stack
"},{"location":"operator-guide/kibana-ilm-rollover/#efk-stack-overview","title":"EFK Stack Overview","text":"We use FEK (also called EFK) (Fluent Bit, Elasticsearch, Kibana) stack in Kubernetes instead of ELK because this stack provides us with the support for Logsight for Stage Verification and Incident Detection. In addition to it, Fluent Bit has a smaller memory fingerprint than Logstash. Fluent Bit has the Inputs, Parsers, Filters and Outputs plugins similarly to Logstash.
FEK Stack
"},{"location":"operator-guide/kibana-ilm-rollover/#automate-elasticsearch-index-rollover-with-ilm","title":"Automate Elasticsearch Index Rollover With ILM","text":"In this guide, index rollover with the Index Lifecycle Management ILM is automated in the FEK stack.
The resources can be created via API using curl, Postman, Kibana Dev Tools console or via GUI. They are going to be created them using Kibana Dev Tools.
Go to Management
\u2192 Dev Tools
in the Kibana dashboard:
Dev Tools
Create index lifecycle policy with the index rollover:
Note
This policy can also be created in GUI in Management
\u2192 Stack Management
\u2192 Index Lifecycle Policies
.
Index Lifecycle has several phases: Hot, Warm, Cold, Frozen, Delete. Indices also have different priorities in each phase. The warmer the phase, the higher the priority is supposed to be, e.g., 100 for the hot phase, 50 for the warm phase, and 0 for the cold phase.
In this Use Case, only the Hot and Delete phases are configured. So an index will be created, rolled over to a new index when 1gb in size or 1day in time and deleted in 7 days. The rollover may not happen exactly at 1GB because it depends on how often Kibana checks the index size. Kibana usually checks the index size every 10 minutes but this can be changed by setting the indices.lifecycle.poll_interval monitoring timer.
The index lifecycle policy example:
Index Lifecycle PolicyPUT _ilm/policy/fluent-bit-policy\n{\n \"policy\": {\n \"phases\": {\n \"hot\": {\n \"min_age\": \"0ms\",\n \"actions\": {\n \"set_priority\": {\n \"priority\": 100\n },\n \"rollover\": {\n \"max_size\": \"1gb\",\n \"max_primary_shard_size\": \"1gb\",\n \"max_age\": \"1d\"\n }\n }\n },\n \"delete\": {\n \"min_age\": \"7d\",\n \"actions\": {\n \"delete\": {\n \"delete_searchable_snapshot\": true\n }\n }\n }\n }\n }\n}\n
Insert the code above into the Dev Tools
and click the arrow to send the PUT
request.
Create an index template so that a new index is created according to this template after the rollover:
Note
This policy can also be created in GUI in Management
\u2192 Stack Management
\u2192 Index Management
\u2192 Index Templates
.
Expand the menu below to see the index template example:
Index TemplatePUT /_index_template/fluent-bit\n{\n \"index_patterns\": [\"fluent-bit-kube-*\"],\n \"template\": {\n \"settings\": {\n \"index\": {\n \"lifecycle\": {\n \"name\": \"fluent-bit-policy\",\n \"rollover_alias\": \"fluent-bit-kube\"\n },\n \"number_of_shards\": \"1\",\n \"number_of_replicas\": \"0\"\n }\n }\n }\n}\n
Note
index.lifecycle.rollover_alias
is required when using a policy containing the rollover action and specifies which alias to rollover on behalf of this index. The intention here is that the rollover alias is also defined on the index.number_of_shards
is the quantity of the primary shards. Elasticsearch index is really just a logical grouping of one or more physical shards, where each shard is actually a self-contained index. By distributing the documents in an index across multiple shards and distributing those shards across multiple nodes, Elasticsearch can ensure redundancy, which both protects against hardware failures and increases query capacity as nodes are added to a cluster. As the cluster grows (or shrinks), Elasticsearch automatically migrates shards to re-balance the cluster. Please refer to the official documentation here.number_of_replicas
is the number of replica shards. A replica shard is a copy of a primary shard. Elasticsearch will never assign a replica to the same node as the primary shard, so make sure you have more than one node in your Elasticsearch cluster if you need to use replica shards. The Elasticsearch cluster details and the quantity of nodes can be checked with:
GET _cluster/health\n
Since we use one node, the number_of_shards is 1 and number_of_replicas is 0. If you put more replicas within one node, your index will get yellow status in Kibana, yet still be working.
Create an empty index with write permissions:
Note
This index can also be created in GUI in Management
\u2192 Stack Management
\u2192 Index Management
\u2192 Indices
.
Index example with the date math format:
Index# URI encoded /<fluent-bit-kube-{now/d}-000001>\nPUT /%3Cfluent-bit-kube-%7Bnow%2Fd%7D-000001%3E\n{\n \"aliases\": {\n \"fluent-bit-kube\": {\n \"is_write_index\": true\n }\n }\n}\n
The code above will create an index in the{index_name}-{current_date}-{rollover_index_increment}
format. For example: fluent-bit-kube-2023.03.17-000001
.
Please refer to the official documentation on the index rollover with Date Math here.
Note
It is also possible to use index pattern below if the date math format does not seem applicable:
Index
PUT fluent-bit-kube-000001\n{\n \"aliases\": {\n \"fluent-bit-kube\": {\n \"is_write_index\": true\n }\n }\n}\n
Check the status of the created index:
GET fluent-bit-kube*-000001/_ilm/explain\n
Configure Fluent Bit. Play attention to the Elasticsearch Output plugin configuration.
The important fields in the [OUTPUT]
section are Index fluent-bit-kube
since we should use the index with the same name as Rollover Alias in Kibana and Logstash_Format Off
as we use the Rollover index pattern in Kibana that increments by 1.
ConfigMap example with Configuration Variables for HTTP_User
and HTTP_Passwd
:
data:\n fluent-bit.conf: |\n [SERVICE]\n Daemon Off\n Flush 10\n Log_Level info\n Parsers_File parsers.conf\n Parsers_File custom_parsers.conf\n HTTP_Server On\n HTTP_Listen 0.0.0.0\n HTTP_Port 2020\n Health_Check On\n\n [INPUT]\n Name tail\n Tag kube.*\n Path /var/log/containers/*.log\n Parser docker\n Mem_Buf_Limit 5MB\n Skip_Long_Lines Off\n Refresh_Interval 10\n [INPUT]\n Name systemd\n Tag host.*\n Systemd_Filter _SYSTEMD_UNIT=kubelet.service\n Read_From_Tail On\n Strip_Underscores On\n\n [FILTER]\n Name kubernetes\n Match kube.*\n Kube_Tag_Prefix kube.var.log.containers.\n Kube_URL https://kubernetes.default.svc:443\n Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token\n Merge_Log Off\n Merge_Log_Key log_processed\n K8S-Logging.Parser On\n K8S-Logging.Exclude On\n [FILTER]\n Name nest\n Match kube.*\n Operation lift\n Nested_under kubernetes\n Add_prefix kubernetes.\n [FILTER]\n Name modify\n Match kube.*\n Copy kubernetes.container_name tags.container\n Copy log message\n Copy kubernetes.container_image tags.image\n Copy kubernetes.namespace_name tags.namespace\n [FILTER]\n Name nest\n Match kube.*\n Operation nest\n Wildcard tags.*\n Nested_under tags\n Remove_prefix tags.\n\n [OUTPUT]\n Name es\n Match kube.*\n Index fluent-bit-kube\n Host elasticsearch-master\n Port 9200\n HTTP_User ${ES_USER}\n HTTP_Passwd ${ES_PASSWORD}\n Logstash_Format Off\n Time_Key @timestamp\n Type flb_type\n Replace_Dots On\n Retry_Limit False\n Trace_Error Off\n
Create index pattern (Data View starting from Kibana v8.0):
Go to Management
\u2192 Stack Management
\u2192 Kibana
\u2192 Index patterns
and create an index with the fluent-bit-kube-*
pattern:
Index Pattern
Check logs in Kibana. Navigate to Analytics
\u2192 Discover
:
Logs in Kibana
Note
In addition, in the top-right corner of the Discover
window, there is a button called Inspect
. Clicking on it will reveal the query that Kibana is sending to Elasticsearch. These queries can be used in Dev Tools.
Monitor the created indices:
GET _cat/indices/fluent-bit-kube-*\n
Note
Physically, the indices are located on the elasticsearch
Kubernetes pod in /usr/share/elasticsearch/data/nodes/0/indices
. It is recommended to backup indices only via Snapshots.
We've configured the index rollover process. Now the index will be rolled over to a new one once it reaches the indicated size or time in the policy, and old indices will be removed according to the policy as well.
When you create an empty index that corresponds to the pattern indicated in the index template, the index template attaches rollover_alias
with the fluent-bit-kube
name, policy and other configured data. Then the Fluent Bit Elasticsearch output plugin sends logs to the Index fluent-bit-kube
rollover alias. The index rollover process is managed by ILM that increments our indices united by the rollover_alias
and distributes the log data to the latest index.
It is also possible to manage index lifecycle without rollover indicated in the policy. If this is the case, this section will explain how to refactor the index to make it look that way: fluent-bit-kube-2023.03.18
.
Note
The main drawback of this method is that the indices can be managed only by their creation date.
To manage index lifecycle without rollover policy, follow the steps below:
Create a Policy without rollover
but with indices deletion:
PUT _ilm/policy/fluent-bit-policy\n{\n \"policy\": {\n \"phases\": {\n \"hot\": {\n \"min_age\": \"0ms\",\n \"actions\": {\n \"set_priority\": {\n \"priority\": 100\n }\n }\n },\n \"delete\": {\n \"min_age\": \"7d\",\n \"actions\": {\n \"delete\": {\n \"delete_searchable_snapshot\": true\n }\n }\n }\n }\n }\n}\n
Create an index template with the rollover_alias
parameter:
PUT /_index_template/fluent-bit\n{\n \"index_patterns\": [\"fluent-bit-kube-*\"],\n \"template\": {\n \"settings\": {\n \"index\": {\n \"lifecycle\": {\n \"name\": \"fluent-bit-policy\",\n \"rollover_alias\": \"fluent-bit-kube\"\n },\n \"number_of_shards\": \"1\",\n \"number_of_replicas\": \"0\"\n }\n }\n }\n}\n
Change the Fluent Bit [OUTPUT]
config to this one:
[OUTPUT]\n Name es\n Match kube.*\n Host elasticsearch-master\n Port 9200\n HTTP_User ${ES_USER}\n HTTP_Passwd ${ES_PASSWORD}\n Logstash_Format On\n Logstash_Prefix fluent-bit-kube\n Logstash_DateFormat %Y.%m.%d\n Time_Key @timestamp\n Type flb_type\n Replace_Dots On\n Retry_Limit False\n Trace_Error On\n
Restart Fluent Bit pods.
Fluent Bit will be producing a new index every day with the new date in its name like in the fluent-bit-kube-2023.03.18
name. Index deleting will be performed according to the policy.
If you experience a lot of difficulties when dealing with Fluent Bit, this section may help you.
Fluent Bit has docker images labelled -debug
, e.g., cr.fluentbit.io/fluent/fluent-bit:2.0.9-debug
.
Change that image in the Kubernetes Fluent Bit DaemonSet and add the Trace_Error On
parameter to the [OUTPUT]
section in the Fluent Bit configmap:
[OUTPUT]\n Trace_Error On\n
After adding the parameter above, you will start seeing more informative logs that will probably help you find out the reason of the problem.
"},{"location":"operator-guide/kibana-ilm-rollover/#related-articles","title":"Related Articles","text":"Make sure the cluster meets the following conditions:
Kubernetes cluster is installed with minimum 2 worker nodes with total capacity 8 Cores and 32Gb RAM.
Machine with kubectl is installed with a cluster-admin access to the Kubernetes cluster.
Ingress controller is installed in a cluster, for example ingress-nginx.
Ingress controller is configured with the disabled HTTP/2 protocol and header size of 64k support.
Find below an example of the Config Map for the NGINX Ingress controller:
kind: ConfigMap\napiVersion: v1\nmetadata:\n name: nginx-configuration\n namespace: ingress-nginx\n labels:\n app.kubernetes.io/name: ingress-nginx\n app.kubernetes.io/part-of: ingress-nginx\ndata:\n client-header-buffer-size: 64k\n large-client-header-buffers: 4 64k\n use-http2: \"false\"\n
Load balancer (if any exists in front of the Ingress controller) is configured with session stickiness, disabled HTTP/2 protocol and header size of 32k support.
Cluster nodes and pods have access to the cluster via external URLs. For instance, add in AWS the VPC NAT gateway elastic IP to the cluster external load balancers security group).
Keycloak instance is installed. To get accurate information on how to install Keycloak, please refer to the Install Keycloak instruction.
Helm 3.10 or higher is installed on the installation machine with the help of the Installing Helm instruction.
Storage classes are used with the Retain Reclaim Policy and Delete Reclaim Policy.
We recommended using our storage class as default storage class.
Info
By default, EDP uses the default Storage Class in a cluster. The EDP development team recommends using the following Storage Classes. See an example below.
Storage class templates with the Retain and Delete Reclaim Policies:
ebs-scgp3gp3-retainapiVersion: storage.k8s.io/v1\nkind: StorageClass\nmetadata:\n name: ebs-sc\n annotations:\n storageclass.kubernetes.io/is-default-class: 'true'\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Retain\nvolumeBindingMode: Immediate\n
kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: gp3\n annotations:\n storageclass.kubernetes.io/is-default-class: 'true'\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Delete\nvolumeBindingMode: Immediate\nallowVolumeExpansion: true\n
kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: gp3-retain\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Retain\nvolumeBindingMode: Immediate\nallowVolumeExpansion: true\n
Logsight can be integrated with the CI/CD pipeline. It connects to log data sources, analyses collected logs, and evaluates deployment risk scores.
"},{"location":"operator-guide/logsight-integration/#overview","title":"Overview","text":"In order to understand if a microservice or a component is ready for the deployment, EDP suggests analyzing logs via Logsight to decide if the deployment is risky or not.
Please find more about Logsight in the official documentation:
Integration with Logsight allows enhancing and optimizing software releases by creating an additional quality gate.
Logsight can be configured in two ways:
To work with Logsight, a new Deployment Risk stage must be added to the pipeline. On this stage, the logs are analyzed with the help of Logsight mechanisms.
On the verification screen of Logsight, continuous verification of the application deployment can be monitored, and tests can be compared for detecting test flakiness.
For example, two versions of a microservice can be compared in order to detect critical differences. Risk score will be calculated for the state reached by version A and version B. Afterwards, the deployment risk will be calculated based on individual risk scores.
If the deployment failure risk is greater than a predefined threshold, the verification gate blocks the deployment from going to the target environment. In such case, the Deployment Risk stage of the pipeline is not passed, and additional attention is required. The exact log messages can be displayed in the Logsight verification screen, to help debug the problem.
"},{"location":"operator-guide/logsight-integration/#use-logsight-for-edp-development","title":"Use Logsight for EDP Development","text":"Please find below the detailed description of Logsight integration with EDP.
"},{"location":"operator-guide/logsight-integration/#deployment-approach","title":"Deployment Approach","text":"EDP uses Logsight in a self-deploying mode.
Logsight provides a deployment approach using Helm charts. Please find below the stack of components that must be deployed:
logsight
\u00a0- the core component.logsight-backend
\u00a0- the backend that provides all necessary APIs and user management.logsight-frontend
\u00a0- the frontend that provides the user interface.logsight-result-api
\u00a0- responsible for obtaining results, for example, during the verification.Below is a diagram of interaction when integrating the components:
Logsight Structure
"},{"location":"operator-guide/logsight-integration/#configure-fluentbit-for-sending-log-data","title":"Configure FluentBit for Sending Log Data","text":"Logsight is integrated with the EDP logging stack. The integration is based on top of the EFK (ElasticSearch-FluentBit-Kibana) stack. It is necessary to deploy a stack with the security support, namely, enable the certificate support.
A FluentBit config indicates the namespace from which the logs will be received for further analysis. Below is an example of the FluentBit config for getting logs from the edp-delivery-edp-delivery-sit
namespace:
[INPUT]\n Name tail\n Tag kube.sit.*\n Path /var/log/containers/*edp-delivery-edp-delivery-sit*.log\n Parser docker\n Mem_Buf_Limit 5MB\n Skip_Long_Lines Off\n Refresh_Interval 10\n\n[FILTER]\n Name kubernetes\n Match kube.sit.*\n Kube_URL https://kubernetes.default.svc:443\n Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token\n Kube_Tag_Prefix kube.sit.var.log.containers.\n Merge_Log Off\n K8S-Logging.Parser On\n K8S-Logging.Exclude On\n\n[FILTER]\n Name nest\n Match kube.sit.*\n Operation lift\n Nested_under kubernetes\n Add_prefix kubernetes.\n\n[FILTER]\n Name modify\n Match kube.sit.*\n Copy kubernetes.container_name tags.container\n Copy log message\n Copy kubernetes.container_image tags.image\n Copy kubernetes.namespace_name tags.namespace\n\n[FILTER]\n Name nest\n Match kube.sit.*\n Operation nest\n Wildcard kubernetes.*\n Nested_under kubernetes\n Remove_prefix kubernetes.\n\n[OUTPUT]\n Name es\n Match kube.sit.*\n Host elasticsearch-master\n Port 9200\n HTTP_User elastic\n HTTP_Passwd *****\n Logstash_Format On\n Logstash_Prefix sit\n Time_Key @timestamp\n Type flb_type\n Replace_Dots On\n Retry_Limit False\n\n[OUTPUT]\n Match kube.sit.*\n Name http\n Host logsight-backend\n Port 8080\n http_User logsight@example.com\n http_Passwd *****\n uri /api/v1/logs/singles\n Format json\n json_date_format iso8601\n json_date_key timestamp\n
"},{"location":"operator-guide/logsight-integration/#deployment-risk-analysis","title":"Deployment Risk Analysis","text":"A deployment-risk
stage is added to the EDP CD pipeline.
Deployment Risk
If the deployment risk is above 70%, the red state of the pipeline is expected.
EDP consists of a set of containerized components. For the convenience of tracking the risk deployment trend for each component, this data is stored as Jenkins artifacts.
If the deployment risk is higher than the threshold of 70%, the EDP promotion of artifacts for the next environments does not pass. The deployment risk report can be analyzed in order to avoid the potential problems with updating the components.
To study the report in detail, use the link from the Jenkins pipeline to the Logsight verification screen:
Logsight Insights Logsight Insights
In this example, logs from different versions of the gerrit-operator
were analyzed. As can be seen from the report, a large number of new messages appeared in the logs, and the output frequency of other notifications has also changed, which led to the high deployment risk.
The environment on which the analysis is performed can exist for different time periods. Logsight only processes the minimum total number of logs since the creating of the environment.
"},{"location":"operator-guide/logsight-integration/#related-articles","title":"Related Articles","text":"Note
Make sure that IRSA is enabled and amazon-eks-pod-identity-webhook is deployed according to the Associate IAM Roles With Service Accounts documentation.
It is possible to use Amazon Simple Storage Service Amazon S3 as object storage for Loki. In this case Loki requires access to AWS resources. Follow the steps below to create a required role:
Create AWS IAM Policy \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki_policy\":
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ListObjects\",\n \"s3:ListBucket\",\n \"s3:PutObject\",\n \"s3:GetObject\",\n \"s3:DeleteObject\"\n ],\n \"Resource\": [\n \"arn:aws:s3:::loki-*\"\n ]\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ListBucket\"\n ],\n \"Resource\": [\n \"arn:aws:s3:::loki-*\"\n ]\n }\n ]\n}\n
Create AWS IAM Role \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki\" with trust relationships:
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER>\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"<OIDC_PROVIDER>:sub\": \"system:serviceaccount:<LOKI_NAMESPACE>:edp-loki\"\n }\n }\n }\n ]\n}\n
Attach the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki_policy\" policy to the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki\" role.
Make sure that Amazon S3 bucket with name loki-\u2039CLUSTER_NAME\u203a exists.
Provide key value eks.amazonaws.com/role-arn: \"arn:aws:iam:::role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki\" into the serviceAccount.annotations parameter in values.yaml during the Loki Installation.
Familiarize yourself with the detailed instructions on adding certificates to EDP resources as well as with the respective setup for Keycloak.
EDP components that support custom certificates can be found in the table below:
Helm Chart Sub Resources admin-console-operator admin-console gerrit-operator edp-gerrit jenkins-operator jenkins-operator, edp-jenkins, jenkins agents sonar-operator sonar-operator, edp-sonar keycloak-operator keycloak-operator nexus-operator oauth2-proxy edp-install oauth2-proxy edp-headlamp edp-headlamp"},{"location":"operator-guide/manage-custom-certificate/#prerequisites","title":"Prerequisites","text":"*.crt
format is used;keytool
command inside;To import custom certificates to Keycloak, follow the steps below:
Generate the cacerts
local keystore and import the certificate there using the keytool tool:
keytool -importcert -file CA.crt \\\n -alias CA.crt -keystore ./cacerts \\\n -storepass changeit -trustcacerts \\\n -noprompt\n
Create the custom-keycloak-keystore
keystore secret from the cacerts
file in the security
namespace:
kubectl -n security create secret generic custom-keycloak-keystore \\\n--from-file=./cacerts\n
Create the spi-truststore-data
SPI truststore secret in the security
namespace:
kubectl -n security create secret generic spi-truststore-data \\\n--from-literal=KC_SPI_TRUSTSTORE_FILE_FILE=/opt/keycloak/spi-certs/cacerts \\\n--from-literal=KC_SPI_TRUSTSTORE_FILE_PASSWORD=changeit\n
Update the Keycloak values.yaml
file from the Install Keycloak page.
...\nextraVolumeMounts: |\n ...\n # Use the Keycloak truststore for SPI connection over HTTPS/TLS\n - name: spi-certificates\n mountPath: /opt/keycloak/spi-certs\n readOnly: true\n ...\n\nextraVolumes: |\n ...\n # Use the Keycloak truststore for SPI connection over HTTPS/TLS\n - name: spi-certificates\n secret:\n secretName: custom-keycloak-keystore\n defaultMode: 420\n ...\n\n...\nextraEnvFrom: |\n - secretRef:\n name: spi-truststore-data\n...\n
Creating custom certificates is a necessary but not sufficient condition for applying, therefore, certificates should be enabled as well.
Create the custom-ca-certificates
secret in the EDP namespace.
kubectl -n edp create secret generic custom-ca-certificates \\\n--from-file=CA.crt\n
Add the certificate by mounting the custom-ca-certificates
secret to the operator pod as a volume.
Example of specifying custom certificates for the keycloak-operator
:
...\nkeycloak-operator:\n enabled: true\n\n # -- Additional volumes to be added to the pod\n extraVolumes:\n - name: custom-ca\n secret:\n defaultMode: 420\n secretName: custom-ca-certificates\n\n # -- Additional volumeMounts to be added to the container\n extraVolumeMounts:\n - name: custom-ca\n mountPath: /etc/ssl/certs/CA.crt\n readOnly: true\n subPath: CA.crt\n...\n
Note
Before moving ahead, be aware that starting from version 3.3.0, our development team has officially deprecated the Jenkins deploy scenario. This means that as of version 3.3.0 and in all subsequent versions (3.3.x and above), the Jenkins deploy scenario is no longer supported or actively maintained. For users running versions 3.3.x and below, the Jenkins deploy scenario remains available. However, we encourage you to plan for the transition to a supported deployment method to ensure continued compatibility and access to the latest features and enhancements. To perform migration, please familiarize yourself with the Migrate CI Pipelines From Jenkins to Tekton. For those who still use EDP v3.3.x and below, the information below remains valid and applicable.
For Sonar, Jenkins and Gerrit, change the flag in the caCerts.enabled
field to true
. Also, change the name of the secret in the caCerts.secret
field to custom-ca-certificates
.
Example of specifying custom certificates for Gerrit
via the gerrit-operator
helm chart values:
...\ngerrit-operator:\n enabled: true\n gerrit:\n caCerts:\n # -- Flag for enabling additional CA certificates\n enabled: true\n # -- Change init CA certificates container image\n image: adoptopenjdk/openjdk11:alpine\n # -- Name of the secret containing additional CA certificates\n secret: custom-ca-certificates\n...\n
This section describes how to add custom certificates to Jenkins agents to use them from Java applications.
Info
For example, curl
doesn't use keystore files specified in this part of the documentation.
EDP Jenkins agents keep keystore files in two places:
/etc/ssl/certs/java
folder with the cacerts
file;/opt/java/openjdk/lib/security
folder with the blocked.certs
, cacerts
, default.policy
and public_suffix_list.dat
files.Copy the files in /etc/ssl/certs/java
and /opt/java/openjdk/lib/security
directories from Jenkins agent pod to the local tmp
folder. There is a copy_certs.sh
script below that can manage this. It copies the files in /etc/ssl/certs/java
and /opt/java/openjdk/lib/security
directories from Jenkins agent pod to the local tmp
folder and imports the custom certificate into the keystore files, after which it creates the jenkins-agent-opt-java-openjdk-lib-security-cacerts
and jenkins-agent-etc-ssl-certs-java-cacerts
secrets from updated keystore files in EDP namespace. Also, the jenkins-agent-opt-java-openjdk-lib-security-cacerts
secret contains three additional files: blocked.certs
, default.policy
and public_suffix_list.dat
which managed by the copy_certs.sh
script as well. Expand the drop-down button below to see the contents of the copy_certs.sh
script.
# Fill in the variables `ns` and `ca_file`\nns=\"edp-project\"\nca_file=\"/tmp/CA.crt\"\n\nimages=$(kubectl get -n \"${ns}\" cm jenkins-slaves -ojson | jq -r \".data[]\" | grep image\\> | sed 's/\\s*<.*>\\(.*\\)<.*>/\\1/')\n\nimage=$(for i in ${images[@]}; do echo $i; done | grep maven-java8)\npod_name=$(echo \"${image}\" | tr '.:/' '-')\n\noverrides=\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"kind\\\":\\\"Pod\\\",\\\"metadata\\\":{\\\"name\\\":\\\"${pod_name}\\\", \\\"namespace\\\": \\\"${ns}\\\"},\n\\\"spec\\\":{\\\"containers\\\":[{\\\"name\\\":\\\"${pod_name}\\\",\\\"image\\\":\\\"${image}\\\",\n\\\"command\\\":[\\\"sh\\\",\\\"-c\\\",\\\"while true;do sleep 30;done;\\\"]}]}}\"\n\nkubectl run -n \"${ns}\" \"${pod_name}\" --image \"${image}\" --overrides=\"${overrides}\"\n\nkubectl wait --for=condition=ready pod \"${pod_name}\" -n \"${ns}\"\n\ncacerts_location=$(kubectl exec -n \"${ns}\" \"${pod_name}\" \\\n -- find / -name cacerts -exec ls -la \"{}\" \\; 2>/dev/null | grep -v ^l | awk '{print $9}')\n\nfor cacerts in ${cacerts_location[@]}; do echo $(dirname \"${cacerts}\"); kubectl exec -n \"${ns}\" \"${pod_name}\" -- ls $(dirname \"${cacerts}\"); done\n\nfor cacerts in ${cacerts_location[@]}; do \\\n echo $(dirname \"${cacerts}\"); \\\n mkdir -p \"/tmp$(dirname \"${cacerts}\")\"; \\\n from_files=''; \\\n for file in $(kubectl exec -n \"${ns}\" \"${pod_name}\" -- ls $(dirname \"${cacerts}\")); do \\\n kubectl exec -n \"${ns}\" \"${pod_name}\" -- cat \"$(dirname \"${cacerts}\")/${file}\" > \"/tmp$(dirname \"${cacerts}\")/${file}\"; \\\n from_files=\"${from_files} --from-file=/tmp$(dirname \"${cacerts}\")/${file}\"\n done ; \\\n keytool -import -storepass changeit -alias kubernetes -file ${ca_file} -noprompt -keystore \"/tmp${cacerts}\"; \\\n kubectl -n \"${ns}\" create secret generic \"jenkins-agent${cacerts//\\//-}\" $from_files \\\ndone\n\nkubectl delete -n \"${ns}\" pod \"${pod_name}\" --force --grace-period=0\n
Before using the copy_certs.sh
script, keep in mind the following:
ns
and ca_file
;jenkins-slaves
ConfigMap and uses the image of the maven-java8
agent as the base image of the temporary pod to get the keystore files;keytool
application;jenkins-agent-opt-java-openjdk-lib-security-cacerts
and jenkins-agent-etc-ssl-certs-java-cacerts
secrets will be created in the EDP namespace.Run the copy_certs.sh
script from the previous point after the requirements are met.
Update manually the jenkins-slaves
ConfigMap.
Add this block with the mount of secrets to the <volumes></volumes>
block of each Jenkins agent:
...\n <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <mountPath>/etc/ssl/certs/java</mountPath>\n <secretName>jenkins-agent-etc-ssl-certs-java-cacerts</secretName>\n </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <mountPath>/opt/java/openjdk/lib/security</mountPath>\n <secretName>jenkins-agent-opt-java-openjdk-lib-security-cacerts</secretName>\n </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n...\n
As an example, the template of gradle-java11-template
is shown below:
...\n </workspaceVolume>\n <volumes>\n <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <mountPath>/etc/ssl/certs/java</mountPath>\n <secretName>jenkins-agent-etc-ssl-certs-java-cacerts</secretName>\n </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <mountPath>/opt/java/openjdk/lib/security</mountPath>\n <secretName>jenkins-agent-opt-java-openjdk-lib-security-cacerts</secretName>\n </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n </volumes>\n <containers>\n...\n
Reload the Jenkins pod:
ns=\"edp\"\nkubectl rollout restart -n \"${ns}\" deployment/jenkins\n
The Jenkins CD job provisioner (or seed-job) is used to create and manage the cd-pipeline folder, and its Deploy pipelines. There is a special job-provisions/cd folder in Jenkins for these provisioners. Explore the steps for managing different provisioner types below.
"},{"location":"operator-guide/manage-jenkins-cd-job-provision/#default","title":"Default","text":"During the EDP deployment, a default provisioner is created to deploy application with container and custom deployment type.
Find the configuration in job-provisions/cd/default.
Default template is presented below:
View: Default template/* Copyright 2022 EPAM Systems.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nimport groovy.json.*\nimport jenkins.model.Jenkins\n\nJenkins jenkins = Jenkins.instance\n\ndef pipelineName = \"${PIPELINE_NAME}-cd-pipeline\"\ndef stageName = \"${STAGE_NAME}\"\ndef qgStages = \"${QG_STAGES}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID}\"\ndef sourceType = \"${SOURCE_TYPE}\"\ndef libraryURL = \"${LIBRARY_URL}\"\ndef libraryBranch = \"${LIBRARY_BRANCH}\"\ndef isAutoDeploy = \"${AUTODEPLOY}\"\ndef scriptPath = \"Jenkinsfile\"\ndef containerDeploymentType = \"container\"\ndef deploymentType = \"${DEPLOYMENT_TYPE}\"\ndef codebaseFolder = jenkins.getItem(pipelineName)\n\ndef autoDeploy = '{\"name\":\"auto-deploy-input\",\"step_name\":\"auto-deploy-input\"}'\ndef manualDeploy = '{\"name\":\"manual-deploy-input\",\"step_name\":\"manual-deploy-input\"}'\ndef runType = isAutoDeploy.toBoolean() ? autoDeploy : manualDeploy\n\ndef stages = buildStages(deploymentType, containerDeploymentType, qgStages, runType)\n\nif (codebaseFolder == null) {\n folder(pipelineName)\n}\n\nif (deploymentType == containerDeploymentType) {\n createContainerizedCdPipeline(pipelineName, stageName, stages, scriptPath, sourceType,\n libraryURL, libraryBranch, gitCredentialsId, gitServerCrVersion,\n isAutoDeploy)\n} else {\n createCustomCdPipeline(pipelineName, stageName)\n}\n\ndef buildStages(deploymentType, containerDeploymentType, qgStages, runType) {\n return deploymentType == containerDeploymentType\n ? '[{\"name\":\"init\",\"step_name\":\"init\"},' + runType + ',{\"name\":\"deploy\",\"step_name\":\"deploy\"},' + qgStages + ',{\"name\":\"promote-images\",\"step_name\":\"promote-images\"}]'\n : ''\n}\n\ndef createContainerizedCdPipeline(pipelineName, stageName, stages, pipelineScript, sourceType, libraryURL, libraryBranch, libraryCredId, gitServerCrVersion, isAutoDeploy) {\n pipelineJob(\"${pipelineName}/${stageName}\") {\n if (sourceType == \"library\") {\n definition {\n cpsScm {\n scm {\n git {\n remote {\n url(libraryURL)\n credentials(libraryCredId)\n }\n branches(\"${libraryBranch}\")\n scriptPath(\"${pipelineScript}\")\n }\n }\n }\n }\n } else {\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\nDeploy()\")\n sandbox(true)\n }\n }\n }\n properties {\n disableConcurrentBuilds()\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${stages}\", \"Consequence of stages in JSON format to be run during execution\")\n\n if (isAutoDeploy?.trim() && isAutoDeploy.toBoolean()) {\n stringParam(\"CODEBASE_VERSION\", null, \"Codebase versions to deploy.\")\n }\n }\n }\n}\n\ndef createCustomCdPipeline(pipelineName, stageName) {\n pipelineJob(\"${pipelineName}/${stageName}\") {\n properties {\n disableConcurrentBuilds()\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n }\n }\n}\n
In some cases, it is necessary to modify or update the job provisioner logic. For example, when adding a new stage requires a custom job provisioner created on the basis of an existing one out of the box. Take the steps below to add a custom job provision.
Navigate to the Jenkins main page and open the job-provisions/cd folder, click New Item and type the name of job provisions, for example - custom.
CD provisioner name
Scroll down to the Copy from field, enter \"/job-provisions/cd/default\", and click OK: Copy CD provisioner
Update the required parameters in the new provisioner. For example, if it is necessary to implement a new stage clean, add the following code to the provisioner:
def buildStages(deploymentType, containerDeploymentType, qgStages) {\n return deploymentType == containerDeploymentType\n ? '[{\"name\":\"init\",\"step_name\":\"init\"},{\"name\":\"clean\",\"step_name\":\"clean\"},{\"name\":\"deploy\",\"step_name\":\"deploy\"},' + qgStages + ',{\"name\":\"promote-images-ecr\",\"step_name\":\"promote-images\"}]'\n : ''\n }\n
Note
Make sure the support for the above mentioned logic is implemented. Please refer to the How to Redefine or Extend the EDP Pipeline Stages Library section of the guide.
After the steps above are performed, the new custom job-provision will be available in Adding Stage during the CD pipeline creation in Admin Console.
Custom CD provision
The Jenkins CI job provisioner (or seed-job) is used to create and manage the application folder, and its Code Review, Build and Create Release pipelines. Depending on the version control system, different job provisioners are used. EDP supports integration with the following version control systems:
By default, the Jenkins operator creates a pipeline for several types of application and libraries. There is a special job-provisions/ci folder in Jenkins for these provisioners. During the EDP deployment, a default provisioner is created for integration with Gerrit version control system. To configure integration with other version control systems, you need to add the required job provisioners to job-provisions/ci folder in Jenkins.
"},{"location":"operator-guide/manage-jenkins-ci-job-provision/#create-custom-provisioner-custom-defaultgithubgitlab","title":"Create Custom Provisioner (custom-default/github/gitlab)","text":"In some cases it is necessary to modify or update the job provisioner logic, for example when an added other code language needs to create a custom job provisioner on the basis of an existing one out of the box. Take the steps below to add a custom job provision:
Navigate to the Jenkins main page and open the job-provisions/ci folder, click New Item and type the name of job-provisions, for example - custom-github.
CI provisioner name
Scroll down to the Copy from field and enter \"/job-provisions/ci/github\", and click OK: Copy ci provisioner
Update the required parameters in the new provisioner. For example, if it is necessary to implement a new build tool docker, several parameters are to be updated. Add the following stages to the docker Code Review and Build pipelines for docker application:
stages['Code-review-application-docker'] = '[{\"name\": \"checkout\"},{\"name\": \"lint\"},{\"name\": \"build\"}]'\n...\nstages['Build-application-docker'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"lint\"},{\"name\": \"build\"},{\"name\": \"push\"},{\"name\": \"git-tag\"}]'\n...\ndef getStageKeyName(buildTool) {\n ...\n if (buildTool.toString().equalsIgnoreCase('docker')) {\n return \"Code-review-application-docker\"\n }\n ...\n}\n
Note
Make sure the support for the above mentioned logic is implemented. Please refer to the How to Redefine or Extend the EDP Pipeline Stages Library section of the guide.
Note
The default template should be changed if there is another creation logic for the Code Review, Build and Create Release pipelines. Furthermore, all pipeline types should have the necessary stages as well.
After the steps above are performed, the new custom job provision will be available in Advanced Settings during the application creation in the EDP Portal UI:
Custom ci provision
During the EDP deployment, a default provisioner is created for integration with Gerrit version control system.
Find the configuration in job-provisions/ci/default.
Default template is presented below:
View: Default template/* Copyright 2022 EPAM Systems.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nimport groovy.json.*\nimport jenkins.model.Jenkins\n\nJenkins jenkins = Jenkins.instance\ndef stages = [:]\ndef jiraIntegrationEnabled = Boolean.parseBoolean(\"${JIRA_INTEGRATION_ENABLED}\" as String)\ndef commitValidateStage = jiraIntegrationEnabled ? ',{\"name\": \"commit-validate\"}' : ''\ndef createJIMStage = jiraIntegrationEnabled ? ',{\"name\": \"create-jira-issue-metadata\"}' : ''\ndef platformType = \"${PLATFORM_TYPE}\"\ndef buildStage = platformType.toString() == \"kubernetes\" ? ',{\"name\": \"build-image-kaniko\"}' : ',{\"name\": \"build-image-from-dockerfile\"}'\ndef buildTool = \"${BUILD_TOOL}\"\ndef goBuildStage = buildTool.toString() == \"go\" ? ',{\"name\": \"build\"}' : ',{\"name\": \"compile\"}'\n\nstages['Code-review-application'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + goBuildStage +\n ',{\"name\": \"tests\"},[{\"name\": \"sonar\"},{\"name\": \"dockerfile-lint\"},{\"name\": \"helm-lint\"}]]'\nstages['Code-review-library'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"compile\"},{\"name\": \"tests\"},{\"name\": \"sonar\"}]'\nstages['Code-review-autotests'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"},{\"name\": \"sonar\"}' + ']'\nstages['Code-review-default'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + ']'\nstages['Code-review-library-terraform'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"terraform-lint\"}]'\nstages['Code-review-library-opa'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"}]'\nstages['Code-review-library-codenarc'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}]'\nstages['Code-review-library-kaniko'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"dockerbuild-verify\"}]'\n\nstages['Build-library-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-npm'] = stages['Build-library-maven']\nstages['Build-library-gradle'] = stages['Build-library-maven']\nstages['Build-library-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"terraform-lint\"}' +\n ',{\"name\": \"terraform-plan\"},{\"name\": \"terraform-apply\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-opa'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"tests\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-codenarc'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-kaniko\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-autotests-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-autotests-gradle'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-application-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-npm'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-gradle'] = stages['Build-application-maven']\nstages['Build-application-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-go'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"tests\"}' +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"}' +\n \"${buildStage}\" + ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Create-release'] = '[{\"name\": \"checkout\"},{\"name\": \"create-branch\"},{\"name\": \"trigger-job\"}]'\n\ndef defaultBuild = '[{\"name\": \"checkout\"}' + \"${createJIMStage}\" + ']'\n\ndef codebaseName = \"${NAME}\"\ndef gitServerCrName = \"${GIT_SERVER_CR_NAME}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}\"\ndef repositoryPath = \"${REPOSITORY_PATH}\"\ndef defaultBranch = \"${DEFAULT_BRANCH}\"\n\ndef codebaseFolder = jenkins.getItem(codebaseName)\nif (codebaseFolder == null) {\n folder(codebaseName)\n}\n\ncreateListView(codebaseName, \"Releases\")\ncreateReleasePipeline(\"Create-release-${codebaseName}\", codebaseName, stages[\"Create-release\"], \"CreateRelease\",\n repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch)\n\nif (buildTool.toString().equalsIgnoreCase('none')) {\n return true\n}\n\nif (BRANCH) {\n def branch = \"${BRANCH}\"\n def formattedBranch = \"${branch.toUpperCase().replaceAll(/\\//, \"-\")}\"\n createListView(codebaseName, formattedBranch)\n\n def type = \"${TYPE}\"\n def crKey = getStageKeyName(buildTool)\n createCiPipeline(\"Code-review-${codebaseName}\", codebaseName, stages[crKey], \"CodeReview\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n def buildKey = \"Build-${type}-${buildTool.toLowerCase()}\".toString()\n if (type.equalsIgnoreCase('application') || type.equalsIgnoreCase('library') || type.equalsIgnoreCase('autotests')) {\n def jobExists = false\n if(\"${formattedBranch}-Build-${codebaseName}\".toString() in Jenkins.instance.getAllItems().collect{it.name})\n jobExists = true\n\n createCiPipeline(\"Build-${codebaseName}\", codebaseName, stages.get(buildKey, defaultBuild), \"Build\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n if(!jobExists)\n queue(\"${codebaseName}/${formattedBranch}-Build-${codebaseName}\")\n }\n}\n\ndef createCiPipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId, watchBranch, gitServerCrName, gitServerCrVersion) {\n pipelineJob(\"${codebaseName}/${watchBranch.toUpperCase().replaceAll(/\\//, \"-\")}-${pipelineName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n triggers {\n gerrit {\n events {\n if (pipelineName.contains(\"Build\"))\n changeMerged()\n else\n patchsetCreated()\n }\n project(\"plain:${codebaseName}\", [\"plain:${watchBranch}\"])\n }\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n stringParam(\"BRANCH\", \"${watchBranch}\", \"Branch to build artifact from\")\n }\n }\n }\n}\n\ndef getStageKeyName(buildTool) {\n if (buildTool.toString().equalsIgnoreCase('terraform')) {\n return \"Code-review-library-terraform\"\n }\n if (buildTool.toString().equalsIgnoreCase('opa')) {\n return \"Code-review-library-opa\"\n }\n if (buildTool.toString().equalsIgnoreCase('codenarc')) {\n return \"Code-review-library-codenarc\"\n }\n if (buildTool.toString().equalsIgnoreCase('kaniko')) {\n return \"Code-review-library-kaniko\"\n }\n def buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n return supBuildTool ? \"Code-review-${TYPE}\" : \"Code-review-default\"\n}\n\ndef createReleasePipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId,\n gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch) {\n pipelineJob(\"${codebaseName}/${pipelineName}\") {\n logRotator {\n numToKeep(14)\n daysToKeep(30)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"STAGES\", \"${codebaseStages}\", \"\")\n if (pipelineName.contains(\"Create-release\")) {\n stringParam(\"JIRA_INTEGRATION_ENABLED\", \"${jiraIntegrationEnabled}\", \"Is Jira integration enabled\")\n stringParam(\"PLATFORM_TYPE\", \"${platformType}\", \"Platform type\")\n stringParam(\"GERRIT_PROJECT\", \"${codebaseName}\", \"\")\n stringParam(\"RELEASE_NAME\", \"\", \"Name of the release(branch to be created)\")\n stringParam(\"COMMIT_ID\", \"\", \"Commit ID that will be used to create branch from for new release. If empty, DEFAULT_BRANCH will be used\")\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"REPOSITORY_PATH\", \"${repository}\", \"Full repository path\")\n stringParam(\"DEFAULT_BRANCH\", \"${defaultBranch}\", \"Default repository branch\")\n }\n }\n }\n }\n}\n\ndef createListView(codebaseName, branchName) {\n listView(\"${codebaseName}/${branchName}\") {\n if (branchName.toLowerCase() == \"releases\") {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^Create-release.*\")\n }\n }\n } else {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^${branchName}-(Code-review|Build).*\")\n }\n }\n }\n columns {\n status()\n weather()\n name()\n lastSuccess()\n lastFailure()\n lastDuration()\n buildButton()\n }\n }\n}\n
Job Provision Pipeline Parameters
The job-provisions pipeline consists of the following parameters of type string:
To create a new job provision for work with GitHub, take the following steps:
Navigate to the Jenkins main page and open the job-provisions/ci folder.
Click New Item and type the name of job-provisions - github.
Select the Freestyle project option and click OK.
Select the Discard old builds check box and configure a few parameters:
Strategy: Log Rotation
Days to keep builds: 10
Max # of builds to keep: 10
Select the This project is parameterized check box and add a few input parameters (the type of the variables is string):
Check the Execute concurrent builds if necessary option.
Check the Restrict where this project can be run option.
Fill in the Label Expression field by typing master to ensure job runs on Jenkins Master.
In the Build section, perform the following:
DSL script check box
As soon as all the steps above are performed, insert the code:
View: Templateimport groovy.json.*\nimport jenkins.model.Jenkins\nimport javaposse.jobdsl.plugin.*\nimport com.cloudbees.hudson.plugins.folder.*\n\nJenkins jenkins = Jenkins.instance\ndef stages = [:]\ndef jiraIntegrationEnabled = Boolean.parseBoolean(\"${JIRA_INTEGRATION_ENABLED}\" as String)\ndef commitValidateStage = jiraIntegrationEnabled ? ',{\"name\": \"commit-validate\"}' : ''\ndef createJIMStage = jiraIntegrationEnabled ? ',{\"name\": \"create-jira-issue-metadata\"}' : ''\ndef platformType = \"${PLATFORM_TYPE}\"\ndef buildStage = platformType == \"kubernetes\" ? ',{\"name\": \"build-image-kaniko\"}' : ',{\"name\": \"build-image-from-dockerfile\"}'\ndef buildTool = \"${BUILD_TOOL}\"\ndef goBuildStage = buildTool.toString() == \"go\" ? ',{\"name\": \"build\"}' : ',{\"name\": \"compile\"}'\n\nstages['Code-review-application'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" + goBuildStage +\n ',{\"name\": \"tests\"},[{\"name\": \"sonar\"},{\"name\": \"dockerfile-lint\"},{\"name\": \"helm-lint\"}]]'\nstages['Code-review-library'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"compile\"},{\"name\": \"tests\"},' +\n '{\"name\": \"sonar\"}]'\nstages['Code-review-autotests'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"},{\"name\": \"sonar\"}' + ']'\nstages['Code-review-default'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" + ']'\nstages['Code-review-library-terraform'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"terraform-lint\"}]'\nstages['Code-review-library-opa'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"}]'\nstages['Code-review-library-codenarc'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}]'\nstages['Code-review-library-kaniko'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"dockerbuild-verify\"}]'\n\nstages['Build-library-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-npm'] = stages['Build-library-maven']\nstages['Build-library-gradle'] = stages['Build-library-maven']\nstages['Build-library-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"terraform-lint\"}' +\n ',{\"name\": \"terraform-plan\"},{\"name\": \"terraform-apply\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-opa'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"tests\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-codenarc'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-kaniko\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-autotests-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-autotests-gradle'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-application-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-npm'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-gradle'] = stages['Build-application-maven']\nstages['Build-application-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-go'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"tests\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build\"}' + \"${buildStage}\" + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},{\"name\": \"tests\"},{\"name\": \"sonar\"}' +\n \"${buildStage}\" + ',{\"name\":\"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Create-release'] = '[{\"name\": \"checkout\"},{\"name\": \"create-branch\"},{\"name\": \"trigger-job\"}]'\n\ndef buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\ndef defaultStages = '[{\"name\": \"checkout\"}' + \"${createJIMStage}\" + ']'\n\ndef codebaseName = \"${NAME}\"\ndef gitServerCrName = \"${GIT_SERVER_CR_NAME}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}\"\ndef repositoryPath = \"${REPOSITORY_PATH.replaceAll(~/:\\d+\\\\//,\"/\")}\"\ndef githubRepository = \"https://${repositoryPath.split(\"@\")[1]}\"\ndef defaultBranch = \"${DEFAULT_BRANCH}\"\n\ndef codebaseFolder = jenkins.getItem(codebaseName)\nif (codebaseFolder == null) {\n folder(codebaseName)\n}\n\ncreateListView(codebaseName, \"Releases\")\ncreateReleasePipeline(\"Create-release-${codebaseName}\", codebaseName, stages[\"Create-release\"], \"CreateRelease\",\n repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch)\n\nif (buildTool.toString().equalsIgnoreCase('none')) {\n return true\n}\n\nif (BRANCH) {\n def branch = \"${BRANCH}\"\n def formattedBranch = \"${branch.toUpperCase().replaceAll(/\\\\//, \"-\")}\"\n createListView(codebaseName, formattedBranch)\n\n def type = \"${TYPE}\"\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n def crKey = getStageKeyName(buildTool).toString()\n createCodeReviewPipeline(\"Code-review-${codebaseName}\", codebaseName, stages.get(crKey, defaultStages), \"CodeReview\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, githubRepository)\n registerWebHook(repositoryPath)\n\n\n def buildKey = \"Build-${type}-${buildTool.toLowerCase()}\".toString()\n\n if (type.equalsIgnoreCase('application') || type.equalsIgnoreCase('library') || type.equalsIgnoreCase('autotests')) {\n def jobExists = false\n if(\"${formattedBranch}-Build-${codebaseName}\".toString() in Jenkins.instance.getAllItems().collect{it.name})\n jobExists = true\n createBuildPipeline(\"Build-${codebaseName}\", codebaseName, stages.get(buildKey, defaultStages), \"Build\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, githubRepository)\n registerWebHook(repositoryPath, 'build')\n\n if(!jobExists)\n queue(\"${codebaseName}/${formattedBranch}-Build-${codebaseName}\")\n }\n}\n\ndef getStageKeyName(buildTool) {\n if (buildTool.toString().equalsIgnoreCase('terraform')) {\n return \"Code-review-library-terraform\"\n }\n if (buildTool.toString().equalsIgnoreCase('opa')) {\n return \"Code-review-library-opa\"\n }\n if (buildTool.toString().equalsIgnoreCase('codenarc')) {\n return \"Code-review-library-codenarc\"\n }\n if (buildTool.toString().equalsIgnoreCase('kaniko')) {\n return \"Code-review-library-kaniko\"\n }\n def buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n return supBuildTool ? \"Code-review-${TYPE}\" : \"Code-review-default\"\n}\n\ndef createCodeReviewPipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId, defaultBranch, gitServerCrName, gitServerCrVersion, githubRepository) {\n pipelineJob(\"${codebaseName}/${defaultBranch.toUpperCase().replaceAll(/\\\\//, \"-\")}-${pipelineName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n if (pipelineName.contains(\"Build\"))\n stringParam(\"BRANCH\", \"${defaultBranch}\", \"Branch to build artifact from\")\n else\n stringParam(\"BRANCH\", \"\\${ghprbActualCommit}\", \"Branch to build artifact from\")\n }\n }\n triggers {\n githubPullRequest {\n cron('')\n onlyTriggerPhrase(false)\n useGitHubHooks(true)\n permitAll(true)\n autoCloseFailedPullRequests(false)\n displayBuildErrorsOnDownstreamBuilds(false)\n whiteListTargetBranches([defaultBranch.toString()])\n extensions {\n commitStatus {\n context('Jenkins Code-Review')\n triggeredStatus('Build is Triggered')\n startedStatus('Build is Started')\n addTestResults(true)\n completedStatus('SUCCESS', 'Verified')\n completedStatus('FAILURE', 'Failed')\n completedStatus('PENDING', 'Penging')\n completedStatus('ERROR', 'Error')\n }\n }\n }\n }\n properties {\n githubProjectProperty {\n projectUrlStr(\"${githubRepository}\")\n }\n }\n }\n}\n\ndef createBuildPipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId, defaultBranch, gitServerCrName, gitServerCrVersion, githubRepository) {\n pipelineJob(\"${codebaseName}/${defaultBranch.toUpperCase().replaceAll(/\\\\//, \"-\")}-${pipelineName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\nnode {\\n git credentialsId: \\'${credId}\\', url: \\'${repository}\\', branch: \\'${BRANCH}\\'\\n}\\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n stringParam(\"BRANCH\", \"${defaultBranch}\", \"Branch to run from\")\n }\n }\n triggers {\n gitHubPushTrigger()\n }\n properties {\n githubProjectProperty {\n projectUrlStr(\"${githubRepository}\")\n }\n }\n }\n}\n\n\ndef createListView(codebaseName, branchName) {\n listView(\"${codebaseName}/${branchName}\") {\n if (branchName.toLowerCase() == \"releases\") {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^Create-release.*\")\n }\n }\n } else {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^${branchName}-(Code-review|Build).*\")\n }\n }\n }\n columns {\n status()\n weather()\n name()\n lastSuccess()\n lastFailure()\n lastDuration()\n buildButton()\n }\n }\n}\n\ndef createReleasePipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId,\n gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch) {\n pipelineJob(\"${codebaseName}/${pipelineName}\") {\n logRotator {\n numToKeep(14)\n daysToKeep(30)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"STAGES\", \"${codebaseStages}\", \"\")\n if (pipelineName.contains(\"Create-release\")) {\n stringParam(\"JIRA_INTEGRATION_ENABLED\", \"${jiraIntegrationEnabled}\", \"Is Jira integration enabled\")\n stringParam(\"PLATFORM_TYPE\", \"${platformType}\", \"Platform type\")\n stringParam(\"GERRIT_PROJECT\", \"${codebaseName}\", \"\")\n stringParam(\"RELEASE_NAME\", \"\", \"Name of the release(branch to be created)\")\n stringParam(\"COMMIT_ID\", \"\", \"Commit ID that will be used to create branch from for new release. If empty, DEFAULT_BRANCH will be used\")\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"REPOSITORY_PATH\", \"${repository}\", \"Full repository path\")\n stringParam(\"DEFAULT_BRANCH\", \"${defaultBranch}\", \"Default repository branch\")\n }\n }\n }\n }\n}\n\ndef registerWebHook(repositoryPath, type = 'code-review') {\n def url = repositoryPath.split('@')[1].split('/')[0]\n def owner = repositoryPath.split('@')[1].split('/')[1]\n def repo = repositoryPath.split('@')[1].split('/')[2]\n def apiUrl = 'https://api.' + url + '/repos/' + owner + '/' + repo + '/hooks'\n def webhookUrl = ''\n def webhookConfig = [:]\n def config = [:]\n def events = []\n\n if (type.equalsIgnoreCase('build')) {\n webhookUrl = System.getenv('JENKINS_UI_URL') + \"/github-webhook/\"\n events = [\"push\"]\n config[\"url\"] = webhookUrl\n config[\"content_type\"] = \"json\"\n config[\"insecure_ssl\"] = 0\n webhookConfig[\"name\"] = \"web\"\n webhookConfig[\"config\"] = config\n webhookConfig[\"events\"] = events\n webhookConfig[\"active\"] = true\n\n } else {\n webhookUrl = System.getenv('JENKINS_UI_URL') + \"/ghprbhook/\"\n events = [\"issue_comment\",\"pull_request\"]\n config[\"url\"] = webhookUrl\n config[\"content_type\"] = \"form\"\n config[\"insecure_ssl\"] = 0\n webhookConfig[\"name\"] = \"web\"\n webhookConfig[\"config\"] = config\n webhookConfig[\"events\"] = events\n webhookConfig[\"active\"] = true\n }\n\n def requestBody = JsonOutput.toJson(webhookConfig)\n def http = new URL(apiUrl).openConnection() as HttpURLConnection\n http.setRequestMethod('POST')\n http.setDoOutput(true)\n println(apiUrl)\n http.setRequestProperty(\"Accept\", 'application/json')\n http.setRequestProperty(\"Content-Type\", 'application/json')\n http.setRequestProperty(\"Authorization\", \"token ${getSecretValue('github-access-token')}\")\n http.outputStream.write(requestBody.getBytes(\"UTF-8\"))\n http.connect()\n println(http.responseCode)\n\n if (http.responseCode == 201) {\n response = new JsonSlurper().parseText(http.inputStream.getText('UTF-8'))\n } else {\n response = new JsonSlurper().parseText(http.errorStream.getText('UTF-8'))\n }\n\n println \"response: ${response}\"\n}\n\ndef getSecretValue(name) {\n def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(\n com.cloudbees.plugins.credentials.common.StandardCredentials.class,\n Jenkins.instance,\n null,\n null\n )\n\n def secret = creds.find { it.properties['id'] == name }\n return secret != null ? secret['secret'] : null\n}\n
After the steps above are performed, the new custom job-provision will be available in Advanced Settings during the application creation in the EDP Portal UI:
Github job provision
To create a new job provision for work with GitLab, take the following steps:
Navigate to the Jenkins main page and open the job-provisions/ci folder.
Click New Item and type the name of job-provisions - gitlab.
Select the Freestyle project option and click OK.
Select the Discard old builds check box and configure a few parameters:
Strategy: Log Rotation
Days to keep builds: 10
Max # of builds to keep: 10
Select the This project is parameterized check box and add a few input parameters as the following strings (the type of the variables is string):
Check the Execute concurrent builds if necessary option.
Check the Restrict where this project can be run option.
Fill in the Label Expression field by typing master to ensure job runs on Jenkins Master.
In the Build Steps section, perform the following:
DSL script check box
As soon as all the steps above are performed, insert the code:
View: Templateimport groovy.json.*\nimport jenkins.model.Jenkins\n\nJenkins jenkins = Jenkins.instance\ndef stages = [:]\ndef jiraIntegrationEnabled = Boolean.parseBoolean(\"${JIRA_INTEGRATION_ENABLED}\" as String)\ndef commitValidateStage = jiraIntegrationEnabled ? ',{\"name\": \"commit-validate\"}' : ''\ndef createJIMStage = jiraIntegrationEnabled ? ',{\"name\": \"create-jira-issue-metadata\"}' : ''\ndef platformType = \"${PLATFORM_TYPE}\"\ndef buildTool = \"${BUILD_TOOL}\"\ndef buildImageStage = platformType == \"kubernetes\" ? ',{\"name\": \"build-image-kaniko\"},' : ',{\"name\": \"build-image-from-dockerfile\"},'\ndef goBuildImageStage = platformType == \"kubernetes\" ? ',{\"name\": \"build-image-kaniko\"}' : ',{\"name\": \"build-image-from-dockerfile\"}'\ndef goBuildStage = buildTool.toString() == \"go\" ? ',{\"name\": \"build\"}' : ',{\"name\": \"compile\"}'\n\nstages['Code-review-application'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" + goBuildStage +\n ',{\"name\": \"tests\"},[{\"name\": \"sonar\"},{\"name\": \"dockerfile-lint\"},{\"name\": \"helm-lint\"}]]'\nstages['Code-review-library'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"compile\"},{\"name\": \"tests\"},' +\n '{\"name\": \"sonar\"}]'\nstages['Code-review-autotests'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"},{\"name\": \"sonar\"}' + ']'\nstages['Code-review-default'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" + ']'\nstages['Code-review-library-terraform'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"terraform-lint\"}]'\nstages['Code-review-library-opa'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"}]'\nstages['Code-review-library-codenarc'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}]'\nstages['Code-review-library-kaniko'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"dockerbuild-verify\"}]'\n\nstages['Build-library-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-npm'] = stages['Build-library-maven']\nstages['Build-library-gradle'] = stages['Build-library-maven']\nstages['Build-library-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"terraform-lint\"}' +\n ',{\"name\": \"terraform-plan\"},{\"name\": \"terraform-apply\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-opa'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"tests\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-codenarc'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-kaniko\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-autotests-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-autotests-gradle'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-application-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildImageStage}\" +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},{\"name\": \"tests\"},{\"name\": \"sonar\"}' +\n \"${buildImageStage}\" + '{\"name\":\"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-npm'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildImageStage}\" +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-gradle'] = stages['Build-application-maven']\nstages['Build-application-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"}' + \"${buildImageStage}\" +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"tool-init\"},' +\n '{\"name\": \"lint\"},{\"name\": \"git-tag\"}]'\nstages['Build-application-helm'] = '[{\"name\": \"checkout\"},{\"name\": \"lint\"}]'\nstages['Build-application-docker'] = '[{\"name\": \"checkout\"},{\"name\": \"lint\"}]'\nstages['Build-application-go'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"tests\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build\"}' + \"${goBuildImageStage}\" + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Create-release'] = '[{\"name\": \"checkout\"},{\"name\": \"create-branch\"},{\"name\": \"trigger-job\"}]'\n\ndef defaultStages = '[{\"name\": \"checkout\"}' + \"${createJIMStage}\" + ']'\n\n\ndef codebaseName = \"${NAME}\"\ndef gitServerCrName = \"${GIT_SERVER_CR_NAME}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitServer = \"${GIT_SERVER ? GIT_SERVER : 'gerrit'}\"\ndef gitSshPort = \"${GIT_SSH_PORT ? GIT_SSH_PORT : '29418'}\"\ndef gitUsername = \"${GIT_USERNAME ? GIT_USERNAME : 'jenkins'}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}\"\ndef defaultRepoPath = \"ssh://${gitUsername}@${gitServer}:${gitSshPort}/${codebaseName}\"\ndef repositoryPath = \"${REPOSITORY_PATH ? REPOSITORY_PATH : defaultRepoPath}\"\ndef defaultBranch = \"${DEFAULT_BRANCH}\"\n\ndef codebaseFolder = jenkins.getItem(codebaseName)\nif (codebaseFolder == null) {\n folder(codebaseName)\n}\n\ncreateListView(codebaseName, \"Releases\")\ncreateReleasePipeline(\"Create-release-${codebaseName}\", codebaseName, stages[\"Create-release\"], \"CreateRelease\",\n repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch)\n\nif (BRANCH) {\n def branch = \"${BRANCH}\"\n def formattedBranch = \"${branch.toUpperCase().replaceAll(/\\\\//, \"-\")}\"\n createListView(codebaseName, formattedBranch)\n\n def type = \"${TYPE}\"\n def crKey = getStageKeyName(buildTool).toString()\n createCiPipeline(\"Code-review-${codebaseName}\", codebaseName, stages.get(crKey, defaultStages), \"CodeReview\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n def buildKey = \"Build-${type}-${buildTool.toLowerCase()}\".toString()\n\n if (type.equalsIgnoreCase('application') || type.equalsIgnoreCase('library') || type.equalsIgnoreCase('autotests')) {\n def jobExists = false\n if(\"${formattedBranch}-Build-${codebaseName}\".toString() in Jenkins.instance.getAllItems().collect{it.name}) {\n jobExists = true\n }\n createCiPipeline(\"Build-${codebaseName}\", codebaseName, stages.get(buildKey, defaultStages), \"Build\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n if(!jobExists) {\n queue(\"${codebaseName}/${formattedBranch}-Build-${codebaseName}\")\n }\n }\n}\n\n\ndef createCiPipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId, defaultBranch, gitServerCrName, gitServerCrVersion) {\ndef jobName = \"${defaultBranch.toUpperCase().replaceAll(/\\\\//, \"-\")}-${pipelineName}\"\ndef existingJob = Jenkins.getInstance().getItemByFullName(\"${codebaseName}/${jobName}\")\ndef webhookToken = null\nif (existingJob) {\n def triggersMap = existingJob.getTriggers()\n triggersMap.each { key, value ->\n webhookToken = value.getSecretToken()\n }\n} else {\n def random = new byte[16]\n new java.security.SecureRandom().nextBytes(random)\n webhookToken = random.encodeHex().toString()\n}\npipelineJob(\"${codebaseName}/${jobName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n properties {\n gitLabConnection {\n gitLabConnection('gitlab')\n }\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n if (pipelineName.contains(\"Build\"))\n stringParam(\"BRANCH\", \"${defaultBranch}\", \"Branch to build artifact from\")\n else\n stringParam(\"BRANCH\", \"\\${gitlabMergeRequestLastCommit}\", \"Branch to build artifact from\")\n }\n }\n triggers {\n gitlabPush {\n buildOnMergeRequestEvents(pipelineName.contains(\"Build\") ? false : true)\n buildOnPushEvents(pipelineName.contains(\"Build\") ? true : false)\n enableCiSkip(false)\n setBuildDescription(true)\n rebuildOpenMergeRequest(pipelineName.contains(\"Build\") ? 'never' : 'source')\n commentTrigger(\"Build it please\")\n skipWorkInProgressMergeRequest(true)\n targetBranchRegex(\"${defaultBranch}\")\n }\n }\n configure {\n it / triggers / 'com.dabsquared.gitlabjenkins.GitLabPushTrigger' << secretToken(webhookToken)\n it / triggers / 'com.dabsquared.gitlabjenkins.GitLabPushTrigger' << triggerOnApprovedMergeRequest(pipelineName.contains(\"Build\") ? false : true)\n it / triggers / 'com.dabsquared.gitlabjenkins.GitLabPushTrigger' << pendingBuildName(pipelineName.contains(\"Build\") ? \"\" : \"Jenkins\")\n }\n}\nregisterWebHook(repository, codebaseName, jobName, webhookToken)\n}\n\ndef getStageKeyName(buildTool) {\n if (buildTool.toString().equalsIgnoreCase('terraform')) {\n return \"Code-review-library-terraform\"\n }\n if (buildTool.toString().equalsIgnoreCase('opa')) {\n return \"Code-review-library-opa\"\n }\n if (buildTool.toString().equalsIgnoreCase('codenarc')) {\n return \"Code-review-library-codenarc\"\n }\n if (buildTool.toString().equalsIgnoreCase('kaniko')) {\n return \"Code-review-library-kaniko\"\n }\n def buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n return supBuildTool ? \"Code-review-${TYPE}\" : \"Code-review-default\"\n}\n\ndef createReleasePipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId,\ngitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch) {\n pipelineJob(\"${codebaseName}/${pipelineName}\") {\n logRotator {\n numToKeep(14)\n daysToKeep(30)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"STAGES\", \"${codebaseStages}\", \"\")\n if (pipelineName.contains(\"Create-release\")) {\n stringParam(\"JIRA_INTEGRATION_ENABLED\", \"${jiraIntegrationEnabled}\", \"Is Jira integration enabled\")\n stringParam(\"PLATFORM_TYPE\", \"${platformType}\", \"Platform type\")\n stringParam(\"GERRIT_PROJECT\", \"${codebaseName}\", \"\")\n stringParam(\"RELEASE_NAME\", \"\", \"Name of the release(branch to be created)\")\n stringParam(\"COMMIT_ID\", \"\", \"Commit ID that will be used to create branch from for new release. If empty, DEFAULT_BRANCH will be used\")\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"REPOSITORY_PATH\", \"${repository}\", \"Full repository path\")\n stringParam(\"DEFAULT_BRANCH\", \"${defaultBranch}\", \"Default repository branch\")\n }\n }\n }\n }\n}\n\ndef createListView(codebaseName, branchName) {\n listView(\"${codebaseName}/${branchName}\") {\n if (branchName.toLowerCase() == \"releases\") {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^Create-release.*\")\n }\n }\n } else {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^${branchName}-(Code-review|Build).*\")\n }\n }\n }\n columns {\n status()\n weather()\n name()\n lastSuccess()\n lastFailure()\n lastDuration()\n buildButton()\n }\n }\n}\n\ndef registerWebHook(repositoryPath, codebaseName, jobName, webhookToken) {\n def apiUrl = 'https://' + repositoryPath.replaceAll(\"ssh://\", \"\").split('@')[1].replace('/', \"%2F\").replaceAll(~/:\\d+%2F/, '/api/v4/projects/') + '/hooks'\n def jobWebhookUrl = \"${System.getenv('JENKINS_UI_URL')}/project/${codebaseName}/${jobName}\"\n def gitlabToken = getSecretValue('gitlab-access-token')\n\n if (checkWebHookExist(apiUrl, jobWebhookUrl, gitlabToken)) {\n println(\"[JENKINS][DEBUG] Webhook for job ${jobName} is already exist\\r\\n\")\n return\n }\n\n println(\"[JENKINS][DEBUG] Creating webhook for job ${jobName}\")\n def webhookConfig = [:]\n webhookConfig[\"url\"] = jobWebhookUrl\n webhookConfig[\"push_events\"] = jobName.contains(\"Build\") ? \"true\" : \"false\"\n webhookConfig[\"merge_requests_events\"] = jobName.contains(\"Build\") ? \"false\" : \"true\"\n webhookConfig[\"issues_events\"] = \"false\"\n webhookConfig[\"confidential_issues_events\"] = \"false\"\n webhookConfig[\"tag_push_events\"] = \"false\"\n webhookConfig[\"note_events\"] = \"true\"\n webhookConfig[\"job_events\"] = \"false\"\n webhookConfig[\"pipeline_events\"] = \"false\"\n webhookConfig[\"wiki_page_events\"] = \"false\"\n webhookConfig[\"enable_ssl_verification\"] = \"true\"\n webhookConfig[\"token\"] = webhookToken\n def requestBody = JsonOutput.toJson(webhookConfig)\n def httpConnector = new URL(apiUrl).openConnection() as HttpURLConnection\n httpConnector.setRequestMethod('POST')\n httpConnector.setDoOutput(true)\n\n httpConnector.setRequestProperty(\"Accept\", 'application/json')\n httpConnector.setRequestProperty(\"Content-Type\", 'application/json')\n httpConnector.setRequestProperty(\"PRIVATE-TOKEN\", \"${gitlabToken}\")\n httpConnector.outputStream.write(requestBody.getBytes(\"UTF-8\"))\n httpConnector.connect()\n\n if (httpConnector.responseCode == 201)\n println(\"[JENKINS][DEBUG] Webhook for job ${jobName} has been created\\r\\n\")\n else {\n println(\"[JENKINS][ERROR] Responce code - ${httpConnector.responseCode}\")\n def response = new JsonSlurper().parseText(httpConnector.errorStream.getText('UTF-8'))\n println(\"[JENKINS][ERROR] Failed to create webhook for job ${jobName}. Response - ${response}\")\n }\n}\n\ndef checkWebHookExist(apiUrl, jobWebhookUrl, gitlabToken) {\n println(\"[JENKINS][DEBUG] Checking if webhook ${jobWebhookUrl} exists\")\n def httpConnector = new URL(apiUrl).openConnection() as HttpURLConnection\n httpConnector.setRequestMethod('GET')\n httpConnector.setDoOutput(true)\n\n httpConnector.setRequestProperty(\"Accept\", 'application/json')\n httpConnector.setRequestProperty(\"Content-Type\", 'application/json')\n httpConnector.setRequestProperty(\"PRIVATE-TOKEN\", \"${gitlabToken}\")\n httpConnector.connect()\n\n if (httpConnector.responseCode == 200) {\n def response = new JsonSlurper().parseText(httpConnector.inputStream.getText('UTF-8'))\n return response.find { it.url == jobWebhookUrl } ? true : false\n }\n}\n\ndef getSecretValue(name) {\n def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(\n com.cloudbees.plugins.credentials.common.StandardCredentials.class,\n Jenkins.instance,\n null,\n null\n )\n\n def secret = creds.find { it.properties['id'] == name }\n return secret != null ? secret['secret'] : null\n}\n
After the steps above are performed, the new custom job-provision will be available in Advanced Settings during the application creation in the EDP Portal UI:
Gitlab job provision
To migrate the CI pipelines for a codebase from Jenkins to Tekton, follow the steps below:
Make sure that Tekton stack is deployed according to the documentation. Enable Tekton as an EDP subcomponent:
values.yamledp-tekton:\n enabled: true\n
"},{"location":"operator-guide/migrate-ci-pipelines-from-jenkins-to-tekton/#disable-jenkins-triggers","title":"Disable Jenkins Triggers","text":"To disable Jenkins Triggers for the codebase, add the following code to the provisioner:
job-provisionerdef tektonCodebaseList = [\"<codebase_name>\"]\nif (!tektonCodebaseList.contains(codebaseName.toString())){\n triggers {\n gerrit {\n events {\n if (pipelineName.contains(\"Build\"))\n changeMerged()\n else\n patchsetCreated()\n }\n project(\"plain:${codebaseName}\", [\"plain:${watchBranch}\"])\n }\n }\n}\n
Note
The sample above shows the usage of Gerrit VCS where the <codebase_name>
value is your codebase name.
By default, each Gerrit project inherits configuration from the All-Projects repository.
To exclude triggering in Jenkins and Tekton CI tools simultaneously, edit the configuration in the All-Projects repository or in the project which inherits rights from your project.
Edit the webhooks.config file in the refs/meta/config and remove all context from this configuration.
Warning
The clearance of the webhooks.config file will disable the pipeline trigger in Tekton.
To use Tekton pipelines, add the configuration to the corresponding Gerrit project (webhooks.config file in the refs/meta/config):
webhooks.config[remote \"changemerged\"]\n url = http://el-gerrit-listener:8080\n event = change-merged\n[remote \"patchsetcreated\"]\n url = http://el-gerrit-listener:8080\n event = patchset-created\n \n
"},{"location":"operator-guide/migrate-ci-pipelines-from-jenkins-to-tekton/#switch-ci-tool-for-codebases","title":"Switch CI Tool for Codebase(s)","text":"Go to the codebase Custom Resource and change the spec.ciTool
field from jenkins
to tekton
.
Get acquainted with the multitenant logging components and the project logs location in the Shared cluster.
"},{"location":"operator-guide/multitenant-logging/#logging-components","title":"Logging Components","text":"To configure the multitenant logging, it is necessary to deploy the following components:
In Grafana, every tenant represents an organization, i.e. it is necessary to create an organization for every namespace in the cluster. To get more details regarding the architecture of the Logging Operator, please review the Diagram 1.
Logging operator scheme
Note
It is necessary to deploy Loki with the auth_enabled: true
flag with the aim to ensure that the logs are separated for each tenant. For the authentication, Loki requires the HTTP header X-Scope-OrgID.
To find the project logs, navigate to Grafana and follow the steps below:
Note
Grafana is a common service for different customers where each customer works in its own separated Grafana Organization and doesn't have any access to another project.
Choose the organization by clicking the Current Organization drop-down list. If a user is assigned to several organizations, switch easily by using the Switch button.
Current organization
Navigate to the left-side menu and click the Explore button to see the Log Browser:
Grafana explore
Click the Log Browser button to see the labels that can be used to filter logs (e.g., hostname, namespace, application name, pod, etc.):
Note
Enable the correct data source, select the relevant logging data from the top left-side corner, and pay attention that the data source name always follows the \u2039project_name\u203a-logging pattern.
Log browser
Filter out logs by clicking the Show logs button or write the query and click the Run query button.
Review the results with the quantity of logs per time, see the example below:
Logs example
Expand logs
Addition button
Ad-hoc stat example
EDP provides the ability to deploy services to namespaces. By default, EDP creates these namespaces automatically. This chapter describes the alternative way of namespace creation and management.
"},{"location":"operator-guide/namespace-management/#overview","title":"Overview","text":"Namespaces are typically created by the platform when running CD Pipelines. The operator creates them according to the specific format: edp-<application-name>-<stage-name>
. The cd-pipeline-operator
should have the permissions to automatically create namespaces when deploying applications and delete them when uninstalling applications.
Occasionally, there are cases when automatic creation of namespaces is not allowed. For example, due to security reasons of the project, EDP user may need to disable this setting. This option is manipulated by the manageNamespace
parameter which is located in the values.yaml file. The manageNamespace
parameter is set to true
by default, but it can be changed to false. As an aftermath, after setting the manageNamespace
parameter users are supposed to face the problem that they can not deploy their application in EDP Portal UI because of permission restrictions:
Namespace creation error
The error message shown above says that user needs to create the namespace in the edp-<application-name>-<stage-name>
format first before creating stages. In addition to it, the cd-pipeline-operator
must be granted with the administrator permissions to have the ability to manage this namespace. To create namespace manually, follow the steps below:
Create the namespace by running the command below:
kubectl create namespace edp-<pipelineName>-<stageName>\n
Note
The edp-<pipelineName>-<stageName>
format for namespaces is set by default but is not mandatory. You can set your custom namespace when creating an Environment.
Create the administrator RoleBinding resource by applying the file below with the kubectl apply -f grant_admin_permissions.yaml
command:
kind: RoleBinding\n apiVersion: rbac.authorization.k8s.io/v1\n metadata:\n name: edp-cd-pipeline-operator-admin\n namespace: edp-<pipelineName>-<stageName>\n subjects:\n - kind: ServiceAccount\n name: edp-cd-pipeline-operator\n namespace: edp\n roleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: admin\n
Restart the cd-pipeline-operator pod, in order not to wait for the operator reconciliation.
The manageNamespace
parameter also defines the resources that will be created depending on the cluster deployed whether it is OpenShift or Kubernetes. This scheme displays the nesting of operator input parameters:
CD Pipeline Operator Input Parameter Scheme
Note
When deploying application on the OpenShift cluster, the registry-view
RoleBinding is created in the main namespace.
This documentation guide provides comprehensive instructions for integrating Nexus with the EPAM Delivery Platform.
Info
In EDP release 3.5, we have changed the deployment strategy for the nexus-operator component, now it is not installed by default. The nexusURL
parameter management has been transferred from the values.yaml file to Kubernetes secrets.
Before proceeding, ensure that you have the following prerequisites:
To install Nexus with pre-defined templates, use the nexus-operator installed via Cluster Add-Ons approach.
"},{"location":"operator-guide/nexus-sonatype/#configuration","title":"Configuration","text":"To ensure strong authentication and accurate access control, creating a Nexus Sonatype service account with the name ci.user is crucial. This user serves as a unique identifier, facilitating connection with the EDP ecosystem.
To create the Nexus ci.user
and define repository parameters follow the steps below:
Open the Nexus UI and navigate to Server administration and configuration
-> Security
-> User
. Click the Create local user
button to create a new user:
Nexus user settings
Type the ci-user
username, define an expiration period, and click the Generate
button to create the token:
Nexus create user
EDP relies on a predetermined repository naming convention all repository names are predefined. Navigate to Server administration and configuration
-> Repository
-> Repositories
in Nexus. You can only create a repository with the required language.
Nexus repository list
JavaJavaScriptDotnetPythona) Click Create a repository by selecting \"maven2(proxy)\" and set the name as \"edp-maven-proxy\". Enter the remote storage URL as \"https://repo1.maven.org/maven2/\". Save the configuration.
b) Click Create a repository by selecting \"maven2(hosted)\" and set the name as \"edp-maven-snapshot\". Change the Version policy to \"snapshot\". Save the configuration.
c) Click Create a repository by selecting \"maven2(hosted)\" and set the name as \"edp-maven-releases\". Change the Version policy to \"release\". Save the configuration.
d) Click Create a repository by selecting \"maven2(group)\" and set the name as \"edp-maven-group\". Change the Version policy to \"release\". Add repository to group. Save the configuration.
a) Click Create a repository by selecting \"npm(proxy)\" and set the name as \"edp-npm-proxy\". Enter the remote storage URL as \"https://registry.npmjs.org\". Save the configuration.
b) Click Create a repository by selecting \"npm(hosted)\" and set the name as \"edp-npm-snapshot\". Save the configuration.
c) Click Create a repository by selecting \"npm(hosted)\" and set the name as \"edp-npm-releases\". Save the configuration.
d) Click Create a repository by selecting \"npm(hosted)\" and set the name as \"edp-npm-hosted\". Save the configuration.
e) Click Create a repository by selecting \"npm(group)\" and set the name as \"edp-npm-group\". Add repository to group. Save the configuration.
a) Click Create a repository by selecting \"nuget(proxy)\" and set the name as \"edp-dotnet-proxy\". Select Protocol version NuGet V3. Enter the remote storage URL as \"https://api.nuget.org/v3/index.json\". Save the configuration.
b) Click Create a repository by selecting \"nuget(hosted)\" and set the name as \"edp-dotnet-snapshot\". Save the configuration.
c) Click Create a repository by selecting \"nuget(hosted)\" and set the name as \"edp-dotnet-releases\". Save the configuration.
d) Click Create a repository by selecting \"nuget(hosted)\" and set the name as \"edp-dotnet-hosted\". Save the configuration.
e) Click Create a repository by selecting \"nuget(group)\" and set the name as \"edp-dotnet-group\". Add repository to group. Save the configuration.
a) Click Create a repository by selecting \"pypi(proxy)\" and set the name as \"edp-python-proxy\". Enter the remote storage URL as \"https://pypi.org\". Save the configuration.
b) Click Create a repository by selecting \"pypi(hosted)\" and set the name as \"edp-python-snapshot\". Save the configuration.
c) Click Create a repository by selecting \"pypi(hosted)\" and set the name as \"edp-python-releases\". Save the configuration.
d) Click Create a repository by selecting \"pypi(group)\" and set the name as \"edp-python-group\". Add repository to group. Save the configuration.
Provision secrets using manifest, EDP Portal or with the externalSecrets operator
Go to EDP Portal -> EDP -> Configuration -> Nexus. Update or fill in the URL, nexus-user-id, nexus-user-password and click the Save button:
Nexus update manual secret
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-nexus\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: nexus\n app.edp.epam.com/integration-secret: true\ntype: Opaque\nstringData:\n url: https://nexus.example.com\n username: <nexus-user-id>\n password: <nexus-user-password>\n
\"ci-nexus\":\n{\n \"url\": \"https://nexus.example.com\",\n \"username\": \"XXXXXXX\",\n \"password\": \"XXXXXXX\"\n},\n
Go to EDP Portal -> EDP -> Configuration -> Nexus and see Managed by External Secret
message.
Nexus managed by external secret operator
More detail of External Secrets Operator Integration can found on the following page
"},{"location":"operator-guide/nexus-sonatype/#related-articles","title":"Related Articles","text":"This section describes how to set up and add notification status to Tekton pipelines by sending pipeline status to the Microsoft Teams channel.
"},{"location":"operator-guide/notification-msteams/#create-incoming-webhook","title":"Create Incoming WebHook","text":"To create a link to Incoming Webhook for the Microsoft Teams channel, follow the steps below:
1. Open the channel which will be receiving notifications and click the \u2022\u2022\u2022
button from the upper-right corner. Select Connectors
in the dropdown menu: Microsoft Teams menu
2. In the search field, type Incoming Webhook
and click Configure
: Connectors
3. Provide a name and upload an image for the webhook if necessary. Click Create
: Connectors setup
4. Copy and save the unique WebHookURL
presented in the dialog. Click Done
: WebHookURL
5. Create a secret with the within the edp namespace.
kubectl -n edp create secret generic microsoft-teams-webhook-url \\\n --from-literal=url=<webhookURL>\n
6. Add the notification task to the pipeline and add the code below in final-block
in the pipeline and save:
{{ include \"send-to-microsoft-teams-build\" . | nindent 4 }}\n
"},{"location":"operator-guide/notification-msteams/#customize-notification-message","title":"Customize Notification Message","text":"To make notification message informative, relevant text should be added to the message. Here are the steps to implement it:
Create a new pipeline with a unique name or modify your custom pipeline created before.
Add the task below in the finally
block with a unique name. Edit the params.message
value if necessary:
- name: 'microsoft-teams-pipeline-status-notification-failed\n params:\n - name: webhook-url-secret\n value: microsoft-teams-webhook-url\n - name: webhook-url-secret-key\n value: url\n - name: message\n value: >-\n Build Failed project: $(params.CODEBASE_NAME)<br> branch: $(params.git-source-revision)<br> pipeline: <a href=$(params.pipelineUrl)>$(context.pipelineRun.name)</a><br> commit message: $(params.COMMIT_MESSAGE)\n taskRef:\n kind: Task\n name: send-to-microsoft-teams\n when:\n - input: $(tasks.status)\n operator: in\n values:\n - Failed\n - PipelineRunTimeout\n
After customization, the following message is supposed to appear in the channel when failing pipelines:
Notification example
"},{"location":"operator-guide/notification-msteams/#related-articles","title":"Related Articles","text":"OAuth2-Proxy is a versatile tool that serves as a reverse proxy, utilizing the OAuth 2.0 protocol with various providers like Google, GitHub, and Keycloak to provide both authentication and authorization. This guide instructs readers on how to protect their applications' endpoints using OAuth2-Proxy. By following these steps, users can strengthen their endpoints' security without modifying their current application code. In the context of EDP, it has integration with the Keycloak OIDC provider, enabling it to link with any component that lacks built-in authentication.
Note
OAuth2-Proxy is disabled by default when installing EDP.
"},{"location":"operator-guide/oauth2-proxy/#prerequisites","title":"Prerequisites","text":"Enabling OAuth2-Proxy implies the following general steps:
--set 'oauth2_proxy.enabled=true'
or the --values
file by enabling the oauth2_proxy parameter.auth-signin
and auth-url
of OAuth2-Proxy to its annotation.This will deploy and connect OAuth2-Proxy to your application endpoint.
"},{"location":"operator-guide/oauth2-proxy/#enable-oauth2-proxy-on-tekton-dashboard","title":"Enable OAuth2-Proxy on Tekton Dashboard","text":"The example below illustrates how to use OAuth2-Proxy in practice when using the Tekton dashboard:
KubernetesOpenshifthelm upgrade
to update edp-install release: helm upgrade --version <version> --set 'oauth2_proxy.enabled=true' edp-install --namespace edp\n
auth-signin
and auth-url
of oauth2-proxy by kubectl
command: kubectl annotate ingress <application-ingress-name> nginx.ingress.kubernetes.io/auth-signin='https://<oauth-ingress-host>/oauth2/start?rd=https://$host$request_uri' nginx.ingress.kubernetes.io/auth-url='http://oauth2-proxy.edp.svc.cluster.local:8080/oauth2/auth'\n
tekton_dashboard_cookie_secret=$(openssl rand -base64 32 | head -c 32)\n
tekton-dashboard-proxy-cookie-secret
in the edp namespace: kubectl -n edp create secret generic tekton-dashboard-proxy-cookie-secret \\\n --from-literal=cookie-secret=${tekton_dashboard_cookie_secret}\n
helm upgrade
to update edp-install release: helm upgrade --version <version> --set 'edp-tekton.dashboard.openshift_proxy.enabled=true' edp-install --namespace edp\n
Keycloak Installation Keycloak OIDC Installation Tekton Installation
"},{"location":"operator-guide/openshift-cluster-settings/","title":"Set Up OpenShift","text":""},{"location":"operator-guide/openshift-cluster-settings/#set-up-openshift","title":"Set Up OpenShift","text":"Make sure the cluster meets the following conditions:
OpenShift cluster is installed with minimum 2 worker nodes with total capacity 8 Cores and 32Gb RAM.
Load balancer (if any exists in front of OpenShift router or ingress controller) is configured with session stickiness, disabled HTTP/2 protocol and header size of 64k support.
Find below an example of the Config Map for the NGINX Ingress Controller:
kind: ConfigMap\napiVersion: v1\nmetadata:\n name: nginx-configuration\n namespace: ingress-nginx\n labels:\n app.kubernetes.io/name: ingress-nginx\n app.kubernetes.io/part-of: ingress-nginx\ndata:\n client-header-buffer-size: 64k\n large-client-header-buffers: 4 64k\n use-http2: \"false\"\n
Cluster nodes and pods have access to the cluster via external URLs. For instance, add in AWS the VPC NAT gateway elastic IP to the cluster external load balancers security group).
Keycloak instance is installed. To get accurate information on how to install Keycloak, please refer to the Install Keycloak instruction.
The installation machine with oc is installed with the cluster-admin access to the OpenShift cluster.
Helm 3.10 is installed on the installation machine with the help of the Installing Helm instruction.
Storage classes are used with the Retain Reclaim Policy and Delete Reclaim Policy.
We recommended using our storage class as default storage class.
Info
By default, EDP uses the default Storage Class in a cluster. The EDP development team recommends using the following Storage Classes. See an example below.
Storage class templates with the Retain and Delete Reclaim Policies:
ebs-scgp3gp3-retainapiVersion: storage.k8s.io/v1\nkind: StorageClass\nmetadata:\n name: ebs-sc\n annotations:\n storageclass.kubernetes.io/is-default-class: 'true'\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Retain\nvolumeBindingMode: Immediate\n
kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: gp3\n annotations:\n storageclass.kubernetes.io/is-default-class: 'true'\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Delete\nvolumeBindingMode: Immediate\nallowVolumeExpansion: true\n
kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: gp3-retain\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Retain\nvolumeBindingMode: WaitForFirstConsumer\nallowVolumeExpansion: true\n
The EPAM Delivery Platform emphasizes the importance of incorporating security practices into the software development lifecycle through the DevSecOps approach. By integrating a diverse range of open-source and enterprise security tools tailored to specific functionalities, organizations can ensure efficient and secure software development. These tools, combined with fundamental DevSecOps principles such as collaboration, continuous security, and automation, contribute to the identification and remediation of vulnerabilities early in the process, minimizes risks, and fosters a security-first culture across the organization.
The EPAM Delivery Platform enabling seamless integration with various security tools and vulnerability management systems, enhancing the security of source code and ensuring compliance.
"},{"location":"operator-guide/overview-devsecops/#supported-solutions","title":"Supported Solutions","text":"The below table categorizes various open-source and enterprise security tools based on their specific functionalities. It provides a comprehensive view of the available options for each security aspect. This classification facilitates informed decision-making when selecting and integrating security tools into a development pipeline, ensuring an efficient and robust security stance. EDP supports the integration of both open-source and enterprise security tools, providing a flexible and versatile solution for security automation. See table below for more details.
Functionality Open-Source Tools (integrated in Pipelines) Enterprise Tools (available for Integration) Hardcoded Credentials Scanner TruffleHog, GitLeaks, Git-secrets GitGuardian, SpectralOps, Bridgecrew Static Application Security Testing SonarQube, Semgrep CLI Veracode, Checkmarx, Coverity Software Composition Analysis OWASP Dependency-Check, cdxgen Black Duck Hub, Mend, Snyk Container Security Trivy, Grype, Clair Aqua Security, Sysdig Secure, Snyk Infrastructure as Code Security Checkov, Tfsec Bridgecrew, Prisma Cloud, Snyk Dynamic Application Security Testing OWASP Zed Attack Proxy Fortify WebInspect, Rapid7 InsightAppSec, Checkmarx Continuous Monitoring and Logging ELK Stack, OpenSearch, Loki Splunk, Datadog Security Audits and Assessments OpenVAS Tenable Nessus, QualysGuard, BurpSuite Professional Vulnerability Management and Reporting DefectDojo, OWASP Dependency-Track MetasploitFor better visualization, see the scheme below:
Security tools in EDP
"},{"location":"operator-guide/overview-devsecops/#integrated-tools","title":"Integrated Tools","text":"For obtaining and managing report post scanning, deployment of various vulnerability management systems and security tools is required. These include:
"},{"location":"operator-guide/overview-devsecops/#defectdojo","title":"DefectDojo","text":"DefectDojo is a comprehensive vulnerability management and security orchestration platform facilitating the handling of uploaded security reports. Examine the prerequisites and fundamental instructions for installing DefectDojo on Kubernetes or OpenShift platforms.
"},{"location":"operator-guide/overview-devsecops/#owasp-dependency-track","title":"OWASP Dependency Track","text":"Dependency Track is an intelligent Software Composition Analysis (SCA) platform that provides a comprehensive solution for managing vulnerabilities in third-party and open-source components.
"},{"location":"operator-guide/overview-devsecops/#gitleaks","title":"Gitleaks","text":"Gitleaks is a versatile SAST tool used to scan Git repositories for hardcoded secrets, such as passwords and API keys, to prevent potential data leaks and unauthorized access.
"},{"location":"operator-guide/overview-devsecops/#trivy","title":"Trivy","text":"Trivy is a simple and comprehensive vulnerability scanner for containers and other artifacts, providing insight into potential security issues across multiple ecosystems.
"},{"location":"operator-guide/overview-devsecops/#grype","title":"Grype","text":"Grype is a fast and reliable vulnerability scanner for container images and filesystems, maintaining an up-to-date vulnerability database for efficient and accurate scanning.
"},{"location":"operator-guide/overview-devsecops/#tfsec","title":"Tfsec","text":"Tfsec is an effective Infrastructure as Code (IaC) security scanner, tailored specifically for reviewing Terraform templates. It helps identify potential security issues related to misconfigurations and non-compliant practices, enabling developers to address vulnerabilities and ensure secure infrastructure deployment.
"},{"location":"operator-guide/overview-devsecops/#checkov","title":"Checkov","text":"Checkov is a robust static code analysis tool designed for IaC security, supporting various IaC frameworks such as Terraform, CloudFormation, and Kubernetes. It assists in detecting and mitigating security and compliance misconfigurations, promoting best practices and adherence to industry standards across the infrastructure.
"},{"location":"operator-guide/overview-devsecops/#cdxgen","title":"Cdxgen","text":"Cdxgen is a lightweight and efficient tool for generating Software Bill of Materials (SBOM) using CycloneDX, a standard format for managing component inventory. It helps organizations maintain an up-to-date record of all software components, their versions, and related vulnerabilities, streamlining monitoring and compliance within the software supply chain.
"},{"location":"operator-guide/overview-devsecops/#semgrep-cli","title":"Semgrep CLI","text":"Semgrep CLI is a versatile and user-friendly command-line interface for the Semgrep security scanner, enabling developers to perform Static Application Security Testing (SAST) for various programming languages. It focuses on detecting and preventing potential security vulnerabilities, code quality issues, and custom anti-patterns, ensuring secure and efficient code development.
"},{"location":"operator-guide/overview-devsecops/#clair","title":"Clair","text":"Clair is an open-source container security tool that is designed to help you assess the security of container images and identify vulnerabilities within them. It is particularly useful for organizations using container orchestration platforms such as Kubernetes.
"},{"location":"operator-guide/overview-devsecops/#openvas","title":"OpenVAS","text":"OpenVAS is an open-source network vulnerability scanner and security management tool. It is designed to identify and assess security vulnerabilities in computer systems, networks, and applications. OpenVAS provides a comprehensive set of features for vulnerability scanning, assessment, and management.
"},{"location":"operator-guide/overview-devsecops/#trufflehog","title":"TruffleHog","text":"TruffleHog is an open-source Python tool designed for finding and identifying potentially sensitive and secret information in the source code and commit history of Git repositories. It's particularly useful for locating unintentional disclosures of confidential data, such as API keys, passwords, and other credentials, that might have been inadvertently committed to a code repository.
"},{"location":"operator-guide/overview-devsecops/#git-secrets","title":"Git-secrets","text":"Git-secrets is an open-source tool that helps prevent the accidental committing of secrets, sensitive information, and other types of confidential data into Git repositories. It is designed to enforce security best practices and reduce the risk of unintentional data exposure by scanning Git repositories for predefined secret patterns.
"},{"location":"operator-guide/overview-devsecops/#elk-stack","title":"ELK Stack","text":"ELK Stack (Fluent Bit, Elasticsearch, Kibana) stack is used in Kubernetes instead of ELK because this stack provides us with the support for Logsight for Stage Verification and Incident Detection. In addition to it, Fluent Bit has a smaller memory fingerprint than Logstash. Fluent Bit has the Inputs, Parsers, Filters and Outputs plugins similarly to Logstash.
"},{"location":"operator-guide/overview-devsecops/#loki","title":"Loki","text":"Loki is a log aggregation system and log processing system designed for cloud-native environments. It is part of the CNCF (Cloud Native Computing Foundation) and is often used alongside other CNCF projects like Prometheus for monitoring and observability.
"},{"location":"operator-guide/overview-devsecops/#opensearch","title":"OpenSearch","text":"OpenSearch is the flexible, scalable, open-source way to build solutions for data-intensive applications. Explore, enrich, and visualize your data with built-in performance, developer-friendly tools, and powerful integrations for machine learning, data processing, and more.
"},{"location":"operator-guide/overview-devsecops/#owasp-dependency-check","title":"OWASP Dependency-Check","text":"OWASP Dependency-Check is a software composition analysis tool that helps identify and report known security vulnerabilities in project dependencies. It is particularly valuable for developers and organizations looking to secure their applications by identifying and addressing vulnerabilities in the libraries and components they use.
"},{"location":"operator-guide/overview-devsecops/#owasp-zed-attack-proxy-zap","title":"OWASP Zed Attack Proxy (ZAP)","text":"OWASP Zed Attack Proxy (ZAP) is an security testing tool for finding vulnerabilities in web applications during the development and testing phases. ZAP is designed to help developers and security professionals identify and address security issues and potential vulnerabilities in web applications. It provides automated and manual testing capabilities, as well as a wide range of features for security testing.
"},{"location":"operator-guide/overview-manage-jenkins-pipelines/","title":"Overview","text":""},{"location":"operator-guide/overview-manage-jenkins-pipelines/#overview","title":"Overview","text":"Jenkins job provisioners are responsible for creating and managing pipelines in Jenkins. In other words, provisioners configure all Jenkins pipelines and bring them to the state described in the provisioners code. Two types of provisioners are available in EDP:
The subsections describe the creation/update process of provisioners and their content depending on EDP customization.
"},{"location":"operator-guide/overview-sast/","title":"Static Application Security Testing Overview","text":""},{"location":"operator-guide/overview-sast/#static-application-security-testing-overview","title":"Static Application Security Testing Overview","text":"EPAM Delivery Platform provides the implemented Static Application Security Testing support allowing to work with the Semgrep security scanner and the DefectDojo vulnerability management system to check the source code for known vulnerabilities.
"},{"location":"operator-guide/overview-sast/#supported-languages","title":"Supported Languages","text":"EDP SAST supports a number of languages and package managers.
Language (Package Managers) Scan Tool Build Tool Java Semgrep Maven, Gradle Go Semgrep Go React Semgrep Npm"},{"location":"operator-guide/overview-sast/#supported-vulnerability-management-system","title":"Supported Vulnerability Management System","text":"To get and then manage a SAST report after scanning, it is necessary to deploy the vulnerability management system, for instance, DefectDojo.
"},{"location":"operator-guide/overview-sast/#defectdojo","title":"DefectDojo","text":"DefectDojo is a vulnerability management and security orchestration platform that allows managing the uploaded security reports.
Inspect the prerequisites and the main steps for installing DefectDojo on Kubernetes or OpenShift platforms.
"},{"location":"operator-guide/overview-sast/#related-articles","title":"Related Articles","text":"Integration with Perf Server allows connecting to the PERF Board (Project Performance Board) and monitoring the overall team performance as well as setting up necessary metrics.
Note
To adjust the PERF Server integration, make sure that PERF Operator is deployed. To get more information about the PERF Operator installation and architecture, please refer to the PERF Operator page.
For integration, take the following steps:
Create Secret in the OpenShift/Kubernetes namespace for Perf Server account with the username and password fields:
apiVersion: v1\ndata:\n password: passwordInBase64\n username: usernameInBase64\nkind: Secret\nmetadata:\n name: epam-perf-user\ntype: kubernetes.io/basic-auth\n
In the edp-config config map, enable the perf_integration flag and click Save:
perf_integration_enabled: 'true'\n
Being in Admin Console, navigate to the Advanced Settings menu to check that the Integrate with Perf Server check box appeared:
Advanced settings
Before installing EDP:
EDP installation scenario is based on the Tekton as a CI tool and EDP Portal as a UI tool.
Find below the list of the key components used by EPAM Delivery Platform:
Component Requirement level Cluster Tekton Mandatory Argo CD Mandatory NGINX Ingress Controller1 Mandatory Keycloak Optional DefectDojo Optional ReportPortal Optional Kiosk Optional External Secrets Optional Harbor OptionalNote
Alternatively, use Helmfiles to install the EDP components.
After setting up the cluster and installing EDP components according to the selected scenario, proceed to the EDP installation.
"},{"location":"operator-guide/prerequisites/#related-articles","title":"Related Articles","text":"OpenShift cluster uses Routes to provide access to pods from external resources.\u00a0\u21a9
ReportPortal integration with Tekton allows managing all automation results and reports in one place, visualizing metrics and analytics, team collaborating to associate statistics results.
For integration, take the following steps:
Log in to the ReportPortal console and navigate to the User Profile menu:
ReportPortal profile
Copy the Access token and use it as a value while creating a kubernetes secret for the ReportPortal credentials:
apiVersion: v1\nkind: Secret\ntype: Opaque\nmetadata:\n name: rp-credentials\n namespace: edp\nstringData:\n rp_uuid: <access-token>\n
In the Configuration examples section of the ReportPortal User Profile menu, copy the following REQUIRED
fields: rp.endpoint
, rp.launch
and rp.project
. Insert these fields to the pytest.ini
file in root directory of your project:
[pytest]\naddopts = -rsxX -l --tb=short --junitxml test-report.xml\nrp_endpoint = <endpoint>\nrp_launch = <launch>\nrp_project = <project>\n
In root directory of the project create/update requirements.txt file and fill with following. it's mandatory to install report-portal python library (version may vary):
pytest-reportportal == 5.1.2\n
Create a custom Tekton task:
View: Custom Tekton taskapiVersion: tekton.dev/v1beta1\nkind: Task\nmetadata:\n labels:\n app.kubernetes.io/version: '0.1'\n name: pytest-reportportal\n namespace: edp\nspec:\n description: |-\n This task can be used to run pytest integrated with report portal.\n params:\n - default: .\n description: The path where package.json of the project is defined.\n name: PATH_CONTEXT\n type: string\n - name: EXTRA_COMMANDS\n type: string\n - default: python:3.8-alpine3.16\n description: The python image you want to use.\n name: BASE_IMAGE\n type: string\n - default: rp-credentials\n description: name of the secret holding the rp token\n name: rp-secret\n type: string\n steps:\n - env:\n - name: HOME\n value: $(workspaces.source.path)\n - name: RP_UUID\n valueFrom:\n secretKeyRef:\n key: rp_uuid\n name: $(params.rp-secret)\n image: $(params.BASE_IMAGE)\n name: pytest\n resources: {}\n script: >\n #!/usr/bin/env sh\n set -e\n export PATH=$PATH:$HOME/.local/bin\n $(params.EXTRA_COMMANDS)\n # tests are being run from ./test directory in the project\n pytest ./tests --reportportal\n workingDir: $(workspaces.source.path)/$(params.PATH_CONTEXT)\n workspaces:\n - name: source\n
Add this task ref to your Tekton pipeline after tasks:
View: Tekton pipeline- name: pytest\n params:\n - name: BASE_IMAGE\n value: $(params.image)\n - name: EXTRA_COMMANDS\n value: |\n set -ex\n pip3 install -r requirements.txt\n [ -f run_service.py ] && python run_service.py &\n runAfter:\n - compile\n taskRef:\n kind: Task\n name: pytest-reportportal\n workspaces:\n - name: source\n workspace: shared-workspace\n
Launch your Tekton pipeline and check that the custom task has been successfully executed:
Tekton task successfully executed
Test reports will be displayed in the Launches section of the ReportPortal:
Test report results
Follow the steps below to integrate the ReportPortal with Keycloak.
"},{"location":"operator-guide/reportportal-keycloak/#prerequisites","title":"Prerequisites","text":"Navigate to Client Scopes > Create client scope and create a new scope with the SAML protocol type.
Navigate to Client Scopes > your_scope_name > Mappers > Configure a new mapper > select the User Attribute mapper type. Add three mappers for the email, first name, and last name by typing lastName
, firstName
, and email
in the User Attribute field:
Basic
.Off
.User mapper sample Scope mappers
Navigate to Clients > Create client and fill in the following fields:
SAML
.report.portal.sp.id
.Warning
The report.portal.sp.id
Client ID is a constant value.
Navigate to Client > your_client > Settings and add https://<report-portal-url\\>/*
to the Valid redirect URIs.
Navigate to Client > your_client > Keys and disable Client signature required.
Client keys
Navigate to Client > your_client > Client scopes and add the scope created on step 3 with the default Assigned type.
Client scopes
Log in to the ReportPortal with the admin permissions.
Navigate to Client > Administrate > Plugins and select the SAML plugin.
Plugins menu
To add a new integration, fill in the following fields:
Add SAML configuration
https://<keycloak_url\\>/auth/realms/<realm\\>/protocol/saml/descriptor
.https://<report_portal_url\\>/uat
.Log in to the ReportPortal.
Note
By default, after the first login, ReportPortal creates the <your_email>_personal project and adds an account with the Project manager
role.
Report portal login page
You can use the Velero tool to restore a EDP tenant. Explore the main steps for backup and restoring below.
Delete all related entities in Keycloak: realm and clients from master/openshift realms. Navigate to the entities list in the Keycloak, select the necessary ones, and click the deletion icon on the entity overview page. If there are customized configs in Keycloak, save them before making backup.
Remove keycloak realm
To restore EDP, install and configure the Velero tool. Please refer to the Install Velero documentation for details.
Remove all locks for operators. Delete all config maps that have \u2039OPERATOR_NAME\u203a-operator-lock names. Then restart all pods with operators, or simply run the following command:
kubectl -n edp delete cm $(kubectl -n edp get cm | grep 'operator-lock' | awk '{print $1}')\n
Recreate the admin password and delete the Jenkins pod. Or change the script to update the admin password in Jenkins every time when the pod is updated.
Semgrep is an open-source static source code analyzer for finding bugs and enforcing code standards.
Semgrep scanner is installed on the EDP Jenkins SAST agent and runs on the sast
pipeline stage. For details, please refer to the edp-library-stages repository.
Semgrep supports more than 20 languages, see the full list in the official documentation. EDP uses Semgrep to scan Java, JavaScript and Go languages.
"},{"location":"operator-guide/sast-scaner-semgrep/#related-articles","title":"Related Articles","text":"In case it is necessary to restart pods, use a CronJob according to the following template:
View: template---\nkind: Role\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n namespace: <NAMESPACE>\n name: apps-restart\nrules:\n - apiGroups: [\"apps\"]\n resources:\n - deployments\n - statefulsets\n verbs:\n - 'get'\n - 'list'\n - 'patch'\n---\nkind: RoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n name: apps-restart\n namespace: <NAMESPACE>\nsubjects:\n - kind: ServiceAccount\n name: apps-restart-sa\n namespace: <NAMESPACE>\nroleRef:\n kind: Role\n name: apps-restart\n apiGroup: \"\"\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: apps-restart-sa\n namespace: <NAMESPACE>\n---\napiVersion: batch/v1beta1\nkind: CronJob\nmetadata:\n name: apps-rollout-restart\n namespace: <NAMESPACE>\nspec:\n schedule: \"0 9 * * MON-FRI\"\n jobTemplate:\n spec:\n template:\n spec:\n serviceAccountName: apps-restart-sa\n containers:\n - name: kubectl-runner\n image: bitnami/kubectl\n command:\n - /bin/sh\n - -c\n - kubectl get -n <NAMESPACE> -o name deployment,statefulset | grep <NAME_PATTERN>| xargs kubectl -n <NAMESPACE> rollout restart\n restartPolicy: Never\n
Modify the Cron expression in the CronJob manifest if needed.
"},{"location":"operator-guide/sonarqube/","title":"SonarQube","text":""},{"location":"operator-guide/sonarqube/#sonarqube-integration","title":"SonarQube Integration","text":"This documentation guide provides comprehensive instructions for integrating SonarQube with the EPAM Delivery Platform.
Info
In EDP release 3.5, we have changed the deployment strategy for the sonarqube-operator component, now it is not installed by default. The sonarURL
parameter management has been transferred from the values.yaml file to Kubernetes secrets.
Before proceeding, ensure that you have the following prerequisites:
To install SonarQube with pre-defined templates, use the sonar-operator installed via Cluster Add-Ons approach.
"},{"location":"operator-guide/sonarqube/#configuration","title":"Configuration","text":"To establish robust authentication and precise access control, generating a SonarQube token is essential. This token is a distinct identifier, enabling effortless integration between SonarQube and EDP. To generate the SonarQube token, proceed with the following steps:
Open the SonarQube UI and navigate to Administration
-> Security
-> User
. Create a new user or select an existing one. Click the Options List
icon to create a token:
SonarQube user settings
Type the ci-user
username, define an expiration period, and click the Generate
button to create the token:
SonarQube create token
Click the Copy
button to copy the generated <Sonarqube-token>
:
SonarQube token
Provision secrets using Manifest, EDP Portal or with the externalSecrets operator:
Go to EDP Portal -> EDP -> Configuration -> SonarQube. Update or fill in the URL and Token fields and click the Save button:
SonarQube update manual secret
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-sonarqube\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: sonar\n app.edp.epam.com/integration-secret: true\ntype: Opaque\nstringData:\n url: https://sonarqube.example.com\n token: <sonarqube-token>\n
\"ci-sonarqube\":\n{\n \"url\": \"https://sonarqube.example.com\",\n \"token\": \"XXXXXXXXXXXX\"\n},\n
Go to EDP Portal -> EDP -> Configuration -> SonarQube and see the Managed by External Secret
message:
SonarQube managed by external secret operator
More details about External Secrets Operator integration can be found in the External Secrets Operator Integration page.
"},{"location":"operator-guide/sonarqube/#related-articles","title":"Related Articles","text":"The following material covers Let's Encrypt certificate automation with cert-manager using AWS Route53.
The cert-manager is a Kubernetes/OpenShift operator that allows to issue and automatically renew SSL certificates. In this tutorial, the steps to secure DNS Name will be demonstrated.
Below is an instruction on how to automatically issue and install wildcard certificates on OpenShift Ingress Controller and API Server covering all cluster Routes. To secure separate OpenShift Routes, please refer to the OpenShift Route Support project for cert-manager
.
oc
utility. The kubectl
tool can also be used for most of the commands.Install the cert-manager
operator via OpenShift OperatorHub that uses Operator Lifecycle Manager (OLM):
Go to the OpenShift Admin Console \u2192 OperatorHub, search for the cert-manager
, and click Install:
Cert-Manager Installation
Modify the ClusterServiceVersion
OLM resource, by selecting the Update approval \u2192 Manual. If selecting Update approval \u2192 Automatic after the automatic operator update, the parameters in the ClusterServiceVersion
will be reset to default.
Note
Installing an operator with Manual approval causes all operators installed in namespace openshift-operators
to function as manual approval strategy. In case the Manual approval is chosen, review the manual installation plan and approve it.
Cert-Manager Installation
Navigate to Operators \u2192 Installed Operators and check the operator status to be Succeeded:
Cert-Manager Installation
In case of errors, troubleshoot the Operator issues:
oc describe operator cert-manager -n openshift-operators\noc describe sub cert-manager -n openshift-operators\n
The cert-manager
should be configured to validate Wildcard certificates using the DNS-based method.
Check the DNS Hosted zone ID in AWS Route53 for your domain.
Hosted Zone ID
Create Route53 Permissions policy in AWS for cert-manager
to be able to create DNS TXT records for the certificate validation. In this example, cert-manager
permissions are given for a particular DNS zone only. Replace Hosted zone ID XXXXXXXX in the \"Resource\": \"arn:aws:route53:::hostedzone/XXXXXXXXXXXX\".
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": \"route53:GetChange\",\n \"Resource\": \"arn:aws:route53:::change/*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"route53:ChangeResourceRecordSets\",\n \"route53:ListResourceRecordSets\"\n ],\n \"Resource\": \"arn:aws:route53:::hostedzone/XXXXXXXXXXXX\"\n }\n ]\n}\n
Create an AWS Role with Custom trust policy for the cert-manager
service account to use the AWS IRSA feature and then attach the created policy. Replace the following:
${aws-account-id}
with the AWS account ID of the EKS cluster.${aws-region}
with the region where the EKS cluster is located.${eks-hash}
with the hash in the EKS API URL; this will be a random 32 character hex string, for example, 45DABD88EEE3A227AF0FA468BE4EF0B5.${namespace}
with the namespace where cert-manager is running.${service-account-name}
with the name of the ServiceAccount object created by cert-manager.cert-manager
is installed via OperatorHub.Optionally, add Permissions boundary to the Role.
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::* ${aws-account-id}:oidc-provider/oidc.eks.${aws-region}.amazonaws.com/id/${eks-hash}\"\n },\n \"Condition\": {\n \"StringEquals\": {\n \"oidc.eks.${aws-region}.amazonaws.com/id/${eks-hash}:sub\": \"system:serviceaccount:${namespace}:${service-account-name}\"\n }\n }\n }\n ]\n}\n
Copy the created Role ARN.
Annotate the ServiceAccount
created by cert-manager
(required for AWS IRSA), and restart the cert-manager
pod.
Replace the eks.amazonaws.com/role-arn
annotation value with your own Role ARN.
oc edit sa cert-manager -n openshift-operators\n
apiVersion: v1\nkind: ServiceAccount\nmetadata:\n annotations:\n eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/cert-manager\n
Modify the cert-manager
Deployment
with the correct file system permissions fsGroup: 1001
, so that the ServiceAccount
token can be read.
Note
In case the ServiceAccount
token cannot be read and the operator is installed using the OperatorHub, add fsGroup: 1001
via OpenShift ClusterServiceVersion OLM resource. It should be a cert-manager
controller spec. These actions are not required for OpenShift v4.10.
oc get csv\noc edit csv cert-manager.${VERSION}\n
spec:\n template:\n spec:\n securityContext:\n fsGroup: 1001\n serviceAccountName: cert-manager\n
Cert-Manager System Permissions
Info
A mutating admission controller will automatically modify all pods running with the service account:
cert-manager controller pod
apiVersion: apps/v1\nkind: Pod\n# ...\nspec:\n # ...\n serviceAccountName: cert-manager\n serviceAccount: cert-manager\n containers:\n - name: ...\n # ...\n env:\n - name: AWS_ROLE_ARN\n value: >-\n arn:aws:iam::XXXXXXXXXXX:role/cert-manager\n - name: AWS_WEB_IDENTITY_TOKEN_FILE\n value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token\n volumeMounts:\n - name: aws-iam-token\n readOnly: true\n mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount\n volumes:\n - name: aws-iam-token\n projected:\n sources:\n - serviceAccountToken:\n audience: sts.amazonaws.com\n expirationSeconds: 86400\n path: token\n defaultMode: 420\n
If you have separate public and private DNS zones for the same domain (split-horizon DNS), modify the cert-manager
Deployment
in order to validate DNS TXT records via public recursive nameservers.
Note
Otherwise, you will be getting an error during a record validation:
Waiting for DNS-01 challenge propagation: NS ns-123.awsdns-00.net.:53 returned REFUSED for _acme-challenge.\n
To avoid the error, add --dns01-recursive-nameservers-only --dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53
as ARGs to the cert-manager
controller Deployment
. oc get csv\noc edit csv cert-manager.${VERSION}\n
labels:\n app: cert-manager\n app.kubernetes.io/component: controller\n app.kubernetes.io/instance: cert-manager\n app.kubernetes.io/name: cert-manager\n app.kubernetes.io/version: v1.9.1\nspec:\n containers:\n - args:\n - '--v=2'\n - '--cluster-resource-namespace=$(POD_NAMESPACE)'\n - '--leader-election-namespace=kube-system'\n - '--dns01-recursive-nameservers-only'\n - '--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53'\n
Note
The Deployment
must be modified via OpenShift ClusterServiceVersion OLM resource if the operator was installed using the OperatorHub. The OpenShift ClusterServiceVersion
OLM resource includes several Deployments, and the ARGs must be modified only for the cert-manager
controller.
Cert-Manager Nameservers
ClusterIssuer
is available on the whole cluster.
Create the ClusterIssuer resource for Let's Encrypt Staging and Prod environments that signs a Certificate using cert-manager
.
Note
Let's Encrypt has a limit of duplicate certificates in the Prod environment. Therefore, a ClusterIssuer
has been created for Let's Encrypt Staging environment. By default, Let's Encrypt Staging certificates will not be trusted in your browser. The certificate validation cannot be tested in the Let's Encrypt Staging environment.
user@example.com
with your contact email.hostedZoneID
XXXXXXXXXXX with the DNS Hosted zone ID in AWS for your domain.${region}
.privateKeySecretRef
will be created automatically by the cert-manager
operator.apiVersion: cert-manager.io/v1\nkind: ClusterIssuer\nmetadata:\n name: letsencrypt-staging\nspec:\n acme:\n email: user@example.com\n server: https://acme-staging-v02.api.letsencrypt.org/directory\n privateKeySecretRef:\n name: letsencrypt-staging-issuer-account-key\n solvers:\n - dns01:\n route53:\n region: ${region}\n hostedZoneID: XXXXXXXXXXX\n
apiVersion: cert-manager.io/v1\nkind: ClusterIssuer\nmetadata:\n name: letsencrypt-prod\nspec:\n acme:\n email: user@example.com\n server: https://acme-v02.api.letsencrypt.org/directory\n privateKeySecretRef:\n name: letsencrypt-prod-issuer-account-key\n solvers:\n - dns01:\n route53:\n region: ${region}\n hostedZoneID: XXXXXXXXXXX\n
Cert-Manager ClusterIssuer
Check the ClusterIssuer
status:
Cert-Manager ClusterIssuer
oc describe clusterissuer letsencrypt-prod\noc describe clusterissuer letsencrypt-staging\n
If the ClusterIssuer
state is not ready, investigate cert-manager
controller pod logs:
oc get pod -n openshift-operators | grep 'cert-manager'\noc logs -f cert-manager-${replica_set}-${random_string} -n openshift-operators\n
In two different namespaces, create a Certificate resource for the OpenShift Router (Ingress controller for OpenShift) and for the OpenShift APIServer.
Secret
to be created in the openshift-ingress
namespace; the API Server, in the openshift-config
namespace. The cert-manager
operator will automatically create these secrets from the Certificate
resource.${DOMAIN}
with your domain name. It can be checked with oc whoami --show-server
. Put domain names in quotes.apiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n name: router-certs\n namespace: openshift-ingress\n labels:\n app: cert-manager\nspec:\n secretName: router-certs\n secretTemplate:\n labels:\n app: cert-manager\n duration: 2160h # 90d\n renewBefore: 360h # 15d\n subject:\n organizations:\n - Org Name\n commonName: '*.${DOMAIN}'\n privateKey:\n algorithm: RSA\n encoding: PKCS1\n size: 2048\n rotationPolicy: Always\n usages:\n - server auth\n - client auth\n dnsNames:\n - '*.${DOMAIN}'\n - '*.apps.${DOMAIN}'\n issuerRef:\n name: letsencrypt-staging\n kind: ClusterIssuer\n
The certificate for OpenShift APIServer in the `openshift-config` namespace apiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n name: api-certs\n namespace: openshift-config\n labels:\n app: cert-manager\nspec:\n secretName: api-certs\n secretTemplate:\n labels:\n app: cert-manager\n duration: 2160h # 90d\n renewBefore: 360h # 15d\n subject:\n organizations:\n - Org Name\n commonName: '*.${DOMAIN}'\n privateKey:\n algorithm: RSA\n encoding: PKCS1\n size: 2048\n rotationPolicy: Always\n usages:\n - server auth\n - client auth\n dnsNames:\n - '*.${DOMAIN}'\n - '*.apps.${DOMAIN}'\n issuerRef:\n name: letsencrypt-staging\n kind: ClusterIssuer\n
Info
cert-manager
supports ECDSA key pairs in the Certificate
resource. To use it, change RSA privateKey
to ECDSA:
privateKey:\n algorithm: ECDSA\n encoding: PKCS1\n size: 256\n rotationPolicy: Always\n
rotationPolicy: Always
is highly recommended since cert-manager
does not rotate private keys by default.Certificate
spec is described in the cert-manager
API documentation.Check that the certificates in the namespaces are ready:
Cert-Manager Certificate Status
Cert-Manager Certificate Status
Check the details of the certificates via CLI:
oc describe certificate api-certs -n openshift-config\noc describe certificate router-certs -n openshift-ingress\n
Check the cert-manager controller pod logs if the Staging Certificate condition is not ready for more than 7 minutes:
oc get pod -n openshift-operators | grep 'cert-manager'\noc logs -f cert-manager-${replica_set}-${random_string} -n openshift-operators\n
When the certificate is ready, its private key will be put into the OpenShift Secret
in the namespace indicated in the Certificate
resource:
oc describe secret api-certs -n openshift-config\noc describe secret router-certs -n openshift-ingress\n
Update the Custom Resource of your Router (Ingress controller). Patch the defaultCertificate
object value with { \"name\": \"router-certs\" }
:
oc patch ingresscontroller default -n openshift-ingress-operator --type=merge --patch='{\"spec\": { \"defaultCertificate\": { \"name\": \"router-certs\" }}}' --insecure-skip-tls-verify\n
Info
After updating the IngressController
object, the OpenShift Ingress operator redeploys the router.
Update the Custom Resource for the OpenShift API Server:
Export the name of APIServer
:
export OKD_API=$(oc whoami --show-server --insecure-skip-tls-verify | cut -f 2 -d ':' | cut -f 3 -d '/' | sed 's/-api././')\n
Patch the servingCertificate
object value with { \"name\": \"api-certs\" }
:
oc patch apiserver cluster --type merge --patch=\"{\\\"spec\\\": {\\\"servingCerts\\\": {\\\"namedCertificates\\\": [ { \\\"names\\\": [ \\\"$OKD_API\\\" ], \\\"servingCertificate\\\": {\\\"name\\\": \\\"api-certs\\\" }}]}}}\" --insecure-skip-tls-verify\n
Test the Staging certificate on the OpenShift Admin Console. The --insecure
flag is used because Let's Encrypt Staging certificates are not trusted in browsers by default:
curl -v --insecure https://console-openshift-console.apps.${DOMAIN}\n
Change issuerRef
to letsencrypt-prod
in both Certificate
resources:
oc edit certificate api-certs -n openshift-config\noc edit certificate router-certs -n openshift-ingress\n
issuerRef:\n name: letsencrypt-prod\n kind: ClusterIssuer\n
Note
In case the certificate reissue is not triggered after that, try to force the certificate renewal with cmctl:
cmctl renew router-certs -n openshift-ingress\ncmctl renew api-certs -n openshift-config\n
If this won't work, delete the api-certs
and router-certs
secrets. It should trigger the Prod certificates issuance:
oc delete secret router-certs -n openshift-ingress\noc delete secret api-certs -n openshift-config\n
Please note that these actions will lead to logging your account out of the OpenShift Admin Console, since certificates will be deleted. Accept the certificate warning in the browser and log in again after that.
Check the status of the Prod certificates:
oc describe certificate api-certs -n openshift-config\noc describe certificate router-certs -n openshift-ingress\n
cmctl status certificate api-certs -n openshift-config\ncmctl status certificate router-certs -n openshift-ingress\n
Check the web console and make sure it has secure connection:
curl -v https://console-openshift-console.apps.${DOMAIN}\n
Below is an example of the DNS TXT challenge
record created by the cert-manager
operator:
DNS Validation
Use nslookup
or dig
tools to check if the DNS propagation for the TXT record is complete:
nslookup -type=txt _acme-challenge.${DOMAIN}\ndig txt _acme-challenge.${DOMAIN}\n
Otherwise, use web tools like Google Admin Toolbox:
DNS Validation
If the correct TXT value is shown (the value corresponds to the current TXT value in the DNS zone), it means that the DNS propagation is complete and Let's Encrypt is able to access the record in order to validate it and issue a trusted certificate.
Note
If the DNS validation challenge self check fails, cert-manager
will retry the self check with a fixed 10-second retry interval. Challenges that do not ever complete the self check will continue retrying until the user intervenes by either retrying the Order
(by deleting the Order
resource) or amending the associated Certificate
resource to resolve any configuration errors.
As soon as the domain ownership has been verified, any cert-manager
affected validation TXT records in the AWS Route53 DNS zone will be cleaned up.
Please find below the issues that may occur and their troubleshooting:
cert-manager
resource is not in a Ready state, describing a resource may show the reason for the error.cert-manager
creates the following resources during a Certificate
issuance: CertificateRequest
, Order
, and Challenge
. Investigate each of them in case of errors.Certificate
and its associated resources.Check the cert-manager
controller pod logs:
oc get pod -n openshift-operators | grep 'cert-manager'\noc logs -f cert-manager-${replica_set}-${random_string} -n openshift-operators\n
Certificate error debugging: a. Decode certificate chain located in the secrets:
oc get secret router-certs -n openshift-ingress -o 'go-template={{index .data \"tls.crt\"}}' | base64 -d | while openssl x509 -noout -text; do :; done 2>/dev/null\noc get secret api-certs -n openshift-config -o 'go-template={{index .data \"tls.crt\"}}' | base64 -d | while openssl x509 -noout -text; do :; done 2>/dev/null\n
cmctl inspect secret router-certs -n openshift-ingress\ncmctl inspect secret api-certs -n openshift-config\n
b. Check the SSL RSA private key consistency:
oc get secret router-certs -n openshift-ingress -o 'go-template={{index .data \"tls.key\"}}' | base64 -d | openssl rsa -check -noout\noc get secret api-certs -n openshift-config -o 'go-template={{index .data \"tls.key\"}}' | base64 -d | openssl rsa -check -noout\n
c. Match the SSL certificate public key against its RSA private key. Their modulus must be identical:
diff <(oc get secret api-certs -n openshift-config -o 'go-template={{index .data \"tls.crt\"}}' | base64 -d | openssl x509 -noout -modulus | openssl md5) <(oc get secret api-certs -n openshift-config -o 'go-template={{index .data \"tls.key\"}}' | base64 -d | openssl rsa -noout -modulus | openssl md5)\ndiff <(oc get secret router-certs -n openshift-ingress -o 'go-template={{index .data \"tls.crt\"}}' | base64 -d | openssl x509 -noout -modulus | openssl md5) <(oc get secret router-certs -n openshift-ingress -o 'go-template={{index .data \"tls.key\"}}' | base64 -d | openssl rsa -noout -modulus | openssl md5)\n
After updating the certificates, the access to the cluster via Lens or CLI will be denied because of the untrusted certificate errors:
$ oc whoami\nUnable to connect to the server: x509: certificate signed by unknown authority\n
Such behavior appears because the oc
tool references an old CA data in the kubeconfig file.
Note
Examine the Certificate Authority data using the following command:
oc config view --minify --raw -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d | openssl x509 -text\n
This certificate has the CA:TRUE
parameter, which means that this is a self-signed root CA certificate.
To fix the error, remove the old CA data from your OpenShift kubeconfig file:
sed -i \"/certificate-authority-data/d\" $KUBECONFIG\n
Since this field will be absent in the kubeconfig file, system root SSL certificate will be used to validate the cluster certificate trust chain. On Ubuntu, Let's Encrypt OpenShift cluster certificates will be validated against Internet Security Research Group
root in /etc/ssl/certs/ca-certificates.crt
.
The cert-manager
automatically renews the certificates based on the X.509 certificate's duration and the renewBefore
value. The minimum value for the spec.duration
is 1 hour; for spec.renewBefore
, 5 minutes. It is also required that spec.duration
> spec.renewBefore
.
Use the cmctl tool to manually trigger a single instant certificate renewal:
cmctl renew router-certs -n openshift-ingress\ncmctl renew api-certs -n openshift-config\n
Otherwise, manually renew all certificates in all namespaces with the app=cert-manager
label:
cmctl renew --all-namespaces -l app=cert-manager\n
Run the cmctl renew --help
command to get more details.
This documentation describes how to integrate tekton-pipelines metrics with Prometheus and Grafana monitoring stack.
"},{"location":"operator-guide/tekton-monitoring/#prerequisites","title":"Prerequisites","text":"Ensure the following requirements are met first before moving ahead:
To create and apply the additional scrape config, follow the steps below:
Create the kubernetes secret file with the additional scrape config:
additional-scrape-configs.yaml fileapiVersion: v1\nkind: Secret\nmetadata:\n name: additional-scrape-configs\nstringData:\n prometheus-additional-job.yaml: |\n - job_name: \"tekton-pipelines\"\n scrape_interval: 30s\n static_configs:\n - targets: [\"tekton-pipelines-controller.<tekton-pipelines-namespace>.svc.cluster.local:9090\"]\n
Apply the created secret:
kubectl apply -f additional-scrape-configs.yaml -n <monitoring-namespace>\n
Update the prometheus stack:
helm update --install prometheus prometheus-community/kube-prometheus-stack --values values.yaml -n <monitoring-namespace>\n
The values.yaml
file should have the following contents:
prometheus:\n prometheusSpec:\n additionalScrapeConfigsSecret:\n enabled: true\n name: additional-scrape-configs\n key: prometheus-additional-job.yaml\n
Download the EDP Tekton Pipeline dashboard:
Import Grafana dashboard
a. Click on the dashboard menu;
b. In the dropdown menu, click the + Import
button;
c. Select the created edp-tekton-overview_rev1.json
file;
Import Grafana dashboard: Options
d. Type the name of the dashboard;
e. Select the folder for the dashboard;
f. Type the UID (set of eight numbers or letters and symbols);
g. Click the Import
button.
As soon as the dashboard procedure is completed, you can track the newcoming metrics in the dashboard menu:
Tekton dashboard
"},{"location":"operator-guide/tekton-monitoring/#related-articles","title":"Related Articles","text":"EPAM Delivery Platform provides Continuous Integration based on Tekton.
Tekton is an open-source Kubernetes native framework for creating CI pipelines, allowing a user to compile, build and test applications.
The edp-tekton GitHub repository provides all Tekton implementation logic on the platform. The Helm charts are used to deploy the resources inside the Kubernetes cluster. Tekton logic is decoupled into separate components:
Edp-tekton components diagram
The diagram above describes the following:
Common-library
is the Helm chart of Library type which stores the common logic shareable across all Tekton pipelines. This library contains Helm templates that generate common Tekton resources.Pipelines-library
is the Helm chart of the Application type which stores the core logic for the EDP pipelines. Tekton CRs like Pipelines, Tasks, EventListeners, Triggers, TriggerTemplates, and other resources are delivered with this chart.Custom-pipelines
is the Helm chart of the Application type which implements custom logic running specifically for internal EDP development, for example, CI and Release. It also demonstrates the customization flow on the platform.Tekton-dashboard
is a multitenancy-adopted implementation of the upstream Tekton Dashboard. It is configured to share Tekton resources across a single namespace.EDP Interceptor
is the custom Tekton Interceptor which enriches the payload from the VCSs events with EDP data from the Codebase CR specification. These data are used to define the Pipeline logic.Inspect the schema below that describes the logic behind the Tekton functionality on the platform:
Component view for the Tekton on EDP
The platform logic consists of the following:
The EventListener
exposes a dedicated Pod that runs the sink logic and receives incoming events from the VCSs (Gerrit, GitHub, GitLab) through the Ingress. It contains triggers with filtering and routing rules for incoming requests.
Upon the Event Payload arrival, the EventListener
runs triggers to process information or validate it via different interceptors.
The EDP Interceptor
extracts information from the codebases.v2.edp.epam.com CR and injects the received data into top-level 'extensions' field of the Event Payload. The Interceptor consists of running Pod and Service.
The Tekton Cel Interceptor
does simple transformations of the resulting data and prepares them for the Pipeline parameters substitution.
The TriggerTemplate
creates a PipelineRun instance with the required parameters extracted from the Event Payload by Interceptors. These parameters are mandatory for Pipelines.
The PipelineRun
has a mapping to the EDP Tekton Pipelines using a template approach which reduces code duplication. Each Pipeline is designed for a specific VCS (Gerrit, GitLab, GitHub), technology stack (such as Java or Python), and type (code-review, build).
A Pipeline
consists of separate EDP Tekton or open-source Tasks. They are arranged in a specific order of execution in the Pipeline.
Each Task
is executed as a Pod on the Kubernetes cluster. Also, Tasks can have a different number of steps that are executed as a Container in Pod.
The Kubernetes native approach allows the creation of PipelineRun either with the kubectl tool or using the EDP Portal UI.
This section provides the details on the EDP upgrade to 2.10.2. Explore the actions and requirements below.
Note
Kiosk is optional for EDP v.2.9.0 and higher, and is enabled by default. To disable it, add the following parameter to the values.yaml
file: global.kioskEnabled: false
. Please refer to the Set Up Kiosk documentation for the details.
Note
In the process of updating the EDP, it is necessary to migrate the database for SonarQube, before performing the update procedure, please carefully read section 4 of this guide.
Before updating EDP to 2.10.2, delete SonarQube plugins by executing the following command in SonarQube pod:
rm -r /opt/sonarqube/extensions/plugins/*\n
Update Custom Resource Definitions. Run the following command to apply all the necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.10/deploy-templates/crds/v2_v1alpha1_jenkins_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakclient_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakrealmcomponent_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakrealmidentityprovider_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakrealmrole_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakrealmuser_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloak_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.10/deploy-templates/crds/edp_v1alpha1_nexus_crd.yaml\n
To upgrade EDP to the v.2.10.2, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.10.2\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.10.2 --dry-run
Migrate the database for SonarQube according to the official documentation.
Note
Please be aware of possible tables duplication for speeding up the migration process during the upgrade. Due to the duplication, the database disk usage can be temporarily increased to twice as the normal usage. Therefore, the recommended database disk usage is below 50% before the migration start.
Navigate to the project http://SonarQubeServerURL/setup link and follow the setup instructions:
Migrate SonarQube database
Remove the resources related to the deprecated Sonar Gerrit Plugin that is deleted in EDP 2.10.2:
[label \"Sonar-Verified\"]\n function = MaxWithBlock\n value = -1 Issues found\n value = 0 No score\n value = +1 Verified\n defaultValue = 0\n
label-Sonar-Verified = -1..+1 group Administrators\nlabel-Sonar-Verified = -1..+1 group Project Owners\nlabel-Sonar-Verified = -1..+1 group Service Users\n
git push origin HEAD:refs/meta/config\n
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:1.0.1\nepamedp/edp-jenkins-dotnet-21-agent:1.0.5\nepamedp/edp-jenkins-dotnet-31-agent:1.0.4\nepamedp/edp-jenkins-go-agent:1.0.6\nepamedp/edp-jenkins-gradle-java8-agent:1.0.3\nepamedp/edp-jenkins-gradle-java11-agent:2.0.3\nepamedp/edp-jenkins-helm-agent:1.0.10\nepamedp/edp-jenkins-maven-java8-agent:1.0.3\nepamedp/edp-jenkins-maven-java11-agent:2.0.4\nepamedp/edp-jenkins-npm-agent:2.0.3\nepamedp/edp-jenkins-opa-agent:1.0.2\nepamedp/edp-jenkins-python-38-agent:2.0.4\nepamedp/edp-jenkins-terraform-agent:2.0.5\n
Since EDP version v.2.10.x, the create-release.groovy, code-review.groovy, and build.groovy files are deprecated (pipeline script from SCM
is replaced with pipeline script
, see below).
This section provides the details on the EDP upgrade to 2.11. Explore the actions and requirements below.
Update Custom Resource Definitions. Run the following command to apply all the necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.12/deploy-templates/crds/edp_v1alpha1_cd_stage_deploy_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.11/deploy-templates/crds/v2_v1alpha1_merge_request_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.11/deploy-templates/crds/edp_v1alpha1_user_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/release/2.11/deploy-templates/crds/edp_v1alpha1_cdpipeline_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.11/deploy-templates/crds/v2_v1alpha1_jenkinssharedlibrary_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.11/deploy-templates/crds/v2_v1alpha1_cdstagejenkinsdeployment_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.11/deploy-templates/crds/v1_v1alpha1_keycloakauthflow_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.11/deploy-templates/crds/v1_v1alpha1_keycloakrealmuser_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.12/deploy-templates/crds/edp_v1alpha1_codebaseimagestream_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.12/deploy-templates/crds/edp_v1alpha1_codebase_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.11/deploy-templates/crds/edp_v1alpha1_sonar_group_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.11/deploy-templates/crds/edp_v1alpha1_permission_template_crd.yaml\n
Backup kaniko-template config-map and then remove it. This component will be delivered during upgrade.
Set required awsRegion parameter. Pay attention that the nesting of the kanikoRoleArn parameter has been changed to the kaniko.roleArn parameter. Check the parameters in the EDP installation chart. For details, please refer to the values.yaml file. To upgrade EDP to the v.2.11.x, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.11.x\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.11.x --dry-run
Update Sonar Project Key:
Note
Avoid using special characters when creating projects in SonarQube. Allowed characters are: letters
, numbers
, -
, _
, .
and :
, with at least one non-digit. For details, please refer to the SonarQube documentation. As the result, the project name will be: project-name-release-0.0
or project-name-branchName
.
Such actions are required to be followed with the aim to store the SonarQube statistics from the previous EDP version:
Warning
Do not run any pipeline with the updated sonar stage on any existing application before the completion of the first step.
4.1. Update the project key in SonarQube from old to new format by adding the default branch name.
- Navigate to Project Settings -> Update Key: Update SonarQube project key - Enter the default branch name and click Update: Update SonarQube project key
4.2. As the result, after the first run, the project name will be changed to a new format containing all previous statistics:
SonarQube project history activity
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:3.0.4\nepamedp/edp-jenkins-dotnet-21-agent:3.0.4\nepamedp/edp-jenkins-dotnet-31-agent:3.0.3\nepamedp/edp-jenkins-go-agent:3.0.5\nepamedp/edp-jenkins-gradle-java11-agent:3.0.2\nepamedp/edp-jenkins-gradle-java8-agent:3.0.2\nepamedp/edp-jenkins-helm-agent:3.0.3\nepamedp/edp-jenkins-maven-java11-agent:3.0.3\nepamedp/edp-jenkins-maven-java8-agent:3.0.3\nepamedp/edp-jenkins-npm-agent:3.0.4\nepamedp/edp-jenkins-opa-agent:3.0.2\nepamedp/edp-jenkins-python-38-agent:3.0.2\nepamedp/edp-jenkins-terraform-agent:3.0.3\n
Add Jenkins agent by following the template:
View: values.yaml
kaniko-docker-template: |-\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>kaniko-docker</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>kaniko-docker</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>epamedp/edp-jenkins-kaniko-docker-agent:1.0.4</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n
Update the Jenkins plugins with the 'pipeline' name and 'HTTP Request Plugin'.
Update Jenkins provisioners according to the Manage Jenkins CI Pipeline Job Provisioner and Manage Jenkins CD Pipeline Job Provisioner documentation.
Restart the codebase-operator to recreate the Code-review and Build pipelines for codebases.
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides the details on the EDP upgrade to 2.12. Explore the actions and requirements below.
Notes
networking.k8s.io/v1
, and Ingress Operators use CustomResourceDefinition apiextensions.k8s.io/v1
.EDP now uses DefectDojo as a SAST tool. It is mandatory to deploy DefectDojo before updating EDP to v.2.12.x.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-admin-console-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_adminconsoles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_cdpipelines.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_cdstagedeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_cdstagejenkinsdeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_codebasebranches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_codebaseimagestreams.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-component-operator/release/0.12/deploy-templates/crds/v1.edp.epam.com_edpcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritgroupmembers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritmergerequests.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritprojectaccesses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritprojects.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritreplicationconfigs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_gittags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_imagestreamtags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsagents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsauthorizationrolemappings.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsauthorizationroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsfolders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsjobbuildruns.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsjobs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsscripts.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsserviceaccounts.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinssharedlibraries.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_jiraissuemetadatas.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_jiraservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakauthflows.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakclients.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakclientscopes.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmidentityproviders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmrolebatches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealms.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmusers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloaks.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_nexuses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_nexususers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_perfdatasourcegitlabs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_perfdatasourcejenkinses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_perfdatasourcesonars.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_perfservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_sonargroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_sonarpermissiontemplates.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_sonars.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_stages.yaml\n
Set the required parameters. For details, please refer to the values.yaml file.
v3.6.1
. According to the Official Gerrit Upgrade flow, a user must initially upgrade to Gerrit v3.5.2
, and then upgrade to v3.6.1
. Therefore, define the gerrit-operator.gerrit.version=3.5.2
value in the edp-install values.yaml
file.Two more components are available with the new functionality:
edp-argocd-operator
external-secrets
false
values for them in the existing value.yaml
file:View: values.yaml
gerrit-operator:\n gerrit:\n version: \"3.5.2\"\nexternalSecrets:\n enabled: false\nargocd:\n enabled: false\n
The edp-jenkins-role
is renamed to the jenkins-resources-role
. Delete the edp-jenkins-role
with the following command:
kubectl delete role edp-jenkins-role -n <edp-namespace>\n
The jenkins-resources-role
role will be created automatically while EDP upgrade.
Recreate the edp-jenkins-resources-permissions
RoleBinding according to the following template:
View: jenkins-resources-role
apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n name: edp-jenkins-resources-permissions\n namespace: <edp-namespace>\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: Role\n name: jenkins-resources-role\n
To upgrade EDP to the v.2.12.x, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.x\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.x --dry-run
After the update, please remove the gerrit-operator.gerrit.version
value. In this case, the default value will be used, and Gerrit will be updated to the v3.6.1
version. Run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.x\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.x --dry-run
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:3.0.8\nepamedp/edp-jenkins-dotnet-21-agent:3.0.7\nepamedp/edp-jenkins-dotnet-31-agent:3.0.7\nepamedp/edp-jenkins-go-agent:3.0.11\nepamedp/edp-jenkins-gradle-java11-agent:3.0.5\nepamedp/edp-jenkins-gradle-java8-agent:3.0.7\nepamedp/edp-jenkins-helm-agent:3.0.8\nepamedp/edp-jenkins-maven-java11-agent:3.0.6\nepamedp/edp-jenkins-maven-java8-agent:3.0.8\nepamedp/edp-jenkins-npm-agent:3.0.7\nepamedp/edp-jenkins-opa-agent:3.0.5\nepamedp/edp-jenkins-python-38-agent:3.0.5\nepamedp/edp-jenkins-terraform-agent:3.0.6\n
Add Jenkins agents by following the template:
View: jenkins-slaves
sast-template: |\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>sast</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>sast</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>epamedp/edp-jenkins-sast-agent:0.1.3</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n
If required, update the requests and limits for the following Jenkins agents:
edp-jenkins-codenarc-agent
edp-jenkins-go-agent
edp-jenkins-gradle-java11-agent
edp-jenkins-gradle-java8-agent
edp-jenkins-maven-java11-agent
edp-jenkins-maven-java8-agent
edp-jenkins-npm-agent
edp-jenkins-dotnet-21-agent
edp-jenkins-dotnet-31-agent
EDP requires to start with the following values:
View: jenkins-slaves
<resourceRequestCpu>500m</resourceRequestCpu>\n <resourceRequestMemory>1Gi</resourceRequestMemory>\n <resourceLimitCpu>2</resourceLimitCpu>\n <resourceLimitMemory>5Gi</resourceLimitMemory>\n
Update Jenkins provisioners according to the Manage Jenkins CI Pipeline Job Provisioner instruction.
Restart the codebase-operator
, to recreate the Code Review and Build pipelines for the codebases.
Warning
In case there are different EDP versions on one cluster, the following error may occur on the init
stage of Jenkins Groovy pipeline: java.lang.NumberFormatException: For input string: \"\"
. To fix this issue, please run the following command using kubectl
v1.24.4+:
kubectl patch codebasebranches.v2.edp.epam.com <codebase-branch-name> -n <edp-namespace> '--subresource=status' '--type=merge' -p '{\"status\": {\"build\": \"0\"}}'\n
"},{"location":"operator-guide/upgrade-edp-2.12/#upgrade-edp-to-2122","title":"Upgrade EDP to 2.12.2","text":"Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides the details on the EDP upgrade to 2.12.2. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.12.2/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.12.1/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\n
To upgrade EDP to 2.12.2, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.2\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.2 --dry-run
This section provides the details on the EDP upgrade to 2.8.4. Explore the actions and requirements below.
Note
Kiosk is implemented and mandatory for EDP v.2.8.4 and is optional for EDP v.2.9.0 and higher.
To upgrade EDP to 2.8.4, take the following steps:
Deploy and configure Kiosk (create a Service Account, Account, and ClusterRoleBinging) according to the Set Up Kiosk documentation.
apiVersion: tenancy.kiosk.sh/v1alpha1\nkind: Space\nmetadata:\n name: <edp-project>\nspec:\n account: <edp-project>-admin\n
Create RoleBinding (required for namespaces created before using Kiosk):
Note
In the uid field under the ownerReferences in the Kubernetes manifest, indicate the Account Custom Resource ID from accounts.config.kiosk.sh kubectl get account <edp-project>-admin -o=custom-columns=NAME:.metadata.uid --no-headers=true
View: rolebinding-kiosk.yaml
apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n generateName: <edp-project>-admin-\n namespace: <edp-project>\n ownerReferences:\n - apiVersion: config.kiosk.sh/v1alpha1\n blockOwnerDeletion: true\n controller: true\n kind: Account\n name: <edp-project>-admin\n uid: ''\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: kiosk-space-admin\nsubjects:\n- kind: ServiceAccount\n name: <edp-project>\n namespace: security\n
kubectl create -f rolebinding-kiosk.yaml\n
With Amazon Elastic Container Registry to store the images, there are two options:
Update Custom Resource Definitions by applying all the necessary CRD to the cluster with the command below:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/release/2.8/deploy-templates/crds/edp_v1alpha1_cdpipeline_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.8/deploy-templates/crds/edp_v1alpha1_codebase_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.8/deploy-templates/crds/edp_v1alpha1_cd_stage_deploy_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.8/deploy-templates/crds/v2_v1alpha1_jenkinsjobbuildrun_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.8/deploy-templates/crds/v2_v1alpha1_cdstagejenkinsdeployment_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.8/deploy-templates/crds/v2_v1alpha1_jenkinsjob_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.8/deploy-templates/crds/edp_v1alpha1_nexus_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.8/deploy-templates/crds/v1_v1alpha1_keycloakauthflow_crd.yaml\n
With Amazon Elastic Container Registry to store and Kaniko to build the images, add the kanikoRoleArn parameter to the values before starting the update process. This parameter is indicated in AWS Roles once IRSA is enabled and AWS IAM Role is created for Kaniko. The value should look as follows:
kanikoRoleArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko\n
To upgrade EDP to the v.2.8.4, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.8.4\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.8.4 --dry-run
Remove the following Kubernetes resources left from the previous EDP installation (it is optional):
kubectl delete cm luminatesec-conf -n <edp-namespace>\nkubectl delete sa edp edp-perf-operator -n <edp-namespace>\nkubectl delete deployment perf-operator -n <edp-namespace>\nkubectl delete clusterrole edp-<edp-namespace> edp-perf-operator-<edp-namespace>\nkubectl delete clusterrolebinding edp-<edp-namespace> edp-perf-operator-<edp-namespace>\nkubectl delete rolebinding edp-<edp-namespace> edp-perf-operator-<edp-namespace>-admin -n <edp-namespace>\nkubectl delete perfserver epam-perf -n <edp-namespace>\nkubectl delete services.v2.edp.epam.com postgres rabbit-mq -n <edp-namespace>\n
Update the CI and CD Jenkins job provisioners:
Note
Please refer to the Manage Jenkins CI Pipeline Job Provisioner section for the details.
View: Default CI provisioner template for EDP 2.8.4/* Copyright 2021 EPAM Systems.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nimport groovy.json.*\nimport jenkins.model.Jenkins\nimport hudson.model.*\n\nJenkins jenkins = Jenkins.instance\ndef stages = [:]\ndef jiraIntegrationEnabled = Boolean.parseBoolean(\"${JIRA_INTEGRATION_ENABLED}\" as String)\ndef commitValidateStage = jiraIntegrationEnabled ? ',{\"name\": \"commit-validate\"}' : ''\ndef createJIMStage = jiraIntegrationEnabled ? ',{\"name\": \"create-jira-issue-metadata\"}' : ''\ndef buildTool = \"${BUILD_TOOL}\"\ndef goBuildStage = buildTool.toString() == \"go\" ? ',{\"name\": \"build\"}' : ',{\"name\": \"compile\"}'\n\nstages['Code-review-application'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + goBuildStage +\n ',{\"name\": \"tests\"},[{\"name\": \"sonar\"},{\"name\": \"dockerfile-lint\"},{\"name\": \"helm-lint\"}]]'\nstages['Code-review-library'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"compile\"},{\"name\": \"tests\"},' +\n '{\"name\": \"sonar\"}]'\nstages['Code-review-autotests'] = '[{\"name\": \"gerrit-checkout\"},{\"name\": \"get-version\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"},{\"name\": \"sonar\"}' + \"${createJIMStage}\" + ']'\nstages['Code-review-default'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + ']'\nstages['Code-review-library-terraform'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"terraform-lint\"}]'\nstages['Code-review-library-opa'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"}]'\nstages['Code-review-library-codenarc'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}]'\n\nstages['Build-library-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-npm'] = stages['Build-library-maven']\nstages['Build-library-gradle'] = stages['Build-library-maven']\nstages['Build-library-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"terraform-lint\"}' +\n ',{\"name\": \"terraform-plan\"},{\"name\": \"terraform-apply\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-opa'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"tests\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-codenarc'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\n\nstages['Build-application-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},[{\"name\": \"sonar\"}],{\"name\": \"build\"},{\"name\": \"build-image-kaniko\"},' +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-npm'] = stages['Build-application-maven']\nstages['Build-application-gradle'] = stages['Build-application-maven']\nstages['Build-application-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},[{\"name\": \"sonar\"}],{\"name\": \"build-image-kaniko\"},' +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-go'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"tests\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build\"},{\"name\": \"build-image-kaniko\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build-image-kaniko\"},{\"name\": \"push\"}' + \"${createJIMStage}\" +\n ',{\"name\": \"git-tag\"}]'\n\nstages['Create-release'] = '[{\"name\": \"checkout\"},{\"name\": \"create-branch\"},{\"name\": \"trigger-job\"}]'\n\ndef defaultBuild = '[{\"name\": \"checkout\"}' + \"${createJIMStage}\" + ']'\n\ndef codebaseName = \"${NAME}\"\ndef gitServerCrName = \"${GIT_SERVER_CR_NAME}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}\"\ndef repositoryPath = \"${REPOSITORY_PATH}\"\ndef defaultBranch = \"${DEFAULT_BRANCH}\"\n\ndef codebaseFolder = jenkins.getItem(codebaseName)\nif (codebaseFolder == null) {\n folder(codebaseName)\n}\n\ncreateListView(codebaseName, \"Releases\")\ncreateReleasePipeline(\"Create-release-${codebaseName}\", codebaseName, stages[\"Create-release\"], \"create-release.groovy\",\n repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, defaultBranch)\n\nif (buildTool.toString().equalsIgnoreCase('none')) {\n return true\n}\n\nif (BRANCH) {\n def branch = \"${BRANCH}\"\n def formattedBranch = \"${branch.toUpperCase().replaceAll(/\\\\//, \"-\")}\"\n createListView(codebaseName, formattedBranch)\n\n def type = \"${TYPE}\"\n def crKey = getStageKeyName(buildTool)\n createCiPipeline(\"Code-review-${codebaseName}\", codebaseName, stages[crKey], \"code-review.groovy\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n def buildKey = \"Build-${type}-${buildTool.toLowerCase()}\".toString()\n if (type.equalsIgnoreCase('application') || type.equalsIgnoreCase('library')) {\n def jobExists = false\n if(\"${formattedBranch}-Build-${codebaseName}\".toString() in Jenkins.instance.getAllItems().collect{it.name})\n jobExists = true\n\n createCiPipeline(\"Build-${codebaseName}\", codebaseName, stages.get(buildKey, defaultBuild), \"build.groovy\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n if(!jobExists)\n queue(\"${codebaseName}/${formattedBranch}-Build-${codebaseName}\")\n }\n}\n\ndef createCiPipeline(pipelineName, codebaseName, codebaseStages, pipelineScript, repository, credId, watchBranch, gitServerCrName, gitServerCrVersion) {\n pipelineJob(\"${codebaseName}/${watchBranch.toUpperCase().replaceAll(/\\\\//, \"-\")}-${pipelineName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n triggers {\n gerrit {\n events {\n if (pipelineName.contains(\"Build\"))\n changeMerged()\n else\n patchsetCreated()\n }\n project(\"plain:${codebaseName}\", [\"plain:${watchBranch}\"])\n }\n }\n definition {\n cpsScm {\n scm {\n git {\n remote {\n url(repository)\n credentials(credId)\n }\n branches(\"${watchBranch}\")\n scriptPath(\"${pipelineScript}\")\n }\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n stringParam(\"BRANCH\", \"${watchBranch}\", \"Branch to build artifact from\")\n }\n }\n }\n }\n}\n\ndef getStageKeyName(buildTool) {\n if (buildTool.toString().equalsIgnoreCase('terraform')) {\n return \"Code-review-library-terraform\"\n }\n if (buildTool.toString().equalsIgnoreCase('opa')) {\n return \"Code-review-library-opa\"\n }\n if (buildTool.toString().equalsIgnoreCase('codenarc')) {\n return \"Code-review-library-codenarc\"\n }\n def buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n return supBuildTool ? \"Code-review-${TYPE}\" : \"Code-review-default\"\n}\n\ndef createReleasePipeline(pipelineName, codebaseName, codebaseStages, pipelineScript, repository, credId,\n gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, defaultBranch) {\n pipelineJob(\"${codebaseName}/${pipelineName}\") {\n logRotator {\n numToKeep(14)\n daysToKeep(30)\n }\n definition {\n cpsScm {\n scm {\n git {\n remote {\n url(repository)\n credentials(credId)\n }\n branches(\"${defaultBranch}\")\n scriptPath(\"${pipelineScript}\")\n }\n }\n parameters {\n stringParam(\"STAGES\", \"${codebaseStages}\", \"\")\n if (pipelineName.contains(\"Create-release\")) {\n stringParam(\"JIRA_INTEGRATION_ENABLED\", \"${jiraIntegrationEnabled}\", \"Is Jira integration enabled\")\n stringParam(\"GERRIT_PROJECT\", \"${codebaseName}\", \"\")\n stringParam(\"RELEASE_NAME\", \"\", \"Name of the release(branch to be created)\")\n stringParam(\"COMMIT_ID\", \"\", \"Commit ID that will be used to create branch from for new release. If empty, HEAD of master will be used\")\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"REPOSITORY_PATH\", \"${repository}\", \"Full repository path\")\n stringParam(\"DEFAULT_BRANCH\", \"${defaultBranch}\", \"Default repository branch\")\n }\n }\n }\n }\n }\n}\n\ndef createListView(codebaseName, branchName) {\n listView(\"${codebaseName}/${branchName}\") {\n if (branchName.toLowerCase() == \"releases\") {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^Create-release.*\")\n }\n }\n } else {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^${branchName}-(Code-review|Build).*\")\n }\n }\n }\n columns {\n status()\n weather()\n name()\n lastSuccess()\n lastFailure()\n lastDuration()\n buildButton()\n }\n }\n}\n
Note
Please refer to the Manage Jenkins CD Pipeline Job Provisioner page for the details.
View: Default CD provisioner template for EDP 2.8.4/* Copyright 2021 EPAM Systems.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nimport groovy.json.*\nimport jenkins.model.Jenkins\n\nJenkins jenkins = Jenkins.instance\n\ndef pipelineName = \"${PIPELINE_NAME}-cd-pipeline\"\ndef stageName = \"${STAGE_NAME}\"\ndef qgStages = \"${QG_STAGES}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID}\"\ndef sourceType = \"${SOURCE_TYPE}\"\ndef libraryURL = \"${LIBRARY_URL}\"\ndef libraryBranch = \"${LIBRARY_BRANCH}\"\ndef autodeploy = \"${AUTODEPLOY}\"\ndef scriptPath = \"Jenkinsfile\"\ndef containerDeploymentType = \"container\"\ndef deploymentType = \"${DEPLOYMENT_TYPE}\"\n\ndef stages = buildStages(deploymentType, containerDeploymentType, qgStages)\n\ndef codebaseFolder = jenkins.getItem(pipelineName)\nif (codebaseFolder == null) {\n folder(pipelineName)\n}\n\nif (deploymentType == containerDeploymentType) {\n createContainerizedCdPipeline(pipelineName, stageName, stages, scriptPath, sourceType,\n libraryURL, libraryBranch, gitCredentialsId, gitServerCrVersion,\n autodeploy)\n} else {\n createCustomCdPipeline(pipelineName, stageName)\n}\n\ndef buildStages(deploymentType, containerDeploymentType, qgStages) {\n return deploymentType == containerDeploymentType\n ? '[{\"name\":\"init\",\"step_name\":\"init\"},{\"name\":\"deploy\",\"step_name\":\"deploy\"},' + qgStages + ',{\"name\":\"promote-images-ecr\",\"step_name\":\"promote-images\"}]'\n : ''\n}\n\ndef createContainerizedCdPipeline(pipelineName, stageName, stages, pipelineScript, sourceType, libraryURL, libraryBranch, libraryCredId, gitServerCrVersion, autodeploy) {\n pipelineJob(\"${pipelineName}/${stageName}\") {\n if (sourceType == \"library\") {\n definition {\n cpsScm {\n scm {\n git {\n remote {\n url(libraryURL)\n credentials(libraryCredId)\n }\n branches(\"${libraryBranch}\")\n scriptPath(\"${pipelineScript}\")\n }\n }\n }\n }\n } else {\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\nDeploy()\")\n sandbox(true)\n }\n }\n }\n properties {\n disableConcurrentBuilds()\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${stages}\", \"Consequence of stages in JSON format to be run during execution\")\n\n if (autodeploy?.trim() && autodeploy.toBoolean()) {\n stringParam(\"AUTODEPLOY\", \"${autodeploy}\", \"Is autodeploy enabled?\")\n stringParam(\"CODEBASE_VERSION\", null, \"Codebase versions to deploy.\")\n }\n }\n }\n}\n\ndef createCustomCdPipeline(pipelineName, stageName) {\n pipelineJob(\"${pipelineName}/${stageName}\") {\n properties {\n disableConcurrentBuilds()\n }\n }\n}\n
Update Jenkins pipelines and stages to the new release tag:
Update the edp-admin-console Custom Resource in the KeycloakClient Custom Resource Definition:
View: keycloakclient.yamlkind: KeycloakClient\napiVersion: v1.edp.epam.com/v1alpha1\nmetadata:\n name: edp-admin-console\n namespace: <edp-namespace>\nspec:\n advancedProtocolMappers: false\n attributes: null\n audRequired: true\n clientId: admin-console-client\n directAccess: true\n public: false\n secret: admin-console-client\n serviceAccount:\n enabled: true\n realmRoles:\n - developer\n targetRealm: <keycloak-edp-realm>\n webUrl: >-\n https://edp-admin-console-example.com\n
kubectl apply -f keycloakclient.yaml\n
Remove the admin-console-client client ID in the edp-namespace-main realm in Keycloak, restart the keycloak-operator pod and check that the new KeycloakClient is created with the confidential access type.
Note
If \"Internal error\" occurs, regenerate the admin-console-client secret in the Credentials tab in Keycloak and update the admin-console-client secret key \"clientSecret\" and \"password\".
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-dotnet-21-agent:1.0.2\nepamedp/edp-jenkins-dotnet-31-agent:1.0.2\nepamedp/edp-jenkins-go-agent:1.0.3\nepamedp/edp-jenkins-gradle-java11-agent:2.0.2\nepamedp/edp-jenkins-gradle-java8-agent:1.0.2\nepamedp/edp-jenkins-helm-agent:1.0.6\nepamedp/edp-jenkins-maven-java11-agent:2.0.3\nepamedp/edp-jenkins-maven-java8-agent:1.0.2\nepamedp/edp-jenkins-npm-agent:2.0.2\nepamedp/edp-jenkins-python-38-agent:2.0.3\nepamedp/edp-jenkins-terraform-agent:2.0.4\n
data:\n codenarc-template: |-\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>codenarc</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>codenarc</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>epamedp/edp-jenkins-codenarc-agent:1.0.0</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n opa-template: |-\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>opa</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>opa</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>epamedp/edp-jenkins-opa-agent:1.0.1</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n
Update compatible plugins in Jenkins and install additional plugins:
Add the annotation deploy.edp.epam.com/previous-stage-name: ''
(it should be empty if the CD pipeline contains one stage) to each Custom Resource in the Custom Resource Definition Stage, for example:
kubectl get stages.v2.edp.epam.com -n <edp-namespace>
kubectl edit stages.v2.edp.epam.com <cd-stage-name> -n <edp-namespace>
apiVersion: v2.edp.epam.com/v1alpha1\nkind: Stage\nmetadata:\n annotations:\n deploy.edp.epam.com/previous-stage-name: ''\n
Note
If a pipeline contains several stages, add a previous stage name indicated in the EDP Admin Console to the annotation, for example: deploy.edp.epam.com/previous-stage-name: 'dev'
.
Execute script to align CDPipeline resources to the new API (jq command-line JSON processor is required):
pipelines=$( kubectl get cdpipelines -n <edp-namespace> -ojson | jq -c '.items[]' )\nfor p in $pipelines; do\n echo \"$p\" | \\\n jq '. | .spec.inputDockerStreams = .spec.input_docker_streams | del(.spec.input_docker_streams) | .spec += { \"deploymentType\": \"container\" } ' | \\\n kubectl apply -f -\ndone\n
Update the database in the edp-db pod in the edp-namespace:
kubectl exec -i -t -n <edp-namespace> edp-db-<pod> -c edp-db \"--\" sh -c \"(bash || ash || sh)\"\n
psql edp-db <admin>;\nSET search_path to '<edp-namespace>';\nUPDATE cd_pipeline SET deployment_type = 'container';\n
Add \"AUTODEPLOY\":\"true/false\",\"DEPLOYMENT_TYPE\":\"container\"
to every Custom Resource in jenkinsjobs.v2.edp.epam.com
:
kubectl get jenkinsjobs.v2.edp.epam.com -n <edp-namespace>\n\nkubectl edit jenkinsjobs.v2.edp.epam.com <cd-pipeline-name> -n <edp-namespace>\n
edp_namespace=<epd_namespace>\nfor stages in $(kubectl get jenkinsjobs -o=name -n $edp_namespace); do kubectl get $stages -n $edp_namespace -o yaml | grep -q \"container\" && echo -e \"\\n$stages is already updated\" || kubectl get $stages -n $edp_namespace -o yaml | sed 's/\"GIT_SERVER_CR_VERSION\"/\"AUTODEPLOY\":\"false\",\"DEPLOYMENT_TYPE\":\"container\",\"GIT_SERVER_CR_VERSION\"/g' | kubectl apply -f -; done\n
job:\n config: '{\"AUTODEPLOY\":\"false\",\"DEPLOYMENT_TYPE\":\"container\",\"GIT_SERVER_CR_VERSION\":\"v2\",\"PIPELINE_NAME\":\"your-pipeline-name\",\"QG_STAGES\":\"{\\\"name\\\":\\\"manual\\\",\\\"step_name\\\":\\\"your-step-name\\\"}\",\"SOURCE_TYPE\":\"default\",\"STAGE_NAME\":\"your-stage-name\"}'\n name: job-provisions/job/cd/job/default\n
SonarQube fails during the CI pipeline run. The previous builds of SonarQube used the latest version of the OpenID Connect Authentication for SonarQube plugin. Version 2.1.0 of this plugin may have issues with the connection, so it is necessary to downgrade it in order to get rid of errors in the pipeline. Take the following steps:
kubectl exec -i -t -n <edp-namespace> sonar-<pod> -c sonar \"--\" sh -c \"(bash || ash || sh)\"\n
rm extensions/plugins/sonar-auth-oidc-plugin*\n
curl -L https://github.com/vaulttec/sonar-auth-oidc/releases/download/v2.0.0/sonar-auth-oidc-plugin-2.0.0.jar --output extensions/plugins/sonar-auth-oidc-plugin-2.0.0.jar\n
The Helm lint checker in EDP 2.8.4 has some additional rules. There can be issues with it during the Code Review pipeline in Jenkins for applications that were transferred from previous EDP versions to EDP 2.8.4. To fix this, add the following annotation to the Chart.yaml
file:
deploy-templates/Chart.yaml
file.Chart.yaml
file:home: https://github.com/your-repo.git\nsources:\n - https://github.com/your-repo.git\nmaintainers:\n - name: DEV Team\n
This section provides the details on the EDP upgrade to 2.9.0. Explore the actions and requirements below.
Note
Kiosk is optional for EDP v.2.9.0 and higher, and enabled by default. To disable it, add the following parameter to the values.yaml
file: kioskEnabled: false
. Please refer to the Set Up Kiosk documentation for the details.
With Amazon Elastic Container Registry to store the images, there are two options:
Before updating EDP to 2.9.0, update the gerrit-is-credentials
secret by adding the new clientSecret
key with the value from gerrit-is-credentials.client_secret
:
kubectl edit secret gerrit-is-credentials -n <edp-namespace>\n
data:\n client_secret: example\n clientSecret: example\n
Update Custom Resource Definitions. This command will apply all the necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_gerritgroupmember_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_gerritgroup_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_gerritprojectaccess_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_gerritproject_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_jenkins_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_jenkinsagent_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_jenkinsauthorizationrolemapping_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_jenkinsauthorizationrole_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.9/deploy-templates/crds/v1_v1alpha1_keycloakclientscope_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.9/deploy-templates/crds/v1_v1alpha1_keycloakrealmuser_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.9/deploy-templates/crds/edp_v1alpha1_nexus_crd.yaml\n
With Amazon Elastic Container Registry to store and Kaniko to build the images, add the kanikoRoleArn parameter to the values before starting the update process. This parameter is indicated in AWS Roles once IRSA is enabled and AWS IAM Role is created for Kaniko.The value should look as follows:
kanikoRoleArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko\n
To upgrade EDP to the v.2.9.0, run the following command:
helm upgrade --install edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.9.0\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with: helm upgrade --install edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.9.0 --dry-run
Remove the following Kubernetes resources left from the previous EDP installation (it is optional):
kubectl delete rolebinding edp-cd-pipeline-operator-<edp-namespace>-admin -n <edp-namespace>\n
After EDP update, please restart the 'sonar-operator' pod to address the proper Sonar plugin versioning. After 'sonar-operator' is restarted, check the list of installed plugins in the corresponding SonarQube menu.
Update Jenkins pipelines and stages to the new release tag:
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:1.0.1\nepamedp/edp-jenkins-dotnet-21-agent:1.0.3\nepamedp/edp-jenkins-dotnet-31-agent:1.0.3\nepamedp/edp-jenkins-go-agent:1.0.4\nepamedp/edp-jenkins-gradle-java8-agent:1.0.3\nepamedp/edp-jenkins-gradle-java11-agent:2.0.3\nepamedp/edp-jenkins-helm-agent:1.0.7\nepamedp/edp-jenkins-maven-java8-agent:1.0.3\nepamedp/edp-jenkins-maven-java11-agent:2.0.4\nepamedp/edp-jenkins-npm-agent:2.0.3\nepamedp/edp-jenkins-opa-agent:1.0.2\nepamedp/edp-jenkins-python-38-agent:2.0.4\nepamedp/edp-jenkins-terraform-agent:2.0.5\n
Update the compatible plugins in Jenkins:
Important
global.kioskEnabled
parameter in the values.yaml file. For details, please refer to the Set Up Kiosk page.gerrit-ssh-port
parameter is moved from the gerrit-operator.gerrit.sshport
to global.gerritSSHPort
values.yaml file.gitServer.user
value is changed from the jenkins
to edp-ci
values.yaml file.This section provides the details on upgrading EDP to 3.0. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/d9a4d15244c527ef6d1d029af27574282a281b98/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_cdstagedeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_codebasebranches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_codebaseimagestreams.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_gittags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_imagestreamtags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_jiraissuemetadatas.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_jiraservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakauthflows.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakclients.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakclientscopes.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmidentityproviders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmrolebatches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealms.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmusers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloaks.yaml\n
Set the required parameters. For more details, please refer to the values.yaml file.
View: values.yamledp-tekton:\n enabled: false\nadmin-console-operator:\n enabled: true\njenkins-operator:\n enabled: true\n
Add proper Helm annotations and labels as indicated below. This step is necessary starting from the release v.3.0.x as custom resources are managed by Helm and removed from the Keycloak Controller logic.
kubectl label EDPComponent main-keycloak app.kubernetes.io/managed-by=Helm -n <edp-namespace>\n kubectl annotate EDPComponent main-keycloak meta.helm.sh/release-name=<edp-release-name> -n <edp-namespace>\n kubectl annotate EDPComponent main-keycloak meta.helm.sh/release-namespace=<edp-namespace> -n <edp-namespace>\n kubectl label KeycloakRealm main app.kubernetes.io/managed-by=Helm -n <edp-namespace>\n kubectl annotate KeycloakRealm main meta.helm.sh/release-name=<edp-release-name> -n <edp-namespace>\n kubectl annotate KeycloakRealm main meta.helm.sh/release-namespace=<edp-namespace> -n <edp-namespace>\n
To upgrade EDP to 3.0, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.0.x\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.0.x --dry-run
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:3.0.10\nepamedp/edp-jenkins-dotnet-31-agent:3.0.9\nepamedp/edp-jenkins-go-agent:3.0.17\nepamedp/edp-jenkins-gradle-java11-agent:3.0.7\nepamedp/edp-jenkins-gradle-java8-agent:3.0.10\nepamedp/edp-jenkins-helm-agent:3.0.11\nepamedp/edp-jenkins-kaniko-docker-agent:1.0.9\nepamedp/edp-jenkins-maven-java11-agent:3.0.7\nepamedp/edp-jenkins-maven-java8-agent:3.0.10\nepamedp/edp-jenkins-npm-agent:3.0.9\nepamedp/edp-jenkins-opa-agent:3.0.7\nepamedp/edp-jenkins-python-38-agent:3.0.8\nepamedp/edp-jenkins-sast-agent:0.1.5\nepamedp/edp-jenkins-terraform-agent:3.0.9\n
edp-jenkins-dotnet-21-agent
agent manifest.Attach the id_rsa.pub
SSH public key from the gerrit-ciuser-sshkey
secret to the edp-ci
Gerrit user in the gerrit
pod:
ssh -p <gerrit_ssh_port> <host> gerrit set-account --add-ssh-key ~/id_rsa.pub\n
Notes
gerrit-admin
SSH key from secrets.<host>
is admin@localhost or any other user with permissions.Change the username from jenkins
to edp-ci
in the gerrit-ciuser-sshkey
secret:
kubectl -n <edp-namespace> patch secret gerrit-ciuser-sshkey\\\n --patch=\"{\\\"data\\\": { \\\"username\\\": \\\"$(echo -n edp-ci |base64 -w0)\\\" }}\" -oyaml\n
Warning
In EDP v.3.0.x, Admin Console is deprecated, and EDP interface is available only via EDP Portal.
"},{"location":"operator-guide/upgrade-edp-3.0/#related-articles","title":"Related Articles","text":"Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides the details on the EDP upgrade to v3.1. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.13.2/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.13.4/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\n
To upgrade EDP to the v3.1, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.1.0\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.1.0 --dry-run
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides the details on the EDP upgrade to v3.2.2. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_cdstagedeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_codebasebranches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_codebaseimagestreams.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_gittags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_imagestreamtags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_jiraissuemetadatas.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_jiraservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_cdstagejenkinsdeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsagents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsauthorizationrolemappings.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsauthorizationroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsfolders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsjobbuildruns.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsjobs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsscripts.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsserviceaccounts.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinssharedlibraries.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-component-operator/v0.13.0/deploy-templates/crds/v1.edp.epam.com_edpcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/v2.14.1/deploy-templates/crds/v2.edp.epam.com_cdpipelines.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/v2.14.1/deploy-templates/crds/v2.edp.epam.com_stages.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/v2.14.1/deploy-templates/crds/v2.edp.epam.com_nexuses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/v2.14.1/deploy-templates/crds/v2.edp.epam.com_nexususers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_sonargroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_sonarpermissiontemplates.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_sonars.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritgroupmembers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritmergerequests.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritprojectaccesses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritprojects.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritreplicationconfigs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/v2.13.0/deploy-templates/crds/v2.edp.epam.com_perfdatasourcegitlabs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/v2.13.0/deploy-templates/crds/v2.edp.epam.com_perfdatasourcejenkinses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/v2.13.0/deploy-templates/crds/v2.edp.epam.com_perfdatasourcesonars.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/v2.13.0/deploy-templates/crds/v2.edp.epam.com_perfservers.yaml\n
Generate a cookie-secret for proxy with the following command:
nexus_proxy_cookie_secret=$(openssl rand -base64 32 | head -c 32)\n
Create nexus-proxy-cookie-secret
in the namespace: kubectl -n <edp-project> create secret generic nexus-proxy-cookie-secret \\\n --from-literal=cookie-secret=${nexus_proxy_cookie_secret}\n
EDP 3.2.2 features OIDC configuration for EDP Portal. If this parameter is required, create keycloak-client-headlamp-secret
as described in this article:
kubectl -n <edp-project> create secret generic keycloak-client-edp-portal-secret \\\n --from-literal=clientSecret=<keycloak_client_secret_key>\n
Delete the following resources:
kubectl -n <edp-project> delete KeycloakClient nexus\nkubectl -n <edp-project> delete EDPComponent nexus\nkubectl -n <edp-project> delete Ingress nexus\nkubectl -n <edp-project> delete deployment edp-tekton-dashboard\n
EDP release 3.2.2 uses the default cluster storageClass and we must check previous storageClass parameters. Align , if required, the storageClassName
in EDP values.yaml
to the same that were used by EDP PVC. For example:
edp-tekton:\n buildTool:\n go:\n cache:\n persistentVolume:\n # -- Specifies storageClass type. If not specified, a default storageClass for go-cache volume is used\n storageClass: ebs-sc\n\njenkins-operator:\n enabled: true\n jenkins:\n storage:\n # -- Storageclass for Jenkins data volume\n class: gp2\n\nsonar-operator:\n sonar:\n storage:\n data:\n # -- Storageclass for Sonar data volume\n class: gp2\n database:\n # -- Storageclass for database data volume\n class: gp2\n\ngerrit-operator:\n gerrit:\n storage:\n # -- Storageclass for Gerrit data volume\n class: gp2\n\nnexus-operator:\n nexus:\n storage:\n # -- Storageclass for Nexus data volume\n class: gp2\n
To upgrade EDP to the v3.2.2, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.2.2\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.2.2 --dry-run
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
Note
We currently disabled cache volumes for go and npm in the EDP 3.3 release.
This section provides the details on the EDP upgrade to v3.3.0. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.16.0/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\n
If you use Gerrit VCS, delete the corresponding resource due to changes in annotations:
kubectl -n edp delete EDPComponent gerrit\n
The deployment will create a new EDPComponent called gerrit
instead. To upgrade EDP to the v3.3.0, run the following command:
helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.3.0\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the --dry-run
tag: helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.3.0 --dry-run
In EDP v3.3.0, a new feature was introduced allowing manual pipeline re-triggering by sending a comment with /recheck
. To enable the re-trigger feature for applications that were added before the upgrade, please proceed with the following:
4.1 For Gerrit VCS, add the following event to the webhooks.config
configuration file in the All-Projects
repository:
[remote \"commentadded\"]\n url = http://el-gerrit-listener:8080\n event = comment-added\n
4.2 For GitHub VCS, check the Issue comments
permission for each webhook in every application added before the EDP upgrade to 3.3.0.
4.3 For GitLab VCS, check the Comments
permission for each webhook in every application added before the EDP upgrade to 3.3.0.
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
Note
Pay attention that the following components: perf-operator
, edp-admin-console
, edp-admin-console-operator
, and edp-jenkins-operator
are deprecated and should be additionally migrated in order to avoid their deletion. For migration details, please refer to the Migrate CI Pipelines From Jenkins to Tekton instruction.
This section provides the details on the EDP upgrade to v3.4.1. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_cdpipelines.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_stages.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_clusterkeycloakrealms.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_clusterkeycloaks.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakauthflows.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakclients.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakclientscopes.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmidentityproviders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmrolebatches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealms.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmusers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloaks.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_templates.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_codebasebranches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_codebaseimagestreams.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_jiraservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.16.0/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\n
Remove deprecated components:
View: values.yaml
perf-operator:\n enabled: false\nadmin-console-operator:\n enabled: false\njenkins-operator:\n enabled: false\n
Since the values.yaml file structure has been modified, move the dockerRegistry subsection to the global section:
The dockerRegistry value has been moved to the global section:
global:\n dockerRegistry:\n # -- Define Image Registry that will to be used in Pipelines. Can be ecr (default), harbor\n type: \"ecr\"\n # -- Docker Registry endpoint\n url: \"<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com\"\n
(Optional) To integrate EDP with Jira, rename the default values from epam-jira-user
to jira-user
for a secret name. In case Jira is already integrated, it will continue working.
codebase-operator:\n jira:\n credentialName: \"jira-user\"\n
(Optional) To switch to the Harbor registry, change the secret format for the external secret from kaniko-docker-config v3.3.0 to kaniko-docker-config v3.4.1:
View: old format \"kaniko-docker-config\": {\"secret-string\"} //base64 format\n
View: new format \"kaniko-docker-config\": {\n \"auths\" : {\n \"registry.com\" :\n {\"username\":\"<registry-username>\",\"password\":\"<registry-password>\",\"auth\":\"secret-string\"}\n }\n}\n
To upgrade EDP to the v3.4.1, run the following command:
helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.4.1\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the --dry-run
tag: helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.4.1 --dry-run
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides detailed instructions for upgrading EPAM Delivery Platform to version 3.5.3. Follow the steps and requirements outlined below:
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.19.0/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\n
Danger
Codebase-operator v2.19.0 is not compatible with the previous versions. Please become familiar with the breaking change in Git Server Custom Resource Definition.
Familiarize yourself with the updated file structure of the values.yaml file and adjust your values.yaml file accordingly:
By default, the deployment of sub components such as edp-sonar-operator
, edp-nexus-operator
, edp-gerrit-operator
, and keycloak-operator
, have been disabled. Set them back to true
in case they are needed or manually deploy external tools, such as SonarQube, Nexus, Gerrit and integrate them with the EPAM Delivery Platform.
The default Git provider has been changed from Gerrit to GitHub:
Old format:
global:\n gitProvider: gerrit\n gerritSSHPort: \"22\"\n
New format:
global:\n gitProvider: github\n #gerritSSHPort: \"22\"\n
The sonarUrl and nexusUrl parameters have been deprecated. All the URLs from external components are stored in integration secrets:
global:\n # -- Optional parameter. Link to use custom sonarqube. Format: http://<service-name>.<sonarqube-namespace>:9000 or http://<ip-address>:9000\n sonarUrl: \"\"\n # -- Optional parameter. Link to use custom nexus. Format: http://<service-name>.<nexus-namespace>:8081 or http://<ip-address>:<port>\n nexusUrl: \"\"\n
Keycloak integration has been moved from the global section to the sso section. Update the parameters accordingly:
Old format:
global:\n # -- Keycloak URL\n keycloakUrl: https://keycloak.example.com\n # -- Administrators of your tenant\n admins:\n - \"stub_user_one@example.com\"\n # -- Developers of your tenant\n developers:\n - \"stub_user_one@example.com\"\n - \"stub_user_two@example.com\"\n
New format:
sso:\n enabled: true\n # -- Keycloak URL\n keycloakUrl: https://keycloak.example.com\n # -- Administrators of your tenant\n admins:\n - \"stub_user_one@example.com\"\n # -- Developers of your tenant\n developers:\n - \"stub_user_one@example.com\"\n - \"stub_user_two@example.com\"\n
(Optional) The default secret name for Jira integration has been changed from jira-user
to ci-jira
. Please adjust the secret name in the parameters accordingly:
codebase-operator:\n jira:\n credentialName: \"ci-jira\"\n
The secret naming and format have been refactored. Below are patterns of the changes for various components:
SonarQubeNexusDependency-TrackDefectDojoJiraGitLabGitHubOld format:
\"sonar-ciuser-token\": {\n \"username\": \"xxxxx\",\n \"secret\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"\n }\n
New format: \"ci-sonarqube\": {\n \"token\": \"xxxxxxxxxxxxxxxxxxxxxxx\",\n \"url\":\"https://sonar.example.com\"\n }\n
Old format:
\"nexus-ci-user\": {\n \"username\": \"xxxxx\",\n \"password\": \"xxxxxxxxxxxxxxxxxx\"\n }\n
New format:
\"ci-nexus\": {\n \"username\": \"xxxxx\",\n \"password\": \"xxxxx\",\n \"url\": \"http://nexus.example.com\"\n }\n
Old format:
\"ci-dependency-track\": {\n \"token\": \"xxxxxxxxxxxxxxxxxx\"\n }\n
New format:
\"ci-dependency-track\": {\n \"token\": \"xxxxxxxxxxxxxxxxxx\",\n \"url\": \"http://dependency-track.example.com\"}\n
Old format:
\"defectdojo-ciuser-token\": {\n \"token\": \"xxxxxxxxxxxxxxxxxx\"\n \"url\": \"http://defectdojo.example.com\"\n }\n
New format:
\"ci-defectdojo\": {\n \"token\": \"xxxxxxxxxxxxxxxxxx\",\n \"url\": \"http://defectdojo.example.com\"\n }\n
Old format:
\"jira-user\": {\n \"username\": \"xxxxx\",\n \"password\": \"xxxxx\"\n }\n
New format:
\"ci-jira\": {\n \"username\": \"xxxxx\",\n \"password\": \"xxxxx\"\n }\n
Old format:
\"gitlab\": {\n \"id_rsa\": \"xxxxxxxxxxxxxx\",\n \"token\": \"xxxxxxxxxxxxxx\",\n \"secretString\": \"xxxxxxxxxxxxxx\"\n }\n
New format:
\"ci-gitlab\": {\n \"id_rsa\": \"xxxxxxxxxxxxxx\",\n \"token\": \"xxxxxxxxxxxxxx\",\n \"secretString\": \"xxxxxxxxxxxxxx\"\n }\n
Old format:
\"github\": {\n \"id_rsa\": \"xxxxxxxxxxxxxx\",\n \"token\": \"xxxxxxxxxxxxxx\",\n \"secretString\": \"xxxxxxxxxxxxxx\"\n }\n
New format:
\"ci-github\": {\n \"id_rsa\": \"xxxxxxxxxxxxxx\",\n \"token\": \"xxxxxxxxxxxxxx\",\n \"secretString\": \"xxxxxxxxxxxxxx\"\n }\n
The tables below illustrate the difference between the old and new format:
Old format
Secret Name Username Password Token Secret URL jira-user * * nexus-ci.user * * sonar-ciuser-token * * defectdojo-ciuser-token * * ci-dependency-track *New format
Secret Name Username Password Token URL ci-jira * * ci-nexus * * * ci-sonarqube * * ci-defectdojo * * ci-dependency-track * *To upgrade EDP to the v3.5.3, run the following command:
helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.5.3\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the --dry-run
tag: helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.5.3 --dry-run
Important
We suggest backing up the EDP environment before starting the upgrade procedure.
This section provides detailed instructions for upgrading the EPAM Delivery Platform to version 3.6.0. Follow the steps and requirements outlined below:
Update Custom Resource Definitions (CRDs). Run the following command to apply all the necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.20.0/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\n
Familiarize yourself with the updated structure of the values.yaml file and adjust it accordingly:
2.1 A new parameter called space has been added to the DockerRegistry
section. It is designed to form URLs in CodebaseImageStreams. This parameter is set the same as the EPAM Delivery Platform
namespace name. Ensure you define the space
parameter prior to the update.
Warning
This parameter is a significant change and must be set before the update.
global:\n dockerRegistry:\n type: \"harbor\"\n url: \"registry.example.com\"\n space: \"edp\"\n
2.2 Subcomponents, such as sonar-operator, nexus-operator, and keycloak-operator, have been removed since dependencies are no longer provisioned by the edp-install Helm Chart. To install and integrate shared components with EDP, please use the edp-cluster-add-ons approach or refer to the SonarQube Integration and Nexus Sonatype Integration documentation pages.
2.3 The Argo CD integration dependency has been deleted as now we implement it using edp-cluster-add-ons approach. To install and integrate Argo CD as a shared component, use the edp-cluster-add-ons approach.
2.4 The handling of secrets for stages namespaces in the cd-pipeline-operator has been updated. The parameter manageSecrets
has been replaced with secretManager
. If your environment previously utilized this parameter, manually modify it from manageSecrets: true
to secretManager: own
. Otherwise, set it to secretManager: none
:
cd-pipeline-operator:\n # -- flag that indicates whether the operator should manage secrets for stages;\n # own - just copy secrets;\n # eso - secrete will be managed by External Secrets Operator(operator should be installed in the cluster);\n # none - not enable secrets management logic;\n secretManager: none\n
To upgrade EDP to the v3.6.0, run the following command:
helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.6.0\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the --dry-run
tag: helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.6.0 --dry-run
Starting from Keycloak v.18.x.x, the Keycloak server has been moved from the Wildfly (JBoss) Application Server to Quarkus framework and is called Keycloak.X.
There are two ways to upgrade Keycloak v.17.0.x-legacy to v.19.0.x on Kubernetes, please perform the steps described in the Prerequisites section of this tutorial, and then select a suitable upgrade strategy for your environment:
Before upgrading Keycloak, please perform the steps below:
Create a backup/snapshot of the Keycloak database volume. Locate the AWS volumeID
and then create its snapshot on AWS:
Find the PVC
name attached to the Postgres pod. It can be similar to data-keycloak-postgresql-0
if the Postgres StatefulSet
name is keycloak-postgresql
:
kubectl get pods keycloak-postgresql-0 -n security -o jsonpath='{.spec.volumes[*].persistentVolumeClaim.claimName}{\"\\n\"}'\n
Locate the PV
volumeName
in the data-keycloak-postgresql-0
Persistent Volume Claim:
kubectl get pvc data-keycloak-postgresql-0 -n security -o jsonpath='{.spec.volumeName}{\"\\n\"}'\n
Get volumeID
in the Persistent Volume:
kubectl get pv ${pv_name} -n security -o jsonpath='{.spec.awsElasticBlockStore.volumeID}{\"\\n\"}'\n
Add two additional keys: password
and postgres-password
, to the keycloak-postgresql
secret in the Keycloak namespace.
Note
password
key must have the same value as the postgresql-password
key.postgres-password
key must have the same value as the postgresql-postgres-password
key.The latest chart for Keycloak.X does not have an option to override Postgres password and admin password keys in the secret, and it uses the Postgres defaults, therefore, a new secret scheme must be implemented:
kubectl -n security edit secret keycloak-postgresql\n
data:\n postgresql-password: XXXXXX\n postgresql-postgres-password: YYYYYY\n password: XXXXXX\n postgres-password: YYYYYY\n
Save Keycloak StatefulSet
names, for example, keycloak
and keycloak-postgresql
. These names will be used in the new Helm deployments:
$ kubectl get statefulset -n security\nNAME READY AGE\nkeycloak 1/1 18h\nkeycloak-postgresql 1/1 18h\n
To upgrade Keycloak by upgrading Postgres Database to a minor release v.11.17, perform the steps described in the Prerequisites section of this tutorial, and then perform the following steps:
"},{"location":"operator-guide/upgrade-keycloak-19.0/#delete-keycloak-resources","title":"Delete Keycloak Resources","text":"Delete Keycloak
and Prostgres
StatefulSets
:
kubectl delete statefulset keycloak keycloak-postgresql -n security\n
Delete the Keycloak Ingress
object, to prevent hostname duplication issues:
kubectl delete ingress keycloak -n security\n
Make sure the Keycloak chart repository is added:
helm repo add codecentric https://codecentric.github.io/helm-charts\nhelm repo update\n
Create values for Keycloak:
Note
Since the Keycloak.X release, Keycloak and Postgres database charts are separated. Upgrade Keycloak, and then install the Postgres database.
Note
nameOverride: \"keycloak\"
sets the name of the Keycloak pod. It must be the same Keycloak name as in the previous StatefulSet
.hostname: keycloak-postgresql
is the hostname of the pod with the Postgres database that is the same as Postgres StatefulSet name, for example, keycloak-postgresql
.\"/opt/keycloak/bin/kc.sh start --auto-build\"
was used in the legacy Keycloak version. However, it is no longer required in the new Keycloak version since it is deprecated and used by default.Optionally, use the following command for applying the old Keycloak theme:
bin/kc.sh start --features-disabled=admin2\n
nameOverride: \"keycloak\"\n\nreplicas: 1\n\n# Deploy the latest verion\nimage:\n tag: \"19.0.1\"\n\n# start: create OpenShift realm which is required by EDP\nextraInitContainers: |\n - name: realm-provider\n image: busybox\n imagePullPolicy: IfNotPresent\n command:\n - sh\n args:\n - -c\n - |\n echo '{\"realm\": \"openshift\",\"enabled\": true}' > /opt/keycloak/data/import/openshift.json\n volumeMounts:\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumeMounts: |\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumes: |\n - name: realm\n emptyDir: {}\n\ncommand:\n - \"/opt/keycloak/bin/kc.sh\"\n - \"--verbose\"\n - \"start\"\n - \"--http-enabled=true\"\n - \"--http-port=8080\"\n - \"--hostname-strict=false\"\n - \"--hostname-strict-https=false\"\n - \"--spi-events-listener-jboss-logging-success-level=info\"\n - \"--spi-events-listener-jboss-logging-error-level=warn\"\n - \"--import-realm\"\n\nextraEnv: |\n - name: KC_PROXY\n value: \"passthrough\"\n - name: KEYCLOAK_ADMIN\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: username\n - name: KEYCLOAK_ADMIN_PASSWORD\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: password\n - name: JAVA_OPTS_APPEND\n value: >-\n -XX:+UseContainerSupport\n -XX:MaxRAMPercentage=50.0\n -Djava.awt.headless=true\n -Djgroups.dns.query={{ include \"keycloak.fullname\" . }}-headless\n\n# This block should be uncommented if you install Keycloak on Kubernetes\ningress:\n enabled: true\n annotations:\n kubernetes.io/ingress.class: nginx\n ingress.kubernetes.io/affinity: cookie\n rules:\n - host: keycloak.<ROOT_DOMAIN>\n paths:\n - path: '{{ tpl .Values.http.relativePath $ | trimSuffix \"/\" }}/'\n pathType: Prefix\n\n# This block should be uncommented if you set Keycloak to OpenShift and change the host field\n# route:\n# enabled: false\n# # Path for the Route\n# path: '/'\n# # Host name for the Route\n# host: \"keycloak.<ROOT_DOMAIN>\"\n# # TLS configuration\n# tls:\n# enabled: true\n\nresources:\n limits:\n memory: \"2048Mi\"\n requests:\n cpu: \"50m\"\n memory: \"512Mi\"\n\n# Check database readiness at startup\ndbchecker:\n enabled: true\n\ndatabase:\n vendor: postgres\n existingSecret: keycloak-postgresql\n hostname: keycloak-postgresql\n port: 5432\n username: admin\n database: keycloak\n
Upgrade the Keycloak Helm chart:
Note
helm upgrade keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security\n
Note
If there are error messages when upgrading via Helm, make sure that StatefulSets
are removed. If they are removed and the error still persists, try to add the --force
flag to the Helm command:
helm upgrade keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security --force\n
Add Bitnami chart repository and update Helm repos:
helm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n
Create values for Postgres:
Note
fullnameOverride: \"keycloak-postgresql\"
sets the name of the Postgres StatefulSet. It must be the same as in the previous StatefulSet
.fullnameOverride: \"keycloak-postgresql\"\n\n# PostgreSQL read only replica parameters\nreadReplicas:\n # Number of PostgreSQL read only replicas\n replicaCount: 1\n\nglobal:\n postgresql:\n auth:\n username: admin\n existingSecret: keycloak-postgresql\n secretKeys:\n adminPasswordKey: postgres-password\n userPasswordKey: password\n database: keycloak\n\nimage:\n registry: docker.io\n repository: bitnami/postgresql\n tag: 11.17.0-debian-11-r3\n\nauth:\n existingSecret: keycloak-postgresql\n secretKeys:\n adminPasswordKey: postgres-password\n userPasswordKey: password\n\nprimary:\n persistence:\n enabled: true\n size: 3Gi\n # If the StorageClass with reclaimPolicy: Retain is used, install an additional StorageClass before installing PostgreSQL\n # (the code is given below).\n # If the default StorageClass will be used - change \"gp2-retain\" to \"gp2\"\n storageClass: \"gp2-retain\"\n
Install the Postgres database chart:
Note
Change the namespace and the values file name if required.
helm install postgresql bitnami/postgresql \\\n--version 11.7.6 \\\n--values postgres-values.yaml \\\n--namespace security\n
Log in to Keycloak and check that everything works as expected.
Optionally, run the vacuumdb application on the database, to recover space occupied by \"dead tuples\" in the tables, analyze the contents of database tables, and collect statistics for PostgreSQL query engine to improve performance:
PGPASSWORD=\"${postgresql_postgres-password}\" vacuumdb --analyze --verbose -d keycloak -U postgres\n
For all databases, run the following command: PGPASSWORD=\"${postgresql_postgres-password}\" vacuumdb --analyze --verbose --all -U postgres\n
"},{"location":"operator-guide/upgrade-keycloak-19.0/#migrate-postgres-database-from-postgres-v11x-to-v145","title":"Migrate Postgres Database From Postgres v.11.x to v.14.5","text":"Info
There is a Postgres database migration script at the end of this tutorial. Please read the section below before using the script.
To upgrade Keycloak by migrating Postgres database from Postgres v.11.x to v.14.5, perform the steps described in the Prerequisites section of this tutorial, and then perform the following steps:
"},{"location":"operator-guide/upgrade-keycloak-19.0/#export-postgres-databases","title":"Export Postgres Databases","text":"Log in to the current Keycloak Postgres pod and create a logical backup of all roles and databases using the pg_dumpall application. If there is no access to the Postgres Superuser, backup the Keycloak database with the pg_dump application:
Note
postgresql-postgres-password
is for the postgres
Superuser and postgresql-password
is for admin
user. The admin
user is indicated by default in the Postgres Helm chart. The admin
user may not have enough permissions to dump all Postgres databases and roles, so the preferred option for exporting all objects is using the pg_dumpall
tool with the postgres
Superuser.PGPASSWORD
variable is not specified before using the pg_dumpall
tool, you will be prompted to enter a password for each database during the export.-l keycloak
parameter is specified, pg_dumpall
will connect to the keycloak
database for dumping global objects and discovering what other databases should be dumped. By default, pg_dumpall
will try to connect to postgres
or template1
databases. This parameter is optional.pg_dumpall --clean
option adds SQL commands to the dumped file for dropping databases before recreating them during import, as well as DROP
commands for roles and tablespaces (pg_dump
also has this option). If the --clean
parameter is specified, connect to the postgres
database initially during import via psql
. The psql
script will attempt to drop other databases immediately, and that will fail for the database you are connected to. This flag is optional, and it is not included into this tutorial.PGPASSWORD=\"${postgresql_postgres-password}\" pg_dumpall -h localhost -p 5432 -U postgres -l keycloak > /tmp/keycloak_wildfly_db_dump.sql\n
Note
If there is no working password for the postgres
Superuser, try the admin
user using the pg_dump tool to export the keycloak
database without global roles:
PGPASSWORD=\"${postgresql_password}\" pg_dump -h localhost -p 5432 -U admin -d keycloak > /tmp/keycloak_wildfly_db_dump.sql\n
Info
Double-check that the contents of the dumped file is not empty. It usually contains more than 4000 lines.
Copy the file with the database dump to a local machine. Since tar
may not be present in the pod and kubectl cp
will not work without tar
, use the following command:
kubectl exec -n security ${postgresql_pod} -- cat /tmp/keycloak_wildfly_db_dump.sql > keycloak_wildfly_db_dump.sql\n
Note
Please find below the alternative commands for exporting the database to the local machine without copying the file to a pod for Postgres and admin users:
kubectl exec -n security ${postgresql_pod} \"--\" sh -c \"PGPASSWORD='\"${postgresql_postgres-password}\"' pg_dumpall -h localhost -p 5432 -U postgres\" > keycloak_wildfly_db_dump.sql\nkubectl exec -n security ${postgresql_pod} \"--\" sh -c \"PGPASSWORD='\"${postgresql_password}\"' pg_dump -h localhost -p 5432 -U admin -d keycloak\" > keycloak_wildfly_db_dump.sql\n
Delete the dumped file from the pod for security reasons:
kubectl exec -n security ${postgresql_pod} \"--\" sh -c \"rm /tmp/keycloak_wildfly_db_dump.sql\"\n
Delete all previous Keycloak resources along with the Postgres database and keycloak StatefulSets
, Ingress
, and custom resources via Helm, or via the tool used for their deployment.
helm list -n security\nhelm delete keycloak -n security\n
Warning
Don't delete the whole namespace. Keep the keycloak-postgresql
and keycloak-admin-creds
secrets.
Delete the volume in AWS, from which a snapshot has been created. Then delete the PVC:
kubectl delete pvc data-keycloak-postgresql-0 -n security\n
Add Bitnami chart repository and update Helm repos:
helm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n
Create Postgres values:
Note
fullnameOverride: \"keycloak-postgresql\"
sets the name of the Postgres StatefulSet. It must be same as in the previous StatefulSet
.
nameOverride: \"keycloak-postgresql\"\n\n# PostgreSQL read only replica parameters\nreadReplicas:\n # Number of PostgreSQL read only replicas\n replicaCount: 1\n\nglobal:\n postgresql:\n auth:\n username: admin\n existingSecret: keycloak-postgresql\n secretKeys:\n adminPasswordKey: postgres-password\n userPasswordKey: password\n database: keycloak\n\nauth:\n existingSecret: keycloak-postgresql\n secretKeys:\n adminPasswordKey: postgres-password\n userPasswordKey: password\n\nprimary:\n persistence:\n enabled: true\n size: 3Gi\n # If the StorageClass with reclaimPolicy: Retain is used, install an additional StorageClass before installing PostgreSQL\n # (the code is given below).\n # If the default StorageClass will be used - change \"gp2-retain\" to \"gp2\"\n storageClass: \"gp2-retain\"\n
Install the Postgres database:
Note
Change the namespace and the values file name if required.
helm install postgresql bitnami/postgresql \\\n--version 11.7.6 \\\n--values postgres-values.yaml \\\n--namespace security\n
Wait for the database to be ready.
Upload the database dump to the new Keycloak Postgres pod:
cat keycloak_wildfly_db_dump.sql | kubectl exec -i -n security ${postgresql_pod} \"--\" sh -c \"cat > /tmp/keycloak_wildfly_db_dump.sql\"\n
Warning
Database import must be done before deploying Keycloak, because Keycloak will write its own data to the database during the start, and the import will partially fail. If that happened, scale down the keycloak StatefulSet
, and try to drop the Keycloak database in the Postgres pod:
dropdb -i -e keycloak -p 5432 -h localhost -U postgres\n
If there still are some conflicting objects like roles, drop them via the DROP ROLE command.
If the previous steps do not help, downscale the Keycloak and Postgres StatefulSets
and delete the attached PVC
(save the volumeID
before removing), and delete the volume on AWS if using gp2-retain
. In case of using gp2
, the volume will be deleted automatically after removing PVC. After that, redeploy the Postgres database, so that the new PVC
is automatically created.
Import the SQL dump file to the Postgres database cluster:
Info
Since the databases were exported in the sql
format, the psql tool will be used to restore (reload) them. pg_restore does not support this plain-text format.
If the entire Postgres database cluster was migrated with the postgres
Superuser using pg_dumpall
, use the import command without indicating the database:
psql -U postgres -f /tmp/keycloak_wildfly_db_dump.sql\n
If the database was migrated with the admin
user using pg_dump
, the postgres
Superuser still can be used to restore it, but, in this case, a database must be indicated:
Warning
If the database name was not indicated during the import for the file dumped with pg_dump
, the psql
tool will import this database to a default Postgres database called postgres
.
psql -U postgres -d keycloak -f /tmp/keycloak_wildfly_db_dump.sql\n
If the postgres
Superuser is not accessible in the Postgres pod, run the command under the admin
or any other user that has the database permissions. In this case, indicate the database as well:
psql -U admin -d keycloak -f /tmp/keycloak_wildfly_db_dump.sql\n
After a successful import, delete the dump file from the pod for security reasons:
kubectl exec -n security ${postgresql_pod} \"--\" sh -c \"rm /tmp/keycloak_wildfly_db_dump.sql\"\n
Note
Please find below the alternative commands for importing the database from the local machine to the pod without storing the backup on a pod for postgres
or admin
users:
cat \"keycloak_wildfly_db_dump.sql\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" sh -c \"cat | PGPASSWORD='\"${postgresql_superuser_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\"\"\ncat \"keycloak_wildfly_db_dump.sql\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" sh -c \"cat | PGPASSWORD='\"${postgresql_superuser_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\ncat \"keycloak_wildfly_db_dump.sql\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" sh -c \"cat | PGPASSWORD='\"${postgresql_admin_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\n
Make sure the Keycloak chart repository is added:
helm repo add codecentric https://codecentric.github.io/helm-charts\nhelm repo update\n
Create Keycloak values:
Note
nameOverride: \"keycloak\"
sets the name of the Keycloak pod. It must be the same Keycloak name as in the previous StatefulSet
.hostname: keycloak-postgresql
is the hostname of the pod with the Postgres database that is the same as Postgres StatefulSet name, for example, keycloak-postgresql
.\"/opt/keycloak/bin/kc.sh start --auto-build\"
was used in the legacy Keycloak version. However, it is no longer required in the new Keycloak version since it is deprecated and used by default.Optionally, use the following command for applying the old Keycloak theme:
bin/kc.sh start --features-disabled=admin2\n
Info
Automatic database migration will start after the Keycloak installation.
View: keycloak-values.yamlnameOverride: \"keycloak\"\n\nreplicas: 1\n\n# Deploy the latest verion\nimage:\n tag: \"19.0.1\"\n\n# start: create OpenShift realm which is required by EDP\nextraInitContainers: |\n - name: realm-provider\n image: busybox\n imagePullPolicy: IfNotPresent\n command:\n - sh\n args:\n - -c\n - |\n echo '{\"realm\": \"openshift\",\"enabled\": true}' > /opt/keycloak/data/import/openshift.json\n volumeMounts:\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumeMounts: |\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumes: |\n - name: realm\n emptyDir: {}\n\ncommand:\n - \"/opt/keycloak/bin/kc.sh\"\n - \"--verbose\"\n - \"start\"\n - \"--http-enabled=true\"\n - \"--http-port=8080\"\n - \"--hostname-strict=false\"\n - \"--hostname-strict-https=false\"\n - \"--spi-events-listener-jboss-logging-success-level=info\"\n - \"--spi-events-listener-jboss-logging-error-level=warn\"\n - \"--import-realm\"\n\nextraEnv: |\n - name: KC_PROXY\n value: \"passthrough\"\n - name: KEYCLOAK_ADMIN\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: username\n - name: KEYCLOAK_ADMIN_PASSWORD\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: password\n - name: JAVA_OPTS_APPEND\n value: >-\n -XX:+UseContainerSupport\n -XX:MaxRAMPercentage=50.0\n -Djava.awt.headless=true\n -Djgroups.dns.query={{ include \"keycloak.fullname\" . }}-headless\n\n# This block should be uncommented if you install Keycloak on Kubernetes\ningress:\n enabled: true\n annotations:\n kubernetes.io/ingress.class: nginx\n ingress.kubernetes.io/affinity: cookie\n rules:\n - host: keycloak.<ROOT_DOMAIN>\n paths:\n - path: '{{ tpl .Values.http.relativePath $ | trimSuffix \"/\" }}/'\n pathType: Prefix\n\n# This block should be uncommented if you set Keycloak to OpenShift and change the host field\n# route:\n# enabled: false\n# # Path for the Route\n# path: '/'\n# # Host name for the Route\n# host: \"keycloak.<ROOT_DOMAIN>\"\n# # TLS configuration\n# tls:\n# enabled: true\n\nresources:\n limits:\n memory: \"2048Mi\"\n requests:\n cpu: \"50m\"\n memory: \"512Mi\"\n\n# Check database readiness at startup\ndbchecker:\n enabled: true\n\ndatabase:\n vendor: postgres\n existingSecret: keycloak-postgresql\n hostname: keycloak-postgresql\n port: 5432\n username: admin\n database: keycloak\n
Deploy Keycloak:
Note
Change the namespace and the values file name if required.
helm install keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security\n
Log in to Keycloak and check if everything has been imported correctly.
Optionally, run the vacuumdb application on the database, to analyze the contents of database tables and collect statistics for the Postgres query optimizer:
PGPASSWORD=\"${postgresql_postgres-password}\" vacuumdb --analyze --verbose -d keycloak -U postgres\n
For all databases, run the following command: PGPASSWORD=\"${postgresql_postgres-password}\" vacuumdb --analyze --verbose --all -U postgres\n
"},{"location":"operator-guide/upgrade-keycloak-19.0/#postgres-database-migration-script","title":"Postgres Database Migration Script","text":"Info
Please read the Migrate Postgres Database From Postgres v.11.x to v.14.5 section of this tutorial before using the script.
Note
kubectl
tool is required for using this script.pg_dump
, pg_dumpall
, psql
, and vacuumdb
commands under the hood.The following script can be used for exporting and importing Postgres databases as well as optimizing them with the vacuumdb application. Please examine the code and make the adjustments if required.
By default, the following command exports Keycloak Postgres databases from a Kubernetes pod to a local machine:
./script.sh\n
After running the command, please follow the prompt.
./script.sh path-to/db_dump.sql\n
-h
flag prints help, and -c|-v
runs the vacuumdb
garbage collector and analyzer.#!/bin/bash\n\n# set -x\n\ndb_migration_help(){\n echo \"Keycloak Postgres database migration\"\n echo\n echo \"Usage:\"\n echo \"------------------------------------------\"\n echo \"Export Keycloak Postgres database from pod\"\n echo \"Run without parameters:\"\n echo \" $0\"\n echo \"------------------------------------------\"\n echo \"Import Keycloak Postgres database to pod\"\n echo \"Pass filename to script:\"\n echo \" $0 path/to/db_dump.sql\"\n echo \"------------------------------------------\"\n echo \"Additional options: \"\n echo \" $0 [OPTIONS...]\"\n echo \"Options:\"\n echo \"h Print Help.\"\n echo \"c|v Run garbage collector and analyzer.\"\n}\n\nkeycloak_ns(){\n printf '%s\\n' 'Enter keycloak namespace: '\n read -r keycloak_namespace\n\n if [ -z \"${keycloak_namespace}\" ]; then\n echo \"Don't skip namespace\"\n exit 1\n fi\n}\n\npostgres_pod(){\n printf '%s\\n' 'Enter postgres pod name: '\n read -r postgres_pod_name\n\n if [ -z \"${postgres_pod_name}\" ]; then\n echo \"Don't skip pod name\"\n exit 1\n fi\n}\n\npostgres_user(){\n printf '%s\\n' 'Enter postgres username: '\n printf '%s' \"Skip to use [postgres] superuser: \"\n read -r postgres_username\n\n if [ -z \"${postgres_username}\" ]; then\n postgres_username='postgres'\n fi\n}\n\npgdb_host_info(){\n database_name='keycloak'\n db_host='localhost'\n db_port='5432'\n}\n\npostgresql_admin_pass(){\n postgresql_password='POSTGRES_PASSWORD'\n postgresql_admin_password=\"$(kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"printenv ${postgresql_password}\")\"\n}\n\npostgresql_su_pass(){\n postgresql_postgres_password='POSTGRES_POSTGRES_PASSWORD'\n postgresql_superuser_password=\"$(kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"printenv ${postgresql_postgres_password}\")\"\n\n if [ -z \"${postgresql_superuser_password}\" ]; then\n echo \"SuperUser password variable does not exist. Using user password instead...\"\n postgresql_admin_pass\n postgresql_superuser_password=\"${postgresql_admin_password}\"\n fi\n}\n\nkeycloak_pgdb_export(){\n current_cluster=\"$(kubectl config current-context | tr -dc '[:alnum:]-')\"\n exported_db_name=\"keycloak_db_dump_${current_cluster}_${keycloak_namespace}_${postgres_username}_$(date +\"%Y%m%d%H%M\").sql\"\n\n if [ \"${postgres_username}\" == 'postgres' ]; then\n # call a function to get a pass for postgres user\n postgresql_su_pass\n kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"PGPASSWORD='\"${postgresql_superuser_password}\"' pg_dumpall -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\"\" > \"${exported_db_name}\"\n else\n # call a function to get a pass for admin user\n postgresql_admin_pass\n kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"PGPASSWORD='\"${postgresql_admin_password}\"' pg_dump -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\" > \"${exported_db_name}\"\n fi\n\n separate_lines=\"---------------\"\n\n if [ ! -s \"${exported_db_name}\" ]; then\n rm -f \"${exported_db_name}\"\n echo \"${separate_lines}\"\n echo \"Something went wrong. The database dump file is empty and was not saved.\"\n else\n echo \"${separate_lines}\"\n grep 'Dumped' \"${exported_db_name}\" | sort -u\n echo \"Database has been exported to $(pwd)/${exported_db_name}\"\n fi\n}\n\nkeycloak_pgdb_import(){\n echo \"Preparing Import\"\n echo \"----------------\"\n\n if [ ! -f \"$1\" ]; then\n echo \"The file $1 does not exist.\"\n exit 1\n fi\n\n keycloak_ns\n postgres_pod\n postgres_user\n pgdb_host_info\n\n if [ \"${postgres_username}\" == 'postgres' ]; then\n # restore full backup with all databases and roles as superuser or a single database\n postgresql_su_pass\n if [ -n \"$(cat \"$1\" | grep 'CREATE ROLE')\" ]; then\n cat \"$1\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"cat | PGPASSWORD='\"${postgresql_superuser_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\"\"\n else\n cat \"$1\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"cat | PGPASSWORD='\"${postgresql_superuser_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\n fi\n else\n # restore a single database\n postgresql_admin_pass\n cat \"$1\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"cat | PGPASSWORD='\"${postgresql_admin_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\n fi\n}\n\nvacuum_pgdb(){\n echo \"Preparing garbage collector and analyzer\"\n echo \"----------------------------------------\"\n\n keycloak_ns\n postgres_pod\n postgres_user\n pgdb_host_info\n\n if [ \"${postgres_username}\" == 'postgres' ]; then\n postgresql_su_pass\n kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"PGPASSWORD='\"${postgresql_superuser_password}\"' vacuumdb --analyze --all -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\"\"\n else\n postgresql_admin_pass\n kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"PGPASSWORD='\"${postgresql_admin_password}\"' vacuumdb --analyze -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\n fi\n}\n\nwhile [ \"$#\" -eq 1 ]; do\n case \"$1\" in\n -h | --help)\n db_migration_help\n exit 0\n ;;\n -c | --clean | -v | --vacuum)\n vacuum_pgdb\n exit 0\n ;;\n --)\n break\n ;;\n -*)\n echo \"Invalid option '$1'. Use -h|--help to see the valid options\" >&2\n exit 1\n ;;\n *)\n keycloak_pgdb_import \"$1\"\n exit 0\n ;;\n esac\n shift\ndone\n\nif [ \"$#\" -gt 1 ]; then\n echo \"Please pass a single file to the script\"\n exit 1\nfi\n\necho \"Preparing Export\"\necho \"----------------\"\nkeycloak_ns\npostgres_pod\npostgres_user\npgdb_host_info\nkeycloak_pgdb_export\n
"},{"location":"operator-guide/upgrade-keycloak-19.0/#related-articles","title":"Related Articles","text":"The Version Control Systems (VCS) section is dedicated to delivering comprehensive information on VCS within the EPAM Delivery Platform. This section comprises detailed descriptions of all the deployment strategies, along with valuable recommendations for their optimal usage, and the list of supported VCS, facilitating seamless integration with EDP.
"},{"location":"operator-guide/vcs/#supported-vcs","title":"Supported VCS","text":"EDP can be integrated with the following Version Control Systems:
Note
So far, EDP doesn't support authorization mechanisms in the upstream GitLab.
"},{"location":"operator-guide/vcs/#vcs-deployment-strategies","title":"VCS Deployment Strategies","text":"EDP offers the following strategies to work with repositories:
Note
Under the hood, all the built-in application frameworks, build tools and frameworks are stored in our public GitHub repository.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitHub/GitLab in Jenkins or Integrate GitHub/GitLab in Tekton page. The Import project strategy is not applicable for Gerrit. Also, it is impossible to choose the Empty project field when using the Import project strategy while creating appication since it is implied that you already have a ready-to-work application in your own repository, whereas the \"Empty project\" option creates a repository but doesn't put anything in it.
Note
Make sure that IRSA is enabled and amazon-eks-pod-identity-webhook is deployed according to the Associate IAM Roles With Service Accounts documentation.
Velero AWS plugin requires access to AWS resources. Follow the steps below to create a required role:
Create AWS IAM Policy \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero_policy\":
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"ec2:DescribeVolumes\",\n \"ec2:DescribeSnapshots\",\n \"ec2:CreateTags\",\n \"ec2:CreateVolume\",\n \"ec2:CreateSnapshot\",\n \"ec2:DeleteSnapshot\"\n ],\n \"Resource\": \"*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:GetObject\",\n \"s3:DeleteObject\",\n \"s3:PutObject\",\n \"s3:AbortMultipartUpload\",\n \"s3:ListMultipartUploadParts\"\n ],\n \"Resource\": [\n \"arn:aws:s3:::velero-*/*\"\n ]\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ListBucket\"\n ],\n \"Resource\": [\n \"arn:aws:s3:::velero-*\"\n ]\n }\n ]\n}\n
Create AWS IAM Role \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero\" with trust relationships:
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER>\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"<OIDC_PROVIDER>:sub\": \"system:serviceaccount:<VELERO_NAMESPACE>:edp-velero\"\n }\n }\n }\n ]\n}\n
Attach the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero_policy\" policy to the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero\" role.
Make sure that Amazon S3 bucket with name velero-\u2039CLUSTER_NAME\u203a exists.
Provide key value eks.amazonaws.com/role-arn: \"arn:aws:iam:::role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero\" into the serviceAccount.server.annotations parameter in values.yaml during the Velero Installation.
This page contains accurate information on how to configure AWS WAF using Terraform with the aim to have a secured traffic exposure and to prevent the Host Header vulnerabilities.
"},{"location":"operator-guide/waf-tf-configuration/#prerequisites","title":"Prerequisites","text":"To follow the instruction, check the following prerequisites:
The solution includes two parts:
The WAF ACL resource is the main resource used for the configuration; The default web ACL option is Block.
Overview WAF Solution
The ACL includes three managed AWS rules that secure the exposed traffic:
AWS provides a lot of rules such as baseline and use-case specific rules, for details, please refer to the Baseline rule groups.
There is the PreventHostInjections rule that prevents the Host Header vulnerabilities. This rule includes one statement that declares that the Host Header should match Regex Pattern Set, thus only in this case it will be passed.
The Regex Pattern Set is another resource that helps to organize regexes, in fact, is a set of regexes. All regexes added to the single set are matched by the OR statement, i.e. when exposing several URLs, it is necessary to add this statement to the set and refer to it in the rule.
"},{"location":"operator-guide/waf-tf-configuration/#waf-acl-configuration","title":"WAF ACL Configuration","text":"To create the Regex Pattern Set, inspect the following code:
resource \"aws_wafv2_regex_pattern_set\" \"common\" {\n name = \"Common\"\n scope = \"REGIONAL\"\n\n regular_expression {\n regex_string = \"^.*(some-url).*((.edp-epam)+)\\\\.com$\"\n }\n\n # Add here additional regular expressions for other endpoints, they are merging with OR operator, e.g.\n\n /*\n regular_expression {\n regex_string = \"^.*(keycloak).*((.edp-epam)+)\\\\.com$\"\n }\n */\n\n tags = var.tags\n}\n
It includes 'regex_string', for example: url - some-url.edp-epam.com, In addition, it is possible to add other links to the same resource using the regular_expression element.
There is the Terraform code for the aws_wafv2_web_acl resource:
resource \"aws_wafv2_web_acl\" \"external\" {\n name = \"ExternalACL\"\n scope = \"REGIONAL\"\n\n default_action {\n block {}\n }\n\n rule {\n name = \"AWS-AWSManagedRulesCommonRuleSet\"\n priority = 1\n\n override_action {\n none {}\n }\n\n statement {\n managed_rule_group_statement {\n name = \"AWSManagedRulesCommonRuleSet\"\n vendor_name = \"AWS\"\n }\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"AWS-AWSManagedRulesCommonRuleSet\"\n sampled_requests_enabled = true\n }\n }\n\n rule {\n name = \"AWS-AWSManagedRulesLinuxRuleSet\"\n priority = 2\n\n statement {\n managed_rule_group_statement {\n name = \"AWSManagedRulesLinuxRuleSet\"\n vendor_name = \"AWS\"\n }\n }\n\n override_action {\n none {}\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"AWS-AWSManagedRulesLinuxRuleSet\"\n sampled_requests_enabled = true\n }\n }\n\n rule {\n name = \"AWS-AWSManagedRulesKnownBadInputsRuleSet\"\n priority = 3\n\n override_action {\n none {}\n }\n\n statement {\n managed_rule_group_statement {\n name = \"AWSManagedRulesKnownBadInputsRuleSet\"\n vendor_name = \"AWS\"\n }\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"AWS-AWSManagedRulesKnownBadInputsRuleSet\"\n sampled_requests_enabled = true\n }\n }\n\n rule {\n name = \"PreventHostInjections\"\n priority = 0\n\n statement {\n regex_pattern_set_reference_statement {\n arn = aws_wafv2_regex_pattern_set.common.arn\n\n field_to_match {\n single_header {\n name = \"host\"\n }\n }\n\n text_transformation {\n priority = 0\n type = \"NONE\"\n }\n }\n }\n\n action {\n allow {}\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"PreventHostInjections\"\n sampled_requests_enabled = true\n }\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"ExternalACL\"\n sampled_requests_enabled = true\n }\n\n tags = var.tags\n}\n
As mentioned previously, ACL includes three managed AWS rules (group rules), for visibility, enabling sampling, and CloudWatch in the config. The 'PreventHostInjections' custom rule refers to the created pattern set and declares the Host Header, as well as sets the 'Action' if matched to 'Allow'.
"},{"location":"operator-guide/waf-tf-configuration/#associate-aws-resource","title":"Associate AWS Resource","text":"To have the created ACL working, it is necessary to associate an AWS resource with it, in this case, it is AWS ALB:
resource \"aws_wafv2_web_acl_association\" \"waf_alb\" {\n resource_arn = aws_lb.<aws_alb_for_waf>.arn\n web_acl_arn = aws_wafv2_web_acl.external.arn\n}\n
Note
AWS ALB can be created in the scope of this Terraform code or created previously. When creating ALB to expose links, the ALB should have a security group that allows some external traffic.
When ALB is associated with the WAF ACL, direct the traffic to the ALB by the Route53 CNAME record:
module \"some_url_exposure\" {\n source = \"terraform-aws-modules/route53/aws//modules/records\"\n version = \"2.0.0\"\n\n zone_name = \"edp-epam.com\"\n\n records = [\n {\n name = \"some-url\"\n type = \"CNAME\"\n ttl = 300\n records = [aws_lb.<aws_alb_for_waf>.dns_name]\n }\n ]\n}\n
In the sample above, the module is used, but it is also possible to use a Terraform resource.
"},{"location":"use-cases/","title":"Overview","text":""},{"location":"use-cases/#overview","title":"Overview","text":"The Use Cases section provides useful recommendations of how to operate with the EPAM Delivery Platform tools and manage the custom resources. Get acquainted with the description of technical scenarios and solutions.
This use case describes the creation and deployment of a FastAPI application to enable a developer to quickly generate a functional code structure for a FastAPI web application (with basic read functionality), customize it to meet specific requirements, and deploy it to a development environment. By using a scaffolding tool and a standardized process for code review, testing and deployment, developers can reduce the time and effort required to build and deploy a new application while improving the quality and reliability of the resulting code. Ultimately, the goal is to enable the development team to release new features and applications more quickly and efficiently while maintaining high code quality and reliability.
"},{"location":"use-cases/application-scaffolding/#roles","title":"Roles","text":"This documentation is tailored for the Developers and Team Leads.
"},{"location":"use-cases/application-scaffolding/#goals","title":"Goals","text":"Administrator
role (to perform merge in Gerrit).To scaffold and deploy FastAPI Application, follow the steps below.
"},{"location":"use-cases/application-scaffolding/#scaffold-the-new-fastapi-application","title":"Scaffold the New FastAPI Application","text":"Open EDP Portal URL. Use the Sign-In option.
Logging screen
Ensure Namespace
value in the User Settings
tab points to the namespace with the EDP installation.
Settings button
Create the new Codebase
with the Application
type using the Create
strategy. To do this, open EDP tab.
Cluster overview
Select the Components
Section under the EDP tab and push the create +
button.
Components tab
Select the Application
Codebase type because we are going to deliver our application as a container and deploy it inside the Kubernetes cluster. Choose the Create
strategy to scaffold our application from the template provided by the EDP and press the Proceed
button.
Step codebase info
On the Application Info tab, define the following values and press the Proceed
button:
fastapi-demo
main
Python
FastAPI
Python
Application info
On the Advances Settings
tab, define the below values and push the Apply
button:
Tekton
edp
0.0.1
and SNAPSHOT
Advanced settings
Check the application status. It should be green:
Application status
This section describes the application deployment approach from the latest branch commit. The general steps are:
main
branch.CD Pipeline
to establish continuous delivery to the development environment. To succeed with the steps above, follow the instructions below:
Build Container from the latest branch commit. To build the initial version of the application's main branch, go to the fastapi-demo application -> branches -> main and select the Build
menu.
Application building
Build pipeline for the fastapi-demo
application starts.
Pipeline building
Track Pipeline's status by accessing Tekton Dashboard by clicking the fastapi-demo-main-build-lb57m
application link.
Console logs
Ensure that Build Pipeline was successfully completed.
Create CD Pipeline. To enable application deployment create a CD Pipeline with a single environment - Development (with the name dev
).
Go to EDP Portal -> EDP -> CD Pipelines tab and push the +
button to create pipeline. In the Create CD Pipeline
dialog, define the below values:
Pipeline tab:
mypipe
Container
, since we are going to deploy containersPipeline tab with parameters
Applications tab. Add fastapi-demo
application, select main
branch, and leave Promote in pipeline
unchecked:
Applications tab with parameters
Stages tab. Add the dev
stage with the values below:
dev
Development Environment
Manual
. We plan to deploy applications to this environment manuallyManual
approve
Apply
buttonStages tab with parameters
Deploy the initial version of the application to the development environment:
mypipe
.dev
stage from the Stages tab.Image stream version
select version 0.0.1-SNAPSHOT.1
and push the Deploy
button.CD Pipeline deploy
To ensure the application is deployed successfully, follow the steps below:
Ensure application status is Healthy
and Synced
, and the Deployed version
points to 0.0.1-SNAPSHOT.1
:
Pipeline health status
Check that the selected version of the container is deployed on the dev
environment. ${EDP_ENV}
- is the EDP namespace name:
# Check the deployment status of fastapi-demo application\n$ kubectl get deployments -n ${EDP_ENV}-mypipe-dev\nNAME READY UP-TO-DATE AVAILABLE AGE\nfastapi-demo-dl1ft 1/1 1 1 30m\n\n# Check the image version of fastapi-demo application\n$ kubectl get pods -o jsonpath=\"{.items[*].spec.containers[*].image}\" -n ${EDP_ENV}-mypipe-dev\n012345678901.dkr.ecr.eu-central-1.amazonaws.com/${EDP_ENV}/fastapi-demo:0.0.1-SNAPSHOT.1\n
This section describes the Code Review
process for a new code. We need to deploy a new version of our fastapi-demo
application that deploys Ingress
object to expose API outside the Kubernetes cluster.
Perform the below steps to merge new code (Pull Request) that passes the Code Review flow. For the steps below, we use Gerrit UI but the same actions can be performed using the command line and git tool:
Login to Gerrit UI, select fastapi-demo
project, and create a change request.
Browse Gerrit Repositories and select fastapi-demo
project.
Browse Gerrit repositories
In the Commands
section of the project, push the Create Change
button.
Create Change request
In the Create Change
dialog, provide the branch main
and the Description
(commit message):
Enable ingress for application\n\nCloses: #xyz\n
Push the Create
button.
Create Change
Push the Edit
button of the merge request and add deployment-templates/values.yaml
for modification.
Update values.yaml file
Review the deployment-templates/values.yaml
file and change the ingress.enabled
flag from false
to true
. Then push the SAVE & PUBLISH
button. As soon as you get Verified +1
from CI, you are ready for review: Push the Mark as Active
button.
Review Change
You can always check your pipelines status from:
Pipeline Status Gerrit
Pipeline Status EDP Portal
With no Code Review Pipeline issues, set Code-Review +2
for the patchset and push the Submit
button. Then, your code is merged to the main
branch, triggering the Build Pipeline. The build Pipeline produces the new version of artifact: 0.0.1-SNAPSHOT.2
, which is available for the deployment.
Gerrit Code Review screen
Deliver the New Version to the Environment. Before the new version deployment, check the ingress object in dev
namespace:
$ kubectl get ingress -n ${EDP_ENV}-mypipe-dev\nNo resources found in ${EDP_ENV}-mypipe-dev namespace.\n
No ingress object exists as expected.
Deploy the new version 0.0.1-SNAPSHOT.2
which has the ingress object in place. Since we use Manual
deployment approach, we perform version upgrade by hand.
CD Pipelines
section of the EDP Portal
, select mypipe
pipeline and choose dev
stage.Image stream version
select the new version 0.0.1-SNAPSHOT.2
and push the Update
button.Healthy
and Synced
, and the Deployed version
points to 0.0.1-SNAPSHOT.2
.CD Pipeline Deploy New Version
Check that the new version with Ingress is deployed:
# Check the version of the deployed image\nkubectl get pods -o jsonpath=\"{.items[*].spec.containers[*].image}\" -n ${EDP_ENV}-mypipe-dev\n012345678901.dkr.ecr.eu-central-1.amazonaws.com/edp-delivery-tekton-dev/fastapi-demo:0.0.1-SNAPSHOT.2\n\n# Check Ingress object\nkubectl get ingress -n ${EDP_ENV}-mypipe-dev\nNAME CLASS HOSTS ADDRESS PORTS AGE\nfastapi-demo-ko1zs <none> fastapi-demo-ko1zs-example.com 12.123.123.123 80 115s\n\n# Check application external URL\ncurl https://your-hostname-appeared-in-hosts-column-above.example.com/\n{\"Hello\":\"World\"}\n
This use case describes the flow of adding an autotest as a quality gate to a newly created CD pipeline with a selected build version of an application to be promoted. The purpose of autotests is to check if application meets predefined criteria for stability and functionality, ensuring that only reliable versions are promoted. The promotion feature allows users to implement complicated testing, thus improving application stability.
"},{"location":"use-cases/autotest-as-quality-gate/#roles","title":"Roles","text":"This documentation is tailored for the Developers and Quality Assurance specialists.
"},{"location":"use-cases/autotest-as-quality-gate/#goals","title":"Goals","text":"To implement autotests as Quality Gates, follow the steps below:
Ensure the namespace is specified in the cluster settings. Click the Settings icon in the top right corner and select Cluster settings:
Cluster settings
Enter the name of the default namespace, then enter your default namespace in the Allowed namespaces field and click the + button. You can also add other namespaces to the Allowed namespaces:
Specify namespace
Create several applications using the Create strategy. Navigate to the EDP tab, choose Components, click the + button:
Add component
Select Application and Create from template:
Create new component menu
Note
Please refer to the Add Application section for details.
On the Codebase info tab, define the following values and press the Proceed button:
gerrit
js-application
js-application
js application
JavaScript
Vue
NPM
Codebase info tab
On the Advanced settings tab, define the below values and push the Apply button:
main
default
Advanced settings tab
Repeat the procedure twice to create the go-application and python-application applications. These applications will have the following parameters:
go-application:
gerrit
go-application
go-application
go application
Go
Gin
Go
main
default
python-application:
gerrit
python-application
python-application
python application
Python
FastAPI
Python
main
default
In the Components tab, click one of the applications name to enter the application menu:
Components list
Click the three dots (⋮) button, select Build:
Application menu
Click the down arrow (v) to observe and wait for the application to be built:
Application building
Click the application run name to watch the building logs in Tekton:
Tekton pipeline run
Wait till the build is successful:
Successful build
Repeat steps 8-12 for the rest of the applications.
The steps below instruct how to create autotests in EDP:
Create a couple of autotests using the Create strategy. Navigate to the EDP tab, choose Components, click on the + button. Select Autotest and Clone project:
Add autotest
Note
Please refer to the Add Autotest section for details.
On the Codebase info tab, define the following values and press the Proceed button:
https://github.com/SergK/autotests.git
gerrit
demo-autotest-gradle
demo-autotest-gradle
demo-autotest-gradle
Java
Java11
Gradle
Allure
Codebase info tab for autotests
On the Advanced settings tab, leave the settings as is and click the Apply button:
Advanced settings tab for autotests
Repeat the steps 1-3 to create one more autotest with the parameters below:
https://github.com/Rolika4/autotests.git
gerrit
demo-autotest-maven
demo-autotest-maven
demo-autotest-maven
Java
Java11
Maven
Allure
Now that applications and autotests are created, create pipeline for them by following the steps below:
Navigate to the CD Pipelines tab and click the + button:
CD pipelines tab
On the Pipeline tab, in the Pipeline name field, enter demo-pipeline:
Pipeline tab
On the Applications tab, add all the three applications, specify the main branch for all for them and check Promote in pipeline for Go and JavaScript applications:
Applications tab
On the Stages tab, click the Add stage button to open the Create stage menu:
Stages tab
In the Create stage menu, specify the following parameters and click Apply:
In cluster
dev
dev
manual
Autotests
dev
demo-autotest-gradle
main
Create stage menu
After the dev stage is added, click Apply:
Create stage menu
After the pipeline is created, click its name to open the pipeline details page:
Enter pipeline
In the pipeline details page, click the Create button to create a new stage:
Create a new stage
In the Create stage menu, specify the following parameters:
In cluster
sit
sit
manual
Autotests
dev
demo-autotest-maven
main
After the CD pipeline is created, deploy applications and run autotests by following the steps below:
Click the dev stage name to expand its details, specify image versions for each of the applications in the Image stream version field and click Deploy:
Deploy applications
Once applications are built, scroll down to Quality Gates and click Promote:
Promote in pipeline
Once promotion procedure is finished, the promoted applications will become available in the Sit stage. You will be able to select image stream versions for the promoted applications. The non-promoted application will stay grey in the stage and won't be allowed to get deployed:
Sit stage
This Use Case demonstrates how to securely manage sensitive data, such as passwords, API keys, and other credentials, that are consumed by application during development or runtime in production. The approach involves storing sensitive data in an external secret store that is located in a \"vault\" namespace (but can be Vault, AWS Secret Store or any other provider). The process implies transmitting confidential information from the vault namespace to the deployed namespace for the purpose of establishing a connection to a database.
"},{"location":"use-cases/external-secrets/#roles","title":"Roles","text":"This documentation is tailored for the Developers and Team Leads.
"},{"location":"use-cases/external-secrets/#goals","title":"Goals","text":"Administrator
role (to perform merge in Gerrit);To use External Secret in EDP approach, follow the steps below:
"},{"location":"use-cases/external-secrets/#add-application","title":"Add Application","text":"To begin, you will need an application first. Here are the steps to create it:
Open EDP Portal URL. Use the Sign-In
option:
Logging screen
In the top right corner, enter the Cluster settings
and ensure that both Default namespace
and Allowed namespace
are set:
Cluster settings
Create the new Codebase
with the Application
type using the Create
strategy. To do this, click the EDP
tab:
Cluster overview
Select the Components
section under the EDP tab and push the +
button:
Components tab
Select the Application
Codebase type because we are going to deliver our application as a container and deploy it inside the Kubernetes cluster. Select the Create
strategy to use predefined template:
Step codebase info
On the Application Info
tab, define the following values and press the Proceed
button:
es-usage
master
Java
Java 17
Maven
Step application info
On the Advanced Settings
tab, define the below values and push the Apply
button:
Tekton
default
Step application info
Check the application status. It should be green:
Application status
This section outlines the process of establishing a CD pipeline within EDP Portal. There are two fundamental steps in this procedure:
master
branch;CD Pipeline
to establish continuous delivery to the SIT environment.To succeed with the steps above, follow the instructions below:
Create CD Pipeline. To enable application deployment, create a CD Pipeline with a single environment - System Integration Testing (SIT for short). Select the CD Pipelines
section under the EDP
tab and push the +
button:
CD-Pipeline tab
On the Pipeline
tab, define the following values and press the Proceed
button:
deploy
Container
Pipeline tab
On the Applications
tab, add es-usage
application, select master
branch, leave Promote in pipeline
unchecked and press the Proceed
button:
Pipeline tab
On the Stage
tab, add the sit
stage with the values below and push the Apply
button:
sit
System integration testing
Manual
. We plan to deploy applications to this environment manuallyManual
Step name: approve
Stage tab
Note
In this scenario, three namespaces are used: demo
, which is the namespace where EDP is deployed, demo-vault
, which is the vault where developers store secrets, anddemo-deploy-sit
, which is the namespace used for deploying the application. The target namespace name for deploying application is formed with the pattern: edp-<cd_pipeline_name>-<stage_name>
.
To make the system to function properly, it is imperative to create the following resources:
Create namespace demo-vault
to store secrets:
kubectl create namespace demo-vault\n
Create Secret:
apiVersion: v1\nkind: Secret\nmetadata:\n name: mongo\n namespace: demo-vault\nstringData:\n password: pass\n username: user\ntype: Opaque\n
Create Role to access the secret:
apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n namespace: demo-vault\n name: external-secret-store\nrules:\n- apiGroups: [\"\"]\n resources:\n - secrets\n verbs:\n - get\n - list\n - watch\n- apiGroups:\n - authorization.k8s.io\n resources:\n - selfsubjectrulesreviews\n verbs:\n - create\n
Create RoleBinding:
apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n name: eso-from-edp\n namespace: demo-vault\nsubjects:\n - kind: ServiceAccount\n name: secret-manager\n namespace: demo-deploy-sit\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: Role\n name: external-secret-store\n
Now that RBAC is configured properly, it is time to add external secrets templates to application Helm chart. Follow the instructions provided below:
Navigate to EDP Portal
-> EDP
-> Overview
, and push the Gerrit link:
Overview page
Log in to Gerrit UI, select Repositories
and select es-usage
project:
Browse Gerrit repositories
In the Commands
section of the project, push the Create Change
button:
Create Change request
In the Create Change
dialog, provide the branch master
and fill in the Description
(commit message) field and push the Create
button:
Add external secrets templates\n
Create Change
Push the Edit
button of the merge request and then the ADD/OPEN/UPLOAD
button and add files:
Add files to repository
Once the file menu is opened, and click SAVE
after editing each of the files:
deploy-templates/templates/sa.yaml:
apiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: secret-manager\n namespace: demo-deploy-sit\n
deploy-templates/templates/secret-store.yaml:
apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: demo\n namespace: demo-deploy-sit\nspec:\n provider:\n kubernetes:\n remoteNamespace: demo-vault\n auth:\n serviceAccount:\n name: secret-manager\n server:\n caProvider:\n type: ConfigMap\n name: kube-root-ca.crt\n key: ca.crt\n
deploy-templates/templates/external-secret.yaml:
apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: mongo # target secret name\n namespace: demo-deploy-sit # target namespace\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: demo\n data:\n - secretKey: username # target value property\n remoteRef:\n key: mongo # remote secret key\n property: username # value will be fetched from this field\n - secretKey: password # target value property\n remoteRef:\n key: mongo # remote secret key\n property: password # value will be fetched from this field\n
deploy-templates/templates/deployment.yaml. Add the environment variable for mongodb to the existing deployment configuration that used the secret:
env:\n - name: MONGO_USERNAME\n valueFrom:\n secretKeyRef:\n name: mongo\n key: username\n - name: MONGO_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mongo\n key: password\n
Push the Publish Edit
button.
As soon as review pipeline finished, and you get Verified +1
from CI, you are ready for review. Click Mark as Active
-> Code-Review +2
-> Submit
:
Apply change
Deploy the application by following the steps provided below:
When build pipeline is finished, navigate to EDP Portal
-> EDP
-> CD-Pipeline
and select deploy
pipeline.
Deploy the initial version of the application to the SIT environment:
sit
stage from the Stages tab;Image stream version
, select latest version and push the Deploy
button.Ensure application status is Healthy
and Synced
:
CD-Pipeline status
To ensure the application is deployed successfully, do the following:
Check that the resources are deployed:
kubectl get secretstore -n demo-deploy-sit\nNAME AGE STATUS READY\ndemo 5m57s Valid True\n
kubectl get externalsecret -n demo-deploy-sit\nNAME STORE REFRESH INTERVAL STATUS READY\nmongo demo 1h SecretSynced True\n
In the top right corner, enter the Cluster settings
and add demo-deploy-sit
to the Allowed namespace
.
Navigate EDP Portal
-> Configuration
-> Secrets
and ensure that secret was created:
Secrets
Navigate EDP Portal
-> Workloads
-> Pods
and select deployed application:
Pod information
This Use Case describes the procedure of adding custom Tekton libraries that include pipelines with tasks. In addition to it, the process of modifying custom pipelines and tasks is enlightened as well.
"},{"location":"use-cases/tekton-custom-pipelines/#goals","title":"Goals","text":"Administrator
role to perform merge in Gerrit.Note
This case is based on our predefined repository and application. Your case may be different.
To create and then modify a custom Tekton library, please follow the steps below:
"},{"location":"use-cases/tekton-custom-pipelines/#add-custom-application-to-edp","title":"Add Custom Application to EDP","text":"Open EDP Portal URL. Use the Sign-In option:
Logging screen
In the top right corner, enter the Cluster settings
and ensure that both Default namespace
and Allowed namespace
are set:
Cluster settings
Create the new Codebase
with the Application
type using the Clone
strategy. To do this, click the EDP tab:
Cluster overview
Select the Components
section under the EDP tab and push the create +
button:
Components tab
Select the Application
codebase type because is meant to be delivered as a container and deployed inside the Kubernetes cluster. Choose the Clone
strategy and this example repository:
Step codebase info
In the Application Info tab, define the following values and click the Proceed
button:
tekton-hello-world
master
Other
go
shell
Application info
Note
These application details are required to match the Pipeline name gerrit-shell-go-app-build-default
.
The PipelineRun name is formed with the help of TriggerTemplates in pipelines-library
so the Pipeline name should correspond to the following structure:
pipelineRef:\n name: gerrit-$(tt.params.buildtool)-$(tt.params.framework)-$(tt.params.cbtype)-build-$(tt.params.versioning-type)\n
The PipelineRun is created as soon as Gerrit (or, if configured, GitHub, GitLab) sends a payload during Merge Request events. In the Advances Settings
tab, define the below values and click the Apply
button:
Tekton
default
Specify the pattern to validate a commit message
empty.Advanced settings
Check the application status. It should be green:
Application status
Now that the application is created successfully, proceed to adding the Tekton library.
Select the Components
section under the EDP tab and push the create +
button:
Components tab
Create a new Codebase with the Library
type using the Create
strategy:
Step codebase info
Note
The EDP Create strategy will automatically pull the code for the Tekton Helm application from here.
In the Application Info tab, define the following values and click the Proceed
button:
custom-tekton-chart
master
Helm
Pipeline
Helm
Step codebase info
In the Advances Settings
tab, define the below values and click the Apply
button:
Tekton
default
Specify the pattern to validate a commit message
empty.Advanced settings
Check the codebase status:
Codebase status
Note
Our recommendation is to avoid modifying the default Tekton resources. Instead, we suggest creating and modifying your own custom Tekton library.
Now that the Tekton Helm library is created, it is time to clone, modify and then apply it to the Kubernetes cluster.
Generate SSH key to work with Gerrit repositories:
ssh-keygen -t ed25519 -C \"your_email@example.com\"\n
Log into Gerrit UI.
Go to Gerrit Settings
-> SSH keys
, paste your generated public SSH key to the New SSH key
field and click ADD NEW SSH KEY
:
Gerrit settings Gerrit settings
Browse Gerrit Repositories and select custom-tekton-chart
project:
Browse Gerrit repositories
Clone the repository with SSH
using Clone with commit-msg hook
command:
Gerrit clone
Note
In case of the strict firewall configurations, please use the HTTP
protocol to pull and configure the HTTP Credentials
in Gerrit.
Examine the repository structure. It should look this way by default:
custom-tekton-chart\n \u251c\u2500\u2500 Chart.yaml\n \u251c\u2500\u2500 chart_schema.yaml\n \u251c\u2500\u2500 ct.yaml\n \u251c\u2500\u2500 lintconf.yaml\n \u251c\u2500\u2500 templates\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 pipelines\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 hello-world\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-build-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-build-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-build-lib-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-build-lib-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-review-lib.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-review.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-build-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-build-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-build-lib-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-build-lib-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-review-lib.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-review.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-build-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-build-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-build-lib-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-build-lib-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-review-lib.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 gitlab-review.yaml\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 tasks\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 task-hello-world.yaml\n \u2514\u2500\u2500 values.yaml\n
Note
Change the values in the values.yaml
file.
The gitProvider
parameter is the git hosting provider, Gerrit in this example. The similar approach be made with GitHub, or GitLab.
The dnsWildCard parameter is the cluster DNS address.
The gerritSSHPort parameter is the SSH port of the Gerrit service on Kubernetes. Check the Gerrit port in your edp installation global section.
Note
Our custom Helm chart includes edp-tekton-common-library dependencies in the Chart.yaml
file. This library allows to use our predefined code snippets.
Here is an example of the filled in values.yaml
file:
nameOverride: \"\"\nfullnameOverride: \"\"\n\nglobal:\n gitProvider: gerrit\n dnsWildCard: \"example.domain.com\"\n gerritSSHPort: \"30009\"\n
Modify and add tasks or pipelines.
As an example, let's assume that we need to add the helm-lint
pipeline task to the review pipeline. To implement this, insert the code below to the gerrit-review.yaml file underneath the hello task:
- name: hello\n taskRef:\n name: hello\n runAfter:\n - init-values\n params:\n - name: BASE_IMAGE\n value: \"$(params.shell-image-version)\"\n - name: username\n value: \"$(params.username)\"\n workspaces:\n - name: source\n workspace: shared-workspace\n\n - name: helm-lint\n taskRef:\n kind: Task\n name: helm-lint\n runAfter:\n - hello\n params:\n - name: EXTRA_COMMANDS\n value: |\n ct lint --validate-maintainers=false --charts deploy-templates/\n workspaces:\n - name: source\n workspace: shared-workspace\n
Note
The helm-lint
task references to the default pipeline-library
Helm chart which is applied to the cluster during EDP installation.
The runAfter
parameter shows that this Pipeline task will be run after the hello
pipeline task.
Build Helm dependencies in the custom chart:
helm dependency update .\n
Ensure that the chart is valid and all the indentations are fine:
helm lint .\n
To validate if the values are substituted in the templates correctly, render the templated YAML files with the values using the following command. It generates and displays all the manifest files with the substituted values:
helm template .\n
Install the custom chart with the command below. You can also use the --dry-run
flag to simulate the chart installation and catch possible errors:
helm upgrade --install edp-tekton-custom . -n edp --dry-run\n
helm upgrade --install edp-tekton-custom . -n edp\n
Check the created pipelines and tasks in the cluster:
kubectl get tasks -n edp\nkubectl get pipelines -n edp\n
Commit and push the modified Tekton Helm chart to Gerrit:
git add .\ngit commit -m \"Add Helm chart testing for go-shell application\"\ngit push origin HEAD:refs/for/master\n
Check the Gerrit code review for the custom Helm chart pipelines repository in Tekton:
Gerrit code review status
Go to Changes
-> Open
, click CODE-REVIEW
and submit the merge request:
Gerrit merge Gerrit merge
Check the build Pipeline status for the custom Pipelines Helm chart repository in Tekton:
Tekton status
Since we applied the Tekton library to the Kubernetes cluster in the previous step, let's test the review and build pipelines for our tekton-hello-world
application.
Perform the below steps to merge new code (Merge Request) that passes the Code Review flow. For the steps below, we use Gerrit UI but the same actions can be performed using the command line and Git tool:
Log into Gerrit UI, select tekton-hello-world
project, and create a change request.
Browse Gerrit Repositories and select tekton-hello-world
project:
Browse Gerrit repositories
Clone the tekton-hello-world
repository to make the necessary changes or click the Create Change
button in the Commands
section of the project to make changes via Gerrit GUI:
Create Change request
In the Create Change
dialog, provide the branch master
, write some text in the Description
(commit message) and click the Create
button:
Create Change
Click the Edit
button of the merge request and add deployment-templates/values.yaml
to modify it and change the ingress.enabled flag
from false
to true
:
Update values.yaml file Update values.yaml file
Check the Review Pipeline status. The helm-lint
pipeline task should be displayed there:
Review Change
Review the deployment-templates/values.yaml
file and push the SAVE & PUBLISH
button. As soon as you get Verified +1
from CI bot, the change is ready for review. Click the Mark as Active
and Code-review
buttons:
Review Change
Click the Submit
button. Then, your code is merged to the main branch, triggering the Build Pipeline.
Review Change
Note
If the build is added and configured, push steps in the pipeline, it will produce a new version of artifact, which will be available for the deployment in EDP Portal.
Check the pipelines in the Tekton dashboard:
Tekton custom pipelines Tekton custom pipelines
What happens under the hood: 1) Gerrit sends a payload during Merge Request event to the Tekton EventListener; 2) EventListener catches it with the help of Interceptor; 3) TriggerTemplate creates a PipelineRun.
The detailed scheme is shown below:
graph LR;\n A[Gerrit events] --> |Payload| B(Tekton EventListener) --> C(Tekton Interceptor CEL filter) --> D(TriggerTemplate)--> E(PipelineRun)
This chart will be using the core of common-library
and pipelines-library
and custom resources on the top of them.
The EDP Portal user guide is intended for developers and provides details on working with EDP Portal, different codebase types, and EDP CI/CD flow.
"},{"location":"user-guide/#edp-portal","title":"EDP Portal","text":"EDP Portal is a central management tool in the EDP ecosystem that provides the ability to define pipelines, project resources and new technologies in a simple way. Using EDP Portal enables to manage business entities:
Overview page
EDP Portal is a complete tool allowing to manage and control the codebases (applications, autotests, libraries and infrastructures) added to the environment as well as to create a CD pipeline.
Inspect the main features available in EDP Portal by following the corresponding link:
EDP Portal allows you to create an application, clone an existing repository with the application to your Version Control System (VCS), or using an external repository and importing an application to the environment. When an application is created or cloned, the system automatically generates a corresponding repository within the integrated Version Control System.
To add an application, navigate to the Components section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create new component dialog will appear, then select Application and choose one of the strategies which will be described later in this page. You can create an Application in YAML or via the two-step menu in the dialog.
"},{"location":"user-guide/add-application/#create-application-in-yaml","title":"Create Application in YAML","text":"Click Edit YAML in the upper-right corner of the Create Application dialog to open the YAML editor and create the Application.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Application dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-application/#create-application-via-ui","title":"Create Application via UI","text":"The Create Application dialog contains the two steps:
Follow the instructions below to fill in the fields of the Codebase Info menu:
In the Create new component menu, select Application:
Application info
Select the necessary configuration strategy. There are three configuration strategies:
Import project - allows using existing VCS repository to integrate with EDP. While importing the existing repository, select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitLab/GitHub With Tekton page.
Clone project \u2013 clones the indicated repository into EPAM Delivery Platform. While cloning the existing repository, it is required to fill in the Repository URL field as well:
Clone application
In our example, we will use the Create from template strategy:
Create application
Select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example
.
Type the name of the application in the Component name field by entering at least two characters and by using the lower-case letters, numbers and inner dashes.
Type the application description.
To create an application with an empty repository in Gerrit, select the Empty project check box.
Select any of the supported application languages with their providers in the Application Code Language field:
Note
The Create from template strategy does not allow to customize the default code language set.
Select necessary Language version/framework depending on the Application code language field.
Choose the necessary build tool in the Build Tool field:
Note
The Select Build Tool field disposes of the default tools and can be changed in accordance with the selected code language.
Note
Tekton pipelines offer built-in support for Java Maven Multi-Module projects. These pipelines are capable of recognizing Java deployable modules based on the information in the pom.xml file and performing relevant deployment actions. It's important to note that although the Dockerfile is typically located in the root directory, Kaniko, the tool used for building container images, uses the targets folder within the deployable module's context. For a clear illustration of a Multi-Module project structure, please refer to this example on GitHub, which showcases a commonly used structure for Java Maven Multi-Module projects.
The Advanced Settings menu should look similar to the picture below:
Advanced settings
Follow the instructions below to fill in the fields of the Advanced Setting menu:
a. Specify the name of the Default branch where you want the development to be performed.
Note
The default branch cannot be deleted. For the Clone project and Import project strategies: if you want to use the existing branch, enter its name into this field.
b. Select the necessary codebase versioning type:
edp - using the edp versioning type, a developer indicates the version number that will be used for all the artifacts stored in artifactory: binaries, pom.xml, metadata, etc. The version stored in repository (e.g. pom.xml) will not be affected or used. Using this versioning overrides any version stored in the repository files without changing actual file.
When selecting the edp versioning type, the extra field will appear:
Edp versioning
Type the version number from which you want the artifacts to be versioned.
Note
The Start Version From field should be filled out in compliance with the semantic versioning rules, e.g. 1.2.3 or 10.10.10. Please refer to the Semantic Versioning page for details.
c. Specify the pattern to validate a commit message. Use regular expression to indicate the pattern that is followed on the project to validate a commit message in the code review pipeline. An example of the pattern: ^[PROJECT_NAME-d{4}]:.*$
.
JIRA integration
d. Select the Integrate with Jira Server check box in case it is required to connect Jira tickets with the commits and have a respective label in the Fix Version field.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration page.
e. In the Jira Server field, select the Jira server.
f. Specify the pattern to find a Jira ticket number in a commit message. Based on this pattern, the value from EDP will be displayed in Jira. Combine several variables to obtain the desired value.
Mapping fields
g. In the Mapping field name section, specify the names of the Jira fields that should be filled in with attributes from EDP:
Select the name of the field in a Jira ticket from the Mapping field name drop-down menu. The available fields are the following: Fix Version/s, Component/s and Labels.
Click the Add button to add the mapping field name.
Enter Jira pattern for the field name:
Click the bin icon to remove the Jira field name.
h. Click the Apply button to add the application to the Applications list.
Note
After the complete adding of the application, inspect the Application Overview part.
"},{"location":"user-guide/add-application/#related-articles","title":"Related Articles","text":"EDP Portal allows you to clone an existing repository with the autotest to your Version Control System (VCS), or using an external repository and adding an autotest for further running in stages or using them as quality gates for applications. When an autotest is cloned, the system automatically generates a corresponding repository within the integrated VCS.
Info
Please refer to the Add Application section for the details on how to add an application codebase type. For the details on how to use autotests as quality gates, please refer to the Stages Menu section of the Add Environment documentation.
To add an autotest, navigate to the Components section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create new component dialog will appear, then select Autotest and choose one of the strategies which will be described later in this page. You can create an autotest in YAML or via the two-step menu in the dialog.
"},{"location":"user-guide/add-autotest/#create-autotest-in-yaml","title":"Create Autotest in YAML","text":"Click Edit YAML in the upper-right corner of the Create Autotest dialog to open the YAML editor and create an autotest:
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Autotest dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-autotest/#create-autotest-via-ui","title":"Create Autotest via UI","text":"The Create Autotest dialog contains the two steps:
There are two available strategies: clone and import.
The Create new component menu should look like the picture below:
Create new component menu
In the Create new component menu, select the necessary configuration strategy. The choice will define the parameters you will need to specify:
Import project - allows using existing VCS repository to integrate with EDP. While importing the existing repository, select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitLab/GitHub With Tekton page.
In our example, we will use the Clone project strategy:
Clone autotest
While cloning the existing repository, it is required to fill in the Repository URL field.
Select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example
.
Select the Repository credentials check box in case you clone the private repository, and fill in the repository login and password/access token.
Fill in the Component name field by entering at least two characters and by using the lower-case letters, numbers and inner dashes.
Type the necessary description in the Description field.
In the Autotest code language field, select the Java code language with its framework (specify Java 8 or Java 11 to be used) and get the default Maven build tool OR add another code language. Selecting Other allows extending the default code languages and get the necessary build tool, for details, inspect the Add Other Code Language section.
Note
Using the Create strategy does not allow to customize the default code language set.
Select the Java framework if Java is selected above.
The Build Tool field can dispose of the default Maven tool, Gradle or other built tool in accordance with the selected code language.
All the autotest reports will be created in the Allure framework that is available in the Autotest Report Framework field by default.
Click the Proceed button to switch to the next menu.
The Advanced Settings menu should look like the picture below:
Advanced settings
a. Specify the name of the default branch where you want the development to be performed.
Note
The default branch cannot be deleted.
b. Select the necessary codebase versioning type:
edp: Using the edp versioning type, a developer indicates the version number from which all the artifacts will be versioned and, as a result, automatically registered in the corresponding file (e.g. pom.xml).
When selecting the edp versioning type, the extra field will appear:
Edp versioning
Type the version number from which you want the artifacts to be versioned.
Note
The Start Version From field must be filled out in compliance with the semantic versioning rules, e.g. 1.2.3 or 10.10.10. Please refer to the Semantic Versioning page for details.
c. Specify the pattern to validate a commit message. Use regular expression to indicate the pattern that is followed on the project to validate a commit message in the code review pipeline. An example of the pattern: ^[PROJECT_NAME-d{4}]:.*$
Jira integration
d. Select the Integrate with Jira Server check box in case it is required to connect Jira tickets with the commits and have a respective label in the Fix Version field.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration page, and Adjust VCS Integration With Jira. Pay attention that the Jira integration feature is not available when using the GitLab CI tool.
e. As soon as the Jira server is set, select it in the Jira Server field.
f. Specify the pattern to find a Jira ticket number in a commit message. Based on this pattern, the value from EDP will be displayed in Jira.
Mapping field name
g. In the Advanced Mapping section, specify the names of the Jira fields that should be filled in with attributes from EDP:
Select the name of the field in a Jira ticket. The available fields are the following: Fix Version/s, Component/s and Labels.
Click the Add button to add the mapping field name.
Enter Jira pattern for the field name:
Click the bin icon to remove the Jira field name.
h. Click the Apply button to add the library to the Libraries list.
Note
After the complete adding of the autotest, inspect the Autotest Overview part.
"},{"location":"user-guide/add-autotest/#the-advanced-settings-menu","title":"The Advanced Settings Menu","text":""},{"location":"user-guide/add-autotest/#related-articles","title":"Related Articles","text":"Portal provides the ability to deploy an environment on your own and specify the essential components.
Navigate to the Environments section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create CD Pipeline dialog will appear.
The creation of the environment becomes available as soon as an application is created including its provisioning in a branch and the necessary entities for the environment. You can create the environment in YAML or via the three-step menu in the dialog.
"},{"location":"user-guide/add-cd-pipeline/#create-environment-in-yaml","title":"Create Environment in YAML","text":"Click Edit YAML in the upper-right corner of the Create CD Pipeline dialog to open the YAML editor and create the environment.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create CD Pipeline dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-cd-pipeline/#create-environment-in-the-dialog","title":"Create Environment in the Dialog","text":"The Create CD Pipeline dialog contains the three steps:
To create an environment, follow the steps below:
Navigate to EDP -> Environments and click the + Create button:
Environments menu
The Pipeline tab of the Create CD Pipeline menu should look like the picture below:
Create CD pipeline
Enter the Environment name that will be displayed in the Environments list.
Select the Deployment type. It can be either container or custom.
Click the Proceed button to move onto the Applications tab.
Type the name of the pipeline in the Pipeline Name field by entering at least two characters and by using the lower-case letters, numbers and inner dashes.
Note
The namespace created by the environment has the following pattern combination: [edp namespace]-[environment name]-[stage name]. Please be aware that the namespace length should not exceed 63 symbols.
Select the deployment type from the drop-down list:
Click the Proceed button to switch to the next menu.
The Pipeline tab of the Create CD Pipeline menu should look like the picture below:
Environment applications
Select the Promote in pipeline check box in order to transfer the application from one to another stage by the specified codebase Docker branch. If the Promote in pipeline check box is not selected, the same codebase Docker stream will be deployed regardless of the stage, i.e. the codebase Docker stream input, which was selected for the pipeline, will always be used.
Note
If there is another deployed environment stage with the respective codebase Docker stream (= image stream as an OpenShift term), the pattern combination will be as follows: [pipeline name]-[stage name]-[application name]-[verified].
Click the Proceed button to switch to the next menu.
Stages are created the following way:
On the Stages menu, click the Add Stage button and fill in the necessary fields in the Adding Stage window :
CD stages
Adding stage
a. Choose the cluster to deploy the stage;
b. Enter the stage name;
c. Enter the description for this stage;
d. Select the trigger type. The key benefit of the automatic deploy feature is to keep environments up-to-date. The available trigger types are Manual and Auto. When the Auto trigger type is chosen, the environment will initiate automatically once the image is built. Manual implies that user has to perform deploy manually by clicking the Deploy button in the environment menu. Please refer to the Architecture Scheme of CD Pipeline Operator page for additional details.
Note
Automatic deploy will start working only after the first manual deploy.
e. Select the quality gate type:
f. Type the step name, which will be displayed in Tekton, for every quality gate;
g. Add an unlimited number of quality gates by clicking the Add button and remove them as well by clicking the recycle bin icon;
In the additional fields, select the previously created autotest name (h) and specify its branch for the autotest that will be launched on the current stage (i).
Note
Execution sequence. The image promotion and execution of the pipelines depend on the sequence in which the environments are added.
j. Click the Apply button to display the stage in the Stages menu.
Continuous delivery menu
Edit the stage by clicking its name and applying changes, and remove the added stage by clicking the recycle bin icon next to its name.
Click the Apply button to start the provisioning of the pipeline.
As a result, a new environment will be created in the environments list.
"},{"location":"user-guide/add-cd-pipeline/#related-articles","title":"Related Articles","text":"Adding other clusters allows deploying applications to several clusters when creating a stage of CD pipeline in EDP Portal.
Note
Before proceeding with the content on this documentation page, it's essential to ensure that Argo CD is integrated into the same cluster with an identical name. At present, EDP operates with the shared Argo CD, necessitating the copying of the secret to the namespace where Argo CD is installed. The command sample is below:
kubectl get secret <SECRET_NAME> --namespace=edp -o yaml | sed 's/namespace: .*/namespace: argocd/' | kubectl apply -f -\n
To add a cluster, follow the steps below:
Navigate to the Configuration section on the navigation bar and select Clusters. The appearance differs depending on the chosen display option:
List optionTiled optionConfiguration menu (List option)
Configuration menu (Tiled option)
Click the + button to enter the Create new cluster menu:
Add Cluster
Once clicked, the Create new cluster dialog will appear. You can create a Cluster in YAML or via UI:
To add cluster in YAML, follow the steps below:
Edit YAML
To add cluster in YAML, follow the steps below:
Add Cluster
As a result, the Kubernetes secret will be created for further integration.
"},{"location":"user-guide/add-cluster/#related-articles","title":"Related Articles","text":"In order to add a new custom global pipeline library, perform the steps below:
Navigate to Jenkins and go to Manage Jenkins -> Configure System -> Global Pipeline Libraries.
Note
It is possible to configure as many libraries as necessary. Since these libraries will be globally usable, any pipeline in the system can utilize the functionality implemented in these libraries.
Specify the following values:
Add custom library
a. Library name: The name of a custom library.
b. Default version: The version which can be branched, tagged or hashed of a commit.
c. Load implicitly: If checked, scripts will automatically have access to this library without needing to request it via @Library. It means that there is no need to upload the library manually because it will be downloaded automatically during the build for each job.
d. Allow default version to be overridden: If checked, scripts may select a custom version of the library by appending @someversion in the @Library annotation. Otherwise, they are restricted to using the version selected here.
e. Include @Library changes in job recent changes: If checked, any changes in the library will be included in the changesets of a build, and changing the library would cause new builds to run for Pipelines that include this library. This can be overridden in the jenkinsfile: @Library(value=\"name@version\", changelog=true|false).
f. Cache fetched versions on controller for quick retrieval: If checked, versions fetched using this library will be cached on the controller. If a new library version is not downloaded during the build for some reason, remove the previous library version from cache in the Jenkins workspace.
Note
If the Default version check box is not defined, the pipeline must specify a version, for example, @Library('my-shared-library@master')
. If the Allow default version to be overridden check box is enabled in the Shared Library\u2019s configuration, a @Library annotation may also override the default version defined for the library.
Source code management
g. Project repository: The URL of the repository
h. Credentials: The credentials for the repository.
Use the Custom Global Pipeline Libraries on the pipeline, for example:
Pipeline
@Library(['edp-library-stages', 'edp-library-pipelines', 'edp-custom-shared-library-name'])_\n\nBuild()\n
Note
edp-custom-shared-library-name
is the name of the Custom Global Pipeline Library that should be added to the Jenkins Global Settings.
Important
This article describes how to add a Git Server when deploying EDP with Jenkins. When deploying EDP with Tekton, Git Server is created automatically.
Add Git servers to use the Import strategy for Jenkins and Tekton when creating an application, autotest or library in EDP Portal (Codebase Info step of the Create Application/Autotest/Library dialog). Enabling the Import strategy is a prerequisite to integrate EDP with Gitlab or GitHub.
Note
GitServer
Custom Resource can be also created manually. See step 3 for Jenkins import strategy in the Integrate GitHub/GitLab in Jenkins article.
To add a Git server, navigate to the Git servers section on the navigation bar and click Create (the plus sign icon in the lower-right corner of the screen). Once clicked, the Create Git server dialog will appear. You can create a Git server in YAML or via the three-step menu in the dialog.
"},{"location":"user-guide/add-git-server/#create-git-server-in-yaml","title":"Create Git Server in YAML","text":"Click Edit YAML in the upper-right corner of the Create Git server dialog to open the YAML editor and create a Git server.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Git server dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-git-server/#create-git-server-in-the-dialog","title":"Create Git Server in the Dialog","text":"Fill in the following fields:
Create Git server
Click the Apply button to add the Git server to the Git servers list. As a result, the Git Server object and the corresponding secret for further integration will be created.
"},{"location":"user-guide/add-git-server/#related-articles","title":"Related Articles","text":"EDP Portal allows you to create an application, clone an existing repository with the application to your Version Control System (VCS), or using an external repository and importing an application to the environment. When an application is created or cloned, the system automatically generates a corresponding repository within the integrated Version Control System. The functionality of the Infrastructure codebase type is to create resources in cloud provider.
To add an application, navigate to the Components section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create new component dialog will appear, then select Application and choose one of the strategies which will be described later in this page. You can create an Application in YAML or via the two-step menu in the dialog.
"},{"location":"user-guide/add-infrastructure/#create-infrastructure-in-yaml","title":"Create Infrastructure in YAML","text":"Click Edit YAML in the upper-right corner of the Create Infrastructure dialog to open the YAML editor and create the Infrastructure.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Infrastructure dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-infrastructure/#create-infrastructure-via-ui","title":"Create Infrastructure via UI","text":"The Create Infrastructure dialog contains the two steps:
Follow the instructions below to fill in the fields of the Codebase Info menu:
In the Create new component menu, select Infrastructure:
Infrastructure info
Select the necessary configuration strategy:
Import project - allows using existing VCS repository to integrate with EDP. While importing the existing repository, select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitLab/GitHub With Tekton page.
Clone project \u2013 clones the indicated repository into EPAM Delivery Platform. While cloning the existing repository, it is required to fill in the Repository URL field as well:
In our example, we will use the Create from template strategy:
Create infrastructure
Select the Git server from the drop-down list and define the Git repo relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example
.
Type the name of the infrastructure in the Component name field by entering at least two characters and by using the lower-case letters, numbers and inner dashes.
Write the description in the Description field.
To create an application with an empty repository in Gerrit, select the Empty project check box.
Select any of the supported application languages with their providers in the Infrastructure Code Language field. So far, only HCL is supported.
Note
The Create from template strategy does not allow to customize the default code language set.
Select necessary Language version/framework depending on the Infrastructure code language field. So far, only AWS is supported.
Choose the necessary build tool in the Build Tool field. So far, only Terraform is supported.\\
Note
The Select Build Tool field disposes of the default tools and can be changed in accordance with the selected code language.
The Advanced Settings menu should look similar to the picture below:
Advanced settings
Follow the instructions below to fill in the fields of the Advanced Setting menu:
a. Specify the name of the Default branch where you want the development to be performed.
Note
The default branch cannot be deleted. For the Clone project and Import project strategies: if you want to use the existing branch, enter its name into this field.
b. Select the necessary codebase versioning type:
edp - using the edp versioning type, a developer indicates the version number that will be used for all the artifacts stored in artifactory: binaries, pom.xml, metadata, etc. The version stored in repository (e.g. pom.xml) will not be affected or used. Using this versioning overrides any version stored in the repository files without changing actual file.
When selecting the edp versioning type, the extra field will appear:
Edp versioning
Type the version number from which you want the artifacts to be versioned.
Note
The Start Version From field should be filled out in compliance with the semantic versioning rules, e.g. 1.2.3 or 10.10.10. Please refer to the Semantic Versioning page for details.
c. Specify the pattern to validate a commit message. Use regular expression to indicate the pattern that is followed on the project to validate a commit message in the code review pipeline. An example of the pattern: ^[PROJECT_NAME-d{4}]:.*$
.
JIRA integration
d. Select the Integrate with Jira Server check box in case it is required to connect Jira tickets with the commits and have a respective label in the Fix Version field.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration page, and setup the Adjust VCS Integration With Jira. Pay attention that the Jira integration feature is not available when using the GitLab CI tool.
e. In the Jira Server field, select the Jira server.
f. Specify the pattern to find a Jira ticket number in a commit message. Based on this pattern, the value from EDP will be displayed in Jira. Combine several variables to obtain the desired value.
Note
The GitLab CI tool is available only with the Import strategy and makes the Jira integration feature unavailable.
Mapping fields
g. In the Mapping field name section, specify the names of the Jira fields that should be filled in with attributes from EDP:
Select the name of the field in a Jira ticket from the Mapping field name drop-down menu. The available fields are the following: Fix Version/s, Component/s and Labels.
Click the Add button to add the mapping field name.
Enter Jira pattern for the field name:
Click the bin icon to remove the Jira field name.
h. Click the Apply button to add the application to the Applications list.
Note
After the complete adding of the application, inspect the Application Overview part.
"},{"location":"user-guide/add-infrastructure/#related-articles","title":"Related Articles","text":"EDP Portal allows you to create a library, clone an existing repository with the library to your Version Control System (VCS), or using an external repository and importing a library to the environment. When a library is created or cloned, the system automatically generates a corresponding repository within the integrated VCS.
To add a library, navigate to the Components section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create new component dialog will appear, then select Library and choose one of the strategies which will be described later in this page. You can create a library in YAML or via the two-step menu in the dialog.
Create new component menu
"},{"location":"user-guide/add-library/#create-library-in-yaml","title":"Create Library in YAML","text":"Click Edit YAML in the upper-right corner of the Create Library dialog to open the YAML editor and create the Library.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Application dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-library/#create-library-via-ui","title":"Create Library via UI","text":"The Create Library dialog contains the two steps:
The Create new component menu should look like the following:
Create new component menu
In the Create new component menu, select the necessary configuration strategy. The choice will define the parameters you will need to specify:
Import project - allows using existing VCS repository to integrate with EDP. While importing the existing repository, select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitLab/GitHub With Tekton page.
Clone project \u2013 clones the indicated repository into EPAM Delivery Platform. While cloning the existing repository, it is required to fill in the Repository URL field as well:
Clone library
In our example, we will use the Create from template strategy:
Create library
/epmd-edp/examples/basic/edp-auto-tests-simple-example
Select any of the supported code languages with its framework in the Library code language field:
Note
The Create strategy does not allow to customize the default code language set.
Select necessary Language version/framework depending on the Library code language field.
The Select Build Tool field disposes of the default tools and can be changed in accordance with the selected code language.
Click the Proceed button to switch to the next menu.
The Advanced Settings menu should look like the picture below:
Advanced settings
a. Specify the name of the default branch where you want the development to be performed.
Note
The default branch cannot be deleted.
b. Select the necessary codebase versioning type:
When selecting the edp versioning type, the extra field will appear:
EDP versioning
Type the version number from which you want the artifacts to be versioned.
Note
The Start Version From field should be filled out in compliance with the semantic versioning rules, e.g. 1.2.3 or 10.10.10. Please refer to the Semantic Versioning page for details.
c. Specify the pattern to validate a commit message. Use regular expression to indicate the pattern that is followed on the project to validate a commit message in the code review pipeline. An example of the pattern: ^[PROJECT_NAME-d{4}]:.*$
Integrate with Jira server
d. Select the Integrate with Jira server check box in case it is required to connect Jira tickets with the commits and have a respective label in the Fix Version field.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration page, and Adjust VCS Integration With Jira. Pay attention that the Jira integration feature is not available when using the GitLab CI tool.
e. As soon as the Jira server is set, select it in the Jira Server field.
f. Specify the pattern to find a Jira ticket number in a commit message. Based on this pattern, the value from EDP will be displayed in Jira.
Mapping fields
g. In the Advanced Mapping section, specify the names of the Jira fields that should be filled in with attributes from EDP:
Select the name of the field in a Jira ticket. The available fields are the following: Fix Version/s, Component/s and Labels.
Click the Add button to add the mapping field name.
Enter Jira pattern for the field name:
Click the bin icon to remove the Jira field name.
h. Click the Apply button to add the library to the Libraries list.
Note
After the complete adding of the library, inspect the Library Overview part.
"},{"location":"user-guide/add-library/#related-articles","title":"Related Articles","text":"With the built-in Marketplace, users can easily create a new application by clicking several buttons. This page contains detailed guidelines on how to create a new component with the help of the Marketplace feature.
"},{"location":"user-guide/add-marketplace/#add-component","title":"Add Component","text":"To create a component from template, follow the instructions below:
Navigate to the Marketplace section on the navigation bar to see the Marketplace overview page.
Click the component name to open its details window and click Create from template:
Create from template
Fill in the required fields and click Apply:
Creating from template window
As a result, new component will appear in the Components section:
Creating from template window
This section describes how to use quality gate in EDP and how to customize the quality gate for the CD pipeline with the selected build version of the promoted application between stages.
"},{"location":"user-guide/add-quality-gate/#apply-new-quality-gate-to-pipelines","title":"Apply New Quality Gate to Pipelines","text":"Quality gate pipeline is a usual Tekton pipeline but with a specific label: app.edp.epam.com/pipelinetype: deploy
. To add and apply the quality gate to your pipelines, follow the steps below:
1. To use the Tekton pipeline as a quality gate pipeline, add this label to the pipelines:
metadata:\n labels:\n app.edp.epam.com/pipelinetype: deploy\n
2. Insert the value that is the quality gate name displayed in the quality gate drop-down list of the CD pipeline menu: metadata:\n name: <name-of-quality-gate>\n
3. Ensure the task promote-images
contains steps and logic to apply to the project. Also ensure that the last task is promote-images
which parameters are mandatory: spec:\n params:\n - default: ''\n description: Codebases with a tag separated with a space.\n name: CODEBASE_TAG\n type: string\n - default: ''\n name: CDPIPELINE_CR\n type: string\n - default: ''\n name: CDPIPELINE_STAGE\n type: string\n tasks:\n - name: promote-images\n params:\n - name: CODEBASE_TAG\n value: $(params.CODEBASE_TAG)\n - name: CDPIPELINE_STAGE\n value: $(params.CDPIPELINE_STAGE)\n - name: CDPIPELINE_CR\n value: $(params.CDPIPELINE_CR)\n runAfter:\n - <last-task-name>\n taskRef:\n kind: Task\n name: promote-images\n
4. Create a new pipeline with a unique name or modify your created pipeline with the command below. Please be aware that the \u2039edp-project\u203a value is the name of the EDP tenant: kubectl apply -f <file>.yaml --namespace edp\n
Example: file.yaml apiVersion: tekton.dev/v1beta1\n kind: Pipeline\n metadata:\n labels:\n app.edp.epam.com/pipelinetype: deploy\n name: <name-of-quality-gate>\n namespace: edp\n spec:\n params:\n - default: >-\n https://<CI-pipeline-provisioner>-edp.<cluster-name>.aws.main.edp.projects.epam.com/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)\n name: pipelineUrl\n type: string\n - default: ''\n description: Codebases with a tag separated with a space.\n name: CODEBASE_TAG\n type: string\n - default: ''\n name: CDPIPELINE_CR\n type: string\n - default: ''\n name: CDPIPELINE_STAGE\n type: string\n tasks:\n - name: autotests\n params:\n - name: BASE_IMAGE\n value: bitnami/kubectl:1.25.4\n - name: EXTRA_COMMANDS\n value: echo \"Hello World\"\n taskRef:\n kind: Task\n name: run-quality-gate\n - name: promote-images\n params:\n - name: CODEBASE_TAG\n value: $(params.CODEBASE_TAG)\n - name: CDPIPELINE_STAGE\n value: $(params.CDPIPELINE_STAGE)\n - name: CDPIPELINE_CR\n value: $(params.CDPIPELINE_CR)\n runAfter:\n - autotests\n taskRef:\n kind: Task\n name: promote-images\n
"},{"location":"user-guide/add-quality-gate/#run-quality-gate","title":"Run Quality Gate","text":"Before running the quality gate, first of all, ensure that the environment has deployed the created CD pipeline and then ensure that the application is successfully deployed and ready to run the quality gate. To run quality gate, please follow the steps below:
Check the CD pipeline status. To do this, open the created CD pipeline, select Image stream version
, click DEPLOY
button and wait until Applications
, Health
and Sync
statuses become green
. This implies that the application is successfully deployed and ready to run the quality gate.
CD pipeline stage overview
Select the name-of-quality-gate of Quality gates
from the drop-down list and click the RUN
button.The execution process should be started in the Pipelines
menu:
Quality gate pipeline status
For a better understanding of this section, please read the documentation about how to add a new stage for quality gate. The scheme below illustrates two approaches of adding quality gates:
Types of adding quality gate
Promote in pipelines
option while creating a CD Pipeline to pass the quality gate in a certain sequence.As a result, after the quality gate is successfully passed, the projected image is promoted to the next stage.
"},{"location":"user-guide/add-quality-gate/#related-articles","title":"Related Articles","text":"This section describes the subsequent possible actions that can be performed with the newly added or existing applications.
"},{"location":"user-guide/application/#check-and-remove-application","title":"Check and Remove Application","text":"As soon as the application is successfully provisioned, the following will be created:
The added application will be listed in the Applications list allowing you to do the following:
Applications menu
Delete application - remove application by clicking the vertical ellipsis button and then selecting Delete.
Note
The application that is used in a CD pipeline cannot be removed.
There are also options to sort the applications:
Select a number of applications displayed per page (15, 25 or 50 rows) and navigate between pages if the number of applications exceeds the capacity of a single page:
Applications pages
EDP Portal provides the ability to enable, disable or edit the Jira Integration functionality for applications.
To edit an application directly from the Applications overview page or when viewing the application data:
Edit application on the Applications overview page
Edit application when viewing the application data
To enable Jira integration, in the Edit Application dialog do the following:
Edit application
a. Mark the Integrate with Jira server check box and fill in the necessary fields. Please see steps d-h of the Add Application page.
b. Select the Apply button to apply the changes.
To disable Jira integration, in the Edit Application dialog do the following:
a. Uncheck the Integrate with Jira server check box.
b. Select the Apply button to apply the changes.
To create, edit and delete application branches, please refer to the Manage Branches page.
This section describes the subsequent possible actions that can be performed with the newly added or existing autotests.
"},{"location":"user-guide/autotest/#check-and-remove-autotest","title":"Check and Remove Autotest","text":"As soon as the autotest is successfully provisioned, the following will be created:
Info
To navigate quickly to Tekton, Version Control System, SonarQube, Nexus, and other resources, click the Overview section on the navigation bar and hit the necessary link.
The added autotest will be listed in the Autotests list allowing you to do the following:
Autotests page
Delete autotest - remove autotest by clicking the vertical ellipsis button and then selecting Delete.
Note
The autotest that is used in a CD pipeline cannot be removed.
There are also options to sort the applications:
EDP Portal provides the ability to enable, disable or edit the Jira Integration functionality for autotests.
To edit an autotest directly from the Autotests overview page or when viewing the autotest data:
Select Edit in the options icon menu:
Edit autotest on the autotests overview page
Edit autotest when viewing the autotest data
To enable Jira integration, on the Edit Autotest page do the following:
Edit library
a. Mark the Integrate with Jira server check box and fill in the necessary fields. Please see steps d-h on the Add Autotests page.
b. Select the Apply button to apply the changes.
Note
Pay attention that the Jira integration feature is not available when using the GitLab CI tool.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration and Adjust VCS Integration With Jira pages.
To disable Jira integration, in the Edit Autotest dialog do the following:
a. Uncheck the Integrate with Jira server check box.
b. Select the Apply button to apply the changes.
As a result, the necessary changes will be applied.
To create, edit and delete application branches, please refer to the Manage Branches page.
In order to add an autotest as a quality gate to a newly added CD pipeline, do the following:
Create a CD pipeline with the necessary parameters. Please refer to the Add CD Pipeline section for the details.
In the Stages menu, select the Autotest quality gate type. It means the promoting process should be confirmed by the successful passing of the autotests.
In the additional fields, select the previously created autotest name and specify its branch.
After filling in all the necessary fields, click the Create button to start the provisioning of the pipeline. After the CD pipeline is added, the new namespace containing the stage name will be created in Kubernetes (in OpenShift, a new project will be created) with the following name pattern: [cluster name]-[cd pipeline name]-[stage name].
In order to configure the added autotest launch at the specific stage with necessary parameters, do the following:
Add the necessary stage to the CD pipeline. Please refer to the Add CD Pipeline documentation for the details.
Navigate to the run.json file and add the stage name and the specific parameters.
There is an ability to run the autotests locally using the IDEA (Integrated Development Environment Application, such as IntelliJ, NetBeans etc.). To launch the autotest project for the local verification, perform the following steps:
Clone the project to the local machine.
Open the project in IDEA and find the run.json file to copy out the necessary command value.
Paste the copied command value into the Command line field and run it with the necessary values and namespace.
As a result, all the launched tests will be executed.
This section provides details on the Build pipeline of the EDP CI/CD pipeline framework. Explore below the pipeline purpose, stages and possible actions to perform.
"},{"location":"user-guide/build-pipeline/#build-pipeline-purpose","title":"Build Pipeline Purpose","text":"The purpose of the Build pipeline contains the following points:
Find below the functional diagram of the Build pipeline with the default stages:
flowchart TD\n build --> get-nexus-repository-url\n compile --> test\n start([fa:fa-circle]) --> fetch-repository\n fetch-repository --> init-values\n get-nexus-repository-url --> push\n get-version --> update-build-number\n git-tag --> update-cbis\n init-values --> get-version\n kaniko-build --> git-tag\n push --> kaniko-build\n sast --> compile\n sonar --> build\n test --> sonar\n update-build-number --> sast\n update-cbis --> stop([fa:fa-circle])
"},{"location":"user-guide/build-pipeline/#build-pipeline-for-application-and-library","title":"Build Pipeline for Application and Library","text":"The Build pipeline is triggered automatically after the Code Review pipeline is completed and the changes are submitted.
To review the Build pipeline, take the following steps:
Open Jenkins via the created link in Gerrit or via the Admin Console Overview page.
Click the Build pipeline link to open its stages for the application and library codebases:
Note
For more details on stages, please refer to the Pipeline Stages documentation.
After the Build pipeline runs all the stages successfully, the corresponding tag numbers will be created in Kubernetes/OpenShift and Nexus.
"},{"location":"user-guide/build-pipeline/#check-the-tag-in-kubernetesopenshift-and-nexus","title":"Check the Tag in Kubernetes/OpenShift and Nexus","text":"After the Build pipeline is completed, check the tag name and the same with the commit revision. Simply navigate to Gerrit \u2192 Projects \u2192 List \u2192 select the project \u2192 Tags.
Note
For the Import strategy, navigate to the repository from which a codebase is imported \u2192 Tags. It is actual both for GitHub and GitLab.
Open the Kubernetes/OpenShift Overview page and click the link to Nexus and check the build of a new version.
Switch to Kubernetes \u2192 CodebaseImageStream (or OpenShift \u2192 Builds \u2192 Images) \u2192 click the image stream that will be used for deployment.
Check the corresponding tag.
The Build pipeline can be started manually. To set the necessary stages and trigger the pipeline manually, take the following steps:
Open the Build pipeline for the created library.
Click the Build with parameters option from the left-side menu. Modify the stages by removing the whole objects massive:{\"name\". \"tests\"} where name is a key and tests is a stage name that should be executed.
Open Jenkins and check the successful execution of all stages.
CD Pipeline (Continuous Delivery Pipeline) - an EDP business entity that describes the whole delivery process of the selected application set via the respective stages. The main idea of the CD pipeline is to promote the application build version between the stages by applying the sequential verification (i.e. the second stage will be available if the verification on the first stage is successfully completed). The CD pipeline can include the essential set of applications with its specific stages as well.
In other words, the CD pipeline allows the selected image stream (Docker container in Kubernetes terms) to pass a set of stages for the verification process (SIT - system integration testing with the automatic type of a quality gate, QA - quality assurance, UAT - user acceptance testing with the manual testing).
Note
It is possible to change the image stream for the application in the CD pipeline. Please refer to the Edit CD Pipeline section for the details.
A CI/CD pipeline helps to automate steps in a software delivery process, such as the code build initialization, automated tests running, and deploying to a staging or production environment. Automated pipelines remove manual errors, provide standardized development feedback cycle, and enable the fast product iterations. To get more information on the CI pipeline, please refer to the CI Pipeline Details chapter.
The codebase stream is used as a holder for the output of the stage, i.e. after the Docker container (or an image stream in OpenShift terms) passes the stage verification, it will be placed to the new codebase stream. Every codebase has a branch that has its own codebase stream - a Docker container that is an output of the build for the corresponding branch.
Note
For more information on the main terms used in EPAM Delivery Platform, please refer to the EDP Glossary
EDP CD pipeline
Explore the details of the CD pipeline below.
"},{"location":"user-guide/cd-pipeline-details/#deploy-pipeline","title":"Deploy Pipeline","text":"The Deploy pipeline is used by default on any stage of the Continuous Delivery pipeline. It addresses the following concerns:
Find below the functional diagram of the Deploy pipeline with the default stages:
Note
The input for a CD pipeline depends on the Trigger Type for a deploy stage and can be either Manual or Auto.
Deploy pipeline stages
"},{"location":"user-guide/cd-pipeline-details/#related-articles","title":"Related Articles","text":"CI Pipeline (Continuous Integration Pipeline) - an EDP business entity that describes the integration of changes made to a codebase into a single project. The main idea of the CI pipeline is to review the changes in the code submitted through a Version Control System (VCS) and build a new codebase version so that it can be transmitted to the Continuous Delivery Pipeline for the rest of the delivery process.
There are three codebase types in EPAM Delivery Platform:
Note
For more information on the above mentioned codebase types, please refer to the Add Application, Add Library, Add Autotests and Autotest as Quality Gate pages.
EDP CI pipeline
"},{"location":"user-guide/ci-pipeline-details/#related-articles","title":"Related Articles","text":"This chapter provides information on CI/CD basic definitions and flow, as well as its components and process.
"},{"location":"user-guide/cicd-overview/#cicd-basic-definitions","title":"CI/CD Basic Definitions","text":"The Continuous Integration part means the following:
The Code Review
and Build
pipelines are used before the code is delivered. An important part of both of them is the integration tests that are launched during the testing stage.
Many applications (SonarQube, Gerrit, etc,) used by the project need databases for their performance.
The Continuous Delivery comprises an approach allowing to produce an application in short cycles so that it can be reliably released at any time point. This part is tightly bound with the usage of the Code Review
, Build
, and Deploy
pipelines.
The Deploy
pipelines deploy the applications configuration and their specific versions, launch automated tests and control quality gates for the specified environment. As a result of the successfully completed process, the specific versions of images are promoted to the next environment. All environments are sequential and promote the build versions of applications one-by-one. The logic of each stage is described as a code of Jenkins pipelines and stored in the VCS.
During the CI/CD, there are several continuous processes that run in the repository, find below the list of possible actions:
Note
For the details on autotests, please refer to the Autotest, Add Autotest, and Autotest as Quality Gate pages.
The release process is divided into cycles and provides regular delivery of completed pieces of functionality while continuing the development and integration of new functionality into the product mainline.
Explore the main flow that is displayed on the diagram below:
EDP CI/CD pipeline
"},{"location":"user-guide/cicd-overview/#related-articles","title":"Related Articles","text":"This section describes the subsequent possible actions that can be performed with the newly added or existing clusters.
In a nutshell, cluster in EDP Portal is a Kubernetes secret that stores credentials and endpoint to connect to the another cluster. Adding new clusters allows users to deploy applications in several clusters, thus improving flexibility of your infrastructure.
The added cluster will be listed in the clusters list allowing you to do the following:
Clusters list
"},{"location":"user-guide/cluster/#view-authentication-data","title":"View Authentication Data","text":"To view authentication data that is used to log in to the cluster, run the kubectl describe
command:
kubectl describe secret cluster_name -n edp\n
"},{"location":"user-guide/cluster/#delete-cluster","title":"Delete Cluster","text":"To delete cluster, use the kubectl delete
command as follows:
kubectl delete secret cluster_name -n edp\n
"},{"location":"user-guide/cluster/#related-articles","title":"Related Articles","text":"This section provides details on the Code Review pipeline of the EDP CI/CD framework. Explore below the pipeline purpose, stages and possible actions to perform.
"},{"location":"user-guide/code-review-pipeline/#code-review-pipeline-purpose","title":"Code Review Pipeline Purpose","text":"The purpose of the Code Review pipeline contains the following points:
Find below the functional diagram of the Code Review pipeline with the default stages:
flowchart TD\n build --> dockerbuild-verify\n compile --> test\n dockerbuild-verify --> stop([fa:fa-circle])\n dockerfile-lint --> dockerbuild-verify\n fetch-repository --> init-values\n fetch-repository --> helm-docs\n fetch-repository --> dockerfile-lint\n fetch-repository --> helm-lint\n helm-docs --> stop([fa:fa-circle])\n helm-lint --> stop([fa:fa-circle])\n init-values --> compile\n start([fa:fa-circle]) --> report-pipeline-start-to-gitlab\n report-pipeline-start-to-gitlab --> fetch-repository\n sonar --> build\n test --> sonar
"},{"location":"user-guide/code-review-pipeline/#code-review-pipeline-for-applications-and-libraries","title":"Code Review Pipeline for Applications and Libraries","text":"Note
Make sure the necessary applications or libraries are added to the Admin Console. For the details on how to add a codebase, please refer to the Add Application or Add Library pages accordingly.
To discover the Code Review pipeline, apply changes that will trigger the Code Review pipeline automatically and take the following steps:
Navigate to Jenkins. In Admin Console, go to the Overview section on the left-side navigation bar and click the link to Jenkins.
Link to Jenkins
or
In Gerrit, go to the Patch Set page and click the CI Jenkins link in the Change Log section
Link from Gerrit
Note
The Code Review pipeline starts automatically for every codebase type (Application, Autotests, Library).
Check the Code Review pipeline for the application of for the library. Click the application name in Jenkins and switch to the additional release-01 branch that is created with the respective Code Review and Build pipelines.
Click the Code Review pipeline link to open the Code Review pipeline stages for the application:
Note
For more details on EDP pipeline stages, please refer to the Pipeline Stages section.
"},{"location":"user-guide/code-review-pipeline/#code-review-pipeline-for-autotests","title":"Code Review Pipeline for Autotests","text":"To discover the Code Review pipeline for autotests, first, apply changes to a codebase that will trigger the Code Review pipeline automatically. The flow for the autotest is similar for that for applications and libraries, however, there are some differences. Explore them below.
Open the run.json file for the created autotest.
Note
Please refer to the Add Autotest page for the details on how to create an autotest.
The run.json file keeps a command that is executed on this stage.
Open the Code Review pipeline in Jenkins (via the link in Gerrit or via the Admin Console Overview page) and click the Configure option from the left side. There are only four stages available: Initialization - Gerrit-checkout - tests - sonar (the launch of the static code analyzer that checks the whole code).
Open the Code Review pipeline in Jenkins with the successfully passed stages.
The Code Review pipeline can be retriggered manually, especially if the pipeline failed before. To retrigger it, take the following steps:
In Jenkins, click the Retrigger option from the drop-down menu for the specific Code Review pipeline version number. Alternatively, click the Jenkins main page and select the Query and Trigger Gerrit Patches option.
Click Search and select the check box of the necessary change and patch set and then click Trigger Selected.
As a result, the Code Review pipeline will be retriggered.
"},{"location":"user-guide/code-review-pipeline/#configure-code-review-pipeline","title":"Configure Code Review Pipeline","text":"The Configure option allows adding/removing the stage from the Code Review pipeline if needed. To configure the Code Review pipeline, take the following steps:
Being in Jenkins, click the Configure option from the left-side menu.
Define the stages set that will be executed for the current pipeline.
Note
All stages are launched from the shared library on GitHub. The list of libraries is located in the edp-library-stages repository.
To apply the new stage process, retrigger the Code Review pipeline. For details, please refer to the Retrigger Code Review Pipeline section.
Open Jenkins and check that there is no removed stage in the Code Review pipeline.
In this section, we will introduce you to the different types of codebases and strategies for onboarding codebases onto the EDP platform.
"},{"location":"user-guide/components/#component-and-codebase","title":"Component and Codebase","text":"From a business perspective, Components
represent the functional building blocks of software projects. They define the purpose and functionality of different parts of a business application, such as core applications, libraries, automated tests, and infrastructure settings. Components are about what software does and how it aligns with business goals.
From a technical implementation perspective, Codebases
are the Kubernetes custom resources that manage the technical aspects of these Components. They serve as the bridge between the business logic represented by Components and the underlying Git repositories. Codebases are responsible for the technical implementation, ensuring that the Components are efficiently stored, versioned, and synchronized with the version control system. They represent the state of Components from a technical standpoint.
Components are the building blocks of software projects. They come in different types, such as Applications
, Libraries
, Autotests
, and Infrastructure
. Each component type serves a specific purpose in the development process. Applications are the deployable unit of projects, libraries contain reusable code, autotests facilitate automated testing, and infrastructure defines a project's infrastructure settings.
Codebases are Kubernetes custom resources (CR) that represent the state of the components. They are a crucial link between component's state and underlying Git repositories. In essence, each codebase corresponds to a specific component and reflects its current state within a single Git repository. This one-to-one mapping ensures that the component's state is efficiently managed and versioned.
"},{"location":"user-guide/components/#types","title":"Types","text":"EDP accommodates a variety of codebase types, each serving a specific purpose in the development process. The codebase types available in EDP are:
Infrastructure as Code
approach, ensuring consistency and reproducibility.The platform supports the following strategies to onboard codebases on the platform:
The codebase-operator is responsible for creating and managing the codebase custom resource on the EPAM Delivery Platform. The codebase CR defines the metadata and configuration of the codebase, such as the name, description, type, repository URL, branch, path, CD tool, etc. The codebase-operator watches for changes in the codebase CR and synchronizes them with the corresponding Git repository and EDP components. Learn more about the codebase-operator and the custom resource (CR) API.
"},{"location":"user-guide/container-stages/","title":"CI Pipeline for Container","text":""},{"location":"user-guide/container-stages/#ci-pipeline-for-container","title":"CI Pipeline for Container","text":"EPAM Delivery Platform ensures the implemented Container support allowing to work with Dockerfile that is processed by means of stages in the Code-Review and Build pipelines. These pipelines are expected to be created after the Container Library is added.
"},{"location":"user-guide/container-stages/#code-review-pipeline-stages","title":"Code Review Pipeline Stages","text":"In the Code Review pipeline, the following stages are available:
checkout stage is a standard step during which all files are checked out from a selected branch of the Git repository.
dockerfile-lint stage uses the hadolint tool to perform linting tests for the Dockerfile.
dockerbuild-verify stage collects artifacts and builds an image from the Dockerfile without pushing to registry. This stage is intended to check if the image is built.
In the Build pipeline, the following stages are available:
checkout stage is a standard step during which all files are checked out from a master branch of the Git repository.
get-version stage where the library version is determined either via:
2.1. EDP versioning functionality.
2.2. Default versioning functionality.
dockerfile-lint stage uses the hadolint tool to perform linting tests for Dockerfile.
build-image-kaniko stage builds Dockerfile using the Kaniko tool.
git-tag stage that is intended for tagging a repository in Git.
EPAM Delivery Platform ensures the implemented Kaniko tool and BuildConfig
object support. Using Kaniko tool allows building the container images from a Dockerfile both on the Kubernetes and OpenShift platforms. The BuildConfig
object enables the building of the container images only on the OpenShift platform.
EDP uses the BuildConfig
object and the Kaniko tool for creating containers from a Dockerfile and pushing them to the internal container image registry. For Kaniko, it is also possible to change the Docker config file and push the containers to different container image registries.
By default, EPAM Delivery Platform uses the build-image-kaniko
stage for building container images on the Kubernetes platform and the build-image-from-dockerfile
stage for building container images on the OpenShift platform.
In order to change a build tool for the OpenShift Platform from the default buildConfig
object to the Kaniko tool, perform the following steps:
stages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-from-dockerfile\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n
stages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-kaniko\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n
The Copy Shared Secrets stage provides the ability to copy secrets from the current Kubernetes namespace into a namespace created during CD pipeline.
Shared secrets
Please follow the steps described below to copy the secrets:
Create a secret in the current Kubernetes namespace that should be used in the deployment. The secret label must be app.edp.epam.com/use: cicd
, since the pipeline script will attempt to copy the secret by its label. For example:
kind: Secret\nmetadata:\n labels:\n app.edp.epam.com/use: cicd\n
Add the following step to the CD pipeline {\"name\":\"copy-secrets\",\"step_name\":\"copy-secrets\"}
. Alternatively, it is possible to create a custom job provisioner with this step.
Run the job. The pipeline script will create a secret with the same data in the namespace generated by the cd pipeline.
Note
Service account tokens are not supported.
Apart from running CD pipeline stages with the default logic, there is the ability to perform the following:
In order to have the ability to customize a stage logic, create a CD pipeline stage source as a Library:
Navigate to the Libraries section of the Admin Console and create a library with the Groovy-pipeline code language:
Note
If you clone the library, make sure that the correct source branch is selected.
Create library
Select the required fields to build your library:
Advanced settings
Go to the Continuous Delivery section of the Admin Console and create a CD pipeline with the library stage source and its branch:
Library source
Follow the steps below to add a new stage:
@Library(['edp-library-stages', 'edp-library-pipelines']) _\n\nDeploy()\n
import com.epam.edp.stages.impl.cd.Stage\n\n@Stage(name = \"notify\")\nclass Notify {\n Script script\n void run(context) {\n --------------- Put your own logic here ------------------\n script.println(\"Send notification logic\")\n --------------- Put your own logic here ------------------\n }\n}\nreturn Notify\n
Add a new stage to the STAGES parameter of the Jenkins job of your CD pipeline:
Stages parameter
Warning
To make this stage permanently present, please modify the job provisioner.
By default, the following stages are implemented in EDP pipeline framework:
Using one of these names for annotation in your own class will lead to redefining the default logic with your own.
Find below a sample of the possible flow of the redefining deploy stage:
@Library(['edp-library-stages', 'edp-library-pipelines']) _\n\nDeploy()\n
import com.epam.edp.stages.impl.cd.Stage\n\n@Stage(name = \"deploy\")\nclass CustomDeployStage {\n Script script\n\n void run(context) {\n --------------- Put your own logic here ------------------\n script.println(\"Custom deploy stage logic\")\n --------------- Put your own logic here ------------------\n }\n}\nreturn CustomDeployStage\n
Note
To add a new Custom Global Pipeline Library, please refer to the Add a New Custom Global Pipeline Library page.
To redefine any stage and add custom logic using global pipeline libraries, perform the steps below:
Navigate to the Libraries section of the Admin Console and create a library with the Groovy-pipeline code language:
Create library
Select the required fields to build your library:
Advanced settings
src/com/epam/edp/customStages/impl/cd/impl/
in the library repository, for instance: src/com/epam/edp/customStages/impl/cd/impl/EmailNotify.groovy
;EmailNotify.groovy
:package com.epam.edp.customStages.impl.cd.impl\n\nimport com.epam.edp.stages.impl.cd.Stage\n\n@Stage(name = \"notify\")\nclass Notify {\n Script script\n void run(context) {\n --------------- Put your own logic here ------------------\n script.println(\"Send notification logic\")\n --------------- Put your own logic here ------------------\n }\n}\n
Create a Jenkinsfile with default content and the added custom library to Jenkins:
@Library(['edp-library-stages', 'edp-library-pipelines', 'edp-custom-shared-library-name']) _\n\nDeploy()\n
Note
edp-custom-shared-library-name
is the name of your Custom Global Pipeline Library that should be added to the Jenkins Global Settings.
Add a new stage to the STAGES parameter of the Jenkins job of your CD pipeline:
Stages parameter
Warning
To make this stage permanently present, please modify the job provisioner.
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
Note
To add a new Custom Global Pipeline Library, please refer to the Add a New Custom Global Pipeline Library page.
By default, the following stages are implemented in EDP pipeline framework:
Using one of these names for annotation in your own class will lead to redefining the default logic with your own.
To redefine any stage and add custom logic using global pipeline libraries, perform the steps below:
Navigate to the Libraries section of the Admin Console and create a library with the Groovy-pipeline code language:
Create library
Select the required fields to build your library:
Advanced settings
src/com/epam/edp/customStages/impl/cd/impl/
in the library repository, for instance: src/com/epam/edp/customStages/impl/cd/impl/CustomDeployStage.groovy;
;CustomDeployStage.groovy
:package com.epam.edp.customStages.impl.cd.impl\n\nimport com.epam.edp.stages.impl.cd.Stage\n\n@Stage(name = \"deploy\")\nclass CustomDeployStage {\n Script script\n\n void run(context) {\n --------------- Put your own logic here ------------------\n script.println(\"Custom deploy stage logic\")\n --------------- Put your own logic here ------------------\n }\n}\n
Create a Jenkinsfile with default content and the added custom library to Jenkins:
@Library(['edp-library-stages', 'edp-library-pipelines', 'edp-custom-shared-library-name']) _\n\nDeploy()\n
Note
edp-custom-shared-library-name
is the name of your Custom Global Pipeline Library that should be added to the Jenkins Global Settings.
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
This chapter describes the main steps that should be followed when customizing a CI pipeline.
"},{"location":"user-guide/customize-ci-pipeline/#redefine-a-default-stage-logic-for-a-particular-application","title":"Redefine a Default Stage Logic for a Particular Application","text":"To redefine any stage and add custom logic, perform the steps below:
Open the GitHub repository:
Paste the copied skeleton from the reference stage and insert the necessary logic.
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
The stage logic structure is the following:
CustomSonar.groovy
import com.epam.edp.stages.impl.ci.ProjectType\nimport com.epam.edp.stages.impl.ci.Stage\n\n@Stage(name = \"sonar\", buildTool = [\"maven\"], type = [ProjectType.APPLICATION, ProjectType.AUTOTESTS, ProjectType.LIBRARY])\nclass CustomSonar {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn CustomSonar\n
Info
There is the ability to redefine the predefined EDP stage as well as to create it from scratch, it depends on the name that is used in the @Stage annotation. For example, using name = \"sonar\" will redefine an existing sonar stage with the same name, but using name=\"new-sonar\" will create a new stage.
By default, the following stages are implemented in EDP:
Mandatory points:
Open Jenkins and make sure that all the changes are correct after the completion of the customized pipeline.
To add a new stage for a particular application, perform the steps below:
Copy the part of a pipeline framework logic that cannot be predefined;
The stage logic structure is the following:
EmailNotify.groovy
import com.epam.edp.stages.impl.ci.ProjectType\nimport com.epam.edp.stages.impl.ci.Stage\n\n@Stage(name = \"email-notify\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass EmailNotify {\n Script script\n void run(context) {\n -------------------'Your custom logic here'\n }\n}\nreturn EmailNotify\n
Open the default set of stages and add a new one into the Default Value field by saving the respective type {\"name\": \"email-notify\"}, save the changes: Add stage
Open Jenkins to check the pipeline; as soon as the checkout stage is passed, the new stage will appear in the pipeline: Check stage
Warning
To make this stage permanently present, please modify the job provisioner.
Note
To add a new Custom Global Pipeline Library, please refer to the Add a New Custom Global Pipeline Library page.
To redefine any stage and add custom logic using global pipeline libraries, perform the steps below:
Open the GitHub repository:
/src/com/epam/edp/customStages/impl/ci/impl/stageName/
in the library repository, for instance: /src/com/epam/edp/customStages/impl/ci/impl/sonar/
;CustomSonar.groovy
.Paste the copied skeleton from the reference stage and insert the necessary logic.
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
The stage logic structure is the following:
CustomSonar.groovy
package com.epam.edp.customStages.impl.ci.impl.sonar\n\nimport com.epam.edp.stages.impl.ci.ProjectType\nimport com.epam.edp.stages.impl.ci.Stage\n\n@Stage(name = \"sonar\", buildTool = [\"maven\"], type = [ProjectType.APPLICATION, ProjectType.AUTOTESTS, ProjectType.LIBRARY])\nclass CustomSonar {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\n
Info
There is the ability to redefine the predefined EDP stage as well as to create it from scratch, it depends on the name that is used in the @Stage annotation. For example, using name = \"sonar\" will redefine an existing sonar stage with the same name, but using name=\"new-sonar\" will create a new stage.
By default, the following stages are implemented in EDP:
Mandatory points:
3.Open Jenkins and make sure that all the changes are correct after the completion of the customized pipeline.
"},{"location":"user-guide/customize-ci-pipeline/#add-a-new-stage-using-shared-library-via-custom-global-pipeline-libraries","title":"Add a New Stage Using Shared Library via Custom Global Pipeline Libraries","text":"Note
To add a new Custom Global Pipeline Library, please refer to the Add a New Custom Global Pipeline Library page.
To redefine any stage and add custom logic using global pipeline libraries, perform the steps below:
Open the GitHub repository:
/src/com/epam/edp/customStages/impl/ci/impl/stageName/
in the library repository, for instance: /src/com/epam/edp/customStages/impl/ci/impl/emailNotify/
;EmailNotify.groovy
.Copy the part of a pipeline framework logic that cannot be predefined;
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
The stage logic structure is the following:
EmailNotify.groovy
package com.epam.edp.customStages.impl.ci.impl.emailNotify\n\nimport com.epam.edp.stages.impl.ci.ProjectType\nimport com.epam.edp.stages.impl.ci.Stage\n\n@Stage(name = \"email-notify\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass EmailNotify {\n Script script\n void run(context) {\n -------------------'Your custom logic here'\n }\n}\n
Open the default set of stages and add a new one into the Default Value field by saving the respective type {\"name\": \"email-notify\"}, save the changes: Add stage
Open Jenkins to check the pipeline; as soon as the checkout stage is passed, the new stage will appear in the pipeline: Check stage
Warning
To make this stage permanently present, please modify the job provisioner.
This section contains the description of dockerbuild-verify, dockerfile-lint stages which one can use in Code Review pipeline.
These stages help to obtain a quick response on the validity of the code in the Code Review pipeline in Kubernetes for all types of applications supported by EDP out of the box.
Add stages
Inspect the functions performed by the following stages:
dockerbuild-verify stage collects artifacts and builds an image from the Dockerfile without push to registry. This stage is intended to check if the image is built.
dockerfile-lint stage launches the hadolint command in order to check the Dockerfile.
This section contains the description of the ecr-to-docker stage, available in the Build pipeline.
The ecr-to-docker stage is intended to perform the push of Docker images collected from the Amazon ECR cluster storage to Docker Hub repositories, where the image becomes accessible to everyone who wants to use it. This stage is optional and is designed for working with various EDP components.
Note
When pushing the image from ECR to Docker Hub using crane, the SHA-256 value remains unchanged.
To run the ecr-to-docker stage just for once, navigate to the Build with Parameters option, add this stage to the stages list, and click Build. To add the ecr-to-docker stage to the pipeline, modify the job provisioner.
Note
To push properly the Docker image from the ECR storage, the ecr-to-docker stage should follow the build-image-kaniko stage. Add custom lib2
The ecr-to-docker stage contains a specific script that launches the following actions:
Checks whether a similar image exists in the Docker Hub in order to avoid its overwriting.
The ecr-to-docker stage expects the authorization credentials to be added as Kubernetes secret into EDP-installed namespace. To create the dockerhub-credentials secret, run the following command:
kubectl -n edp create secret generic dockerhub-credentials \\\n --from-literal=accesstoken=<dockerhub_access_token> \\\n --from-literal=account=<dockerhub_account_name> \\\n --from-literal=username=<dockerhub_user_name>\n
Note
Git Server is responsible for integration with Version Control System, whether it is GitHub, GitLab or Gerrit.
The Git Server is set via the global.gitProvider parameter of the values.yaml file.
To view the current Git Server, you can open EDP
-> Configuration
-> Git Servers
and inspect the following properties:
Git Server menu
To view authentication data that is used to connect to the Git server, use kubectl describe
command as follows:
kubectl describe GitServer git_server_name -n edp\n
"},{"location":"user-guide/git-server-overview/#delete-git-server","title":"Delete Git Server","text":"To remove a Git Server from the Git Servers list, utilize the kubectl delete
command as follows:
kubectl delete GitServer git_server_name -n edp\n
"},{"location":"user-guide/git-server-overview/#related-articles","title":"Related Articles","text":"This page is dedicated to the GitOps section of the Configuration tab, the process of establishing the GitOps repository, outline benefits it extends to users within the platform capabilities. GitOps, short for \"Git Operations\", is a modern approach to managing and automating infrastructure and application deployments. In GitOps, the desired state of your environment is declared and stored in a Git repository. With GitOps, you can ensure that your infrastructure and applications are always in sync with your intended configurations and readily adapt to changing requirements.
"},{"location":"user-guide/gitops/#overview","title":"Overview","text":"The purpose of the GitOps section is to provide users with the ability to customize the state of their environments with the help of GitOps approach that enables you to store your entire deployment configuration in a Git repository, providing version control for changes, consistent collaboration, and automated deployments. Enforcing GitOps allows you to declaratively define and automate your configurations, ensuring consistency, version control, and collaboration within your team.
To open the GitOps subsection, navigate to EDP Portal
-> EDP
-> Components
-> GitOps
:
GitOps section
"},{"location":"user-guide/gitops/#add-gitops-repository","title":"Add GitOps Repository","text":"To add a GitOps repository, follow the steps below:
Navigate to EDP
-> Components
-> GitOps
. Click the + Add GitOps Repository button:
Add GitOps repository
Fill in the required fields (in case VCS supports nesting) and click Save:
Required fields
Check the GitOps repository connected to the platform:
System Codebase
In addition to it, the system Codebase is called the same as the GitOps repository will be added to the Codebase list of the Components section:
GitOps Codebase
Note
The platform allows only one GitOps repository at a time.
"},{"location":"user-guide/gitops/#gitops-usage","title":"GitOps Usage","text":"Once the GitOps repository is added to the platform, you can set custom parameters for the deployed Helm Chart. To redefine the parameters, follow the steps below:
In the GitOps repository, create the values.yaml file according to the <pipeline-name>/<stage-name>/<application-name>-values.yaml
pattern.
In the created values.yaml file, enter the parameters with their custom values.
Navigate to the Environments section. Open the created environment, open its stage and deploy it with the Values override checkbox selected as it is shown below:
GitOps Codebase
In case you need to delete the GitOps repository, do the following:
Delete the GitOps repository in the Git provider.
Delete the Codebase custom resource using the kubectl delete
command:
kubectl delete Codebase edp-gitops -n edp\n
The Helm release deletion stage provides the ability to remove Helm releases from the namespace.
Note
Pay attention that this stages will remove all Helm releases from the namespace. To avoid loss of important data, before using this stage, make the necessary backups.
To remove Helm releases, follow the steps below:
Add the following step to the CD pipeline {\"name\":\"helm-uninstall\",\"step_name\":\"helm-uninstall\"}
. Alternatively, with this step, it is possible to create a custom job provisioner.
Run the job. The pipeline script will remove Helm releases from the namespace.
This section contains the description of the helm-lint and helm-docs stages that can be used in the Code Review pipeline.
The stages help to obtain a quick response on the validity of the helm chart code and documentation in the Code Review pipeline.
Inspect the functions performed by the following stages:
helm-lint stage launches the ct lint --charts-deploy-templates/ command in order to validate the chart.
Helm lint
See the current scheme:
View: chart_schema.yamlname: str()\nhome: str()\nversion: str()\ntype: str()\napiVersion: str()\nappVersion: any(str(), num())\ndescription: str()\nkeywords: list(str(), required=False)\nsources: list(str(), required=True)\nmaintainers: list(include('maintainer'), required=True)\ndependencies: list(include('dependency'), required=False)\nicon: str(required=False)\nengine: str(required=False)\ncondition: str(required=False)\ntags: str(required=False)\ndeprecated: bool(required=False)\nkubeVersion: str(required=False)\nannotations: map(str(), str(), required=False)\n---\nmaintainer:\n name: str(required=True)\n email: str(required=False)\n url: str(required=False)\n---\ndependency:\n name: str()\n version: str()\n repository: str()\n condition: str(required=False)\n tags: list(str(), required=False)\n enabled: bool(required=False)\n import-values: any(list(str()), list(include('import-value')), required=False)\n alias: str(required=False)\n
To get more information about the chart testing lint, please refer to the ct_lint documentation.
helm-docs stage helps to validate the generated documentation for the Helm deployment templates in the Code Review pipeline for all types of applications supported by EDP. This stage launches the helm-docs command in order to validate the chart documentation file existence and verify its relevance.
Requirements: helm-docs v1.10.0
Note
The helm-docs stage is optional. To extend the pipeline with an additional stage, please refer to the Configure Code Review Pipeline page.
Helm docs
Note
The example of the generated documentation.
This section describes the subsequent possible actions that can be performed with the newly added or existing infrastructures.
"},{"location":"user-guide/infrastructure/#check-and-remove-application","title":"Check and Remove Application","text":"As soon as the infrastructure is successfully provisioned, the following will be created:
The added application will be listed in the Applications list allowing you to do the following:
Applications menu
There are also options to sort the infrastructures:
EDP Portal provides the ability to enable, disable or edit the Jira Integration functionality for infrastructures.
To edit an infrastructure directly from the infrastructures overview page or when viewing the infrastructure data:
Edit infrastructure on the Infrastructures overview page
Edit infrastructure when viewing the infrastructure data
To enable Jira integration, in the Edit Infrastructure dialog do the following:
Edit infrastructure
a. Mark the Integrate with Jira server check box and fill in the necessary fields. Please see steps d-h on the Add Infrastructure page.
b. Select the Apply button to apply the changes.
To disable Jira integration, in the Edit Infrastructure dialog do the following:
a. Uncheck the Integrate with Jira server check box.
b. Select the Apply button to apply the changes.
To create, edit and delete infrastructure branches, please refer to the Manage Branches page.
This section describes the subsequent possible actions that can be performed with the newly added or existing libraries.
"},{"location":"user-guide/library/#check-and-remove-library","title":"Check and Remove Library","text":"As soon as the library is successfully provisioned, the following will be created:
Info
To navigate quickly to OpenShift, Tekton, Gerrit, SonarQube, Nexus, and other resources, click the Overview section on the navigation bar and hit the necessary link.
The added library will be listed in the Libraries list allowing to do the following:
Library menu
Create another library by clicking the plus sign icon on the right side of the screen and performing the same steps as described on the Add Library page.
Open library data by clicking its link name. Once clicked, the following blocks will be displayed:
Delete Library - remove library by clicking the vertical ellipsis button and then selecting Delete.
Note
The library that is used in a CD pipeline cannot be removed.
There are also options to sort the libraries:
EDP Portal provides the ability to enable, disable or edit the Jira Integration functionality for libraries.
To edit a library directly from the Libraries overview page or when viewing the library data:
Select Edit in the options icon menu:
Edit library on the libraries overview page
Edit library when viewing the library data
To enable Jira integration, in the Edit Library dialog do the following:
Edit library
a. Mark the Integrate with Jira server check box and fill in the necessary fields. Please see the steps d-h of the Add Library page.
b. Select the Apply button to apply the changes.
To disable Jira integration, in the Edit Library dialog do the following:
a. Uncheck the Integrate with Jira server check box.
b. Select the Apply button to apply the changes.
As a result, the necessary changes will be applied.
To create, edit and delete library branches, please refer to the Manage Branches page.
This page describes how to manage branches in the created component, whether it is an application, library, autotest or infrastructure.
"},{"location":"user-guide/manage-branches/#add-new-branch","title":"Add New Branch","text":"Note
When working with libraries, pay attention when specifying the branch name: the branch name is involved in the formation of the library version, so it must comply with the Semantic Versioning rules for the library.
When adding a component, the default branch is a master branch. In order to add a new branch, follow the steps below:
Navigate to the Branches block by clicking the component name link in the Components list.
Select the options icon related to the necessary branch and then select Create:
Add branch
Click Edit YAML in the upper-right corner of the dialog to open the YAML editor and add a branch. Otherwise, fill in the required fields in the dialog:
New branch
a. Release Branch - select the Release Branch check box if you need to create a release branch.
b. Branch name - type the branch name. Pay attention that this field remains static if you create a release branch. For the Clone and Import strategies: if you want to use the existing branch, enter its name into this field.
c. From Commit Hash - paste the commit hash from which the branch will be created. For the Clone and Import strategies: Note that if the From Commit Hash field is empty, the latest commit from the branch name will be used.
d. Branch version - enter the necessary branch version for the artifact. The Release Candidate (RC) postfix is concatenated to the branch version number.
e. Default branch version - type the branch version that will be used in a master branch after the release creation. The Snapshot postfix is concatenated to the master branch version number.
f. Click the Apply button and wait until the new branch will be added to the list.
Info
Adding of a new branch is indicated in the context of the EDP versioning type.
The default component repository is cloned and changed to the new indicated version before the build, i.e. the new indicated version will not be committed to the repository; thus, the existing repository will keep the default version.
"},{"location":"user-guide/manage-branches/#build-branch","title":"Build Branch","text":"In order to build branch from the latest commit, do the following:
Select the options icon related to the necessary branch and then select Build:
Build branch
The pipeline run status is displayed near the branch name in the Branches block:
Pipeline run status in EDP Portal
The corresponding item appears on the Tekton Dashboard in the PipelineRuns section:
Pipeline run status in Tekton
"},{"location":"user-guide/manage-branches/#delete-branch","title":"Delete Branch","text":"Note
The default master branch cannot be removed.
In order to delete the added branch with the corresponding record in the EDP Portal database, do the following:
Select the options icon related to the necessary branch and then select Delete:
Delete branch
This page describes actions that can be performed to an already created environment. If no environments are created yet, navigate to the Add Environment page.
Environments page
Open environment data by clicking its link name.
Edit the environment by selecting the options icon next to its name in the environments list, and then selecting Edit. For details see the Edit Existing Environment section.
Delete the added environment by selecting the options icon next to its name in the environment list, and then selecting Delete.
Note
Please keep in mind that after deleting the environment, all the created resources within the environment will be deleted.
Sort the existing environments in a table by clicking the sorting icons in the table header. When sorting by name, the environments will be displayed in alphabetical order. You can also sort the environments by their status.
Search the necessary environment by the namespace or by entering the corresponding name, language or the build tool into the Filter tool.
Select a number of environment displayed per page (15, 25 or 50 rows) and navigate between pages if the number of environments exceeds the capacity of a single page.
To view environment details, click the environment name in the environments list. Once clicked, the following data will be displayed:
Environment details
a. Allows to view environment in Argo CD, view its metadata (generation, finalizers, namespace, etc.).
b. Shows application/stage status.
c. Shows application/stage names. Once clicked, navigates you to the application data or stage details.
d. Allows to create a new stage.
e. Allows to view environment data in Argo CD, Grafana, Kibana and shows in which cluster the environment is deployed in.
f. Allows to edit or delete a stage.
"},{"location":"user-guide/manage-environments/#edit-existing-environment","title":"Edit Existing Environment","text":"Edit the environment directly from the environment overview page or when viewing the environment data:
Select Edit in the options icon menu next to the environment name:
Edit environment on the environment overview page
Edit environment when viewing the environment data
Apply the necessary changes (edit the list of applications for deploy, application branches, and promotion in the pipeline). Add new extra stages by clicking the plus sign icon and filling in the application branch and promotion in the pipeline.
Edit environment dialog
Select the Apply button to confirm the changes.
In order to create a new stage for the existing environment, follow the steps below:
Navigate to the Stages block by clicking the environment name link in the environments list.
Add environment stage
Select Create to open the Create stage dialog.
Fill in the required fields in the dialog. Alternatively, click Edit YAML in the upper-right corner of the Create stage dialog to open the YAML editor and add a stage. Please see the Stages Menu section for details.
Click the Apply button.
In order to edit a stage for the existing environment, follow the steps below:
Navigate to the Stages block by clicking the environment name link in the environments list.
Edit environment stage
Select the options icon related to the necessary stage and then select Edit.
Edit environment stage dialog
In the Edit Stage dialog, change the stage trigger type. See more about this field in the Stages Menu section.
Click the Apply button.
Note
You cannot remove the last stage, as the environment does not exist without at least one.
In order to delete a stage for the existing environment, follow the steps below:
Navigate to the Stages block by clicking the environment name link in the environments list.
Delete environment stage
Select the options icon related to the necessary stage and then select Delete. After the confirmation, the CD stage is deleted with all its components: database record, Tekton pipeline, and cluster namespace.
To view the environment stage data for the existing environment, follow the steps below:
Navigate to the Stages block by clicking the environment name link in the environments list.
Expand environment stage
Click stage name. The following blocks will be displayed:
environment stage overview
To deploy an application, follow the steps below:
Deploy the promoted application
Navigate to the Applications block of the stage and select an application.
Select the image stream version from the drop-down list.
(Optional) Enable setting custom values for Helm Charts. For more details, please refer to the Manage GitOps page.
Click Deploy. The application will be deployed in the Argo CD tool as well.
Info
In case of using OpenShift internal registry, if the deployment fails with the ImagePullBackOff error, delete the pod that was created for this application.
To update or uninstall the application, select Update or Uninstall.
Update or uninstall the application
As a result, the application will be updated or uninstalled in the Argo CD tool as well.
Note
In a nutshell, the Update button updates your image version in the Helm chart, whereas the Uninstall button deletes the Helm chart from the namespace where the Argo CD application is deployed.
"},{"location":"user-guide/manage-environments/#troubleshoot-application","title":"Troubleshoot Application","text":"There is a couple of EDP Portal capabilities that will help in monitoring and troubleshooting deployed applications, namely, terminal and logs.
To inspect the deployed application in EDP Portal, take the following steps:
Open the application logs by clicking the Show Logs
button:
Show Logs button
Inspect the shown logs:
Inspect Logs
Open the application terminal by clicking the Show Terminal
button:
Show Terminal button
Operate the terminal to fix the problem if any:
Inspect application
The EDP Marketplace offers a range of Templates, predefined tools and settings for creating software. These Templates speed up development, minimize errors, and ensure consistency. A key EDP Marketplace feature is customization. Organizations can create and share their own Templates, finely tuned to their needs. Each Template serves as a tailored blueprint of tools and settings.
These tailored Templates include preset CI/CD pipelines, automating your development workflows. From initial integration to final deployment, these processes are efficiently managed. Whether for new applications or existing ones, these templates enhance processes, save time, and ensure consistency.
To see the Marketplace section, navigate to the Main menu -> EDP -> Marketplace. General look of the Marketplace section is described below:
Marketplace section (listed view)
There is also a possibility to switch into the tiled view instead of the listed one:
Marketplace section (tiled view)
To view the details of a marketplace item, simply click on its name:
Item details
The details window shows supplemental information, such as item's author, keywords, release version and the link to the repository it is located in. The window also contains the Create from template button that allows users to create the component by the chosen template. The procedure of creating new components is described in the Add Component via Marketplace page.
"},{"location":"user-guide/marketplace/#related-articles","title":"Related Articles","text":"Open Policy Agent (OPA) is a policy engine that provides:
EPAM Delivery Platform ensures the implemented Open Policy Agent support allowing to work with Open Policy Agent bundles that is processed by means of stages in the Code Review and Build pipelines. These pipelines are expected to be created after the Rego OPA Library is added.
"},{"location":"user-guide/opa-stages/#code-review-pipeline-stages","title":"Code Review Pipeline Stages","text":"In the Code Review pipeline, the following stages are available:
checkout stage, a standard step during which all files are checked out from a selected branch of the Git repository.
tests stage containing a script that performs the following actions:
2.1. Runs policy tests.
2.2. Converts OPA test results into JUnit format.
2.3. Publishes JUnit-formatted results to Jenkins.
In the Build pipeline, the following stages are available:
checkout stage, a standard step during which all files are checked out from a selected branch of the Git repository.
get-version optional stage, a step where library version is determined either via:
2.1. Standard EDP versioning functionality.
2.2. Manually specified version. In this case .manifest file in a root directory MUST be provided. File must contain a JSON document with revision field. Minimal example: { \"revision\": \"1.0.0\" }\"
.
tests stage containing a script that performs the following actions: 3.1. Runs policy tests. 3.2. Converts OPA test results into JUnit format. 3.3. Publishes JUnit-formatted results to Jenkins.
git-tag stage, a standard step where git branch is tagged with a version.
This chapter provides detailed information about the EDP pipeline framework concepts and parts, as well as the accurate data about the Code Review
, Build
and Deploy
pipelines with the respective stages.
Note
The whole logic is applied to Jenkins as it is the main tool for the CI/CD processes organization.
EDP pipeline framework basic
The general EDP Pipeline Framework consists of several parts:
Jenkinsfile example
Pipeline script
"},{"location":"user-guide/pipeline-framework/#cicd-jobs-comparison","title":"CI/CD Jobs Comparison","text":"Explore the CI and CD job comparison. Please note that the dynamic stages order can be changed, meanwhile, the predefined stages order in the reference pipeline cannot be changed, i.e. only the predefined stages set can be run.
CI/CD jobs comparison
"},{"location":"user-guide/pipeline-framework/#context","title":"Context","text":"Context - a variable that stores and transfers all necessary parameters between stages that are used by pipeline during performing.
Note
If the input context isn't transferred, the stage will be failed.
"},{"location":"user-guide/pipeline-framework/#annotations-for-cicd-stages","title":"Annotations for CI/CD Stages","text":"Annotation for CI Stages:
Annotation for CD Stages:
CodeReview() \u2013 a function that allows using the EDP implementation for the Code Review pipeline.
Note
All values of different parameters that are used during the pipeline execution are stored in the \"Map\" context.
The Code Review pipeline consists of several steps:
On the master:
On a particular Jenkins agent that depends on the build tool:
Using in pipelines - @Library(['edp-library-pipelines@version'])
The corresponding enums, interfaces, classes, and their methods can be used separately from the EDP Pipelines library function (please refer to Table 1 and Table 2).
Table 1. Enums and Interfaces with the respective properties, methods, and examples.
Enums Interfaces PlatformType: - OPENSHIFT - KUBERNETES JobType: - CODEREVIEW - BUILD - DEPLOY BuildToolType: - MAVEN - GRADLE - NPM - DOTNET Platform() - contains methods for working with platform CLI. At the moment only OpenShift is supported. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Methods: getJsonPathValue(String k8s_kind, String k8s_kind_name, String jsonPath): return String value of specific parameter of particular object using jsonPath utility. Example:context.platform.getJsonPathValue(''cm'',
''project-settings'', ''.data.username'')
. BuildTool() - contains methods for working with different buildTool from ENUM BuildToolType. Should be invoked on Jenkins build agents. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Nexus object - Object of class Nexus. Methods: init: return parameters of buildTool that are needed for running stages. Example: context.buildTool = new BuildToolFactory().
getBuildToolImpl
(context.application.config.build_tool, this,
context.nexus) context.buildTool.init()
. Table 2. Classes with the respective properties, methods, and examples.
Classes Description (properties, methods, and examples) PlatformFactory() - Class that contains methods getting an implementation of CLI of the platform. At the moment OpenShift and Kubernetes are supported. Methods:getPlatformImpl(PlatformType platform, Script script): return Class Platform
. Example: context.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)
. Application(String name, Platform platform, Script script) - Class that describes the application object. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Platform platform - Object of a class Platform(). String name - Name for the application for creating an object. Map config - Map of configuration settings for the particular application that is loaded from config map project-settings. String version - Application version, initially empty. Is set on the get-version step. String deployableModule - The name of the deployable module for multi-module applications, initially empty. String buildVersion - Version of the built artifact, contains build number of Job initially empty. String deployableModuleDir - The name of deployable module directory for multi-module applications, initially empty. Array imageBuildArgs - List of arguments for building an application Docker image. Methods: setConfig(String gerrit_autouser, String gerrit_host, String gerrit_sshPort, String gerrit_project): set the config property with values from config map. Example: context.application = new Application(context.job, context.gerrit.project, context.platform, this) context.application.setConfig(context.gerrit.autouser, context.gerrit.host, context.gerrit.sshPort, context.gerrit.project)
Job(type: JobType.value, platform: Platform, script: Script) - Class that describes the Gerrit tool. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Platform platform - Object of a class Platform(). JobType.value type. String deployTemplatesDirectory - The name of the directory in application repository where deploy templates are located. It can be set for a particular Job through DEPLOY_TEMPLATES_DIRECTORY parameter. String edpName - The name of the EDP Project. Map stages - Contains all stages in JSON format that is retrieved from Jenkins job env variable. String envToPromote - The name of the environment for promoting images. Boolean promoteImages - Defines whether images should be promoted or not. Methods: getParameterValue(String parameter, String defaultValue = null): return parameter of ENV variable of Jenkins job. init(): set all the properties of the Job object. setDisplayName(String displayName): set display name of the Jenkins job. setDescription(String description, Boolean addDescription = false): set new or add to the existing description of the Jenkins job. printDebugInfo(Map context): print context info to the log of Jenkins' job. runStage(String stage_name, Map context): run the particular stage according to its name. Example: context.job = new Job(JobType.CODEREVIEW.value,
context.platform, this)
context.job.init()
context.job.printDebugInfo(context)
context.job.setDisplayName(\"test\")
context.job.setDescription(\"Name: ${context.application.config.name}\")
Gerrit(Job job, Platform platform, Script script) - Class that describes the Gerrit tool. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String credentialsId - Credential Id in Jenkins for Gerrit.String autouser - Username of an auto user in Gerrit for integration with Jenkins.String host - Gerrit host.String project - the project name of the built application.String branch - branch to build the application from.String changeNumber - change number of Gerrit commit.String changeName - change name of Gerrit commit.String refspecName - refspecName of Gerrit commit.String sshPort - Gerrit ssh port number.String patchsetNumber - patchsetNumber of Gerrit commit.Methods: init(): set all the properties of Gerrit object. Example: context.gerrit = new Gerrit(context.job, context.platform, this)
context.gerrit.init()
Nexus(Job job, Platform platform, Script script) - Class that describes the Nexus tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String autouser - Username of an auto user in Nexus for integration with Jenkins.String credentialsId - Credential Id in Jenkins for Nexus.String host - Nexus host.String port - Nexus http(s) port.String repositoriesUrl - Base URL of repositories in Nexus.String restUrl - URL of Rest API.Methods:init(): set all the properties of Nexus objectExample: context.nexus = new Nexus(context.job, context.platform, this)
context.nexus.init()
Sonar(Job job, Platform platform, Script script) - Class that describes the Sonar tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String route - External route of the sonar application.Methods:init(): set all the properties of Sonar objectExample: context.sonar = new Sonar(context.job, context.platform, this)
context.sonar.init()
"},{"location":"user-guide/pipeline-framework/#code-review-pipeline-stages","title":"Code Review Pipeline Stages","text":"Each EDP stage implementation has run method that is as input parameter required to pass the \"Map\" context with different keys. Some stages can implement the logic for several build tools and application types, some of them are specific.
The Code Review pipeline includes the following default stages: Checkout \u2192 Gerrit Checkout \u2192 Compile \u2192 Tests \u2192 Sonar.
Info
To get the full description of every stage, please refer to the EDP Stages Framework section.
"},{"location":"user-guide/pipeline-framework/#how-to-redefine-or-extend-the-edp-pipeline-stages-library","title":"How to Redefine or Extend the EDP Pipeline Stages Library","text":"Inspect the points below to redefine or extend the EDP Pipeline Stages Library:
Redefinition:
import com.epam.edp.stages.ProjectType\nimport com.epam.edp.stages.Stage\n@Stage(name = \"compile\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass CustomBuildMavenApplication {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn CustomBuildMavenApplication\n
Extension:
import com.epam.edp.stages.ProjectType\nimport com.epam.edp.stages.Stage\n@Stage(name = \"new-stage\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass NewStageMavenApplication {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn NewStageMavenApplication\n
"},{"location":"user-guide/pipeline-framework/#using-edp-stages-library-in-the-pipeline","title":"Using EDP Stages Library in the Pipeline","text":"In order to use the EDP stages, the created pipeline should fit some requirements, that`s why a developer has to do the following:
context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n
After that, there is the ability to run any EDP stage beforehand by defining a necessary context: context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)
For instance, the pipeline can look like:
@Library(['edp-library-stages']) _\n\nimport com.epam.edp.stages.StageFactory\nimport org.apache.commons.lang.RandomStringUtils\n\ncontext = [:]\n\nnode('maven') {\n context.workDir = new File(\"/tmp/${RandomStringUtils.random(10, true, true)}\")\n context.workDir.deleteDir()\n\n context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n\n context.gerrit = [:]\n context.application = [:]\n context.application.config = [:]\n context.buildTool = [:]\n context.nexus = [:]\n\n\n\n stage(\"checkout\") {\n context.gerrit.branch = \"master\"\n context.gerrit.credentialsId = \"jenkins\"\n context.application.config.cloneUrl = \"ssh://jenkins@gerrit:32092/sit-718-cloned-java-maven-project\"\n context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)\n }\n\n\n stage(\"compile\") {\n context.buildTool.command = \"mvn\"\n context.nexus.credentialsId = \"nexus\"\n context.factory.getStage(\"compile\",\"maven\",\"application\").run(context)\n }\n}\n
Or in a declarative way:
@Library(['edp-library-stages']) _\n\nimport com.epam.edp.stages.StageFactory\nimport org.apache.commons.lang.RandomStringUtils\n\ncontext = [:]\n\npipeline {\n agent { label 'maven' }\n stages {\n stage('Init'){\n steps {\n script {\n context.workDir = new File(\"/tmp/${RandomStringUtils.random(10, true, true)}\")\n context.workDir.deleteDir()\n context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n\n context.gerrit = [:]\n context.application = [:]\n context.application.config = [:]\n context.buildTool = [:]\n context.nexus = [:]\n }\n }\n }\n\n stage(\"Checkout\") {\n steps {\n script {\n context.gerrit.branch = \"master\"\n context.gerrit.credentialsId = \"jenkins\"\n context.application.config.cloneUrl = \"ssh://jenkins@gerrit:32092/sit-718-cloned-java-maven-project\"\n context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)\n }\n }\n }\n\n stage('Compile') {\n steps {\n script {\n context.buildTool.command = \"mvn\"\n context.nexus.credentialsId = \"nexus\"\n context.factory.getStage(\"compile\",\"maven\",\"application\").run(context)\n }\n }\n }\n }\n}\n
"},{"location":"user-guide/pipeline-framework/#build-pipeline","title":"Build Pipeline","text":"Build() \u2013 a function that allows using the EDP implementation for the Build pipeline. All values of different parameters that are used during the pipeline execution are stored in the \"Map\" context.
The Build pipeline consists of several steps:
On the master:
On a particular Jenkins agent that depends on the build tool:
Using in pipelines - @Library(['edp-library-pipelines@version'])
The corresponding enums, interfaces, classes, and their methods can be used separately from the EDP Pipelines library function (please refer to Table 3 and Table 4).
Table 3. Enums and Interfaces with the respective properties, methods, and examples.
Enums Interfaces PlatformType:- OPENSHIFT- KUBERNETESJobType:- CODEREVIEW- BUILD- DEPLOYBuildToolType:- MAVEN- GRADLE- NPM- DOTNET Platform() - contains methods for working with platform CLI. At the moment only OpenShift is supported.Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Methods:getJsonPathValue(String k8s_kind, String k8s_kind_name, String jsonPath): return String value of specific parameter of particular object using jsonPath utility.Example:context.platform.getJsonPathValue(\"cm\",\"project-settings\",
\".data.username\")
BuildTool() - contains methods for working with different buildTool from ENUM BuildToolType. Should be invoked on Jenkins build agents.Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Nexus object - Object of class Nexus. See description below:Methods:init: return parameters of buildTool that are needed for running stages.Example:context.buildTool = new BuildToolFactory().getBuildToolImpl
(context.application.config.build_tool, this,
context.nexus)context.buildTool.init()
Table 4. Classes with the respective properties, methods, and examples. Classes Description (properties, methods, and examples) PlatformFactory() - Class that contains methods getting an implementation of CLI of the platform. At the moment OpenShift and Kubernetes are supported. Methods:getPlatformImpl(PlatformType platform, Script script): return Class PlatformExample:context.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)
Application(String name, Platform platform, Script script) - Class that describes the application object. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().String name - Name for the application for creating an object.Map config - Map of configuration settings for the particular application that is loaded from config map project-settings.String version - Application version, initially empty. Is set on the get-version step.String deployableModule - The name of the deployable module for multi-module applications, initially empty.String buildVersion - Version of the built artifact, contains build number of Job initially empty.String deployableModuleDir - The name of deployable module directory for multi-module applications, initially empty.Array imageBuildArgs - List of arguments for building the application Docker image.Methods:setConfig(String gerrit_autouser, String gerrit_host, String gerrit_sshPort, String gerrit_project): set the config property with values from config map.Example:context.application = new Application(context.job, context.gerrit.project, context.platform, this) context.application.setConfig(context.gerrit.autouser, context.gerrit.host, context.gerrit.sshPort, context.gerrit.project)
Job(type: JobType.value, platform: Platform, script: Script) - Class that describes the Gerrit tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().JobType.value type.String deployTemplatesDirectory - The name of the directory in application repository, where deploy templates are located. It can be set for a particular Job through DEPLOY_TEMPLATES_DIRECTORY parameter.String edpName - The name of the EDP Project.Map stages - Contains all stages in JSON format that is retrieved from Jenkins job env variable.String envToPromote - The name of the environment for promoting images.Boolean promoteImages - Defines whether images should be promoted or not.Methods:getParameterValue(String parameter, String defaultValue = null): return parameter of ENV variable of Jenkins job.init(): set all the properties of the Job object.setDisplayName(String displayName): set display name of the Jenkins job.setDescription(String description, Boolean addDescription = false): set new or add to the existing description of the Jenkins job.printDebugInfo(Map context): print context info to the log of Jenkins' job.runStage(String stage_name, Map context): run the particular stage according to its name.Example:context.job = new Job(JobType.CODEREVIEW.value, context.platform, this) context.job.init() context.job.printDebugInfo(context) context.job.setDisplayName(\"test\") context.job.setDescription(\"Name: ${context.application.config.name}\")
Gerrit(Job job, Platform platform, Script script) - Class that describes the Gerrit tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String credentialsId - Credentials Id in Jenkins for Gerrit.String autouser - Username of an auto user in Gerrit for integration with Jenkins.String host - Gerrit host.String project - the project name of the built application.String branch - branch to build an application from.String changeNumber - change number of Gerrit commit.String changeName - change name of Gerrit commit.String refspecName - refspecName of Gerrit commit.String sshPort - Gerrit ssh port number.String patchsetNumber - patchsetNumber of Gerrit commit.Methods:init(): set all the properties of Gerrit objectExample: context.gerrit = new Gerrit(context.job, context.platform, this) context.gerrit.init()
Nexus(Job job, Platform platform, Script script) - Class that describes the Nexus tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String autouser - Username of an auto user in Nexus for integration with Jenkins.String credentialsId - Credentials Id in Jenkins for Nexus.String host - Nexus host.String port - Nexus http(s) port.String repositoriesUrl - Base URL of repositories in Nexus.String restUrl - URL of Rest API.Methods:init(): set all the properties of the Nexus object.Example:context.nexus = new Nexus(context.job, context.platform, this) context.nexus.init()
Sonar(Job job, Platform platform, Script script) - Class that describes the Sonar tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String route - External route of the sonar application.Methods:init(): set all the properties of Sonar object.Example:context.sonar = new Sonar(context.job, context.platform, this) context.sonar.init()
"},{"location":"user-guide/pipeline-framework/#build-pipeline-stages","title":"Build Pipeline Stages","text":"Each EDP stage implementation has run method that is as input parameter required to pass a context map with different keys. Some stages can implement the logic for several build tools and application types, some of them are specific.
The Build pipeline includes the following default stages: Checkout \u2192 Gerrit Checkout \u2192 Compile \u2192 Get version \u2192 Tests \u2192 Sonar \u2192 Build \u2192 Build Docker Image \u2192 Push \u2192 Git tag.
Info
To get the full description of every stage, please refer to the EDP Stages Framework section.
"},{"location":"user-guide/pipeline-framework/#how-to-redefine-or-extend-edp-pipeline-stages-library","title":"How to Redefine or Extend EDP Pipeline Stages Library","text":"Inspect the points below to redefine or extend the EDP Pipeline Stages Library:
Redefinition:
import com.epam.edp.stages.ProjectType\nimport com.epam.edp.stages.Stage\n@Stage(name = \"compile\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass CustomBuildMavenApplication {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn CustomBuildMavenApplication\n
Extension:
import com.epam.edp.stages.ProjectType\nimport com.epam.edp.stages.Stage\n@Stage(name = \"new-stage\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass NewStageMavenApplication {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn NewStageMavenApplication\n
"},{"location":"user-guide/pipeline-framework/#using-edp-stages-library-in-the-pipeline_1","title":"Using EDP Stages Library in the Pipeline","text":"In order to use the EDP stages, the created pipeline should fit some requirements, that`s why a developer has to do the following:
context.factory = new StageFactory(script: this)\ncontext.factory.loadEdpStages().each() { context.factory.add(it) }\n
After that, there is the ability to run any EDP stage beforehand by defining a requirement context context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)
For instance, the pipeline can look like:
@Library(['edp-library-stages']) _\n\nimport com.epam.edp.stages.StageFactory\nimport org.apache.commons.lang.RandomStringUtils\n\ncontext = [:]\n\nnode('maven') {\n context.workDir = new File(\"/tmp/${RandomStringUtils.random(10, true, true)}\")\n context.workDir.deleteDir()\n\n context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n\n context.gerrit = [:]\n context.application = [:]\n context.application.config = [:]\n context.buildTool = [:]\n context.nexus = [:]\n\n\n\n stage(\"checkout\") {\n context.gerrit.branch = \"master\"\n context.gerrit.credentialsId = \"jenkins\"\n context.application.config.cloneUrl = \"ssh://jenkins@gerrit:32092/sit-718-cloned-java-maven-project\"\n context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)\n }\n\n\n stage(\"compile\") {\n context.buildTool.command = \"mvn\"\n context.nexus.credentialsId = \"nexus\"\n context.factory.getStage(\"compile\",\"maven\",\"application\").run(context)\n }\n}\n
Or in a declarative way:
@Library(['edp-library-stages']) _\n\nimport com.epam.edp.stages.StageFactory\nimport org.apache.commons.lang.RandomStringUtils\n\ncontext = [:]\n\npipeline {\n agent { label 'maven' }\n stages {\n stage('Init'){\n steps {\n script {\n context.workDir = new File(\"/tmp/${RandomStringUtils.random(10, true, true)}\")\n context.workDir.deleteDir()\n context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n\n context.gerrit = [:]\n context.application = [:]\n context.application.config = [:]\n context.buildTool = [:]\n context.nexus = [:]\n }\n }\n }\n\n stage(\"Checkout\") {\n steps {\n script {\n context.gerrit.branch = \"master\"\n context.gerrit.credentialsId = \"jenkins\"\n context.application.config.cloneUrl = \"ssh://jenkins@gerrit:32092/sit-718-cloned-java-maven-project\"\n context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)\n }\n }\n }\n\n stage('Compile') {\n steps {\n script {\n context.buildTool.command = \"mvn\"\n context.nexus.credentialsId = \"nexus\"\n context.factory.getStage(\"compile\",\"maven\",\"application\").run(context)\n }\n }\n }\n }\n}\n
"},{"location":"user-guide/pipeline-framework/#edp-library-stages-description","title":"EDP Library Stages Description","text":"Using in pipelines - @Library(['edp-library-stages@version'])
The corresponding enums, classes, interfaces and their methods can be used separately from the EDP Stages library function (please refer to Table 5).
Table 5. Enums and Classes with the respective properties, methods, and examples.
Enums Classes ProjectType: - APPLICATION - AUTOTESTS - LIBRARY StageFactory() - Class that contains methods getting an implementation of the particular stage either EDP from shared library or custom from application repository.Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Map stages - Map of stages implementations.Methods:loadEdpStages(): return a list of Classes that describes EDP stages implementations.loadCustomStages(String directory): return a list of Classes that describes EDP custom stages from application repository from \"directory\". The \"directory\" should have an absolute path to files with classes of custom stages implementations. Should be run from a Jenkins agent.add(Class clazz): register class for some particular stage in stages map of StageFactory class.getStage(String name, String buildTool, String type): return an object of the class for a particular stage from stages property based on stage name and buildTool, type of application.Example:context.factory = new StageFactory(script: this)
context.factory.loadEdpStages().each() { context.factory.add(it) }
context.factory.loadCustomStages(\"${context.workDir}/stages\").each() { context.factory.add(it) }
context.factory.getStage(stageName.toLowerCase(),context.application.config.build_tool.toLowerCase(),
context.application.config.type).run(context)
"},{"location":"user-guide/pipeline-framework/#edp-stages-framework","title":"EDP Stages Framework","text":"Each EDP stage implementation has run method that is as input parameter required to pass a context map with different keys. Some stages can implement the logic for several build tools and application types, some of them are specific.
Inspect the Table 6 and Table 7 that contain the full description of every stage that can be included in Code Review and Build pipelines: Checkout \u2192 Gerrit Checkout \u2192 Compile \u2192 Get version \u2192 Tests \u2192 Sonar \u2192 Build \u2192 Build Docker Image \u2192 Push \u2192 Git tag.
Table 6. The Checkout, Gerrit Checkout, Compile, Get version, and Tests stages description.
Checkout Gerrit Checkout Compile Get version Tests name = \"checkout\",buildTool = [\"maven\", \"npm\", \"dotnet\",\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- StageFactory context.factory- String context.gerrit.branch- String context.gerrit.credentialsId- String context.application.config.cloneUrl name = \"gerrit-checkout\",buildTool = [\"maven\", \"npm\", \"dotnet\",\"gradle\"]type = [ProjectType.APPLICATION, ProjectType.AUTOTESTS, ProjectType.LIBRARY]context required:- String context.workDir- StageFactory context.factory- String context.gerrit.changeName- String context.gerrit.refspecName- String context.gerrit.credentialsId- String context.application.config.cloneUrl name = \"compile\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.sln_filenameoutput:- String context.buildTool.sln_filenamebuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.command- String context.nexus.credentialsIdbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.command- String context.nexus.credentialsIdbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.groupRepository name = \"get-version\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- Map(empty) context.application- String context.gerrit.branch- Job context.joboutput:-String context.application.deplyableModule- String context.application.deplyableModuleDir- String context.application.version- String context.application.buildVersionbuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.command- Job context.job- String context.gerrit.branchoutput:- String context.application.deplyableModuleDir- String context.application.version- String context.application.buildVersionbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.command- Job context.job- String context.gerrit.branchoutput:- String context.application.deplyableModule- String context.application.deplyableModuleDir- String context.application.version- String context.application.buildVersionbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- Job context.job- String context.gerrit.branchoutput:- String context.application.deplyableModuleDir- String context.application.version- String context.application.buildVersion name = \"tests\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDirbuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.commandbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.commandtype = [ProjectType.AUTOTESTS]context required:- String context.workDir- String context.buildTool.command- String context.application.config.report_frameworkbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDirTable 7. The Sonar, Build, Build Docker Image, Push, and Git tag stages description.
Sonar Build Build Docker Image Push Git tag name = \"sonar\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.job.type- String context.application.name- String context.buildTool.sln_filename- String context.sonar.route- String context.gerrit.changeName(Only for codereview pipeline)- String context.gerrit.branch(Only for build pipeline)buildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.job.type- String context.nexus.credentialsId- String context.buildTool.command- String context.application.name- String context.sonarRoute- String context.gerrit.changeName(Only for codereview pipeline)- String context.gerrit.branch(Only for build pipeline)buildTool = [\"maven\"]type = [ProjectType.APPLICATION, ProjectType.AUTOTESTS, ProjectType.LIBRARY]context required:- String context.workDir- String context.job.type- String context.nexus.credentialsId- String context.application.name- String context.buildTool.command- String context.sonar.route- String context.gerrit.changeName(Only for codereview pipeline)- String context.gerrit.branch(Only for build pipeline)buildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.job.type- String context.sonar.route- String context.application.name- String context.gerrit.changeName(Only for codereview pipeline)- String context.gerrit.branch(Only for build pipeline) name = \"build\"buildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.command- String context.nexus.credentialsIdbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.command- String context.nexus.credentialsIdbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.groupRepository name = \"build-image\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.application.deployableModule- String context.application.deployableModuleDir- String context.application.name- String context.application.config.language- String context.application.buildVersion- Boolean context.job.promoteImages- String context.job.envToPromotebuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.application.deployableModule- String context.application.deployableModuleDir- String context.application.name- String context.application.config.language- String context.application.buildVersion- Boolean context.job.promoteImages- String context.job.envToPromotebuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.application.deployableModule- String context.application.deployableModuleDir- String context.application.name- String context.application.config.language- String context.application.buildVersion- Boolean context.job.promoteImages- String context.job.envToPromotebuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.application.deployableModule- String context.application.deployableModuleDir- String context.application.name- String context.application.config.language- String context.application.buildVersion- Boolean context.job.promoteImages- String context.job.envToPromote name = \"push\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.gerrit.project- String context.buildTool.sln_filename- String context.buildTool.snugetApiKey- String context.buildTool.hostedRepositorybuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.application.version- String context.buildTool.hostedRepository- String context. buildTool.settingsbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.application.version- String context.buildTool.hostedRepository- String context.buildTool.commandbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.hostedRepository- String context.gerrit.autouser name = \"git-tag\"buildTool = [\"maven\", \"npm\", \"dotnet\",\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.gerrit.credentialsId- String context.gerrit.sshPort- String context.gerrit.host- String context.gerrit.autouser- String context.application.buildVersion"},{"location":"user-guide/pipeline-framework/#deploy-pipeline","title":"Deploy Pipeline","text":"Deploy() \u2013 a function that allows using the EDP implementation for the deploy pipeline. All values of different parameters that are used during the pipeline execution are stored in the \"Map\" context.
The deploy pipeline consists of several steps:
On the master:
On a particular autotest Jenkins agent that depends on the build tool:
_Using in pipelines - @Library(['edp-library-pipelines@version']) _
The corresponding enums and interfaces with their methods can be used separately from the EDP Pipelines library function (please refer to Table 8 and Table 9).
Table 8. Enums and Interfaces with the respective properties, methods, and examples.
Enums Interfaces PlatformType:- OPENSHIFT- KUBERNETESJobType:- CODEREVIEW- BUILD- DEPLOYBuildToolType:- MAVEN- GRADLE- NPM- DOTNET Platform() - contains methods for working with platform CLI. At the moment only OpenShift is supported.Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Methods:getJsonPathValue(String k8s_kind, String k8s_kind_name, String jsonPath): return String value of specific parameter of particular object using jsonPath utility. Example:context.platform.getJsonPathValue(\"cm\",\"project-settings\",
\".data.username\")
BuildTool() - contains methods for working with different buildTool from ENUM BuildToolType. (Should be invoked on Jenkins build agents)Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Nexus object - Object of class Nexus.Methods:init: return parameters of buildTool that are needed for running stages. Example:context.buildTool = new BuildToolFactory().getBuildToolImpl
(context.application.config.build_tool, this, context.nexus)
context.buildTool.init()
Table 9. Classes with the respective properties, methods, and examples. Classes Description (properties, methods, and examples) PlatformFactory() - Class that contains methods getting implementation of CLI of platform. At the moment OpenShift and Kubernetes are supported. Methods:getPlatformImpl(PlatformType platform, Script script): return Class PlatformExample: context.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)
Application(String name, Platform platform, Script script) - Class that describe the application object. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Platform platform - Object of a class Platform()String name - Name for the application for creating objectMap config - Map of configuration settings for particular application that is loaded from config map project-settingsString version - Application version, initially empty. Is set on get-version step.String deployableModule - The name of deployable module for multi module applications, initially empty.String buildVersion - Version of built artifact, contains build number of Job initially emptyString deployableModuleDir - The name of deployable module directory for multi module applications, initially empty.Array imageBuildArgs - List of arguments for building application Docker imageMethods: setConfig(String gerrit_autouser, String gerrit_host, String gerrit_sshPort, String gerrit_project): set the config property with values from config mapExample: context.application = new Application(context.job, context.gerrit.project, context.platform, this)
context.application.setConfig(context.gerrit.autouser, context.gerrit.host, context.gerrit.sshPort, context.gerrit.project)
Job(type: JobType.value, platform: Platform, script: Script) - Class that describe the Gerrit tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\"Platform platform - Object of a class Platform().JobType.value type.String deployTemplatesDirectory - The name of the directory in application repository, where deploy templates are located. Can be set for particular Job through DEPLOY_TEMPLATES_DIRECTORY parameter.String edpName - The name of the EDP Project.Map stages - Contains all stages in JSON format that is retrieved from Jenkins job env variable.String envToPromote - The name of the environment for promoting images.Boolean promoteImages - Defines whether images should be promoted or not. Methods:getParameterValue(String parameter, String defaultValue = null): return parameter of ENV variable of Jenkins job. init(): set all the properties of Job object. setDisplayName(String displayName): set display name of the Jenkins job. setDescription(String description, Boolean addDescription = false): set new or add to existing description of the Jenkins job. printDebugInfo(Map context): print context info to log of Jenkins job. runStage(String stage_name, Map context): run the particular stage according to its name. Example: context.job = new Job(JobType.DEPLOY.value, context.platform, this)
context.job.init()
context.job.printDebugInfo(context)
context.job.setDisplayName(\"test\")
context.job.setDescription(\"Name: ${context.application.config.name}\")
Gerrit(Job job, Platform platform, Script script) - Class that describe the Gerrit tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform(). Job job - Object of a class Job().String credentialsId - Credential Id in Jenkins for Gerrit. String autouser - Username of autouser in Gerrit for integration with Jenkins. String host - Gerrit host. String project - project name of built application. String branch - branch to build application from. String changeNumber - change number of Gerrit commit. String changeName - change name of Gerrit commit. String refspecName - refspecName of Gerrit commit. String sshPort - gerrit ssh port number. String patchsetNumber - patchsetNumber of Gerrit commit.Methods:init(): set all the properties of Gerrit object. Example:context.gerrit = new Gerrit(context.job, context.platform, this)
context.gerrit.init()
. Nexus(Job job, Platform platform, Script script) - Class that describe the Nexus tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Platform platform - Object of a class Platform(). Job job - Object of a class Job(). String autouser - Username of autouser in Nexus for integration with Jenkins. String credentialsId - Credential Id in Jenkins for Nexus. String host - Nexus host. String port - Nexus http(s) port. String repositoriesUrl - Base URL of repositories in Nexus. String restUrl - URL of Rest API. Methods:init(): set all the properties of Nexus object. Example: context.nexus = new Nexus(context.job, context.platform, this)
context.nexus.init()
."},{"location":"user-guide/pipeline-framework/#edp-library-stages-description_1","title":"EDP Library Stages Description","text":"Using in pipelines - @Library(['edp-library-stages@version']) _
The corresponding classes with methods can be used separately from the EDP Pipelines library function (please refer to Table 10).
Table 10. Classes with the respective properties, methods, and examples.
Classes Description (properties, methods, and examples) StageFactory() - Class that contains methods getting implementation of particular stage either EDP from shared library or custom from application repository. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\"Map stages - Map of stages implementationsMethods:loadEdpStages(): return list of Classes that describes EDP stages implementationsloadCustomStages(String directory): return list of Classes that describes EDP custom stages from application repository from \"directory\". The \"directory\" should be absolute path to files with classes of custom stages implementations. Should be run from Jenkins agent.add(Class clazz): register class for some particular stage in stages map of StageFactory classgetStage(String name, String buildTool, String type): return object of the class for particular stage from stages property based on stage name and buildTool, type of applicationExample:context.factory = new StageFactory(script: this)
context.factory.loadEdpStages().each() { context.factory.add(it) }
context.factory.loadCustomStages(\"${context.workDir}/stages\").each() { context.factory.add(it) }
context.factory.getStage(stageName.toLowerCase(),context.application.config.build_tool.toLowerCase(),
context.application.config.type).run(context)
."},{"location":"user-guide/pipeline-framework/#deploy-pipeline-stages","title":"Deploy Pipeline Stages","text":"Each EDP stage implementation has run method that is as input parameter required to pass a context map with different keys. Some stages can implement the logic for several build tools and application types, some of them are specific.
The stages for the deploy pipeline are independent of the build tool and application type. Find below (see Table 11 ) the full description of every stage: Deploy \u2192 Automated tests \u2192 Promote Images.
Table 11. The Deploy, Automated tests, and Promote Images stages description.
Deploy Automated tests Promote Images name = \"deploy\"buildTool = nulltype = nullcontext required:\u2022 String context.workDir\u2022 StageFactory context.factory\u2022 String context.gerrit.autouser\u2022 String context.gerrit.host\u2022 String context.application.config.cloneUrl\u2022 String context.jenkins.token\u2022 String context.job.edpName\u2022 String context.job.buildUrl\u2022 String context.job.jenkinsUrl\u2022 String context.job.metaProject\u2022 List context.job.applicationsList [['name':'application1_name','version':'application1_version],...]\u2022 String context.job.deployTemplatesDirectoryoutput:\u2022 List context.job.updatedApplicaions [['name':'application1_name','version':'application1_version],...] name = \"automation-tests\", buildTool = null, type = nullcontext required:- String context.workDir- StageFactory context.factory- String context.gerrit.credentialsId- String context.autotest.config.cloneUrl- String context.autotest.name- String context.job.stageWithoutPrefixName- String context.buildTool.settings- String context.autotest.config.report_framework name = \"promote-images\"buildTool = nulltype = nullcontext required:- String context.workDir- String context.buildTool.sln_filename- List context.job.updatedApplicaions [['name':'application1_name','version':'application1_version],...]"},{"location":"user-guide/pipeline-framework/#how-to-redefine-or-extend-edp-pipeline-stages-library_1","title":"How to Redefine or Extend EDP Pipeline Stages Library","text":"Info
Currently, the redefinition of Deploy pipeline stages is prohibited.
"},{"location":"user-guide/pipeline-framework/#using-edp-library-stages-in-the-pipeline","title":"Using EDP Library Stages in the Pipeline","text":"In order to use the EDP stages, the created pipeline should fit some requirements, that`s why a developer has to do the following:
After that, there is the ability to run any EDP stage beforehand by defining requirement context context.job.runStage(\"Deploy\", context)
.
For instance, the pipeline can look like:
@Library(['edp-library-stages', 'edp-library-pipelines']) _\n\nimport com.epam.edp.stages.StageFactory\nimport com.epam.edp.platform.PlatformFactory\nimport com.epam.edp.platform.PlatformType\nimport com.epam.edp.JobType\n\ncontext = [:]\n\nnode('master') {\n\tstage(\"Init\") {\n\t\tcontext.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)\n\t\tcontext.job = new com.epam.edp.Job(JobType.DEPLOY.value, context.platform, this)\n\t\tcontext.job.init()\n\t\tcontext.job.initDeployJob()\n\t\tprintln(\"[JENKINS][DEBUG] Created object job with type - ${context.job.type}\")\n\n\t\tcontext.nexus = new com.epam.edp.Nexus(context.job, context.platform, this)\n\t\tcontext.nexus.init()\n\n\t\tcontext.jenkins = new com.epam.edp.Jenkins(context.job, context.platform, this)\n\t\tcontext.jenkins.init()\n\n\t\tcontext.gerrit = new com.epam.edp.Gerrit(context.job, context.platform, this)\n\t\tcontext.gerrit.init()\n\n\t\tcontext.factory = new StageFactory(script: this)\n\t\tcontext.factory.loadEdpStages().each() { context.factory.add(it) }\n\n\t\tcontext.environment = new com.epam.edp.Environment(context.job.deployProject, context.platform, this)\n\t\tcontext.job.printDebugInfo(context)\n\t\tcontext.job.setDisplayName(\"${currentBuild.displayName}-${context.job.deployProject}\")\n\n\t\tcontext.job.generateInputDataForDeployJob()\n\t}\n\n\tstage(\"Pre Deploy Custom stage\") {\n\t\tprintln(\"Some custom pre deploy logic\")\n\t}\n\n\tcontext.job.runStage(\"Deploy\", context)\n\n\tstage(\"Post Deploy Custom stage\") {\n\t\tprintln(\"Some custom post deploy logic\")\n\t}\n}\n
Or in a declarative way:
@Library(['edp-library-stages', 'edp-library-pipelines']) _\n\nimport com.epam.edp.stages.StageFactory\nimport com.epam.edp.platform.PlatformFactory\nimport com.epam.edp.platform.PlatformType\nimport com.epam.edp.JobType\n\ncontext = [:]\n\npipeline {\n\tagent { label 'master'}\n\tstages {\n\t\tstage('Init') {\n\t\t\tsteps {\n\t\t\t\tscript {\n\t\t\t\t\tcontext.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)\n\t\t\t\t\tcontext.job = new com.epam.edp.Job(JobType.DEPLOY.value, context.platform, this)\n\t\t\t\t\tcontext.job.init()\n\t\t\t\t\tcontext.job.initDeployJob()\n\t\t\t\t\tprintln(\"[JENKINS][DEBUG] Created object job with type - ${context.job.type}\")\n\n\t\t\t\t\tcontext.nexus = new com.epam.edp.Nexus(context.job, context.platform, this)\n\t\t\t\t\tcontext.nexus.init()\n\n\t\t\t\t\tcontext.jenkins = new com.epam.edp.Jenkins(context.job, context.platform, this)\n\t\t\t\t\tcontext.jenkins.init()\n\n\t\t\t\t\tcontext.gerrit = new com.epam.edp.Gerrit(context.job, context.platform, this)\n\t\t\t\t\tcontext.gerrit.init()\n\n\t\t\t\t\tcontext.factory = new StageFactory(script: this)\n\t\t\t\t\tcontext.factory.loadEdpStages().each() { context.factory.add(it) }\n\n\t\t\t\t\tcontext.environment = new com.epam.edp.Environment(context.job.deployProject, context.platform, this)\n\t\t\t\t\tcontext.job.printDebugInfo(context)\n\t\t\t\t\tcontext.job.setDisplayName(\"${currentBuild.displayName}-${context.job.deployProject}\")\n\n\t\t\t\t\tcontext.job.generateInputDataForDeployJob()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tstage('Deploy') {\n\t\t\tsteps {\n\t\t\t\tscript {\n\t\t\t\t\tcontext.factory.getStage(\"deploy\").run(context)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tstage('Custom stage') {\n\t\t\tsteps {\n\t\t\t\tprintln(\"Some custom logic\")\n\t\t\t}\n\t\t}\n\t}\n}\n
"},{"location":"user-guide/pipeline-framework/#related-articles","title":"Related Articles","text":"Get acquainted with EDP CI/CD workflow and stages description.
"},{"location":"user-guide/pipeline-stages/#edp-cicd-workflow","title":"EDP CI/CD Workflow","text":"Within EDP, the pipeline framework comprises the following pipelines:
Note
Please refer to the EDP Pipeline Framework page for details.
The diagram below shows the delivery path through these pipelines and the respective stages. Please be aware that stages may differ for different codebase types.
stages
"},{"location":"user-guide/pipeline-stages/#stages-description","title":"Stages Description","text":"The table below provides the details on all the stages in the EDP pipeline framework:
Name Dependency Description Pipeline Application Library Autotest Source code Documentation init Initiates information gathering Create Release, Code Review, Build + + Build.groovy checkout Performs for all files the checkout from a selected branch of the Git repository. For the main branch - from HEAD, for code review - from the commit Create Release, Build + + Checkout.groovy sast Launches vulnerability testing via Semgrep scanner. Pushes a vulnerability report to the DefectDojo. Build + Security compile Compiles the code, includes individual groovy files for each type of app or lib (NPM, DotNet, Python, Maven, Gradle) Code Review, Build + + Compile tests Launches testing procedure, includes individual groovy files for each type of app or lib Code Review, Build + + + Tests sonar Launches testing via SonarQube scanner and includes individual groovy files for each type of app or lib Code Review, Build + + Sonar build Builds the application, includes individual groovy files for each type of app or lib (Go, Maven, Gradle, NPM) Code Review, Build + Build create-branch EDP create-release process Creates default branch in Gerrit during create and clone strategies Create Release + + + CreateBranch.groovy trigger-job EDP create-release process Triggers \"build\" job Create Release + + + TriggerJob.groovy gerrit-checkout Performs checkout to the current project branch in Gerrit Code Review + + + GerritCheckout.groovy commit-validate Optional in EDP Admin Console Takes Jira parameters, when \"Jira Integration\" is enabled for the project in the Admin Console. Code Review + + CommitValidate.groovy dockerfile-lint Launches linting tests for Dockerfile Code Review + LintDockerApplicationLibrary.groovy Use Dockerfile Linters for Code Review dockerbuild-verify \"Build\" stage (if there are no \"COPY\" layers in Dockerfile) Launches build procedure for Dockerfile without pushing an image to the repository Code Review + BuildDockerfileApplicationLibrary.groovy Use Dockerfile Linters for Code Review helm-lint Launches linting tests for deployment charts Code Review + LintHelmApplicationLibrary.groovy Use helm-lint for Code Review helm-docs Checks generated documentation for deployment charts Code Review + HelmDocsApplication.groovy Use helm-docs for Code Review helm-uninstall Helm release deletion step to clear Helm releases Deploy + HelmUninstall.groovy Helm release deletion semi-auto-deploy-input Provides auto deploy with timeout and manual deploy flow Deploy + SemiAutoDeployInput.groovy Semi Auto Deploy get-version Defines the versioning of the project depending on the versioning schema selected in Admin Console Build + + GetVersion terraform-plan AWS credentials added to Jenkins Checks Terraform version, and installs default version if necessary, and launches terraform init, returns AWS username which used for action, and terraform plan command is called with an output of results to .tfplan file Build + TerraformPlan.groovy Use Terraform library in EDP terraform-apply AWS credentials added to Jenkins, the \"Terraform-plan\" stage Checks Terraform version, and installs default version if necessary, and launches terraform init, launches terraform plan from saves before .tfplan file, asks to approve, and run terraform apply from .tfplan file Build + TerraformApply.groovy Use Terraform library in EDP build-image-from-dockerfile Platform: OpenShift Builds Dockerfile Build + + .groovy files for building Dockerfile image build-image-kaniko Platform: k8s Builds Dockerfile using the Kaniko tool Build + BuildImageKaniko.groovy push Pushes an artifact to the Nexus repository Build + + Push create-Jira-issue-metadata \"get-version\" stage Creates a temporary CR in the namespace and after that pushes Jira Integration data to Jira ticket, and delete CR Build + + JiraIssueMetadata.groovy ecr-to-docker DockerHub credentials added to Jenkins Copies the docker image from the ECR project registry to DockerHub via the Crane tool after it is built Build + EcrToDocker.groovy Promote Docker Images From ECR to Docker Hub git-tag \"Get-version\" stage Creates a tag in SCM for the current build Build + + GitTagApplicationLibrary.groovy deploy Deploys the application Deploy + Deploy.groovy manual Works with the manual approve to proceed Deploy + ManualApprove.groovy promote-images Promotes docker images to the registry Deploy + PromoteImage.groovyNote
The Create Release pipeline is an internal EDP mechanism for adding, importing or cloning a codebase. It is not a part of the pipeline framework.
"},{"location":"user-guide/pipeline-stages/#related-articles","title":"Related Articles","text":"After the necessary applications are added to EDP, they can be managed via the Admin Console. To prepare for the release, create a new branch from a selected commit with a set of CI pipelines (Code Review and Build pipelines), launch the Build pipeline, and add a new CD pipeline as well.
Note
Please refer to the Add Application and Add CD Pipeline for the details on how to add an application or a CD pipeline.
Become familiar with the following preparation steps for release and a CD pipeline structure:
Open Gerrit via the Admin Console Overview page to have this tab available in a web browser.
Being in Admin Console, open the Applications section and click an application from the list to create a new branch.
Once clicked the application name, scroll down to the Branches menu and click the Create button to open the Create New Branch dialog box, fill in the Branch Name field by typing a branch name.
Paste the copied hash to the From Commit Hash field and click Proceed.
Note
If the commit hash is not added to the From Commit Hash field, the new branch will be created from the head of the master branch.
"},{"location":"user-guide/prepare-for-release/#launch-the-build-pipeline","title":"Launch the Build Pipeline","text":"After the new branches are added, open the details page of every application and click the CI link that refers to Jenkins.
Note
The adding of a new branch may take some time. As soon as the new branch is created, it will be displayed in the list of the Branches menu.
To build a new version of a corresponding Docker container (an image stream in OpenShift terms) for the new branch, start the Build pipeline. Being in Jenkins, select the new branch tab and click the link to the Build pipeline.
Navigate to the Build with Parameters option and click the Build button to launch the Build pipeline.
Warning
The predefined default parameters should not be changed when triggering the Build pipeline, otherwise, it will lead to the pipeline failure.
Add a new CD pipeline and indicate the new release branch using the Admin console tool. Pay attention to the Applications menu, the necessary application(s) should be selected there, as well as the necessary branch(es) from the drop-down list.
Note
For the details on how to add a CD pipeline, please refer to the Add CD Pipeline page.
As soon as the Build pipelines are successfully passed in Jenkins, the Docker Registry, which is used in EDP by default, will have the new image streams (Docker container in Kubernetes terms) version that corresponds to the current branch.
Open the Kubernetes/OpenShift page of the project via the Admin Console Overview page \u2192 go to CodebaseImageStream (in OpenShift, go to Builds \u2192 Images) \u2192 check whether the image streams are created under the specific name (the combination of the application and branch names) and the specific tags are added. Click every image stream link.
When the CD pipeline is added through the Admin Console, it becomes available in the CD pipelines list. Every pipeline has the details page with the additional information. To explore the CD pipeline structure, follow the steps below:
Open Admin Console and navigate to Continuous Delivery section, click the newly created CD pipeline name.
Discover the CD pipeline components:
Note
Initially, an environment is empty and does not have any deployment unit. When deploying the subsequent stages, the artifacts of the selected versions will be deployed to the current project and the environment will display the current stage status. The project has a standard pattern: \u2039edp-name\u203a-\u2039pipeline-name\u203a-\u2039stage-name\u203a.
Follow the steps below to deploy the QA and UAT application stages:
As soon as the Build pipelines for both applications are successfully passed, the new version of the Docker container will appear, thus allowing to launch the CD pipeline. Simply navigate to Continuous Delivery and click the pipeline name to open it in Jenkins.
Click the QA stage link.
Deploy the QA stage by clicking the Build Now option.
After the initialization step starts, in case another menu is opened, the Pause for Input option will appear. Select the application version in the drop-down list and click Proceed. The pipeline passes the following stages:
After all the stages are passed, the new image streams will be created in the Kubernetes/OpenShift with the new names.
Deploy the UAT stage, which takes the versions that were verified during the QA stage, by clicking the Build Now option, and select the necessary application versions. The launch process is the same as for all the deploy pipelines.
To get the status of the pipeline deployment, open the CD pipeline details page and check the Deployed versions state.
Admin Console allows creating a CD pipeline with a part of the application set as a team environment. To do this, perform the following steps;
As a result, the team will have the same abilities to verify the code changes when developing and during the release.
"},{"location":"user-guide/prepare-for-release/#related-articles","title":"Related Articles","text":"The Semi Auto Deploy stage provides the ability to deploy applications with the custom logic that comprises the following behavior:
To enable the Semi Auto Deploy stage during the deploy process, follow the steps below:
{\"name\":\"auto-deploy-input\",\"step_name\":\"auto-deploy-input\"}
step to the {\"name\":\"semi-auto-deploy-input\",\"step_name\":\"semi-auto-deploy-input\"}
step in the CD pipeline. Alternatively, it is possible to create a custom job provisioner with this step.After the timeout starts and in case the pipeline has been interrupted not from the Input requested menu, the automatic deployment will be proceeding. To resolve the issue and stop the pipeline, click the Input requested menu -> Abort or being on the pipeline UI, click the Abort button.
"},{"location":"user-guide/semi-auto-deploy/#related-articles","title":"Related Articles","text":"EPAM Delivery Platform ensures the implemented Terraform support by adding a separate component type called Infrastructure. The Infrastructure codebase type allows to work with Terraform code that is processed by means of stages in the Code-Review and Build pipelines.
"},{"location":"user-guide/terraform-stages/#pipeline-stages-for-terraform","title":"Pipeline Stages for Terraform","text":"Under the hood, Infrastructure codebase type, namely Terraform, looks quite similar to other codebase types. The distinguishing characterstic of the Infrastructure codebase type is that there is a stage called terraform-check in both of Code Review and Build pipelines. This stage runs the pre-commit activities which in their turn run the following commands and tools:
Terraform fmt - the first step of the stage is basically the terraform fmt
command. The terraform fmt
command automatically updates the formatting of Terraform configuration files to follow the standard conventions and make the code more readable and consistent.
Lock provider versions - locks the versions of the Terraform providers used in the project. This ensures that the project uses specific versions of the providers and prevents unexpected changes from impacting the infrastructure due to newer provider versions.
Terraform validate - checks the syntax and validity of the Terraform configuration files. It scans the configuration files for all possible issues.
Terraform docs - generates human-readable documentation for the Terraform project.
Tflint - additional validation step using the tflint
linter to provide more in-depth checks in addition to what the terraform validate
command does.
Checkov - runs the checkov
command against the Terraform codebase to identify any security misconfigurations or compliance issues.
Tfsec - another security-focused validation step using the tfsec
command. Tfsec is a security scanner for Terraform templates that detects potential security issues and insecure configurations in the Terraform code.
Note
The commands and their attributes are displayed in the .pre-commit-config.yaml file.
"},{"location":"user-guide/terraform-stages/#related-articles","title":"Related Articles","text":"Set the CODEBASE_BRANCH_MAX_CONCURRENT_RECONCILES Env variable in codebase-operator by updating Deployment template. For example:
...\n env:\n - name: WATCH_NAMESPACE\n ...\n\n - name: CODEBASE_BRANCH_MAX_CONCURRENT_RECONCILES\n value: 10\n ...\n
It's not recommended to set the value above 10.
"},{"location":"faq/#how-to-change-the-lifespan-of-an-access-token-that-is-used-for-edp-portal-and-oidc-login-plugin","title":"How To Change the Lifespan of an Access Token That Is Used for EDP Portal and 'oidc-login' Plugin?","text":"Change the Access Token Lifespan: go to your Keycloak and select Openshift realm > Realm settings > Tokens > Access Token Lifespan > set a new value to the field and save this change.
By default, \"Access Token Lifespan\" value is 5 minutes.
Access Token Lifespan
"},{"location":"features/","title":"Basic Concepts","text":""},{"location":"features/#basic-concepts","title":"Basic Concepts","text":"Consult EDP Glossary section for definitions mentioned on this page and EDP Toolset to have a full list of tools used with the Platform. The below table contains a full list of features provided by EDP.
Features Description Cloud Agnostic EDP runs on Kubernetes cluster, so any Public Cloud Provider which provides Kubernetes can be used. Kubernetes clusters deployed on-premises work as well CI/CD for Microservices EDP is initially designed to support CI/CD for Microservices running as containerized applications inside Kubernetes Cluster. EDP also supports CI for:- Terraform Modules, - Open Policy Rules,- Workflows for Java (8,11,17), JavaScript (React, Vue, Angular, Express, Antora), C# (.NET 6.0), Python (FastAPI, Flask, 3.8), Go (Beego, Operator SDK) Version Control System (VCS) EDP installs Gerrit as a default Source Code Management (SCM) tool. EDP also supports GitHub and GitLab integration Branching Strategy EDP supports Trunk-based development as well as GitHub/GitLab flow. EDP creates two Pipelines per each codebase branch (see Pipeline Framework): Code Review and Build Repository Structure EDP provides separate Git repository per each Codebase and doesn't work with Monorepo. However, EDP does support customization and runs helm-lint, dockerfile-lint steps using Monorepo approach. Artifacts Versioning EDP supports two approaches for Artifacts versioning: - default (BRANCH-[TECH_STACK_VERSION]-BUILD_ID)- EDP (MAJOR.MINOR.PATCH-BUILD_ID), which is SemVer.Custom versioning can be created by implementing get-version stage Application Library EDP provides baseline codebase templates for Microservices, Libraries, within create strategy while onboarding new Codebase Stages Library Each EDP Pipeline consists of pre-defined steps (stages). Consult library documentation for more details CI Pipelines EDP provides CI Pipelines for first-class citizens: - Applications (Microservices) based on Java (8,11,17), JavaScript (React, Vue, Angular, Express, Antora, Next.js), C# (.NET 3.1, .NET 6.0), Python (FastAPI, Flask, 3.8), Go (Beego, Gin, Operator SDK), Helm (Charts, Pipeline)- Libraries based on Java (8,11,17), JavaScript (React, Vue, Angular, Express), Python (FastAPI, Flask, 3.8), Groovy Pipeline (Codenarc), HCL (Terraform), Rego (OPA), Container (Docker), Helm (Charts, Pipeline), C#(.NET 3.1, .NET 6.0) - Autotests based on Java8, Java11, Java17 CD Pipelines EDP provides capabilities to design CD Pipelines (in EDP Portal UI) for Microservices and defines logic for artifacts flow (promotion) from env to env. Artifacts promotion is performed automatically (Autotests), manually (User Approval) or combining both approaches Autotests EDP provides CI pipeline for autotest implemented in Java. Autotests can be used as Quality Gates in CD Pipelines Custom Pipeline Library EDP can be extended by introducing Custom Pipeline Library Dynamic Environments Each EDP CD Pipeline creates/destroys environment upon user requests"},{"location":"getting-started/","title":"Quick Start","text":""},{"location":"getting-started/#quick-start","title":"Quick Start","text":""},{"location":"getting-started/#software-requirements","title":"Software Requirements","text":"The system should have the following specifications to run properly:
EPAM Delivery Platform supports the following tools:
Domain Related Tools/Solutions Artifacts Management Nexus Repository, Jfrog Artifactory AWS IRSA, AWS ECR, AWS EFS, Parameter Store, S3, ALB/NLB, Route53 Build .NET, Go, Apache Gradle, Apache Maven, NPM Cluster Backup Velero Code Review Gerrit, GitLab, GitHub Container Registry AWS ECR, OpenShift Registry, Harbor, DockerHub Containers Hadolint, Kaniko, Crane Documentation as Code MkDocs, Antora (AsciiDoc) Infrastructure as Code Terraform, TFLint, Terraform Docs, Crossplane, AWS Controllers for Kubernetes Kubernetes Deployment Kubectl, Helm, Helm Docs, Chart Testing, Argo CD, Argo Rollout Kubernetes Multitenancy Kiosk, Capsule Logging OpenSearch, EFK, ELK, Loki, Splunk Monitoring Prometheus, Grafana, VictoriaMetrics Pipeline Orchestration Tekton Policies/Rules Open Policy Agent Secrets Management External Secret Operator, Vault, AWS Parameter Store Secure Development SonarQube, DefectDojo, Dependency Track, Semgrep, Grype, Trivy, Clair, GitLeaks, CycloneDX Generator, tfsec, checkov SSO Keycloak, oauth2-proxy Test Report Tool ReportPortal, Allure Tracing OpenTelemetry, Jaeger"},{"location":"getting-started/#install-edp","title":"Install EDP","text":"To install EDP with the necessary parameters, please refer to the Install EDP section of the Operator Guide. Mind the parameters in the EDP installation chart. For details, please refer to the values.yaml.
Find below the example of the installation command:
helm install edp epamedp/edp-install --wait --timeout=900s \\\n --set global.dnsWildCard=<cluster_DNS_wildcard> \\\n --set global.platform=<platform_type> \\\n --set awsRegion=<region> \\\n --namespace edp\n
Warning
Please be aware that the command above is an example.
"},{"location":"getting-started/#related-articles","title":"Related Articles","text":"Getting Started
"},{"location":"glossary/","title":"Glossary","text":""},{"location":"glossary/#glossary","title":"Glossary","text":"Get familiar with the definitions and context for the most useful EDP terms presented in table below.
Terms Details EDP Component - an item used in CI/CD process EDP Portal UI - an EDP component that helps to manage, set up, and control the business entities. Artifactory - an EDP component that stores all the binary artifacts. NOTE: Nexus is used as a possible implementation of a repository. CI/CD Server - an EDP component that launches pipelines that perform the build, QA, and deployment code logic. NOTE: Tekton is used as a possible implementation of a CI/CD server. Code Review tool - an EDP component that collaborates with the changes in the codebase. NOTE: Gerrit is used as a possible implementation of a code review tool. Identity Server - an authentication server providing a common way to verify requests to all of the applications. NOTE: Keycloak is used as a possible implementation of an identity server. Security Realm Tenant - a realm in identity server (e.g Keycloak) where all users' accounts and their access permissions are managed. The realm is unique for the identity server instance. Static Code Analyzer - an EDP component that inspects continuously a code quality before the necessary changes appear in a master branch. NOTE: SonarQube is used as a possible implementation of a static code analyzer. VCS (Version Control System) - a replication of the Gerrit repository that displays all the changes made by developers. NOTE: GitHub and GitLab are used as the possible implementation of a repository with the version control system. EDP Business Entity - a part of the CI/CD process (the integration, delivery, and deployment of any codebase changes) Application - a codebase type that is built as the binary artifact and deployable unit with the code that is stored in VCS. As a result, the application becomes a container and can be deployed in an environment. Autotests - a codebase type that inspects a product (e.g. an application set) on a stage. Autotests are not deployed to any container and launched from the respective code stage. CD Pipeline (Continuous Delivery Pipeline) - an EDP business entity that describes the whole delivery process of the selected application set via the respective stages. The main idea of the CD pipeline is to promote the application version between the stages by applying the sequential verification (i.e. the second stage will be available if the verification on the first stage is successfully completed). NOTE: The CD pipeline can include the essential set of applications with its specific stages as well. CD Pipeline Stage - an EDP business entity that is presented as the logical gate required for the application set inspection. Every stage has one OpenShift project where the selected application set is deployed. All stages are sequential and promote applications one-by-one. Codebase - an EDP business entity that possesses a code. Codebase Branch - an EDP business entity that represents a specific version in a Git branch. Every codebase branch has a Codebase Docker Stream entity. Codebase Docker Stream - a deployable component that leads to the application build and displays that the last build was verified on the specific stage. Every CD pipeline stage accepts a set of Codebase Docker Streams (CDS) that are input and output. SAMPLE: if an application1 has a master branch, the input CDS will be named as [app name]-[pipeline name]-[stage name]-[master] and the output after the passing of the DEV stage will be as follows: [app name]-[pipeline name]-[stage name]-[dev]-[verified]. Git Server - a custom resource that is responsible for integration with Version Control System (VCS), whether it is GitHub, GitLab or Gerrit. Infrastructure - a codebase type that is used to define and manage the underlying infrastructure of projects using the Infrastructure as Code (IaC) approach, ensuring consistency and reproducibility. Library - a codebase type that is built as the binary artifact, i.e. it`s stored in the Artifactory and can be uploaded by other applications, autotests or libraries. Quality Gate - an EDP business entity that represents the minimum acceptable results after the testing. Every stage has a quality gate that should be passed to promote the application. The stage quality gate can be a manual approve from a QA specialist OR a successful autotest launch. Quality Gate Type - this value defines trigger type that promotes artifacts (images) to the next environment in CD Pipeline. There are manual and automatic types of quality gates. The manual type means that the promoting process should be confirmed in Tekton. The automatic type promotes the images automatically in case there are no errors in the Allure Report. NOTE: If any of the test types is not passed, the CD pipeline will fail. Trigger Type - a value that defines a trigger type used for the CD pipeline triggering. There are manual and automatic types of triggering. The manual type means that the CD pipeline should be triggered manually. The automatic type triggers the CD pipeline automatically as soon as the Codebase Docker Stream was changed. Automated Tests - different types of automated tests that can be run on the environment for a specific stage. Build Pipeline - a Tekton pipeline that builds a corresponding codebase branch in the Codebase. Build Stage - a stage that takes place after the code has been submitted/merged to the repository of the main branch (the pull request from the feature branch is merged to the main one, the Patch set is submitted in Gerrit). Code Review Pipeline - a Tekton pipeline that inspects the code candidate in the Code Review tool. Code Review Stage - a stage where code is reviewed before it goes to the main branch repository of the version control system (the commit to the feature branch is pushed, the Patch set is created in Gerrit). Deploy Pipeline - a Tekton pipeline that is responsible for the CD Pipeline Stage deployment with the full set of applications and autotests. Deployment Stage - a part of the Continuous Delivery where artifacts are being deployed to environments. EDP CI Pipelines - an orchestrator for stages that is responsible for the common technical events, e.g. initialization, in Tekton pipeline. Environment - a part of the stage where the built and packed into an image application are deployed for further testing. It`s possible to deploy several applications to several environments (Team and Integration environments) within one stage. Team Environment - an environment type that can be deployed at any time by the manual trigger of the Deploy pipeline where team or developers can check out their applications. NOTE: The promotion from such kind of environment is prohibited and developed only for the local testing. OpenShift / Kubernetes (K8S) ConfigMap - a resource that stores configuration data and processes the strings that do not contain sensitive information. Docker Container - is a lightweight, standalone, and executable package. Docker Registry - a store for the Docker Container that is created for the application after the Build pipeline performance. OpenShift Web Console - a web console that enables to view, manage, and change OpenShift / K8S resources using browser. Operator Framework - a deployable unit in OpenShift that is responsible for one or a set of resources and performs its life circle (adding, displaying, and provisioning). Path - a route component that helps to find a specified path (e.g. /api) at once and skip the other. Pod - the smallest deployable unit of the large microservice application that is responsible for the application launch. The pod is presented as the one launched Docker container. When the Docker container is collected, it will be kept in Docker Registry and then saved as Pod in the OpenShift project. NOTE: The Deployment Config is responsible for the Pod push, restart, and stop processes. PV (Persistent Volume) - a cluster resource that captures the details of the storage implementation and has an independent lifecycle of any individual pod. PVC (Persistent Volume Claim) - a user request for storage that can request specific size and access mode. PV resources are consumed by PVCs. Route - a resource in OpenShift that allows getting the external access to the pushed application. Secret - an object that stores and manages all the sensitive information (e.g. passwords, tokens, and SSH keys). Service - an external connection point with Pod that is responsible for the network. A specific Service is connected to a specific Pod using labels and redirects all the requests to Pod as well. Site - a route component (link name) that is created from the indicated application name and applies automatically the project name and a wildcard DNS record."},{"location":"overview/","title":"Overview","text":""},{"location":"overview/#overview","title":"Overview","text":"EPAM Delivery Platform (EDP) is an open-source cloud-agnostic SaaS/PaaS solution for software development, licensed under Apache License 2.0. It provides a pre-defined set of CI/CD patterns and tools, which allow a user to start product development quickly with established code review, release, versioning, branching, build processes. These processes include static code analysis, security checks, linters, validators, dynamic feature environments provisioning. EDP consolidates the top Open-Source CI/CD tools by running them on Kubernetes/OpenShift, which enables web/app development either in isolated (on-prem) or cloud environments.
EPAM Delivery Platform, which is also called \"The Rocket\", is a platform that allows shortening the time that is passed before an active development can be started from several months to several hours.
EDP consists of the following:
CI pipelines
Language Framework Build Tool Application Library Autotest Java Java 8, Java 11, Java 17 Gradle, Maven Python Python 3.8, FastAPI, Flask Python C# .Net 3.1, .Net 6.0 .Net Go Beego, Gin, Operator SDK Go JavaScript React, Vue, Angular, Express, Next.js, Antora NPM HCL Terraform Terraform Helm Helm, Pipeline Helm Groovy Codenarc Codenarc Rego OPA OPA Container Docker KanikoEPAM Delivery Platform (EDP) is suitable for all aspects of delivery starting from development including the capability to deploy production environment. EDP architecture is represented on a diagram below.
Architecture
EDP consists of four cross-cutting concerns:
On the top of these indicated concerns, EDP adds several blocks that include:
Artifact samples: frontend, backend, mobile, applications, functional and non-functional autotests, workloads for 3rd party components that can be deployed together with applications.
Explore the EDP technology stack diagram
Technology stack
The EDP IaaS layer supports most popular public clouds AWS, Azure and GCP keeping the capability to be deployed on private/hybrid clouds based on OpenStack. EDP containers are based on Docker technology, orchestrated by Kubernetes compatible solutions.
There are two main options for Kubernetes provided by EDP:
There is no limitation to run EDP on vanilla Kubernetes.
"},{"location":"overview/#related-articles","title":"Related Articles","text":"RoadMap consists of three streams:
Goals:
OperatorHub is a defacto leading solution which consolidates Kubernetes Community around Operators. EDP follows the best practices of delivering Operators in a quick and reliable way. We want to improve Deployment and Management experience for our Customers by publishing all EDP operators on this HUB.
Another artifact aggregator which is used by EDP - ArtifactHub, that holds description for both components: stable and under-development.
OperatorHub. Keycloak Operator
EDP Keycloak Operator is now available from OperatorHub both for Upstream (Kubernetes) and OpenShift deployments.
"},{"location":"roadmap/#ii-architecture","title":"II. Architecture","text":"Goals:
Multiple instances of EDP are run in a single Kubernetes cluster. One way to achieve this is to use Multitenancy. Initially, Kiosk was selected as tools that provides this capability. An alternative option that EDP Team took into consideration is Capsule. Another tool which goes far beyond multitenancy is vcluster going a good candidate for e2e testing scenarios where one needs simple lightweight kubernetes cluster in CI pipelines.
EDP Release 3.5.3
The EPAM Delivery Platform (EDP) has added Capsule as a general tenant management solution for Kubernetes. Capsule is an open-source operator that enables you to create and manage multiple tenants on a shared Kubernetes cluster, while ensuring resource isolation, security, and governance.
EDP Release 3.5.3
Vcluster is actively used in EDP for e2e testing purposes.
"},{"location":"roadmap/#microservice-reference-architecture-framework","title":"Microservice Reference Architecture Framework","text":"EDP provides basic Application Templates for a number of technology stacks (Java, .Net, NPM, Python) and Helm is used as a deployment tool. The goal is to extend this library and provide: Application Templates which are built on pre-defined architecture patterns (e.g., Microservice, API Gateway, Circuit Breaker, CQRS, Event Driven) and Deployment Approaches: Canary, Blue/Green. This requires additional tools installation on cluster as well.
"},{"location":"roadmap/#policy-enforcement-for-kubernetes","title":"Policy Enforcement for Kubernetes","text":"Running workload in Kubernetes calls for extra effort from Cluster Administrators to ensure those workloads do follow best practices or specific requirements defined on organization level. Those requirements can be formalized in policies and integrated into: CI Pipelines and Kubernetes Cluster (through Admission Controller approach) - to guarantee proper resource management during development and runtime phases. EDP uses Open Policy Agent (from version 2.8.0), since it supports compliance check for more use-cases: Kubernetes Workloads, Terraform and Java code, HTTP APIs and many others. Kyverno is another option being checked in scope of this activity.
"},{"location":"roadmap/#secrets-management","title":"Secrets Management","text":"EDP should provide secrets management as a part of platform. There are multiple tools providing secrets management capabilities. The aim is to be aligned with GitOps and Operator Pattern approaches so HashiCorp Vault, Banzaicloud Bank Vaults, Bitnami Sealed Secrets are currently used for internal projects and some of them should be made publicly available - as a part of EDP Deployment.
EDP Release 2.12.x
External Secret Operator is a recommended secret management tool for the EDP components.
"},{"location":"roadmap/#release-management","title":"Release Management","text":"Conventional Commits and Conventional Changelog are two approaches to be used as part of release process. Today EDP provides only capabilities to manage Release Branches. This activity should address this gap by formalizing and implementing Release Process as a part of EDP. Topics to be covered: Versioning, Tagging, Artifacts Promotion.
"},{"location":"roadmap/#kubernetes-native-cicd-pipelines","title":"Kubernetes Native CI/CD Pipelines","text":"EDP has deprecated Jenkins in favour of Tekton. Jenkins is no longer available since EDP v3.4.4.
EDP Release 2.12.x
Argo CD is suggested as a solution providing the Continuous Delivery
capabilities.
EDP Release 3.0
Tekton is used as a CI/CD pipelines orchestration tool on the platform. Review edp-tekton GitHub repository that keeps all the logic behind this solution on the EDP (Pipelines, Tasks, TriggerTemplates, Interceptors, etc). Get acquainted with the series of publications on our Medium Page.
"},{"location":"roadmap/#advanced-edp-role-based-model","title":"Advanced EDP Role-based Model","text":"EDP has a number of base roles which are used across EDP. In some cases it is necessary to provide more granular permissions for specific users. It is possible to do this using Kubernetes Native approach.
"},{"location":"roadmap/#notifications-framework","title":"Notifications Framework","text":"EDP has a number of components which need to report their statuses: Build/Code Review/Deploy Pipelines, changes in Environments, updates with artifacts. The goal for this activity is to onboard Kubernetes Native approach which provides Notification capabilities with different sources/channels integration (e.g. Email, Slack, MS Teams). Some of these tools are Argo Events, Botkube.
"},{"location":"roadmap/#reconciler-component-retirement","title":"Reconciler Component Retirement","text":"Persistent layer, which is based on edp-db (PostgreSQL) and reconciler component should be retired in favour of Kubernetes Custom Resource (CR). The latest features in EDP are implemented using CR approach.
EDP Release 3.0
Reconciler component is deprecated and is no longer supported. All the EDP components are migrated to Kubernetes Custom Resources (CR).
"},{"location":"roadmap/#iii-building-blocks","title":"III. Building Blocks","text":"Goals:
EDP Release 2.12.x
SAST is introduced as a mandatory part of the CI Pipelines. The list of currently supported SAST scanners and the instruction on how to add them are also available.
"},{"location":"roadmap/#infrastructure-as-code","title":"Infrastructure as Code","text":"EDP Target tool for Infrastructure as Code (IaC) is Terraform. EDP sees two CI/CD scenarios while working with IaC: Module Development and Live Environment Deployment. Today, EDP provides basic capabilities (CI Pipelines) for Terraform Module Development. At the same time, currently EDP doesn't provide Deployment pipelines for Live Environments and the feature is under development. Terragrunt is an option to use in Live Environment deployment. Another Kubernetes Native approach to provision infrastructure components is Crossplane.
"},{"location":"roadmap/#database-schema-management","title":"Database Schema Management","text":"One of the challenges for Application running in Kubernetes is to manage database schema. There are a number of tools which provides such capabilities, e.g. Liquibase, Flyway. Both tools provide versioning control for database schemas. There are different approaches on how to run migration scripts in Kubernetes: in init container, as separate Job or as a separate CD stage. Purpose of this activity is to provide database schema management solution in Kubernetes as a part of EDP. EDP Team investigates SchemaHero tool and use-cases which suits Kubernetes native approach for database schema migrations.
"},{"location":"roadmap/#open-policy-agent","title":"Open Policy Agent","text":"Open Policy Agent is introduced in version 2.8.0. EDP now supports CI for Rego Language, so you can develop your own policies. The next goal is to provide pipeline steps for running compliance policies check for Terraform, Java, Helm Chart as a part of CI process.
"},{"location":"roadmap/#report-portal","title":"Report Portal","text":"EDP uses Allure Framework as a Test Report tool. Another option is to integrate Report Portal into EDP ecosystem.
EDP Release 3.0
Use ReportPortal to consolidate and analyze your Automation tests results. Consult our pages on how to perform reporting and Keycloak integration.
"},{"location":"roadmap/#carrier","title":"Carrier","text":"Carrier provides Non-functional testing capabilities.
"},{"location":"roadmap/#java-17","title":"Java 17","text":"EDP supports two LTS versions of Java: 8 and 11. The goal is to provide Java 17 (LTS) support.
EDP Release 3.2.1
CI Pipelines for Java 17 is available in EDP.
"},{"location":"roadmap/#velero","title":"Velero","text":"Velero is used as a cluster backup tool and is deployed as a part of Platform. Currently, Multitenancy/On-premise support for backup capabilities is in process.
"},{"location":"roadmap/#istio","title":"Istio","text":"Istio is to be used as a Service Mesh and to address challenges for Microservice or Distributed Architectures.
"},{"location":"roadmap/#kong","title":"Kong","text":"Kong is one of tools which is planned to use as an API Gateway solution provider. Another possible candidate for investigation is Ambassador API Gateway
"},{"location":"roadmap/#openshift-4x","title":"OpenShift 4.X","text":"EDP supports the OpenShift 4.9 platform.
EDP Release 2.12.x
EDP Platform runs on the latest OKD versions: 4.9 and 4.10. Creating the IAM Roles for Service Account is a recommended way to work with AWS Resources from the OKD cluster.
"},{"location":"roadmap/#iv-admin-console-ui","title":"IV. Admin Console (UI)","text":"Goals:
EDP Release 2.12.x
EDP Team has introduced a new UI component called EDP Headlamp, which will replace the EDP Admin Console in future releases. EDP Headlamp is based on the Kinvolk Headlamp UI Client.
EDP Release 3.0
EDP Headlamp is used as a Control Plane UI on the platform.
EDP Release 3.4
Since EDP v3.4.0, Headlamp UI has been renamed to EDP Portal.
"},{"location":"roadmap/#users-management","title":"Users Management","text":"EDP uses Keycloak as an Identity and Access provider. EDP roles/groups are managed inside the Keycloak realm, then these changes are propagated across the EDP Tools. We plan to provide this functionality in EDP Portal using the Kubernetes-native approach (Custom Resources).
"},{"location":"roadmap/#the-delivery-pipelines-dashboard","title":"The Delivery Pipelines Dashboard","text":"The CD Pipeline section in EDP Portal provides basic information, such as environments, artifact versions deployed per each environment, and direct links to the namespaces. One option is to enrich this panel with metrics from the Prometheus, custom resources, or events. Another option is to use the existing dashboards and expose EDP metrics to them, for example, plugin for Lens or OpenShift UI Console.
"},{"location":"roadmap/#split-jira-and-commit-validation-sections","title":"Split Jira and Commit Validation Sections","text":"Commit Validate step was initially designed to be aligned with Jira Integration and cannot be used as single feature. Target state is to ensure features CommitMessage Validation and Jira Integration both can be used independently. We also want to add support for Conventional Commits.
EDP Release 3.2.0
EDP Portal has separate sections for Jira Integration and CommitMessage Validation step.
"},{"location":"roadmap/#v-documentation-as-code","title":"V. Documentation as Code","text":"Goal:
Consolidate documentation in a single repository edp-install, use mkdocs
tool to generate docs and GitHub Pages as a hosting solution.
EPAM Delivery Platform supports only the three last versions. For a stable performance, the EDP team recommends installing the corresponding Kubernetes and OpenShift versions as indicated in the table below.
Get acquainted with the list of the latest releases and component versions on which the platform is tested and verified:
EDP Release Version Release Date EKS Version OpenShift Version 3.6 Nov 03, 2023 1.26 4.12 3.5 Sep 21, 2023 1.26 4.12 3.4 Aug 18, 2023 1.26 4.12 3.3 May 25, 2023 1.26 4.12 3.2 Mar 26, 2023 1.23 4.10 3.1 Jan 24, 2023 1.23 4.10 3.0 Dec 19, 2023 1.23 4.10 2.12 Aug 30, 2023 1.23 4.10"},{"location":"developer-guide/","title":"Overview","text":""},{"location":"developer-guide/#overview","title":"Overview","text":"The EPAM Delivery Platform (EDP) Developer Guide serves as a comprehensive technical resource specifically designed for developers. It offers detailed insights into expanding the functionalities of EDP. This section focuses on explaining the development approach and fundamental architectural blueprints that form the basis of the platform's ecosystem.
Within these pages, you'll find architectural diagrams, component schemas, and deployment strategies essential for grasping the structural elements of EDP. These technical illustrations serve as references, providing a detailed understanding of component interactions and deployment methodologies. Understanding the architecture of EDP and integrating third-party solutions into its established framework enables the creation of efficient, scalable, and customizable solutions within the EPAM Delivery Platform.
"},{"location":"developer-guide/aws-deployment-diagram/","title":"AWS Deployment Diagram","text":""},{"location":"developer-guide/aws-deployment-diagram/#edp-deployment-on-aws","title":"EDP Deployment on AWS","text":"This document describes the EPAM Delivery Platform (EDP) deployment architecture on AWS. It utilizes various AWS services such as Amazon Elastic Kubernetes Service (EKS), Amazon EC2, Amazon Route 53, and others to build and deploy software in a repeatable, automated way.
"},{"location":"developer-guide/aws-deployment-diagram/#overview","title":"Overview","text":"The EDP deployment architecture consists of two AWS accounts: Shared and Explorer. The Shared account hosts shared services, while the Explorer account runs the development team workload and EDP services. Both accounts have an AWS EKS cluster deployed in multiple Availability Zones (AZs). The EKS cluster runs the EDP Services, development team workload, and shared services in the case of the Shared account.
EPAM Delivery Platform Deployment Diagram on AWS
"},{"location":"developer-guide/aws-deployment-diagram/#key-components","title":"Key Components","text":"The EKS cluster is deployed across multiple AZs to ensure high availability and fault tolerance. This allows for automatic failover in case of an AZ outage or instance failure. Autoscaling Groups automatically adjust the number of EC2 instances based on demand, ensuring scalability while maintaining availability.
"},{"location":"developer-guide/aws-deployment-diagram/#design-considerations","title":"Design Considerations","text":""},{"location":"developer-guide/aws-deployment-diagram/#reliability","title":"Reliability","text":"The EPAM Delivery Platform (EDP) deployment architecture on AWS follows best practices and patterns from the Well-Architected Framework. By leveraging AWS services such as EKS, EC2, Route 53, ALB, WAF, ACM, and Parameter Store, the EDP provides a robust and scalable CI/CD system that enables developers to deploy and manage infrastructure and applications quickly. The architecture ensures high availability, fault tolerance, reliability, performance efficiency, security, and cost optimization for the EDP deployment.
"},{"location":"developer-guide/aws-reference-architecture/","title":"AWS Reference Architecture","text":""},{"location":"developer-guide/aws-reference-architecture/#edp-reference-architecture-on-aws","title":"EDP Reference Architecture on AWS","text":"The reference architecture of the EPAM Delivery Platform (EDP) on AWS is designed to provide a robust and scalable CI/CD system for developing and deploying software in a repeatable and automated manner. The architecture leverages AWS Managed Services to enable developers to quickly deploy and manage infrastructure and applications. EDP recommends to follow the best practices and patterns from the Well-Architected Framework, the AWS Architecture Center, and EKS Best Practices Guide.
"},{"location":"developer-guide/aws-reference-architecture/#architecture-details","title":"Architecture Details","text":"The AWS Cloud comprises three accounts: Production, Shared, and Development.
Note
AWS Account management is out of scope for this document.
Each account serves specific purposes:
EPAM Delivery Platform Reference Architecture on AWS
"},{"location":"developer-guide/aws-reference-architecture/#infrastructure-as-code","title":"Infrastructure as Code","text":"Infrastructure as Code (IaC) is a key principle in the EPAM Delivery Platform architecture. Terraform is the IaC tool to provision and manage all services in each account. AWS S3 and AWS DynamoDB serve as the backend for Terraform state, ensuring consistency and reliability in the deployment process. This approach enables the architecture to be version-controlled and allows for easy replication and reproducibility of environments.
"},{"location":"developer-guide/aws-reference-architecture/#docker-registry","title":"Docker Registry","text":"The architecture utilizes AWS Elastic Container Registry (ECR) as a Docker Registry for container image management. ECR offers a secure, scalable, and reliable solution for storing and managing container images. It integrates seamlessly with other AWS services and provides a highly available and durable storage solution for containers in the CI/CD pipeline.
"},{"location":"developer-guide/aws-reference-architecture/#iam-roles-for-service-accounts-irsa","title":"IAM Roles for Service Accounts (IRSA)","text":"The EPAM Delivery Platform implements IAM Roles for Service Accounts (IRSA) to provide secure access to AWS services from Kubernetes Clusters. This feature enables fine-grained access control with individual Kubernetes pods assuming specific IAM roles for authenticated access to AWS resources. IRSA eliminates the need for managing and distributing access keys within the cluster, significantly enhancing security and reducing operational complexity.
"},{"location":"developer-guide/aws-reference-architecture/#ssl-certificates","title":"SSL Certificates","text":"The architecture uses the AWS Certificate Manager (ACM) to secure communication between services to provide SSL certificates. ACM eliminates the need to manually manage SSL/TLS certificates, automating the renewal and deployment process. The EPAM Delivery Platform ensures secure and encrypted traffic within its environment by leveraging ACM.
"},{"location":"developer-guide/aws-reference-architecture/#aws-waf","title":"AWS WAF","text":"The architecture's external Application Load Balancer (ALB) endpoint is protected by the AWS Web Application Firewall (WAF). WAF protects against common web exploits and ensures the security and availability of the applications hosted within the EPAM Delivery Platform. It offers regular rule updates and easy integration with other AWS services.
"},{"location":"developer-guide/aws-reference-architecture/#parameter-store-and-secrets-manager","title":"Parameter Store and Secrets Manager","text":"The architecture leverages the AWS Systems Manager Parameter Store and Secrets Manager to securely store and manage all secrets and parameters utilized within the EKS clusters\u2014parameter Store stores general configuration information, such as database connection strings and API keys. In contrast, Secrets Manager securely stores sensitive information, such as passwords and access tokens. By centralizing secrets management, the architecture ensures proper access control and reduces the risk of unauthorized access.
"},{"location":"developer-guide/aws-reference-architecture/#summary","title":"Summary","text":"The reference architecture of the EPAM Delivery Platform on AWS provides a comprehensive and scalable environment for building and deploying software applications. With a strong focus on automation, security, and best practices, this architecture enables developers to leverage the full potential of AWS services while following industry-standard DevOps practices.
"},{"location":"developer-guide/edp-workflow/","title":"Contribution Guide","text":""},{"location":"developer-guide/edp-workflow/#edp-project-rules-working-process","title":"EDP Project Rules. Working Process","text":"This page contains the details on the project rules and working process for EDP team and contributors. Explore the main points about working with Gerrit, following the main commit flow, as well as the details about commit types and message below.
"},{"location":"developer-guide/edp-workflow/#project-rules","title":"Project Rules","text":"Before starting the development, please check the project rules:
It is highly recommended to become familiar with the Gerrit flow. For details, please refer to the Gerrit official documentation and pay attention to the main points:
a. Voting in Gerrit.
b. Resolution of Merge Conflict.
c. Comments resolution.
d. One Jira task should have one Merge Request (MR). If there are many changes within one MR, add the next patch set to the open MR by selecting the Amend commit check box.
Only the Assignee is responsible for the MR merge and Jira task status.
Every MR should be merged in a timely manner.
Log time to Jira ticket.
With EDP, the main workflow is based on the getting a Jira task and creating a Merge Request according to the rules described below.
Workflow
Get Jira task \u2192 implement, verify by yourself the results \u2192 create Merge Request (MR) \u2192 send for review \u2192 resolve comments/add changes, ask colleagues for the final review \u2192 track the MR merge \u2192 verify by yourself the results \u2192 change the status in the Jira ticket to CODE COMPLETE or RESOLVED \u2192 share necessary links with a QA specialist in the QA Verification channel \u2192 QA specialist closes the Jira task after his verification \u2192 Jira task should be CLOSED.
Commit Flow
Get a task in the Jira/GitHub dashboard. Please be aware of the following points:
JiraGitHuba. Every task has a reporter who can provide more details in case something is not clear.
b. The responsible person for the task and code implementation is the assignee who tracks the following:
c. Pay attention to the task Status that differs in different entities, the workflow will help to see the whole task processing:
View Jira workflow
d. There are several entities that are used on the EDP project: Story, Improvement, Task, Bug.
a. Every task has a reporter who can provide more details in case something is not clear.
b. The responsible person for the task and code implementation is the assignee who tracks the following:
c. If the task is created on your own, make sure it is populated completely. See an example below:
GitHub issue
Implement feature, improvement, fix and check the results on your own. If it is impossible to check the results of your work before the merge, verify all later.
Create a Merge Request, for details, please refer to the Code Review Process.
When committing, use the pattern: commit type: Commit message (#GitHub ticket number).
a. commit type:
feat
: (new feature for the user, not a new feature for build script)
fix
: (bug fix for the user, not a fix to a build script)
docs
: (changes to the documentation)
style
: (formatting, missing semicolons, etc; no production code change)
refactor
: (refactoring production code, eg. renaming a variable)
test
: (adding missing tests, refactoring tests; no production code change)
chore
: (updating grunt tasks etc; no production code change)
!
: (added to other commit types to mark breaking changes) For example:
feat!: Add ingress links column into Applications table on stage page (#77)\n\nBREAKING CHANGE: Ingress links column has been added into the Applications table on the stage details page\n
b. Commit message:
brief, for example:
fix: Remove secretKey duplication from registry secrets (#63)
or
descriptive, for example:
feat: Provide the ability to configure hadolint check (#88)\n\n*Add configuration files .hadolint.yaml and .hadolint.yml to stash\n
Note
It is mandatory to start a commit message from a capital letter.
c. GitHub tickets are typically identified using a number preceded by the # sign and enclosed in parentheses.
Note
Make sure there is a descriptive commit message for a breaking change Merge Request. For example:
feat!: Add ingress links column into Applications table on stage page (#77)
BREAKING CHANGE: Ingress links column has been added into the Applications table on the stage details page
Note
If a Merge Request contains both new functionality and breaking changes, make sure the functionality description is placed before the breaking changes. For example:
feat!: Update Gerrit to improve access
BREAKING CHANGES: Update Gerrit config according to groups
"},{"location":"developer-guide/edp-workflow/#related-articles","title":"Related Articles","text":"This section provides a comprehensive overview of the EDP deployment approach on a Kubernetes cluster. EDP is designed and functions based on a set of key guiding principles:
Loosely Coupling: EDP comprises several loosely coupled operators responsible for different platform parts. These operators can be deployed independently, enabling the most straightforward platform customization and delivery approach.
Kubernetes Operator
The following deployment diagram illustrates the platform's core components, which provide the minimum functional capabilities required for the platform operation: build, push, deploy, and run applications. The platform relies on several mandatory dependencies:
EPAM Delivery Platform Deployment Diagram
Business applications are deployed on the platform using the CD Pipeline Operator and Argo CD. By default, the CD Pipeline Operator uses Argo CD as a deployment tool. However, it can be replaced with any other tool, like FluxCD, Spinnaker, etc. The target environment for the application deployment is a Kubernetes cluster where EDP is deployed, but it can be any other Kubernetes cluster.
"},{"location":"developer-guide/local-development/","title":"Operator Development","text":""},{"location":"developer-guide/local-development/#workspace-setup-manual","title":"Workspace Setup Manual","text":"This page is intended for developers with the aim to share details on how to set up the local environment and start coding in Go language for EPAM Delivery Platform.
"},{"location":"developer-guide/local-development/#prerequisites","title":"Prerequisites","text":"Note
Make sure GOPATH and GOROOT environment variables are added in PATH.
"},{"location":"developer-guide/local-development/#environment-setup","title":"Environment Setup","text":"Set up your environment by following the steps below.
"},{"location":"developer-guide/local-development/#set-up-your-ide","title":"Set Up Your IDE","text":"We recommend using GoLand and enabling the Kubernetes plugin. Before installing plugins, make sure to save your work because IDE may require restarting.
"},{"location":"developer-guide/local-development/#set-up-your-operator","title":"Set Up Your Operator","text":"To set up the cloned operator, follow the three steps below:
Configure Go Build Option. Open folder in GoLand, click the button and select the Go Build
option:
Add configuration
Fill in the variables in Configuration tab:
Files
field, indicate the path to the main.go file;Working directory
field, indicate the path to the operator;Environment field
, specify the namespace to watch by setting WATCH_NAMESPACE
variable. It should equal default
but it can be any other if required by the cluster specifications.Environment field
, also specify the platform type by setting PLATFORM_TYPE
. It should equal either kubernetes
or openshift
.Build config
Check cluster connectivity and variables. Local development implies working within local Kubernetes clusters. Kind (Kubernetes in Docker) is recommended so set this or another environment first before running code.
Before making commit and sending pull request, take care of precautionary measures to avoid crashing some other parts of the code.
"},{"location":"developer-guide/local-development/#testing-and-linting","title":"Testing and Linting","text":"Testing and linting must be used before every single commit with no exceptions. The instructions for the commands below are written here.
It is mandatory to run test and lint to make sure the code passes the tests and meets acceptance criteria. Most operators are covered by tests so just run them by issuing the commands \"make test\" and \"make lint\":
make test\n
The command \"make test\" should give the output similar to the following:
\"make test\" command
make lint\n
The command \"make lint\" should give the output similar to the following:
\"make lint\" command
"},{"location":"developer-guide/local-development/#observe-auto-generated-docs-api-and-manifests","title":"Observe Auto-Generated Docs, API and Manifests","text":"The commands below are especially essential when making changes to API. The code is unsatisfactory if these commands fail.
Generate documentation in the .MD file format so the developer can read it:
make api-docs\n
The command \"make api-docs\" should give the output similar to the following:
\"make api-docs\" command with the file contents
There are also manifests within the operator that generate zz_generated.deepcopy.go file in /api/v1 directory. This file is necessary for the platform to work but it's time-consuming to fill it by yourself so there is a mechanism that does it automatically. Update it using the following command and check if it looks properly:
make generate\n
The command \"make generate\" should give the output similar to the following:
\"make generate\" command
Refresh custom resource definitions for Kubernetes, thus allowing the cluster to know what resources it deals with.
make manifests\n
The command \"make manifests\" should give the output similar to the following:
\"make manifests\" command
At the end of the procedure, you can push your code confidently to your branch and create a pull request.
That's it, you're all set! Good luck in coding!
"},{"location":"developer-guide/local-development/#related-articles","title":"Related Articles","text":"This section defines necessary steps to start developing the EDP documentation in the MkDocs Framework. The framework presents a static site generator with documentation written in Markdown. All the docs are configured with a YAML configuration file.
Note
For more details on the framework, please refer to the MkDocs official website.
There are two options for working with MkDocs:
Please see below the detailed description of each options and choose the one that suits you.
"},{"location":"developer-guide/mk-docs-development/#mkdocs-with-docker","title":"MkDocs With Docker","text":"Prerequisites:
make
utility is installed.To work with MkDocs, take the following steps:
Clone the edp-install repository to your local folder.
Run the following command:
make docs
Enter the localhost:8000 address in the browser and check that documentation pages are available.
Open the file editor, navigate to edp-install->docs and make necessary changes. Check all the changes at localhost:8000.
Create a merge request with changes.
Prerequisites:
To work with MkDocs without Docker, take the following steps:
Clone the edp-install repository to your local folder.
Run the following command:
pip install -r hack/mkdocs/requirements.txt\n
Run the local development command:
mkdocs serve --dev-addr 0.0.0.0:8000\n
Note
This command may not work on Windows, so a quick solution is:
python -m mkdocs serve --dev-addr 0.0.0.0:8000\n
Enter the localhost:8000 address in the browser and check that documentation pages are available.
Open the file editor, navigate to edp-install->docs and make necessary changes. Check all the changes at localhost:8000.
Create a merge request with changes.
The EPAM Delivery Platform\u2019s (EDP) Reference Architecture serves as a blueprint for software delivery, outlining the best practices, tools, and technologies leveraged by the platform to ensure efficient and high-quality software development. It provides a comprehensive guide to navigate the complexities of software delivery, from code to deployment.
EDP operates on Kubernetes, a leading open-source system for automating deployment, scaling, and management of containerized applications. It consolidates a variety of open-source tools, ensuring a flexible and adaptable system that can seamlessly run on any public cloud or on-premises infrastructure. This versatility allows for a wide range of deployment options, catering to diverse business needs and operational requirements.
"},{"location":"developer-guide/reference-architecture/#key-principles","title":"Key Principles","text":"The EPAM Delivery Platform (EDP) is built on a set of key principles that guide its design and functionality:
EDP encompasses a comprehensive CI/CD ecosystem integrating essential tools such as the Tekton and Argo CD, augmented by additional functionalities. Within this robust framework, EDP seamlessly integrates SonarQube for continuous code quality assessment, enabling thorough analysis and ensuring adherence to coding standards. Additionally, incorporating Static Application Security Testing (SAST) toolset fortifies platform's security posture by proactively identifying vulnerabilities within the codebase. EDP leverages dedicated artifact storage solutions to manage and version application artifacts securely, ensuring streamlined deployment processes and traceability throughout the software development lifecycle. See the reference architecture diagram below.
EPAM Delivery Platform Reference Architecture
Developers access the platform by authenticating with their corporate credentials. The platform utilizes OpenID Connect (OIDC) for authentication and authorization across all tools and Kubernetes clusters. Using OIDC, EDP establishes a unified and secure authentication mechanism, ensuring seamless access control and user authentication for all integrated tools. This standardized approach upholds strict security protocols, ensuring consistency in authentication and authorization policies across the platform ecosystem. To integrate existing Identity Providers (IdPs), Keycloak serves as an identity broker on the platform. EDP offers the keycloak-operator to streamline Keycloak integration within the platform.
Developers engage with the platform via the EDP Portal, an intuitive interface offering a comprehensive overview of the platform\u2019s capabilities. This centralized hub facilitates seamless navigation and access to various platform tools and components. Within the EDP Portal, developers can generate new components (codebases). The platform integrates with version control systems, optimizing source code management, fostering collaboration, and streamlining code review processes. To create new codebases, developers utilize Application Templates, ensuring a standardized approach to application development. The platform accommodates a range of application templates such as Java, Node.js, .NET, Python, and more. Additionally, developers can design custom templates via the EDP Marketplace to cater to their specific requirements.
Tekton is a potent, adaptable, and cloud-native framework designed for crafting CI/CD systems. It offers a collection of shared, reusable components that empower developers to construct, test, and deploy applications across various cloud providers or on-premises systems. As a foundational element within the EDP CI/CD ecosystem, Tekton seamlessly integrates with other tools and services, providing a robust and adaptable framework for constructing CI/CD pipelines. Tekton Pipelines allow developers to efficiently build, test, and deploy applications, while Tekton Triggers initiate pipelines based on specific events.
The codebase operator is a crucial part of the platform ecosystem. It manages codebases, their creation, deletion, and scaffolding, as well as their associated resources. It provides versioning, branching, and release capabilities and enables seamless integration with Git servers and Jira.
The platform has various cloud-agnostic tools that offer different functionalities, such as artifact storage, static security analysis, and code quality assessment. These tools are accessible through pipelines and codebase controllers. Additionally, the platform supports integration with managed services from cloud providers to deliver its core functionality\u2014for instance, AWS Parameter Store stores secrets and AWS ECR - container images. AzureDevops Artifacts is an option to store artifacts leveraging Azure Cloud capabilities. SonarCloud, a cloud-based version of SonarQube, can be integrated to conduct static code analysis.
The CD Pipeline Operator oversees CD pipelines and their related resources. It offers a collection of shared, reusable components for constructing CD pipelines. Integrated with Tekton and Argo CD, the CD Pipeline Operator harnesses their capabilities, ensuring a robust and dependable software delivery process. With a Kubernetes API interface, the CD Pipeline Operator facilitates the management of CD pipelines. It enables artifact promotion logic and the triggering of CD pipelines based on specific events, further enhancing the efficiency and adaptability of the software delivery workflow.
Argo CD is a pivotal deployment tool adopted within the platform, embracing the GitOps delivery approach. It serves as the foundation for deploying both operational and business workloads. EDP recommends running a dedicated Argo CD instance to manage operational workloads, employing the Kubernetes add-ons approach for streamlined management.
Production workloads operate in isolation within dedicated Kubernetes clusters to uphold stringent standards and ensure the utmost security and resource allocation. This approach guarantees the highest isolation and operational integrity levels for critical production systems, aligning with industry best practices. EDP strongly recommends utilizing a pull model for production deployment. In this model, production deployment is initiated by the Argo CD instance explicitly deployed for the production environment.
The Platform is meticulously engineered to uphold best practices in workload distribution across various environments, including development, testing (manual/automation), user acceptance (UAT), staging, and production. While lower environments like development and testing may feasibly share clusters for workload efficiency, EDP strongly advocates and enforces the necessity of segregating production workloads into dedicated clusters. This segregation ensures the highest isolation, security, and resource allocation levels for mission-critical production systems, adhering to industry standards and ensuring optimal operational integrity.
EDP harnesses the robust capabilities of Kubernetes in conjunction with a suite of powerful tools tailored for monitoring, logging, and tracing. It integrates the Prometheus stack within ecosystem, leveraging its metrics collection, storage, and querying capabilities to enable comprehensive monitoring of system performance and health. EDP runs OpenSearch for centralized logging, enabling efficient log aggregation, analysis, and management across the platform. Incorporating OpenTelemetry enables standardized and seamless observability data collection, facilitating deep insights into platform behavior and performance. Additionally, it allows for connection with external aggregators and tools that support the OpenTelemetry protocol (OTLP).
Platform and Tools
EDP integrates with GitLab, GitHub, and Gerrit for version control. These systems are foundational components enabling efficient source code management, collaboration, and code review processes.
Platform ensures robust security measures by leveraging OpenID Connect (OIDC) for authentication and authorization across all platform tools and Kubernetes clusters. By employing OIDC, EDP establishes a unified and secure authentication mechanism, enabling seamless access control and user authentication for all tools integrated into the platform. This standardized approach ensures stringent security protocols, maintaining authentication consistency and authorization policies across the platform ecosystem.
"},{"location":"developer-guide/reference-cicd-pipeline/","title":"Reference CI/CD Pipeline","text":""},{"location":"developer-guide/reference-cicd-pipeline/#reference-cicd-pipeline","title":"Reference CI/CD Pipeline","text":"This document provides an in-depth overview of the Continuous Integration and Continuous Delivery (CI/CD) pipeline reference architecture implemented within the EPAM Delivery Platform (EDP). The pipeline is designed to facilitate efficient and automated software deployment across diverse environments, leveraging a suite of tools and methodologies for enhanced reliability, scalability, and security.
"},{"location":"developer-guide/reference-cicd-pipeline/#cicd-pipeline-architecture","title":"CI/CD Pipeline Architecture","text":"The CI/CD pipeline within EDP orchestrates the software delivery process, encompassing several sequential stages to ensure robustness and reliability.
EPAM Delivery Platform Reference CI/CD Pipeline
The CI/CD Pipeline follows a modular and scalable architecture that leverages various tools to ensure the reliability and efficiency of the software delivery process. The architecture can be divided into stages, each responsible for specific tasks. Explore the key components involved in the pipeline and their functionalities.
Source Code: The pipeline starts with the source code, representing the application's codebase. Developers commit their changes to the source code repository, triggering the pipeline.
Validate Commit Message: The commit message validation component checks the format and content of the commit message. It ensures the commit message follows the correct format and includes a valid Tracking Issue key. It helps maintain a standardized commit message format throughout the application development.
Build: The Build component compiles the source code, runs unit tests, and generates the application artifact. It consumes the artifact from the Artifact Repository (Nexus), ensuring consistent and reliable builds.
SAST with SonarQube: The Static Analysis Security Testing (SAST) component utilizes SonarQube to analyze the source code for potential security vulnerabilities, code smells, and quality issues. This step helps identify and address security or code quality issues early in development.
SCA: The Software Composition Analysis (SCA) component performs dependency analysis using cdxgen, Dependency-Track, semgrep, and DefectDojo. It checks for known vulnerabilities or license compliance issues in the application's dependencies. By identifying and resolving these issues, it ensures the security and stability of the software.
Publish: The Publish component publishes the application artifact to the Artifact Repository. It posts Docker images to the Docker Registry and stores binary artifacts in the Nexus Repository. This process ensures that the artifacts are securely stored and easily accessed for future deployments.
Deploy: The Deploy component uses Argo CD or Tekton to deploy applications to target environments in Kubernetes, leveraging Helm charts to ensure seamless deployment. Deploy to Test/Quality Assurance/Performance Environments: The final stages of the pipeline involve deploying the application to different environments for testing and quality assurance purposes. The results of the tests are consolidated and reported to the Report Portal, facilitating efficient test reporting and analysis.
The overall architecture of the CI/CD Pipeline ensures a streamlined and automated software delivery process, from source code to deployment. It provides developers with the necessary tools and processes to ensure their applications' quality, security, and scalability. Furthermore, Tekton Chains enhances supply chain security by signing and generating in-toto metadata that verifies the integrity of artifacts and the CI/CD Pipeline.
Note
The tools mentioned in this document are just examples and can be replaced with other tools that offer similar functionality. For instance, instead of Harbor for the Docker Registry, it is possible to use AWS ECR. Consider using Azure Artefacts or JFrog Artifactory instead of Nexus for the artifact repository. Instead of setting up an self-managed instance of SonarQube, leverage SonarCloud, the cloud-based version of SonarQube, as an alternative. The CI/CD Pipeline architecture is flexible and adaptable, allowing the use of different tools based on specific project requirements and platform preferences.
"},{"location":"operator-guide/","title":"Overview","text":""},{"location":"operator-guide/#overview","title":"Overview","text":"The EDP Operator guide is intended for DevOps and provides information on EDP installation, configuration and customization, as well as the platform support. Inspect the documentation to adjust the EPAM Delivery Platform according to your business needs:
Inspect the main steps to add and update Jenkins agent.
"},{"location":"operator-guide/add-jenkins-agent/#createupdate-jenkins-agent","title":"Create/Update Jenkins Agent","text":"Every Jenkins agent is based on epamedp/edp-jenkins-base-agent. Check DockerHub for the latest version. Use it to create a new agent (or update an old one). See the example with Dockerfile of gradle-java11-agent below:
View: Dockerfile # Copyright 2021 EPAM Systems.\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n # http://www.apache.org/licenses/LICENSE-2.0\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n\n FROM epamedp/edp-jenkins-base-agent:1.0.1\n SHELL [\"/bin/bash\", \"-o\", \"pipefail\", \"-c\"]\n ENV GRADLE_VERSION=7.1 \\\n PATH=$PATH:/opt/gradle/bin\n\n # Install Gradle\n RUN curl -skL -o /tmp/gradle-bin.zip https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip && \\\n mkdir -p /opt/gradle && \\\n unzip -q /tmp/gradle-bin.zip -d /opt/gradle && \\\n ln -sf /opt/gradle/gradle-$GRADLE_VERSION/bin/gradle /usr/local/bin/gradle\n\n RUN yum install java-11-openjdk-devel.x86_64 -y && \\\n rpm -V java-11-openjdk-devel.x86_64 && \\\n yum clean all -y\n\n WORKDIR $HOME/.gradle\n\n RUN chown -R \"1001:0\" \"$HOME\" && \\\n chmod -R \"g+rw\" \"$HOME\"\n\n USER 1001\n
After the Docker agent update/creation, build and load the image into the project registry (e.g. DockerHub, AWS ECR, etc.).
"},{"location":"operator-guide/add-jenkins-agent/#add-jenkins-agent-configuration","title":"Add Jenkins Agent Configuration","text":"To add a new Jenkins agent, take the steps below:
Run the following command. Please be aware that edp
is the name of the EDP tenant.
kubectl edit configmap jenkins-slaves -n edp\n
Note
On an OpenShift cluster, run the oc
command instead of kubectl
one.
Add new agent template. View: ConfigMap jenkins-slaves
data:\n docker-template: |-\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>docker</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>docker</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>IMAGE_NAME:IMAGE_TAG</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n
Note
The name and label properties should be unique(docker in the example above). Insert image name and tag instead of IMAGE_NAME:IMAGE_TAG.
Open Jenkins to ensure that everything is added correctly. Click the Manage Jenkins option, navigate to the Manage Nodes and Clouds->Configure Clouds->Kubernetes->Pod Templates..., and scroll down to find new Jenkins agent Pod Template details...:
Jenkins pod template
As a result, the newly added Jenkins agent will be available in the Advanced Settings block of the Admin Console tool during the codebase creation:
Advanced settings
If your application is integrated with EDP, take the steps below to change an existing agent configuration:
Run the following command. Please be aware that edp
is the name of the EDP tenant.
kubectl edit configmap jenkins-slaves -n edp\n
Note
On an OpenShift cluster, run the oc
command instead of kubectl
one.
Find the agent template in use and change and change the parameters.
Open Jenkins and check the correct addition. Click the Manage Jenkins option, navigate to the Manage Nodes and Clouds->Configure Clouds->Kubernetes->Pod Templates..., and scroll down to Pod Template details... with the necessary data.
This page describes the entity of Cluster Add-Ons for EPAM Delivery Platform, as well as their purpose, benefits and usage.
"},{"location":"operator-guide/add-ons-overview/#what-are-add-ons","title":"What Are Add-Ons","text":"EDP Add-Ons is basically a Kubernetes-based structure that enables users to quickly install additional components for the platform using Argo CD applications.
Add-Ons have been introduced into EDP starting from version 3.4.0. They empower users to seamlessly incorporate the platform with various additional components, such as SonarQube, Nexus, Keycloak, Jira, and more. This eliminates the need for manual installations, as outlined in the Install EDP page.
In a nutshell, Add-Ons represent separate Helm Charts that imply to be installed by one click using the Argo CD tool.
"},{"location":"operator-guide/add-ons-overview/#add-ons-repository-structure","title":"Add-Ons Repository Structure","text":"All the Add-Ons are stored in our public GitHub repository adhering to the GitOps approach. Apart from default Helm and Git files, it contains both custom resources called Applications for Argo CD and application source code. The repository follows the GitOps approach to enable Add-Ons with the capability to rollback changes when needed. The repository structure is the following:
\u251c\u2500\u2500 CHANGELOG.md\n \u251c\u2500\u2500 LICENSE\n \u251c\u2500\u2500 Makefile\n \u251c\u2500\u2500 README.md\n \u251c\u2500\u2500 add-ons\n \u2514\u2500\u2500 chart\n
To enable EDP Add-Ons, it is necessary to have the configured Argo CD, and connect and synchronize the forked repository. To do this, follow the guidelines below:
Fork the Add-Ons repository to your personal account.
Provide the parameter values for the values.yaml files of the desired Add-Ons you are going to install.
Navigate to Argo CD -> Settings -> Repositories. Connect your forked repository where you have the values.yaml files changed by clicking the + Connect repo button:
Connect the forked repository
In the appeared window, fill in the following fields and click the Connect button:
Repository parameters
As soon as the repository is connected, the new item in the repository list will appear:
Connected repository
Navigate to Argo CD -> Applications. Click the + New app button:
Adding Argo CD application
Fill in the required fields:
As soon as the repository is synchronized, the list of applications that can be installed by Add-Ons will be shown:
Add-Ons list
Now that Add-Ons are enabled in Argo CD, they can be installed by following the steps below:
Choose the Add-On to install.
On the chosen Add-On, click the \u22ee button and then Details:
Open Add-Ons
To install the Add-On, click the \u22ee button -> Sync:
Install Add-Ons
Once the Add-On is installed, the Sync OK message will appear in the Add-On status bar:
Sync OK message
Open the application details by clicking on the little square with an arrow underneath the Add-On name:
Open details
Track application resources and status in the App details menu:
Application details
As we see, Argo CD offers great observability and monitoring tools for its resources which comes in handy when using EDP Add-Ons.
"},{"location":"operator-guide/add-ons-overview/#available-add-ons-list","title":"Available Add-Ons List","text":"The list of the available Add-Ons:
Name Description Default Argo CD A GitOps continuous delivery tool that helps automate the deployment, configuration, and lifecycle management of applications in Kubernetes clusters. false AWS EFS CSI Driver A Container Storage Interface (CSI) driver that enables the dynamic provisioning of Amazon Elastic File System (EFS) volumes in Kubernetes clusters. true Cert Manager A native Kubernetes certificate management controller that automates the issuance and renewal of TLS certificates. true DefectDojo A security vulnerability management tool that allows tracking and managing security findings in applications. true DependencyTrack A Software Composition Analysis (SCA) platform that helps identify and manage open-source dependencies and their associated vulnerabilities. true EDP An internal platform created by EPAM to enhance software delivery processes using DevOps principles and tools. false Extensions OIDC EDP Helm chart to provision OIDC clients for different Add-Ons using EDP Keycloak Operator. true External Secrets A Kubernetes Operator that fetches secrets from external secret management systems and injects them as Kubernetes Secrets. true Fluent Bit A lightweight and efficient log processor and forwarder that collects and routes logs from various sources in Kubernetes clusters. false Harbor A cloud-native container image registry that provides support for vulnerability scanning, policy-based image replication, and more. true Nginx ingress An Ingress controller that provides external access to services running within a Kubernetes cluster using Nginx as the underlying server. true Jaeger Operator An operator for deploying and managing Jaeger, an end-to-end distributed tracing system, in Kubernetes clusters. true Keycloak An open-source Identity and Access Management (IAM) solution that enables authentication, authorization, and user management in Kubernetes clusters. true Keycloak PostgreSQL A PostgreSQL database operator that simplifies the deployment and management of PostgreSQL instances in Kubernetes clusters. false MinIO Operator An operator that simplifies the deployment and management of MinIO, a high-performance object storage server compatible with Amazon S3, in Kubernetes clusters. true OpenSearch A community-driven, open-source search and analytics engine that provides scalable and distributed search capabilities for Kubernetes clusters. true OpenTelemetry Operator An operator for automating the deployment and management of OpenTelemetry, a set of observability tools for capturing, analyzing, and exporting telemetry data. true PostgreSQL Operator An operator for running and managing PostgreSQL databases in Kubernetes clusters with high availability and scalability. true Prometheus Operator An operator that simplifies the deployment and management of Prometheus, a monitoring and alerting toolkit, in Kubernetes clusters. true Redis Operator An operator for managing Redis, an in-memory data structure store, in Kubernetes clusters, providing high availability and horizontal scalability. true StorageClass A Kubernetes resource that provides a way to define different classes of storage with different performance characteristics for persistent volumes. true Tekton A flexible and cloud-native framework for building, testing, and deploying applications using Kubernetes-native workflows. true Vault An open-source secrets management solution that provides secure storage, encryption, and access control for sensitive data in Kubernetes clusters. true"},{"location":"operator-guide/add-other-code-language/","title":"Add Other Code Language","text":""},{"location":"operator-guide/add-other-code-language/#add-other-code-language","title":"Add Other Code Language","text":"There is an ability to extend the default code languages when creating a codebase with the Clone or Import strategy.
Other code language
Warning
The Create strategy does not allow to customize the default code language set.
To customize the Build Tool list, perform the following:
Edit the edp-admin-console deployment by adding the necessary code language into the BUILD TOOLS field:
kubectl edit deployment edp-admin-console -n edp\n
Note
Using an OpenShift cluster, run the oc
command instead of kubectl
one.
Info
edp
is the name of the EDP tenant here and in all the following steps.
...\nspec:\n containers:\n - env:\n ...\n - name: BUILD_TOOLS\n value: docker # List of custom build tools in Admin Console, e.g. 'docker,helm';\n ...\n...\n
As a result, the newly added Jenkins agent will be available in the Select Jenkins Slave dropdown list of the Advanced Settings block during the codebase creation:
Advanced settings
If it is necessary to create Code Review and Build pipelines, add corresponding entries (e.g. stages[Build-application-docker], [Code-review-application-docker]). See the example below:
...\nstages['Code-review-application-docker'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + ',{\"name\": \"sonar\"}]'\nstages['Build-application-docker'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build-image-kaniko\"}' + ',{\"name\": \"git-tag\"}]'\n...\n
Jenkins job provisioner
Note
Application is one of the available options. Another option might be to add a library. Please refer to the Add Library page for details.
"},{"location":"operator-guide/add-other-code-language/#related-articles","title":"Related Articles","text":"In order to add a new security scanner, perform the steps below:
Select a pipeline customization option from the Customize CI Pipeline article. Follow the steps described in this article, to create a new repository.
Note
This tutorial will focus on adding a new stage using shared library via the custom global pipeline libraries.
Open the new repository and create a directory with the /src/com/epam/edp/customStages/impl/ci/impl/stageName/
name in the library repository, for example: /src/com/epam/edp/customStages/impl/ci/impl/security/
. After that, add a Groovy file with another name to the same stages catalog, for example: CustomSAST.groovy
.
Copy the logic from SASTMavenGradleGoApplication.groovy
stage into the new CustomSAST.groovy
stage.
Add a new runGoSecScanner
function to the stage:
@Stage(name = \"sast-custom\", buildTool = [\"maven\",\"gradle\",\"go\"], type = [ProjectType.APPLICATION])\nclass CustomSAST {\n...\n def runGoSecScanner(context) {\n def edpName = context.platform.getJsonPathValue(\"cm\", \"edp-config\", \".data.edp_name\")\n def reportData = [:]\n reportData.active = \"true\"\n reportData.verified = \"false\"\n reportData.path = \"sast-gosec-report.json\"\n reportData.type = \"Gosec Scanner\"\n reportData.productTypeName = \"Tenant\"\n reportData.productName = \"${edpName}\"\n reportData.engagementName = \"${context.codebase.name}-${context.git.branch}\"\n reportData.autoCreateContext = \"true\"\n reportData.closeOldFindings = \"true\"\n reportData.pushToJira = \"false\"\n reportData.environment = \"Development\"\n reportData.testTitle = \"SAST\"\n script.sh(script: \"\"\"\n set -ex\n gosec -fmt=json -out=${reportData.path} ./...\n \"\"\")\n return reportData\n }\n...\n}\n
Add function calls for the runGoSecScanner
and publishReport
functions:
...\nscript.node(\"sast\") {\n script.dir(\"${testDir}\") {\n script.unstash 'all-repo'\n...\n def dataFromGoSecScanner = runGoSecScanner(context)\n publishReport(defectDojoCredentials, dataFromGoSecScanner)\n }\n}\n...\n
Gosec scanner will be installed on the Jenkins SAST agent. It is based on the epamedp/edp-jenkins-base-agent
. Please check DockerHub for its latest version.
See below an example of the edp-jenkins-sast-agent
Dockerfile:
# Copyright 2022 EPAM Systems.\n\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n # http://www.apache.org/licenses/LICENSE-2.0\n\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\n # See the License for the specific language governing permissions and\n # limitations under the License.\n\n FROM epamedp/edp-jenkins-base-agent:1.0.31\n\n SHELL [\"/bin/bash\", \"-o\", \"pipefail\", \"-c\"]\n\n USER root\n\n ENV SEMGREP_SCANNER_VERSION=0.106.0 \\\n GOSEC_SCANNER_VERSION=2.12.0\n\n RUN apk --no-cache add \\\n curl=7.79.1-r2 \\\n build-base=0.5-r3 \\\n python3-dev=3.9.5-r2 \\\n py3-pip=20.3.4-r1 \\\n go=1.16.15-r0\n\n # hadolint ignore=DL3059\n RUN pip3 install --no-cache-dir --upgrade --ignore-installed \\\n pip==22.2.1 \\\n ruamel.yaml==0.17.21 \\\n semgrep==${SEMGREP_SCANNER_VERSION}\n\n # Install GOSEC\n RUN curl -Lo /tmp/gosec.tar.gz https://github.com/securego/gosec/releases/download/v${GOSEC_SCANNER_VERSION}/gosec_${GOSEC_SCANNER_VERSION}_linux_amd64.tar.gz && \\\n tar xf /tmp/gosec.tar.gz && \\\n rm -f /tmp/gosec.tar.gz && \\\n mv gosec /bin/gosec\n\n RUN chown -R \"1001:0\" \"$HOME\" && \\\n chmod -R \"g+rw\" \"$HOME\"\n\n USER 1001\n
EDP uses Argo CD as a part of the Continues Delivery/Continues Deployment implementation. Argo CD follows the best GitOps practices, uses Kubernetes native approach for the Deployment Management, has rich UI and required RBAC capabilities.
"},{"location":"operator-guide/argocd-integration/#argo-cd-deployment-approach-in-edp","title":"Argo CD Deployment Approach in EDP","text":"Argo CD can be installed using two different approaches:
Both approaches can be deployed with High Availability (HA) or Non High Availability (non HA) installation manifests.
EDP uses the HA deployment with the cluster-admin permissions, to minimize cluster resources consumption by sharing single Argo CD instance across multiple EDP Tenants. Please follow the installation instructions to deploy Argo CD.
"},{"location":"operator-guide/argocd-integration/#edp-argo-cd-integration","title":"EDP Argo CD Integration","text":"See a diagram below for the details:
Argo CD Diagram
argocd
namespace.cluster-admin
role for managing cluster-scope resources.control-plane
application is created using the App of Apps approach, and its code is managed by the control-plane
members.control-plane
is used to onboard new Argo CD Tenants (Argo CD Projects - AppProject).EDP Tenant Member
manages Argo CD Applications
using kind: Application
in the edpTenant
namespace.The App Of Apps approach is used to manage the EDP Tenants
. Inspect the edp-grub repository structure that is used to provide the EDP Tenants for the Argo CD Projects:
edp-grub\n\u251c\u2500\u2500 LICENSE\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 apps ### All Argo CD Applications are stored here\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 grub-argocd.yaml # Application that provisions Argo CD Resources - Argo Projects (EDP Tenants)\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 grub-keycloak.yaml # Application that provisions Keycloak Resources - Argo CD Groups (EDP Tenants)\n\u251c\u2500\u2500 apps-configs\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 grub\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 argocd ### Argo CD resources definition\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 team-bar.yaml\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 team-foo.yaml\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 keycloak ### Keycloak resources definition\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 team-bar.yaml\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 team-foo.yaml\n\u251c\u2500\u2500 bootstrap\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 root.yaml ### Root application in App of Apps, which provision Applications from /apps\n\u2514\u2500\u2500 examples ### Examples\n \u2514\u2500\u2500 tenant\n \u2514\u2500\u2500 foo-petclinic.yaml\n
The Root Application must be created under the control-plane
scope.
Note
Make sure that both EDP and Argo CD are installed, and that SSO is enabled.
To start using Argo CD with EDP, perform the following steps:
"},{"location":"operator-guide/argocd-integration/#keycloak","title":"Keycloak","text":"Create a Keycloak Group.
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmGroup\nmetadata:\n name: argocd-team-foo-users\nspec:\n name: ArgoCD-team-foo-users\n realm: main\n
In Keycloak, add users to the ArgoCD-team-foo-users
Keycloak Group.
Add a credential template for Gerrit, GitHub, GitLab integrations. The credential template must be created for each Git server.
GerritGitHub/GitLabCopy existing SSH private key for Gerrit to Argo CD namespace
EDP_NAMESPACE=<EPD_NAMESPACE>\nGERRIT_PORT=$(kubectl get gerrit gerrit -n ${EDP_NAMESPACE} -o jsonpath='{.spec.sshPort}')\nGERRIT_ARGOCD_SSH_KEY_NAME=\"gerrit-argocd-sshkey\"\nGERRIT_URL=$(echo \"ssh://argocd@gerrit.${EDP_NAMESPACE}:${GERRIT_PORT}\" | base64)\nkubectl get secret ${GERRIT_ARGOCD_SSH_KEY_NAME} -n ${EDP_NAMESPACE} -o json | jq 'del(.data.username,.metadata.annotations,.metadata.creationTimestamp,.metadata.labels,.metadata.resourceVersion,.metadata.uid,.metadata.ownerReferences)' | jq '.metadata.namespace = \"argocd\"' | jq --arg name \"${EDP_NAMESPACE}\" '.metadata.name = $name' | jq --arg url \"${GERRIT_URL}\" '.data.url = $url' | jq '.data.sshPrivateKey = .data.id_rsa' | jq 'del(.data.id_rsa,.data.\"id_rsa.pub\")' | kubectl apply -f -\nkubectl label --overwrite secret ${EDP_NAMESPACE} -n argocd \"argocd.argoproj.io/secret-type=repo-creds\"\n
Generate an SSH key pair and add a public key to GitLab or GitHub account.
Warning
Use an additional GitHub/GitLab User to access a repository. For example: - GitHub, add a User to a repository with a \"Read\" role. - GitLab, add a User to a repository with a \"Guest\" role.
ssh-keygen -t ed25519 -C \"email@example.com\" -f argocd\n
Copy SSH private key to Argo CD namespace
EDP_NAMESPACE=<EDP_NAMESPACE>\nVCS_HOST=\"<github.com_or_gitlab.com>\"\nACCOUNT_NAME=\"<ACCOUNT_NAME>\"\nURL=\"ssh://git@${VCS_HOST}:22/${ACCOUNT_NAME}\"\n\nkubectl create secret generic ${EDP_NAMESPACE} -n argocd \\\n--from-file=sshPrivateKey=argocd \\\n--from-literal=url=\"${URL}\"\nkubectl label --overwrite secret ${EDP_NAMESPACE} -n argocd \"argocd.argoproj.io/secret-type=repo-creds\"\n
Add public SSH key to GitHub/GitLab account.
Add SSH Known hosts for Gerrit, GitHub, GitLab integration.
GerritGitHub/GitLabAdd Gerrit host to Argo CD config map with known hosts
EDP_NAMESPACE=<EDP_NAMESPACE>\nKNOWN_HOSTS_FILE=\"/tmp/ssh_known_hosts\"\nARGOCD_KNOWN_HOSTS_NAME=\"argocd-ssh-known-hosts-cm\"\nGERRIT_PORT=$(kubectl get gerrit gerrit -n ${EDP_NAMESPACE} -o jsonpath='{.spec.sshPort}')\n\nrm -f ${KNOWN_HOSTS_FILE}\nkubectl get cm ${ARGOCD_KNOWN_HOSTS_NAME} -n argocd -o jsonpath='{.data.ssh_known_hosts}' > ${KNOWN_HOSTS_FILE}\nkubectl exec -it deployment/gerrit -n ${EDP_NAMESPACE} -- ssh-keyscan -p ${GERRIT_PORT} gerrit.${EDP_NAMESPACE} >> ${KNOWN_HOSTS_FILE}\nkubectl create configmap ${ARGOCD_KNOWN_HOSTS_NAME} -n argocd --from-file ${KNOWN_HOSTS_FILE} -o yaml --dry-run=client | kubectl apply -f -\n
Add GitHub/GitLab host to Argo CD config map with known hosts
EDP_NAMESPACE=<EPD_NAMESPACE>\nVCS_HOST=\"<VCS_HOST>\"\nKNOWN_HOSTS_FILE=\"/tmp/ssh_known_hosts\"\nARGOCD_KNOWN_HOSTS_NAME=\"argocd-ssh-known-hosts-cm\"\n\nrm -f ${KNOWN_HOSTS_FILE}\nkubectl get cm ${ARGOCD_KNOWN_HOSTS_NAME} -n argocd -o jsonpath='{.data.ssh_known_hosts}' > ${KNOWN_HOSTS_FILE}\nssh-keyscan ${VCS_HOST} >> ${KNOWN_HOSTS_FILE}\nkubectl create configmap ${ARGOCD_KNOWN_HOSTS_NAME} -n argocd --from-file ${KNOWN_HOSTS_FILE} -o yaml --dry-run=client | kubectl apply -f -\n
Create an Argo CD Project (EDP Tenant), for example, with the team-foo
name:
apiVersion: argoproj.io/v1alpha1\nkind: AppProject\nmetadata:\n name: team-foo\n namespace: argocd\n # Finalizer that ensures that project is not deleted until it is not referenced by any application\n finalizers:\n - resources-finalizer.argocd.argoproj.io\nspec:\n description: CD pipelines for team-foo\n roles:\n - name: developer\n description: Users for team-foo tenant\n policies:\n - p, proj:team-foo:developer, applications, create, team-foo/*, allow\n - p, proj:team-foo:developer, applications, delete, team-foo/*, allow\n - p, proj:team-foo:developer, applications, get, team-foo/*, allow\n - p, proj:team-foo:developer, applications, override, team-foo/*, allow\n - p, proj:team-foo:developer, applications, sync, team-foo/*, allow\n - p, proj:team-foo:developer, applications, update, team-foo/*, allow\n - p, proj:team-foo:developer, repositories, create, team-foo/*, allow\n - p, proj:team-foo:developer, repositories, delete, team-foo/*, allow\n - p, proj:team-foo:developer, repositories, update, team-foo/*, allow\n - p, proj:team-foo:developer, repositories, get, team-foo/*, allow\n groups:\n # Keycloak Group name\n - ArgoCD-team-foo-users\n destinations:\n # ensure we can deploy to ns with tenant prefix\n - namespace: 'team-foo-*'\n # allow to deploy to specific server (local in our case)\n server: https://kubernetes.default.svc\n # Deny all cluster-scoped resources from being created, except for Namespace\n clusterResourceWhitelist:\n - group: ''\n kind: Namespace\n # Allow all namespaced-scoped resources to be created, except for ResourceQuota, LimitRange, NetworkPolicy\n namespaceResourceBlacklist:\n - group: ''\n kind: ResourceQuota\n - group: ''\n kind: LimitRange\n - group: ''\n kind: NetworkPolicy\n # we are ok to create any resources inside namespace\n namespaceResourceWhitelist:\n - group: '*'\n kind: '*'\n # enable access only for specific git server. The example below 'team-foo' - it is namespace where EDP deployed\n sourceRepos:\n - ssh://argocd@gerrit.team-foo:30007/*\n # enable capability to deploy objects from namespaces\n sourceNamespaces:\n - team-foo\n
Optional: if the Argo CD controller has not been enabled to manage the Application resources in the specific namespaces (team-foo
, in our case) in the Install Argo CD, modify the argocd-cmd-params-cm
ConfigMap in the Argo CD namespace and add the application.namespaces
parameter to the subsection data:
...\ndata:\n application.namespaces: team-foo\n...\n
values.yaml file...\nconfigs:\n params:\n application.namespaces: team-foo\n...\n
Check that your new Repository, Known Hosts, and AppProject are added to the Argo CD UI.
Once Argo CD is successfully integrated, EDP user can utilize Argo CD to deploy CD pipelines.
"},{"location":"operator-guide/argocd-integration/#check-argo-cd-integration-optional","title":"Check Argo CD Integration (Optional)","text":"This section provides the information on how to test the integration with Argo CD and is not mandatory to be followed.
Follow the Add Application instruction to deploy a test EDP application with the demo
name, which should be stored in a Gerrit private repository:
apiVersion: argoproj.io/v1alpha1\nkind: Application\nmetadata:\n name: demo\nspec:\n project: team-foo\n destination:\n namespace: team-foo-demo\n server: https://kubernetes.default.svc\n source:\n helm:\n parameters:\n - name: image.tag\n value: master-0.1.0-1\n - name: image.repository\n value: image-repo\n path: deploy-templates\n repoURL: ssh://argocd@gerrit.team-foo:30007/demo.git\n targetRevision: master\n syncPolicy:\n syncOptions:\n - CreateNamespace=true\n automated:\n selfHeal: true\n prune: true\n
Check that your new Application is added to the Argo CD UI under the team-foo
Project scope.
This documentation outlines platform SLSA integration and guides verifying image authenticity and provenance.
Supply Chain Levels of Software Assurance (SLSA) is a framework for assessing and enhancing software supply chain security. Software Supply Chain Security is a critical aspect of modern software development and deployment. Supply Chain Levels of Software Assurance (SLSA) provides a framework for assessing and enhancing the security of your software supply chain.
"},{"location":"operator-guide/artifacts-verification/#prerequisites","title":"Prerequisites","text":"Ensure you have installed rekor-cli and cosign on your environment before proceeding.
"},{"location":"operator-guide/artifacts-verification/#release-assets","title":"Release Assets","text":"The table below represents a list of EDP components with corresponding images that are signed and pushed to DockerHub:
Asset Description codebase-operator Docker Image edp-headlamp Docker Image edp-tekton Docker Image cd-pipeline-operator Docker Image gerrit-operator Docker Image edp-gerrit Docker Image"},{"location":"operator-guide/artifacts-verification/#verify-container-images","title":"Verify Container Images","text":"EPAM Delivery Platform's container images are signed using cosign with the cosign.pub key for signing and transparency. You can verify a container image's signature by executing the cosign verify
command.
To confirm the authenticity of the image, run the cosign verify
command. See the example below:
cosign verify --key https://raw.githubusercontent.com/epam/edp-install/master/cosign.pub epamedp/codebase-operator:2.20.0 | jq .\n
Verification for epamedp/codebase-operator:2.20.0:
Verification for index.docker.io/epamedp/codebase-operator:2.20.0\nThe following checks were performed on each of these signatures:\n - The cosign claims were validated\n - The claims were present in the transparency log\n - The signatures were integrated into the transparency log when the certificate was valid\n - The signatures were verified against the specified public key\n[\n {\n \"critical\": {\n \"identity\": {\n \"docker-reference\": \"index.docker.io/epamedp/codebase-operator\"\n },\n \"image\": {\n \"docker-manifest-digest\": \"sha256:36585a13b5b5ff5a15138e9d16cc74eb3aac4560b77be15161d3b3db25b89e1d\"\n },\n \"type\": \"cosign container image signature\"\n },\n \"optional\": null\n }\n]\n
"},{"location":"operator-guide/artifacts-verification/#verify-container-image-with-slsa-attestations","title":"Verify Container Image With SLSA Attestations","text":"An SLSA Level 3 provenance is verified using. The following command will verify the signature of an attestation and how it was issued. It will contain the payloadType, payload, and signature.
Run the cosign verify-attestation
command using the cosign.pub:
cosign verify-attestation --key https://raw.githubusercontent.com/epam/edp-install/master/cosign.pub --type slsaprovenance epamedp/codebase-operator:2.20.0 | jq .\n
Verification for epamedp/codebase-operator:2.20.0:
Verification for epamedp/codebase-operator:2.20.0\nThe following checks were performed on each of these signatures:\n - The cosign claims were validated\n - The claims were present in the transparency log\n - The signatures were integrated into the transparency log when the certificate was valid\n - The signatures were verified against the specified public key\n{\n \"payloadType\": \"application/vnd.in-toto+json\",\n \"payload\": \"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsInN1YmplY3QiOlt7Im5hbWUiOiJpbmRleC5kb2NrZXIuaW8vZXBhbWVkcC9jb2RlYmFzZS1vcGVyYXRvciIsImRpZ2VzdCI6eyJzaGEyNTYiOiIzNjU4NWExM2I1YjVmZjVhMTUxMzhlOWQxNmNjNzRlYjNhYWM0NTYwYjc3YmUxNTE2MWQzYjNkYjI1Yjg5ZTFkIn19XSwicHJlZGljYXRlIjp7ImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL3Rla3Rvbi5kZXYvY2hhaW5zL3YyIn0sImJ1aWxkVHlwZSI6InRla3Rvbi5kZXYvdjFiZXRhMS9UYXNrUnVuIiwiaW52b2NhdGlvbiI6eyJjb25maWdTb3VyY2UiOnt9LCJwYXJhbWV0ZXJzIjp7IkJVSUxERVJfSU1BR0UiOiJnY3IuaW8va2FuaWtvLXByb2plY3QvZXhlY3V0b3I6djEuMTIuMS1kZWJ1ZyIsIkNPTlRFWFQiOiIuLyIsIkRPQ0tFUkZJTEUiOiJEb2NrZXJmaWxlIiwiSU1BR0UiOiJlcGFtZWRwL2NvZGViYXNlLW9wZXJhdG9yOjIuMjAuMCIsIklNQUdFX1RBUiI6ImNvZGViYXNlLW9wZXJhdG9yXzIuMjAuMCJ9LCJlbnZpcm9ubWVudCI6eyJhbm5vdGF0aW9ucyI6eyJtZXRhLmhlbG0uc2gvcmVsZWFzZS1uYW1lIjoiZWRwLWN1c3RvbS1waXBlbGluZXMiLCJtZXRhLmhlbG0uc2gvcmVsZWFzZS1uYW1lc3BhY2UiOiJlZHAtZGVsaXZlcnkiLCJwaXBlbGluZS50ZWt0b24uZGV2L2FmZmluaXR5LWFzc2lzdGFudCI6ImFmZmluaXR5LWFzc2lzdGFudC1iZjRkNzRkMWM0IiwicGlwZWxpbmUudGVrdG9uLmRldi9yZWxlYXNlIjoiMjI5OWIxNSIsInRla3Rvbi5kZXYvY2F0ZWdvcmllcyI6IkltYWdlIEJ1aWxkIiwidGVrdG9uLmRldi9kaXNwbGF5TmFtZSI6IkJ1aWxkIGFuZCB1cGxvYWQgY29udGFpbmVyIGltYWdlIHVzaW5nIEthbmlrbyIsInRla3Rvbi5kZXYvcGlwZWxpbmVzLm1pblZlcnNpb24iOiIwLjE3LjAiLCJ0ZWt0b24uZGV2L3BsYXRmb3JtcyI6ImxpbnV4L2FtZDY0IiwidGVrdG9uLmRldi90YWdzIjoiaW1hZ2UtYnVpbGQifSwibGFiZWxzIjp7ImFwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnkiOiJIZWxtIiwiYXBwLmt1YmVybmV0ZXMuaW8vdmVyc2lvbiI6IjAuOC4wIiwiaGVsbS5zaC9jaGFydCI6ImVkcC1jdXN0b20tcGlwZWxpbmVzLTAuOC4wIiwiazhzbGVucy1lZGl0LXJlc291cmNlLXZlcnNpb24iOiJ2MSIsInRla3Rvbi5kZXYvbWVtYmVyT2YiOiJ0YXNrcyIsInRla3Rvbi5kZXYvcGlwZWxpbmUiOiJnZXJyaXQtb3BlcmF0b3JzLWFwcC1yZWxlYXNlLWVkcCIsInRla3Rvbi5kZXYvcGlwZWxpbmVSdW4iOiJlZHAtY29kZWJhc2Utb3BlcmF0b3ItcmVsZWFzZSIsInRla3Rvbi5kZXYvcGlwZWxpbmVUYXNrIjoia2FuaWtvLWJ1aWxkIiwidGVrdG9uLmRldi90YXNrIjoia2FuaWtvLXJlbGVhc2UifX19LCJidWlsZENvbmZpZyI6eyJzdGVwcyI6W3siZW50cnlQb2ludCI6Ii9rYW5pa28vZXhlY3V0b3IgXFxcbiAgLS1kb2NrZXJmaWxlPS93b3Jrc3BhY2Uvc291cmNlL0RvY2tlcmZpbGUgXFxcbiAgLS1jb250ZXh0PS93b3Jrc3BhY2Uvc291cmNlLy4vIFxcXG4gIC0tZGVzdGluYXRpb249ZXBhbWVkcC9jb2RlYmFzZS1vcGVyYXRvcjoyLjIwLjAgXFxcbiAgLS1kaWdlc3QtZmlsZT0vdGVrdG9uL3Jlc3VsdHMvSU1BR0VfRElHRVNUIFxcXG4gIC0tdGFyLXBhdGg9Y29kZWJhc2Utb3BlcmF0b3JfMi4yMC4wLnRhciBcXFxuIiwiYXJndW1lbnRzIjpudWxsLCJlbnZpcm9ubWVudCI6eyJjb250YWluZXIiOiJidWlsZC1hbmQtcHVzaCIsImltYWdlIjoib2NpOi8vZ2NyLmlvL2thbmlrby1wcm9qZWN0L2V4ZWN1dG9yQHNoYTI1NjphN2VhOWY2OWQ3N2Q3ZTdhMGVhODIxZjE1MDY5YmU0NTQyMGE1MzZmODFhYjU3ODdhOTg4NjU5ZTQ4YzI1Mzc3In0sImFubm90YXRpb25zIjpudWxsfSx7ImVudHJ5UG9pbnQiOiJzZXQgLWVcbmltYWdlPVwiZXBhbWVkcC9jb2RlYmFzZS1vcGVyYXRvcjoyLjIwLjBcIlxuZWNobyAtbiBcIiR7aW1hZ2V9XCIgfCB0ZWUgXCIvdGVrdG9uL3Jlc3VsdHMvSU1BR0VfVVJMXCJcbiIsImFyZ3VtZW50cyI6bnVsbCwiZW52aXJvbm1lbnQiOnsiY29udGFpbmVyIjoid3JpdGUtdXJsIiwiaW1hZ2UiOiJvY2k6Ly9kb2NrZXIuaW8vbGlicmFyeS9hbHBpbmVAc2hhMjU2OjcxNDRmN2JhYjNkNGMyNjQ4ZDdlNTk0MDlmMTVlYzUyYTE4MDA2YTEyOGM3MzNmY2ZmMjBkM2E0YTU0YmE0NGEifSwiYW5ub3RhdGlvbnMiOm51bGx9XX0sIm1ldGFkYXRhIjp7ImJ1aWxkU3RhcnRlZE9uIjoiMjAyMy0xMS0wM1QxMzozMDo1NVoiLCJidWlsZEZpbmlzaGVkT24iOiIyMDIzLTExLTAzVDEzOjMxOjE1WiIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoib2NpOi8vZ2NyLmlvL2thbmlrby1wcm9qZWN0L2V4ZWN1dG9yIiwiZGlnZXN0Ijp7InNoYTI1NiI6ImE3ZWE5ZjY5ZDc3ZDdlN2EwZWE4MjFmMTUwNjliZTQ1NDIwYTUzNmY4MWFiNTc4N2E5ODg2NTllNDhjMjUzNzcifX0seyJ1cmkiOiJvY2k6Ly9kb2NrZXIuaW8vbGlicmFyeS9hbHBpbmUiLCJkaWdlc3QiOnsic2hhMjU2IjoiNzE0NGY3YmFiM2Q0YzI2NDhkN2U1OTQwOWYxNWVjNTJhMTgwMDZhMTI4YzczM2ZjZmYyMGQzYTRhNTRiYTQ0YSJ9fV19fQ==\",\n \"signatures\": [\n {\n \"keyid\": \"SHA256:7E2nAQnycq4vfPlzmLZGzpK/Vr6oXKqqGokDyrBSLck\",\n \"sig\": \"MEUCIAZLrA/wTkqmnCZXh85R9Y/Ue5f8wuGgjLMYdoFw9GRLAiEA/sE598EX5fppqbry+xvE+aap8+qHPioOin8t6Ttzx3k=\"\n }\n ]\n}\n
For more details about attestation, please refer to the official cosign documentation page.
"},{"location":"operator-guide/artifacts-verification/#verify-release-pipeline","title":"Verify Release Pipeline","text":"Within each release component, you will discover a Rekor UUID, which serves to validate the flow of the release pipeline. Execute the following command to obtain comprehensive information about the release pipeline of codebase-operator with UUID:
24296fb24b8ad77a671b24f6b83f79e46fe5214cde46ed045ceba35d640a7e017cbc5524e90329ff
:
rekor-cli get --uuid 24296fb24b8ad77a671b24f6b83f79e46fe5214cde46ed045ceba35d640a7e017cbc5524e90329ff --format json | jq -r .Attestation | jq .\n
The result:
{\n \"_type\": \"https://in-toto.io/Statement/v0.1\",\n \"predicateType\": \"https://slsa.dev/provenance/v0.2\",\n \"subject\": [\n {\n \"name\": \"index.docker.io/epamedp/codebase-operator\",\n \"digest\": {\n \"sha256\": \"36585a13b5b5ff5a15138e9d16cc74eb3aac4560b77be15161d3b3db25b89e1d\"\n }\n }\n ],\n \"predicate\": {\n \"builder\": {\n \"id\": \"https://tekton.dev/chains/v2\"\n },\n \"buildType\": \"tekton.dev/v1beta1/TaskRun\",\n \"invocation\": {\n \"configSource\": {},\n \"parameters\": {\n \"BUILDER_IMAGE\": \"gcr.io/kaniko-project/executor:v1.12.1-debug\",\n \"CONTEXT\": \"./\",\n \"DOCKERFILE\": \"Dockerfile\",\n \"IMAGE\": \"epamedp/codebase-operator:2.20.0\",\n \"IMAGE_TAR\": \"codebase-operator_2.20.0\"\n },\n \"environment\": {\n \"annotations\": {\n ...\n },\n \"labels\": {\n ...\n }\n }\n },\n \"buildConfig\": {\n \"steps\": [\n {\n \"entryPoint\": \"/kaniko/executor \\\\\\n --dockerfile=/workspace/source/Dockerfile \\\\\\n --context=/workspace/source/./ \\\\\\n --destination=epamedp/codebase-operator:2.20.0 \\\\\\n --digest-file=/tekton/results/IMAGE_DIGEST \\\\\\n --tar-path=codebase-operator_2.20.0.tar \\\\\\n\",\n \"arguments\": null,\n \"environment\": {\n \"container\": \"build-and-push\",\n \"image\": \"oci://gcr.io/kaniko-project/executor@sha256:a7ea9f69d77d7e7a0ea821f15069be45420a536f81ab5787a988659e48c25377\"\n },\n \"annotations\": null\n },\n {\n \"entryPoint\": \"set -e\\nimage=\\\"epamedp/codebase-operator:2.20.0\\\"\\necho -n \\\"${image}\\\" | tee \\\"/tekton/results/IMAGE_URL\\\"\\n\",\n \"arguments\": null,\n \"environment\": {\n \"container\": \"write-url\",\n \"image\": \"oci://docker.io/library/alpine@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a\"\n },\n \"annotations\": null\n }\n ]\n },\n \"metadata\": {\n ...\n },\n \"materials\": [\n {\n \"uri\": \"oci://gcr.io/kaniko-project/executor\",\n \"digest\": {\n \"sha256\": \"a7ea9f69d77d7e7a0ea821f15069be45420a536f81ab5787a988659e48c25377\"\n }\n },\n {\n \"uri\": \"oci://docker.io/library/alpine\",\n \"digest\": {\n \"sha256\": \"7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a\"\n }\n }\n ]\n }\n}\n
By signing all our artifacts, we assure you that they are trustworthy. This guide is indispensable for developers and administrators to enhance their software's reliability and meet modern security standards. The adoption of SLSA will bring you confidence while using the platform.
"},{"location":"operator-guide/artifacts-verification/#related-articles","title":"Related Articles","text":"This documentation provides the detailed instructions on how to install the EPAM Delivery Platform via the AWS Marketplace.
To initiate the installation process, navigate to our dedicated AWS Marketplace page and commence the deployment of EPAM Delivery Platform.
Disclaimer
EDP is aligned with industry standards for storing and managing sensitive data, ensuring optimal security. However, the use of custom solutions introduces uncertainties, thus the responsibility for the safety of your data is totally covered by platform administrator.
"},{"location":"operator-guide/aws-marketplace-install/#prerequisites","title":"Prerequisites","text":"Please familiarize yourself with the Prerequisites page before deploying the product. To perform a minimal installation, ensure that you meet the following requirements:
To deploy the platform, follow the steps below:
To apply Tekton stack, deploy Tekton resources by executing the command below:
kubectl create ns tekton-pipelines\n kubectl create ns tekton-chains\n kubectl create ns tekton-pipelines-resolvers\n kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml\n kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml\n kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml\n kubectl apply --filename https://storage.googleapis.com/tekton-releases/chains/latest/release.yaml\n
Define the mandatory parameters you would like to use for installation using the following command:
kubectl create ns edp\n helm install edp-install \\\n --namespace edp ./* \\\n --set global.dnsWildCard=example.com \\\n --set awsRegion=<AWS_REGION>\n
(Optional) Provide token to sign in to EDP Portal. Run the following command to create Service Account with cluster admin permissions:
kubectl create serviceaccount edp-admin -n edp\nkubectl create clusterrolebinding edp-cluster-admin --clusterrole=cluster-admin --serviceaccount=edp:edp-admin\nkubectl apply -f - <<EOF\napiVersion: v1\nkind: Secret\nmetadata:\n name: edp-admin-token\n namespace: edp\n annotations:\n kubernetes.io/service-account.name: edp-admin\ntype: kubernetes.io/service-account-token\nEOF\n
(Optional) To get access to EDP Portal, run the port-forwarding command:
kubectl port-forward service/edp-headlamp 59480:80 -n edp\n
(Optional) To open EDP Portal, navigate to the http://localhost:59480
.
(Optional) To get admin token to sign in to EDP Portal:
kubectl get secrets -o jsonpath=\"{.items[?(@.metadata.annotations['kubernetes\\.io/service-account\\.name']=='edp-admin')].data.token}\" -n edp|base64 --decode\n
As a result, you will get access to EPAM Delivery Platform components via EDP Portal UI. Navigate to our Use Cases to try out EDP functionality. Visit other subsections of the Operator Guide to figure out how to configure EDP and integrate it with various tools.
"},{"location":"operator-guide/aws-marketplace-install/#related-articles","title":"Related Articles","text":"This documentation guide provides comprehensive instructions of integrating Capsule with the EPAM Delivery Platform to enhance security and resource management.
Note
When integrating the EPAM Delivery Platform with Capsule, it's essential to understand that the platform needs administrative rights to make and oversee resources. This requirement might raise security concerns, but it's important to clarify that it only pertains to the deployment process within the platform. There is an alternative approach available. You can manually create permissions for each deployment flow. This alternative method can be used to address and lessen these security concerns.
"},{"location":"operator-guide/capsule/#installation","title":"Installation","text":"To install the Capsule tool, use the Cluster Add-Ons approach. For more details, please refer to the Capsule official page.
"},{"location":"operator-guide/capsule/#configuration","title":"Configuration","text":"To use Capsule in EDP, follow the steps below:
Run the command below to upgrade EDP with Capsule capabilities:
helm upgrade --install edp epamedp/edp-install -n edp --values values.yaml --set cd-pipeline-operator.tenancyEngine=capsule\n
Open the CapsuleConfiguration
custom resource called default
:
kubectl edit CapsuleConfiguration default\n
Add the tenant name (by default, it's the EDP namespace name) to the manifest's spec section as follows:
spec:\n userGroups:\n - system:serviceaccounts:edp\n
As a result, EDP will be using Capsule capabilities to manage tenants, thus providing better access management.
"},{"location":"operator-guide/capsule/#related-articles","title":"Related Articles","text":"This article provides the instruction of configuring Keycloak as OIDC Identity Provider for EKS. The example is written on Terraform (HCL).
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#prerequisites","title":"Prerequisites","text":"To follow the instruction, check the following prerequisites:
Note
To connect OIDC with a cluster, install and configure the kubelogin plugin. For Windows, it is recommended to download the kubelogin as a binary and add it to your PATH.
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#solution-overview","title":"Solution Overview","text":"The solution includes three types of the resources - AWS (EKS), Keycloak, Kubernetes. The left part of Keycloak resources remain unchanged after creation, thus allowing us to associate a claim for a user group membership. Other resources can be created, deleted or changed if needed. The most crucial from Kubernetes permissions are Kubernetes RoleBindings and ClusterRoles/Roles. Roles present a set of permissions, in turn RoleBindings map Kubernetes Role to representative Keycloak groups, so a group member can have just appropriate permissions.
EKS Keycloak OIDC
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#keycloak-configuration","title":"Keycloak Configuration","text":"To configure Keycloak, follow the steps described below.
resource \"keycloak_openid_client\" \"openid_client\" {\n realm_id = \"openshift\"\n client_id = \"kubernetes\"\n access_type = \"CONFIDENTIAL\"\n standard_flow_enabled = true\n implicit_flow_enabled = false\n direct_access_grants_enabled = true\n service_accounts_enabled = true\n oauth2_device_authorization_grant_enabled = true\n backchannel_logout_session_required = true\n\n root_url = \"http://localhost:8000/\"\n base_url = \"http://localhost:8000/\"\n admin_url = \"http://localhost:8000/\"\n web_origins = [\"*\"]\n\n valid_redirect_uris = [\n \"http://localhost:8000/*\"\n ]\n}\n
resource \"keycloak_openid_client_scope\" \"openid_client_scope\" {\n realm_id = <realm_id>\n name = \"groups\"\n description = \"When requested, this scope will map a user's group memberships to a claim\"\n include_in_token_scope = true\n consent_screen_text = false\n}\n
resource \"keycloak_openid_client_default_scopes\" \"client_default_scopes\" {\n realm_id = <realm_id>\n client_id = keycloak_openid_client.openid_client.id\n\n default_scopes = [\n \"profile\",\n \"email\",\n \"roles\",\n \"web-origins\",\n keycloak_openid_client_scope.openid_client_scope.name,\n ]\n}\n
resource \"keycloak_openid_group_membership_protocol_mapper\" \"group_membership_mapper\" {\n realm_id = <realm_id>\n client_scope_id = keycloak_openid_client_scope.openid_client_scope.id\n name = \"group-membership-mapper\"\n add_to_id_token = true\n add_to_access_token = true\n add_to_userinfo = true\n full_path = false\n\n claim_name = \"groups\"\n}\n
...\n \"email_verified\": false,\n \"name\": \"An User\",\n \"groups\": [\n \"<env_prefix_name>-oidc-viewers\",\n \"<env_prefix_name>-oidc-cluster-admins\"\n ],\n \"preferred_username\": \"an_user@example.com\",\n \"given_name\": \"An\",\n \"family_name\": \"User\",\n \"email\": \"an_user@example.com\"\n ...\n
resource \"keycloak_group\" \"oidc_tenant_admin\" {\n realm_id = <realm_id>\n name = \"kubernetes-oidc-admins\"\n}\n
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#eks-configuration","title":"EKS Configuration","text":"To configure EKS, follow the steps described below. In AWS Console, open EKS home page -> Choose a cluster -> Configuration tab -> Authentication tab.
The Terraform code for association with Keycloak:
...\ncluster_identity_providers = {\n keycloak = {\n client_id = <keycloak_client_id>\n identity_provider_config_name = \"Keycloak\"\n issuer_url = \"https://<keycloak_url>/auth/realms/<realm_name>\"\n groups_claim = \"groups\"\n }\n...\n
resource \"aws_eks_identity_provider_config\" \"keycloak\" {\n for_each = { for k, v in var.cluster_identity_providers : k => v if true }\n\n cluster_name = var.platform_name\n\n oidc {\n client_id = each.value.client_id\n groups_claim = lookup(each.value, \"groups_claim\", null)\n groups_prefix = lookup(each.value, \"groups_prefix\", null)\n identity_provider_config_name = try(each.value.identity_provider_config_name, each.key)\n issuer_url = each.value.issuer_url\n required_claims = lookup(each.value, \"required_claims\", null)\n username_claim = lookup(each.value, \"username_claim\", null)\n username_prefix = lookup(each.value, \"username_prefix\", null)\n }\n\n tags = var.tags\n}\n
Note
The resource creation takes around 20-30 minutes. The resource doesn't support updating, so each change will lead to deletion of the old instance and creation of a new instance instead.
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#kubernetes-configuration","title":"Kubernetes Configuration","text":"To connect the created Keycloak resources with permissions, it is necessary to create Kubernetes Roles and RoleBindings:
resource \"kubernetes_cluster_role_v1\" \"oidc_tenant_admin\" {\n metadata {\n name = \"oidc-admin\"\n }\n rule {\n api_groups = [\"*\"]\n resources = [\"*\"]\n verbs = [\"*\"]\n }\n}\n
resource \"kubernetes_cluster_role_binding_v1\" \"oidc_cluster_rb\" {\n metadata {\n name = \"oidc-cluster-admin\"\n }\n role_ref {\n api_group = \"rbac.authorization.k8s.io\"\n kind = \"ClusterRole\"\n name = kubernetes_cluster_role_v1.oidc_tenant_admin.metadata[0].name\n }\n subject {\n kind = \"Group\"\n name = keycloak_group.oidc_tenant_admin.name\n api_group = \"rbac.authorization.k8s.io\"\n # work-around due https://github.com/hashicorp/terraform-provider-kubernetes/issues/710\n namespace = \"\"\n }\n}\n
Note
When creating the Keycloak group, ClusterRole, and ClusterRoleBinding, a user receives cluster admin permissions. There is also an option to provide admin permissions just to a particular namespace or another resources set in another namespace. For details, please refer to the Mixing Kubernetes Roles page.
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#kubeconfig","title":"Kubeconfig","text":"Template for kubeconfig:
apiVersion: v1\npreferences: {}\nkind: Config\n\nclusters:\n- cluster:\n server: https://<eks_url>.eks.amazonaws.com\n certificate-authority-data: <certificate_authority_data>\n name: <cluster_name>\n\ncontexts:\n- context:\n cluster: <cluster_name>\n user: <keycloak_user_email>\n name: <cluster_name>\n\ncurrent-context: <cluster_name>\n\nusers:\n- name: <keycloak_user_email>\n user:\n exec:\n apiVersion: client.authentication.k8s.io/v1beta1\n command: kubectl\n args:\n - oidc-login\n - get-token\n - -v1\n - --oidc-issuer-url=https://<keycloak_url>/auth/realms/<realm>\n - --oidc-client-id=<keycloak_client_id>\n - --oidc-client-secret=<keycloak_client_secret>\n
Flag -v1 can be used for debug, in a common case it's not needed and can be deleted. To find the client secret:
Before testing, ensure that a user is a member of the correct Keycloak group. To add a user to a Keycloak group:
Follow the steps below to test the configuration:
KUBECONFIG=<path_to_oidc_kubeconfig> kubectl get ingresses -n <namespace_name>\n
OIDC Successful Login
Error from server (Forbidden): ingresses.networking.k8s.io is forbidden:\nUser \"https://<keycloak_url>/auth/realms/<realm>#<keycloak_user_id>\"\ncannot list resource \"ingresses\" in API group \"networking.k8s.io\" in the namespace \"<namespace_name>\"\n
To update the session, clear cache. The default location for the login cache:
rm -rf ~/.kube/cache\n
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#access-cluster-via-lens","title":"Access Cluster via Lens","text":"To access the Kubernetes cluster via Lens, follow the steps below to configure it:
Note
Lens does not add namespaces of the project automatically, so it is necessary to add them manually, simply go to Settings -> Namespaces and add the namespaces of a project.
"},{"location":"operator-guide/configure-keycloak-oidc-eks/#related-articles","title":"Related Articles","text":"Harbor serves as a tool for storing images and artifacts. This documentation contains instructions on how to create a project in Harbor and set up a robot account for interacting with the registry from CI pipelines.
"},{"location":"operator-guide/container-registry-harbor-integration-tekton-ci/#overview","title":"Overview","text":"Harbor integration with Tekton enables the centralized storage of container images within the cluster, eliminating the need for external services. By leveraging Harbor as the container registry, users can manage and store their automation results and reports in one place.
"},{"location":"operator-guide/container-registry-harbor-integration-tekton-ci/#integration-procedure","title":"Integration Procedure","text":"The integration process involves two steps:
Creating a project to store application images.
Creating two accounts with different permissions to push (read/write) and pull (read-only) project images.
The process of creating new projects is the following:
Navigate to the Projects menu, click the New Project button:
Projects menu
On the New Project menu, enter a project name that matches your EDP namespace in the Project Name field. Keep other fields as default and click OK to continue:
New Project menu
To make EDP and Harbor project interact with each other, set up a robot account:
Navigate to your newly created project, select Robot Accounts menu and choose New Robot Account:
Create Robot Account menu
In the pop-up window, fill in the fields as follows:
edp-push
;read/write permissions
;Pull Repository
and Push Repository
.To proceed, click the ADD button:
Robot Accounts menu
In the appeared window, copy the robot account credentials or click the Export to file button to save the secret and account name locally:
New credentials for Robot Account
Provision the kaniko-docker-config secrets using kubectl, EDP Portal or with the externalSecrets operator:
Example
The auth
string can be generated by this command:
echo -n \"robot\\$edp-project+edp:secret\" | base64\n
kubectlManual SecretExternal Secrets Operator apiVersion: v1\n kind: Secret\n metadata:\n name: kaniko-docker-config\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: registry\n app.edp.epam.com/integration-secret: \"true\"\n type: kubernetes.io/dockerconfigjson\n stringData:\n .dockerconfigjson: |\n {\n \"auths\" : {\n \"harbor-registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"secret-string\"\n }\n }\n }\n
Navigate to EDP Portal UI
-> EDP
-> Configuration
-> Registry
. Fill in the required fields and click Save
.
Registry update manual secret
\"kaniko-docker-config\":\n {\"auths\" : \"harbor-registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"secret-string\"\n }\n }\n
Navigate to EDP Portal UI
-> EDP
-> Configuration
-> Registry
. Here, you will observe the Managed by ExternalSecret
message:
Registry managed by external secret operator
Note
More details of External Secrets Operator Integration can be found in the External Secrets Operator Integration page.
Repeat steps 2-3 with values below:
edp-pull
;read-only permissions
;Pull Repository
.Provision the regcred secrets using kubectl, EDP Portal or with the externalSecrets operator:
Example
The auth
string can be generated by this command:
echo -n \"robot\\$edp-project+edp-push:secret\" | base64\n
kubectlManual SecretExternal Secrets Operator apiVersion: v1\nkind: Secret\nmetadata:\n name: regcred\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: registry\n app.edp.epam.com/integration-secret: \"true\"\ntype: kubernetes.io/dockerconfigjson\nstringData:\n .dockerconfigjson: |\n {\n \"auths\" : {\n \"harbor-registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"secret-string\"\n }\n }\n }\n
Navigate to EDP Portal UI
-> EDP
-> Configuration
-> Registry
. Fill in the required fields and click Save.
Registry update manual secret
\"regcred\":\n {\"auths\" : \"harbor-registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"secret-string\"\n }\n }\n
Navigate to EDP Portal UI
-> EDP
-> Configuration
-> Registry
. Here, you will observe the Managed by ExternalSecret
message:
Registry managed by external secret operator
Note
More details of External Secrets Operator Integration can be found in the External Secrets Operator Integration page.
In the values.yaml file for the edp-install Helm chart, set the following values for the specified fields:
Manual SecretExternal Secrets OperatorIf the kaniko-docker-config
secret has been created manually:
...\nkaniko:\n existingDockerConfig: \"kaniko-docker-config\"\nglobal:\n dockerRegistry:\n url: harbor-registry.com\n type: \"harbor\"\n...\n
If the kaniko-docker-config
secret has been created via External Secrets Operator:
...\nkaniko:\n existingDockerConfig: \"kaniko-docker-config\"\nexternalSecrets:\n enabled: true\nglobal:\n dockerRegistry:\n url: harbor-registry.com\n type: \"harbor\"\n...\n
(Optional) If you've already deployed the EDP Helm chart, you can update it using the following command:
helm update --install edp epamedp/edp-install \\\n--values values.yaml \\\n--namespace edp\n
As a result, application images built in EDP Portal will be stored in Harbor project and will be deployed from the harbor registry.
Harbor projects can be added and retained with a retention policy generated through the EDP script in edp-cluster-add-ons.
"},{"location":"operator-guide/container-registry-harbor-integration-tekton-ci/#related-articles","title":"Related Articles","text":"This tutorial provides detailed instructions on the optimal method to uninstall the EPAM Delivery Platform.
"},{"location":"operator-guide/delete-edp/#deletion-procedure","title":"Deletion Procedure","text":"To uninstall EDP, perform the following steps:
It is highly recommended to delete all the resources created via EDP Portal UI first. It can be:
We recommend deleting them via EDP Portal UI respectively, although it is also possible to delete all the EDP Portal resources using the kubectl delete
command.
Delete application namespaces. They should be called according to the edp-<cd-pipeline>-<stage-name>
pattern.
Uninstall EDP the same way it was installed.
Run the script that deletes the rest of the custom resources:
View: CleanEDP.sh#!/bin/sh\n\n###################################################################\n# A POSIX script to remove EDP Kubernetes Custom Resources #\n# #\n# PREREQUISITES #\n# kubectl>=1.23.x, awscli (for EKS authentication) #\n# #\n# TESTED #\n# OS: Ubuntu, FreeBSD, Windows (GitBash) #\n# Shells: zsh, bash, dash #\n###################################################################\n\n[ -n \"${DEBUG}\" ] && set -x\n\nset -e\n\nexit_err() {\nprintf '%s\\n' \"$1\" >&2\nexit 1\n}\n\ncheck_kubectl() {\nif ! hash kubectl; then\nexit_err \"Error: kubectl is not installed\"\nfi\n}\n\nget_script_help() {\nself_name=\"$(basename \"$0\")\"\necho \"\\\n${self_name} deletes EDP Kubernetes Custom Resources\n\nUsage: ${self_name}\n\nOptions:\n${self_name} [OPTION] [FILE]\n\n-h, --help Print Help\n-k, --kubeconfig Pass Kubeconfig file\n\nDebug:\nDEBUG=true ${self_name}\n\nExamples:\n${self_name} --kubeconfig ~/.kube/custom_config\"\n}\n\nyellow_fg() {\ntput setaf 3 || true\n}\n\nno_color_out() {\ntput sgr0 || true\n}\n\nget_current_context() {\nkubectl config current-context\n}\n\nget_context_ns() {\nkubectl config view \\\n--minify --output jsonpath='{..namespace}' 2> /dev/null\n}\n\nget_ns() {\nkubectl get ns \"${edp_ns}\" --output name --request-timeout='5s'\n}\n\ndelete_ns() {\nkubectl delete ns \"${edp_ns}\" --timeout='30s'\n}\n\nget_edp_crds() {\nkubectl get crds --no-headers=true | awk '/edp.epam.com/ {print $1}'\n}\n\nget_all_edp_crs_manif() {\nkubectl get \"${edp_crds_comma_list}\" -n \"${edp_ns}\" \\\n--output yaml --ignore-not-found --request-timeout='15s'\n}\n\ndel_all_edp_crs() {\nkubectl delete --all \"${edp_crds_comma_list}\" -n \"${edp_ns}\" \\\n--ignore-not-found --timeout='15s'\n}\n\niterate_edp_crs() {\nedp_crds_comma_list=\"$(printf '%s' \"${edp_crds}\" | tr -s '\\n' ',')\"\nget_all_edp_crs_manif \\\n| sed '/finalizers:/,/.*:/{//!d;}' \\\n| kubectl replace -f - || true\ndel_all_edp_crs || true\n}\n\niterate_edp_crds() {\nn=0\nwhile [ \"$n\" -lt 2 ]; do\nn=$((n + 1))\n\nif [ \"$n\" -eq 2 ]; then\n# Delete remaining resources\nedp_crds=\"keycloakclients,codebasebranches,jenkinsfolders\"\niterate_edp_crs\necho \"EDP Custom Resources in NS ${color_ns} have been deleted.\"\nbreak\nfi\n\necho \"Replacing EDP CR Manifests. Wait for output (may take 2min)...\"\nedp_crds=\"$(get_edp_crds)\"\niterate_edp_crs\ndone\n}\n\nselect_ns() {\nis_context=\"$(get_current_context)\" || exit 1\nprintf '%s' \"Current cluster: \"\nprintf '%s\\n' \"$(yellow_fg)${is_context}$(no_color_out)\"\n\ncurrent_ns=\"$(get_context_ns)\" || true\n\nprintf '%s\\n' \"Enter EDP namespace\"\nprintf '%s' \"Skip to use [$(yellow_fg)${current_ns}$(no_color_out)]: \"\nread -r edp_ns\n\nif [ -z \"${edp_ns}\" ]; then\nedp_ns=\"${current_ns}\"\necho \"${edp_ns}\"\nif [ -z \"${edp_ns}\" ]; then\nexit_err \"Error: namespace is not specified\"\nfi\nelse\nget_ns || exit 1\nfi\n\ncolor_ns=\"$(yellow_fg)${edp_ns}$(no_color_out)\"\n}\n\nchoose_delete_ns() {\nprintf '%s\\n' \"Do you want to delete namespace ${color_ns} as well? (y/n)?\"\nprintf '%s' \"Skip or enter [N/n] to keep the namespace: \"\nread -r answer\nif [ \"${answer}\" != \"${answer#[Yy]}\" ]; then\ndelete_edp_ns=true\necho \"Namespace ${color_ns} is marked for deletion.\"\nelse\necho \"Skipped. Deleting EDP Custom Resources only.\"\nfi\n}\n\ndelete_ns_if_true() {\nif [ \"${delete_edp_ns}\" = true ]; then\necho \"Deleting ${color_ns} namespace...\"\ndelete_ns || exit 1\nfi\n}\n\ninvalid_option() {\nexit_err \"Invalid option '$1'. Use -h, --help for details\"\n}\n\nmain_func() {\ncheck_kubectl\nselect_ns\nchoose_delete_ns\niterate_edp_crds\ndelete_ns_if_true\n}\n\nwhile [ \"$#\" -gt 0 ]; do\ncase \"$1\" in\n-h | --help)\nget_script_help\nexit 0\n;;\n-k | --kubeconfig)\nshift\n[ $# = 0 ] && exit_err \"No Kubeconfig file specified\"\nexport KUBECONFIG=\"$1\"\n;;\n--)\nbreak\n;;\n-k* | --k*)\necho \"Did you mean '--kubeconfig'?\"\ninvalid_option \"$1\"\n;;\n-* | *)\ninvalid_option \"$1\"\n;;\nesac\nshift\ndone\n\nmain_func\n
The script will prompt user to specify the namespace where EDP was deployed in and choose if the namespace is going to be deleted. This script will delete EDP custom resources in the namespace specified by user.
In Keycloak, delete the edp-main
realm, also delete client which is supposed to be called by the edp-main
pattern in the openshift realm.
To delete the job provisioner, take the following steps:
Delete the job provisioner from Jenkins. Navigate to Admin Console->Jenkins->jobs->job-provisions folder, select the necessary provisioner and click the drop-down right to the provisioner name. Select Delete project.
Delete job provisioner
This documentation guide provides comprehensive instructions for installing and integrating DependencyTrack with the EPAM Delivery Platform.
"},{"location":"operator-guide/dependency-track/#prerequisites","title":"Prerequisites","text":"To install DependencyTrack use EDP addons approach.
"},{"location":"operator-guide/dependency-track/#configuration","title":"Configuration","text":"Open Administration
-> Access Management
-> Teams
. Click Create Team
-> Automation
and click Create
.
Click +
in Permissions
and add:
BOM_UPLOAD\nPROJECT_CREATION_UPLOAD\nVIEW_PORTFOLIO\n
Click +
in API keys
to create token:
DependencyTrack settings
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-dependency-track\n namespace: <edp>\n labels:\n app.edp.epam.com/secret-type: dependency-track\n app.edp.epam.com/integration-secret: \"true\"\nstringData:\n token: <dependency-track-token>\n url: <dependency-track-api-url>\ntype: Opaque\n
Go to the EDP Portal UI
open EDP
-> Configuration
-> DependencyTrack
apply Token
and URL
click the save
button.
DependencyTrack update manual secret
Store DependencyTrack URL and Token in the AWS Parameter Store with the following format:
\"ci-dependency-track\":\n{\n \"token\": \"XXXXXXXXXXXX\",\n \"url\": \"https://dependency-track.example.com\"\n}\n
Go to the EDP Platform UI
open EDP
-> Configuration
-> DependencyTrack
see the Managed by External Secret
.
DependencyTrack managed by external secret operator
More detail on External Secrets Operator Integration can be found on the following page
After following the instructions provided, you should be able to integrate your DependencyTrack with the EPAM Delivery Platform.
"},{"location":"operator-guide/dependency-track/#related-articles","title":"Related Articles","text":"This instruction provides detailed information on the Amazon Elastic Kubernetes Service cluster deployment and contains the additional setup such as Argo CD installation and EDP addons usage for the infrastructure management.
"},{"location":"operator-guide/deploy-aws-eks/#prerequisites","title":"Prerequisites","text":"Before the EKS cluster deployment and configuration, make sure to check the prerequisites. Install the required tools listed below:
To check the correct tools installation, run the following commands:
git --version\nterraform version\naws --version\ntfenv --version\n
"},{"location":"operator-guide/deploy-aws-eks/#terraform-backend","title":"Terraform Backend","text":"This step will do the following:
To create the required resources, do the following:
Fork and clone git repo with project edp-terraform-aws-platform, rename it in the correspondence with project name.
git clone https://github.com/epmd-edp/edp-terraform-aws-platform.git\nmv edp-terraform-aws-platform edp-terraform-aws-platform-edp\ncd edp-terraform-aws-platform-edp/s3-backend\n
Fill the input variables for Terraform run in the s3-backend/template.tfvars
file, refer to the s3-backend/example.tfvars as an example.
# -- e.g eu-central-1\nregion = \"<REGION>\" # mandatory\n\ntags = {\n \"SysName\" = \"Terraform-Backend\"\n \"SysOwner\" = \"owner@example.com\"\n \"Environment\" = \"EKS-TEST-CLUSTER\"\n} # isn't required\n
Find the detailed description of the variables in the s3-backend/variables.tf file. Run Terraform apply. Initialize the backend and apply the changes.
terraform init\nterraform apply -var-file=./template.tfvars\n
View: Terraform output example Outputs:\n\nterraform_lock_table_dynamodb_id = \"terraform_locks\"\nterraform_states_s3_bucket_name = \"terraform-states-012345678910\"\n
(Optional) Commit the local state.
git add s3-backend/terraform.tfstate\ngit commit -m \"Terraform state for s3-backend\"\n
This step will do the following:
Take the following steps:
Navigate to IAM module directory.
cd ../iam\n
(Optional) Setup backend for store Terraform states remotely and support state locking and consistency checking via DynamoDB. Insert the missing fields in the file iam/providers.tf
.
...\n backend \"s3\" {\n bucket = \"terraform-states-<ACCOUNT_ID>\"\n key = \"<REGION>/<CLUSTER_NAME>/iam/terraform.tfstate\"\n region = \"<REGION>\"\n acl = \"bucket-owner-full-control\"\n dynamodb_table = \"terraform_locks\"\n encrypt = true\n }\n...\n
Note
If you plan to work with a local state, then comment out this block (the EDP team does not recommend this approach)
Fill in the input variables for Terraform run in the iam/template.tfvars
file. Use the iam/example.tfvars as an example. Please find the detailed description of the variables in the iam/variables.tf file.
# Template file to use as an example to create terraform.tfvars file. Fill the gaps instead of <...>\n# More details on each variable can be found in the variables.tf file\n\n# -- Condition to create or not IAM role for cluster deploy\ncreate_iam_deployer = true\n\n# -- Condition to create or not IAM role for Kaniko deploy\n# -- Need in case if used ECR registry. Create it after deploy EKS CLuster\ncreate_iam_kaniko = false\n\n# -- Worker and Deployer role variables\n\n# -- e.g eu-central-1\nregion = \"<REGION>\" # mandatory\n\n# -- Information about boundary policies\n# -- https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html\niam_permissions_boundary_policy_arn = \"arn:aws:iam::<AWS_ACCOUNT_ID>:policy/eo_role_boundary\" # mandatory\n\ntags = \"\" # isn't mandatory\n\n# -- Kaniko role variables\n\n# -- More information\n# -- https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html\ncluster_oidc_issuer_url = \"https://oidc.eks.<AWS_REGION>.amazonaws.com/id/<AWS_OIDC_ID>\"\n\noidc_provider_arn = \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.eks.<AWS_REGION>.amazonaws.com/id/<AWS_OIDC_ID>\"\n\nnamespace = \"edp\"\n
Initialize the backend and apply the changes.
terraform init\nterraform apply -var-file=./template.tfvars\n
View: Terraform output example Outputs:\n\nkaniko_iam_role_arn = []\nkaniko_iam_role_name = []\ndeployer_iam_role_arn = [\n \"arn:aws:iam::012345678910:role/EKSDeployerRole\",\n]\ndeployer_iam_role_name = [\n \"EKSDeployerRole\",\n]\n
This step will do the following:
Take the following steps:
Navigate to VPC module directory.
cd ../vpc\n
(Optional) Setup backend for store Terraform states remotely and support state locking and consistency checking via DynamoDB. Insert the missing fields in the file vpc/providers.tf
.
...\n backend \"s3\" {\n bucket = \"terraform-states-<ACCOUNT_ID>\"\n key = \"<REGION>/<CLUSTER_NAME>/vpc/terraform.tfstate\"\n region = \"<REGION>\"\n acl = \"bucket-owner-full-control\"\n dynamodb_table = \"terraform_locks\"\n encrypt = true\n }\n...\n
Note
If you plan to work with a local state, then comment out this block (the EDP team does not recommend this approach)
Fill in the input variables for Terraform run in the vpc/template.tfvars
file. Use the vpc/example.tfvars as an example. Please find the detailed description of the variables in the vpc/variables.tf file.
# -- e.g eu-central-1\nregion = \"<REGION>\"\n\nrole_arn = \"arn:aws:iam::<ACCOUNT_ID>:role/EKSDeployerRole\"\n\nplatform_name = \"<PLATFORM_NAME>\"\n\n# -- VPC CIDR, e.g. \"10.0.0.0/16\"\nplatform_cidr = \"<PLATFORM_CIDR>\"\n\n# -- VPC Subnets AZs, e.g. [\"eu-central-1a\", \"eu-central-1b\", \"eu-central-1c\"]\nsubnet_azs = [\"<SUBNET_AZS1>\", \"<SUBNET_AZS2>\"]\n\n# -- Private Subnets CIDR, e.g. [\"10.0.1.0/24\", \"10.0.2.0/24\", \"10.0.3.0/24\"]\nprivate_cidrs = [\"<PRIVATE_CIDRS1>\", \"<PRIVATE_CIDRS2>\"]\n\n# -- Private Subnets CIDR, e.g. [\"10.0.101.0/24\", \"10.0.102.0/24\", \"10.0.103.0/24\"]\npublic_cidrs = [\"<PUBLIC_CIDRS1>\", \"<PUBLIC_CIDRS2>\"]\n\n# -- Tags for resources, isn't mandatory\ntags = \"\"\n
Initialize the backend and apply the changes.
terraform init\nterraform apply -var-file=./template.tfvars\n
View: Terraform output example Outputs:\n\nprivate_subnets = [\n \"subnet-012345678910\",\n \"subnet-012345678910\",\n \"subnet-012345678910\",\n]\npublic_subnets = [\n \"subnet-012345678910\",\n \"subnet-012345678910\",\n \"subnet-012345678910\",\n]\nvpc_id = \"vpc-012345678910\"\n
This step will do the following:
Take the following steps:
Navigate to EKS module directory.
cd ../eks\n
(Optional) Setup backend for store Terraform states remotely and support state locking and consistency checking via DynamoDB. Insert the missing fields in the file eks/providers.tf
.
...\n backend \"s3\" {\n bucket = \"terraform-states-<ACCOUNT_ID>\"\n key = \"<REGION>/<CLUSTER_NAME>/eks/terraform.tfstate\"\n region = \"<REGION>\"\n acl = \"bucket-owner-full-control\"\n dynamodb_table = \"terraform_locks\"\n encrypt = true\n }\n...\n
Note
If you plan to work with a local state, then comment out this block (the EDP team does not recommend this approach)
Fill in the input variables for Terraform run in the eks/template.tfvars
file. Use the eks/example.tfvars as an example. Please find the detailed description of the variables in the eks/variables.tf file.
# -- e.g eu-central-1\nregion = \"<REGION>\"\nplatform_name = \"<PLATFORM_NAME>\"\nplatform_domain_name = \"<PLATFORM_DNS>\"\n\nrole_arn = \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/EKSDeployerRole\"\nrole_permissions_boundary_arn = \"arn:aws:iam::<AWS_ACCOUNT_ID>:policy/eo_role_boundary\"\n\nvpc_id = \"<VPC_ID>\" # VPC ID\nprivate_subnets_id = [] # EKS must have two subnets.\npublic_subnets_id = [] # ALB must have two subnets.\n\ninfra_public_security_group_ids = [] # List with security groups\n\n# -- Parameter in AWS Parameter Store that contain data in format \"account:token\" in base64 format\nadd_userdata = <<EOF\nexport TOKEN=$(aws ssm get-parameter --name <PARAMETER_NAME> --query 'Parameter.Value' --region <REGION> --output text)\ncat <<DATA > /var/lib/kubelet/config.json\n{\n \"auths\":{\n \"https://index.docker.io/v1/\":{\n \"auth\":\"$TOKEN\"\n }\n }\n}\nDATA\nEOF\n\nspot_instance_types = [] # list with instance types\n\naws_auth_users = [] # -- AWS List users\ntags = \"\"\n\nenable_argocd = true\n\nargocd_manage_add_ons = true\n\neks_addons_repo_ssh_key_secret_name = \"<AWS_SECRET_MANAGER_KEY>\" # ssh key with add-ons repository\n\nrepo_url = \"<SSH_REPO_URL>\" # repository with add-ons\n\naddons_path = \"<ADD_ONS_FOLDER>\" # path to add-ons folder at repository\n\n# OIDC Identity provider\ncluster_identity_providers = {}\n
This section contains variables to configure addons approach. Please find the detailed description about EDP addons.
Setup Argo CD for work with addons and store and management cluster applications using the GitOps approach. Fill in the input variables in the file eks/values/argocd-values.yaml.
configs:\n ssh:\n knownHosts: |\n # -- list of known host in format:\n # [host]:port key-type key\n # Example\n # [ssh.github.com]:443 ssh-rsa qgSdfOuiYhew/+afhQnvjfjhnhnqgSdfOuiYhew/+afhQnvjfjhnhn\n...\nserver:\n ingress:\n hosts:\n - \"argocd.example.com\"\n
Update local Kubernetes configuration:
aws eks update-kubeconfig --region <REGION> --name <CLUSTER_NAME>\n
After following the instructions provided, you should be able to configure AWS and create an EKS cluster with installed base utilities.
"},{"location":"operator-guide/deploy-aws-eks/#related-articles","title":"Related Articles","text":"This instruction provides detailed information on the OKD 4.10 cluster deployment in the AWS Cloud and contains the additional setup necessary for the managed infrastructure.
A full description of the cluster deployment can be found in the official documentation.
"},{"location":"operator-guide/deploy-okd-4.10/#prerequisites","title":"Prerequisites","text":"Before the OKD cluster deployment and configuration, make sure to check the prerequisites.
"},{"location":"operator-guide/deploy-okd-4.10/#required-tools","title":"Required Tools","text":"Install the following tools listed below:
Create the AWS IAM user with the required permissions. Make sure the AWS account is active, and the user doesn't have a permission boundary. Remove any Service Control Policy (SCP) restrictions from the AWS account.
Generate a key pair for cluster node SSH access. Please perform the steps below:
ssh-keygen -t ed25519 -N '' -f <path>/<file_name>\n
eval \"$(ssh-agent -s)\"\n
ssh-add <path>/<file_name>\n
Build the ccoctl
tool:
cloud-credential-operator
repository.git clone https://github.com/openshift/cloud-credential-operator.git\n
cloud-credential-operator
folder and build the ccoctl
tool.cd cloud-credential-operator && git checkout release-4.10\nGO_PACKAGE='github.com/openshift/cloud-credential-operator'\ngo build -ldflags \"-X $GO_PACKAGE/pkg/version.versionFromGit=$(git describe --long --tags --abbrev=7 --match 'v[0-9]*')\" ./cmd/ccoctl\n
Before deploying the OKD cluster, please perform the steps below:
"},{"location":"operator-guide/deploy-okd-4.10/#create-aws-resources","title":"Create AWS Resources","text":"Create the AWS resources with the Cloud Credential Operator utility (the ccoctl
tool):
Generate the public and private RSA key files that are used to set up the OpenID Connect identity provider for the cluster:
./ccoctl aws create-key-pair\n
Create an OpenID Connect identity provider and an S3 bucket on AWS:
./ccoctl aws create-identity-provider \\\n--name=<NAME> \\\n--region=<AWS_REGION> \\\n--public-key-file=./serviceaccount-signer.public\n
where:
Create the IAM roles for each component in the cluster:
Extract the list of the CredentialsRequest
objects from the OpenShift Container Platform release image:
oc adm release extract \\\n--credentials-requests \\\n--cloud=aws \\\n--to=./credrequests \\\n--quay.io/openshift-release-dev/ocp-release:4.10.25-x86_64\n
Note
A version of the openshift-release-dev docker image can be found in the Quay registry.
ccoctl
tool to process all CredentialsRequest
objects in the credrequests
directory:ccoctl aws create-iam-roles \\\n--name=<NAME> \\\n--region=<AWS_REGION> \\\n--credentials-requests-dir=./credrequests\n--identity-provider-arn=arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<NAME>-oidc.s3.<AWS_REGION>.amazonaws.com\n
Before deploying the OKD cluster, please perform the steps below:
Download the OKD installer.
Extract the installation program:
tar -xvf openshift-install-linux.tar.gz\n
Download the installation pull secret for any private registry. This pull secret allows to authenticate with the services that are provided by the authorities, including Quay.io, serving the container images for OKD components. For example, here is a pull secret for Docker Hub:
The pull secret for the private registry{\n \"auths\":{\n \"https://index.docker.io/v1/\":{\n \"auth\":\"$TOKEN\"\n }\n }\n}\n
Create a deployment directory and the install-config.yaml file:
mkdir okd-deployment\ntouch okd-deployment/install-config.yaml\n
To specify more details about the OKD cluster platform or to modify the values of the required parameters, customize the install-config.yaml file for the AWS. Please see below an example of the customized file:
install-config.yaml - OKD cluster\u2019s platform installation configuration fileapiVersion: v1\nbaseDomain: <YOUR_DOMAIN>\ncredentialsMode: Manual\ncompute:\n- architecture: amd64\n hyperthreading: Enabled\n name: worker\n platform:\n aws:\n rootVolume:\n size: 30\n zones:\n - eu-central-1a\n type: r5.large\n replicas: 3\ncontrolPlane:\n architecture: amd64\n hyperthreading: Enabled\n name: master\n platform:\n aws:\n rootVolume:\n size: 50\n zones:\n - eu-central-1a\n type: m5.xlarge\n replicas: 3\nmetadata:\n creationTimestamp: null\n name: 4-10-okd-sandbox\nnetworking:\n clusterNetwork:\n - cidr: 10.128.0.0/14\n hostPrefix: 23\n machineNetwork:\n - cidr: 10.0.0.0/16\n networkType: OVNKubernetes\n serviceNetwork:\n - 172.30.0.0/16\nplatform:\n aws:\n region: eu-central-1\n userTags:\n user:tag: 4-10-okd-sandbox\npublish: External\npullSecret: <PULL_SECRET>\nsshKey: |\n <SSH_KEY>\n
where:
Create the required OpenShift Container Platform installation manifests:
./openshift-install create manifests --dir okd-deployment\n
Copy the manifests generated by the ccoctl
tool to the manifests
directory created by the installation program:
cp ./manifests/* ./okd-deployment/manifests/\n
Copy the private key generated in the tls
directory by the ccoctl
tool to the installation directory:
cp -a ./tls ./okd-deployment\n
To initialize the cluster deployment, run the following command:
./openshift-install create cluster --dir okd-deployment --log-level=info\n
Note
If the cloud provider account configured on the host does not have sufficient permissions to deploy the cluster, the installation process stops, and the missing permissions are displayed.
When the cluster deployment is completed, directions for accessing the cluster are displayed in the terminal, including a link to the web console and credentials for the kubeadmin user. The kubeconfig
for the cluster will be located in okd-deployment/auth/kubeconfig.
...\nINFO Install complete!\nINFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/home/myuser/install_dir/auth/kubeconfig'\nINFO Access the OpenShift web-console here: https://console-openshift-console.apps.mycluster.example.com\nINFO Login to the console with the user: \"kubeadmin\", and password: \"4vYBz-Ee6gm-ymBZj-Wt5AL\"\nINFO Time elapsed: 36m22s:\n
Warning
The Ignition config files contain certificates that expire after 24 hours, which are then renewed at that time. Do not turn off the cluster for this time, or you will have to update the certificates manually. See OpenShift Container Platform documentation for more information.
"},{"location":"operator-guide/deploy-okd-4.10/#log-into-the-cluster","title":"Log Into the Cluster","text":"To log into the cluster, export the kubeconfig
:
export KUBECONFIG=<installation_directory>/auth/kubeconfig\n
Optionally, use the Lens tool for further work with the Kubernetes cluster.
Note
To install and manage the cluster, refer to Lens documentation.
"},{"location":"operator-guide/deploy-okd-4.10/#manage-okd-cluster-without-the-inbound-rules","title":"Manage OKD Cluster Without the Inbound Rules","text":"In order to manage the OKD cluster without the 0.0.0.0/0
inbound rules, please perform the steps below:
Create a Security Group with a list of your external IPs:
aws ec2 create-security-group --group-name <SECURITY_GROUP_NAME> --description \"<DESCRIPTION_OF_SECURITY_GROUP>\" --vpc-id <VPC_ID>\naws ec2 authorize-security-group-ingress \\\n--group-id '<SECURITY_GROUP_ID>' \\\n--ip-permissions 'IpProtocol=all,PrefixListIds=[{PrefixListId=<PREFIX_LIST_ID>}]'\n
Manually attach this new Security Group to all master nodes of the cluster.
Create another Security Group with an Elastic IP of the Cluster VPC:
aws ec2 create-security-group --group-name custom-okd-4-10 --description \"Cluster Ip to 80, 443\" --vpc-id <VPC_ID>\naws ec2 authorize-security-group-ingress \\\n --group-id '<SECURITY_GROUP_ID>' \\\n --protocol all \\\n --port 80 \\\n --cidr <ELASTIC_IP_OF_CLUSTER_VPC>\naws ec2 authorize-security-group-ingress \\\n --group-id '<SECURITY_GROUP_ID>' \\\n --protocol all \\\n --port 443 \\\n --cidr <ELASTIC_IP_OF_CLUSTER_VPC>\n
Modify the cluster load balancer via the router-default
svc in the openshift-ingress
namespace, paste two Security Groups created on previous steps:
apiVersion: v1\nkind: Service\nmetadata:\n name: router-default\n namespace: openshift-ingress\n annotations:\n service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: \"tag_name=some_value\"\n service.beta.kubernetes.io/aws-load-balancer-security-groups: \"<SECURITY_GROUP_IDs>\"\n ...\n
In order to optimize the usage of Spot Instances on the AWS, add the following line under the providerSpec
field in the MachineSet of Worker Nodes:
providerSpec:\n value:\n spotMarketOptions: {}\n
"},{"location":"operator-guide/deploy-okd-4.10/#related-articles","title":"Related Articles","text":"This instruction provides detailed information on the OKD 4.9 cluster deployment in the AWS Cloud and contains the additional setup necessary for the managed infrastructure.
A full description of the cluster deployment can be found in the official documentation.
"},{"location":"operator-guide/deploy-okd/#prerequisites","title":"Prerequisites","text":"Before the OKD cluster deployment and configuration, make sure to check the prerequisites.
"},{"location":"operator-guide/deploy-okd/#required-tools","title":"Required Tools","text":"Install the following tools listed below:
Create the AWS IAM user with the required permissions. Make sure the AWS account is active, and the user doesn't have a permission boundary. Remove any Service Control Policy (SCP) restrictions from the AWS account.
Generate a key pair for cluster node SSH access. Please perform the steps below:
ssh-keygen -t ed25519 -N '' -f <path>/<file_name>\n
eval \"$(ssh-agent -s)\"\n
ssh-add <path>/<file_name>\n
Before deploying the OKD cluster, please perform the steps below:
Download the OKD installer.
Extract the installation program:
tar -xvf openshift-install-linux.tar.gz\n
Download the installation pull secret for any private registry.
This pull secret allows to authenticate with the services that are provided by the included authorities, including Quay.io serving container images for OKD components. For example, here is a pull secret for Docker Hub:
The pull secret for the private registry{\n \"auths\":{\n \"https://index.docker.io/v1/\":{\n \"auth\":\"$TOKEN\"\n }\n }\n}\n
Create the deployment directory and the install-config.yaml file:
mkdir okd-deployment\ntouch okd-deployment/install-config.yaml\n
To specify more details about the OKD cluster platform or to modify the values of the required parameters, customize the install-config.yaml file for AWS. Please see an example of the customized file below:
install-config.yaml - OKD cluster\u2019s platform installation configuration fileapiVersion: v1\nbaseDomain: <YOUR_DOMAIN>\ncompute:\n- architecture: amd64\n hyperthreading: Enabled\n name: worker\n platform:\n aws:\n zones:\n - eu-central-1a\n rootVolume:\n size: 50\n type: r5.large\n replicas: 3\ncontrolPlane:\n architecture: amd64\n hyperthreading: Enabled\n name: master\n platform:\n aws:\n rootVolume:\n size: 50\n zones:\n - eu-central-1a\n type: m5.xlarge\n replicas: 3\nmetadata:\n creationTimestamp: null\n name: 4-9-okd-sandbox\nplatform:\n aws:\n region: eu-central-1\n userTags:\n user:tag: 4-9-okd-sandbox\npublish: External\npullSecret: <PULL_SECRET>\nsshKey: |\n <SSH_KEY>\n
where:
To initialize the cluster deployment, run the following command:
./openshift-install create cluster --dir <installation_directory> --log-level=info\n
Note
If the cloud provider account configured on the host does not have sufficient permissions to deploy the cluster, the installation process stops, and the missing permissions are displayed.
When the cluster deployment is completed, directions for accessing the cluster are displayed in the terminal, including a link to the web console and credentials for the kubeadmin user. The kubeconfig
for the cluster will be located in okd-deployment/auth/kubeconfig.
...\nINFO Install complete!\nINFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/home/myuser/install_dir/auth/kubeconfig'\nINFO Access the OpenShift web-console here: https://console-openshift-console.apps.mycluster.example.com\nINFO Login to the console with the user: \"kubeadmin\", and password: \"4vYBz-Ee6gm-ymBZj-Wt5AL\"\nINFO Time elapsed: 36m22s:\n
Warning
The Ignition config files contain certificates that expire after 24 hours, which are then renewed at that time. Do not turn off the cluster for this time, or you will have to update the certificates manually. See OpenShift Container Platform documentation for more information.
"},{"location":"operator-guide/deploy-okd/#log-into-the-cluster","title":"Log Into the Cluster","text":"To log into the cluster, export the kubeconfig
:
export KUBECONFIG=<installation_directory>/auth/kubeconfig\n
Optionally, use the Lens tool for further work with the Kubernetes cluster.
Note
To install and manage the cluster, refer to Lens documentation.
"},{"location":"operator-guide/deploy-okd/#related-articles","title":"Related Articles","text":"The Amazon Elastic Block Store (Amazon EBS) Container Storage Interface (CSI) driver allows Amazon Elastic Kubernetes Service (Amazon EKS) clusters to manage the lifecycle of Amazon EBS volumes for Kubernetes Persistent Volumes.
"},{"location":"operator-guide/ebs-csi-driver/#prerequisites","title":"Prerequisites","text":"An existing AWS Identity and Access Management (IAM) OpenID Connect (OIDC) provider for your cluster. To determine whether you already have an OIDC provider or to create a new one, see Creating an IAM OIDC provider for your cluster.
To add an Amazon EBS CSI add-on, please follow the steps below:
Check your cluster details (the random value in the cluster name will be required in the next step):
kubectl cluster-info\n
Create Kubernetes IAM Trust Policy for Amazon EBS CSI Driver. Replace AWS_ACCOUNT_ID
with your account ID, AWS_REGION
with your AWS Region, and EXAMPLED539D4633E53DE1B71EXAMPLE
with the value that was returned in the previous step. Save this Trust Policy into a file aws-ebs-csi-driver-trust-policy.json
.
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::AWS_ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud\": \"sts.amazonaws.com\",\n \"oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub\": \"system:serviceaccount:kube-system:ebs-csi-controller-sa\"\n }\n }\n }\n ]\n }\n
To get the notion of the IAM Role creation, please refer to the official documentation.
Create the IAM role, for example:
aws iam create-role \\\n --role-name AmazonEKS_EBS_CSI_DriverRole \\\n --assume-role-policy-document file://\"aws-ebs-csi-driver-trust-policy.json\"\n
Attach the required AWS Managed Policy AmazonEBSCSIDriverPolicy
to the role with the following command:
aws iam attach-role-policy \\\n --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \\\n --role-name AmazonEKS_EBS_CSI_DriverRole\n
Add the Amazon EBS CSI add-on using the AWS CLI. Replace my-cluster
with the name of your cluster, AWS_ACCOUNT_ID
with your account ID, and AmazonEKS_EBS_CSI_DriverRole
with the name of the role that was created earlier:
aws eks create-addon --cluster-name my-cluster --addon-name aws-ebs-csi-driver \\\n --service-account-role-arn arn:aws:iam::AWS_ACCOUNT_ID:role/AmazonEKS_EBS_CSI_DriverRole\n
Note
When the plugin is deployed, it creates the ebs-csi-controller-sa
service account. The service account is bound to a Kubernetes ClusterRole
with the required Kubernetes permissions. The ebs-csi-controller-sa
service account should already be annotated with arn:aws:iam::AWS_ACCOUNT_ID:role/AmazonEKS_EBS_CSI_DriverRole
. To check the annotation, please run:
kubectl get sa ebs-csi-controller-sa -n kube-system -o=jsonpath='{.metadata.annotations}'\n
In case pods have errors, restart the ebs-csi-controller
deployment:
kubectl rollout restart deployment ebs-csi-controller -n kube-system\n
EDP uses two different methods to regulate access to resources, each tailored to specific scenarios:
roles
and groups
in Keycloak and is used for SonarQube and partly for Nexus.EDP custom resources
. This approach requires modifying custom resources that outline the required access privileges for every user or group and is used to govern access to Gerrit, Nexus, EDP Portal, EKS Cluster and Argo CD.Info
These two approaches are not interchangeable, as each has its unique capabilities.
"},{"location":"operator-guide/edp-access-model/#keycloak","title":"Keycloak","text":"This section explains what realm roles and realm groups are and how they function within Keycloak.
"},{"location":"operator-guide/edp-access-model/#realm-roles","title":"Realm Roles","text":"The Keycloak realm of edp
has two realm roles with a composite types named administrator
and developer
:
administrator
realm role is designed for users who need administrative access to the tools used in the project. This realm role contains the sonar-administrators
role. Users who are assigned the administrator
realm role will be granted these two roles automatically.developer
realm role, on the other hand, is designed for users who need access to the development tools used in the project. This realm role also contains the sonar-developers
role. Users who are assigned the developer
realm role will be granted these two roles automatically.These realm roles have been defined to make it easier to assign groups of rights to users.
The table below shows the realm roles and the composite types they relate to.
Realm Role Name Regular Role Composite role administrator developer sonar-administrators sonar-developers"},{"location":"operator-guide/edp-access-model/#realm-groups","title":"Realm Groups","text":"EDP uses two different realms for group management, edp
and openshift
:
edp
realm contains two groups that are specifically used for controlling access to Argo CD. These groups are named ArgoCDAdmins
and ArgoCD-edp-users
.openshift
realm contains five groups that are used for access control in both the EDP Portal and EKS cluster. These groups are named edp-oidc-admins
, edp-oidc-builders
, edp-oidc-deployers
,edp-oidc-developers
and edp-oidc-viewers
.edp
ArgoCD-edp-users
edp
edp-oidc-admins
openshift edp-oidc-builders
openshift edp-oidc-deployers
openshift edp-oidc-developers
openshift edp-oidc-viewers
openshift"},{"location":"operator-guide/edp-access-model/#sonarqube","title":"SonarQube","text":"In the case of SonarQube, there are two ways to manage access: via Keycloak and via EDP approach. This sections describes both of the approaches.
"},{"location":"operator-guide/edp-access-model/#manage-access-via-keycloak","title":"Manage Access via Keycloak","text":"SonarQube access is managed using Keycloak roles in the edp
realm. The sonar-developers
and sonar-administrators
realm roles are the two available roles that determine user access levels. To grant access, the corresponding role must be added to the user in Keycloak.
For example, a user who needs developer access to SonarQube should be assigned the sonar-developers
or developer
composite role in Keycloak.
EDP provides its own SonarQube Permission Template, which is used to manage user access and permissions for SonarQube projects.
The template is stored in the custom SonarQube resource of the operator, an example of a custom resource can be found below.
SonarPermissionTemplate
apiVersion: v2.edp.epam.com/v1\nkind: SonarPermissionTemplate\nmetadata:\n name: edp-default\nspec:\n description: EDP permission templates (DO NOT REMOVE)\n groupPermissions:\n - groupName: non-interactive-users\n permissions:\n - user\n - groupName: sonar-administrators\n permissions:\n - admin\n - user\n - groupName: sonar-developers\n permissions:\n - codeviewer\n - issueadmin\n - securityhotspotadmin\n - user\n name: edp-default\n projectKeyPattern: .+\n sonarOwner: sonar\n
The SonarQube Permission Template contains three groups: non-interactive-users
, sonar-administrators
and sonar-developers
:
non-interactive-users
are users who do not require direct access to the SonarQube project but need to be informed about the project's status and progress. This group has read-only access to the project, which means that they can view the project's data and metrics but cannot modify or interact with it in any way.sonar-administrators
are users who have full control over the SonarQube project. They have the ability to create, modify, and delete projects, as well as manage user access and permissions. This group also has the ability to configure SonarQube settings and perform other administrative tasks.sonar-developers
are users who are actively working on the SonarQube project. They have read and write access to the project, which means that they can modify the project's data and metrics. This group also has the ability to configure project-specific settings and perform other development tasks.These groups are designed to provide different levels of access to the SonarQube project, depending on the user's role and responsibilities.
Info
If a user has no group, it will have the sonar-users
group by default. This group does not have any permissions in the edp-default
Permission Template.
The permissions that are attached to each of the groups are described below in the table:
Group Name Permissionsnon-interactive-users
user sonar-administrators
admin, user sonar-developers
codeviewer, issueadmin, securityhotspotadmin, user sonar-users
-"},{"location":"operator-guide/edp-access-model/#nexus","title":"Nexus","text":"Users authenticate to Nexus using their Keycloak credentials.
During the authentication process, the OAuth2-Proxy receives the user's role from Keycloak.
Info
Only users with either the administrator
or developer
role in Keycloak can access Nexus.
Nexus has four distinct roles available, including edp-admin
, edp-viewer
, nx-admin
and nx-anonymous
. To grant the user access to one or more of these roles, an entry must be added to the custom Nexus resource.
For instance, in the context of the custom Nexus resource, the user \"user_1@example.com\" has been assigned the \"nx-admin\" role. An example can be found below:
Nexus
apiVersion: v2.edp.epam.com/v1\nkind: Nexus\nmetadata:\n name: nexus\nspec:\n basePath: /\n edpSpec:\n dnsWildcard: example.com\n keycloakSpec:\n enabled: false\n roles:\n - developer\n - administrator\n users:\n - roles:\n - nx-admin\n username: user_1@example.com\n
"},{"location":"operator-guide/edp-access-model/#gerrit","title":"Gerrit","text":"The user should use their credentials from Keycloak when authenticating to Gerrit.
After logging into Gerrit, the user is not automatically attached to any groups. To add a user to a group, the GerritGroupMember
custom resource must be created. This custom resource specifies the user's email address and the name of the group to which they should be added.
The ConfigMap below is an example of the GerritGroupMember
resource:
GerritGroupMember
apiVersion: v2.edp.epam.com/v1\nkind: GerritGroupMember\nmetadata:\n name: user-admins\nspec:\n accountId: user@user.com\n groupId: Administrators\n
After the GerritGroupMember
resource is created, the user will have the permissions and access levels associated with that group.
Both Portal and EKS Cluster use Keycloak groups for controlling access. Users need to be added to the required group in Keycloak to get access. The groups that are used for access control are in the openshift
realm.
Note
The openshift
realm is used because a Keycloak client for OIDC is in this realm.
There are two types of groups provided for users:
For example, the edp-oidc-viewers
group can be extended with rights from the edp-oidc-builders
group.
edp-oidc-admins
edp-oidc-developers
edp-oidc-viewers
edp-oidc-builders
edp-oidc-deployers
Name Action List View Getting of all namespaced resources Build Starting a PipelineRun from EDP Portal UI Deploy Deploying a new version of application via Argo CD Application Group Name View Build Deploy Full Namespace Access edp-oidc-admins
edp-oidc-developers
edp-oidc-viewers
edp-oidc-builders
edp-oidc-deployers
"},{"location":"operator-guide/edp-access-model/#cluster-rbac-resources","title":"Cluster RBAC Resources","text":"The edp
namespace has five role bindings that provide the necessary permissions for the Keycloak groups described above.
edp-oidc-admins
tenant-builder tenant-builder edp-oidc-builders
tenant-deployer tenant-deployer edp-oidc-deployers
tenant-developer tenant-developer edp-oidc-developers
tenant-viewer view edp-oidc-viewers
, edp-oidc-developers
Note
EDP provides an aggregate ClusterRole with permissions to view custom EDP resources. ClusterRole is named edp-aggregate-view-edp
Info
The tenant-admin
RoleBinding will be created in a created namespace by cd-pipeline-operator
. tenant-admin
RoleBinding assign the admin
role to edp-oidc-admins
and edp-oidc-developers
groups.
To provide users with admin or developer privileges for project namespaces, they need to be added to the edp-oidc-admins
and edp-oidc-developers
groups in Keycloak.
In Argo CD, groups are specified when creating an AppProject to restrict access to deployed applications. To gain access to deployed applications within a project, the user must be added to their corresponding Argo CD group in Keycloak. This ensures that only authorized users can access and modify applications within the project.
Info
By default, only the ArgoCDAdmins
group is automatically created in Keycloak.
Explore the way Kiosk, a multi-tenancy extension for Kubernetes, is used in EDP.
"},{"location":"operator-guide/edp-kiosk-usage/#prerequisites","title":"Prerequisites","text":"Kiosk usage
Agenda
edp
installation of EDP generates new Kiosk Space resource that is linked to edp Kiosk Account;This page is a detailed guide on integrating Keycloak with the edp-keycloak-operator to serve as an identity provider for AWS Elastic Kubernetes Service (EKS). It provides step-by-step instructions for creating necessary realms, users, roles, and client configurations for a seamless Keycloak-EKS collaboration. Additionally, it includes guidelines on installing the edp-keycloak-operator using Helm charts.
"},{"location":"operator-guide/eks-oidc-integration/#prerequisites","title":"Prerequisites","text":"To prepare Keycloak for integration with the edp-keycloak-operator, follow the steps below:
Ensure that the openshift realm is created.
Create the orchestrator user and set the password in the Master realm.
In the Role Mapping tab, assign the proper roles to the user:
Realm Roles:
Client Roles openshift-realm
:
Role mappings
"},{"location":"operator-guide/eks-oidc-integration/#install-keycloak-operator","title":"Install Keycloak Operator","text":"To install the Keycloak operator, follow the steps below:
Add the epamedp
Helm chart to a local client:
helm repo add epamedp https://epam.github.io/edp-helm-charts/stable\nhelm repo update\n
Install the Keycloak operator:
helm install keycloak-operator epamedp/keycloak-operator --namespace security --set name=keycloak-operator\n
The next stage after installing Keycloak is to integrate it with the Keycloak operator. It can be implemented with the following steps:
Create the keycloak secret that will contain username and password to perform the integration. Set your own password. The username must be orchestrator:
kubectl -n security create secret generic keycloak \\\n --from-literal=username=orchestrator \\\n --from-literal=password=<password>\n
Create the Keycloak Custom Resource with the Keycloak instance URL and the secret created in the previous step:
apiVersion: v1.edp.epam.com/v1\nkind: Keycloak\nmetadata:\n name: main\n namespace: security\nspec:\n secret: keycloak # Secret name\n url: https://keycloak.example.com # Keycloak URL\n
Create the KeycloakRealm Custom Resource:
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealm\nmetadata:\n name: control-plane\n namespace: security\nspec:\n realmName: control-plane\n keycloakOwner: main\n
Create the KeycloakRealmGroup Custom Resource for both administrators and developers:
administratorsdevelopersapiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmGroup\nmetadata:\n name: administrators\n namespace: security\nspec:\n realm: control-plane\n name: eks-oidc-administrator\n
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmGroup\nmetadata:\n name: developers\n namespace: security\nspec:\n realm: control-plane\n name: eks-oidc-developers\n
Create the KeycloakClientScope Custom Resource:
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakClientScope\nmetadata:\n name: groups-keycloak-eks\n namespace: security\nspec:\n name: groups\n realm: control-plane\n description: \"Group Membership\"\n protocol: openid-connect\n protocolMappers:\n - name: groups\n protocol: openid-connect\n protocolMapper: \"oidc-group-membership-mapper\"\n config:\n \"access.token.claim\": \"true\"\n \"claim.name\": \"groups\"\n \"full.path\": \"false\"\n \"id.token.claim\": \"true\"\n \"userinfo.token.claim\": \"true\"\n
Create the KeycloakClient Custom Resource:
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakClient\nmetadata:\n name: eks\n namespace: security\nspec:\n advancedProtocolMappers: true\n clientId: eks\n directAccess: true\n public: false\n defaultClientScopes:\n - groups\n targetRealm: control-plane\n webUrl: \"http://localhost:8000\"\n
Create the KeycloakRealmUser Custom Resource for both administrator and developer roles:
administrator roledeveloper roleapiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmUser\nmetadata:\n name: keycloakrealmuser-sample\n namespace: security\nspec:\n realm: control-plane\n username: \"administrator\"\n firstName: \"John\"\n lastName: \"Snow\"\n email: \"administrator@example.com\"\n enabled: true\n emailVerified: true\n password: \"12345678\"\n keepResource: true\n requiredUserActions:\n - UPDATE_PASSWORD\n groups:\n - eks-oidc-administrator\n
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakRealmUser\nmetadata:\n name: keycloakrealmuser-sample\n namespace: security\nspec:\n realm: control-plane\n username: \"developers\"\n firstName: \"John\"\n lastName: \"Snow\"\n email: \"developers@example.com\"\n enabled: true\n emailVerified: true\n password: \"12345678\"\n keepResource: true\n requiredUserActions:\n - UPDATE_PASSWORD\n groups:\n - eks-oidc-developers\n
As a result, Keycloak is integrated with the AWS Elastic Kubernetes Service. This integration enables users to log in to the EKS cluster effortlessly using their kubeconfig files while managing permissions through Keycloak.
This page contains accurate information on how to associate an IAM role with the service account (IRSA) in EPAM Delivery Platform.
Get acquainted with the AWS Official Documentation on the subject before proceeding.
"},{"location":"operator-guide/enable-irsa/#common-configuration-of-iam-roles-with-service-accounts","title":"Common Configuration of IAM Roles With Service Accounts","text":"To successfully associate the IAM role with the service account, follow the steps below:
Create an IAM role that will further be associated with the service account. This role must have the following trust policy:
IAM Role
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER>\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"<OIDC_PROVIDER>:sub\": \"system:serviceaccount:<SERVICE_ACCOUNT_NAMESPACE>:<SERVICE_ACCOUNT_NAME>\"\n }\n }\n }\n ]\n}\n
View cluster's \u2039OIDC_PROVIDER\u203a URL.
aws eks describe-cluster --name <CLUSTER_NAME> --query \"cluster.identity.oidc.issuer\" --output text\n
Example output:
https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E\n
\u2039OIDC_PROVIDER\u203a in this example will be:
oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E\n
Deploy the amazon-eks-pod-identity-webhook v0.2.0.
Note
The amazon-eks-pod-identity-webhook functionality is provided out of the box in EKS v1.21 and higher. This does not apply if the cluster has been upgraded from older versions. Therefore, skip step 2 and continue from step 3 in this documentation.
2.1. Provide the stable(ed8c41f) version of the Docker image in the deploy/deployment-base.yaml file.
2.2. Provide ${CA_BUNDLE}_in the_deploy/mutatingwebhook.yaml file:
secret_name=$(kubectl -n default get sa default -o jsonpath='{.secrets[0].name}') \\\n CA_BUNDLE=$(kubectl -n default get secret/$secret_name -o jsonpath='{.data.ca\\.crt}' | tr -d '\\n')\n
2.3. Deploy the Webhook:
kubectl apply -f deploy/\n
2.4. Approve the csr:
csr_name=$(kubectl get csr -o jsonpath='{.items[?(@.spec.username==\"system:serviceaccount:default:pod-identity-webhook\")].metadata.name}')\n kubectl certificate approve $csr_name\n
Annotate the created service account with the IAM role:
Service Account
apiVersion: v1\n kind: ServiceAccount\n metadata:\n name: <SERVICE_ACCOUNT_NAME>\n namespace: <NAMESPACE>\n annotations:\n eks.amazonaws.com/role-arn: \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>\"\n
All newly launched pods with this service account will be modified and then use the associated IAM role. Find below the pod specification template:
Pod Template
apiVersion: v1\n kind: Pod\n metadata:\n name: irsa-test\n namespace: <POD_NAMESPACE>\n spec:\n serviceAccountName: <SERVICE_ACCOUNT_NAME>\n securityContext:\n fsGroup: 65534\n containers:\n - name: terraform\n image: epamedp/edp-jenkins-terraform-agent:3.0.9\n command: ['sh', '-c', 'aws sts \"get-caller-identity\" && sleep 3600']\n
Check the logs of the created pod from the template above.
Example output:
{\n \"UserId\": \"XXXXXXXXXXXXXXXXXXXXX:botocore-session-XXXXXXXXXX\",\n \"Account\": \"XXXXXXXXXXXX\",\n \"Arn\": \"arn:aws:sts::XXXXXXXXXXXX:assumed-role/AWSIRSATestRole/botocore-session-XXXXXXXXXX\"\n }\n
As a result, it is possible to perform actions in AWS under the AWSIRSATestRole role.
External Secrets Operator (ESO) can be integrated with EDP.
There are multiple Secrets Providers that can be used within ESO. EDP is integrated with two major providers:
EDP uses various secrets to integrate various applications. Below is a list of secrets that are used in the EPAM Delivery Platform and their description. All the secrets are encoded in Base64 format.
Secret Name Fields Description Used by keycloak usernamepassword Username and password with specific rights for EDP tenant in Keycloak keycloak-operator ci-defectdojo tokenurl DefectDojo tokenDefectDojo URL edp-tekton kaniko-docker-config .dockerconfigjson Serialized JSON that follows docker config patterns edp-tekton regcred .dockerconfigjson Serialized JSON that follows docker config patterns cd-pipeline-operator ci-github id_rsatokensecretString Private key from github repo API tokenRandom string edp-tekton ci-gitlab id_rsatokensecretString Private key from gitlab repo API tokenRandom string edp-tekton ci-jira usernamepassword Jira username Jira password edp-codebase-operator ci-sonarqube tokenurl SonarQube tokenSonarQube URL edp-tekton ci-nexus usernamepasswordurl Nexus usernameNexus passwordNexus URL edp-tekton ci-dependency-track tokenurl Dependency-Track tokenDependency-Track URL edp-tekton oauth2-proxy-cookie-secret cookie-secret Secret key for oauth2-proxy edp-install keycloak-client-headlamp-secret clientSecret Secret key for keycloak client keycloak-operator"},{"location":"operator-guide/external-secrets-operator-integration/#edp-core-secrets","title":"EDP Core Secrets","text":"The list below represents the baseline required for full operation within EDP:
These secrets are mandatory for Tekton pipelines to work properly.
"},{"location":"operator-guide/external-secrets-operator-integration/#kubernetes-provider","title":"Kubernetes Provider","text":"All secrets are stored in Kubernetes in pre-defined namespaces. EDP suggests using the following approach for secrets management:
EDP_NAMESPACE-vault
, where EDP_NAMESPACE is a name of the namespace where EDP is deployed, such as edp-vault
. This namespace is used by EDP platform. Access to secrets in the edp-vault
is permitted only for EDP Administrators
.EDP_NAMESPACE-cicd-vault
, where EDP_NAMESPACE is a name of the namespace where EDP is deployed, such as edp-cicd-vault
. Development team uses access to secrets in the edp-cicd-vault
for microservices development.See a diagram below for more details:
In order to install EDP, a list of passwords must be created. Secrets are provided automatically when using ESO.
Create a common namespace for secrets and EDP:
kubectl create namespace edp-vault\nkubectl create namespace edp\n
Create secrets in the edp-vault
namespace:
apiVersion: v1\nkind: Secret\nmetadata:\n name: keycloak\n namespace: edp-vault\ndata:\n password: cGFzcw== # pass in base64\n username: dXNlcg== # user in base64\ntype: Opaque\n
In the edp-vault
namespace, create a Role with a permission to read secrets:
apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n namespace: edp-vault\n name: external-secret-store\nrules:\n- apiGroups: [\"\"]\n resources:\n - secrets\n verbs:\n - get\n - list\n - watch\n- apiGroups:\n - authorization.k8s.io\n resources:\n - selfsubjectrulesreviews\n verbs:\n - create\n
In the edp-vault
namespace, create a ServiceAccount used by SecretStore
:
apiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: secret-manager\n namespace: edp\n
Connect the Role from the edp-vault
namespace with the ServiceAccount in the edp
namespace:
apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n name: eso-from-edp\n namespace: edp-vault\nsubjects:\n - kind: ServiceAccount\n name: secret-manager\n namespace: edp\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: Role\n name: external-secret-store\n
Create a SecretStore in the edp
namespace, and use ServiceAccount for authentication:
apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: edp-vault\n namespace: edp\nspec:\n provider:\n kubernetes:\n remoteNamespace: edp-vault # namespace with secrets\n auth:\n serviceAccount:\n name: secret-manager\n server:\n caProvider:\n type: ConfigMap\n name: kube-root-ca.crt\n key: ca.crt\n
Each secret must be defined by the ExternalSecret
object. A code example below creates the keycloak
secret in the edp
namespace based on a secret with the same name in the edp-vault
namespace:
apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: keycloak\n namespace: edp\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: edp-vault\n # target:\n # name: secret-to-be-created # name of the k8s Secret to be created. metadata.name used if not defined\n data:\n - secretKey: username # key to be created\n remoteRef:\n key: keycloak # remote secret name\n property: username # value will be fetched from this field\n - secretKey: password # key to be created\n remoteRef:\n key: keycloak # remote secret name\n property: password # value will be fetched from this field\n
Apply the same approach for enabling secrets management in the namespaces used for microservices development, such as sit
and qa
on the diagram above.
AWS SSM Parameter Store can be used as a Secret Provider for ESO. For EDP, it is recommended to use the IAM Roles For Service Accounts approach (see a diagram below).
"},{"location":"operator-guide/external-secrets-operator-integration/#aws-parameter-store-in-edp-scenario","title":"AWS Parameter Store in EDP Scenario","text":"In order to install EDP, a list of passwords must be created. Follow the steps below, to get secrets from the SSM:
In the AWS, create an AWS IAM policy and an IAM role used by ServiceAccount
in SecretStore
. The IAM role must have permissions to get values from the SSM Parameter Store.
a. Create an IAM policy that allows to get values from the Parameter Store with the edp/
path. Use your AWS Region
and AWS Account Id
:
{\n\"Version\": \"2012-10-17\",\n\"Statement\": [\n {\n \"Sid\": \"VisualEditor0\",\n \"Effect\": \"Allow\",\n \"Action\": \"ssm:GetParameter*\",\n \"Resource\": \"arn:aws:ssm:eu-central-1:012345678910:parameter/edp/*\"\n }\n]\n}\n
b. Create an AWS IAM role with trust relationships (defined below) and attach the IAM policy. Put your string for Federated
value (see more on IRSA enablement for EKS Cluster) and AWS region.
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::012345678910:oidc-provider/oidc.eks.eu-central-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXX\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringLike\": {\n \"oidc.eks.eu-central-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXX:sub\": \"system:serviceaccount:edp:*\"\n }\n }\n }\n ]\n}\n
Create a secret in the AWS Parameter Store with the name /edp/my-json-secret
. This secret is represented as a parameter of type string within the AWS Parameter Store:
{\n \"keycloak\":\n {\n \"username\": \"keycloak-username\",\n \"password\": \"keycloak-password\"\n },\n \"defectdojo-ciuser-token\":\n {\n \"token\": \"XXXXXXXXXXXX\",\n \"url\": \"https://defectdojo.example.com\"\n },\n \"kaniko-docker-config\":\n {\n \"auths\" :\n {\n \"registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\": \"<base64 encoded 'user:secret' string>\"\n }\n }},\n \"regcred\":\n {\n \"auths\":\n {\n \"registry.com\":\n {\n \"username\":\"registry-username\",\n \"password\":\"registry-password\",\n \"auth\":\"<base64 encoded 'user:secret' string>\"\n }\n }},\n \"github-config\":\n {\n \"id_rsa\": \"id-rsa-key\",\n \"token\": \"github-token\",\n \"secretString\": \"XXXXXXXXXXXX\"\n },\n \"gitlab-config\":\n {\n \"id_rsa\": \"id-rsa-key\",\n \"token\": \"gitlab-token\",\n \"secretString\": \"XXXXXXXXXXXX\"\n },\n \"jira-user\":\n {\n \"username\": \"jira-username\",\n \"password\": \"jira-password\"\n },\n \"sonar-ciuser-token\": { \"username\": \"<ci-user>\", \"secret\": \"<secret>\" },\n \"nexus-ci-user\": { \"username\": \"<ci.user>\", \"password\": \"<secret>\" },\n \"oauth2-proxy-cookie-secret\": { \"cookie-secret\": \"XXXXXXXXXXXX\" },\n \"nexus-proxy-cookie-secret\": { \"cookie-secret\": \"XXXXXXXXXXXX\" },\n \"keycloak-client-headlamp-secret\": \"XXXXXXXXXXXX\",\n \"keycloak-client-argo-secret\": \"XXXXXXXXXXXX\"\n}\n
Set External Secret operator enabled by updating the values.yaml file:
EDP install values.yamlexternalSecrets:\n enabled: true\n
Install/upgrade edp-install:
helm upgrade --install edp epamedp/edp-install --wait --timeout=900s \\\n--version <edp_version> \\\n--values values.yaml \\\n--namespace edp \\\n--atomic\n
A webhook enables third-party services like GitHub to send real-time updates to an application. Updates are triggered by an event or an action by the webhook provider (for example, a push to a repository, a Pull Request creation), and pushed to the application via HTTP requests, namely, Jenkins. The GitHub Jenkins job provisioner creates a webhook in the GitHub repository during the Create release pipeline once the Integrate GitHub/GitLab in Jenkins is enabled and the GitHub Webhook Configuration is completed.
The Jenkins setup in EDP uses the following plugins responsible for listening on GitHub webhooks:
In case of any issues with webhooks, try the following solutions:
Check that the firewalls are configured to accept the incoming traffic from the IP address range that is described in the GitHub documentation.
Check that GitHub Personal Access Token is correct and has sufficient scope permissions.
Check that the job has run at least once before using the hook (once an application is created in EDP, the build job should be run automatically in Jenkins).
Check that both Push and issue comment and Pull Request webhooks are created on the GitHub side (unlike GitLab, GitHub does not need separate webhooks for each branch):
Webhooks settings
Click each webhook and check if the event delivery is successful:
https://jenkins-the-host.com/github-webhook/
for the GitHub plugin and https://jenkins-the-host.com/ghprbhook/
for the GitHub Pull Request Builder.Check that the X-Hub-Signature secret is verified. It is provided by the Jenkins GitHub plugin for Push events and by the GitHub Pull Request Builder plugin for Pull Request events. The Secret field is optional. Nevertheless, if incorrect, it can prevent webhook events.
For the GitHub plugin (Push events):
For the GitHub Pull Request Builder (Pull Request events):
Redeliver events by clicking the Redeliver button and check the Response body.
Manage webhook
Note
Use Postman to debug webhooks. Add all headers to Postman from the webhook Request -> Headers field and send the payload (Request body) using the appropriate content type.
Examples for Push and Pull Request events:
Postman push event payload headers GitHub plugin push events
The response in the Jenkins log:
Jan 17, 2022 8:51:14 AM INFO org.jenkinsci.plugins.github.webhook.subscriber.PingGHEventSubscriber onEvent\nPING webhook received from repo <https://github.com/user-profile/user-repo>!\n
Postman pull request event payload headers GitHub pull request builder
The response in the Jenkins log:
Jan 17, 2022 8:17:53 AM FINE org.jenkinsci.plugins.ghprb.GhprbRootAction\nGot payload event: ping\n
Check that the repo pushing to Jenkins, the GitHub project URL in the project configuration, and the repos in the pipeline Job must be lined up.
Enable the GitHub hook trigger for GITScm polling for the Build job.
GitHub hook trigger
Enable the GitHub Pull Request Builder for the Code Review job.
GitHub pull request builder
Filter through Jenkins log by using Jenkins custom log recorder:
The Push events for the GitHub:
Logger Log Level org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventSubscriber ALL com.cloudbees.jenkins.GitHubPushTrigger ALL com.cloudbees.jenkins.GitHubWebHook ALL org.jenkinsci.plugins.github.webhook.WebhookManager ALL org.jenkinsci.plugins.github.webhook.subscriber.PingGHEventSubscriber ALLThe Pull Request events for the GitHub Pull Request Builder:
Logger Log Level org.jenkinsci.plugins.ghprb.GhprbRootAction ALL org.jenkinsci.plugins.ghprb.GhprbTrigger ALL org.jenkinsci.plugins.ghprb.GhprbPullRequest ALL org.jenkinsci.plugins.ghprb.GhprbRepository ALLNote
Below is an example of using the Pipeline script with webhooks for the GitHub plugin implemented in the EDP pipelines:
properties([pipelineTriggers([githubPush()])])\n\nnode {\n git credentialsId: 'github-sshkey', url: 'https://github.com/someone/something.git', branch: 'master'\n}\n
Push events may not work correctly with the Job Pipeline script from SCM option in the current version of the GitHub plugin 1.34.1.
Follow the steps below to automatically integrate Jenkins with GitHub webhooks.
Note
Before applying the GitHub integration, make sure you have already visited the Integrate GitHub/GitLab in Jenkins page.
Ensure the new job provisioner is created, as well as Secret with SSH key and GitServer custom resources.
Ensure the access token for GitHub is created.
Navigate to Dashboard -> Manage Jenkins -> Manage Credentials -> Global -> Add Credentials, and create new credentials with the Secret text kind. In the Secret field, provide the GitHub API token, fill in the ID field with the github-access-token
value:
Jenkins github credentials
Navigate to Jenkins -> Manage Jenkins -> Configure system -> GitHub, and configure the GitHub server:
GitHub plugin config GitHub plugin Shared secrets config
Note
Keep the Manage hooks checkbox clear since the Job Provisioner automatically creates webhooks in the repository regardless of the checkbox selection. Select Advanced to see the shared secrets that can be used in a webhook Secret field to authenticate payloads from GitHub to Jenkins. The Secret field is optional.
Configure the GitHub Pull Request Builder plugin. This plugin is responsible for listening on Pull Request webhook events and triggering Code Review jobs:
Note
The Secret field is optional and is used in a webhook Secret field to authenticate payloads from GitHub to Jenkins. For details, please refer to the official GitHub pull request builder plugin documentation.
GitHub pull plugin config
A webhook enables third-party services like GitLab to send real-time updates to the application. Updates are triggered by an event or action by the webhook provider (for example, a push to a repository, a Merge Request creation), and pushed to the application via the HTTP requests, namely, Jenkins. The GitLab Jenkins job provisioner creates a webhook in the GitLab repository during the Create release pipeline once the Integrate GitHub/GitLab in Jenkins is enabled and the GitLab Integration is completed.
The Jenkins setup in EDP uses the GitLab plugin responsible for listening on GitLab webhook Push and Merge Request events.
In case of any issues with webhooks, try the following solutions:
Check that the firewalls are configured to accept incoming traffic from the IP address range that is described in the GitLab documentation.
Check that GitLab Personal Access Token is correct and has the api scope. If you have used the Project Access Token, make sure that the role is Owner or Maintainer, and it has the api scope.
Check that the job has run at least once before using the hook (once an application is created in EDP, the build job should be run automatically in Jenkins).
Check that both Push Events, Note Events and Merge Requests Events, Note Events webhooks are created on the GitLab side for each branch (unlike GitHub, GitLab must have separate webhooks for each branch).
Webhooks list
Click Edit next to each webhook and check if the event delivery is successful. If the webhook is sent, the Recent Deliveries list becomes available. Click View details.
Webhooks settings
https://jenkins-server.com/project/project-name/MAIN-Build-job
is for the Push events. https://jenkins-server.com/project/project-name/MAIN-Code-review-job
is for the Merge Request events.Verify the Secret token (X-Gitlab-Token). This token comes from the Jenkins job due to the Jenkins GitLab Plugin and is created by our Job Provisioner:
Secret token is optional and can be empty. Nevertheless, if incorrect, it can prevent webhook events.
Redeliver events by clicking the Resend Request button and check the Response body.
Note
Use Postman to debug webhooks. Add all headers to Postman from the webhook Request Headers field and send the payload (Request body) using the appropriate content type.
Examples for Push and Merge Request events:
Postman push request payload headers Push request build pipeline
The response in the Jenkins log:
Jan 17, 2022 11:26:34 AM INFO com.dabsquared.gitlabjenkins.webhook.GitLabWebHook getDynamic\nWebHook call ed with url: /project/project-name/MAIN-Build-job\nJan 17, 2022 11:26:34 AM INFO com.dabsquared.gitlabjenkins.trigger.handler.AbstractWebHookTriggerHandler handle\nproject-name/MAIN-Build-job triggered for push.\n
Postman merge request payload headers Merge request code review pipeline
The response in the Jenkins log:
Jan 17, 2022 11:14:58 AM INFO com.dabsquared.gitlabjenkins.webhook.GitLabWebHook getDynamic\nWebHook called with url: /project/project-name/MAIN-Code-review-job\n
Check that the repository pushing to Jenkins and the repository(ies) in the pipeline Job are lined up. GitLab Connection must be defined in the job settings.
Check that the settings in the Build Triggers for the Build job are as follows:
Build triggers build pipeline
Check that the settings in the Build Triggers for the Code Review job are as follows:
Build triggers code review pipeline
Filter through Jenkins log by using Jenkins custom log recorder:
The Push and Merge Request events for the GitLab:
Logger Log Level com.dabsquared.gitlabjenkins.webhook.GitLabWebHook ALL com.dabsquared.gitlabjenkins.trigger.handler.AbstractWebHookTriggerHandler ALL com.dabsquared.gitlabjenkins.trigger.handler.merge.MergeRequestHookTriggerHandlerImpl ALL com.dabsquared.gitlabjenkins.util.CommitStatusUpdater ALLFollow the steps below to automatically create and integrate Jenkins GitLab webhooks.
Note
Before applying the GitLab integration, make sure to enable Integrate GitHub/GitLab in Jenkins. For details, please refer to the Integrate GitHub/GitLab in Jenkins page.
Ensure the new job provisioner is created, as well as Secret with SSH key and GitServer custom resources.
Ensure the access token for GitLab is created.
Create the Jenkins Credential ID by navigating to Dashboard -> Manage Jenkins -> Manage Credentials -> Global -> Add Credentials:
Jenkins credential
Warning
When using the GitLab integration, a webhook is automatically created. After the removal of the application, the webhook stops working but is not deleted. If necessary, it must be deleted manually.
Note
The next step is necessary if it is needed to see the status of Jenkins Merge Requests builds in the GitLab CI/CD Pipelines section.
In order to see the status of Jenkins Merge Requests builds in the GitLab CI/CD Pipelines section, configure the GitLab plugin by navigating to Manage Jenkins -> Configure System and filling in the GitLab plugin settings:
GitLab plugin configuration
Find below an example of the Merge Requests build statuses in the GitLab CI/CD Pipelines section:
GitLab pipelines statuses
This page provides instructions for configuring OIDC authorization for Harbor. This enables the use of Single Sign-On (SSO) for authorization in Harbor and allows centralized control over user access and rights through a single configuration point.
"},{"location":"operator-guide/harbor-oidc/#prerequisites","title":"Prerequisites","text":"Before the beginning, ensure your cluster meets the following requirements:
To start from, configure Keycloak by creating two Kubernetes resources. Follow the steps below to succeed:
Generate the keycloak-client-harbor-secret for Keycloak using either the commands below or using the External Secrets Operator:
keycloak_client_harbor_secret=$(openssl rand -base64 32 | head -c 32)\n
kubectl -n edp create secret generic keycloak-client-harbor-secret \\\n --from-literal=cookie-secret=${keycloak_client_harbor_secret}\n
Create the KeycloakClient custom resource by applying the HarborKeycloakClient.yaml file in the edp namespace. This custom resource will use the keycloak-client-harbor-secret
to include the harbor client. After the download, you will receive the created harbor client, and the password that is actually the value of the Kubernetes secret from the step 1:
apiVersion: v1.edp.epam.com/v1\nkind: KeycloakClient\nmetadata:\n name: harbor\nspec:\n advancedProtocolMappers: true\n clientId: harbor\n directAccess: true\n public: false\n secret: keycloak-client-harbor-secret\n defaultClientScopes:\n - profile\n - email\n - roles\n targetRealm: control-plane\n webUrl: <harbor_endpoint>\n protocolMappers:\n - name: roles\n protocol: openid-connect\n protocolMapper: oidc-usermodel-realm-role-mapper\n config:\n access.token.claim: true\n claim.name: roles\n id.token.claim: true\n userinfo.token.claim: true\n multivalued: true\n
The next stage is to configure Harbor. Proceed with following the steps below:
Log in to Harbor UI with an account that has Harbor system administrator privileges. To get the administrator password, execute the command below:
kubectl get secret harbor -n harbor -o jsonpath='{.data.HARBOR_ADMIN_PASSWORD}' | base64 --decode\n
Navigate to Administration -> Configuration -> Authentication. Configure OIDC using the parameters below:
auth_mode: oidc_auth\noidc_name: keycloak\noidc_endpoint: <keycloak_endpoint>/auth/realms/control-plane\noidc_client_id: harbor\noidc_client_secret: <keycloak-client-harbor-secret>\noidc_groups_claim: roles\noidc_admin_group: administrator\noidc_scope: openid,email,profile,roles\nverify_certificate: true\noidc_auto_onboard: true\noidc_user_claim: preferred_username\n
Harbor Authentication Configuration
As a result, users will be prompted to authenticate themselves when logging in to Harbor UI.
"},{"location":"operator-guide/harbor-oidc/#related-articles","title":"Related Articles","text":"This page provides the instructions of configuring the OIDC authorization for EDP Portal UI, thus allowing using SSO for authorization in Portal and controlling user access and rights from one configuration point.
"},{"location":"operator-guide/headlamp-oidc/#prerequisites","title":"Prerequisites","text":"Ensure the following values are set first before starting the Portal OIDC configuration:
realm_id
= openshift
client_id
= kubernetes
keycloak_client_key
= keycloak_client_secret_key (received from: Openshift realm
-> clients
-> kubernetes
-> Credentials
-> Client secret
)
group
= edp-oidc-admins
, edp-oidc-builders
, edp-oidc-deployers
, edp-oidc-developers
, edp-oidc-viewers
(Should be created manually in the realm from point 1)
Note
The values indicated above are the result of the Keycloak configuration as an OIDC identity provider. To receive them, follow the instructions on the Keycloak OIDC EKS Configuration page.
"},{"location":"operator-guide/headlamp-oidc/#configure-keycloak","title":"Configure Keycloak","text":"To proceed with the Keycloak configuration, perform the following:
Add the URL of the Headlamp to the valid_redirect_uris
variable in Keycloak:
valid_redirect_uris = [\n \"https://edp-headlamp-edp.<dns_wildcard>/*\"\n \"http://localhost:8000/*\"\n ]\n
Make sure to define the following Keycloak client values as indicated:
Keycloak client configuration
Configure the Keycloak client key in Kubernetes using the Kubernetes secrets or the External Secrets Operator:
apiVersion: v1\nkind: Secret\nmetadata:\n name: keycloak-client-headlamp-secret\n namespace: edp\ntype: Opaque\nstringData:\n clientSecret: <keycloak_client_secret_key>\n
Assign user to one or more groups in Keycloak.
Headlamp can be integrated in Kubernetes in three steps:
Update the values.yaml file by enabling OIDC:
View: values.yamledp-headlamp:\n config:\n oidc:\n enabled: true\n
Navigate to Headlamp and log in by clicking the Sign In
button:
Headlamp login page
Go to EDP
section -> Account
-> Settings
, and set up a namespace:
Headlamp namespace settings
As a result, it is possible to control access and rights from the Keycloak endpoint.
"},{"location":"operator-guide/headlamp-oidc/#related-articles","title":"Related Articles","text":"This page describes how to integrate EDP with GitLab or GitHub in case of following the Jenkins deploy scenario.
"},{"location":"operator-guide/import-strategy-jenkins/#integration-procedure","title":"Integration Procedure","text":"To start from, it is required to add both Secret with SSH key and GitServer custom resources by taking the steps below:
Generate an SSH key pair and add a public key to GitLab or GitHub account.
ssh-keygen -t ed25519 -C \"email@example.com\"\n
Generate access token for GitLab or GitHub account with read/write access to the API. Both personal and project access tokens are applicable.
GitHubGitLabTo create access token in GitHub, follow the steps below:
Repo permission
Note
The access below is required for the GitHub Pull Request Builder plugin to get Pull Request commits, their status, and author info.
Admin permission User permission
Warning
Make sure to save a new personal access token because it won`t be displayed later.
To create access token in GitLab, follow the steps below:
Personal access tokens
Note
Make sure to save the access token as there will not be any ability to access it once again.
In case you want to create a project access token instead of a personal one, the GitLab Jenkins plugin will be able to accept payloads from webhooks for the project only:
Project access tokens
Create secret in the edp
namespace for the Git account with the id_rsa, username, and token fields. We recommend using EDP Portal to implement this:
Open EDP Portal URL. Use the Sign-In option:
Logging screen
In the top right corner, enter the Cluster settings
and set the Default namespace
. The Allowed namespaces
field is optional. All the resources created via EDP Portal are created in the Default namespace
whereas Allowed namespaces
means the namespaces you are allowed to access in this cluster:
Cluster settings
Log into EDP Portal UI, select EDP
-> Git Servers
-> +
to see the Create Git Server
menu:
Git Servers overview
Choose your Git provider, insert Host, Access token, Private SSH key. Adjust SSH port, User and HTTPS port if needed and click Apply
:
Note
Do not forget to press enter at the very end of the private key to have the last row empty.
Create Git Servers menu
After performing the steps above, two Kubernetes custom resources will be created in the default namespace: secret and GitServer. EDP Portal appends random symbols to both the secret and the GitServer to provide names with uniqueness. Also, the attempt to connect to your actual Git server will be performed. If the connection with the server is established, the Git server status should be green:
Git server status
Note
The value of the nameSshKeySecret property is the name of the Secret that is indicated in the first step above.
Create the JenkinsServiceAccount
custom resource with the credentials field that corresponds to the nameSshKeySecret property above:
apiVersion: v2.edp.epam.com/v1\nkind: JenkinsServiceAccount\nmetadata:\n name: gitlab # It can also be github.\n namespace: edp\nspec:\n credentials: <nameSshKeySecret>\n ownerName: ''\n type: ssh\n
Double-check that the new SSH credentials called gitlab
/github
are created in Jenkins using the SSH key. Navigate to Jenkins
-> Manage Jenkins
-> Manage Credentials
-> (global)
:
Jenkins credentials
Create a new job provisioner by following the instructions for GitHub or GitLab. The job provisioner will create a job suite for an application added to EDP. The job provisioner will also create webhooks for the project in GitLab using a GitLab token.
Configure GitHub or GitLab plugins in Jenkins.
This page describes how to integrate EDP with GitLab or GitHub Version Control System.
"},{"location":"operator-guide/import-strategy-tekton/#integration-procedure","title":"Integration Procedure","text":"To start from, it is required to add both Secret with SSH key, API token, and GitServer resources by taking the steps below.
Generate an SSH key pair and add a public key to GitLab or GitHub account.
ssh-keygen -t ed25519 -C \"email@example.com\"\n
Generate access token for GitLab or GitHub account with read/write access to the API. Both personal and project access tokens are applicable.
GitHubGitLabTo create access token in GitHub, follow the steps below:
Repo permission
Note
The access below is required for the GitHub Pull Request Builder plugin to get Pull Request commits, their status, and author info.
Admin:repo permission Admin:org permission User permission
Warning
Make sure to save a new personal access token because it won`t be displayed later.
To create access token in GitLab, follow the steps below:
Personal access tokens
Note
Make sure to save the access token as there will not be any ability to access it once again.
In case you want to create a project access token instead of a personal one, take the following steps:
Project access tokens
Create a secret in the edp
namespace for the Git account with the id_rsa, username, and token fields. Take the following template as an example (use ci-gitlab instead of ci-github for GitLab):
Navigate to EDP Portal
-> EDP
-> Configuration
-> Git Servers
. Fill in the required fields:
Project access tokens
Create a manifest file called secret.yaml with the following content filled in:
kubectl apply -f - <<EOF\n apiVersion: v1\n kind: Secret\n metadata:\n name: ci-github\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: repository\n type: Opaque\n stringData:\n id_rsa: <id_rsa_data>\n username: git\n token: <your_github_access_token>\nEOF\n
As a result, you will be able to create codebases using an integrated Version Control System.
"},{"location":"operator-guide/import-strategy-tekton/#related-articles","title":"Related Articles","text":"Enabling the VCS Import strategy is a prerequisite to integrate EDP with GitLab or GitHub.
"},{"location":"operator-guide/import-strategy/#general-steps","title":"General Steps","text":"In order to use the Import strategy, it is required to add both Secret with SSH key and GitServer custom resources by taking the steps below.
Generate an SSH key pair and add a public key to GitLab or GitHub account.
ssh-keygen -t ed25519 -C \"email@example.com\"\n
Generate access token for GitLab or GitHub account with read/write access to the API. Both personal and project access tokens are applicable.
To create access token in GitHub, follow the steps below:
Repo permission
Note
The access below is required for the GitHub Pull Request Builder plugin to get Pull Request commits, their status, and author info.
Admin permission User permission
Warning
Make sure to save a new personal access token because it won`t be displayed later.
To create access token in GitLab, follow the steps below:
Personal access tokens
Note
Make sure to save the access token as there will not be any ability to access it once again.
In case you want to create a project access token instead of a personal one, the GitLab Jenkins plugin will be able to accept payloads from webhooks for the project only:
Project access tokens
The further steps depend on the CI tool used.
Tekton CI toolJenkins CI toolCreate a secret in the edp-project
namespace for the Git account with the id_rsa, username, and token fields. Take the following template as an example (use github instead of gitlab for GitHub):
kubectl create secret generic gitlab -n edp \\\n--from-file=id_rsa=id_rsa \\\n--from-literal=username=git \\\n--from-literal=token=your_gitlab_access_token\n
After completing the steps above, you can get back and continue installing EDP.
Create secret in the edp
namespace for the Git account with the id_rsa, username, and token fields. We recommend using EDP Portal to implement this:
Open EDP Portal URL. Use the Sign-In option:
Logging screen
In the top right corner, enter the Cluster settings
and set the Default namespace
. The Allowed namespaces
field is optional. All the resources created via EDP Portal are created in the Default namespace
whereas Allowed namespaces
means the namespaces you are allowed to access in this cluster:
Cluster settings
Log into EDP Portal UI, select EDP
-> Git Servers
-> +
to see the Create Git Server
menu:
Git Servers overview
Choose your Git provider, insert Host, Access token, Private SSH key. Adjust SSH port, User and HTTPS port if needed and click Apply
:
Note
Do not forget to press enter at the very end of the private key to have the last row empty.
Create Git Servers menu
When everything is done, two custom resources will be created in the default namespace: secret and Git server. EDP Portal appends random symbols to both the secret and the server to provide names with uniqueness. Also, the attempt to connect to your Git server will be performed. If everything is correct, the Git server status should be green:
Git server status
Note
The value of the nameSshKeySecret property is the name of the Secret that is indicated in the first step above.
Create the JenkinsServiceAccount
custom resource with the credentials field that corresponds to the nameSshKeySecret property above:
apiVersion: v2.edp.epam.com/v1\nkind: JenkinsServiceAccount\nmetadata:\n name: gitlab # It can also be github.\n namespace: edp\nspec:\n credentials: <nameSshKeySecret>\n ownerName: ''\n type: ssh\n
Double-check that the new SSH credentials called gitlab
/github
are created in Jenkins using the SSH key. Navigate to Jenkins
-> Manage Jenkins
-> Manage Credentials
-> (global)
:
Jenkins credentials
The next step is to create a new job provisioner by following the instructions for GitHub or GitLab. The job provisioner will create a job suite for an application added to EDP. It will also create webhooks for the project in GitLab using a GitLab token.
The next step is to integrate Jenkins with GitHub or GitLab by setting their plugins.
Inspect the prerequisites and the main steps to perform for enabling Argo CD in EDP.
"},{"location":"operator-guide/install-argocd/#prerequisites","title":"Prerequisites","text":"The following tools must be installed:
Argo CD enablement for EDP consists of two major steps:
Info
It is also possible to install Argo CD using the Helmfile. For details, please refer to the Install via Helmfile page.
"},{"location":"operator-guide/install-argocd/#integrate-with-edp","title":"Integrate With EDP","text":"To enable Argo CD integration, ensure that the argocd.enabled
flag values.yaml is set to true
Argo CD can be installed in several ways, please follow the official documentation for more details.
Follow the steps below to install Argo CD using Helm:
For the OpenShift users:
When using the OpenShift platform, apply the SecurityContextConstraints
resource. Change the namespace in the users
section if required.
View: argocd-scc.yaml
allowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\napiVersion: security.openshift.io/v1\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 99\n max: 65543\ngroups: []\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: argo-redis-ha\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n- KILL\n- MKNOD\n- SETUID\n- SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nseccompProfiles:\n - '*'\nusers:\n- system:serviceaccount:argocd:argo-redis-ha\n- system:serviceaccount:argocd:argo-redis-ha-haproxy\n- system:serviceaccount:argocd:argocd-notifications-controller\n- system:serviceaccount:argocd:argo-argocd-repo-server\n- system:serviceaccount:argocd:argocd-server\nvolumes:\n- configMap\n- downwardAPI\n- emptyDir\n- persistentVolumeClaim\n- projected\n- secret\n
Check out the values.yaml file sample of the Argo CD customization, which is based on the HA mode without autoscaling
:
redis-ha:\n enabled: true\n\ncontroller:\n enableStatefulSet: true\n\nserver:\n replicas: 2\n extraArgs:\n - \"--insecure\"\n env:\n - name: ARGOCD_API_SERVER_REPLICAS\n value: '2'\n ingress:\n enabled: true\n hosts:\n - \"argocd.<Values.global.dnsWildCard>\"\n config:\n # required when SSO is enabled\n url: \"https://argocd.<.Values.global.dnsWildCard>\"\n application.instanceLabelKey: argocd.argoproj.io/instance-edp\n oidc.config: |\n name: Keycloak\n issuer: https://<.Values.global.keycloakEndpoint>/auth/realms/edp-main\n clientID: argocd\n clientSecret: $oidc.keycloak.clientSecret\n requestedScopes:\n - openid\n - profile\n - email\n - groups\n rbacConfig:\n # users may be still be able to login,\n # but will see no apps, projects, etc...\n policy.default: ''\n scopes: '[groups]'\n policy.csv: |\n # default global admins\n g, ArgoCDAdmins, role:admin\n\nconfigs:\n params:\n application.namespaces: edp\n\nrepoServer:\n replicas: 2\n\n# we use Keycloak so no DEX is required\ndex:\n enabled: false\n\n# Disabled for multitenancy env with single instance deployment\napplicationSet:\n enabled: false\n
View: openshift-values.yaml redis-ha:\n enabled: true\n\ncontroller:\n enableStatefulSet: true\n\nserver:\n replicas: 2\n extraArgs:\n - \"--insecure\"\n env:\n - name: ARGOCD_API_SERVER_REPLICAS\n value: '2'\n route:\n enabled: true\n hostname: \"argocd.<.Values.global.dnsWildCard>\"\n termination_type: edge\n termination_policy: Redirect\n config:\n # required when SSO is enabled\n url: \"https://argocd.<.Values.global.dnsWildCard>\"\n application.instanceLabelKey: argocd.argoproj.io/instance-edp\n oidc.config: |\n name: Keycloak\n issuer: https://<.Values.global.keycloakEndpoint>/auth/realms/edp-main\n clientID: argocd\n clientSecret: $oidc.keycloak.clientSecret\n requestedScopes:\n - openid\n - profile\n - email\n - groups\n rbacConfig:\n # users may be still be able to login,\n # but will see no apps, projects, etc...\n policy.default: ''\n scopes: '[groups]'\n policy.csv: |\n # default global admins\n g, ArgoCDAdmins, role:admin\n\nconfigs:\n params:\n application.namespaces: edp\n\nrepoServer:\n replicas: 2\n\n# we use Keycloak so no DEX is required\ndex:\n enabled: false\n\n# Disabled for multitenancy env with single instance deployment\napplicationSet:\n enabled: false\n
Populate Argo CD values with the values from the EDP values.yaml:
edp
namespace.Run the installation:
kubectl create ns argocd\nhelm repo add argo https://argoproj.github.io/argo-helm\nhelm install argo --version 5.33.1 argo/argo-cd -f values.yaml -n argocd\n
Update the argocd-secret
secret in the argocd
namespace by providing the correct Keycloak client secret (oidc.keycloak.clientSecret
) with the value from the keycloak-client-argocd-secret
secret in the EDP namespace. Then restart the deployment:
ARGOCD_CLIENT=$(kubectl -n edp get secret keycloak-client-argocd-secret -o jsonpath='{.data.clientSecret}')\nkubectl -n argocd patch secret argocd-secret -p=\"{\\\"data\\\":{\\\"oidc.keycloak.clientSecret\\\": \\\"${ARGOCD_CLIENT}\\\"}}\" -v=1\nkubectl -n argocd rollout restart deployment argo-argocd-server\n
Inspect the main steps to perform for installing DefectDojo via Helm Chart.
Info
It is also possible to install DefectDojo using the EDP addons approach. For details, please refer to the EDP addons approach.
"},{"location":"operator-guide/install-defectdojo/#prerequisites","title":"Prerequisites","text":"Info
Please refer to the DefectDojo Helm Chart and Deploy DefectDojo into the Kubernetes cluster sections for details.
To install DefectDojo, follow the steps below:
Check that a security namespace is created. If not, run the following command to create it:
kubectl create namespace defectdojo\n
For the OpenShift users:
When using the OpenShift platform, install the SecurityContextConstraints
resource. In case of using a custom namespace for defectdojo
, change the namespace in the users
section.
View: defectdojo-scc.yaml
allowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\napiVersion: security.openshift.io/v1\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 999\n max: 65543\ngroups: []\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: defectdojo\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n- KILL\n- MKNOD\n- SETUID\n- SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n- system:serviceaccount:defectdojo:defectdojo\n- system:serviceaccount:defectdojo:defectdojo-rabbitmq\n- system:serviceaccount:defectdojo:default\nvolumes:\n- configMap\n- downwardAPI\n- emptyDir\n- persistentVolumeClaim\n- projected\n- secret\n
Add a chart repository:
helm repo add defectdojo 'https://raw.githubusercontent.com/DefectDojo/django-DefectDojo/helm-charts'\nhelm repo update\n
Create PostgreSQL admin secret:
kubectl -n defectdojo create secret generic defectdojo-postgresql-specific \\\n--from-literal=postgresql-password=<postgresql_password> \\\n--from-literal=postgresql-postgres-password=<postgresql_postgres_password>\n
Note
The postgresql_password
and postgresql_postgres_password
passwords must be 16 characters long.
Create Rabbitmq admin secret:
kubectl -n defectdojo create secret generic defectdojo-rabbitmq-specific \\\n--from-literal=rabbitmq-password=<rabbitmq_password> \\\n--from-literal=rabbitmq-erlang-cookie=<rabbitmq_erlang_cookie>\n
Note
The rabbitmq_password
password must be 10 characters long.
The rabbitmq_erlang_cookie
password must be 32 characters long.
Create DefectDojo admin secret:
kubectl -n defectdojo create secret generic defectdojo \\\n--from-literal=DD_ADMIN_PASSWORD=<dd_admin_password> \\\n--from-literal=DD_SECRET_KEY=<dd_secret_key> \\\n--from-literal=DD_CREDENTIAL_AES_256_KEY=<dd_credential_aes_256_key> \\\n--from-literal=METRICS_HTTP_AUTH_PASSWORD=<metric_http_auth_password>\n
Note
The dd_admin_password
password must be 22 characters long.
The dd_secret_key
password must be 128 characters long.
The dd_credential_aes_256_key
password must be 128 characters long.
The metric_http_auth_password
password must be 32 characters long.
Install DefectDojo v.2.22.4 using defectdojo/defectdojo Helm chart v.1.6.69:
helm upgrade --install \\\ndefectdojo \\\n--version 1.6.69 \\\ndefectdojo/defectdojo \\\n--namespace defectdojo \\\n--values values.yaml\n
Check out the values.yaml file sample of the DefectDojo customization:
View: values.yamltag: 2.22.4\nfullnameOverride: defectdojo\nhost: defectdojo.<ROOT_DOMAIN>\nsite_url: https://defectdojo.<ROOT_DOMAIN>\nalternativeHosts:\n - defectdojo-django.defectdojo\n\ninitializer:\n # should be false after initial installation was performed\n run: true\ndjango:\n ingress:\n enabled: true # change to 'false' for OpenShift\n activateTLS: false\n uwsgi:\n livenessProbe:\n # Enable liveness checks on uwsgi container. Those values are use on nginx readiness checks as well.\n # default value is 120, so in our case 20 is just fine\n initialDelaySeconds: 20\n
For the OpenShift platform, install a Route:
View: defectdojo-route.yamlkind: Route\napiVersion: route.openshift.io/v1\nmetadata:\n name: defectdojo\n namespace: defectdojo\nspec:\n host: defectdojo.<ROOT_DOMAIN>\n path: /\n tls:\n insecureEdgeTerminationPolicy: Redirect\n termination: edge\n to:\n kind: Service\n name: defectdojo-django\n port:\n targetPort: http\n wildcardPolicy: None\n
To prepare DefectDojo for integration with EDP, follow the steps below:
Create ci user in DefectDojo UI:
echo \"DefectDojo admin password: $(kubectl \\\nget secret defectdojo \\\n--namespace=defectdojo \\\n--output jsonpath='{.data.DD_ADMIN_PASSWORD}' \\\n| base64 --decode)\"\n
Get a token of the DefectDojo user:
Provision the secret using EDP Portal
, Manifest
or with the externalSecrets
operator:
Go to EDP Portal -> EDP -> Configuration -> DefectDojo. Update or fill in the URL and Token and click the Save button.
DefectDojo update manual secret
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-defectdojo\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: defectdojo\n app.edp.epam.com/integration-secret: \"true\"\nstringData:\n url: https://defectdojo.example.com\n token: <token>\n
Store defectdojo URL and Token in AWS Parameter Store with following format:
\"ci-defectdojo\":\n{\n \"url\": \"https://defectdojo.example.com\",\n \"token\": \"XXXXXXXXXXXX\"\n}\n
Go to EDP Portal -> EDP -> Configuration -> DefectDojo and see the Managed by External Secret
message. More details about the External Secrets Operator integration procedure can be found in the External Secrets Operator Integration page.
After following the instructions provided, you should be able to integrate your DefectDojo with the EPAM Delivery Platform using one of the few available scenarios.
"},{"location":"operator-guide/install-defectdojo/#related-articles","title":"Related Articles","text":"Inspect the main steps to install EPAM Delivery Platform. Please check the Prerequisites Overview page before starting the installation. Also to authenticate each of the release artifacts, please refer to the Verification of EDP Artifacts guide. There are two recommended ways to deploy EPAM Delivery Platform:
Note
The installation process below is given for a Kubernetes cluster. The steps that differ for an OpenShift cluster are indicated in the notes.
Disclaimer
EDP is aligned with industry standards for storing and managing sensitive data, ensuring optimal security. However, the use of custom solutions introduces uncertainties, thus the responsibility for the safety of your data is totally covered by platform administrator.
EDP manages secrets via External Secret Operator to integrate with a multitude of utilities. For insights into the secrets in use and their utilization, refer to the provided External Secrets Operator Integration.
Create an edp namespace or a Kiosk space depending on whether Kiosk is used or not.
Without Kiosk, create a namespace:
kubectl create namespace edp\n
Note
For an OpenShift cluster, run the oc
command instead of the kubectl
one.
With Kiosk, create a relevant space:
apiVersion: tenancy.kiosk.sh/v1alpha1\nkind: Space\nmetadata:\n name: edp\nspec:\n account: edp-admin\n
Note
Kiosk is mandatory for EDP v.2.8.x. It is not implemented for the previous versions, and is optional for EDP since v.2.9.x.
(Optional) Deploy and configure Keycloak to enable Single Sign-On approach. To see the details on how to configure Keycloak correctly, please refer to the Install Keycloak page.
Add the Helm charts repository:
helm repo add epamedp https://epam.github.io/edp-helm-charts/stable\n
Choose the required Helm chart version:
helm search repo epamedp/edp-install\nNAME CHART VERSION APP VERSION DESCRIPTION\nepamedp/edp-install 3.5.3 3.5.3 A Helm chart for EDP Install\n
Note
It is highly recommended to use the latest released version.
EDP can be integrated with the following version control systems:
This integration implies in what system the development of the application will be or is already being carried out. The global.gitProvider
flag in the edp-install controls this integration:
...\nglobal:\n gitProvider: gerrit\n...\n
values.yaml...\nglobal:\n gitProvider: github\n...\n
values.yaml...\nglobal:\n gitProvider: gitlab\n...\n
Internal Gerrit server can be deployed as a result of EDP deployment. For more details on how to integrate EDP with GitLab or GitHub instead of Gerrit, please refer to the Integrate GitHub/GitLab in Tekton page.
(Optional) Integrate platform with SonarQube:
...\nsonar-operator:\n enabled: true\n...\n
(Optional) Integrate platform with Nexus:
...\nnexus-operator:\n enabled: true\n...\n
(Optional) Configure Container Registry for image storage.
Since EDP v3.4.0, we enabled users to configure Harbor registry instead of AWS ECR and Openshift-registry. We recommend installing Harbor using our edp-cluster-add-ons although you can install it any other way. To integrate EDP with Harbor, see Harbor integration page.
To enable Harbor as a registry storage, use the values below:
global:\n dockerRegistry:\n type: \"harbor\"\n url: \"harbor.example.com\"\n
Check the parameters in the EDP installation chart. For details, please refer to the values.yaml file.
Install EDP in the edp namespace with the Helm tool:
helm install edp epamedp/edp-install --wait --timeout=900s \\\n--version <edp_version> \\\n--values values.yaml \\\n--namespace edp\n
See the details on the parameters below:
Example values.yaml fileglobal:\n # -- platform type that can be either \"kubernetes\" or \"openshift\"\n platform: \"kubernetes\"\n # DNS wildcard for routing in the Kubernetes cluster;\n dnsWildCard: \"example.com\"\n # -- Administrators of your tenant\n # -- Can be gerrit, github or gitlab. By default: github\n gitProvider: github\n dockerRegistry:\n # -- Docker Registry endpoint\n url: \"<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com\"\n type: \"ecr\"\n\nsso:\n enabled: false\n # Keycloak address with which the platform will be integrated\n keycloakUrl: \"https://keycloak.example.com\"\n admins:\n - \"stub_user_one@example.com\"\n developers:\n - \"stub_user_one@example.com\"\n - \"stub_user_two@example.com\"\n\n# AWS Region, e.g. \"eu-central-1\"\nawsRegion:\n\nargocd:\n # -- Enable ArgoCD integration\n enabled: true\n # -- ArgoCD URL in format schema://URI\n # -- By default, https://argocd.{{ .Values.global.dnsWildCard }}\n url: \"\"\n\nedp-tekton:\n # Tekton Kaniko configuration section\n kaniko:\n # -- AWS IAM role to be used for kaniko pod service account (IRSA). Format: arn:aws:iam::<AWS_ACCOUNT_ID>:role/<AWS_IAM_ROLE_NAME>\n roleArn:\n\nedp-headlamp:\n config:\n oidc:\n enabled: false\n
Note
Set global.platform=openshift
while deploying EDP in OpenShift.
Info
The full installation with integration between tools will take at least 10 minutes.
To check if the installation is successful, run the command below:
helm status edp -n edp\n
You can also check ingress endpoints to get EDP Portal endpoint to enter EDP Portal UI:
kubectl describe ingress -n edp\n
Once EDP is successfully installed, you can navigate to our Use Cases to try out EDP functionality.
Inspect the prerequisites and the main steps to perform for enabling External Secrets Operator in EDP.
"},{"location":"operator-guide/install-external-secrets-operator/#prerequisites","title":"Prerequisites","text":"To install External Secrets Operator with Helm, run the following commands:
helm repo add external-secrets https://charts.external-secrets.io\n\nhelm install external-secrets \\\n external-secrets/external-secrets \\\n --version 0.8.3 \\\n -n external-secrets \\\n --create-namespace\n
Info
It is also possible to install External Secrets Operator using the Helmfile or Operator Lifecycle Manager (OLM).
"},{"location":"operator-guide/install-external-secrets-operator/#related-articles","title":"Related Articles","text":"EPAM Delivery Platform uses Harbor as a storage for application images that are created when building applications.
Inspect the prerequisites and the main steps to perform for enabling Harbor in EDP.
"},{"location":"operator-guide/install-harbor/#prerequisites","title":"Prerequisites","text":"To install Harbor with Helm, follow the steps below:
Create a namespace for Harbor:
kubectl create namespace harbor\n
Create a secret for administrator user and registry:
ManuallyExternal Secret Operatorkubectl create secret generic harbor \\\n --from-literal=HARBOR_ADMIN_PASSWORD=<secret> \\\n --from-literal=REGISTRY_HTPASSWD=<secret> \\\n --from-literal=REGISTRY_PASSWD=<secret> \\\n --from-literal=secretKey=<secret> \\\n --namespace harbor\n
apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: harbor\n namespace: harbor\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: aws-parameterstore\ndata:\n- secretKey: HARBOR_ADMIN_PASSWORD\n remoteRef:\n conversionStrategy: Default\n decodingStrategy: None\n key: /control-plane/deploy-secrets\n property: harbor.HARBOR_ADMIN_PASSWORD\n- secretKey: secretKey\n remoteRef:\n conversionStrategy: Default\n decodingStrategy: None\n key: /control-plane/deploy-secrets\n property: harbor.secretKey\n- secretKey: REGISTRY_HTPASSWD\n remoteRef:\n conversionStrategy: Default\n decodingStrategy: None\n key: /control-plane/deploy-secrets\n property: harbor.REGISTRY_HTPASSWD\n- secretKey: REGISTRY_PASSWD\n remoteRef:\n conversionStrategy: Default\n decodingStrategy: None\n key: /control-plane/deploy-secrets\n property: harbor.REGISTRY_PASSWD\n
Note
The HARBOR_ADMIN_PASSWORD
is the initial password of Harbor admin. The secretKey
is the secret key that is used for encryption. Must be 16 characters long. The REGISTRY_PASSWD
is Harbor registry password. The REGISTRY_HTPASSWD
is login and password in htpasswd string format. This value is the string in the password file generated by the htpasswd
command where the username is harbor_registry_user
and the encryption type is bcrypt
. See the example below:
htpasswd -bBc passwordfile harbor_registry_user harbor_registry_password\n
The username must be harbor_registry_user
. The password must be the value from REGISTRY_PASSWD
. Add the Helm Harbor Charts for the local client.
helm repo add harbor https://helm.goharbor.io\n
Check the parameters in the Harbor installation chart. For details, please refer to the values.yaml file.
Install Harbor in the \u2039harbor\u203a namespace with the Helm tool.
helm install harbor harbor/harbor\n --version 1.12.2 \\\n --namespace harbor \\\n --values values.yaml\n
See the details on the parameters below:
Example values.yaml file
# we use Harbor secret to consolidate all the Harbor secrets\nexistingSecretAdminPassword: harbor\nexistingSecretAdminPasswordKey: HARBOR_ADMIN_PASSWORD\nexistingSecretSecretKey: harbor\n\ncore:\n # The XSRF key. Will be generated automatically if it isn't specified\n xsrfKey: \"\"\njobservice:\n # Secret is used when job service communicates with other components.\n # If a secret key is not specified, Helm will generate one.\n # Must be a string of 16 chars.\n secret: \"\"\nregistry:\n # Secret is used to secure the upload state from client\n # and registry storage backend.\n # If a secret key is not specified, Helm will generate one.\n # Must be a string of 16 chars.\n secret: \"\"\n credentials:\n username: harbor_registry_user\n existingSecret: harbor\nfullnameOverride: harbor\n# If Harbor is deployed behind the proxy, set it as the URL of proxy\nexternalURL: https://core.harbor.domain\nipFamily:\n ipv6:\n enabled: false\nexpose:\n tls:\n enabled: false\n ingress:\n hosts:\n core: core.harbor.domain\n notary: notary.harbor.domain\nupdateStrategy:\n type: Recreate\npersistence:\n persistentVolumeClaim:\n registry:\n size: 30Gi\n jobservice:\n jobLog:\n size: 1Gi\n database:\n size: 2Gi\n redis:\n size: 1Gi\n trivy:\n size: 5Gi\ndatabase:\n internal:\n # The initial superuser password for internal database\n password: \"changeit\"\n
To check if the installation is successful, run the command below:
helm status <harbor-release> -n harbor\n
You can also check ingress endpoints to get Harbor endpoint to enter Harbor UI: kubectl describe ingress <harbor_ingress> -n harbor\n
Inspect the prerequisites and the main steps to perform for installing Install NGINX Ingress Controller on Kubernetes.
"},{"location":"operator-guide/install-ingress-nginx/#prerequisites","title":"Prerequisites","text":"Info
It is also possible to install NGINX Ingress Controller using the Helmfile. For details, please refer to the Install via Helmfile page.
To install the ingress-nginx chart, follow the steps below:
Create an ingress-nginx namespace:
kubectl create namespace ingress-nginx\n
Add a chart repository:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx\nhelm repo update\n
Install the ingress-nginx chart:
helm install ingress ingress-nginx/ingress-nginx \\\n--version 4.7.0 \\\n--values values.yaml \\\n--namespace ingress-nginx\n
Check out the values.yaml file sample of the ingress-nginx chart customization:
controller:\n addHeaders:\n X-Content-Type-Options: nosniff\n X-Frame-Options: SAMEORIGIN\n resources:\n limits:\n memory: \"256Mi\"\n requests:\n cpu: \"50m\"\n memory: \"128M\"\n config:\n ssl-redirect: 'true'\n client-header-buffer-size: '64k'\n http2-max-field-size: '64k'\n http2-max-header-size: '64k'\n large-client-header-buffers: '4 64k'\n upstream-keepalive-timeout: '120'\n keep-alive: '10'\n use-forwarded-headers: 'true'\n proxy-real-ip-cidr: '172.32.0.0/16'\n proxy-buffer-size: '8k'\n\n # To watch Ingress objects without the ingressClassName field set parameter value to true.\n # https://kubernetes.github.io/ingress-nginx/#i-have-only-one-ingress-controller-in-my-cluster-what-should-i-do\n watchIngressWithoutClass: true\n\n service:\n type: NodePort\n nodePorts:\n http: 32080\n https: 32443\n updateStrategy:\n rollingUpdate:\n maxUnavailable: 1\n type: RollingUpdate\n metrics:\n enabled: true\ndefaultBackend:\n enabled: true\nserviceAccount:\n create: true\n name: nginx-ingress-service-account\n
Warning
Align value controller.config.proxy-real-ip-cidr with AWS VPC CIDR.
"},{"location":"operator-guide/install-keycloak/","title":"Install Keycloak","text":""},{"location":"operator-guide/install-keycloak/#install-keycloak","title":"Install Keycloak","text":"Inspect the prerequisites and the main steps to perform for installing Keycloak.
Info
The installation process below is given for a Kubernetes cluster. The steps that differ for an OpenShift cluster are indicated in the warnings blocks.
"},{"location":"operator-guide/install-keycloak/#prerequisites","title":"Prerequisites","text":"Info
EDP team is using a Keycloakx helm chart from the codecentric repository, but other repositories can be used as well (e.g. Bitnami). Before installing Keycloak, it is necessary to install a PostgreSQL database.
Info
It is also possible to install Keycloak using the Helmfile. For details, please refer to the Install via Helmfile page.
"},{"location":"operator-guide/install-keycloak/#postgresql-installation","title":"PostgreSQL Installation","text":"To install PostgreSQL, follow the steps below:
Check that a security namespace is created. If not, run the following command to create it:
kubectl create namespace security\n
Warning
On the OpenShift platform, apply the SecurityContextConstraints
resource. Change the namespace in the users
section if required.
allowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\napiVersion: security.openshift.io/v1\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 999\n max: 65543\ngroups: []\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: keycloak\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n - KILL\n - MKNOD\n - SETUID\n - SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n - system:serviceaccount:security:keycloakx\nvolumes:\n - configMap\n - downwardAPI\n - emptyDir\n - persistentVolumeClaim\n - projected\n - secret\n
View: postgresql-keycloak-scc.yaml allowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\napiVersion: security.openshift.io/v1\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 999\n max: 65543\ngroups: []\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: postgresql-keycloak\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n- KILL\n- MKNOD\n- SETUID\n- SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n- system:serviceaccount:security:default\nvolumes:\n- configMap\n- downwardAPI\n- emptyDir\n- persistentVolumeClaim\n- projected\n- secret\n
Create PostgreSQL admin secret:
kubectl -n security create secret generic keycloak-postgresql \\\n--from-literal=password=<postgresql_password> \\\n--from-literal=postgres-password=<postgresql_postgres_password>\n
Add a helm chart repository:
helm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n
Install PostgreSQL v15.2.0 using bitnami/postgresql Helm chart v12.1.15:
Info
The PostgreSQL can be deployed in production ready mode. For example, it may include multiple replicas, persistent storage, autoscaling, and monitoring. For details, please refer to the official Chart documentation.
helm install postgresql bitnami/postgresql \\\n--version 12.1.15 \\\n--values values.yaml \\\n--namespace security\n
Check out the values.yaml file sample of the PostgreSQL customization:
View: values.yaml# PostgreSQL read only replica parameters\nreadReplicas:\n # Number of PostgreSQL read only replicas\n replicaCount: 1\n\nimage:\n tag: 15.2.0-debian-11-r0\n\nglobal:\n postgresql:\n auth:\n username: admin\n existingSecret: keycloak-postgresql\n database: keycloak\n\nprimary:\n persistence:\n enabled: true\n size: 3Gi\n
To install Keycloak, follow the steps below:
Use security
namespace from the PostgreSQL installation.
Add a chart repository:
helm repo add codecentric https://codecentric.github.io/helm-charts\nhelm repo update\n
Create Keycloak admin secret:
kubectl -n security create secret generic keycloak-admin-creds \\\n--from-literal=username=<keycloak_admin_username> \\\n--from-literal=password=<keycloak_admin_password>\n
Install Keycloak 20.0.3 using codecentric/keycloakx Helm chart:
Info
Keycloak can be deployed in production ready mode. For example, it may include multiple replicas, persistent storage, autoscaling, and monitoring. For details, please refer to the official Chart documentation.
helm install keycloakx codecentric/keycloakx \\\n--version 2.2.1 \\\n--values values.yaml \\\n--namespace security\n
Check out the values.yaml file sample of the Keycloak customization:
View: values.yamlreplicas: 1\n\n# Deploy the latest version\nimage:\n tag: \"20.0.3\"\n\n# start: create OpenShift realm which is required by EDP\nextraInitContainers: |\n - name: realm-provider\n image: busybox\n imagePullPolicy: IfNotPresent\n command:\n - sh\n args:\n - -c\n - |\n echo '{\"realm\": \"openshift\",\"enabled\": true}' > /opt/keycloak/data/import/openshift.json\n volumeMounts:\n - name: realm\n mountPath: /opt/keycloak/data/import\n\n# The following parameter is unrecommended to expose. Exposed health checks lead to an unnecessary attack vector.\nhealth:\n enabled: false\n# The following parameter is unrecommended to expose. Exposed metrics lead to an unnecessary attack vector.\nmetrics:\n enabled: false\n\nextraVolumeMounts: |\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumes: |\n - name: realm\n emptyDir: {}\n\ncommand:\n - \"/opt/keycloak/bin/kc.sh\"\n - \"--verbose\"\n - \"start\"\n - \"--auto-build\"\n - \"--http-enabled=true\"\n - \"--http-port=8080\"\n - \"--hostname-strict=false\"\n - \"--hostname-strict-https=false\"\n - \"--spi-events-listener-jboss-logging-success-level=info\"\n - \"--spi-events-listener-jboss-logging-error-level=warn\"\n - \"--import-realm\"\n\nextraEnv: |\n - name: KC_PROXY\n value: \"passthrough\"\n - name: KEYCLOAK_ADMIN\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: username\n - name: KEYCLOAK_ADMIN_PASSWORD\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: password\n - name: JAVA_OPTS_APPEND\n value: >-\n -XX:+UseContainerSupport\n -XX:MaxRAMPercentage=50.0\n -Djava.awt.headless=true\n -Djgroups.dns.query={{ include \"keycloak.fullname\" . }}-headless\n\n# This block should be uncommented if you install Keycloak on Kubernetes\ningress:\n enabled: true\n annotations:\n kubernetes.io/ingress.class: nginx\n ingress.kubernetes.io/affinity: cookie\n # The following parameter is unrecommended to expose. Admin paths lead to an unnecessary attack vector.\n console:\n enabled: false\n rules:\n - host: keycloak.<ROOT_DOMAIN>\n paths:\n - path: '{{ tpl .Values.http.relativePath $ | trimSuffix \"/\" }}/'\n pathType: Prefix\n\n# This block should be uncommented if you set Keycloak to OpenShift and change the host field\n# route:\n# enabled: false\n# # Path for the Route\n# path: '/'\n# # Host name for the Route\n# host: \"keycloak.<ROOT_DOMAIN>\"\n# # TLS configuration\n# tls:\n# enabled: true\n\nresources:\n limits:\n memory: \"2048Mi\"\n requests:\n cpu: \"50m\"\n memory: \"512Mi\"\n\n# Check database readiness at startup\ndbchecker:\n enabled: true\n\ndatabase:\n vendor: postgres\n existingSecret: keycloak-postgresql\n hostname: postgresql\n port: 5432\n username: admin\n database: keycloak\n
To prepare Keycloak for integration with EDP, follow the steps below:
Ensure that the openshift
realm is created.
Create the edp_<EDP_PROJECT>
user and set the password in the Master
realm.
Note
This user should be used by EDP to access Keycloak. Please refer to the Install EDP and Install EDP via Helmfile sections for details.
In the Role Mapping
tab, assign the proper roles to the user:
Realm Roles:
Client Roles openshift-realm
:
Role mappings
Kiosk is a multi-tenancy extension for managing tenants and namespaces in a shared Kubernetes cluster. Within EDP, Kiosk is used to separate resources and enables the following options (see more details):
Inspect the main steps to set up Kiosk for the proceeding EDP installation.
Note
Kiosk deploy is mandatory for EDP v.2.8. In earlier versions, Kiosk is not implemented. Since EDP v.2.9.0, integration with Kiosk is an optional feature. You may not want to use it, so just skip those steps and disable in Helm parameters during EDP deploy.
# global.kioskEnabled: <true/false>\n
"},{"location":"operator-guide/install-kiosk/#prerequisites","title":"Prerequisites","text":" # Install kiosk with helm v3\n\n helm repo add kiosk https://charts.devspace.sh/\n kubectl create namespace kiosk\n helm install kiosk --version 0.2.11 kiosk/kiosk -n kiosk --atomic\n
For more details, please refer to the Kiosk page on the GitHub.
"},{"location":"operator-guide/install-kiosk/#configuration","title":"Configuration","text":"To provide access to the EDP tenant, follow the steps below.
kubectl create namespace security\n
Note
On an OpenShift cluster, run the oc
command instead of kubectl
one.
kubectl -n security create sa edp\n
Info
Please note that edp
is the name of the EDP tenant here and in all the following steps.
apiVersion: tenancy.kiosk.sh/v1alpha1\nkind: Account\nmetadata:\n name: edp-admin\nspec:\n space:\n clusterRole: kiosk-space-admin\n subjects:\n - kind: ServiceAccount\n name: edp\n namespace: security\n
apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n name: edp-kiosk-edit\nsubjects:\n- kind: ServiceAccount\n name: edp\n namespace: security\nroleRef:\n kind: ClusterRole\n name: kiosk-edit\n apiGroup: rbac.authorization.k8s.io\n
EDP configures the logging with the help of Grafana Loki aggregation system.
"},{"location":"operator-guide/install-loki/#installation","title":"Installation","text":"To install Loki, follow the steps below:
Create logging namespace:
kubectl create namespace logging\n
Note
On the OpenShift cluster, run the oc
command instead of the kubectl
command.
Add a chart repository:
helm repo add grafana https://grafana.github.io/helm-charts\n helm repo update\n
Note
It is possible to use Amazon Simple Storage Service Amazon S3 as an object storage for Loki. To configure access, please refer to the IRSA for Loki documentation.
Install Loki v.2.6.0:
helm install loki grafana/loki \\\n --version 2.6.0 \\\n --values values.yaml \\\n --namespace logging\n
Check out the values.yaml file sample of the Loki customization:
View: values.yamlimage:\n repository: grafana/loki\n tag: 2.3.0\nconfig:\n auth_enabled: false\n schema_config:\n configs:\n - from: 2021-06-01\n store: boltdb-shipper\n object_store: s3\n schema: v11\n index:\n prefix: loki_index_\n period: 24h\n storage_config:\n aws:\n s3: s3://<AWS_REGION>/loki-<CLUSTER_NAME>\n boltdb_shipper:\n active_index_directory: /data/loki/index\n cache_location: /data/loki/boltdb-cache\n shared_store: s3\n chunk_store_config:\n max_look_back_period: 24h\nresources:\n limits:\n memory: \"128Mi\"\n requests:\n cpu: \"50m\"\n memory: \"128Mi\"\nserviceAccount:\n create: true\n name: edp-loki\n annotations:\n eks.amazonaws.com/role-arn: \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki\npersistence:\n enabled: false\n
Note
In case of using cluster scheduling and amazon-eks-pod-identity-webhook, it is necessary to restart the Loki pod after the cluster is up and running. Please refer to the Schedule Pods Restart documentation.
Configure custom bucket policy to delete the old data.
Inspect the prerequisites and the main steps to perform for installing ReportPortal.
Info
It is also possible to install ReportPortal using the Helmfile. For details, please refer to the Install via Helmfile page.
"},{"location":"operator-guide/install-reportportal/#prerequisites","title":"Prerequisites","text":"Info
Please refer to the ReportPortal Helm Chart section for details.
"},{"location":"operator-guide/install-reportportal/#minio-installation","title":"MinIO Installation","text":"To install MinIO, follow the steps below:
Check that edp
namespace is created. If not, run the following command to create it:
kubectl create namespace edp\n
For the OpenShift users:
When using the OpenShift platform, install the SecurityContextConstraints
resources. In case of using a custom namespace for the reportportal
, change the namespace in the users
section.
apiVersion: security.openshift.io/v1\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: report-portal-minio-rabbitmq-postgresql\nallowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegeEscalation: true\nallowPrivilegedContainer: false\nallowedCapabilities: null\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - min: 999\n max: 65543\ngroups: []\npriority: 1\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities:\n - KILL\n - MKNOD\n - SETUID\n - SETGID\nrunAsUser:\n type: MustRunAsRange\n uidRangeMin: 1\n uidRangeMax: 65543\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n - system:serviceaccount:report-portal:minio\n - system:serviceaccount:report-portal:rabbitmq\n - system:serviceaccount:report-portal:postgresql\nvolumes:\n - configMap\n - downwardAPI\n - emptyDir\n - persistentVolumeClaim\n - projected\n - secret\n
View: report-portal-elasticsearch-scc.yaml apiVersion: security.openshift.io/v1\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: report-portal-elasticsearch\nallowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegedContainer: true\nallowedCapabilities: []\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - max: 1000\n min: 1000\ngroups: []\npriority: 0\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities: []\nrunAsUser:\n type: MustRunAsRange\n uidRangeMax: 1000\n uidRangeMin: 0\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n - system:serviceaccount:report-portal:elasticsearch-master\nvolumes:\n - configMap\n - downwardAPI\n - emptyDir\n - persistentVolumeClaim\n - projected\n - secret\n
Add a chart repository:
helm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n
Create MinIO admin secret:
kubectl -n edp create secret generic reportportal-minio-creds \\\n--from-literal=root-password=<root_password> \\\n--from-literal=root-user=<root_user>\n
Install MinIO v.11.10.3 using bitnami/minio Helm chart v.11.10.3:
helm install minio bitnami/minio \\\n--version 11.10.3 \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the MinIO customization:
View: values.yamlauth:\n existingSecret: reportportal-minio-creds\npersistence:\n size: 1Gi\n
To install RabbitMQ, follow the steps below:
Use edp
namespace from the MinIO installation.
Use bitnami
chart repository from the MinIO installation.
Create RabbitMQ admin secret:
kubectl -n edp create secret generic reportportal-rabbitmq-creds \\\n--from-literal=rabbitmq-password=<rabbitmq_password> \\\n--from-literal=rabbitmq-erlang-cookie=<rabbitmq_erlang_cookie>\n
Warning
The rabbitmq_password
password must be 10 characters long. The rabbitmq_erlang_cookie
password must be 32 characters long.
Install RabbitMQ v.10.3.8 using bitnami/rabbitmq Helm chart v.10.3.8:
helm install rabbitmq bitnami/rabbitmq \\\n--version 10.3.8 \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the RabbitMQ customization:
View: values.yamlauth:\n existingPasswordSecret: reportportal-rabbitmq-creds\n existingErlangSecret: reportportal-rabbitmq-creds\npersistence:\n size: 1Gi\n
After the rabbitmq pod gets the status Running, you need to configure the RabbitMQ memory threshold
kubectl -n edp exec -it rabbitmq-0 -- rabbitmqctl set_vm_memory_high_watermark 0.8\n
To install Elasticsearch, follow the steps below:
Use edp
namespace from the MinIO installation.
Add a chart repository:
helm repo add elastic https://helm.elastic.co\nhelm repo update\n
Install Elasticsearch v.7.17.3 using elastic/elasticsearch Helm chart v.7.17.3:
helm install elasticsearch elastic/elasticsearch \\\n--version 7.17.3 \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the Elasticsearch customization:
View: values.yamlreplicas: 1\n\nextraEnvs:\n - name: discovery.type\n value: single-node\n - name: cluster.initial_master_nodes\n value: \"\"\n\nrbac:\n create: true\n\nresources:\n requests:\n cpu: \"100m\"\n memory: \"2Gi\"\n\nvolumeClaimTemplate:\n resources:\n requests:\n storage: 3Gi\n
To install PostgreSQL, follow the steps below:
Use edp
namespace from the MinIO installation.
Add a chart repository:
helm repo add bitnami-archive https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami\nhelm repo update\n
Create PostgreSQL admin secret:
kubectl -n edp create secret generic reportportal-postgresql-creds \\\n--from-literal=postgresql-password=<postgresql_password> \\\n--from-literal=postgresql-postgres-password=<postgresql_postgres_password>\n
Warning
The postgresql_password
and postgresql_postgres_password
passwords must be 16 characters long.
Install PostgreSQL v.10.9.4 using Helm chart v.10.9.4:
helm install postgresql bitnami-archive/postgresql \\\n--version 10.9.4 \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the PostgreSQL customization:
View: values.yamlpersistence:\n size: 1Gi\nresources:\n requests:\n cpu: \"100m\"\nserviceAccount:\n enabled: true\npostgresqlUsername: \"rpuser\"\npostgresqlDatabase: \"reportportal\"\nexistingSecret: \"reportportal-postgresql-creds\"\ninitdbScripts:\n init_postgres.sh: |\n #!/bin/sh\n /opt/bitnami/postgresql/bin/psql -U postgres -d ${POSTGRES_DB} -c 'CREATE EXTENSION IF NOT EXISTS ltree; CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE EXTENSION IF NOT EXISTS pg_trgm;'\n
To install ReportPortal, follow the steps below:
Use edp
namespace from the MinIO installation.
For the OpenShift users:
When using the OpenShift platform, install the SecurityContextConstraints
resource. In case of using a custom namespace for the reportportal
, change the namespace in the users
section.
apiVersion: security.openshift.io/v1\nkind: SecurityContextConstraints\nmetadata:\n annotations:\n \"helm.sh/hook\": \"pre-install\"\n name: report-portal\nallowHostDirVolumePlugin: false\nallowHostIPC: false\nallowHostNetwork: false\nallowHostPID: false\nallowHostPorts: false\nallowPrivilegedContainer: true\nallowedCapabilities: []\nallowedFlexVolumes: []\ndefaultAddCapabilities: []\nfsGroup:\n type: MustRunAs\n ranges:\n - max: 1000\n min: 1000\ngroups: []\npriority: 0\nreadOnlyRootFilesystem: false\nrequiredDropCapabilities: []\nrunAsUser:\n type: MustRunAsRange\n uidRangeMax: 1000\n uidRangeMin: 0\nseLinuxContext:\n type: MustRunAs\nsupplementalGroups:\n type: RunAsAny\nusers:\n - system:serviceaccount:report-portal:reportportal\nvolumes:\n - configMap\n - downwardAPI\n - emptyDir\n - persistentVolumeClaim\n - projected\n - secret\n
Add a chart repository:
helm repo add report-portal \"https://reportportal.github.io/kubernetes\"\nhelm repo update\n
Install ReportPortal v.5.8.0 using Helm chart v.5.8.0:
helm install report-portal report-portal/reportportal \\\n--values values.yaml \\\n--namespace edp\n
Check out the values.yaml file sample of the ReportPortal customization:
View: values.yamlserviceindex:\n resources:\n requests:\n cpu: 50m\nuat:\n resources:\n requests:\n cpu: 50m\nserviceui:\n resources:\n requests:\n cpu: 50m\n serviceAccountName: \"reportportal\"\n securityContext:\n runAsUser: 0\nserviceapi:\n resources:\n requests:\n cpu: 50m\nserviceanalyzer:\n resources:\n requests:\n cpu: 50m\nserviceanalyzertrain:\n resources:\n requests:\n cpu: 50m\n\nrabbitmq:\n SecretName: \"reportportal-rabbitmq-creds\"\n endpoint:\n address: rabbitmq.<EDP_PROJECT>.svc.cluster.local\n user: user\n apiuser: user\n\npostgresql:\n SecretName: \"reportportal-postgresql-creds\"\n endpoint:\n address: postgresql.<EDP_PROJECT>.svc.cluster.local\n\nelasticsearch:\n endpoint: http://elasticsearch-master.<EDP_PROJECT>.svc.cluster.local:9200\n\nminio:\n secretName: \"reportportal-minio-creds\"\n endpoint: http://minio.<EDP_PROJECT>.svc.cluster.local:9000\n endpointshort: minio.<EDP_PROJECT>.svc.cluster.local:9000\n accesskeyName: \"root-user\"\n secretkeyName: \"root-password\"\n\ningress:\n # IF YOU HAVE SOME DOMAIN NAME SET INGRESS.USEDOMAINNAME to true\n usedomainname: true\n hosts:\n - report-portal-<EDP_PROJECT>.<ROOT_DOMAIN>\n
For the OpenShift platform, install a Gateway with Route:
View: gateway-config-cm.yamlkind: ConfigMap\nmetadata:\n name: gateway-config\n namespace: report-portal\napiVersion: v1\ndata:\n traefik-dynamic-config.yml: |\n http:\n middlewares:\n strip-ui:\n stripPrefix:\n prefixes:\n - \"/ui\"\n forceSlash: false\n strip-api:\n stripPrefix:\n prefixes:\n - \"/api\"\n forceSlash: false\n strip-uat:\n stripPrefix:\n prefixes:\n - \"/uat\"\n forceSlash: false\n\n routers:\n index-router:\n rule: \"Path(`/`)\"\n service: \"index\"\n ui-router:\n rule: \"PathPrefix(`/ui`)\"\n middlewares:\n - strip-ui\n service: \"ui\"\n uat-router:\n rule: \"PathPrefix(`/uat`)\"\n middlewares:\n - strip-uat\n service: \"uat\"\n api-router:\n rule: \"PathPrefix(`/api`)\"\n middlewares:\n - strip-api\n service: \"api\"\n\n services:\n uat:\n loadBalancer:\n servers:\n - url: \"http://report-portal-reportportal-uat:9999/\"\n\n index:\n loadBalancer:\n servers:\n - url: \"http://report-portal-reportportal-index:8080/\"\n\n api:\n loadBalancer:\n servers:\n - url: \"http://report-portal-reportportal-api:8585/\"\n\n ui:\n loadBalancer:\n servers:\n - url: \"http://report-portal-reportportal-ui:8080/\"\n traefik.yml: |\n entryPoints:\n http:\n address: \":8081\"\n metrics:\n address: \":8082\"\n\n metrics:\n prometheus:\n entryPoint: metrics\n addEntryPointsLabels: true\n addServicesLabels: true\n buckets:\n - 0.1\n - 0.3\n - 1.2\n - 5.0\n\n providers:\n file:\n filename: /etc/traefik/traefik-dynamic-config.yml\n
View: gateway-deployment.yaml apiVersion: apps/v1\nkind: Deployment\nmetadata:\n labels:\n app: reportportal\n name: gateway\n namespace: report-portal\nspec:\n replicas: 1\n selector:\n matchLabels:\n component: gateway\n template:\n metadata:\n labels:\n component: gateway\n spec:\n containers:\n - image: quay.io/waynesun09/traefik:2.3.6\n name: traefik\n ports:\n - containerPort: 8080\n protocol: TCP\n resources: {}\n volumeMounts:\n - mountPath: /etc/traefik/\n name: config\n readOnly: true\n volumes:\n - name: config\n configMap:\n defaultMode: 420\n name: gateway-config\n
View: gateway-route.yaml kind: Route\napiVersion: route.openshift.io/v1\nmetadata:\n labels:\n app: reportportal\n name: reportportal\n namespace: report-portal\nspec:\n host: report-portal.<CLUSTER_DOMAIN>\n port:\n targetPort: http\n tls:\n insecureEdgeTerminationPolicy: Redirect\n termination: edge\n to:\n kind: Service\n name: gateway\n weight: 100\n wildcardPolicy: None\n
View: gateway-service.yaml apiVersion: v1\nkind: Service\nmetadata:\n labels:\n app: reportportal\n component: gateway\n name: gateway\n namespace: report-portal\nspec:\n ports:\n # use 8081 to allow for usage of the dashboard which is on port 8080\n - name: http\n port: 8081\n protocol: TCP\n targetPort: 8081\n selector:\n component: gateway\n sessionAffinity: None\n type: ClusterIP\n
Note
For user access: default/1q2w3e For admin access: superadmin/erebus Please refer to the ReportPortal.io page for details.
"},{"location":"operator-guide/install-reportportal/#related-articles","title":"Related Articles","text":"EPAM Delivery Platform uses Tekton resources, such as Tasks, Pipelines, Triggers, Interceptors and Chains for running the CI/CD pipelines.
Inspect the main steps to perform for installing the Tekton resources via the Tekton release files.
"},{"location":"operator-guide/install-tekton/#prerequisites","title":"Prerequisites","text":"oc
utility is required. Please refer to the OKD page on GitHub for details.kaniko-cache
and this parameter is located in our Tekton common-library
.To install Tekton resources, follow the steps below:
Info
Please refer to the Install Tekton Pipelines and Install and set up Tekton Triggers sections for details.
Install Tekton pipelines v0.53.0 using the release file:
Note
Tekton Pipeline resources are used for managing and running EDP Tekton Pipelines and Tasks. Please refer to the EDP Tekton Pipelines and EDP Tekton Tasks pages for details.
kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.53.0/release.yaml\n
Install Tekton Triggers v0.25.2 using the release file:
Note
Tekton Trigger resources are used for managing and running EDP Tekton EventListeners, Triggers, TriggerBindings and TriggerTemplates. Please refer to the EDP Tekton Triggers page for details.
kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/previous/v0.25.2/release.yaml\n
Install Tekton Interceptors v0.25.2 using the release file:
Note
EPAM Delivery Platform uses GitLab, GitHub and Cel ClusterInterceptors for managing requests from webhooks.
kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/previous/v0.25.2/interceptors.yaml\n
Install Tekton Chains v0.19.0 using the release file:
kubectl apply -f https://storage.googleapis.com/tekton-releases/chains/previous/v0.19.0/release.yaml\n
To install Tekton resources, follow the steps below:
Info
Please refer to the Install Tekton Operator documentation for details.
Note
Tekton Operator also deploys Pipelines as Code CI that requires OpenShift v4.11 (based on Kubernetes v1.24) or higher. This feature is optional and its deployments can be scaled to zero replicas.
Install Tekton Operator v0.67.0 using the release file:
kubectl apply -f https://github.com/tektoncd/operator/releases/download/v0.67.0/openshift-release.yaml\n
After the installation, the Tekton Operator will install the following components: Pipeline, Trigger, and Addons.
Note
If there is the following error in the openshift-operators
namespace for openshift-pipelines-operator
and tekton-operator-webhook
deployments:
Error: container has runAsNonRoot and image will run as root\n
Patch the deployments with the following commands:
kubectl -n openshift-operators patch deployment openshift-pipelines-operator -p '{\"spec\": {\"template\": {\"spec\": {\"securityContext\": {\"runAsUser\": 1000}}}}}'\nkubectl -n openshift-operators patch deployment tekton-operator-webhook -p '{\"spec\": {\"template\": {\"spec\": {\"securityContext\": {\"runAsUser\": 1000}}}}}'\n
Grant access for Tekton Service Accounts in the openshift-pipelines
namespace to the Privileged SCC:
oc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-operators-proxy-webhook\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-pipelines-controller\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-pipelines-resolvers\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-pipelines-webhook\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-triggers-controller\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-triggers-core-interceptors\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:tekton-triggers-webhook\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:pipelines-as-code-controller\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:pipelines-as-code-watcher\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:pipelines-as-code-webhook\noc adm policy add-scc-to-user privileged system:serviceaccount:openshift-pipelines:default\n
"},{"location":"operator-guide/install-tekton/#related-articles","title":"Related Articles","text":"Velero is an open source tool to safely back up, recover, and migrate Kubernetes clusters and persistent volumes. It works both on premises and in a public cloud. Velero consists of a server process running as a deployment in your Kubernetes cluster and a command-line interface (CLI) with which DevOps teams and platform operators configure scheduled backups, trigger ad-hoc backups, perform restores, and more.
"},{"location":"operator-guide/install-velero/#installation","title":"Installation","text":"To install Velero, follow the steps below:
Create velero namespace:
kubectl create namespace velero\n
Note
On an OpenShift cluster, run the oc
command instead of kubectl
one.
Add a chart repository:
helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts\n helm repo update\n
Note
Velero AWS Plugin requires access to AWS resources. To configure access, please refer to the IRSA for Velero documentation.
Install Velero v.2.14.13:
helm install velero vmware-tanzu/velero \\\n --version 2.14.13 \\\n --values values.yaml \\\n --namespace velero\n
Check out the values.yaml file sample of the Velero customization:
View: values.yamlimage:\n repository: velero/velero\n tag: v1.5.3\nsecurityContext:\n fsGroup: 65534\nrestic:\n securityContext:\n fsGroup: 65534\nserviceAccount:\n server:\n create: true\n name: edp-velero\n annotations:\n eks.amazonaws.com/role-arn: \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero\"\ncredentials:\n useSecret: false\nconfiguration:\n provider: aws\n backupStorageLocation:\n name: default\n bucket: velero-<CLUSTER_NAME>\n config:\n region: eu-central-1\n volumeSnapshotLocation:\n name: default\n config:\n region: <AWS_REGION>\ninitContainers:\n - name: velero-plugin-for-aws\n image: velero/velero-plugin-for-aws:v1.1.0\n volumeMounts:\n - mountPath: /target\n name: plugins\n
Note
In case of using cluster scheduling and amazon-eks-pod-identity-webhook, it is necessary to restart the Velero pod after the cluster is up and running. Please refer to the Schedule Pods Restart documentation.
Install the client side (velero cli) according to the official documentation.
Create backup for all components in the namespace:
velero backup create <BACKUP_NAME> --include-namespaces <NAMESPACE>\n
Create a daily backup of the namespace:
velero schedule create <BACKUP_NAME> --schedule \"0 10 * * MON-FRI\" --include-namespaces <NAMESPACE> --ttl 120h0m0s\n
To restore from backup, use the following command:
velero restore create <RESTORE_NAME> --from-backup <BACKUP_NAME>\n
This article provides the instruction on how to deploy EDP and components in Kubernetes using Helmfile that is intended for deploying Helm charts. Helmfile templates are available in GitHub repository.
Important
The Helmfile installation method for EPAM Delivery Platform (EDP) is currently not actively maintained. We strongly recommend exploring alternative installation options for the most up-to-date and well-supported deployment experience. You may consider using the Add-Ons approach or opting for installation via the AWS Marketplace to ensure a reliable and secure deployment of EDP.
"},{"location":"operator-guide/install-via-helmfile/#prerequisites","title":"Prerequisites","text":"The following tools and plugins must be installed:
envs/common.yaml
file contains the specification for environments pattern, list of helm repositories from which it is necessary to fetch the helm charts and additional Helm parameters.envs/platform.yaml
file contains global parameters that are used in various Helmfiles.releases/envs/
contains symbol links to environments files.releases/*.yaml
file contains description of parameters that is used when deploying a Helm chart.helmfile.yaml
file defines components to be installed by defining a path to Helm releases files.envs/ci.yaml
file contains stub parameters for CI linter.test/lint-ci.sh
script for running CI linter with debug loglevel and stub parameters.resources/*.yaml
file contains additional resources for the OpenShift platform.Before applying the Helmfile, please fill in the global parameters in the envs/platform.yaml
(check the examples in the envs/ci.yaml
) and releases/*.yaml
files for every Helm deploy.
Pay attention to the following recommendations while working with the Helmfile:
test/lint-ci.sh
script.helm diff
):helmfile --environment platform -f helmfile.yaml diff\n
helmfile --selector component=ingress --environment platform -f helmfile.yaml apply\n
helmfile --selector component=ingress --environment platform -f helmfile.yaml sync\n
nginx-ingress
file, use the following command:helmfile --selector component=ingress --environment platform -f helmfile.yaml diff\n
helmfile --selector component=ingress --environment platform -f helmfile.yaml destroy\n
Using the Helmfile, the following components can be installed:
Info
Skip this step for the OpenShift platform, because it has its own Ingress Controller.
To install NGINX Ingress controller, follow the steps below:
In the releases/nginx-ingress.yaml
file, set the proxy-real-ip-cidr
parameter according to the value with AWS VPC IPv4 CIDR.
Install NGINX Ingress controller:
helmfile --selector component=ingress --environment platform -f helmfile.yaml apply\n
Keycloak requires a database deployment, so it has two charts: releases/keycloak.yaml
and releases/postgresql-keycloak.yaml
.
To install Keycloak, follow the steps below:
Create a security
namespace:
Note
For the OpenShift users: This namespace is also indicated as users
in the following custom SecurityContextConstraints
resources: resources/keycloak-scc.yaml
and resources/postgresql-keycloak-scc.yaml
. Change the namespace name when using a custom namespace.
kubectl create namespace security\n
Create PostgreSQL admin secret:
kubectl -n security create secret generic keycloak-postgresql \\\n--from-literal=password=<postgresql_password> \\\n--from-literal=postgres-password=<postgresql_postgres_password>\n
In the envs/platform.yaml
file, set the dnsWildCard
parameter.
Create Keycloak admin secret:
kubectl -n security create secret generic keycloak-admin-creds \\\n--from-literal=username=<keycloak_admin_username> \\\n--from-literal=password=<keycloak_admin_password>\n
Install Keycloak:
helmfile --selector component=sso --environment platform -f helmfile.yaml apply\n
To install External Secrets Operator, follow the steps below:
helmfile --selector component=secrets --environment platform -f helmfile.yaml apply\n
"},{"location":"operator-guide/install-via-helmfile/#deploy-kiosk","title":"Deploy Kiosk","text":"To install Kiosk, follow the steps below:
helmfile --selector component=kiosk --environment platform -f helmfile.yaml apply\n
"},{"location":"operator-guide/install-via-helmfile/#deploy-epam-delivery-platform","title":"Deploy EPAM Delivery Platform","text":"To install EDP, follow the steps below:
Create a platform
namespace:
kubectl create namespace platform\n
For EDP, it is required to have Keycloak access to perform the integration. Create a secret with the user and password provisioned in the step 2 of the Keycloak Configuration section.
kubectl -n platform create secret generic keycloak \\\n --from-literal=username=<username> \\\n --from-literal=password=<password>\n
In the envs/platform.yaml
file, set the edpName
and keycloakEndpoint
parameters.
In the releases/edp-install.yaml
file, check and fill in all values.
Install EDP:
helmfile --selector component=edp --environment platform -f helmfile.yaml apply\n
Before Argo CD deployment, install the following tools:
To install Argo CD, follow the steps below:
Install Argo CD:
For the OpenShift users:
When using a custom namespace for Argo CD, the `argocd` namespace is also indicated as `users` in the `resources/argocd-scc.yaml` custom `SecurityContextConstraints` resource. Change it there as well.\n
helmfile --selector component=argocd --environment platform -f helmfile.yaml apply\n
Update the argocd-secret
secret in the Argo CD namespace by providing the correct Keycloak client secret (oidc.keycloak.clientSecret
) with the value from the keycloak-client-argocd-secret
secret in EDP namespace. Then restart the deployment:
ARGOCD_CLIENT=$(kubectl -n platform get secret keycloak-client-argocd-secret -o jsonpath='{.data.clientSecret}')\nkubectl -n argocd patch secret argocd-secret -p=\"{\\\"data\\\":{\\\"oidc.keycloak.clientSecret\\\": \\\"${ARGOCD_CLIENT}\\\"}}\" -v=1\nkubectl -n argocd rollout restart deployment argo-argocd-server\n
Prerequisites
Info
It is also possible to install DefectDojo via Helm Chart. For details, please refer to the Install DefectDojo page.
To install DefectDojo via Helmfile, follow the steps below:
Create a DefectDojo namespace:
For the OpenShift users:
This namespace is also indicated as users
in the resources/defectdojo-scc.yaml
custom SecurityContextConstraints
resource. Change it when using a custom namespace. Also, change the namespace in the resources/defectdojo-route.yaml
file.
kubectl create namespace defectdojo\n
Modify the host
in resources/defectdojo-route.yaml
(only for OpenShift).
Create a PostgreSQL admin secret:
kubectl -n defectdojo create secret generic defectdojo-postgresql-specific \\\n--from-literal=postgresql-password=<postgresql_password> \\\n--from-literal=postgresql-postgres-password=<postgresql_postgres_password>\n
Note
The postgresql_password
and postgresql_postgres_password
passwords must be 16 characters long.
Create a RabbitMQ admin secret:
kubectl -n defectdojo create secret generic defectdojo-rabbitmq-specific \\\n--from-literal=rabbitmq-password=<rabbitmq_password> \\\n--from-literal=rabbitmq-erlang-cookie=<rabbitmq_erlang_cookie>\n
Note
The rabbitmq_password
password must be 10 characters long.
The rabbitmq_erlang_cookie
password must be 32 characters long.
Create a DefectDojo admin secret:
kubectl -n defectdojo create secret generic defectdojo \\\n--from-literal=DD_ADMIN_PASSWORD=<dd_admin_password> \\\n--from-literal=DD_SECRET_KEY=<dd_secret_key> \\\n--from-literal=DD_CREDENTIAL_AES_256_KEY=<dd_credential_aes_256_key> \\\n--from-literal=METRICS_HTTP_AUTH_PASSWORD=<metric_http_auth_password>\n
Note
The dd_admin_password
password must be 22 characters long.
The dd_secret_key
password must be 128 characters long.
The dd_credential_aes_256_key
password must be 128 characters long.
The metric_http_auth_password
password must be 32 characters long.
Create a Keycloak client secret for DefectDojo:
Note
The keycloak_client_secret
value received from: edpName
-main realm -> clients -> defectdojo -> Credentials -> Client secret
kubectl -n defectdojo create secret generic defectdojo-extrasecrets \\\n--from-literal=DD_SOCIAL_AUTH_KEYCLOAK_SECRET=<keycloak_client_secret>\n
In the envs/platform.yaml
file, set the dnsWildCard
parameter.
In the releases/defectdojo.yaml file, check and fill in all values.
Install DefectDojo:
helmfile --selector component=defectdojo --environment platform -f helmfile.yaml apply\n
Info
It is also possible to install ReportPortal via Helm Chart. For details, please refer to the Install ReportPortal page.
ReportPortal requires third-party deployments: RabbitMQ, ElasticSearch, PostgreSQL, MinIO.
To install third-party resources, follow the steps below:
Create a RabbitMQ admin secret:
kubectl -n report-portal create secret generic reportportal-rabbitmq-creds \\\n--from-literal=rabbitmq-password=<rabbitmq_password> \\\n--from-literal=rabbitmq-erlang-cookie=<rabbitmq_erlang_cookie>\n
Warning
The rabbitmq_password
password must be 10 characters long.
The rabbitmq_erlang_cookie
password must be 32 characters long.
Create a PostgreSQL admin secret:
kubectl -n report-portal create secret generic reportportal-postgresql-creds \\\n--from-literal=postgresql-password=<postgresql_password> \\\n--from-literal=postgresql-postgres-password=<postgresql_postgres_password>\n
Warning
The postgresql_password
and postgresql_postgres_password
passwords must be 16 characters long.
Create a MinIO admin secret:
kubectl -n report-portal create secret generic reportportal-minio-creds \\\n--from-literal=root-password=<root_password> \\\n--from-literal=root-user=<root_user>\n
In the envs/platform.yaml
file, set the dnsWildCard
and edpName
parameters.
For the OpenShift users:
The namespace is also indicated as users
in the following custom SecurityContextConstraints
resources: resources/report-portal-elasticsearch-scc.yaml
and resources/report-portal-third-party-resources-scc.yaml
. Change the namespace name when using a custom namespace.
Install third-party resources:
helmfile --selector component=report-portal-third-party-resources --environment platform -f helmfile.yaml apply\n
After the rabbitmq pod gets the status Running, you need to configure the RabbitMQ memory threshold
kubectl -n report-portal exec -it rabbitmq-0 -- rabbitmqctl set_vm_memory_high_watermark 0.8\n
To install ReportPortal via Helmfile, follow the steps below:
For the OpenShift users:
users
in the resources/report-portal-reportportal-scc.yaml
custom SecurityContextConstraints
resource. Change it when using a custom namespace.resources/report-portal-gateway/gateway-config-cm
, resources/report-portal-gateway/gateway-deployment
, resources/report-portal-gateway/gateway-route
, and resources/report-portal-gateway/gateway-service
.host
in resources/report-portal-gateway/gateway-route
helmfile --selector component=report-portal --environment platform -f helmfile.yaml apply\n
Note
For user access: default/1q2w3e For admin access: superadmin/erebus Please refer to the ReportPortal.io page for details.
"},{"location":"operator-guide/install-via-helmfile/#deploy-moon","title":"Deploy Moon","text":"Moon is a browser automation solution compatible with Selenium, Cypress, Playwright, and Puppeteer using Kubernetes or Openshift to launch browsers.
Note
Aerokube/Moon does not require third-party deployments.
Follow the steps below to deploy Moon:
Use the following command to install Moon:
helmfile --selector component=moon --environment platform -f helmfile.yaml apply\n
After the installation, open the Ingress Dashboard and check that SELENOID
and SSE
have the CONNECTED
status.
Main board
In Moon, use the following command with the Ingress rule, for example, wd/hub
:
curl -X POST 'http://<INGRESS_LINK>/wd/hub/session' -d '{\n \"desiredCapabilities\":{\n \"browserName\":\"firefox\",\n \"version\": \"79.0\",\n \"platform\":\"ANY\",\n \"enableVNC\": true,\n \"name\": \"edp\",\n \"sessionTimeout\": \"480s\"\n }\n }'\n
See below the list of Moon Dashboard Ingress rules:
Moon Dashboard Ingress rules
After using the command above, the container will start, and the VNC viewer will be displayed on the Moon Dashboard:
VNC viewer with the container starting
The monitoring stack includes Grafana, Prometheus, Alertmanager, and Karma-dashboard. To deploy it follow the steps:
Generate a token for Keycloak client:
Note
The token must be 32-character and include alphabetic and numeric symbols. For example, use the following command:
keycloak_client_secret=$(date +%s | sha256sum | base64 | head -c 32 ; echo)\n
Create a secret for the Keycloak client:
kubectl -n platform create secret generic keycloak-client-grafana \\\n --from-literal=clientSecret=<keycloak_client_secret>\n
Create a secret for the Grafana:
kubectl -n monitoring create secret generic keycloak-client-grafana \\\n --from-literal=GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=<keycloak_client_secret> \\\n
Create a custom resource for the Keycloak client:
View: keycloak_clientapiVersion: v1.edp.epam.com/v1\nkind: KeycloakClient\nmetadata:\n name: grafana\n namespace: platform\nspec:\n clientId: grafana\n directAccess: true\n serviceAccount:\n enabled: true\n targetRealm: platform-main\n webUrl: https://grafana-monitoring.<dnsWildCard>\n secret: keycloak-client.grafana\n
Run command:
helmfile --selector component=monitoring --environment platform -f helmfile.yaml apply\n
To install Elasticsearch, Kibana and Fluentbit, run command:
helmfile --selector component=logging-elastic --environment platform -f helmfile.yaml apply\n
To install Grafana, Loki, Promtail, follow the steps below:
Make sure that appropriate resources are created:
Create a custom resource for the Keycloak client:
View: keycloak_clientapiVersion: v1.edp.epam.com/v1\nkind: KeycloakClient\nmetadata:\n name: grafana\n namespace: platform\nspec:\n clientId: grafana-logging\n directAccess: true\n serviceAccount:\n enabled: true\n targetRealm: platform-main\n webUrl: https://grafana-logging.<dnsWildCard>\n secret: keycloak-client.grafana\n
Run command:
helmfile --selector component=logging --environment platform -f helmfile.yaml apply\n
In order to adjust the Version Control System integration with Jira Server, first make sure you have the following prerequisites:
When checked the prerequisites, follow the steps below to proceed with the integration:
Integrate every project in VCS Server with every project in Crucible by creating a corresponding request in EPAM Support Portal. Add the repositories links and fill in the Keep Informed field as this request must be approved.
Request example
Provide additional details to the support team. If the VCS is Gerrit, inspect the sample below of its integration:
2.1 Create a new \"crucible-\" user in Gerrit with SSH key and add a new user to the \"Non-Interactive Users\" Gerrit group;
2.2 Create a new group in Gerrit \"crucible-watcher-group\" and add the \"crucible-\" user;
2.3 Provide access to All-Projects for the \"crucible-watcher-group\" group:
Gerrit All-Projects configuration
Gerrit All-Projects configuration
To link commits with Jira ticket, being in Gerrit, enter a Jira ticket ID in a commit message using the specific format:
[PROJECT-CODE-1234]: commit message
where PROJECT-CODE is a specific code of a project, 1234 is an ID number, and a commit message.
As a result, all Gerrit commits will be displayed on Crucible:
Crucible project
This documentation guide provides step-by-step instructions for enabling the Jira integration option in the EDP Portal UI for EPAM Delivery Platform. Jira integration allows including useful metadata in Jira tickets.
"},{"location":"operator-guide/jira-integration/#overview","title":"Overview","text":"Integrating Jira can provide a number of benefits, such as increased visibility and traceability, automatic linking code changes to relevant Jira issues, streamlining the management and tracking of development progress.
By linking CI pipelines to Jira issues, teams can get a better understanding of the status of their work and how it relates to the overall development process. This can help to improve communication and collaboration, and ultimately lead to faster and more efficient delivery of software.
Enabling Jira integration allows for the automatic population of three fields in Jira tickets: Fix Versions, Components, and Labels. Each of these fields provides distinct benefits:
Teams can utilize these fields to enhance their work prioritization, identify dependencies, improve collaboration, and ultimately achieve faster software delivery.
"},{"location":"operator-guide/jira-integration/#integration-procedure","title":"Integration Procedure","text":"In order to adjust the Jira server integration, add the JiraServer CR by performing the following:
Provision the ci-jira secret using EDP Portal
, Manifest
or with the externalSecrets
operator:
Go to EDP Portal -> EDP -> Configuration -> Jira. Update or fill in the URL, User, Password fields and click the Save button:
Jira update manual secret
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-jira\n namespace: edp\n labels:\n app.edp.epam.com/secret-type=jira\nstringData:\n username: username\n password: password\n
\"ci-jira\":\n{\n \"username\": \"username\",\n \"password\": \"password\"\n}\n
Required Permissions for Issue Management
To manage issue labels, components, and add links in Jira, please make sure the user has the following permissions:
Edit Issues: This permission is necessary to modify issue fields, including adding or removing labels and components.
Link Issues: You must have this permission to create and manage links between issues.
Add Comments: Required for adding external links and comments to issues.
Create JiraServer CR in the OpenShift/Kubernetes namespace with the apiUrl, credentialName and rootUrl fields:
apiVersion: v2.edp.epam.com/v1\nkind: JiraServer\nmetadata:\n name: jira-server\nspec:\n apiUrl: 'https://jira-api.example.com'\n credentialName: ci-jira\n rootUrl: 'https://jira.example.com'\n
Note
The value of the credentialName property is the name of the Secret, which is indicated in the first point above.
There is also a possibility to set up Jira integration when deploying EPAM Delivery Platform. To follow this approach, please familiarize yourself with the following parameters of the values.yaml file in the EDP installer. Enabling the jira.integration
parameter creates the following custom resources:
To set up Jira integration along with EDP, follow the steps below:
Create the ci-jira secret in the edp
namespace as it's described above.
Deploy the platform with the jira.integration
parameter set to true
in the values.yaml file.
To use Jira integration, you need to set up your codebases accordingly.
When creating a codebase, navigate to the Advanced Settings tab. Select the Integrate with Jira server check box and fill in the required fields:
Advanced settings
There are four predefined variables with the respective values that can be specified singly or as a combination. These variables show different data depending on which versioning type is currently used:
If the EDP versioning type is used:
If the default versioning type is used:
Note
There are no character restrictions when combining the variables. You can concatenate them using the dash sign. Combination samples: EDP_SEM_VERSION-EDP_COMPONENT; EDP_COMPONENT-hello-world/EDP_VERSION; etc.
If the Jira integration is set up correctly, you will start seeing additional metadata in the tickets:
Supplemental information
If metadata is not visible in a Jira ticket, check the status field of the JiraIssueMetadata Custom Resources in the edp namespace. The codebase operator deletes this resource after successful processing, but in case of an error, the 'JiraIssueMetadata' resource may still exist within the namespace.
"},{"location":"operator-guide/jira-integration/#related-articles","title":"Related Articles","text":"Note
The information below is relevant in case ECR is used as Docker container registry. Make sure that IRSA is enabled and amazon-eks-pod-identity-webhook is deployed according to the Associate IAM Roles With Service Accounts documentation.
The \"build-image-kaniko\" stage manages ECR through IRSA that should be available on the cluster. Follow the steps below to create a required role:
Create AWS IAM Policy \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko_policy\":
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"ecr:*\",\n \"cloudtrail:LookupEvents\"\n ],\n \"Resource\": \"arn:aws:ecr:<AWS_REGION>:<AWS_ACCOUNT_ID>:repository/<EDP_NAMESPACE>/*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": \"ecr:GetAuthorizationToken\",\n \"Resource\": \"*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"ecr:DescribeRepositories\",\n \"ecr:CreateRepository\"\n ],\n \"Resource\": \"arn:aws:ecr:<AWS_REGION>:<AWS_ACCOUNT_ID>:repository/*\"\n }\n ]\n}\n
Create AWS IAM Role \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko\" with trust relationships:
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER>\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"<OIDC_PROVIDER>:sub\": \"system:serviceaccount:edp:edp-kaniko\"\n }\n }\n }\n ]\n}\n
Attach the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko_policy\" policy to the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko\" role.
Define the resulted arn role value into the kaniko.roleArn parameter in values.yaml during the EDP installation.
This documentation describes the advantages of EFK stack over the traditional ELK stack, explains the value that this stack brings to EDP and instructs how to set up the EFK stack to integrate the advanced logging system with your application.
"},{"location":"operator-guide/kibana-ilm-rollover/#elk-stack-overview","title":"ELK Stack Overview","text":"The ELK (Elasticsearch, Logstash and Kibana) stack gives the ability to aggregate logs from all the managed systems and applications, analyze these logs and create visualizations for application and infrastructure monitoring, faster troubleshooting, security analytics and more.
Here is a brief description of the ELK stack default components:
ELK Stack
"},{"location":"operator-guide/kibana-ilm-rollover/#efk-stack-overview","title":"EFK Stack Overview","text":"We use FEK (also called EFK) (Fluent Bit, Elasticsearch, Kibana) stack in Kubernetes instead of ELK because this stack provides us with the support for Logsight for Stage Verification and Incident Detection. In addition to it, Fluent Bit has a smaller memory fingerprint than Logstash. Fluent Bit has the Inputs, Parsers, Filters and Outputs plugins similarly to Logstash.
FEK Stack
"},{"location":"operator-guide/kibana-ilm-rollover/#automate-elasticsearch-index-rollover-with-ilm","title":"Automate Elasticsearch Index Rollover With ILM","text":"In this guide, index rollover with the Index Lifecycle Management ILM is automated in the FEK stack.
The resources can be created via API using curl, Postman, Kibana Dev Tools console or via GUI. They are going to be created them using Kibana Dev Tools.
Go to Management
\u2192 Dev Tools
in the Kibana dashboard:
Dev Tools
Create index lifecycle policy with the index rollover:
Note
This policy can also be created in GUI in Management
\u2192 Stack Management
\u2192 Index Lifecycle Policies
.
Index Lifecycle has several phases: Hot, Warm, Cold, Frozen, Delete. Indices also have different priorities in each phase. The warmer the phase, the higher the priority is supposed to be, e.g., 100 for the hot phase, 50 for the warm phase, and 0 for the cold phase.
In this Use Case, only the Hot and Delete phases are configured. So an index will be created, rolled over to a new index when 1gb in size or 1day in time and deleted in 7 days. The rollover may not happen exactly at 1GB because it depends on how often Kibana checks the index size. Kibana usually checks the index size every 10 minutes but this can be changed by setting the indices.lifecycle.poll_interval monitoring timer.
The index lifecycle policy example:
Index Lifecycle PolicyPUT _ilm/policy/fluent-bit-policy\n{\n \"policy\": {\n \"phases\": {\n \"hot\": {\n \"min_age\": \"0ms\",\n \"actions\": {\n \"set_priority\": {\n \"priority\": 100\n },\n \"rollover\": {\n \"max_size\": \"1gb\",\n \"max_primary_shard_size\": \"1gb\",\n \"max_age\": \"1d\"\n }\n }\n },\n \"delete\": {\n \"min_age\": \"7d\",\n \"actions\": {\n \"delete\": {\n \"delete_searchable_snapshot\": true\n }\n }\n }\n }\n }\n}\n
Insert the code above into the Dev Tools
and click the arrow to send the PUT
request.
Create an index template so that a new index is created according to this template after the rollover:
Note
This policy can also be created in GUI in Management
\u2192 Stack Management
\u2192 Index Management
\u2192 Index Templates
.
Expand the menu below to see the index template example:
Index TemplatePUT /_index_template/fluent-bit\n{\n \"index_patterns\": [\"fluent-bit-kube-*\"],\n \"template\": {\n \"settings\": {\n \"index\": {\n \"lifecycle\": {\n \"name\": \"fluent-bit-policy\",\n \"rollover_alias\": \"fluent-bit-kube\"\n },\n \"number_of_shards\": \"1\",\n \"number_of_replicas\": \"0\"\n }\n }\n }\n}\n
Note
index.lifecycle.rollover_alias
is required when using a policy containing the rollover action and specifies which alias to rollover on behalf of this index. The intention here is that the rollover alias is also defined on the index.number_of_shards
is the quantity of the primary shards. Elasticsearch index is really just a logical grouping of one or more physical shards, where each shard is actually a self-contained index. By distributing the documents in an index across multiple shards and distributing those shards across multiple nodes, Elasticsearch can ensure redundancy, which both protects against hardware failures and increases query capacity as nodes are added to a cluster. As the cluster grows (or shrinks), Elasticsearch automatically migrates shards to re-balance the cluster. Please refer to the official documentation here.number_of_replicas
is the number of replica shards. A replica shard is a copy of a primary shard. Elasticsearch will never assign a replica to the same node as the primary shard, so make sure you have more than one node in your Elasticsearch cluster if you need to use replica shards. The Elasticsearch cluster details and the quantity of nodes can be checked with:
GET _cluster/health\n
Since we use one node, the number_of_shards is 1 and number_of_replicas is 0. If you put more replicas within one node, your index will get yellow status in Kibana, yet still be working.
Create an empty index with write permissions:
Note
This index can also be created in GUI in Management
\u2192 Stack Management
\u2192 Index Management
\u2192 Indices
.
Index example with the date math format:
Index# URI encoded /<fluent-bit-kube-{now/d}-000001>\nPUT /%3Cfluent-bit-kube-%7Bnow%2Fd%7D-000001%3E\n{\n \"aliases\": {\n \"fluent-bit-kube\": {\n \"is_write_index\": true\n }\n }\n}\n
The code above will create an index in the{index_name}-{current_date}-{rollover_index_increment}
format. For example: fluent-bit-kube-2023.03.17-000001
.
Please refer to the official documentation on the index rollover with Date Math here.
Note
It is also possible to use index pattern below if the date math format does not seem applicable:
Index
PUT fluent-bit-kube-000001\n{\n \"aliases\": {\n \"fluent-bit-kube\": {\n \"is_write_index\": true\n }\n }\n}\n
Check the status of the created index:
GET fluent-bit-kube*-000001/_ilm/explain\n
Configure Fluent Bit. Play attention to the Elasticsearch Output plugin configuration.
The important fields in the [OUTPUT]
section are Index fluent-bit-kube
since we should use the index with the same name as Rollover Alias in Kibana and Logstash_Format Off
as we use the Rollover index pattern in Kibana that increments by 1.
ConfigMap example with Configuration Variables for HTTP_User
and HTTP_Passwd
:
data:\n fluent-bit.conf: |\n [SERVICE]\n Daemon Off\n Flush 10\n Log_Level info\n Parsers_File parsers.conf\n Parsers_File custom_parsers.conf\n HTTP_Server On\n HTTP_Listen 0.0.0.0\n HTTP_Port 2020\n Health_Check On\n\n [INPUT]\n Name tail\n Tag kube.*\n Path /var/log/containers/*.log\n Parser docker\n Mem_Buf_Limit 5MB\n Skip_Long_Lines Off\n Refresh_Interval 10\n [INPUT]\n Name systemd\n Tag host.*\n Systemd_Filter _SYSTEMD_UNIT=kubelet.service\n Read_From_Tail On\n Strip_Underscores On\n\n [FILTER]\n Name kubernetes\n Match kube.*\n Kube_Tag_Prefix kube.var.log.containers.\n Kube_URL https://kubernetes.default.svc:443\n Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token\n Merge_Log Off\n Merge_Log_Key log_processed\n K8S-Logging.Parser On\n K8S-Logging.Exclude On\n [FILTER]\n Name nest\n Match kube.*\n Operation lift\n Nested_under kubernetes\n Add_prefix kubernetes.\n [FILTER]\n Name modify\n Match kube.*\n Copy kubernetes.container_name tags.container\n Copy log message\n Copy kubernetes.container_image tags.image\n Copy kubernetes.namespace_name tags.namespace\n [FILTER]\n Name nest\n Match kube.*\n Operation nest\n Wildcard tags.*\n Nested_under tags\n Remove_prefix tags.\n\n [OUTPUT]\n Name es\n Match kube.*\n Index fluent-bit-kube\n Host elasticsearch-master\n Port 9200\n HTTP_User ${ES_USER}\n HTTP_Passwd ${ES_PASSWORD}\n Logstash_Format Off\n Time_Key @timestamp\n Type flb_type\n Replace_Dots On\n Retry_Limit False\n Trace_Error Off\n
Create index pattern (Data View starting from Kibana v8.0):
Go to Management
\u2192 Stack Management
\u2192 Kibana
\u2192 Index patterns
and create an index with the fluent-bit-kube-*
pattern:
Index Pattern
Check logs in Kibana. Navigate to Analytics
\u2192 Discover
:
Logs in Kibana
Note
In addition, in the top-right corner of the Discover
window, there is a button called Inspect
. Clicking on it will reveal the query that Kibana is sending to Elasticsearch. These queries can be used in Dev Tools.
Monitor the created indices:
GET _cat/indices/fluent-bit-kube-*\n
Note
Physically, the indices are located on the elasticsearch
Kubernetes pod in /usr/share/elasticsearch/data/nodes/0/indices
. It is recommended to backup indices only via Snapshots.
We've configured the index rollover process. Now the index will be rolled over to a new one once it reaches the indicated size or time in the policy, and old indices will be removed according to the policy as well.
When you create an empty index that corresponds to the pattern indicated in the index template, the index template attaches rollover_alias
with the fluent-bit-kube
name, policy and other configured data. Then the Fluent Bit Elasticsearch output plugin sends logs to the Index fluent-bit-kube
rollover alias. The index rollover process is managed by ILM that increments our indices united by the rollover_alias
and distributes the log data to the latest index.
It is also possible to manage index lifecycle without rollover indicated in the policy. If this is the case, this section will explain how to refactor the index to make it look that way: fluent-bit-kube-2023.03.18
.
Note
The main drawback of this method is that the indices can be managed only by their creation date.
To manage index lifecycle without rollover policy, follow the steps below:
Create a Policy without rollover
but with indices deletion:
PUT _ilm/policy/fluent-bit-policy\n{\n \"policy\": {\n \"phases\": {\n \"hot\": {\n \"min_age\": \"0ms\",\n \"actions\": {\n \"set_priority\": {\n \"priority\": 100\n }\n }\n },\n \"delete\": {\n \"min_age\": \"7d\",\n \"actions\": {\n \"delete\": {\n \"delete_searchable_snapshot\": true\n }\n }\n }\n }\n }\n}\n
Create an index template with the rollover_alias
parameter:
PUT /_index_template/fluent-bit\n{\n \"index_patterns\": [\"fluent-bit-kube-*\"],\n \"template\": {\n \"settings\": {\n \"index\": {\n \"lifecycle\": {\n \"name\": \"fluent-bit-policy\",\n \"rollover_alias\": \"fluent-bit-kube\"\n },\n \"number_of_shards\": \"1\",\n \"number_of_replicas\": \"0\"\n }\n }\n }\n}\n
Change the Fluent Bit [OUTPUT]
config to this one:
[OUTPUT]\n Name es\n Match kube.*\n Host elasticsearch-master\n Port 9200\n HTTP_User ${ES_USER}\n HTTP_Passwd ${ES_PASSWORD}\n Logstash_Format On\n Logstash_Prefix fluent-bit-kube\n Logstash_DateFormat %Y.%m.%d\n Time_Key @timestamp\n Type flb_type\n Replace_Dots On\n Retry_Limit False\n Trace_Error On\n
Restart Fluent Bit pods.
Fluent Bit will be producing a new index every day with the new date in its name like in the fluent-bit-kube-2023.03.18
name. Index deleting will be performed according to the policy.
If you experience a lot of difficulties when dealing with Fluent Bit, this section may help you.
Fluent Bit has docker images labelled -debug
, e.g., cr.fluentbit.io/fluent/fluent-bit:2.0.9-debug
.
Change that image in the Kubernetes Fluent Bit DaemonSet and add the Trace_Error On
parameter to the [OUTPUT]
section in the Fluent Bit configmap:
[OUTPUT]\n Trace_Error On\n
After adding the parameter above, you will start seeing more informative logs that will probably help you find out the reason of the problem.
"},{"location":"operator-guide/kibana-ilm-rollover/#related-articles","title":"Related Articles","text":"Make sure the cluster meets the following conditions:
Kubernetes cluster is installed with minimum 2 worker nodes with total capacity 8 Cores and 32Gb RAM.
Machine with kubectl is installed with a cluster-admin access to the Kubernetes cluster.
Ingress controller is installed in a cluster, for example ingress-nginx.
Ingress controller is configured with the disabled HTTP/2 protocol and header size of 64k support.
Find below an example of the Config Map for the NGINX Ingress controller:
kind: ConfigMap\napiVersion: v1\nmetadata:\n name: nginx-configuration\n namespace: ingress-nginx\n labels:\n app.kubernetes.io/name: ingress-nginx\n app.kubernetes.io/part-of: ingress-nginx\ndata:\n client-header-buffer-size: 64k\n large-client-header-buffers: 4 64k\n use-http2: \"false\"\n
Load balancer (if any exists in front of the Ingress controller) is configured with session stickiness, disabled HTTP/2 protocol and header size of 32k support.
Cluster nodes and pods have access to the cluster via external URLs. For instance, add in AWS the VPC NAT gateway elastic IP to the cluster external load balancers security group).
Keycloak instance is installed. To get accurate information on how to install Keycloak, please refer to the Install Keycloak instruction.
Helm 3.10 or higher is installed on the installation machine with the help of the Installing Helm instruction.
Storage classes are used with the Retain Reclaim Policy and Delete Reclaim Policy.
We recommended using our storage class as default storage class.
Info
By default, EDP uses the default Storage Class in a cluster. The EDP development team recommends using the following Storage Classes. See an example below.
Storage class templates with the Retain and Delete Reclaim Policies:
ebs-scgp3gp3-retainapiVersion: storage.k8s.io/v1\nkind: StorageClass\nmetadata:\n name: ebs-sc\n annotations:\n storageclass.kubernetes.io/is-default-class: 'true'\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Retain\nvolumeBindingMode: Immediate\n
kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: gp3\n annotations:\n storageclass.kubernetes.io/is-default-class: 'true'\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Delete\nvolumeBindingMode: Immediate\nallowVolumeExpansion: true\n
kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: gp3-retain\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Retain\nvolumeBindingMode: Immediate\nallowVolumeExpansion: true\n
Logsight can be integrated with the CI/CD pipeline. It connects to log data sources, analyses collected logs, and evaluates deployment risk scores.
"},{"location":"operator-guide/logsight-integration/#overview","title":"Overview","text":"In order to understand if a microservice or a component is ready for the deployment, EDP suggests analyzing logs via Logsight to decide if the deployment is risky or not.
Please find more about Logsight in the official documentation:
Integration with Logsight allows enhancing and optimizing software releases by creating an additional quality gate.
Logsight can be configured in two ways:
To work with Logsight, a new Deployment Risk stage must be added to the pipeline. On this stage, the logs are analyzed with the help of Logsight mechanisms.
On the verification screen of Logsight, continuous verification of the application deployment can be monitored, and tests can be compared for detecting test flakiness.
For example, two versions of a microservice can be compared in order to detect critical differences. Risk score will be calculated for the state reached by version A and version B. Afterwards, the deployment risk will be calculated based on individual risk scores.
If the deployment failure risk is greater than a predefined threshold, the verification gate blocks the deployment from going to the target environment. In such case, the Deployment Risk stage of the pipeline is not passed, and additional attention is required. The exact log messages can be displayed in the Logsight verification screen, to help debug the problem.
"},{"location":"operator-guide/logsight-integration/#use-logsight-for-edp-development","title":"Use Logsight for EDP Development","text":"Please find below the detailed description of Logsight integration with EDP.
"},{"location":"operator-guide/logsight-integration/#deployment-approach","title":"Deployment Approach","text":"EDP uses Logsight in a self-deploying mode.
Logsight provides a deployment approach using Helm charts. Please find below the stack of components that must be deployed:
logsight
\u00a0- the core component.logsight-backend
\u00a0- the backend that provides all necessary APIs and user management.logsight-frontend
\u00a0- the frontend that provides the user interface.logsight-result-api
\u00a0- responsible for obtaining results, for example, during the verification.Below is a diagram of interaction when integrating the components:
Logsight Structure
"},{"location":"operator-guide/logsight-integration/#configure-fluentbit-for-sending-log-data","title":"Configure FluentBit for Sending Log Data","text":"Logsight is integrated with the EDP logging stack. The integration is based on top of the EFK (ElasticSearch-FluentBit-Kibana) stack. It is necessary to deploy a stack with the security support, namely, enable the certificate support.
A FluentBit config indicates the namespace from which the logs will be received for further analysis. Below is an example of the FluentBit config for getting logs from the edp-delivery-edp-delivery-sit
namespace:
[INPUT]\n Name tail\n Tag kube.sit.*\n Path /var/log/containers/*edp-delivery-edp-delivery-sit*.log\n Parser docker\n Mem_Buf_Limit 5MB\n Skip_Long_Lines Off\n Refresh_Interval 10\n\n[FILTER]\n Name kubernetes\n Match kube.sit.*\n Kube_URL https://kubernetes.default.svc:443\n Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\n Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token\n Kube_Tag_Prefix kube.sit.var.log.containers.\n Merge_Log Off\n K8S-Logging.Parser On\n K8S-Logging.Exclude On\n\n[FILTER]\n Name nest\n Match kube.sit.*\n Operation lift\n Nested_under kubernetes\n Add_prefix kubernetes.\n\n[FILTER]\n Name modify\n Match kube.sit.*\n Copy kubernetes.container_name tags.container\n Copy log message\n Copy kubernetes.container_image tags.image\n Copy kubernetes.namespace_name tags.namespace\n\n[FILTER]\n Name nest\n Match kube.sit.*\n Operation nest\n Wildcard kubernetes.*\n Nested_under kubernetes\n Remove_prefix kubernetes.\n\n[OUTPUT]\n Name es\n Match kube.sit.*\n Host elasticsearch-master\n Port 9200\n HTTP_User elastic\n HTTP_Passwd *****\n Logstash_Format On\n Logstash_Prefix sit\n Time_Key @timestamp\n Type flb_type\n Replace_Dots On\n Retry_Limit False\n\n[OUTPUT]\n Match kube.sit.*\n Name http\n Host logsight-backend\n Port 8080\n http_User logsight@example.com\n http_Passwd *****\n uri /api/v1/logs/singles\n Format json\n json_date_format iso8601\n json_date_key timestamp\n
"},{"location":"operator-guide/logsight-integration/#deployment-risk-analysis","title":"Deployment Risk Analysis","text":"A deployment-risk
stage is added to the EDP CD pipeline.
Deployment Risk
If the deployment risk is above 70%, the red state of the pipeline is expected.
EDP consists of a set of containerized components. For the convenience of tracking the risk deployment trend for each component, this data is stored as Jenkins artifacts.
If the deployment risk is higher than the threshold of 70%, the EDP promotion of artifacts for the next environments does not pass. The deployment risk report can be analyzed in order to avoid the potential problems with updating the components.
To study the report in detail, use the link from the Jenkins pipeline to the Logsight verification screen:
Logsight Insights Logsight Insights
In this example, logs from different versions of the gerrit-operator
were analyzed. As can be seen from the report, a large number of new messages appeared in the logs, and the output frequency of other notifications has also changed, which led to the high deployment risk.
The environment on which the analysis is performed can exist for different time periods. Logsight only processes the minimum total number of logs since the creating of the environment.
"},{"location":"operator-guide/logsight-integration/#related-articles","title":"Related Articles","text":"Note
Make sure that IRSA is enabled and amazon-eks-pod-identity-webhook is deployed according to the Associate IAM Roles With Service Accounts documentation.
It is possible to use Amazon Simple Storage Service Amazon S3 as object storage for Loki. In this case Loki requires access to AWS resources. Follow the steps below to create a required role:
Create AWS IAM Policy \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki_policy\":
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ListObjects\",\n \"s3:ListBucket\",\n \"s3:PutObject\",\n \"s3:GetObject\",\n \"s3:DeleteObject\"\n ],\n \"Resource\": [\n \"arn:aws:s3:::loki-*\"\n ]\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ListBucket\"\n ],\n \"Resource\": [\n \"arn:aws:s3:::loki-*\"\n ]\n }\n ]\n}\n
Create AWS IAM Role \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki\" with trust relationships:
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER>\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"<OIDC_PROVIDER>:sub\": \"system:serviceaccount:<LOKI_NAMESPACE>:edp-loki\"\n }\n }\n }\n ]\n}\n
Attach the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki_policy\" policy to the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki\" role.
Make sure that Amazon S3 bucket with name loki-\u2039CLUSTER_NAME\u203a exists.
Provide key value eks.amazonaws.com/role-arn: \"arn:aws:iam:::role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039LOKI_NAMESPACE\u203aLoki\" into the serviceAccount.annotations parameter in values.yaml during the Loki Installation.
Familiarize yourself with the detailed instructions on adding certificates to EDP resources as well as with the respective setup for Keycloak.
EDP components that support custom certificates can be found in the table below:
Helm Chart Sub Resources admin-console-operator admin-console gerrit-operator edp-gerrit jenkins-operator jenkins-operator, edp-jenkins, jenkins agents sonar-operator sonar-operator, edp-sonar keycloak-operator keycloak-operator nexus-operator oauth2-proxy edp-install oauth2-proxy edp-headlamp edp-headlamp"},{"location":"operator-guide/manage-custom-certificate/#prerequisites","title":"Prerequisites","text":"*.crt
format is used;keytool
command inside;To import custom certificates to Keycloak, follow the steps below:
Generate the cacerts
local keystore and import the certificate there using the keytool tool:
keytool -importcert -file CA.crt \\\n -alias CA.crt -keystore ./cacerts \\\n -storepass changeit -trustcacerts \\\n -noprompt\n
Create the custom-keycloak-keystore
keystore secret from the cacerts
file in the security
namespace:
kubectl -n security create secret generic custom-keycloak-keystore \\\n--from-file=./cacerts\n
Create the spi-truststore-data
SPI truststore secret in the security
namespace:
kubectl -n security create secret generic spi-truststore-data \\\n--from-literal=KC_SPI_TRUSTSTORE_FILE_FILE=/opt/keycloak/spi-certs/cacerts \\\n--from-literal=KC_SPI_TRUSTSTORE_FILE_PASSWORD=changeit\n
Update the Keycloak values.yaml
file from the Install Keycloak page.
...\nextraVolumeMounts: |\n ...\n # Use the Keycloak truststore for SPI connection over HTTPS/TLS\n - name: spi-certificates\n mountPath: /opt/keycloak/spi-certs\n readOnly: true\n ...\n\nextraVolumes: |\n ...\n # Use the Keycloak truststore for SPI connection over HTTPS/TLS\n - name: spi-certificates\n secret:\n secretName: custom-keycloak-keystore\n defaultMode: 420\n ...\n\n...\nextraEnvFrom: |\n - secretRef:\n name: spi-truststore-data\n...\n
Creating custom certificates is a necessary but not sufficient condition for applying, therefore, certificates should be enabled as well.
Create the custom-ca-certificates
secret in the EDP namespace.
kubectl -n edp create secret generic custom-ca-certificates \\\n--from-file=CA.crt\n
Add the certificate by mounting the custom-ca-certificates
secret to the operator pod as a volume.
Example of specifying custom certificates for the keycloak-operator
:
...\nkeycloak-operator:\n enabled: true\n\n # -- Additional volumes to be added to the pod\n extraVolumes:\n - name: custom-ca\n secret:\n defaultMode: 420\n secretName: custom-ca-certificates\n\n # -- Additional volumeMounts to be added to the container\n extraVolumeMounts:\n - name: custom-ca\n mountPath: /etc/ssl/certs/CA.crt\n readOnly: true\n subPath: CA.crt\n...\n
Note
Before moving ahead, be aware that starting from version 3.3.0, our development team has officially deprecated the Jenkins deploy scenario. This means that as of version 3.3.0 and in all subsequent versions (3.3.x and above), the Jenkins deploy scenario is no longer supported or actively maintained. For users running versions 3.3.x and below, the Jenkins deploy scenario remains available. However, we encourage you to plan for the transition to a supported deployment method to ensure continued compatibility and access to the latest features and enhancements. To perform migration, please familiarize yourself with the Migrate CI Pipelines From Jenkins to Tekton. For those who still use EDP v3.3.x and below, the information below remains valid and applicable.
For Sonar, Jenkins and Gerrit, change the flag in the caCerts.enabled
field to true
. Also, change the name of the secret in the caCerts.secret
field to custom-ca-certificates
.
Example of specifying custom certificates for Gerrit
via the gerrit-operator
helm chart values:
...\ngerrit-operator:\n enabled: true\n gerrit:\n caCerts:\n # -- Flag for enabling additional CA certificates\n enabled: true\n # -- Change init CA certificates container image\n image: adoptopenjdk/openjdk11:alpine\n # -- Name of the secret containing additional CA certificates\n secret: custom-ca-certificates\n...\n
This section describes how to add custom certificates to Jenkins agents to use them from Java applications.
Info
For example, curl
doesn't use keystore files specified in this part of the documentation.
EDP Jenkins agents keep keystore files in two places:
/etc/ssl/certs/java
folder with the cacerts
file;/opt/java/openjdk/lib/security
folder with the blocked.certs
, cacerts
, default.policy
and public_suffix_list.dat
files.Copy the files in /etc/ssl/certs/java
and /opt/java/openjdk/lib/security
directories from Jenkins agent pod to the local tmp
folder. There is a copy_certs.sh
script below that can manage this. It copies the files in /etc/ssl/certs/java
and /opt/java/openjdk/lib/security
directories from Jenkins agent pod to the local tmp
folder and imports the custom certificate into the keystore files, after which it creates the jenkins-agent-opt-java-openjdk-lib-security-cacerts
and jenkins-agent-etc-ssl-certs-java-cacerts
secrets from updated keystore files in EDP namespace. Also, the jenkins-agent-opt-java-openjdk-lib-security-cacerts
secret contains three additional files: blocked.certs
, default.policy
and public_suffix_list.dat
which managed by the copy_certs.sh
script as well. Expand the drop-down button below to see the contents of the copy_certs.sh
script.
# Fill in the variables `ns` and `ca_file`\nns=\"edp-project\"\nca_file=\"/tmp/CA.crt\"\n\nimages=$(kubectl get -n \"${ns}\" cm jenkins-slaves -ojson | jq -r \".data[]\" | grep image\\> | sed 's/\\s*<.*>\\(.*\\)<.*>/\\1/')\n\nimage=$(for i in ${images[@]}; do echo $i; done | grep maven-java8)\npod_name=$(echo \"${image}\" | tr '.:/' '-')\n\noverrides=\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"kind\\\":\\\"Pod\\\",\\\"metadata\\\":{\\\"name\\\":\\\"${pod_name}\\\", \\\"namespace\\\": \\\"${ns}\\\"},\n\\\"spec\\\":{\\\"containers\\\":[{\\\"name\\\":\\\"${pod_name}\\\",\\\"image\\\":\\\"${image}\\\",\n\\\"command\\\":[\\\"sh\\\",\\\"-c\\\",\\\"while true;do sleep 30;done;\\\"]}]}}\"\n\nkubectl run -n \"${ns}\" \"${pod_name}\" --image \"${image}\" --overrides=\"${overrides}\"\n\nkubectl wait --for=condition=ready pod \"${pod_name}\" -n \"${ns}\"\n\ncacerts_location=$(kubectl exec -n \"${ns}\" \"${pod_name}\" \\\n -- find / -name cacerts -exec ls -la \"{}\" \\; 2>/dev/null | grep -v ^l | awk '{print $9}')\n\nfor cacerts in ${cacerts_location[@]}; do echo $(dirname \"${cacerts}\"); kubectl exec -n \"${ns}\" \"${pod_name}\" -- ls $(dirname \"${cacerts}\"); done\n\nfor cacerts in ${cacerts_location[@]}; do \\\n echo $(dirname \"${cacerts}\"); \\\n mkdir -p \"/tmp$(dirname \"${cacerts}\")\"; \\\n from_files=''; \\\n for file in $(kubectl exec -n \"${ns}\" \"${pod_name}\" -- ls $(dirname \"${cacerts}\")); do \\\n kubectl exec -n \"${ns}\" \"${pod_name}\" -- cat \"$(dirname \"${cacerts}\")/${file}\" > \"/tmp$(dirname \"${cacerts}\")/${file}\"; \\\n from_files=\"${from_files} --from-file=/tmp$(dirname \"${cacerts}\")/${file}\"\n done ; \\\n keytool -import -storepass changeit -alias kubernetes -file ${ca_file} -noprompt -keystore \"/tmp${cacerts}\"; \\\n kubectl -n \"${ns}\" create secret generic \"jenkins-agent${cacerts//\\//-}\" $from_files \\\ndone\n\nkubectl delete -n \"${ns}\" pod \"${pod_name}\" --force --grace-period=0\n
Before using the copy_certs.sh
script, keep in mind the following:
ns
and ca_file
;jenkins-slaves
ConfigMap and uses the image of the maven-java8
agent as the base image of the temporary pod to get the keystore files;keytool
application;jenkins-agent-opt-java-openjdk-lib-security-cacerts
and jenkins-agent-etc-ssl-certs-java-cacerts
secrets will be created in the EDP namespace.Run the copy_certs.sh
script from the previous point after the requirements are met.
Update manually the jenkins-slaves
ConfigMap.
Add this block with the mount of secrets to the <volumes></volumes>
block of each Jenkins agent:
...\n <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <mountPath>/etc/ssl/certs/java</mountPath>\n <secretName>jenkins-agent-etc-ssl-certs-java-cacerts</secretName>\n </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <mountPath>/opt/java/openjdk/lib/security</mountPath>\n <secretName>jenkins-agent-opt-java-openjdk-lib-security-cacerts</secretName>\n </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n...\n
As an example, the template of gradle-java11-template
is shown below:
...\n </workspaceVolume>\n <volumes>\n <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <mountPath>/etc/ssl/certs/java</mountPath>\n <secretName>jenkins-agent-etc-ssl-certs-java-cacerts</secretName>\n </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n <mountPath>/opt/java/openjdk/lib/security</mountPath>\n <secretName>jenkins-agent-opt-java-openjdk-lib-security-cacerts</secretName>\n </org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>\n </volumes>\n <containers>\n...\n
Reload the Jenkins pod:
ns=\"edp\"\nkubectl rollout restart -n \"${ns}\" deployment/jenkins\n
The Jenkins CD job provisioner (or seed-job) is used to create and manage the cd-pipeline folder, and its Deploy pipelines. There is a special job-provisions/cd folder in Jenkins for these provisioners. Explore the steps for managing different provisioner types below.
"},{"location":"operator-guide/manage-jenkins-cd-job-provision/#default","title":"Default","text":"During the EDP deployment, a default provisioner is created to deploy application with container and custom deployment type.
Find the configuration in job-provisions/cd/default.
Default template is presented below:
View: Default template/* Copyright 2022 EPAM Systems.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nimport groovy.json.*\nimport jenkins.model.Jenkins\n\nJenkins jenkins = Jenkins.instance\n\ndef pipelineName = \"${PIPELINE_NAME}-cd-pipeline\"\ndef stageName = \"${STAGE_NAME}\"\ndef qgStages = \"${QG_STAGES}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID}\"\ndef sourceType = \"${SOURCE_TYPE}\"\ndef libraryURL = \"${LIBRARY_URL}\"\ndef libraryBranch = \"${LIBRARY_BRANCH}\"\ndef isAutoDeploy = \"${AUTODEPLOY}\"\ndef scriptPath = \"Jenkinsfile\"\ndef containerDeploymentType = \"container\"\ndef deploymentType = \"${DEPLOYMENT_TYPE}\"\ndef codebaseFolder = jenkins.getItem(pipelineName)\n\ndef autoDeploy = '{\"name\":\"auto-deploy-input\",\"step_name\":\"auto-deploy-input\"}'\ndef manualDeploy = '{\"name\":\"manual-deploy-input\",\"step_name\":\"manual-deploy-input\"}'\ndef runType = isAutoDeploy.toBoolean() ? autoDeploy : manualDeploy\n\ndef stages = buildStages(deploymentType, containerDeploymentType, qgStages, runType)\n\nif (codebaseFolder == null) {\n folder(pipelineName)\n}\n\nif (deploymentType == containerDeploymentType) {\n createContainerizedCdPipeline(pipelineName, stageName, stages, scriptPath, sourceType,\n libraryURL, libraryBranch, gitCredentialsId, gitServerCrVersion,\n isAutoDeploy)\n} else {\n createCustomCdPipeline(pipelineName, stageName)\n}\n\ndef buildStages(deploymentType, containerDeploymentType, qgStages, runType) {\n return deploymentType == containerDeploymentType\n ? '[{\"name\":\"init\",\"step_name\":\"init\"},' + runType + ',{\"name\":\"deploy\",\"step_name\":\"deploy\"},' + qgStages + ',{\"name\":\"promote-images\",\"step_name\":\"promote-images\"}]'\n : ''\n}\n\ndef createContainerizedCdPipeline(pipelineName, stageName, stages, pipelineScript, sourceType, libraryURL, libraryBranch, libraryCredId, gitServerCrVersion, isAutoDeploy) {\n pipelineJob(\"${pipelineName}/${stageName}\") {\n if (sourceType == \"library\") {\n definition {\n cpsScm {\n scm {\n git {\n remote {\n url(libraryURL)\n credentials(libraryCredId)\n }\n branches(\"${libraryBranch}\")\n scriptPath(\"${pipelineScript}\")\n }\n }\n }\n }\n } else {\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\nDeploy()\")\n sandbox(true)\n }\n }\n }\n properties {\n disableConcurrentBuilds()\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${stages}\", \"Consequence of stages in JSON format to be run during execution\")\n\n if (isAutoDeploy?.trim() && isAutoDeploy.toBoolean()) {\n stringParam(\"CODEBASE_VERSION\", null, \"Codebase versions to deploy.\")\n }\n }\n }\n}\n\ndef createCustomCdPipeline(pipelineName, stageName) {\n pipelineJob(\"${pipelineName}/${stageName}\") {\n properties {\n disableConcurrentBuilds()\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n }\n }\n}\n
In some cases, it is necessary to modify or update the job provisioner logic. For example, when adding a new stage requires a custom job provisioner created on the basis of an existing one out of the box. Take the steps below to add a custom job provision.
Navigate to the Jenkins main page and open the job-provisions/cd folder, click New Item and type the name of job provisions, for example - custom.
CD provisioner name
Scroll down to the Copy from field, enter \"/job-provisions/cd/default\", and click OK: Copy CD provisioner
Update the required parameters in the new provisioner. For example, if it is necessary to implement a new stage clean, add the following code to the provisioner:
def buildStages(deploymentType, containerDeploymentType, qgStages) {\n return deploymentType == containerDeploymentType\n ? '[{\"name\":\"init\",\"step_name\":\"init\"},{\"name\":\"clean\",\"step_name\":\"clean\"},{\"name\":\"deploy\",\"step_name\":\"deploy\"},' + qgStages + ',{\"name\":\"promote-images-ecr\",\"step_name\":\"promote-images\"}]'\n : ''\n }\n
Note
Make sure the support for the above mentioned logic is implemented. Please refer to the How to Redefine or Extend the EDP Pipeline Stages Library section of the guide.
After the steps above are performed, the new custom job-provision will be available in Adding Stage during the CD pipeline creation in Admin Console.
Custom CD provision
The Jenkins CI job provisioner (or seed-job) is used to create and manage the application folder, and its Code Review, Build and Create Release pipelines. Depending on the version control system, different job provisioners are used. EDP supports integration with the following version control systems:
By default, the Jenkins operator creates a pipeline for several types of application and libraries. There is a special job-provisions/ci folder in Jenkins for these provisioners. During the EDP deployment, a default provisioner is created for integration with Gerrit version control system. To configure integration with other version control systems, you need to add the required job provisioners to job-provisions/ci folder in Jenkins.
"},{"location":"operator-guide/manage-jenkins-ci-job-provision/#create-custom-provisioner-custom-defaultgithubgitlab","title":"Create Custom Provisioner (custom-default/github/gitlab)","text":"In some cases it is necessary to modify or update the job provisioner logic, for example when an added other code language needs to create a custom job provisioner on the basis of an existing one out of the box. Take the steps below to add a custom job provision:
Navigate to the Jenkins main page and open the job-provisions/ci folder, click New Item and type the name of job-provisions, for example - custom-github.
CI provisioner name
Scroll down to the Copy from field and enter \"/job-provisions/ci/github\", and click OK: Copy ci provisioner
Update the required parameters in the new provisioner. For example, if it is necessary to implement a new build tool docker, several parameters are to be updated. Add the following stages to the docker Code Review and Build pipelines for docker application:
stages['Code-review-application-docker'] = '[{\"name\": \"checkout\"},{\"name\": \"lint\"},{\"name\": \"build\"}]'\n...\nstages['Build-application-docker'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"lint\"},{\"name\": \"build\"},{\"name\": \"push\"},{\"name\": \"git-tag\"}]'\n...\ndef getStageKeyName(buildTool) {\n ...\n if (buildTool.toString().equalsIgnoreCase('docker')) {\n return \"Code-review-application-docker\"\n }\n ...\n}\n
Note
Make sure the support for the above mentioned logic is implemented. Please refer to the How to Redefine or Extend the EDP Pipeline Stages Library section of the guide.
Note
The default template should be changed if there is another creation logic for the Code Review, Build and Create Release pipelines. Furthermore, all pipeline types should have the necessary stages as well.
After the steps above are performed, the new custom job provision will be available in Advanced Settings during the application creation in the EDP Portal UI:
Custom ci provision
During the EDP deployment, a default provisioner is created for integration with Gerrit version control system.
Find the configuration in job-provisions/ci/default.
Default template is presented below:
View: Default template/* Copyright 2022 EPAM Systems.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nimport groovy.json.*\nimport jenkins.model.Jenkins\n\nJenkins jenkins = Jenkins.instance\ndef stages = [:]\ndef jiraIntegrationEnabled = Boolean.parseBoolean(\"${JIRA_INTEGRATION_ENABLED}\" as String)\ndef commitValidateStage = jiraIntegrationEnabled ? ',{\"name\": \"commit-validate\"}' : ''\ndef createJIMStage = jiraIntegrationEnabled ? ',{\"name\": \"create-jira-issue-metadata\"}' : ''\ndef platformType = \"${PLATFORM_TYPE}\"\ndef buildStage = platformType.toString() == \"kubernetes\" ? ',{\"name\": \"build-image-kaniko\"}' : ',{\"name\": \"build-image-from-dockerfile\"}'\ndef buildTool = \"${BUILD_TOOL}\"\ndef goBuildStage = buildTool.toString() == \"go\" ? ',{\"name\": \"build\"}' : ',{\"name\": \"compile\"}'\n\nstages['Code-review-application'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + goBuildStage +\n ',{\"name\": \"tests\"},[{\"name\": \"sonar\"},{\"name\": \"dockerfile-lint\"},{\"name\": \"helm-lint\"}]]'\nstages['Code-review-library'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"compile\"},{\"name\": \"tests\"},{\"name\": \"sonar\"}]'\nstages['Code-review-autotests'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"},{\"name\": \"sonar\"}' + ']'\nstages['Code-review-default'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + ']'\nstages['Code-review-library-terraform'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"terraform-lint\"}]'\nstages['Code-review-library-opa'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"}]'\nstages['Code-review-library-codenarc'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}]'\nstages['Code-review-library-kaniko'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"dockerbuild-verify\"}]'\n\nstages['Build-library-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-npm'] = stages['Build-library-maven']\nstages['Build-library-gradle'] = stages['Build-library-maven']\nstages['Build-library-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"terraform-lint\"}' +\n ',{\"name\": \"terraform-plan\"},{\"name\": \"terraform-apply\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-opa'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"tests\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-codenarc'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-kaniko\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-autotests-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-autotests-gradle'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-application-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-npm'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-gradle'] = stages['Build-application-maven']\nstages['Build-application-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-go'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"tests\"}' +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"}' +\n \"${buildStage}\" + ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Create-release'] = '[{\"name\": \"checkout\"},{\"name\": \"create-branch\"},{\"name\": \"trigger-job\"}]'\n\ndef defaultBuild = '[{\"name\": \"checkout\"}' + \"${createJIMStage}\" + ']'\n\ndef codebaseName = \"${NAME}\"\ndef gitServerCrName = \"${GIT_SERVER_CR_NAME}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}\"\ndef repositoryPath = \"${REPOSITORY_PATH}\"\ndef defaultBranch = \"${DEFAULT_BRANCH}\"\n\ndef codebaseFolder = jenkins.getItem(codebaseName)\nif (codebaseFolder == null) {\n folder(codebaseName)\n}\n\ncreateListView(codebaseName, \"Releases\")\ncreateReleasePipeline(\"Create-release-${codebaseName}\", codebaseName, stages[\"Create-release\"], \"CreateRelease\",\n repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch)\n\nif (buildTool.toString().equalsIgnoreCase('none')) {\n return true\n}\n\nif (BRANCH) {\n def branch = \"${BRANCH}\"\n def formattedBranch = \"${branch.toUpperCase().replaceAll(/\\//, \"-\")}\"\n createListView(codebaseName, formattedBranch)\n\n def type = \"${TYPE}\"\n def crKey = getStageKeyName(buildTool)\n createCiPipeline(\"Code-review-${codebaseName}\", codebaseName, stages[crKey], \"CodeReview\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n def buildKey = \"Build-${type}-${buildTool.toLowerCase()}\".toString()\n if (type.equalsIgnoreCase('application') || type.equalsIgnoreCase('library') || type.equalsIgnoreCase('autotests')) {\n def jobExists = false\n if(\"${formattedBranch}-Build-${codebaseName}\".toString() in Jenkins.instance.getAllItems().collect{it.name})\n jobExists = true\n\n createCiPipeline(\"Build-${codebaseName}\", codebaseName, stages.get(buildKey, defaultBuild), \"Build\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n if(!jobExists)\n queue(\"${codebaseName}/${formattedBranch}-Build-${codebaseName}\")\n }\n}\n\ndef createCiPipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId, watchBranch, gitServerCrName, gitServerCrVersion) {\n pipelineJob(\"${codebaseName}/${watchBranch.toUpperCase().replaceAll(/\\//, \"-\")}-${pipelineName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n triggers {\n gerrit {\n events {\n if (pipelineName.contains(\"Build\"))\n changeMerged()\n else\n patchsetCreated()\n }\n project(\"plain:${codebaseName}\", [\"plain:${watchBranch}\"])\n }\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n stringParam(\"BRANCH\", \"${watchBranch}\", \"Branch to build artifact from\")\n }\n }\n }\n}\n\ndef getStageKeyName(buildTool) {\n if (buildTool.toString().equalsIgnoreCase('terraform')) {\n return \"Code-review-library-terraform\"\n }\n if (buildTool.toString().equalsIgnoreCase('opa')) {\n return \"Code-review-library-opa\"\n }\n if (buildTool.toString().equalsIgnoreCase('codenarc')) {\n return \"Code-review-library-codenarc\"\n }\n if (buildTool.toString().equalsIgnoreCase('kaniko')) {\n return \"Code-review-library-kaniko\"\n }\n def buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n return supBuildTool ? \"Code-review-${TYPE}\" : \"Code-review-default\"\n}\n\ndef createReleasePipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId,\n gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch) {\n pipelineJob(\"${codebaseName}/${pipelineName}\") {\n logRotator {\n numToKeep(14)\n daysToKeep(30)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"STAGES\", \"${codebaseStages}\", \"\")\n if (pipelineName.contains(\"Create-release\")) {\n stringParam(\"JIRA_INTEGRATION_ENABLED\", \"${jiraIntegrationEnabled}\", \"Is Jira integration enabled\")\n stringParam(\"PLATFORM_TYPE\", \"${platformType}\", \"Platform type\")\n stringParam(\"GERRIT_PROJECT\", \"${codebaseName}\", \"\")\n stringParam(\"RELEASE_NAME\", \"\", \"Name of the release(branch to be created)\")\n stringParam(\"COMMIT_ID\", \"\", \"Commit ID that will be used to create branch from for new release. If empty, DEFAULT_BRANCH will be used\")\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"REPOSITORY_PATH\", \"${repository}\", \"Full repository path\")\n stringParam(\"DEFAULT_BRANCH\", \"${defaultBranch}\", \"Default repository branch\")\n }\n }\n }\n }\n}\n\ndef createListView(codebaseName, branchName) {\n listView(\"${codebaseName}/${branchName}\") {\n if (branchName.toLowerCase() == \"releases\") {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^Create-release.*\")\n }\n }\n } else {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^${branchName}-(Code-review|Build).*\")\n }\n }\n }\n columns {\n status()\n weather()\n name()\n lastSuccess()\n lastFailure()\n lastDuration()\n buildButton()\n }\n }\n}\n
Job Provision Pipeline Parameters
The job-provisions pipeline consists of the following parameters of type string:
To create a new job provision for work with GitHub, take the following steps:
Navigate to the Jenkins main page and open the job-provisions/ci folder.
Click New Item and type the name of job-provisions - github.
Select the Freestyle project option and click OK.
Select the Discard old builds check box and configure a few parameters:
Strategy: Log Rotation
Days to keep builds: 10
Max # of builds to keep: 10
Select the This project is parameterized check box and add a few input parameters (the type of the variables is string):
Check the Execute concurrent builds if necessary option.
Check the Restrict where this project can be run option.
Fill in the Label Expression field by typing master to ensure job runs on Jenkins Master.
In the Build section, perform the following:
DSL script check box
As soon as all the steps above are performed, insert the code:
View: Templateimport groovy.json.*\nimport jenkins.model.Jenkins\nimport javaposse.jobdsl.plugin.*\nimport com.cloudbees.hudson.plugins.folder.*\n\nJenkins jenkins = Jenkins.instance\ndef stages = [:]\ndef jiraIntegrationEnabled = Boolean.parseBoolean(\"${JIRA_INTEGRATION_ENABLED}\" as String)\ndef commitValidateStage = jiraIntegrationEnabled ? ',{\"name\": \"commit-validate\"}' : ''\ndef createJIMStage = jiraIntegrationEnabled ? ',{\"name\": \"create-jira-issue-metadata\"}' : ''\ndef platformType = \"${PLATFORM_TYPE}\"\ndef buildStage = platformType == \"kubernetes\" ? ',{\"name\": \"build-image-kaniko\"}' : ',{\"name\": \"build-image-from-dockerfile\"}'\ndef buildTool = \"${BUILD_TOOL}\"\ndef goBuildStage = buildTool.toString() == \"go\" ? ',{\"name\": \"build\"}' : ',{\"name\": \"compile\"}'\n\nstages['Code-review-application'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" + goBuildStage +\n ',{\"name\": \"tests\"},[{\"name\": \"sonar\"},{\"name\": \"dockerfile-lint\"},{\"name\": \"helm-lint\"}]]'\nstages['Code-review-library'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"compile\"},{\"name\": \"tests\"},' +\n '{\"name\": \"sonar\"}]'\nstages['Code-review-autotests'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"},{\"name\": \"sonar\"}' + ']'\nstages['Code-review-default'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" + ']'\nstages['Code-review-library-terraform'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"terraform-lint\"}]'\nstages['Code-review-library-opa'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"}]'\nstages['Code-review-library-codenarc'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}]'\nstages['Code-review-library-kaniko'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"dockerbuild-verify\"}]'\n\nstages['Build-library-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-npm'] = stages['Build-library-maven']\nstages['Build-library-gradle'] = stages['Build-library-maven']\nstages['Build-library-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"terraform-lint\"}' +\n ',{\"name\": \"terraform-plan\"},{\"name\": \"terraform-apply\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-opa'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"tests\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-codenarc'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-kaniko\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-autotests-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-autotests-gradle'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-application-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-npm'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-gradle'] = stages['Build-application-maven']\nstages['Build-application-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"}' + \"${buildStage}\" +\n ',{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-go'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"tests\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build\"}' + \"${buildStage}\" + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},{\"name\": \"tests\"},{\"name\": \"sonar\"}' +\n \"${buildStage}\" + ',{\"name\":\"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Create-release'] = '[{\"name\": \"checkout\"},{\"name\": \"create-branch\"},{\"name\": \"trigger-job\"}]'\n\ndef buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\ndef defaultStages = '[{\"name\": \"checkout\"}' + \"${createJIMStage}\" + ']'\n\ndef codebaseName = \"${NAME}\"\ndef gitServerCrName = \"${GIT_SERVER_CR_NAME}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}\"\ndef repositoryPath = \"${REPOSITORY_PATH.replaceAll(~/:\\d+\\\\//,\"/\")}\"\ndef githubRepository = \"https://${repositoryPath.split(\"@\")[1]}\"\ndef defaultBranch = \"${DEFAULT_BRANCH}\"\n\ndef codebaseFolder = jenkins.getItem(codebaseName)\nif (codebaseFolder == null) {\n folder(codebaseName)\n}\n\ncreateListView(codebaseName, \"Releases\")\ncreateReleasePipeline(\"Create-release-${codebaseName}\", codebaseName, stages[\"Create-release\"], \"CreateRelease\",\n repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch)\n\nif (buildTool.toString().equalsIgnoreCase('none')) {\n return true\n}\n\nif (BRANCH) {\n def branch = \"${BRANCH}\"\n def formattedBranch = \"${branch.toUpperCase().replaceAll(/\\\\//, \"-\")}\"\n createListView(codebaseName, formattedBranch)\n\n def type = \"${TYPE}\"\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n def crKey = getStageKeyName(buildTool).toString()\n createCodeReviewPipeline(\"Code-review-${codebaseName}\", codebaseName, stages.get(crKey, defaultStages), \"CodeReview\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, githubRepository)\n registerWebHook(repositoryPath)\n\n\n def buildKey = \"Build-${type}-${buildTool.toLowerCase()}\".toString()\n\n if (type.equalsIgnoreCase('application') || type.equalsIgnoreCase('library') || type.equalsIgnoreCase('autotests')) {\n def jobExists = false\n if(\"${formattedBranch}-Build-${codebaseName}\".toString() in Jenkins.instance.getAllItems().collect{it.name})\n jobExists = true\n createBuildPipeline(\"Build-${codebaseName}\", codebaseName, stages.get(buildKey, defaultStages), \"Build\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion, githubRepository)\n registerWebHook(repositoryPath, 'build')\n\n if(!jobExists)\n queue(\"${codebaseName}/${formattedBranch}-Build-${codebaseName}\")\n }\n}\n\ndef getStageKeyName(buildTool) {\n if (buildTool.toString().equalsIgnoreCase('terraform')) {\n return \"Code-review-library-terraform\"\n }\n if (buildTool.toString().equalsIgnoreCase('opa')) {\n return \"Code-review-library-opa\"\n }\n if (buildTool.toString().equalsIgnoreCase('codenarc')) {\n return \"Code-review-library-codenarc\"\n }\n if (buildTool.toString().equalsIgnoreCase('kaniko')) {\n return \"Code-review-library-kaniko\"\n }\n def buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n return supBuildTool ? \"Code-review-${TYPE}\" : \"Code-review-default\"\n}\n\ndef createCodeReviewPipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId, defaultBranch, gitServerCrName, gitServerCrVersion, githubRepository) {\n pipelineJob(\"${codebaseName}/${defaultBranch.toUpperCase().replaceAll(/\\\\//, \"-\")}-${pipelineName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n if (pipelineName.contains(\"Build\"))\n stringParam(\"BRANCH\", \"${defaultBranch}\", \"Branch to build artifact from\")\n else\n stringParam(\"BRANCH\", \"\\${ghprbActualCommit}\", \"Branch to build artifact from\")\n }\n }\n triggers {\n githubPullRequest {\n cron('')\n onlyTriggerPhrase(false)\n useGitHubHooks(true)\n permitAll(true)\n autoCloseFailedPullRequests(false)\n displayBuildErrorsOnDownstreamBuilds(false)\n whiteListTargetBranches([defaultBranch.toString()])\n extensions {\n commitStatus {\n context('Jenkins Code-Review')\n triggeredStatus('Build is Triggered')\n startedStatus('Build is Started')\n addTestResults(true)\n completedStatus('SUCCESS', 'Verified')\n completedStatus('FAILURE', 'Failed')\n completedStatus('PENDING', 'Penging')\n completedStatus('ERROR', 'Error')\n }\n }\n }\n }\n properties {\n githubProjectProperty {\n projectUrlStr(\"${githubRepository}\")\n }\n }\n }\n}\n\ndef createBuildPipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId, defaultBranch, gitServerCrName, gitServerCrVersion, githubRepository) {\n pipelineJob(\"${codebaseName}/${defaultBranch.toUpperCase().replaceAll(/\\\\//, \"-\")}-${pipelineName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\nnode {\\n git credentialsId: \\'${credId}\\', url: \\'${repository}\\', branch: \\'${BRANCH}\\'\\n}\\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n stringParam(\"BRANCH\", \"${defaultBranch}\", \"Branch to run from\")\n }\n }\n triggers {\n gitHubPushTrigger()\n }\n properties {\n githubProjectProperty {\n projectUrlStr(\"${githubRepository}\")\n }\n }\n }\n}\n\n\ndef createListView(codebaseName, branchName) {\n listView(\"${codebaseName}/${branchName}\") {\n if (branchName.toLowerCase() == \"releases\") {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^Create-release.*\")\n }\n }\n } else {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^${branchName}-(Code-review|Build).*\")\n }\n }\n }\n columns {\n status()\n weather()\n name()\n lastSuccess()\n lastFailure()\n lastDuration()\n buildButton()\n }\n }\n}\n\ndef createReleasePipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId,\n gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch) {\n pipelineJob(\"${codebaseName}/${pipelineName}\") {\n logRotator {\n numToKeep(14)\n daysToKeep(30)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"STAGES\", \"${codebaseStages}\", \"\")\n if (pipelineName.contains(\"Create-release\")) {\n stringParam(\"JIRA_INTEGRATION_ENABLED\", \"${jiraIntegrationEnabled}\", \"Is Jira integration enabled\")\n stringParam(\"PLATFORM_TYPE\", \"${platformType}\", \"Platform type\")\n stringParam(\"GERRIT_PROJECT\", \"${codebaseName}\", \"\")\n stringParam(\"RELEASE_NAME\", \"\", \"Name of the release(branch to be created)\")\n stringParam(\"COMMIT_ID\", \"\", \"Commit ID that will be used to create branch from for new release. If empty, DEFAULT_BRANCH will be used\")\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"REPOSITORY_PATH\", \"${repository}\", \"Full repository path\")\n stringParam(\"DEFAULT_BRANCH\", \"${defaultBranch}\", \"Default repository branch\")\n }\n }\n }\n }\n}\n\ndef registerWebHook(repositoryPath, type = 'code-review') {\n def url = repositoryPath.split('@')[1].split('/')[0]\n def owner = repositoryPath.split('@')[1].split('/')[1]\n def repo = repositoryPath.split('@')[1].split('/')[2]\n def apiUrl = 'https://api.' + url + '/repos/' + owner + '/' + repo + '/hooks'\n def webhookUrl = ''\n def webhookConfig = [:]\n def config = [:]\n def events = []\n\n if (type.equalsIgnoreCase('build')) {\n webhookUrl = System.getenv('JENKINS_UI_URL') + \"/github-webhook/\"\n events = [\"push\"]\n config[\"url\"] = webhookUrl\n config[\"content_type\"] = \"json\"\n config[\"insecure_ssl\"] = 0\n webhookConfig[\"name\"] = \"web\"\n webhookConfig[\"config\"] = config\n webhookConfig[\"events\"] = events\n webhookConfig[\"active\"] = true\n\n } else {\n webhookUrl = System.getenv('JENKINS_UI_URL') + \"/ghprbhook/\"\n events = [\"issue_comment\",\"pull_request\"]\n config[\"url\"] = webhookUrl\n config[\"content_type\"] = \"form\"\n config[\"insecure_ssl\"] = 0\n webhookConfig[\"name\"] = \"web\"\n webhookConfig[\"config\"] = config\n webhookConfig[\"events\"] = events\n webhookConfig[\"active\"] = true\n }\n\n def requestBody = JsonOutput.toJson(webhookConfig)\n def http = new URL(apiUrl).openConnection() as HttpURLConnection\n http.setRequestMethod('POST')\n http.setDoOutput(true)\n println(apiUrl)\n http.setRequestProperty(\"Accept\", 'application/json')\n http.setRequestProperty(\"Content-Type\", 'application/json')\n http.setRequestProperty(\"Authorization\", \"token ${getSecretValue('github-access-token')}\")\n http.outputStream.write(requestBody.getBytes(\"UTF-8\"))\n http.connect()\n println(http.responseCode)\n\n if (http.responseCode == 201) {\n response = new JsonSlurper().parseText(http.inputStream.getText('UTF-8'))\n } else {\n response = new JsonSlurper().parseText(http.errorStream.getText('UTF-8'))\n }\n\n println \"response: ${response}\"\n}\n\ndef getSecretValue(name) {\n def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(\n com.cloudbees.plugins.credentials.common.StandardCredentials.class,\n Jenkins.instance,\n null,\n null\n )\n\n def secret = creds.find { it.properties['id'] == name }\n return secret != null ? secret['secret'] : null\n}\n
After the steps above are performed, the new custom job-provision will be available in Advanced Settings during the application creation in the EDP Portal UI:
Github job provision
To create a new job provision for work with GitLab, take the following steps:
Navigate to the Jenkins main page and open the job-provisions/ci folder.
Click New Item and type the name of job-provisions - gitlab.
Select the Freestyle project option and click OK.
Select the Discard old builds check box and configure a few parameters:
Strategy: Log Rotation
Days to keep builds: 10
Max # of builds to keep: 10
Select the This project is parameterized check box and add a few input parameters as the following strings (the type of the variables is string):
Check the Execute concurrent builds if necessary option.
Check the Restrict where this project can be run option.
Fill in the Label Expression field by typing master to ensure job runs on Jenkins Master.
In the Build Steps section, perform the following:
DSL script check box
As soon as all the steps above are performed, insert the code:
View: Templateimport groovy.json.*\nimport jenkins.model.Jenkins\n\nJenkins jenkins = Jenkins.instance\ndef stages = [:]\ndef jiraIntegrationEnabled = Boolean.parseBoolean(\"${JIRA_INTEGRATION_ENABLED}\" as String)\ndef commitValidateStage = jiraIntegrationEnabled ? ',{\"name\": \"commit-validate\"}' : ''\ndef createJIMStage = jiraIntegrationEnabled ? ',{\"name\": \"create-jira-issue-metadata\"}' : ''\ndef platformType = \"${PLATFORM_TYPE}\"\ndef buildTool = \"${BUILD_TOOL}\"\ndef buildImageStage = platformType == \"kubernetes\" ? ',{\"name\": \"build-image-kaniko\"},' : ',{\"name\": \"build-image-from-dockerfile\"},'\ndef goBuildImageStage = platformType == \"kubernetes\" ? ',{\"name\": \"build-image-kaniko\"}' : ',{\"name\": \"build-image-from-dockerfile\"}'\ndef goBuildStage = buildTool.toString() == \"go\" ? ',{\"name\": \"build\"}' : ',{\"name\": \"compile\"}'\n\nstages['Code-review-application'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" + goBuildStage +\n ',{\"name\": \"tests\"},[{\"name\": \"sonar\"},{\"name\": \"dockerfile-lint\"},{\"name\": \"helm-lint\"}]]'\nstages['Code-review-library'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"compile\"},{\"name\": \"tests\"},' +\n '{\"name\": \"sonar\"}]'\nstages['Code-review-autotests'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"},{\"name\": \"sonar\"}' + ']'\nstages['Code-review-default'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" + ']'\nstages['Code-review-library-terraform'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"terraform-lint\"}]'\nstages['Code-review-library-opa'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"}]'\nstages['Code-review-library-codenarc'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}]'\nstages['Code-review-library-kaniko'] = '[{\"name\": \"checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"dockerbuild-verify\"}]'\n\nstages['Build-library-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-npm'] = stages['Build-library-maven']\nstages['Build-library-gradle'] = stages['Build-library-maven']\nstages['Build-library-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"terraform-lint\"}' +\n ',{\"name\": \"terraform-plan\"},{\"name\": \"terraform-apply\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-opa'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"tests\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-codenarc'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-kaniko\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-autotests-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-autotests-gradle'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\nstages['Build-application-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildImageStage}\" +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},{\"name\": \"tests\"},{\"name\": \"sonar\"}' +\n \"${buildImageStage}\" + '{\"name\":\"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-npm'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' + \"${buildImageStage}\" +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-gradle'] = stages['Build-application-maven']\nstages['Build-application-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"}' + \"${buildImageStage}\" +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"tool-init\"},' +\n '{\"name\": \"lint\"},{\"name\": \"git-tag\"}]'\nstages['Build-application-helm'] = '[{\"name\": \"checkout\"},{\"name\": \"lint\"}]'\nstages['Build-application-docker'] = '[{\"name\": \"checkout\"},{\"name\": \"lint\"}]'\nstages['Build-application-go'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sast\"},{\"name\": \"tests\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build\"}' + \"${goBuildImageStage}\" + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Create-release'] = '[{\"name\": \"checkout\"},{\"name\": \"create-branch\"},{\"name\": \"trigger-job\"}]'\n\ndef defaultStages = '[{\"name\": \"checkout\"}' + \"${createJIMStage}\" + ']'\n\n\ndef codebaseName = \"${NAME}\"\ndef gitServerCrName = \"${GIT_SERVER_CR_NAME}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitServer = \"${GIT_SERVER ? GIT_SERVER : 'gerrit'}\"\ndef gitSshPort = \"${GIT_SSH_PORT ? GIT_SSH_PORT : '29418'}\"\ndef gitUsername = \"${GIT_USERNAME ? GIT_USERNAME : 'jenkins'}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}\"\ndef defaultRepoPath = \"ssh://${gitUsername}@${gitServer}:${gitSshPort}/${codebaseName}\"\ndef repositoryPath = \"${REPOSITORY_PATH ? REPOSITORY_PATH : defaultRepoPath}\"\ndef defaultBranch = \"${DEFAULT_BRANCH}\"\n\ndef codebaseFolder = jenkins.getItem(codebaseName)\nif (codebaseFolder == null) {\n folder(codebaseName)\n}\n\ncreateListView(codebaseName, \"Releases\")\ncreateReleasePipeline(\"Create-release-${codebaseName}\", codebaseName, stages[\"Create-release\"], \"CreateRelease\",\n repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch)\n\nif (BRANCH) {\n def branch = \"${BRANCH}\"\n def formattedBranch = \"${branch.toUpperCase().replaceAll(/\\\\//, \"-\")}\"\n createListView(codebaseName, formattedBranch)\n\n def type = \"${TYPE}\"\n def crKey = getStageKeyName(buildTool).toString()\n createCiPipeline(\"Code-review-${codebaseName}\", codebaseName, stages.get(crKey, defaultStages), \"CodeReview\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n def buildKey = \"Build-${type}-${buildTool.toLowerCase()}\".toString()\n\n if (type.equalsIgnoreCase('application') || type.equalsIgnoreCase('library') || type.equalsIgnoreCase('autotests')) {\n def jobExists = false\n if(\"${formattedBranch}-Build-${codebaseName}\".toString() in Jenkins.instance.getAllItems().collect{it.name}) {\n jobExists = true\n }\n createCiPipeline(\"Build-${codebaseName}\", codebaseName, stages.get(buildKey, defaultStages), \"Build\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n if(!jobExists) {\n queue(\"${codebaseName}/${formattedBranch}-Build-${codebaseName}\")\n }\n }\n}\n\n\ndef createCiPipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId, defaultBranch, gitServerCrName, gitServerCrVersion) {\ndef jobName = \"${defaultBranch.toUpperCase().replaceAll(/\\\\//, \"-\")}-${pipelineName}\"\ndef existingJob = Jenkins.getInstance().getItemByFullName(\"${codebaseName}/${jobName}\")\ndef webhookToken = null\nif (existingJob) {\n def triggersMap = existingJob.getTriggers()\n triggersMap.each { key, value ->\n webhookToken = value.getSecretToken()\n }\n} else {\n def random = new byte[16]\n new java.security.SecureRandom().nextBytes(random)\n webhookToken = random.encodeHex().toString()\n}\npipelineJob(\"${codebaseName}/${jobName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n properties {\n gitLabConnection {\n gitLabConnection('gitlab')\n }\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n if (pipelineName.contains(\"Build\"))\n stringParam(\"BRANCH\", \"${defaultBranch}\", \"Branch to build artifact from\")\n else\n stringParam(\"BRANCH\", \"\\${gitlabMergeRequestLastCommit}\", \"Branch to build artifact from\")\n }\n }\n triggers {\n gitlabPush {\n buildOnMergeRequestEvents(pipelineName.contains(\"Build\") ? false : true)\n buildOnPushEvents(pipelineName.contains(\"Build\") ? true : false)\n enableCiSkip(false)\n setBuildDescription(true)\n rebuildOpenMergeRequest(pipelineName.contains(\"Build\") ? 'never' : 'source')\n commentTrigger(\"Build it please\")\n skipWorkInProgressMergeRequest(true)\n targetBranchRegex(\"${defaultBranch}\")\n }\n }\n configure {\n it / triggers / 'com.dabsquared.gitlabjenkins.GitLabPushTrigger' << secretToken(webhookToken)\n it / triggers / 'com.dabsquared.gitlabjenkins.GitLabPushTrigger' << triggerOnApprovedMergeRequest(pipelineName.contains(\"Build\") ? false : true)\n it / triggers / 'com.dabsquared.gitlabjenkins.GitLabPushTrigger' << pendingBuildName(pipelineName.contains(\"Build\") ? \"\" : \"Jenkins\")\n }\n}\nregisterWebHook(repository, codebaseName, jobName, webhookToken)\n}\n\ndef getStageKeyName(buildTool) {\n if (buildTool.toString().equalsIgnoreCase('terraform')) {\n return \"Code-review-library-terraform\"\n }\n if (buildTool.toString().equalsIgnoreCase('opa')) {\n return \"Code-review-library-opa\"\n }\n if (buildTool.toString().equalsIgnoreCase('codenarc')) {\n return \"Code-review-library-codenarc\"\n }\n if (buildTool.toString().equalsIgnoreCase('kaniko')) {\n return \"Code-review-library-kaniko\"\n }\n def buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n return supBuildTool ? \"Code-review-${TYPE}\" : \"Code-review-default\"\n}\n\ndef createReleasePipeline(pipelineName, codebaseName, codebaseStages, pipelineType, repository, credId,\ngitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, platformType, defaultBranch) {\n pipelineJob(\"${codebaseName}/${pipelineName}\") {\n logRotator {\n numToKeep(14)\n daysToKeep(30)\n }\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\n${pipelineType}()\")\n sandbox(true)\n }\n parameters {\n stringParam(\"STAGES\", \"${codebaseStages}\", \"\")\n if (pipelineName.contains(\"Create-release\")) {\n stringParam(\"JIRA_INTEGRATION_ENABLED\", \"${jiraIntegrationEnabled}\", \"Is Jira integration enabled\")\n stringParam(\"PLATFORM_TYPE\", \"${platformType}\", \"Platform type\")\n stringParam(\"GERRIT_PROJECT\", \"${codebaseName}\", \"\")\n stringParam(\"RELEASE_NAME\", \"\", \"Name of the release(branch to be created)\")\n stringParam(\"COMMIT_ID\", \"\", \"Commit ID that will be used to create branch from for new release. If empty, DEFAULT_BRANCH will be used\")\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"REPOSITORY_PATH\", \"${repository}\", \"Full repository path\")\n stringParam(\"DEFAULT_BRANCH\", \"${defaultBranch}\", \"Default repository branch\")\n }\n }\n }\n }\n}\n\ndef createListView(codebaseName, branchName) {\n listView(\"${codebaseName}/${branchName}\") {\n if (branchName.toLowerCase() == \"releases\") {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^Create-release.*\")\n }\n }\n } else {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^${branchName}-(Code-review|Build).*\")\n }\n }\n }\n columns {\n status()\n weather()\n name()\n lastSuccess()\n lastFailure()\n lastDuration()\n buildButton()\n }\n }\n}\n\ndef registerWebHook(repositoryPath, codebaseName, jobName, webhookToken) {\n def apiUrl = 'https://' + repositoryPath.replaceAll(\"ssh://\", \"\").split('@')[1].replace('/', \"%2F\").replaceAll(~/:\\d+%2F/, '/api/v4/projects/') + '/hooks'\n def jobWebhookUrl = \"${System.getenv('JENKINS_UI_URL')}/project/${codebaseName}/${jobName}\"\n def gitlabToken = getSecretValue('gitlab-access-token')\n\n if (checkWebHookExist(apiUrl, jobWebhookUrl, gitlabToken)) {\n println(\"[JENKINS][DEBUG] Webhook for job ${jobName} is already exist\\r\\n\")\n return\n }\n\n println(\"[JENKINS][DEBUG] Creating webhook for job ${jobName}\")\n def webhookConfig = [:]\n webhookConfig[\"url\"] = jobWebhookUrl\n webhookConfig[\"push_events\"] = jobName.contains(\"Build\") ? \"true\" : \"false\"\n webhookConfig[\"merge_requests_events\"] = jobName.contains(\"Build\") ? \"false\" : \"true\"\n webhookConfig[\"issues_events\"] = \"false\"\n webhookConfig[\"confidential_issues_events\"] = \"false\"\n webhookConfig[\"tag_push_events\"] = \"false\"\n webhookConfig[\"note_events\"] = \"true\"\n webhookConfig[\"job_events\"] = \"false\"\n webhookConfig[\"pipeline_events\"] = \"false\"\n webhookConfig[\"wiki_page_events\"] = \"false\"\n webhookConfig[\"enable_ssl_verification\"] = \"true\"\n webhookConfig[\"token\"] = webhookToken\n def requestBody = JsonOutput.toJson(webhookConfig)\n def httpConnector = new URL(apiUrl).openConnection() as HttpURLConnection\n httpConnector.setRequestMethod('POST')\n httpConnector.setDoOutput(true)\n\n httpConnector.setRequestProperty(\"Accept\", 'application/json')\n httpConnector.setRequestProperty(\"Content-Type\", 'application/json')\n httpConnector.setRequestProperty(\"PRIVATE-TOKEN\", \"${gitlabToken}\")\n httpConnector.outputStream.write(requestBody.getBytes(\"UTF-8\"))\n httpConnector.connect()\n\n if (httpConnector.responseCode == 201)\n println(\"[JENKINS][DEBUG] Webhook for job ${jobName} has been created\\r\\n\")\n else {\n println(\"[JENKINS][ERROR] Responce code - ${httpConnector.responseCode}\")\n def response = new JsonSlurper().parseText(httpConnector.errorStream.getText('UTF-8'))\n println(\"[JENKINS][ERROR] Failed to create webhook for job ${jobName}. Response - ${response}\")\n }\n}\n\ndef checkWebHookExist(apiUrl, jobWebhookUrl, gitlabToken) {\n println(\"[JENKINS][DEBUG] Checking if webhook ${jobWebhookUrl} exists\")\n def httpConnector = new URL(apiUrl).openConnection() as HttpURLConnection\n httpConnector.setRequestMethod('GET')\n httpConnector.setDoOutput(true)\n\n httpConnector.setRequestProperty(\"Accept\", 'application/json')\n httpConnector.setRequestProperty(\"Content-Type\", 'application/json')\n httpConnector.setRequestProperty(\"PRIVATE-TOKEN\", \"${gitlabToken}\")\n httpConnector.connect()\n\n if (httpConnector.responseCode == 200) {\n def response = new JsonSlurper().parseText(httpConnector.inputStream.getText('UTF-8'))\n return response.find { it.url == jobWebhookUrl } ? true : false\n }\n}\n\ndef getSecretValue(name) {\n def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(\n com.cloudbees.plugins.credentials.common.StandardCredentials.class,\n Jenkins.instance,\n null,\n null\n )\n\n def secret = creds.find { it.properties['id'] == name }\n return secret != null ? secret['secret'] : null\n}\n
After the steps above are performed, the new custom job-provision will be available in Advanced Settings during the application creation in the EDP Portal UI:
Gitlab job provision
To migrate the CI pipelines for a codebase from Jenkins to Tekton, follow the steps below:
Make sure that Tekton stack is deployed according to the documentation. Enable Tekton as an EDP subcomponent:
values.yamledp-tekton:\n enabled: true\n
"},{"location":"operator-guide/migrate-ci-pipelines-from-jenkins-to-tekton/#disable-jenkins-triggers","title":"Disable Jenkins Triggers","text":"To disable Jenkins Triggers for the codebase, add the following code to the provisioner:
job-provisionerdef tektonCodebaseList = [\"<codebase_name>\"]\nif (!tektonCodebaseList.contains(codebaseName.toString())){\n triggers {\n gerrit {\n events {\n if (pipelineName.contains(\"Build\"))\n changeMerged()\n else\n patchsetCreated()\n }\n project(\"plain:${codebaseName}\", [\"plain:${watchBranch}\"])\n }\n }\n}\n
Note
The sample above shows the usage of Gerrit VCS where the <codebase_name>
value is your codebase name.
By default, each Gerrit project inherits configuration from the All-Projects repository.
To exclude triggering in Jenkins and Tekton CI tools simultaneously, edit the configuration in the All-Projects repository or in the project which inherits rights from your project.
Edit the webhooks.config file in the refs/meta/config and remove all context from this configuration.
Warning
The clearance of the webhooks.config file will disable the pipeline trigger in Tekton.
To use Tekton pipelines, add the configuration to the corresponding Gerrit project (webhooks.config file in the refs/meta/config):
webhooks.config[remote \"changemerged\"]\n url = http://el-gerrit-listener:8080\n event = change-merged\n[remote \"patchsetcreated\"]\n url = http://el-gerrit-listener:8080\n event = patchset-created\n \n
"},{"location":"operator-guide/migrate-ci-pipelines-from-jenkins-to-tekton/#switch-ci-tool-for-codebases","title":"Switch CI Tool for Codebase(s)","text":"Go to the codebase Custom Resource and change the spec.ciTool
field from jenkins
to tekton
.
Get acquainted with the multitenant logging components and the project logs location in the Shared cluster.
"},{"location":"operator-guide/multitenant-logging/#logging-components","title":"Logging Components","text":"To configure the multitenant logging, it is necessary to deploy the following components:
In Grafana, every tenant represents an organization, i.e. it is necessary to create an organization for every namespace in the cluster. To get more details regarding the architecture of the Logging Operator, please review the Diagram 1.
Logging operator scheme
Note
It is necessary to deploy Loki with the auth_enabled: true
flag with the aim to ensure that the logs are separated for each tenant. For the authentication, Loki requires the HTTP header X-Scope-OrgID.
To find the project logs, navigate to Grafana and follow the steps below:
Note
Grafana is a common service for different customers where each customer works in its own separated Grafana Organization and doesn't have any access to another project.
Choose the organization by clicking the Current Organization drop-down list. If a user is assigned to several organizations, switch easily by using the Switch button.
Current organization
Navigate to the left-side menu and click the Explore button to see the Log Browser:
Grafana explore
Click the Log Browser button to see the labels that can be used to filter logs (e.g., hostname, namespace, application name, pod, etc.):
Note
Enable the correct data source, select the relevant logging data from the top left-side corner, and pay attention that the data source name always follows the \u2039project_name\u203a-logging pattern.
Log browser
Filter out logs by clicking the Show logs button or write the query and click the Run query button.
Review the results with the quantity of logs per time, see the example below:
Logs example
Expand logs
Addition button
Ad-hoc stat example
EDP provides the ability to deploy services to namespaces. By default, EDP creates these namespaces automatically. This chapter describes the alternative way of namespace creation and management.
"},{"location":"operator-guide/namespace-management/#overview","title":"Overview","text":"Namespaces are typically created by the platform when running CD Pipelines. The operator creates them according to the specific format: edp-<application-name>-<stage-name>
. The cd-pipeline-operator
should have the permissions to automatically create namespaces when deploying applications and delete them when uninstalling applications.
Occasionally, there are cases when automatic creation of namespaces is not allowed. For example, due to security reasons of the project, EDP user may need to disable this setting. This option is manipulated by the manageNamespace
parameter which is located in the values.yaml file. The manageNamespace
parameter is set to true
by default, but it can be changed to false. As an aftermath, after setting the manageNamespace
parameter users are supposed to face the problem that they can not deploy their application in EDP Portal UI because of permission restrictions:
Namespace creation error
The error message shown above says that user needs to create the namespace in the edp-<application-name>-<stage-name>
format first before creating stages. In addition to it, the cd-pipeline-operator
must be granted with the administrator permissions to have the ability to manage this namespace. To create namespace manually, follow the steps below:
Create the namespace by running the command below:
kubectl create namespace edp-<pipelineName>-<stageName>\n
Note
The edp-<pipelineName>-<stageName>
format for namespaces is set by default but is not mandatory. You can set your custom namespace when creating an Environment.
Create the administrator RoleBinding resource by applying the file below with the kubectl apply -f grant_admin_permissions.yaml
command:
kind: RoleBinding\n apiVersion: rbac.authorization.k8s.io/v1\n metadata:\n name: edp-cd-pipeline-operator-admin\n namespace: edp-<pipelineName>-<stageName>\n subjects:\n - kind: ServiceAccount\n name: edp-cd-pipeline-operator\n namespace: edp\n roleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: admin\n
Restart the cd-pipeline-operator pod, in order not to wait for the operator reconciliation.
The manageNamespace
parameter also defines the resources that will be created depending on the cluster deployed whether it is OpenShift or Kubernetes. This scheme displays the nesting of operator input parameters:
CD Pipeline Operator Input Parameter Scheme
Note
When deploying application on the OpenShift cluster, the registry-view
RoleBinding is created in the main namespace.
This documentation guide provides comprehensive instructions for integrating Nexus with the EPAM Delivery Platform.
Info
In EDP release 3.5, we have changed the deployment strategy for the nexus-operator component, now it is not installed by default. The nexusURL
parameter management has been transferred from the values.yaml file to Kubernetes secrets.
Before proceeding, ensure that you have the following prerequisites:
To install Nexus with pre-defined templates, use the nexus-operator installed via Cluster Add-Ons approach.
"},{"location":"operator-guide/nexus-sonatype/#configuration","title":"Configuration","text":"To ensure strong authentication and accurate access control, creating a Nexus Sonatype service account with the name ci.user is crucial. This user serves as a unique identifier, facilitating connection with the EDP ecosystem.
To create the Nexus ci.user
and define repository parameters follow the steps below:
Open the Nexus UI and navigate to Server administration and configuration
-> Security
-> User
. Click the Create local user
button to create a new user:
Nexus user settings
Type the ci-user
username, define an expiration period, and click the Generate
button to create the token:
Nexus create user
EDP relies on a predetermined repository naming convention all repository names are predefined. Navigate to Server administration and configuration
-> Repository
-> Repositories
in Nexus. You can only create a repository with the required language.
Nexus repository list
JavaJavaScriptDotnetPythona) Click Create a repository by selecting \"maven2(proxy)\" and set the name as \"edp-maven-proxy\". Enter the remote storage URL as \"https://repo1.maven.org/maven2/\". Save the configuration.
b) Click Create a repository by selecting \"maven2(hosted)\" and set the name as \"edp-maven-snapshot\". Change the Version policy to \"snapshot\". Save the configuration.
c) Click Create a repository by selecting \"maven2(hosted)\" and set the name as \"edp-maven-releases\". Change the Version policy to \"release\". Save the configuration.
d) Click Create a repository by selecting \"maven2(group)\" and set the name as \"edp-maven-group\". Change the Version policy to \"release\". Add repository to group. Save the configuration.
a) Click Create a repository by selecting \"npm(proxy)\" and set the name as \"edp-npm-proxy\". Enter the remote storage URL as \"https://registry.npmjs.org\". Save the configuration.
b) Click Create a repository by selecting \"npm(hosted)\" and set the name as \"edp-npm-snapshot\". Save the configuration.
c) Click Create a repository by selecting \"npm(hosted)\" and set the name as \"edp-npm-releases\". Save the configuration.
d) Click Create a repository by selecting \"npm(hosted)\" and set the name as \"edp-npm-hosted\". Save the configuration.
e) Click Create a repository by selecting \"npm(group)\" and set the name as \"edp-npm-group\". Add repository to group. Save the configuration.
a) Click Create a repository by selecting \"nuget(proxy)\" and set the name as \"edp-dotnet-proxy\". Select Protocol version NuGet V3. Enter the remote storage URL as \"https://api.nuget.org/v3/index.json\". Save the configuration.
b) Click Create a repository by selecting \"nuget(hosted)\" and set the name as \"edp-dotnet-snapshot\". Save the configuration.
c) Click Create a repository by selecting \"nuget(hosted)\" and set the name as \"edp-dotnet-releases\". Save the configuration.
d) Click Create a repository by selecting \"nuget(hosted)\" and set the name as \"edp-dotnet-hosted\". Save the configuration.
e) Click Create a repository by selecting \"nuget(group)\" and set the name as \"edp-dotnet-group\". Add repository to group. Save the configuration.
a) Click Create a repository by selecting \"pypi(proxy)\" and set the name as \"edp-python-proxy\". Enter the remote storage URL as \"https://pypi.org\". Save the configuration.
b) Click Create a repository by selecting \"pypi(hosted)\" and set the name as \"edp-python-snapshot\". Save the configuration.
c) Click Create a repository by selecting \"pypi(hosted)\" and set the name as \"edp-python-releases\". Save the configuration.
d) Click Create a repository by selecting \"pypi(group)\" and set the name as \"edp-python-group\". Add repository to group. Save the configuration.
Provision secrets using manifest, EDP Portal or with the externalSecrets operator
Go to EDP Portal -> EDP -> Configuration -> Nexus. Update or fill in the URL, nexus-user-id, nexus-user-password and click the Save button:
Nexus update manual secret
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-nexus\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: nexus\n app.edp.epam.com/integration-secret: \"true\"\ntype: Opaque\nstringData:\n url: https://nexus.example.com\n username: <nexus-user-id>\n password: <nexus-user-password>\n
\"ci-nexus\":\n{\n \"url\": \"https://nexus.example.com\",\n \"username\": \"XXXXXXX\",\n \"password\": \"XXXXXXX\"\n},\n
Go to EDP Portal -> EDP -> Configuration -> Nexus and see Managed by External Secret
message.
Nexus managed by external secret operator
More detail of External Secrets Operator Integration can found on the following page
"},{"location":"operator-guide/nexus-sonatype/#related-articles","title":"Related Articles","text":"This section describes how to set up and add notification status to Tekton pipelines by sending pipeline status to the Microsoft Teams channel.
"},{"location":"operator-guide/notification-msteams/#create-incoming-webhook","title":"Create Incoming WebHook","text":"To create a link to Incoming Webhook for the Microsoft Teams channel, follow the steps below:
1. Open the channel which will be receiving notifications and click the \u2022\u2022\u2022
button from the upper-right corner. Select Connectors
in the dropdown menu: Microsoft Teams menu
2. In the search field, type Incoming Webhook
and click Configure
: Connectors
3. Provide a name and upload an image for the webhook if necessary. Click Create
: Connectors setup
4. Copy and save the unique WebHookURL
presented in the dialog. Click Done
: WebHookURL
5. Create a secret with the within the edp namespace.
kubectl -n edp create secret generic microsoft-teams-webhook-url \\\n --from-literal=url=<webhookURL>\n
6. Add the notification task to the pipeline and add the code below in final-block
in the pipeline and save:
{{ include \"send-to-microsoft-teams-build\" . | nindent 4 }}\n
"},{"location":"operator-guide/notification-msteams/#customize-notification-message","title":"Customize Notification Message","text":"To make notification message informative, relevant text should be added to the message. Here are the steps to implement it:
Create a new pipeline with a unique name or modify your custom pipeline created before.
Add the task below in the finally
block with a unique name. Edit the params.message
value if necessary:
- name: 'microsoft-teams-pipeline-status-notification-failed\n params:\n - name: webhook-url-secret\n value: microsoft-teams-webhook-url\n - name: webhook-url-secret-key\n value: url\n - name: message\n value: >-\n Build Failed project: $(params.CODEBASE_NAME)<br> branch: $(params.git-source-revision)<br> pipeline: <a href=$(params.pipelineUrl)>$(context.pipelineRun.name)</a><br> commit message: $(params.COMMIT_MESSAGE)\n taskRef:\n kind: Task\n name: send-to-microsoft-teams\n when:\n - input: $(tasks.status)\n operator: in\n values:\n - Failed\n - PipelineRunTimeout\n
After customization, the following message is supposed to appear in the channel when failing pipelines:
Notification example
"},{"location":"operator-guide/notification-msteams/#related-articles","title":"Related Articles","text":"OAuth2-Proxy is a versatile tool that serves as a reverse proxy, utilizing the OAuth 2.0 protocol with various providers like Google, GitHub, and Keycloak to provide both authentication and authorization. This guide instructs readers on how to protect their applications' endpoints using OAuth2-Proxy. By following these steps, users can strengthen their endpoints' security without modifying their current application code. In the context of EDP, it has integration with the Keycloak OIDC provider, enabling it to link with any component that lacks built-in authentication.
Note
OAuth2-Proxy is disabled by default when installing EDP.
"},{"location":"operator-guide/oauth2-proxy/#prerequisites","title":"Prerequisites","text":"Enabling OAuth2-Proxy implies the following general steps:
--set 'oauth2_proxy.enabled=true'
or the --values
file by enabling the oauth2_proxy parameter.auth-signin
and auth-url
of OAuth2-Proxy to its annotation.This will deploy and connect OAuth2-Proxy to your application endpoint.
"},{"location":"operator-guide/oauth2-proxy/#enable-oauth2-proxy-on-tekton-dashboard","title":"Enable OAuth2-Proxy on Tekton Dashboard","text":"The example below illustrates how to use OAuth2-Proxy in practice when using the Tekton dashboard:
KubernetesOpenshifthelm upgrade
to update edp-install release: helm upgrade --version <version> --set 'oauth2_proxy.enabled=true' edp-install --namespace edp\n
auth-signin
and auth-url
of oauth2-proxy by kubectl
command: kubectl annotate ingress <application-ingress-name> nginx.ingress.kubernetes.io/auth-signin='https://<oauth-ingress-host>/oauth2/start?rd=https://$host$request_uri' nginx.ingress.kubernetes.io/auth-url='http://oauth2-proxy.edp.svc.cluster.local:8080/oauth2/auth'\n
tekton_dashboard_cookie_secret=$(openssl rand -base64 32 | head -c 32)\n
tekton-dashboard-proxy-cookie-secret
in the edp namespace: kubectl -n edp create secret generic tekton-dashboard-proxy-cookie-secret \\\n --from-literal=cookie-secret=${tekton_dashboard_cookie_secret}\n
helm upgrade
to update edp-install release: helm upgrade --version <version> --set 'edp-tekton.dashboard.openshift_proxy.enabled=true' edp-install --namespace edp\n
Keycloak Installation Keycloak OIDC Installation Tekton Installation
"},{"location":"operator-guide/openshift-cluster-settings/","title":"Set Up OpenShift","text":""},{"location":"operator-guide/openshift-cluster-settings/#set-up-openshift","title":"Set Up OpenShift","text":"Make sure the cluster meets the following conditions:
OpenShift cluster is installed with minimum 2 worker nodes with total capacity 8 Cores and 32Gb RAM.
Load balancer (if any exists in front of OpenShift router or ingress controller) is configured with session stickiness, disabled HTTP/2 protocol and header size of 64k support.
Find below an example of the Config Map for the NGINX Ingress Controller:
kind: ConfigMap\napiVersion: v1\nmetadata:\n name: nginx-configuration\n namespace: ingress-nginx\n labels:\n app.kubernetes.io/name: ingress-nginx\n app.kubernetes.io/part-of: ingress-nginx\ndata:\n client-header-buffer-size: 64k\n large-client-header-buffers: 4 64k\n use-http2: \"false\"\n
Cluster nodes and pods have access to the cluster via external URLs. For instance, add in AWS the VPC NAT gateway elastic IP to the cluster external load balancers security group).
Keycloak instance is installed. To get accurate information on how to install Keycloak, please refer to the Install Keycloak instruction.
The installation machine with oc is installed with the cluster-admin access to the OpenShift cluster.
Helm 3.10 is installed on the installation machine with the help of the Installing Helm instruction.
Storage classes are used with the Retain Reclaim Policy and Delete Reclaim Policy.
We recommended using our storage class as default storage class.
Info
By default, EDP uses the default Storage Class in a cluster. The EDP development team recommends using the following Storage Classes. See an example below.
Storage class templates with the Retain and Delete Reclaim Policies:
ebs-scgp3gp3-retainapiVersion: storage.k8s.io/v1\nkind: StorageClass\nmetadata:\n name: ebs-sc\n annotations:\n storageclass.kubernetes.io/is-default-class: 'true'\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Retain\nvolumeBindingMode: Immediate\n
kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: gp3\n annotations:\n storageclass.kubernetes.io/is-default-class: 'true'\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Delete\nvolumeBindingMode: Immediate\nallowVolumeExpansion: true\n
kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: gp3-retain\nallowedTopologies: []\nmountOptions: []\nprovisioner: ebs.csi.aws.com\nreclaimPolicy: Retain\nvolumeBindingMode: WaitForFirstConsumer\nallowVolumeExpansion: true\n
The EPAM Delivery Platform emphasizes the importance of incorporating security practices into the software development lifecycle through the DevSecOps approach. By integrating a diverse range of open-source and enterprise security tools tailored to specific functionalities, organizations can ensure efficient and secure software development. These tools, combined with fundamental DevSecOps principles such as collaboration, continuous security, and automation, contribute to the identification and remediation of vulnerabilities early in the process, minimizes risks, and fosters a security-first culture across the organization.
The EPAM Delivery Platform enabling seamless integration with various security tools and vulnerability management systems, enhancing the security of source code and ensuring compliance.
"},{"location":"operator-guide/overview-devsecops/#supported-solutions","title":"Supported Solutions","text":"The below table categorizes various open-source and enterprise security tools based on their specific functionalities. It provides a comprehensive view of the available options for each security aspect. This classification facilitates informed decision-making when selecting and integrating security tools into a development pipeline, ensuring an efficient and robust security stance. EDP supports the integration of both open-source and enterprise security tools, providing a flexible and versatile solution for security automation. See table below for more details.
Functionality Open-Source Tools (integrated in Pipelines) Enterprise Tools (available for Integration) Hardcoded Credentials Scanner TruffleHog, GitLeaks, Git-secrets GitGuardian, SpectralOps, Bridgecrew Static Application Security Testing SonarQube, Semgrep CLI Veracode, Checkmarx, Coverity Software Composition Analysis OWASP Dependency-Check, cdxgen Black Duck Hub, Mend, Snyk Container Security Trivy, Grype, Clair Aqua Security, Sysdig Secure, Snyk Infrastructure as Code Security Checkov, Tfsec Bridgecrew, Prisma Cloud, Snyk Dynamic Application Security Testing OWASP Zed Attack Proxy Fortify WebInspect, Rapid7 InsightAppSec, Checkmarx Continuous Monitoring and Logging ELK Stack, OpenSearch, Loki Splunk, Datadog Security Audits and Assessments OpenVAS Tenable Nessus, QualysGuard, BurpSuite Professional Vulnerability Management and Reporting DefectDojo, OWASP Dependency-Track MetasploitFor better visualization, see the scheme below:
Security tools in EDP
"},{"location":"operator-guide/overview-devsecops/#integrated-tools","title":"Integrated Tools","text":"For obtaining and managing report post scanning, deployment of various vulnerability management systems and security tools is required. These include:
"},{"location":"operator-guide/overview-devsecops/#defectdojo","title":"DefectDojo","text":"DefectDojo is a comprehensive vulnerability management and security orchestration platform facilitating the handling of uploaded security reports. Examine the prerequisites and fundamental instructions for installing DefectDojo on Kubernetes or OpenShift platforms.
"},{"location":"operator-guide/overview-devsecops/#owasp-dependency-track","title":"OWASP Dependency Track","text":"Dependency Track is an intelligent Software Composition Analysis (SCA) platform that provides a comprehensive solution for managing vulnerabilities in third-party and open-source components.
"},{"location":"operator-guide/overview-devsecops/#gitleaks","title":"Gitleaks","text":"Gitleaks is a versatile SAST tool used to scan Git repositories for hardcoded secrets, such as passwords and API keys, to prevent potential data leaks and unauthorized access.
"},{"location":"operator-guide/overview-devsecops/#trivy","title":"Trivy","text":"Trivy is a simple and comprehensive vulnerability scanner for containers and other artifacts, providing insight into potential security issues across multiple ecosystems.
"},{"location":"operator-guide/overview-devsecops/#grype","title":"Grype","text":"Grype is a fast and reliable vulnerability scanner for container images and filesystems, maintaining an up-to-date vulnerability database for efficient and accurate scanning.
"},{"location":"operator-guide/overview-devsecops/#tfsec","title":"Tfsec","text":"Tfsec is an effective Infrastructure as Code (IaC) security scanner, tailored specifically for reviewing Terraform templates. It helps identify potential security issues related to misconfigurations and non-compliant practices, enabling developers to address vulnerabilities and ensure secure infrastructure deployment.
"},{"location":"operator-guide/overview-devsecops/#checkov","title":"Checkov","text":"Checkov is a robust static code analysis tool designed for IaC security, supporting various IaC frameworks such as Terraform, CloudFormation, and Kubernetes. It assists in detecting and mitigating security and compliance misconfigurations, promoting best practices and adherence to industry standards across the infrastructure.
"},{"location":"operator-guide/overview-devsecops/#cdxgen","title":"Cdxgen","text":"Cdxgen is a lightweight and efficient tool for generating Software Bill of Materials (SBOM) using CycloneDX, a standard format for managing component inventory. It helps organizations maintain an up-to-date record of all software components, their versions, and related vulnerabilities, streamlining monitoring and compliance within the software supply chain.
"},{"location":"operator-guide/overview-devsecops/#semgrep-cli","title":"Semgrep CLI","text":"Semgrep CLI is a versatile and user-friendly command-line interface for the Semgrep security scanner, enabling developers to perform Static Application Security Testing (SAST) for various programming languages. It focuses on detecting and preventing potential security vulnerabilities, code quality issues, and custom anti-patterns, ensuring secure and efficient code development.
"},{"location":"operator-guide/overview-devsecops/#clair","title":"Clair","text":"Clair is an open-source container security tool that is designed to help you assess the security of container images and identify vulnerabilities within them. It is particularly useful for organizations using container orchestration platforms such as Kubernetes.
"},{"location":"operator-guide/overview-devsecops/#openvas","title":"OpenVAS","text":"OpenVAS is an open-source network vulnerability scanner and security management tool. It is designed to identify and assess security vulnerabilities in computer systems, networks, and applications. OpenVAS provides a comprehensive set of features for vulnerability scanning, assessment, and management.
"},{"location":"operator-guide/overview-devsecops/#trufflehog","title":"TruffleHog","text":"TruffleHog is an open-source Python tool designed for finding and identifying potentially sensitive and secret information in the source code and commit history of Git repositories. It's particularly useful for locating unintentional disclosures of confidential data, such as API keys, passwords, and other credentials, that might have been inadvertently committed to a code repository.
"},{"location":"operator-guide/overview-devsecops/#git-secrets","title":"Git-secrets","text":"Git-secrets is an open-source tool that helps prevent the accidental committing of secrets, sensitive information, and other types of confidential data into Git repositories. It is designed to enforce security best practices and reduce the risk of unintentional data exposure by scanning Git repositories for predefined secret patterns.
"},{"location":"operator-guide/overview-devsecops/#elk-stack","title":"ELK Stack","text":"ELK Stack (Fluent Bit, Elasticsearch, Kibana) stack is used in Kubernetes instead of ELK because this stack provides us with the support for Logsight for Stage Verification and Incident Detection. In addition to it, Fluent Bit has a smaller memory fingerprint than Logstash. Fluent Bit has the Inputs, Parsers, Filters and Outputs plugins similarly to Logstash.
"},{"location":"operator-guide/overview-devsecops/#loki","title":"Loki","text":"Loki is a log aggregation system and log processing system designed for cloud-native environments. It is part of the CNCF (Cloud Native Computing Foundation) and is often used alongside other CNCF projects like Prometheus for monitoring and observability.
"},{"location":"operator-guide/overview-devsecops/#opensearch","title":"OpenSearch","text":"OpenSearch is the flexible, scalable, open-source way to build solutions for data-intensive applications. Explore, enrich, and visualize your data with built-in performance, developer-friendly tools, and powerful integrations for machine learning, data processing, and more.
"},{"location":"operator-guide/overview-devsecops/#owasp-dependency-check","title":"OWASP Dependency-Check","text":"OWASP Dependency-Check is a software composition analysis tool that helps identify and report known security vulnerabilities in project dependencies. It is particularly valuable for developers and organizations looking to secure their applications by identifying and addressing vulnerabilities in the libraries and components they use.
"},{"location":"operator-guide/overview-devsecops/#owasp-zed-attack-proxy-zap","title":"OWASP Zed Attack Proxy (ZAP)","text":"OWASP Zed Attack Proxy (ZAP) is an security testing tool for finding vulnerabilities in web applications during the development and testing phases. ZAP is designed to help developers and security professionals identify and address security issues and potential vulnerabilities in web applications. It provides automated and manual testing capabilities, as well as a wide range of features for security testing.
"},{"location":"operator-guide/overview-manage-jenkins-pipelines/","title":"Overview","text":""},{"location":"operator-guide/overview-manage-jenkins-pipelines/#overview","title":"Overview","text":"Jenkins job provisioners are responsible for creating and managing pipelines in Jenkins. In other words, provisioners configure all Jenkins pipelines and bring them to the state described in the provisioners code. Two types of provisioners are available in EDP:
The subsections describe the creation/update process of provisioners and their content depending on EDP customization.
"},{"location":"operator-guide/overview-sast/","title":"Static Application Security Testing Overview","text":""},{"location":"operator-guide/overview-sast/#static-application-security-testing-overview","title":"Static Application Security Testing Overview","text":"EPAM Delivery Platform provides the implemented Static Application Security Testing support allowing to work with the Semgrep security scanner and the DefectDojo vulnerability management system to check the source code for known vulnerabilities.
"},{"location":"operator-guide/overview-sast/#supported-languages","title":"Supported Languages","text":"EDP SAST supports a number of languages and package managers.
Language (Package Managers) Scan Tool Build Tool Java Semgrep Maven, Gradle Go Semgrep Go React Semgrep Npm"},{"location":"operator-guide/overview-sast/#supported-vulnerability-management-system","title":"Supported Vulnerability Management System","text":"To get and then manage a SAST report after scanning, it is necessary to deploy the vulnerability management system, for instance, DefectDojo.
"},{"location":"operator-guide/overview-sast/#defectdojo","title":"DefectDojo","text":"DefectDojo is a vulnerability management and security orchestration platform that allows managing the uploaded security reports.
Inspect the prerequisites and the main steps for installing DefectDojo on Kubernetes or OpenShift platforms.
"},{"location":"operator-guide/overview-sast/#related-articles","title":"Related Articles","text":"Integration with Perf Server allows connecting to the PERF Board (Project Performance Board) and monitoring the overall team performance as well as setting up necessary metrics.
Note
To adjust the PERF Server integration, make sure that PERF Operator is deployed. To get more information about the PERF Operator installation and architecture, please refer to the PERF Operator page.
For integration, take the following steps:
Create Secret in the OpenShift/Kubernetes namespace for Perf Server account with the username and password fields:
apiVersion: v1\ndata:\n password: passwordInBase64\n username: usernameInBase64\nkind: Secret\nmetadata:\n name: epam-perf-user\ntype: kubernetes.io/basic-auth\n
In the edp-config config map, enable the perf_integration flag and click Save:
perf_integration_enabled: 'true'\n
Being in Admin Console, navigate to the Advanced Settings menu to check that the Integrate with Perf Server check box appeared:
Advanced settings
Before installing EDP:
EDP installation scenario is based on the Tekton as a CI tool and EDP Portal as a UI tool.
Find below the list of the key components used by EPAM Delivery Platform:
Component Requirement level Cluster Tekton Mandatory Argo CD Mandatory NGINX Ingress Controller1 Mandatory Keycloak Optional DefectDojo Optional ReportPortal Optional Kiosk Optional External Secrets Optional Harbor OptionalNote
Alternatively, use Helmfiles to install the EDP components.
After setting up the cluster and installing EDP components according to the selected scenario, proceed to the EDP installation.
"},{"location":"operator-guide/prerequisites/#related-articles","title":"Related Articles","text":"OpenShift cluster uses Routes to provide access to pods from external resources.\u00a0\u21a9
ReportPortal integration with Tekton allows managing all automation results and reports in one place, visualizing metrics and analytics, team collaborating to associate statistics results.
For integration, take the following steps:
Log in to the ReportPortal console and navigate to the User Profile menu:
ReportPortal profile
Copy the Access token and use it as a value while creating a kubernetes secret for the ReportPortal credentials:
apiVersion: v1\nkind: Secret\ntype: Opaque\nmetadata:\n name: rp-credentials\n namespace: edp\nstringData:\n rp_uuid: <access-token>\n
In the Configuration examples section of the ReportPortal User Profile menu, copy the following REQUIRED
fields: rp.endpoint
, rp.launch
and rp.project
. Insert these fields to the pytest.ini
file in root directory of your project:
[pytest]\naddopts = -rsxX -l --tb=short --junitxml test-report.xml\nrp_endpoint = <endpoint>\nrp_launch = <launch>\nrp_project = <project>\n
In root directory of the project create/update requirements.txt file and fill with following. it's mandatory to install report-portal python library (version may vary):
pytest-reportportal == 5.1.2\n
Create a custom Tekton task:
View: Custom Tekton taskapiVersion: tekton.dev/v1beta1\nkind: Task\nmetadata:\n labels:\n app.kubernetes.io/version: '0.1'\n name: pytest-reportportal\n namespace: edp\nspec:\n description: |-\n This task can be used to run pytest integrated with report portal.\n params:\n - default: .\n description: The path where package.json of the project is defined.\n name: PATH_CONTEXT\n type: string\n - name: EXTRA_COMMANDS\n type: string\n - default: python:3.8-alpine3.16\n description: The python image you want to use.\n name: BASE_IMAGE\n type: string\n - default: rp-credentials\n description: name of the secret holding the rp token\n name: rp-secret\n type: string\n steps:\n - env:\n - name: HOME\n value: $(workspaces.source.path)\n - name: RP_UUID\n valueFrom:\n secretKeyRef:\n key: rp_uuid\n name: $(params.rp-secret)\n image: $(params.BASE_IMAGE)\n name: pytest\n resources: {}\n script: >\n #!/usr/bin/env sh\n set -e\n export PATH=$PATH:$HOME/.local/bin\n $(params.EXTRA_COMMANDS)\n # tests are being run from ./test directory in the project\n pytest ./tests --reportportal\n workingDir: $(workspaces.source.path)/$(params.PATH_CONTEXT)\n workspaces:\n - name: source\n
Add this task ref to your Tekton pipeline after tasks:
View: Tekton pipeline- name: pytest\n params:\n - name: BASE_IMAGE\n value: $(params.image)\n - name: EXTRA_COMMANDS\n value: |\n set -ex\n pip3 install -r requirements.txt\n [ -f run_service.py ] && python run_service.py &\n runAfter:\n - compile\n taskRef:\n kind: Task\n name: pytest-reportportal\n workspaces:\n - name: source\n workspace: shared-workspace\n
Launch your Tekton pipeline and check that the custom task has been successfully executed:
Tekton task successfully executed
Test reports will be displayed in the Launches section of the ReportPortal:
Test report results
Follow the steps below to integrate the ReportPortal with Keycloak.
"},{"location":"operator-guide/reportportal-keycloak/#prerequisites","title":"Prerequisites","text":"Navigate to Client Scopes > Create client scope and create a new scope with the SAML protocol type.
Navigate to Client Scopes > your_scope_name > Mappers > Configure a new mapper > select the User Attribute mapper type. Add three mappers for the email, first name, and last name by typing lastName
, firstName
, and email
in the User Attribute field:
Basic
.Off
.User mapper sample Scope mappers
Navigate to Clients > Create client and fill in the following fields:
SAML
.report.portal.sp.id
.Warning
The report.portal.sp.id
Client ID is a constant value.
Navigate to Client > your_client > Settings and add https://<report-portal-url\\>/*
to the Valid redirect URIs.
Navigate to Client > your_client > Keys and disable Client signature required.
Client keys
Navigate to Client > your_client > Client scopes and add the scope created on step 3 with the default Assigned type.
Client scopes
Log in to the ReportPortal with the admin permissions.
Navigate to Client > Administrate > Plugins and select the SAML plugin.
Plugins menu
To add a new integration, fill in the following fields:
Add SAML configuration
https://<keycloak_url\\>/auth/realms/<realm\\>/protocol/saml/descriptor
.https://<report_portal_url\\>/uat
.Log in to the ReportPortal.
Note
By default, after the first login, ReportPortal creates the <your_email>_personal project and adds an account with the Project manager
role.
Report portal login page
You can use the Velero tool to restore a EDP tenant. Explore the main steps for backup and restoring below.
Delete all related entities in Keycloak: realm and clients from master/openshift realms. Navigate to the entities list in the Keycloak, select the necessary ones, and click the deletion icon on the entity overview page. If there are customized configs in Keycloak, save them before making backup.
Remove keycloak realm
To restore EDP, install and configure the Velero tool. Please refer to the Install Velero documentation for details.
Remove all locks for operators. Delete all config maps that have \u2039OPERATOR_NAME\u203a-operator-lock names. Then restart all pods with operators, or simply run the following command:
kubectl -n edp delete cm $(kubectl -n edp get cm | grep 'operator-lock' | awk '{print $1}')\n
Recreate the admin password and delete the Jenkins pod. Or change the script to update the admin password in Jenkins every time when the pod is updated.
Semgrep is an open-source static source code analyzer for finding bugs and enforcing code standards.
Semgrep scanner is installed on the EDP Jenkins SAST agent and runs on the sast
pipeline stage. For details, please refer to the edp-library-stages repository.
Semgrep supports more than 20 languages, see the full list in the official documentation. EDP uses Semgrep to scan Java, JavaScript and Go languages.
"},{"location":"operator-guide/sast-scaner-semgrep/#related-articles","title":"Related Articles","text":"In case it is necessary to restart pods, use a CronJob according to the following template:
View: template---\nkind: Role\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n namespace: <NAMESPACE>\n name: apps-restart\nrules:\n - apiGroups: [\"apps\"]\n resources:\n - deployments\n - statefulsets\n verbs:\n - 'get'\n - 'list'\n - 'patch'\n---\nkind: RoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n name: apps-restart\n namespace: <NAMESPACE>\nsubjects:\n - kind: ServiceAccount\n name: apps-restart-sa\n namespace: <NAMESPACE>\nroleRef:\n kind: Role\n name: apps-restart\n apiGroup: \"\"\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: apps-restart-sa\n namespace: <NAMESPACE>\n---\napiVersion: batch/v1beta1\nkind: CronJob\nmetadata:\n name: apps-rollout-restart\n namespace: <NAMESPACE>\nspec:\n schedule: \"0 9 * * MON-FRI\"\n jobTemplate:\n spec:\n template:\n spec:\n serviceAccountName: apps-restart-sa\n containers:\n - name: kubectl-runner\n image: bitnami/kubectl\n command:\n - /bin/sh\n - -c\n - kubectl get -n <NAMESPACE> -o name deployment,statefulset | grep <NAME_PATTERN>| xargs kubectl -n <NAMESPACE> rollout restart\n restartPolicy: Never\n
Modify the Cron expression in the CronJob manifest if needed.
"},{"location":"operator-guide/sonarqube/","title":"SonarQube","text":""},{"location":"operator-guide/sonarqube/#sonarqube-integration","title":"SonarQube Integration","text":"This documentation guide provides comprehensive instructions for integrating SonarQube with the EPAM Delivery Platform.
Info
In EDP release 3.5, we have changed the deployment strategy for the sonarqube-operator component, now it is not installed by default. The sonarURL
parameter management has been transferred from the values.yaml file to Kubernetes secrets.
Before proceeding, ensure that you have the following prerequisites:
To install SonarQube with pre-defined templates, use the sonar-operator installed via Cluster Add-Ons approach.
"},{"location":"operator-guide/sonarqube/#configuration","title":"Configuration","text":"To establish robust authentication and precise access control, generating a SonarQube token is essential. This token is a distinct identifier, enabling effortless integration between SonarQube and EDP. To generate the SonarQube token, proceed with the following steps:
Open the SonarQube UI and navigate to Administration
-> Security
-> User
. Create a new user or select an existing one. Click the Options List
icon to create a token:
SonarQube user settings
Type the ci-user
username, define an expiration period, and click the Generate
button to create the token:
SonarQube create token
Click the Copy
button to copy the generated <Sonarqube-token>
:
SonarQube token
Provision secrets using Manifest, EDP Portal or with the externalSecrets operator:
Go to EDP Portal -> EDP -> Configuration -> SonarQube. Update or fill in the URL and Token fields and click the Save button:
SonarQube update manual secret
apiVersion: v1\nkind: Secret\nmetadata:\n name: ci-sonarqube\n namespace: edp\n labels:\n app.edp.epam.com/secret-type: sonar\n app.edp.epam.com/integration-secret: \"true\"\ntype: Opaque\nstringData:\n url: https://sonarqube.example.com\n token: <sonarqube-token>\n
\"ci-sonarqube\":\n{\n \"url\": \"https://sonarqube.example.com\",\n \"token\": \"XXXXXXXXXXXX\"\n},\n
Go to EDP Portal -> EDP -> Configuration -> SonarQube and see the Managed by External Secret
message:
SonarQube managed by external secret operator
More details about External Secrets Operator integration can be found in the External Secrets Operator Integration page.
"},{"location":"operator-guide/sonarqube/#related-articles","title":"Related Articles","text":"The following material covers Let's Encrypt certificate automation with cert-manager using AWS Route53.
The cert-manager is a Kubernetes/OpenShift operator that allows to issue and automatically renew SSL certificates. In this tutorial, the steps to secure DNS Name will be demonstrated.
Below is an instruction on how to automatically issue and install wildcard certificates on OpenShift Ingress Controller and API Server covering all cluster Routes. To secure separate OpenShift Routes, please refer to the OpenShift Route Support project for cert-manager
.
oc
utility. The kubectl
tool can also be used for most of the commands.Install the cert-manager
operator via OpenShift OperatorHub that uses Operator Lifecycle Manager (OLM):
Go to the OpenShift Admin Console \u2192 OperatorHub, search for the cert-manager
, and click Install:
Cert-Manager Installation
Modify the ClusterServiceVersion
OLM resource, by selecting the Update approval \u2192 Manual. If selecting Update approval \u2192 Automatic after the automatic operator update, the parameters in the ClusterServiceVersion
will be reset to default.
Note
Installing an operator with Manual approval causes all operators installed in namespace openshift-operators
to function as manual approval strategy. In case the Manual approval is chosen, review the manual installation plan and approve it.
Cert-Manager Installation
Navigate to Operators \u2192 Installed Operators and check the operator status to be Succeeded:
Cert-Manager Installation
In case of errors, troubleshoot the Operator issues:
oc describe operator cert-manager -n openshift-operators\noc describe sub cert-manager -n openshift-operators\n
The cert-manager
should be configured to validate Wildcard certificates using the DNS-based method.
Check the DNS Hosted zone ID in AWS Route53 for your domain.
Hosted Zone ID
Create Route53 Permissions policy in AWS for cert-manager
to be able to create DNS TXT records for the certificate validation. In this example, cert-manager
permissions are given for a particular DNS zone only. Replace Hosted zone ID XXXXXXXX in the \"Resource\": \"arn:aws:route53:::hostedzone/XXXXXXXXXXXX\".
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": \"route53:GetChange\",\n \"Resource\": \"arn:aws:route53:::change/*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"route53:ChangeResourceRecordSets\",\n \"route53:ListResourceRecordSets\"\n ],\n \"Resource\": \"arn:aws:route53:::hostedzone/XXXXXXXXXXXX\"\n }\n ]\n}\n
Create an AWS Role with Custom trust policy for the cert-manager
service account to use the AWS IRSA feature and then attach the created policy. Replace the following:
${aws-account-id}
with the AWS account ID of the EKS cluster.${aws-region}
with the region where the EKS cluster is located.${eks-hash}
with the hash in the EKS API URL; this will be a random 32 character hex string, for example, 45DABD88EEE3A227AF0FA468BE4EF0B5.${namespace}
with the namespace where cert-manager is running.${service-account-name}
with the name of the ServiceAccount object created by cert-manager.cert-manager
is installed via OperatorHub.Optionally, add Permissions boundary to the Role.
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::* ${aws-account-id}:oidc-provider/oidc.eks.${aws-region}.amazonaws.com/id/${eks-hash}\"\n },\n \"Condition\": {\n \"StringEquals\": {\n \"oidc.eks.${aws-region}.amazonaws.com/id/${eks-hash}:sub\": \"system:serviceaccount:${namespace}:${service-account-name}\"\n }\n }\n }\n ]\n}\n
Copy the created Role ARN.
Annotate the ServiceAccount
created by cert-manager
(required for AWS IRSA), and restart the cert-manager
pod.
Replace the eks.amazonaws.com/role-arn
annotation value with your own Role ARN.
oc edit sa cert-manager -n openshift-operators\n
apiVersion: v1\nkind: ServiceAccount\nmetadata:\n annotations:\n eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/cert-manager\n
Modify the cert-manager
Deployment
with the correct file system permissions fsGroup: 1001
, so that the ServiceAccount
token can be read.
Note
In case the ServiceAccount
token cannot be read and the operator is installed using the OperatorHub, add fsGroup: 1001
via OpenShift ClusterServiceVersion OLM resource. It should be a cert-manager
controller spec. These actions are not required for OpenShift v4.10.
oc get csv\noc edit csv cert-manager.${VERSION}\n
spec:\n template:\n spec:\n securityContext:\n fsGroup: 1001\n serviceAccountName: cert-manager\n
Cert-Manager System Permissions
Info
A mutating admission controller will automatically modify all pods running with the service account:
cert-manager controller pod
apiVersion: apps/v1\nkind: Pod\n# ...\nspec:\n # ...\n serviceAccountName: cert-manager\n serviceAccount: cert-manager\n containers:\n - name: ...\n # ...\n env:\n - name: AWS_ROLE_ARN\n value: >-\n arn:aws:iam::XXXXXXXXXXX:role/cert-manager\n - name: AWS_WEB_IDENTITY_TOKEN_FILE\n value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token\n volumeMounts:\n - name: aws-iam-token\n readOnly: true\n mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount\n volumes:\n - name: aws-iam-token\n projected:\n sources:\n - serviceAccountToken:\n audience: sts.amazonaws.com\n expirationSeconds: 86400\n path: token\n defaultMode: 420\n
If you have separate public and private DNS zones for the same domain (split-horizon DNS), modify the cert-manager
Deployment
in order to validate DNS TXT records via public recursive nameservers.
Note
Otherwise, you will be getting an error during a record validation:
Waiting for DNS-01 challenge propagation: NS ns-123.awsdns-00.net.:53 returned REFUSED for _acme-challenge.\n
To avoid the error, add --dns01-recursive-nameservers-only --dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53
as ARGs to the cert-manager
controller Deployment
. oc get csv\noc edit csv cert-manager.${VERSION}\n
labels:\n app: cert-manager\n app.kubernetes.io/component: controller\n app.kubernetes.io/instance: cert-manager\n app.kubernetes.io/name: cert-manager\n app.kubernetes.io/version: v1.9.1\nspec:\n containers:\n - args:\n - '--v=2'\n - '--cluster-resource-namespace=$(POD_NAMESPACE)'\n - '--leader-election-namespace=kube-system'\n - '--dns01-recursive-nameservers-only'\n - '--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53'\n
Note
The Deployment
must be modified via OpenShift ClusterServiceVersion OLM resource if the operator was installed using the OperatorHub. The OpenShift ClusterServiceVersion
OLM resource includes several Deployments, and the ARGs must be modified only for the cert-manager
controller.
Cert-Manager Nameservers
ClusterIssuer
is available on the whole cluster.
Create the ClusterIssuer resource for Let's Encrypt Staging and Prod environments that signs a Certificate using cert-manager
.
Note
Let's Encrypt has a limit of duplicate certificates in the Prod environment. Therefore, a ClusterIssuer
has been created for Let's Encrypt Staging environment. By default, Let's Encrypt Staging certificates will not be trusted in your browser. The certificate validation cannot be tested in the Let's Encrypt Staging environment.
user@example.com
with your contact email.hostedZoneID
XXXXXXXXXXX with the DNS Hosted zone ID in AWS for your domain.${region}
.privateKeySecretRef
will be created automatically by the cert-manager
operator.apiVersion: cert-manager.io/v1\nkind: ClusterIssuer\nmetadata:\n name: letsencrypt-staging\nspec:\n acme:\n email: user@example.com\n server: https://acme-staging-v02.api.letsencrypt.org/directory\n privateKeySecretRef:\n name: letsencrypt-staging-issuer-account-key\n solvers:\n - dns01:\n route53:\n region: ${region}\n hostedZoneID: XXXXXXXXXXX\n
apiVersion: cert-manager.io/v1\nkind: ClusterIssuer\nmetadata:\n name: letsencrypt-prod\nspec:\n acme:\n email: user@example.com\n server: https://acme-v02.api.letsencrypt.org/directory\n privateKeySecretRef:\n name: letsencrypt-prod-issuer-account-key\n solvers:\n - dns01:\n route53:\n region: ${region}\n hostedZoneID: XXXXXXXXXXX\n
Cert-Manager ClusterIssuer
Check the ClusterIssuer
status:
Cert-Manager ClusterIssuer
oc describe clusterissuer letsencrypt-prod\noc describe clusterissuer letsencrypt-staging\n
If the ClusterIssuer
state is not ready, investigate cert-manager
controller pod logs:
oc get pod -n openshift-operators | grep 'cert-manager'\noc logs -f cert-manager-${replica_set}-${random_string} -n openshift-operators\n
In two different namespaces, create a Certificate resource for the OpenShift Router (Ingress controller for OpenShift) and for the OpenShift APIServer.
Secret
to be created in the openshift-ingress
namespace; the API Server, in the openshift-config
namespace. The cert-manager
operator will automatically create these secrets from the Certificate
resource.${DOMAIN}
with your domain name. It can be checked with oc whoami --show-server
. Put domain names in quotes.apiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n name: router-certs\n namespace: openshift-ingress\n labels:\n app: cert-manager\nspec:\n secretName: router-certs\n secretTemplate:\n labels:\n app: cert-manager\n duration: 2160h # 90d\n renewBefore: 360h # 15d\n subject:\n organizations:\n - Org Name\n commonName: '*.${DOMAIN}'\n privateKey:\n algorithm: RSA\n encoding: PKCS1\n size: 2048\n rotationPolicy: Always\n usages:\n - server auth\n - client auth\n dnsNames:\n - '*.${DOMAIN}'\n - '*.apps.${DOMAIN}'\n issuerRef:\n name: letsencrypt-staging\n kind: ClusterIssuer\n
The certificate for OpenShift APIServer in the `openshift-config` namespace apiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n name: api-certs\n namespace: openshift-config\n labels:\n app: cert-manager\nspec:\n secretName: api-certs\n secretTemplate:\n labels:\n app: cert-manager\n duration: 2160h # 90d\n renewBefore: 360h # 15d\n subject:\n organizations:\n - Org Name\n commonName: '*.${DOMAIN}'\n privateKey:\n algorithm: RSA\n encoding: PKCS1\n size: 2048\n rotationPolicy: Always\n usages:\n - server auth\n - client auth\n dnsNames:\n - '*.${DOMAIN}'\n - '*.apps.${DOMAIN}'\n issuerRef:\n name: letsencrypt-staging\n kind: ClusterIssuer\n
Info
cert-manager
supports ECDSA key pairs in the Certificate
resource. To use it, change RSA privateKey
to ECDSA:
privateKey:\n algorithm: ECDSA\n encoding: PKCS1\n size: 256\n rotationPolicy: Always\n
rotationPolicy: Always
is highly recommended since cert-manager
does not rotate private keys by default.Certificate
spec is described in the cert-manager
API documentation.Check that the certificates in the namespaces are ready:
Cert-Manager Certificate Status
Cert-Manager Certificate Status
Check the details of the certificates via CLI:
oc describe certificate api-certs -n openshift-config\noc describe certificate router-certs -n openshift-ingress\n
Check the cert-manager controller pod logs if the Staging Certificate condition is not ready for more than 7 minutes:
oc get pod -n openshift-operators | grep 'cert-manager'\noc logs -f cert-manager-${replica_set}-${random_string} -n openshift-operators\n
When the certificate is ready, its private key will be put into the OpenShift Secret
in the namespace indicated in the Certificate
resource:
oc describe secret api-certs -n openshift-config\noc describe secret router-certs -n openshift-ingress\n
Update the Custom Resource of your Router (Ingress controller). Patch the defaultCertificate
object value with { \"name\": \"router-certs\" }
:
oc patch ingresscontroller default -n openshift-ingress-operator --type=merge --patch='{\"spec\": { \"defaultCertificate\": { \"name\": \"router-certs\" }}}' --insecure-skip-tls-verify\n
Info
After updating the IngressController
object, the OpenShift Ingress operator redeploys the router.
Update the Custom Resource for the OpenShift API Server:
Export the name of APIServer
:
export OKD_API=$(oc whoami --show-server --insecure-skip-tls-verify | cut -f 2 -d ':' | cut -f 3 -d '/' | sed 's/-api././')\n
Patch the servingCertificate
object value with { \"name\": \"api-certs\" }
:
oc patch apiserver cluster --type merge --patch=\"{\\\"spec\\\": {\\\"servingCerts\\\": {\\\"namedCertificates\\\": [ { \\\"names\\\": [ \\\"$OKD_API\\\" ], \\\"servingCertificate\\\": {\\\"name\\\": \\\"api-certs\\\" }}]}}}\" --insecure-skip-tls-verify\n
Test the Staging certificate on the OpenShift Admin Console. The --insecure
flag is used because Let's Encrypt Staging certificates are not trusted in browsers by default:
curl -v --insecure https://console-openshift-console.apps.${DOMAIN}\n
Change issuerRef
to letsencrypt-prod
in both Certificate
resources:
oc edit certificate api-certs -n openshift-config\noc edit certificate router-certs -n openshift-ingress\n
issuerRef:\n name: letsencrypt-prod\n kind: ClusterIssuer\n
Note
In case the certificate reissue is not triggered after that, try to force the certificate renewal with cmctl:
cmctl renew router-certs -n openshift-ingress\ncmctl renew api-certs -n openshift-config\n
If this won't work, delete the api-certs
and router-certs
secrets. It should trigger the Prod certificates issuance:
oc delete secret router-certs -n openshift-ingress\noc delete secret api-certs -n openshift-config\n
Please note that these actions will lead to logging your account out of the OpenShift Admin Console, since certificates will be deleted. Accept the certificate warning in the browser and log in again after that.
Check the status of the Prod certificates:
oc describe certificate api-certs -n openshift-config\noc describe certificate router-certs -n openshift-ingress\n
cmctl status certificate api-certs -n openshift-config\ncmctl status certificate router-certs -n openshift-ingress\n
Check the web console and make sure it has secure connection:
curl -v https://console-openshift-console.apps.${DOMAIN}\n
Below is an example of the DNS TXT challenge
record created by the cert-manager
operator:
DNS Validation
Use nslookup
or dig
tools to check if the DNS propagation for the TXT record is complete:
nslookup -type=txt _acme-challenge.${DOMAIN}\ndig txt _acme-challenge.${DOMAIN}\n
Otherwise, use web tools like Google Admin Toolbox:
DNS Validation
If the correct TXT value is shown (the value corresponds to the current TXT value in the DNS zone), it means that the DNS propagation is complete and Let's Encrypt is able to access the record in order to validate it and issue a trusted certificate.
Note
If the DNS validation challenge self check fails, cert-manager
will retry the self check with a fixed 10-second retry interval. Challenges that do not ever complete the self check will continue retrying until the user intervenes by either retrying the Order
(by deleting the Order
resource) or amending the associated Certificate
resource to resolve any configuration errors.
As soon as the domain ownership has been verified, any cert-manager
affected validation TXT records in the AWS Route53 DNS zone will be cleaned up.
Please find below the issues that may occur and their troubleshooting:
cert-manager
resource is not in a Ready state, describing a resource may show the reason for the error.cert-manager
creates the following resources during a Certificate
issuance: CertificateRequest
, Order
, and Challenge
. Investigate each of them in case of errors.Certificate
and its associated resources.Check the cert-manager
controller pod logs:
oc get pod -n openshift-operators | grep 'cert-manager'\noc logs -f cert-manager-${replica_set}-${random_string} -n openshift-operators\n
Certificate error debugging: a. Decode certificate chain located in the secrets:
oc get secret router-certs -n openshift-ingress -o 'go-template={{index .data \"tls.crt\"}}' | base64 -d | while openssl x509 -noout -text; do :; done 2>/dev/null\noc get secret api-certs -n openshift-config -o 'go-template={{index .data \"tls.crt\"}}' | base64 -d | while openssl x509 -noout -text; do :; done 2>/dev/null\n
cmctl inspect secret router-certs -n openshift-ingress\ncmctl inspect secret api-certs -n openshift-config\n
b. Check the SSL RSA private key consistency:
oc get secret router-certs -n openshift-ingress -o 'go-template={{index .data \"tls.key\"}}' | base64 -d | openssl rsa -check -noout\noc get secret api-certs -n openshift-config -o 'go-template={{index .data \"tls.key\"}}' | base64 -d | openssl rsa -check -noout\n
c. Match the SSL certificate public key against its RSA private key. Their modulus must be identical:
diff <(oc get secret api-certs -n openshift-config -o 'go-template={{index .data \"tls.crt\"}}' | base64 -d | openssl x509 -noout -modulus | openssl md5) <(oc get secret api-certs -n openshift-config -o 'go-template={{index .data \"tls.key\"}}' | base64 -d | openssl rsa -noout -modulus | openssl md5)\ndiff <(oc get secret router-certs -n openshift-ingress -o 'go-template={{index .data \"tls.crt\"}}' | base64 -d | openssl x509 -noout -modulus | openssl md5) <(oc get secret router-certs -n openshift-ingress -o 'go-template={{index .data \"tls.key\"}}' | base64 -d | openssl rsa -noout -modulus | openssl md5)\n
After updating the certificates, the access to the cluster via Lens or CLI will be denied because of the untrusted certificate errors:
$ oc whoami\nUnable to connect to the server: x509: certificate signed by unknown authority\n
Such behavior appears because the oc
tool references an old CA data in the kubeconfig file.
Note
Examine the Certificate Authority data using the following command:
oc config view --minify --raw -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d | openssl x509 -text\n
This certificate has the CA:TRUE
parameter, which means that this is a self-signed root CA certificate.
To fix the error, remove the old CA data from your OpenShift kubeconfig file:
sed -i \"/certificate-authority-data/d\" $KUBECONFIG\n
Since this field will be absent in the kubeconfig file, system root SSL certificate will be used to validate the cluster certificate trust chain. On Ubuntu, Let's Encrypt OpenShift cluster certificates will be validated against Internet Security Research Group
root in /etc/ssl/certs/ca-certificates.crt
.
The cert-manager
automatically renews the certificates based on the X.509 certificate's duration and the renewBefore
value. The minimum value for the spec.duration
is 1 hour; for spec.renewBefore
, 5 minutes. It is also required that spec.duration
> spec.renewBefore
.
Use the cmctl tool to manually trigger a single instant certificate renewal:
cmctl renew router-certs -n openshift-ingress\ncmctl renew api-certs -n openshift-config\n
Otherwise, manually renew all certificates in all namespaces with the app=cert-manager
label:
cmctl renew --all-namespaces -l app=cert-manager\n
Run the cmctl renew --help
command to get more details.
This documentation describes how to integrate tekton-pipelines metrics with Prometheus and Grafana monitoring stack.
"},{"location":"operator-guide/tekton-monitoring/#prerequisites","title":"Prerequisites","text":"Ensure the following requirements are met first before moving ahead:
To create and apply the additional scrape config, follow the steps below:
Create the kubernetes secret file with the additional scrape config:
additional-scrape-configs.yaml fileapiVersion: v1\nkind: Secret\nmetadata:\n name: additional-scrape-configs\nstringData:\n prometheus-additional-job.yaml: |\n - job_name: \"tekton-pipelines\"\n scrape_interval: 30s\n static_configs:\n - targets: [\"tekton-pipelines-controller.<tekton-pipelines-namespace>.svc.cluster.local:9090\"]\n
Apply the created secret:
kubectl apply -f additional-scrape-configs.yaml -n <monitoring-namespace>\n
Update the prometheus stack:
helm update --install prometheus prometheus-community/kube-prometheus-stack --values values.yaml -n <monitoring-namespace>\n
The values.yaml
file should have the following contents:
prometheus:\n prometheusSpec:\n additionalScrapeConfigsSecret:\n enabled: true\n name: additional-scrape-configs\n key: prometheus-additional-job.yaml\n
Download the EDP Tekton Pipeline dashboard:
Import Grafana dashboard
a. Click on the dashboard menu;
b. In the dropdown menu, click the + Import
button;
c. Select the created edp-tekton-overview_rev1.json
file;
Import Grafana dashboard: Options
d. Type the name of the dashboard;
e. Select the folder for the dashboard;
f. Type the UID (set of eight numbers or letters and symbols);
g. Click the Import
button.
As soon as the dashboard procedure is completed, you can track the newcoming metrics in the dashboard menu:
Tekton dashboard
"},{"location":"operator-guide/tekton-monitoring/#related-articles","title":"Related Articles","text":"EPAM Delivery Platform provides Continuous Integration based on Tekton.
Tekton is an open-source Kubernetes native framework for creating CI pipelines, allowing a user to compile, build and test applications.
The edp-tekton GitHub repository provides all Tekton implementation logic on the platform. The Helm charts are used to deploy the resources inside the Kubernetes cluster. Tekton logic is decoupled into separate components:
Edp-tekton components diagram
The diagram above describes the following:
Common-library
is the Helm chart of Library type which stores the common logic shareable across all Tekton pipelines. This library contains Helm templates that generate common Tekton resources.Pipelines-library
is the Helm chart of the Application type which stores the core logic for the EDP pipelines. Tekton CRs like Pipelines, Tasks, EventListeners, Triggers, TriggerTemplates, and other resources are delivered with this chart.Custom-pipelines
is the Helm chart of the Application type which implements custom logic running specifically for internal EDP development, for example, CI and Release. It also demonstrates the customization flow on the platform.Tekton-dashboard
is a multitenancy-adopted implementation of the upstream Tekton Dashboard. It is configured to share Tekton resources across a single namespace.EDP Interceptor
is the custom Tekton Interceptor which enriches the payload from the VCSs events with EDP data from the Codebase CR specification. These data are used to define the Pipeline logic.Inspect the schema below that describes the logic behind the Tekton functionality on the platform:
Component view for the Tekton on EDP
The platform logic consists of the following:
The EventListener
exposes a dedicated Pod that runs the sink logic and receives incoming events from the VCSs (Gerrit, GitHub, GitLab) through the Ingress. It contains triggers with filtering and routing rules for incoming requests.
Upon the Event Payload arrival, the EventListener
runs triggers to process information or validate it via different interceptors.
The EDP Interceptor
extracts information from the codebases.v2.edp.epam.com CR and injects the received data into top-level 'extensions' field of the Event Payload. The Interceptor consists of running Pod and Service.
The Tekton Cel Interceptor
does simple transformations of the resulting data and prepares them for the Pipeline parameters substitution.
The TriggerTemplate
creates a PipelineRun instance with the required parameters extracted from the Event Payload by Interceptors. These parameters are mandatory for Pipelines.
The PipelineRun
has a mapping to the EDP Tekton Pipelines using a template approach which reduces code duplication. Each Pipeline is designed for a specific VCS (Gerrit, GitLab, GitHub), technology stack (such as Java or Python), and type (code-review, build).
A Pipeline
consists of separate EDP Tekton or open-source Tasks. They are arranged in a specific order of execution in the Pipeline.
Each Task
is executed as a Pod on the Kubernetes cluster. Also, Tasks can have a different number of steps that are executed as a Container in Pod.
The Kubernetes native approach allows the creation of PipelineRun either with the kubectl tool or using the EDP Portal UI.
This section provides the details on the EDP upgrade to 2.10.2. Explore the actions and requirements below.
Note
Kiosk is optional for EDP v.2.9.0 and higher, and is enabled by default. To disable it, add the following parameter to the values.yaml
file: global.kioskEnabled: false
. Please refer to the Set Up Kiosk documentation for the details.
Note
In the process of updating the EDP, it is necessary to migrate the database for SonarQube, before performing the update procedure, please carefully read section 4 of this guide.
Before updating EDP to 2.10.2, delete SonarQube plugins by executing the following command in SonarQube pod:
rm -r /opt/sonarqube/extensions/plugins/*\n
Update Custom Resource Definitions. Run the following command to apply all the necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.10/deploy-templates/crds/v2_v1alpha1_jenkins_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakclient_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakrealmcomponent_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakrealmidentityprovider_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakrealmrole_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloakrealmuser_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.10/deploy-templates/crds/v1_v1alpha1_keycloak_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.10/deploy-templates/crds/edp_v1alpha1_nexus_crd.yaml\n
To upgrade EDP to the v.2.10.2, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.10.2\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.10.2 --dry-run
Migrate the database for SonarQube according to the official documentation.
Note
Please be aware of possible tables duplication for speeding up the migration process during the upgrade. Due to the duplication, the database disk usage can be temporarily increased to twice as the normal usage. Therefore, the recommended database disk usage is below 50% before the migration start.
Navigate to the project http://SonarQubeServerURL/setup link and follow the setup instructions:
Migrate SonarQube database
Remove the resources related to the deprecated Sonar Gerrit Plugin that is deleted in EDP 2.10.2:
[label \"Sonar-Verified\"]\n function = MaxWithBlock\n value = -1 Issues found\n value = 0 No score\n value = +1 Verified\n defaultValue = 0\n
label-Sonar-Verified = -1..+1 group Administrators\nlabel-Sonar-Verified = -1..+1 group Project Owners\nlabel-Sonar-Verified = -1..+1 group Service Users\n
git push origin HEAD:refs/meta/config\n
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:1.0.1\nepamedp/edp-jenkins-dotnet-21-agent:1.0.5\nepamedp/edp-jenkins-dotnet-31-agent:1.0.4\nepamedp/edp-jenkins-go-agent:1.0.6\nepamedp/edp-jenkins-gradle-java8-agent:1.0.3\nepamedp/edp-jenkins-gradle-java11-agent:2.0.3\nepamedp/edp-jenkins-helm-agent:1.0.10\nepamedp/edp-jenkins-maven-java8-agent:1.0.3\nepamedp/edp-jenkins-maven-java11-agent:2.0.4\nepamedp/edp-jenkins-npm-agent:2.0.3\nepamedp/edp-jenkins-opa-agent:1.0.2\nepamedp/edp-jenkins-python-38-agent:2.0.4\nepamedp/edp-jenkins-terraform-agent:2.0.5\n
Since EDP version v.2.10.x, the create-release.groovy, code-review.groovy, and build.groovy files are deprecated (pipeline script from SCM
is replaced with pipeline script
, see below).
This section provides the details on the EDP upgrade to 2.11. Explore the actions and requirements below.
Update Custom Resource Definitions. Run the following command to apply all the necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.12/deploy-templates/crds/edp_v1alpha1_cd_stage_deploy_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.11/deploy-templates/crds/v2_v1alpha1_merge_request_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.11/deploy-templates/crds/edp_v1alpha1_user_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/release/2.11/deploy-templates/crds/edp_v1alpha1_cdpipeline_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.11/deploy-templates/crds/v2_v1alpha1_jenkinssharedlibrary_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.11/deploy-templates/crds/v2_v1alpha1_cdstagejenkinsdeployment_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.11/deploy-templates/crds/v1_v1alpha1_keycloakauthflow_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.11/deploy-templates/crds/v1_v1alpha1_keycloakrealmuser_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.12/deploy-templates/crds/edp_v1alpha1_codebaseimagestream_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.12/deploy-templates/crds/edp_v1alpha1_codebase_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.11/deploy-templates/crds/edp_v1alpha1_sonar_group_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.11/deploy-templates/crds/edp_v1alpha1_permission_template_crd.yaml\n
Backup kaniko-template config-map and then remove it. This component will be delivered during upgrade.
Set required awsRegion parameter. Pay attention that the nesting of the kanikoRoleArn parameter has been changed to the kaniko.roleArn parameter. Check the parameters in the EDP installation chart. For details, please refer to the values.yaml file. To upgrade EDP to the v.2.11.x, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.11.x\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.11.x --dry-run
Update Sonar Project Key:
Note
Avoid using special characters when creating projects in SonarQube. Allowed characters are: letters
, numbers
, -
, _
, .
and :
, with at least one non-digit. For details, please refer to the SonarQube documentation. As the result, the project name will be: project-name-release-0.0
or project-name-branchName
.
Such actions are required to be followed with the aim to store the SonarQube statistics from the previous EDP version:
Warning
Do not run any pipeline with the updated sonar stage on any existing application before the completion of the first step.
4.1. Update the project key in SonarQube from old to new format by adding the default branch name.
- Navigate to Project Settings -> Update Key: Update SonarQube project key - Enter the default branch name and click Update: Update SonarQube project key
4.2. As the result, after the first run, the project name will be changed to a new format containing all previous statistics:
SonarQube project history activity
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:3.0.4\nepamedp/edp-jenkins-dotnet-21-agent:3.0.4\nepamedp/edp-jenkins-dotnet-31-agent:3.0.3\nepamedp/edp-jenkins-go-agent:3.0.5\nepamedp/edp-jenkins-gradle-java11-agent:3.0.2\nepamedp/edp-jenkins-gradle-java8-agent:3.0.2\nepamedp/edp-jenkins-helm-agent:3.0.3\nepamedp/edp-jenkins-maven-java11-agent:3.0.3\nepamedp/edp-jenkins-maven-java8-agent:3.0.3\nepamedp/edp-jenkins-npm-agent:3.0.4\nepamedp/edp-jenkins-opa-agent:3.0.2\nepamedp/edp-jenkins-python-38-agent:3.0.2\nepamedp/edp-jenkins-terraform-agent:3.0.3\n
Add Jenkins agent by following the template:
View: values.yaml
kaniko-docker-template: |-\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>kaniko-docker</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>kaniko-docker</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>epamedp/edp-jenkins-kaniko-docker-agent:1.0.4</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n
Update the Jenkins plugins with the 'pipeline' name and 'HTTP Request Plugin'.
Update Jenkins provisioners according to the Manage Jenkins CI Pipeline Job Provisioner and Manage Jenkins CD Pipeline Job Provisioner documentation.
Restart the codebase-operator to recreate the Code-review and Build pipelines for codebases.
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides the details on the EDP upgrade to 2.12. Explore the actions and requirements below.
Notes
networking.k8s.io/v1
, and Ingress Operators use CustomResourceDefinition apiextensions.k8s.io/v1
.EDP now uses DefectDojo as a SAST tool. It is mandatory to deploy DefectDojo before updating EDP to v.2.12.x.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-admin-console-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_adminconsoles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_cdpipelines.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_cdstagedeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_cdstagejenkinsdeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_codebasebranches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_codebaseimagestreams.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-component-operator/release/0.12/deploy-templates/crds/v1.edp.epam.com_edpcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritgroupmembers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritmergerequests.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritprojectaccesses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritprojects.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerritreplicationconfigs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_gittags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_imagestreamtags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsagents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsauthorizationrolemappings.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsauthorizationroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsfolders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsjobbuildruns.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsjobs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsscripts.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinsserviceaccounts.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_jenkinssharedlibraries.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_jiraissuemetadatas.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.13/deploy-templates/crds/v2.edp.epam.com_jiraservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakauthflows.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakclients.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakclientscopes.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmidentityproviders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmrolebatches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealms.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloakrealmusers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.12/deploy-templates/crds/v1.edp.epam.com_keycloaks.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_nexuses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_nexususers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_perfdatasourcegitlabs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_perfdatasourcejenkinses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_perfdatasourcesonars.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_perfservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_sonargroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_sonarpermissiontemplates.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_sonars.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/release/2.12/deploy-templates/crds/v2.edp.epam.com_stages.yaml\n
Set the required parameters. For details, please refer to the values.yaml file.
v3.6.1
. According to the Official Gerrit Upgrade flow, a user must initially upgrade to Gerrit v3.5.2
, and then upgrade to v3.6.1
. Therefore, define the gerrit-operator.gerrit.version=3.5.2
value in the edp-install values.yaml
file.Two more components are available with the new functionality:
edp-argocd-operator
external-secrets
false
values for them in the existing value.yaml
file:View: values.yaml
gerrit-operator:\n gerrit:\n version: \"3.5.2\"\nexternalSecrets:\n enabled: false\nargocd:\n enabled: false\n
The edp-jenkins-role
is renamed to the jenkins-resources-role
. Delete the edp-jenkins-role
with the following command:
kubectl delete role edp-jenkins-role -n <edp-namespace>\n
The jenkins-resources-role
role will be created automatically while EDP upgrade.
Recreate the edp-jenkins-resources-permissions
RoleBinding according to the following template:
View: jenkins-resources-role
apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n name: edp-jenkins-resources-permissions\n namespace: <edp-namespace>\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: Role\n name: jenkins-resources-role\n
To upgrade EDP to the v.2.12.x, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.x\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.x --dry-run
After the update, please remove the gerrit-operator.gerrit.version
value. In this case, the default value will be used, and Gerrit will be updated to the v3.6.1
version. Run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.x\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.x --dry-run
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:3.0.8\nepamedp/edp-jenkins-dotnet-21-agent:3.0.7\nepamedp/edp-jenkins-dotnet-31-agent:3.0.7\nepamedp/edp-jenkins-go-agent:3.0.11\nepamedp/edp-jenkins-gradle-java11-agent:3.0.5\nepamedp/edp-jenkins-gradle-java8-agent:3.0.7\nepamedp/edp-jenkins-helm-agent:3.0.8\nepamedp/edp-jenkins-maven-java11-agent:3.0.6\nepamedp/edp-jenkins-maven-java8-agent:3.0.8\nepamedp/edp-jenkins-npm-agent:3.0.7\nepamedp/edp-jenkins-opa-agent:3.0.5\nepamedp/edp-jenkins-python-38-agent:3.0.5\nepamedp/edp-jenkins-terraform-agent:3.0.6\n
Add Jenkins agents by following the template:
View: jenkins-slaves
sast-template: |\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>sast</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>sast</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>epamedp/edp-jenkins-sast-agent:0.1.3</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n
If required, update the requests and limits for the following Jenkins agents:
edp-jenkins-codenarc-agent
edp-jenkins-go-agent
edp-jenkins-gradle-java11-agent
edp-jenkins-gradle-java8-agent
edp-jenkins-maven-java11-agent
edp-jenkins-maven-java8-agent
edp-jenkins-npm-agent
edp-jenkins-dotnet-21-agent
edp-jenkins-dotnet-31-agent
EDP requires to start with the following values:
View: jenkins-slaves
<resourceRequestCpu>500m</resourceRequestCpu>\n <resourceRequestMemory>1Gi</resourceRequestMemory>\n <resourceLimitCpu>2</resourceLimitCpu>\n <resourceLimitMemory>5Gi</resourceLimitMemory>\n
Update Jenkins provisioners according to the Manage Jenkins CI Pipeline Job Provisioner instruction.
Restart the codebase-operator
, to recreate the Code Review and Build pipelines for the codebases.
Warning
In case there are different EDP versions on one cluster, the following error may occur on the init
stage of Jenkins Groovy pipeline: java.lang.NumberFormatException: For input string: \"\"
. To fix this issue, please run the following command using kubectl
v1.24.4+:
kubectl patch codebasebranches.v2.edp.epam.com <codebase-branch-name> -n <edp-namespace> '--subresource=status' '--type=merge' -p '{\"status\": {\"build\": \"0\"}}'\n
"},{"location":"operator-guide/upgrade-edp-2.12/#upgrade-edp-to-2122","title":"Upgrade EDP to 2.12.2","text":"Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides the details on the EDP upgrade to 2.12.2. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.12.2/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.12.1/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\n
To upgrade EDP to 2.12.2, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.2\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.12.2 --dry-run
This section provides the details on the EDP upgrade to 2.8.4. Explore the actions and requirements below.
Note
Kiosk is implemented and mandatory for EDP v.2.8.4 and is optional for EDP v.2.9.0 and higher.
To upgrade EDP to 2.8.4, take the following steps:
Deploy and configure Kiosk (create a Service Account, Account, and ClusterRoleBinging) according to the Set Up Kiosk documentation.
apiVersion: tenancy.kiosk.sh/v1alpha1\nkind: Space\nmetadata:\n name: <edp-project>\nspec:\n account: <edp-project>-admin\n
Create RoleBinding (required for namespaces created before using Kiosk):
Note
In the uid field under the ownerReferences in the Kubernetes manifest, indicate the Account Custom Resource ID from accounts.config.kiosk.sh kubectl get account <edp-project>-admin -o=custom-columns=NAME:.metadata.uid --no-headers=true
View: rolebinding-kiosk.yaml
apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n generateName: <edp-project>-admin-\n namespace: <edp-project>\n ownerReferences:\n - apiVersion: config.kiosk.sh/v1alpha1\n blockOwnerDeletion: true\n controller: true\n kind: Account\n name: <edp-project>-admin\n uid: ''\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: kiosk-space-admin\nsubjects:\n- kind: ServiceAccount\n name: <edp-project>\n namespace: security\n
kubectl create -f rolebinding-kiosk.yaml\n
With Amazon Elastic Container Registry to store the images, there are two options:
Update Custom Resource Definitions by applying all the necessary CRD to the cluster with the command below:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/release/2.8/deploy-templates/crds/edp_v1alpha1_cdpipeline_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.8/deploy-templates/crds/edp_v1alpha1_codebase_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.8/deploy-templates/crds/edp_v1alpha1_cd_stage_deploy_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.8/deploy-templates/crds/v2_v1alpha1_jenkinsjobbuildrun_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.8/deploy-templates/crds/v2_v1alpha1_cdstagejenkinsdeployment_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.8/deploy-templates/crds/v2_v1alpha1_jenkinsjob_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.8/deploy-templates/crds/edp_v1alpha1_nexus_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.8/deploy-templates/crds/v1_v1alpha1_keycloakauthflow_crd.yaml\n
With Amazon Elastic Container Registry to store and Kaniko to build the images, add the kanikoRoleArn parameter to the values before starting the update process. This parameter is indicated in AWS Roles once IRSA is enabled and AWS IAM Role is created for Kaniko. The value should look as follows:
kanikoRoleArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko\n
To upgrade EDP to the v.2.8.4, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.8.4\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.8.4 --dry-run
Remove the following Kubernetes resources left from the previous EDP installation (it is optional):
kubectl delete cm luminatesec-conf -n <edp-namespace>\nkubectl delete sa edp edp-perf-operator -n <edp-namespace>\nkubectl delete deployment perf-operator -n <edp-namespace>\nkubectl delete clusterrole edp-<edp-namespace> edp-perf-operator-<edp-namespace>\nkubectl delete clusterrolebinding edp-<edp-namespace> edp-perf-operator-<edp-namespace>\nkubectl delete rolebinding edp-<edp-namespace> edp-perf-operator-<edp-namespace>-admin -n <edp-namespace>\nkubectl delete perfserver epam-perf -n <edp-namespace>\nkubectl delete services.v2.edp.epam.com postgres rabbit-mq -n <edp-namespace>\n
Update the CI and CD Jenkins job provisioners:
Note
Please refer to the Manage Jenkins CI Pipeline Job Provisioner section for the details.
View: Default CI provisioner template for EDP 2.8.4/* Copyright 2021 EPAM Systems.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nimport groovy.json.*\nimport jenkins.model.Jenkins\nimport hudson.model.*\n\nJenkins jenkins = Jenkins.instance\ndef stages = [:]\ndef jiraIntegrationEnabled = Boolean.parseBoolean(\"${JIRA_INTEGRATION_ENABLED}\" as String)\ndef commitValidateStage = jiraIntegrationEnabled ? ',{\"name\": \"commit-validate\"}' : ''\ndef createJIMStage = jiraIntegrationEnabled ? ',{\"name\": \"create-jira-issue-metadata\"}' : ''\ndef buildTool = \"${BUILD_TOOL}\"\ndef goBuildStage = buildTool.toString() == \"go\" ? ',{\"name\": \"build\"}' : ',{\"name\": \"compile\"}'\n\nstages['Code-review-application'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + goBuildStage +\n ',{\"name\": \"tests\"},[{\"name\": \"sonar\"},{\"name\": \"dockerfile-lint\"},{\"name\": \"helm-lint\"}]]'\nstages['Code-review-library'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"compile\"},{\"name\": \"tests\"},' +\n '{\"name\": \"sonar\"}]'\nstages['Code-review-autotests'] = '[{\"name\": \"gerrit-checkout\"},{\"name\": \"get-version\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"},{\"name\": \"sonar\"}' + \"${createJIMStage}\" + ']'\nstages['Code-review-default'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" + ']'\nstages['Code-review-library-terraform'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"terraform-lint\"}]'\nstages['Code-review-library-opa'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"tests\"}]'\nstages['Code-review-library-codenarc'] = '[{\"name\": \"gerrit-checkout\"}' + \"${commitValidateStage}\" +\n ',{\"name\": \"sonar\"},{\"name\": \"build\"}]'\n\nstages['Build-library-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"build\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-npm'] = stages['Build-library-maven']\nstages['Build-library-gradle'] = stages['Build-library-maven']\nstages['Build-library-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-terraform'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"terraform-lint\"}' +\n ',{\"name\": \"terraform-plan\"},{\"name\": \"terraform-apply\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-opa'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n ',{\"name\": \"tests\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-library-codenarc'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"sonar\"},{\"name\": \"build\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n\n\nstages['Build-application-maven'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},[{\"name\": \"sonar\"}],{\"name\": \"build\"},{\"name\": \"build-image-kaniko\"},' +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-npm'] = stages['Build-application-maven']\nstages['Build-application-gradle'] = stages['Build-application-maven']\nstages['Build-application-dotnet'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},[{\"name\": \"sonar\"}],{\"name\": \"build-image-kaniko\"},' +\n '{\"name\": \"push\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-go'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"tests\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build\"},{\"name\": \"build-image-kaniko\"}' +\n \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\nstages['Build-application-python'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"},{\"name\": \"compile\"},' +\n '{\"name\": \"tests\"},{\"name\": \"sonar\"},' +\n '{\"name\": \"build-image-kaniko\"},{\"name\": \"push\"}' + \"${createJIMStage}\" +\n ',{\"name\": \"git-tag\"}]'\n\nstages['Create-release'] = '[{\"name\": \"checkout\"},{\"name\": \"create-branch\"},{\"name\": \"trigger-job\"}]'\n\ndef defaultBuild = '[{\"name\": \"checkout\"}' + \"${createJIMStage}\" + ']'\n\ndef codebaseName = \"${NAME}\"\ndef gitServerCrName = \"${GIT_SERVER_CR_NAME}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID ? GIT_CREDENTIALS_ID : 'gerrit-ciuser-sshkey'}\"\ndef repositoryPath = \"${REPOSITORY_PATH}\"\ndef defaultBranch = \"${DEFAULT_BRANCH}\"\n\ndef codebaseFolder = jenkins.getItem(codebaseName)\nif (codebaseFolder == null) {\n folder(codebaseName)\n}\n\ncreateListView(codebaseName, \"Releases\")\ncreateReleasePipeline(\"Create-release-${codebaseName}\", codebaseName, stages[\"Create-release\"], \"create-release.groovy\",\n repositoryPath, gitCredentialsId, gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, defaultBranch)\n\nif (buildTool.toString().equalsIgnoreCase('none')) {\n return true\n}\n\nif (BRANCH) {\n def branch = \"${BRANCH}\"\n def formattedBranch = \"${branch.toUpperCase().replaceAll(/\\\\//, \"-\")}\"\n createListView(codebaseName, formattedBranch)\n\n def type = \"${TYPE}\"\n def crKey = getStageKeyName(buildTool)\n createCiPipeline(\"Code-review-${codebaseName}\", codebaseName, stages[crKey], \"code-review.groovy\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n def buildKey = \"Build-${type}-${buildTool.toLowerCase()}\".toString()\n if (type.equalsIgnoreCase('application') || type.equalsIgnoreCase('library')) {\n def jobExists = false\n if(\"${formattedBranch}-Build-${codebaseName}\".toString() in Jenkins.instance.getAllItems().collect{it.name})\n jobExists = true\n\n createCiPipeline(\"Build-${codebaseName}\", codebaseName, stages.get(buildKey, defaultBuild), \"build.groovy\",\n repositoryPath, gitCredentialsId, branch, gitServerCrName, gitServerCrVersion)\n\n if(!jobExists)\n queue(\"${codebaseName}/${formattedBranch}-Build-${codebaseName}\")\n }\n}\n\ndef createCiPipeline(pipelineName, codebaseName, codebaseStages, pipelineScript, repository, credId, watchBranch, gitServerCrName, gitServerCrVersion) {\n pipelineJob(\"${codebaseName}/${watchBranch.toUpperCase().replaceAll(/\\\\//, \"-\")}-${pipelineName}\") {\n logRotator {\n numToKeep(10)\n daysToKeep(7)\n }\n triggers {\n gerrit {\n events {\n if (pipelineName.contains(\"Build\"))\n changeMerged()\n else\n patchsetCreated()\n }\n project(\"plain:${codebaseName}\", [\"plain:${watchBranch}\"])\n }\n }\n definition {\n cpsScm {\n scm {\n git {\n remote {\n url(repository)\n credentials(credId)\n }\n branches(\"${watchBranch}\")\n scriptPath(\"${pipelineScript}\")\n }\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${codebaseStages}\", \"Consequence of stages in JSON format to be run during execution\")\n stringParam(\"GERRIT_PROJECT_NAME\", \"${codebaseName}\", \"Gerrit project name(Codebase name) to be build\")\n stringParam(\"BRANCH\", \"${watchBranch}\", \"Branch to build artifact from\")\n }\n }\n }\n }\n}\n\ndef getStageKeyName(buildTool) {\n if (buildTool.toString().equalsIgnoreCase('terraform')) {\n return \"Code-review-library-terraform\"\n }\n if (buildTool.toString().equalsIgnoreCase('opa')) {\n return \"Code-review-library-opa\"\n }\n if (buildTool.toString().equalsIgnoreCase('codenarc')) {\n return \"Code-review-library-codenarc\"\n }\n def buildToolsOutOfTheBox = [\"maven\",\"npm\",\"gradle\",\"dotnet\",\"none\",\"go\",\"python\"]\n def supBuildTool = buildToolsOutOfTheBox.contains(buildTool.toString())\n return supBuildTool ? \"Code-review-${TYPE}\" : \"Code-review-default\"\n}\n\ndef createReleasePipeline(pipelineName, codebaseName, codebaseStages, pipelineScript, repository, credId,\n gitServerCrName, gitServerCrVersion, jiraIntegrationEnabled, defaultBranch) {\n pipelineJob(\"${codebaseName}/${pipelineName}\") {\n logRotator {\n numToKeep(14)\n daysToKeep(30)\n }\n definition {\n cpsScm {\n scm {\n git {\n remote {\n url(repository)\n credentials(credId)\n }\n branches(\"${defaultBranch}\")\n scriptPath(\"${pipelineScript}\")\n }\n }\n parameters {\n stringParam(\"STAGES\", \"${codebaseStages}\", \"\")\n if (pipelineName.contains(\"Create-release\")) {\n stringParam(\"JIRA_INTEGRATION_ENABLED\", \"${jiraIntegrationEnabled}\", \"Is Jira integration enabled\")\n stringParam(\"GERRIT_PROJECT\", \"${codebaseName}\", \"\")\n stringParam(\"RELEASE_NAME\", \"\", \"Name of the release(branch to be created)\")\n stringParam(\"COMMIT_ID\", \"\", \"Commit ID that will be used to create branch from for new release. If empty, HEAD of master will be used\")\n stringParam(\"GIT_SERVER_CR_NAME\", \"${gitServerCrName}\", \"Name of Git Server CR to generate link to Git server\")\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"REPOSITORY_PATH\", \"${repository}\", \"Full repository path\")\n stringParam(\"DEFAULT_BRANCH\", \"${defaultBranch}\", \"Default repository branch\")\n }\n }\n }\n }\n }\n}\n\ndef createListView(codebaseName, branchName) {\n listView(\"${codebaseName}/${branchName}\") {\n if (branchName.toLowerCase() == \"releases\") {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^Create-release.*\")\n }\n }\n } else {\n jobFilters {\n regex {\n matchType(MatchType.INCLUDE_MATCHED)\n matchValue(RegexMatchValue.NAME)\n regex(\"^${branchName}-(Code-review|Build).*\")\n }\n }\n }\n columns {\n status()\n weather()\n name()\n lastSuccess()\n lastFailure()\n lastDuration()\n buildButton()\n }\n }\n}\n
Note
Please refer to the Manage Jenkins CD Pipeline Job Provisioner page for the details.
View: Default CD provisioner template for EDP 2.8.4/* Copyright 2021 EPAM Systems.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nimport groovy.json.*\nimport jenkins.model.Jenkins\n\nJenkins jenkins = Jenkins.instance\n\ndef pipelineName = \"${PIPELINE_NAME}-cd-pipeline\"\ndef stageName = \"${STAGE_NAME}\"\ndef qgStages = \"${QG_STAGES}\"\ndef gitServerCrVersion = \"${GIT_SERVER_CR_VERSION}\"\ndef gitCredentialsId = \"${GIT_CREDENTIALS_ID}\"\ndef sourceType = \"${SOURCE_TYPE}\"\ndef libraryURL = \"${LIBRARY_URL}\"\ndef libraryBranch = \"${LIBRARY_BRANCH}\"\ndef autodeploy = \"${AUTODEPLOY}\"\ndef scriptPath = \"Jenkinsfile\"\ndef containerDeploymentType = \"container\"\ndef deploymentType = \"${DEPLOYMENT_TYPE}\"\n\ndef stages = buildStages(deploymentType, containerDeploymentType, qgStages)\n\ndef codebaseFolder = jenkins.getItem(pipelineName)\nif (codebaseFolder == null) {\n folder(pipelineName)\n}\n\nif (deploymentType == containerDeploymentType) {\n createContainerizedCdPipeline(pipelineName, stageName, stages, scriptPath, sourceType,\n libraryURL, libraryBranch, gitCredentialsId, gitServerCrVersion,\n autodeploy)\n} else {\n createCustomCdPipeline(pipelineName, stageName)\n}\n\ndef buildStages(deploymentType, containerDeploymentType, qgStages) {\n return deploymentType == containerDeploymentType\n ? '[{\"name\":\"init\",\"step_name\":\"init\"},{\"name\":\"deploy\",\"step_name\":\"deploy\"},' + qgStages + ',{\"name\":\"promote-images-ecr\",\"step_name\":\"promote-images\"}]'\n : ''\n}\n\ndef createContainerizedCdPipeline(pipelineName, stageName, stages, pipelineScript, sourceType, libraryURL, libraryBranch, libraryCredId, gitServerCrVersion, autodeploy) {\n pipelineJob(\"${pipelineName}/${stageName}\") {\n if (sourceType == \"library\") {\n definition {\n cpsScm {\n scm {\n git {\n remote {\n url(libraryURL)\n credentials(libraryCredId)\n }\n branches(\"${libraryBranch}\")\n scriptPath(\"${pipelineScript}\")\n }\n }\n }\n }\n } else {\n definition {\n cps {\n script(\"@Library(['edp-library-stages', 'edp-library-pipelines']) _ \\n\\nDeploy()\")\n sandbox(true)\n }\n }\n }\n properties {\n disableConcurrentBuilds()\n }\n parameters {\n stringParam(\"GIT_SERVER_CR_VERSION\", \"${gitServerCrVersion}\", \"Version of GitServer CR Resource\")\n stringParam(\"STAGES\", \"${stages}\", \"Consequence of stages in JSON format to be run during execution\")\n\n if (autodeploy?.trim() && autodeploy.toBoolean()) {\n stringParam(\"AUTODEPLOY\", \"${autodeploy}\", \"Is autodeploy enabled?\")\n stringParam(\"CODEBASE_VERSION\", null, \"Codebase versions to deploy.\")\n }\n }\n }\n}\n\ndef createCustomCdPipeline(pipelineName, stageName) {\n pipelineJob(\"${pipelineName}/${stageName}\") {\n properties {\n disableConcurrentBuilds()\n }\n }\n}\n
Update Jenkins pipelines and stages to the new release tag:
Update the edp-admin-console Custom Resource in the KeycloakClient Custom Resource Definition:
View: keycloakclient.yamlkind: KeycloakClient\napiVersion: v1.edp.epam.com/v1alpha1\nmetadata:\n name: edp-admin-console\n namespace: <edp-namespace>\nspec:\n advancedProtocolMappers: false\n attributes: null\n audRequired: true\n clientId: admin-console-client\n directAccess: true\n public: false\n secret: admin-console-client\n serviceAccount:\n enabled: true\n realmRoles:\n - developer\n targetRealm: <keycloak-edp-realm>\n webUrl: >-\n https://edp-admin-console-example.com\n
kubectl apply -f keycloakclient.yaml\n
Remove the admin-console-client client ID in the edp-namespace-main realm in Keycloak, restart the keycloak-operator pod and check that the new KeycloakClient is created with the confidential access type.
Note
If \"Internal error\" occurs, regenerate the admin-console-client secret in the Credentials tab in Keycloak and update the admin-console-client secret key \"clientSecret\" and \"password\".
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-dotnet-21-agent:1.0.2\nepamedp/edp-jenkins-dotnet-31-agent:1.0.2\nepamedp/edp-jenkins-go-agent:1.0.3\nepamedp/edp-jenkins-gradle-java11-agent:2.0.2\nepamedp/edp-jenkins-gradle-java8-agent:1.0.2\nepamedp/edp-jenkins-helm-agent:1.0.6\nepamedp/edp-jenkins-maven-java11-agent:2.0.3\nepamedp/edp-jenkins-maven-java8-agent:1.0.2\nepamedp/edp-jenkins-npm-agent:2.0.2\nepamedp/edp-jenkins-python-38-agent:2.0.3\nepamedp/edp-jenkins-terraform-agent:2.0.4\n
data:\n codenarc-template: |-\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>codenarc</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>codenarc</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>epamedp/edp-jenkins-codenarc-agent:1.0.0</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n opa-template: |-\n <org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n <inheritFrom></inheritFrom>\n <name>opa</name>\n <namespace></namespace>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <instanceCap>2147483647</instanceCap>\n <slaveConnectTimeout>100</slaveConnectTimeout>\n <idleMinutes>5</idleMinutes>\n <activeDeadlineSeconds>0</activeDeadlineSeconds>\n <label>opa</label>\n <serviceAccount>jenkins</serviceAccount>\n <nodeSelector>beta.kubernetes.io/os=linux</nodeSelector>\n <nodeUsageMode>NORMAL</nodeUsageMode>\n <workspaceVolume class=\"org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume\">\n <memory>false</memory>\n </workspaceVolume>\n <volumes/>\n <containers>\n <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n <name>jnlp</name>\n <image>epamedp/edp-jenkins-opa-agent:1.0.1</image>\n <privileged>false</privileged>\n <alwaysPullImage>false</alwaysPullImage>\n <workingDir>/tmp</workingDir>\n <command></command>\n <args>${computer.jnlpmac} ${computer.name}</args>\n <ttyEnabled>false</ttyEnabled>\n <resourceRequestCpu></resourceRequestCpu>\n <resourceRequestMemory></resourceRequestMemory>\n <resourceLimitCpu></resourceLimitCpu>\n <resourceLimitMemory></resourceLimitMemory>\n <envVars>\n <org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n <key>JAVA_TOOL_OPTIONS</key>\n <value>-XX:+UnlockExperimentalVMOptions -Dsun.zip.disableMemoryMapping=true</value>\n </org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar>\n </envVars>\n <ports/>\n </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>\n </containers>\n <envVars/>\n <annotations/>\n <imagePullSecrets/>\n <podRetention class=\"org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default\"/>\n </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>\n
Update compatible plugins in Jenkins and install additional plugins:
Add the annotation deploy.edp.epam.com/previous-stage-name: ''
(it should be empty if the CD pipeline contains one stage) to each Custom Resource in the Custom Resource Definition Stage, for example:
kubectl get stages.v2.edp.epam.com -n <edp-namespace>
kubectl edit stages.v2.edp.epam.com <cd-stage-name> -n <edp-namespace>
apiVersion: v2.edp.epam.com/v1alpha1\nkind: Stage\nmetadata:\n annotations:\n deploy.edp.epam.com/previous-stage-name: ''\n
Note
If a pipeline contains several stages, add a previous stage name indicated in the EDP Admin Console to the annotation, for example: deploy.edp.epam.com/previous-stage-name: 'dev'
.
Execute script to align CDPipeline resources to the new API (jq command-line JSON processor is required):
pipelines=$( kubectl get cdpipelines -n <edp-namespace> -ojson | jq -c '.items[]' )\nfor p in $pipelines; do\n echo \"$p\" | \\\n jq '. | .spec.inputDockerStreams = .spec.input_docker_streams | del(.spec.input_docker_streams) | .spec += { \"deploymentType\": \"container\" } ' | \\\n kubectl apply -f -\ndone\n
Update the database in the edp-db pod in the edp-namespace:
kubectl exec -i -t -n <edp-namespace> edp-db-<pod> -c edp-db \"--\" sh -c \"(bash || ash || sh)\"\n
psql edp-db <admin>;\nSET search_path to '<edp-namespace>';\nUPDATE cd_pipeline SET deployment_type = 'container';\n
Add \"AUTODEPLOY\":\"true/false\",\"DEPLOYMENT_TYPE\":\"container\"
to every Custom Resource in jenkinsjobs.v2.edp.epam.com
:
kubectl get jenkinsjobs.v2.edp.epam.com -n <edp-namespace>\n\nkubectl edit jenkinsjobs.v2.edp.epam.com <cd-pipeline-name> -n <edp-namespace>\n
edp_namespace=<epd_namespace>\nfor stages in $(kubectl get jenkinsjobs -o=name -n $edp_namespace); do kubectl get $stages -n $edp_namespace -o yaml | grep -q \"container\" && echo -e \"\\n$stages is already updated\" || kubectl get $stages -n $edp_namespace -o yaml | sed 's/\"GIT_SERVER_CR_VERSION\"/\"AUTODEPLOY\":\"false\",\"DEPLOYMENT_TYPE\":\"container\",\"GIT_SERVER_CR_VERSION\"/g' | kubectl apply -f -; done\n
job:\n config: '{\"AUTODEPLOY\":\"false\",\"DEPLOYMENT_TYPE\":\"container\",\"GIT_SERVER_CR_VERSION\":\"v2\",\"PIPELINE_NAME\":\"your-pipeline-name\",\"QG_STAGES\":\"{\\\"name\\\":\\\"manual\\\",\\\"step_name\\\":\\\"your-step-name\\\"}\",\"SOURCE_TYPE\":\"default\",\"STAGE_NAME\":\"your-stage-name\"}'\n name: job-provisions/job/cd/job/default\n
SonarQube fails during the CI pipeline run. The previous builds of SonarQube used the latest version of the OpenID Connect Authentication for SonarQube plugin. Version 2.1.0 of this plugin may have issues with the connection, so it is necessary to downgrade it in order to get rid of errors in the pipeline. Take the following steps:
kubectl exec -i -t -n <edp-namespace> sonar-<pod> -c sonar \"--\" sh -c \"(bash || ash || sh)\"\n
rm extensions/plugins/sonar-auth-oidc-plugin*\n
curl -L https://github.com/vaulttec/sonar-auth-oidc/releases/download/v2.0.0/sonar-auth-oidc-plugin-2.0.0.jar --output extensions/plugins/sonar-auth-oidc-plugin-2.0.0.jar\n
The Helm lint checker in EDP 2.8.4 has some additional rules. There can be issues with it during the Code Review pipeline in Jenkins for applications that were transferred from previous EDP versions to EDP 2.8.4. To fix this, add the following annotation to the Chart.yaml
file:
deploy-templates/Chart.yaml
file.Chart.yaml
file:home: https://github.com/your-repo.git\nsources:\n - https://github.com/your-repo.git\nmaintainers:\n - name: DEV Team\n
This section provides the details on the EDP upgrade to 2.9.0. Explore the actions and requirements below.
Note
Kiosk is optional for EDP v.2.9.0 and higher, and enabled by default. To disable it, add the following parameter to the values.yaml
file: kioskEnabled: false
. Please refer to the Set Up Kiosk documentation for the details.
With Amazon Elastic Container Registry to store the images, there are two options:
Before updating EDP to 2.9.0, update the gerrit-is-credentials
secret by adding the new clientSecret
key with the value from gerrit-is-credentials.client_secret
:
kubectl edit secret gerrit-is-credentials -n <edp-namespace>\n
data:\n client_secret: example\n clientSecret: example\n
Update Custom Resource Definitions. This command will apply all the necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_gerritgroupmember_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_gerritgroup_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_gerritprojectaccess_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_gerritproject_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_jenkins_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_jenkinsagent_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_jenkinsauthorizationrolemapping_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/release/2.9/deploy-templates/crds/v2_v1alpha1_jenkinsauthorizationrole_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.9/deploy-templates/crds/v1_v1alpha1_keycloakclientscope_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.9/deploy-templates/crds/v1_v1alpha1_keycloakrealmuser_crd.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/release/2.9/deploy-templates/crds/edp_v1alpha1_nexus_crd.yaml\n
With Amazon Elastic Container Registry to store and Kaniko to build the images, add the kanikoRoleArn parameter to the values before starting the update process. This parameter is indicated in AWS Roles once IRSA is enabled and AWS IAM Role is created for Kaniko.The value should look as follows:
kanikoRoleArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039EDP_NAMESPACE\u203aKaniko\n
To upgrade EDP to the v.2.9.0, run the following command:
helm upgrade --install edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.9.0\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with: helm upgrade --install edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=2.9.0 --dry-run
Remove the following Kubernetes resources left from the previous EDP installation (it is optional):
kubectl delete rolebinding edp-cd-pipeline-operator-<edp-namespace>-admin -n <edp-namespace>\n
After EDP update, please restart the 'sonar-operator' pod to address the proper Sonar plugin versioning. After 'sonar-operator' is restarted, check the list of installed plugins in the corresponding SonarQube menu.
Update Jenkins pipelines and stages to the new release tag:
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:1.0.1\nepamedp/edp-jenkins-dotnet-21-agent:1.0.3\nepamedp/edp-jenkins-dotnet-31-agent:1.0.3\nepamedp/edp-jenkins-go-agent:1.0.4\nepamedp/edp-jenkins-gradle-java8-agent:1.0.3\nepamedp/edp-jenkins-gradle-java11-agent:2.0.3\nepamedp/edp-jenkins-helm-agent:1.0.7\nepamedp/edp-jenkins-maven-java8-agent:1.0.3\nepamedp/edp-jenkins-maven-java11-agent:2.0.4\nepamedp/edp-jenkins-npm-agent:2.0.3\nepamedp/edp-jenkins-opa-agent:1.0.2\nepamedp/edp-jenkins-python-38-agent:2.0.4\nepamedp/edp-jenkins-terraform-agent:2.0.5\n
Update the compatible plugins in Jenkins:
Important
global.kioskEnabled
parameter in the values.yaml file. For details, please refer to the Set Up Kiosk page.gerrit-ssh-port
parameter is moved from the gerrit-operator.gerrit.sshport
to global.gerritSSHPort
values.yaml file.gitServer.user
value is changed from the jenkins
to edp-ci
values.yaml file.This section provides the details on upgrading EDP to 3.0. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/d9a4d15244c527ef6d1d029af27574282a281b98/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_cdstagedeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_codebasebranches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_codebaseimagestreams.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_gittags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_imagestreamtags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_jiraissuemetadatas.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/release/2.14/deploy-templates/crds/v2.edp.epam.com_jiraservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakauthflows.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakclients.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakclientscopes.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmidentityproviders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmrolebatches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealms.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloakrealmusers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/release/1.14/deploy-templates/crds/v1.edp.epam.com_keycloaks.yaml\n
Set the required parameters. For more details, please refer to the values.yaml file.
View: values.yamledp-tekton:\n enabled: false\nadmin-console-operator:\n enabled: true\njenkins-operator:\n enabled: true\n
Add proper Helm annotations and labels as indicated below. This step is necessary starting from the release v.3.0.x as custom resources are managed by Helm and removed from the Keycloak Controller logic.
kubectl label EDPComponent main-keycloak app.kubernetes.io/managed-by=Helm -n <edp-namespace>\n kubectl annotate EDPComponent main-keycloak meta.helm.sh/release-name=<edp-release-name> -n <edp-namespace>\n kubectl annotate EDPComponent main-keycloak meta.helm.sh/release-namespace=<edp-namespace> -n <edp-namespace>\n kubectl label KeycloakRealm main app.kubernetes.io/managed-by=Helm -n <edp-namespace>\n kubectl annotate KeycloakRealm main meta.helm.sh/release-name=<edp-release-name> -n <edp-namespace>\n kubectl annotate KeycloakRealm main meta.helm.sh/release-namespace=<edp-namespace> -n <edp-namespace>\n
To upgrade EDP to 3.0, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.0.x\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.0.x --dry-run
Update image versions for the Jenkins agents in the ConfigMap:
kubectl edit configmap jenkins-slaves -n <edp-namespace>\n
epamedp/edp-jenkins-codenarc-agent:3.0.10\nepamedp/edp-jenkins-dotnet-31-agent:3.0.9\nepamedp/edp-jenkins-go-agent:3.0.17\nepamedp/edp-jenkins-gradle-java11-agent:3.0.7\nepamedp/edp-jenkins-gradle-java8-agent:3.0.10\nepamedp/edp-jenkins-helm-agent:3.0.11\nepamedp/edp-jenkins-kaniko-docker-agent:1.0.9\nepamedp/edp-jenkins-maven-java11-agent:3.0.7\nepamedp/edp-jenkins-maven-java8-agent:3.0.10\nepamedp/edp-jenkins-npm-agent:3.0.9\nepamedp/edp-jenkins-opa-agent:3.0.7\nepamedp/edp-jenkins-python-38-agent:3.0.8\nepamedp/edp-jenkins-sast-agent:0.1.5\nepamedp/edp-jenkins-terraform-agent:3.0.9\n
edp-jenkins-dotnet-21-agent
agent manifest.Attach the id_rsa.pub
SSH public key from the gerrit-ciuser-sshkey
secret to the edp-ci
Gerrit user in the gerrit
pod:
ssh -p <gerrit_ssh_port> <host> gerrit set-account --add-ssh-key ~/id_rsa.pub\n
Notes
gerrit-admin
SSH key from secrets.<host>
is admin@localhost or any other user with permissions.Change the username from jenkins
to edp-ci
in the gerrit-ciuser-sshkey
secret:
kubectl -n <edp-namespace> patch secret gerrit-ciuser-sshkey\\\n --patch=\"{\\\"data\\\": { \\\"username\\\": \\\"$(echo -n edp-ci |base64 -w0)\\\" }}\" -oyaml\n
Warning
In EDP v.3.0.x, Admin Console is deprecated, and EDP interface is available only via EDP Portal.
"},{"location":"operator-guide/upgrade-edp-3.0/#related-articles","title":"Related Articles","text":"Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides the details on the EDP upgrade to v3.1. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.13.2/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.13.4/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\n
To upgrade EDP to the v3.1, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.1.0\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.1.0 --dry-run
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides the details on the EDP upgrade to v3.2.2. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_cdstagedeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_codebasebranches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_codebaseimagestreams.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_gittags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_imagestreamtags.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_jiraissuemetadatas.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_jiraservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_cdstagejenkinsdeployments.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsagents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsauthorizationrolemappings.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsauthorizationroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsfolders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsjobbuildruns.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsjobs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsscripts.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinsserviceaccounts.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_jenkinssharedlibraries.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-component-operator/v0.13.0/deploy-templates/crds/v1.edp.epam.com_edpcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/v2.14.1/deploy-templates/crds/v2.edp.epam.com_cdpipelines.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/v2.14.1/deploy-templates/crds/v2.edp.epam.com_stages.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/v2.14.1/deploy-templates/crds/v2.edp.epam.com_nexuses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-nexus-operator/v2.14.1/deploy-templates/crds/v2.edp.epam.com_nexususers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_sonargroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_sonarpermissiontemplates.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-sonar-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_sonars.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritgroupmembers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritmergerequests.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritprojectaccesses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritprojects.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerritreplicationconfigs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.14.0/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/v2.13.0/deploy-templates/crds/v2.edp.epam.com_perfdatasourcegitlabs.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/v2.13.0/deploy-templates/crds/v2.edp.epam.com_perfdatasourcejenkinses.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/v2.13.0/deploy-templates/crds/v2.edp.epam.com_perfdatasourcesonars.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-perf-operator/v2.13.0/deploy-templates/crds/v2.edp.epam.com_perfservers.yaml\n
Generate a cookie-secret for proxy with the following command:
nexus_proxy_cookie_secret=$(openssl rand -base64 32 | head -c 32)\n
Create nexus-proxy-cookie-secret
in the namespace: kubectl -n <edp-project> create secret generic nexus-proxy-cookie-secret \\\n --from-literal=cookie-secret=${nexus_proxy_cookie_secret}\n
EDP 3.2.2 features OIDC configuration for EDP Portal. If this parameter is required, create keycloak-client-headlamp-secret
as described in this article:
kubectl -n <edp-project> create secret generic keycloak-client-edp-portal-secret \\\n --from-literal=clientSecret=<keycloak_client_secret_key>\n
Delete the following resources:
kubectl -n <edp-project> delete KeycloakClient nexus\nkubectl -n <edp-project> delete EDPComponent nexus\nkubectl -n <edp-project> delete Ingress nexus\nkubectl -n <edp-project> delete deployment edp-tekton-dashboard\n
EDP release 3.2.2 uses the default cluster storageClass and we must check previous storageClass parameters. Align , if required, the storageClassName
in EDP values.yaml
to the same that were used by EDP PVC. For example:
edp-tekton:\n buildTool:\n go:\n cache:\n persistentVolume:\n # -- Specifies storageClass type. If not specified, a default storageClass for go-cache volume is used\n storageClass: ebs-sc\n\njenkins-operator:\n enabled: true\n jenkins:\n storage:\n # -- Storageclass for Jenkins data volume\n class: gp2\n\nsonar-operator:\n sonar:\n storage:\n data:\n # -- Storageclass for Sonar data volume\n class: gp2\n database:\n # -- Storageclass for database data volume\n class: gp2\n\ngerrit-operator:\n gerrit:\n storage:\n # -- Storageclass for Gerrit data volume\n class: gp2\n\nnexus-operator:\n nexus:\n storage:\n # -- Storageclass for Nexus data volume\n class: gp2\n
To upgrade EDP to the v3.2.2, run the following command:
helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.2.2\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the following command: helm upgrade edp epamedp/edp-install -n <edp-namespace> --values values.yaml --version=3.2.2 --dry-run
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
Note
We currently disabled cache volumes for go and npm in the EDP 3.3 release.
This section provides the details on the EDP upgrade to v3.3.0. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.16.0/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-jenkins-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_jenkins.yaml\n
If you use Gerrit VCS, delete the corresponding resource due to changes in annotations:
kubectl -n edp delete EDPComponent gerrit\n
The deployment will create a new EDPComponent called gerrit
instead. To upgrade EDP to the v3.3.0, run the following command:
helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.3.0\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the --dry-run
tag: helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.3.0 --dry-run
In EDP v3.3.0, a new feature was introduced allowing manual pipeline re-triggering by sending a comment with /recheck
. To enable the re-trigger feature for applications that were added before the upgrade, please proceed with the following:
4.1 For Gerrit VCS, add the following event to the webhooks.config
configuration file in the All-Projects
repository:
[remote \"commentadded\"]\n url = http://el-gerrit-listener:8080\n event = comment-added\n
4.2 For GitHub VCS, check the Issue comments
permission for each webhook in every application added before the EDP upgrade to 3.3.0.
4.3 For GitLab VCS, check the Comments
permission for each webhook in every application added before the EDP upgrade to 3.3.0.
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
Note
Pay attention that the following components: perf-operator
, edp-admin-console
, edp-admin-console-operator
, and edp-jenkins-operator
are deprecated and should be additionally migrated in order to avoid their deletion. For migration details, please refer to the Migrate CI Pipelines From Jenkins to Tekton instruction.
This section provides the details on the EDP upgrade to v3.4.1. Explore the actions and requirements below.
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_cdpipelines.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-cd-pipeline-operator/v2.15.0/deploy-templates/crds/v2.edp.epam.com_stages.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_clusterkeycloakrealms.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_clusterkeycloaks.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakauthflows.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakclients.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakclientscopes.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmcomponents.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmgroups.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmidentityproviders.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmrolebatches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmroles.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealms.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloakrealmusers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-keycloak-operator/v1.17.0/deploy-templates/crds/v1.edp.epam.com_keycloaks.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_templates.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_codebasebranches.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_codebaseimagestreams.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.17.0/deploy-templates/crds/v2.edp.epam.com_jiraservers.yaml\nkubectl apply -f https://raw.githubusercontent.com/epam/edp-gerrit-operator/v2.16.0/deploy-templates/crds/v2.edp.epam.com_gerrits.yaml\n
Remove deprecated components:
View: values.yaml
perf-operator:\n enabled: false\nadmin-console-operator:\n enabled: false\njenkins-operator:\n enabled: false\n
Since the values.yaml file structure has been modified, move the dockerRegistry subsection to the global section:
The dockerRegistry value has been moved to the global section:
global:\n dockerRegistry:\n # -- Define Image Registry that will to be used in Pipelines. Can be ecr (default), harbor\n type: \"ecr\"\n # -- Docker Registry endpoint\n url: \"<AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com\"\n
(Optional) To integrate EDP with Jira, rename the default values from epam-jira-user
to jira-user
for a secret name. In case Jira is already integrated, it will continue working.
codebase-operator:\n jira:\n credentialName: \"jira-user\"\n
(Optional) To switch to the Harbor registry, change the secret format for the external secret from kaniko-docker-config v3.3.0 to kaniko-docker-config v3.4.1:
View: old format \"kaniko-docker-config\": {\"secret-string\"} //base64 format\n
View: new format \"kaniko-docker-config\": {\n \"auths\" : {\n \"registry.com\" :\n {\"username\":\"<registry-username>\",\"password\":\"<registry-password>\",\"auth\":\"secret-string\"}\n }\n}\n
To upgrade EDP to the v3.4.1, run the following command:
helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.4.1\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the --dry-run
tag: helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.4.1 --dry-run
Important
We suggest making a backup of the EDP environment before starting the upgrade procedure.
This section provides detailed instructions for upgrading EPAM Delivery Platform to version 3.5.3. Follow the steps and requirements outlined below:
Update Custom Resource Definitions (CRDs). Run the following command to apply all necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.19.0/deploy-templates/crds/v2.edp.epam.com_gitservers.yaml\n
Danger
Codebase-operator v2.19.0 is not compatible with the previous versions. Please become familiar with the breaking change in Git Server Custom Resource Definition.
Familiarize yourself with the updated file structure of the values.yaml file and adjust your values.yaml file accordingly:
By default, the deployment of sub components such as edp-sonar-operator
, edp-nexus-operator
, edp-gerrit-operator
, and keycloak-operator
, have been disabled. Set them back to true
in case they are needed or manually deploy external tools, such as SonarQube, Nexus, Gerrit and integrate them with the EPAM Delivery Platform.
The default Git provider has been changed from Gerrit to GitHub:
Old format:
global:\n gitProvider: gerrit\n gerritSSHPort: \"22\"\n
New format:
global:\n gitProvider: github\n #gerritSSHPort: \"22\"\n
The sonarUrl and nexusUrl parameters have been deprecated. All the URLs from external components are stored in integration secrets:
global:\n # -- Optional parameter. Link to use custom sonarqube. Format: http://<service-name>.<sonarqube-namespace>:9000 or http://<ip-address>:9000\n sonarUrl: \"\"\n # -- Optional parameter. Link to use custom nexus. Format: http://<service-name>.<nexus-namespace>:8081 or http://<ip-address>:<port>\n nexusUrl: \"\"\n
Keycloak integration has been moved from the global section to the sso section. Update the parameters accordingly:
Old format:
global:\n # -- Keycloak URL\n keycloakUrl: https://keycloak.example.com\n # -- Administrators of your tenant\n admins:\n - \"stub_user_one@example.com\"\n # -- Developers of your tenant\n developers:\n - \"stub_user_one@example.com\"\n - \"stub_user_two@example.com\"\n
New format:
sso:\n enabled: true\n # -- Keycloak URL\n keycloakUrl: https://keycloak.example.com\n # -- Administrators of your tenant\n admins:\n - \"stub_user_one@example.com\"\n # -- Developers of your tenant\n developers:\n - \"stub_user_one@example.com\"\n - \"stub_user_two@example.com\"\n
(Optional) The default secret name for Jira integration has been changed from jira-user
to ci-jira
. Please adjust the secret name in the parameters accordingly:
codebase-operator:\n jira:\n credentialName: \"ci-jira\"\n
The secret naming and format have been refactored. Below are patterns of the changes for various components:
SonarQubeNexusDependency-TrackDefectDojoJiraGitLabGitHubOld format:
\"sonar-ciuser-token\": {\n \"username\": \"xxxxx\",\n \"secret\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"\n }\n
New format: \"ci-sonarqube\": {\n \"token\": \"xxxxxxxxxxxxxxxxxxxxxxx\",\n \"url\":\"https://sonar.example.com\"\n }\n
Old format:
\"nexus-ci-user\": {\n \"username\": \"xxxxx\",\n \"password\": \"xxxxxxxxxxxxxxxxxx\"\n }\n
New format:
\"ci-nexus\": {\n \"username\": \"xxxxx\",\n \"password\": \"xxxxx\",\n \"url\": \"http://nexus.example.com\"\n }\n
Old format:
\"ci-dependency-track\": {\n \"token\": \"xxxxxxxxxxxxxxxxxx\"\n }\n
New format:
\"ci-dependency-track\": {\n \"token\": \"xxxxxxxxxxxxxxxxxx\",\n \"url\": \"http://dependency-track.example.com\"}\n
Old format:
\"defectdojo-ciuser-token\": {\n \"token\": \"xxxxxxxxxxxxxxxxxx\"\n \"url\": \"http://defectdojo.example.com\"\n }\n
New format:
\"ci-defectdojo\": {\n \"token\": \"xxxxxxxxxxxxxxxxxx\",\n \"url\": \"http://defectdojo.example.com\"\n }\n
Old format:
\"jira-user\": {\n \"username\": \"xxxxx\",\n \"password\": \"xxxxx\"\n }\n
New format:
\"ci-jira\": {\n \"username\": \"xxxxx\",\n \"password\": \"xxxxx\"\n }\n
Old format:
\"gitlab\": {\n \"id_rsa\": \"xxxxxxxxxxxxxx\",\n \"token\": \"xxxxxxxxxxxxxx\",\n \"secretString\": \"xxxxxxxxxxxxxx\"\n }\n
New format:
\"ci-gitlab\": {\n \"id_rsa\": \"xxxxxxxxxxxxxx\",\n \"token\": \"xxxxxxxxxxxxxx\",\n \"secretString\": \"xxxxxxxxxxxxxx\"\n }\n
Old format:
\"github\": {\n \"id_rsa\": \"xxxxxxxxxxxxxx\",\n \"token\": \"xxxxxxxxxxxxxx\",\n \"secretString\": \"xxxxxxxxxxxxxx\"\n }\n
New format:
\"ci-github\": {\n \"id_rsa\": \"xxxxxxxxxxxxxx\",\n \"token\": \"xxxxxxxxxxxxxx\",\n \"secretString\": \"xxxxxxxxxxxxxx\"\n }\n
The tables below illustrate the difference between the old and new format:
Old format
Secret Name Username Password Token Secret URL jira-user * * nexus-ci.user * * sonar-ciuser-token * * defectdojo-ciuser-token * * ci-dependency-track *New format
Secret Name Username Password Token URL ci-jira * * ci-nexus * * * ci-sonarqube * * ci-defectdojo * * ci-dependency-track * *To upgrade EDP to the v3.5.3, run the following command:
helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.5.3\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the --dry-run
tag: helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.5.3 --dry-run
Important
We suggest backing up the EDP environment before starting the upgrade procedure.
This section provides detailed instructions for upgrading the EPAM Delivery Platform to version 3.6.0. Follow the steps and requirements outlined below:
Update Custom Resource Definitions (CRDs). Run the following command to apply all the necessary CRDs to the cluster:
kubectl apply -f https://raw.githubusercontent.com/epam/edp-codebase-operator/v2.20.0/deploy-templates/crds/v2.edp.epam.com_codebases.yaml\n
Familiarize yourself with the updated structure of the values.yaml file and adjust it accordingly:
2.1 A new parameter called space has been added to the DockerRegistry
section. It is designed to form URLs in CodebaseImageStreams. This parameter is set the same as the EPAM Delivery Platform
namespace name. Ensure you define the space
parameter prior to the update.
Warning
This parameter is a significant change and must be set before the update.
global:\n dockerRegistry:\n type: \"harbor\"\n url: \"registry.example.com\"\n space: \"edp\"\n
2.2 Subcomponents, such as sonar-operator, nexus-operator, and keycloak-operator, have been removed since dependencies are no longer provisioned by the edp-install Helm Chart. To install and integrate shared components with EDP, please use the edp-cluster-add-ons approach or refer to the SonarQube Integration and Nexus Sonatype Integration documentation pages.
2.3 The Argo CD integration dependency has been deleted as now we implement it using edp-cluster-add-ons approach. To install and integrate Argo CD as a shared component, use the edp-cluster-add-ons approach.
2.4 The handling of secrets for stages namespaces in the cd-pipeline-operator has been updated. The parameter manageSecrets
has been replaced with secretManager
. If your environment previously utilized this parameter, manually modify it from manageSecrets: true
to secretManager: own
. Otherwise, set it to secretManager: none
:
cd-pipeline-operator:\n # -- flag that indicates whether the operator should manage secrets for stages;\n # own - just copy secrets;\n # eso - secrete will be managed by External Secrets Operator(operator should be installed in the cluster);\n # none - not enable secrets management logic;\n secretManager: none\n
To upgrade EDP to the v3.6.0, run the following command:
helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.6.0\n
Note
To verify the installation, it is possible to test the deployment before applying it to the cluster with the --dry-run
tag: helm upgrade edp epamedp/edp-install -n edp --values values.yaml --version=3.6.0 --dry-run
Starting from Keycloak v.18.x.x, the Keycloak server has been moved from the Wildfly (JBoss) Application Server to Quarkus framework and is called Keycloak.X.
There are two ways to upgrade Keycloak v.17.0.x-legacy to v.19.0.x on Kubernetes, please perform the steps described in the Prerequisites section of this tutorial, and then select a suitable upgrade strategy for your environment:
Before upgrading Keycloak, please perform the steps below:
Create a backup/snapshot of the Keycloak database volume. Locate the AWS volumeID
and then create its snapshot on AWS:
Find the PVC
name attached to the Postgres pod. It can be similar to data-keycloak-postgresql-0
if the Postgres StatefulSet
name is keycloak-postgresql
:
kubectl get pods keycloak-postgresql-0 -n security -o jsonpath='{.spec.volumes[*].persistentVolumeClaim.claimName}{\"\\n\"}'\n
Locate the PV
volumeName
in the data-keycloak-postgresql-0
Persistent Volume Claim:
kubectl get pvc data-keycloak-postgresql-0 -n security -o jsonpath='{.spec.volumeName}{\"\\n\"}'\n
Get volumeID
in the Persistent Volume:
kubectl get pv ${pv_name} -n security -o jsonpath='{.spec.awsElasticBlockStore.volumeID}{\"\\n\"}'\n
Add two additional keys: password
and postgres-password
, to the keycloak-postgresql
secret in the Keycloak namespace.
Note
password
key must have the same value as the postgresql-password
key.postgres-password
key must have the same value as the postgresql-postgres-password
key.The latest chart for Keycloak.X does not have an option to override Postgres password and admin password keys in the secret, and it uses the Postgres defaults, therefore, a new secret scheme must be implemented:
kubectl -n security edit secret keycloak-postgresql\n
data:\n postgresql-password: XXXXXX\n postgresql-postgres-password: YYYYYY\n password: XXXXXX\n postgres-password: YYYYYY\n
Save Keycloak StatefulSet
names, for example, keycloak
and keycloak-postgresql
. These names will be used in the new Helm deployments:
$ kubectl get statefulset -n security\nNAME READY AGE\nkeycloak 1/1 18h\nkeycloak-postgresql 1/1 18h\n
To upgrade Keycloak by upgrading Postgres Database to a minor release v.11.17, perform the steps described in the Prerequisites section of this tutorial, and then perform the following steps:
"},{"location":"operator-guide/upgrade-keycloak-19.0/#delete-keycloak-resources","title":"Delete Keycloak Resources","text":"Delete Keycloak
and Prostgres
StatefulSets
:
kubectl delete statefulset keycloak keycloak-postgresql -n security\n
Delete the Keycloak Ingress
object, to prevent hostname duplication issues:
kubectl delete ingress keycloak -n security\n
Make sure the Keycloak chart repository is added:
helm repo add codecentric https://codecentric.github.io/helm-charts\nhelm repo update\n
Create values for Keycloak:
Note
Since the Keycloak.X release, Keycloak and Postgres database charts are separated. Upgrade Keycloak, and then install the Postgres database.
Note
nameOverride: \"keycloak\"
sets the name of the Keycloak pod. It must be the same Keycloak name as in the previous StatefulSet
.hostname: keycloak-postgresql
is the hostname of the pod with the Postgres database that is the same as Postgres StatefulSet name, for example, keycloak-postgresql
.\"/opt/keycloak/bin/kc.sh start --auto-build\"
was used in the legacy Keycloak version. However, it is no longer required in the new Keycloak version since it is deprecated and used by default.Optionally, use the following command for applying the old Keycloak theme:
bin/kc.sh start --features-disabled=admin2\n
nameOverride: \"keycloak\"\n\nreplicas: 1\n\n# Deploy the latest verion\nimage:\n tag: \"19.0.1\"\n\n# start: create OpenShift realm which is required by EDP\nextraInitContainers: |\n - name: realm-provider\n image: busybox\n imagePullPolicy: IfNotPresent\n command:\n - sh\n args:\n - -c\n - |\n echo '{\"realm\": \"openshift\",\"enabled\": true}' > /opt/keycloak/data/import/openshift.json\n volumeMounts:\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumeMounts: |\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumes: |\n - name: realm\n emptyDir: {}\n\ncommand:\n - \"/opt/keycloak/bin/kc.sh\"\n - \"--verbose\"\n - \"start\"\n - \"--http-enabled=true\"\n - \"--http-port=8080\"\n - \"--hostname-strict=false\"\n - \"--hostname-strict-https=false\"\n - \"--spi-events-listener-jboss-logging-success-level=info\"\n - \"--spi-events-listener-jboss-logging-error-level=warn\"\n - \"--import-realm\"\n\nextraEnv: |\n - name: KC_PROXY\n value: \"passthrough\"\n - name: KEYCLOAK_ADMIN\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: username\n - name: KEYCLOAK_ADMIN_PASSWORD\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: password\n - name: JAVA_OPTS_APPEND\n value: >-\n -XX:+UseContainerSupport\n -XX:MaxRAMPercentage=50.0\n -Djava.awt.headless=true\n -Djgroups.dns.query={{ include \"keycloak.fullname\" . }}-headless\n\n# This block should be uncommented if you install Keycloak on Kubernetes\ningress:\n enabled: true\n annotations:\n kubernetes.io/ingress.class: nginx\n ingress.kubernetes.io/affinity: cookie\n rules:\n - host: keycloak.<ROOT_DOMAIN>\n paths:\n - path: '{{ tpl .Values.http.relativePath $ | trimSuffix \"/\" }}/'\n pathType: Prefix\n\n# This block should be uncommented if you set Keycloak to OpenShift and change the host field\n# route:\n# enabled: false\n# # Path for the Route\n# path: '/'\n# # Host name for the Route\n# host: \"keycloak.<ROOT_DOMAIN>\"\n# # TLS configuration\n# tls:\n# enabled: true\n\nresources:\n limits:\n memory: \"2048Mi\"\n requests:\n cpu: \"50m\"\n memory: \"512Mi\"\n\n# Check database readiness at startup\ndbchecker:\n enabled: true\n\ndatabase:\n vendor: postgres\n existingSecret: keycloak-postgresql\n hostname: keycloak-postgresql\n port: 5432\n username: admin\n database: keycloak\n
Upgrade the Keycloak Helm chart:
Note
helm upgrade keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security\n
Note
If there are error messages when upgrading via Helm, make sure that StatefulSets
are removed. If they are removed and the error still persists, try to add the --force
flag to the Helm command:
helm upgrade keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security --force\n
Add Bitnami chart repository and update Helm repos:
helm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n
Create values for Postgres:
Note
fullnameOverride: \"keycloak-postgresql\"
sets the name of the Postgres StatefulSet. It must be the same as in the previous StatefulSet
.fullnameOverride: \"keycloak-postgresql\"\n\n# PostgreSQL read only replica parameters\nreadReplicas:\n # Number of PostgreSQL read only replicas\n replicaCount: 1\n\nglobal:\n postgresql:\n auth:\n username: admin\n existingSecret: keycloak-postgresql\n secretKeys:\n adminPasswordKey: postgres-password\n userPasswordKey: password\n database: keycloak\n\nimage:\n registry: docker.io\n repository: bitnami/postgresql\n tag: 11.17.0-debian-11-r3\n\nauth:\n existingSecret: keycloak-postgresql\n secretKeys:\n adminPasswordKey: postgres-password\n userPasswordKey: password\n\nprimary:\n persistence:\n enabled: true\n size: 3Gi\n # If the StorageClass with reclaimPolicy: Retain is used, install an additional StorageClass before installing PostgreSQL\n # (the code is given below).\n # If the default StorageClass will be used - change \"gp2-retain\" to \"gp2\"\n storageClass: \"gp2-retain\"\n
Install the Postgres database chart:
Note
Change the namespace and the values file name if required.
helm install postgresql bitnami/postgresql \\\n--version 11.7.6 \\\n--values postgres-values.yaml \\\n--namespace security\n
Log in to Keycloak and check that everything works as expected.
Optionally, run the vacuumdb application on the database, to recover space occupied by \"dead tuples\" in the tables, analyze the contents of database tables, and collect statistics for PostgreSQL query engine to improve performance:
PGPASSWORD=\"${postgresql_postgres-password}\" vacuumdb --analyze --verbose -d keycloak -U postgres\n
For all databases, run the following command: PGPASSWORD=\"${postgresql_postgres-password}\" vacuumdb --analyze --verbose --all -U postgres\n
"},{"location":"operator-guide/upgrade-keycloak-19.0/#migrate-postgres-database-from-postgres-v11x-to-v145","title":"Migrate Postgres Database From Postgres v.11.x to v.14.5","text":"Info
There is a Postgres database migration script at the end of this tutorial. Please read the section below before using the script.
To upgrade Keycloak by migrating Postgres database from Postgres v.11.x to v.14.5, perform the steps described in the Prerequisites section of this tutorial, and then perform the following steps:
"},{"location":"operator-guide/upgrade-keycloak-19.0/#export-postgres-databases","title":"Export Postgres Databases","text":"Log in to the current Keycloak Postgres pod and create a logical backup of all roles and databases using the pg_dumpall application. If there is no access to the Postgres Superuser, backup the Keycloak database with the pg_dump application:
Note
postgresql-postgres-password
is for the postgres
Superuser and postgresql-password
is for admin
user. The admin
user is indicated by default in the Postgres Helm chart. The admin
user may not have enough permissions to dump all Postgres databases and roles, so the preferred option for exporting all objects is using the pg_dumpall
tool with the postgres
Superuser.PGPASSWORD
variable is not specified before using the pg_dumpall
tool, you will be prompted to enter a password for each database during the export.-l keycloak
parameter is specified, pg_dumpall
will connect to the keycloak
database for dumping global objects and discovering what other databases should be dumped. By default, pg_dumpall
will try to connect to postgres
or template1
databases. This parameter is optional.pg_dumpall --clean
option adds SQL commands to the dumped file for dropping databases before recreating them during import, as well as DROP
commands for roles and tablespaces (pg_dump
also has this option). If the --clean
parameter is specified, connect to the postgres
database initially during import via psql
. The psql
script will attempt to drop other databases immediately, and that will fail for the database you are connected to. This flag is optional, and it is not included into this tutorial.PGPASSWORD=\"${postgresql_postgres-password}\" pg_dumpall -h localhost -p 5432 -U postgres -l keycloak > /tmp/keycloak_wildfly_db_dump.sql\n
Note
If there is no working password for the postgres
Superuser, try the admin
user using the pg_dump tool to export the keycloak
database without global roles:
PGPASSWORD=\"${postgresql_password}\" pg_dump -h localhost -p 5432 -U admin -d keycloak > /tmp/keycloak_wildfly_db_dump.sql\n
Info
Double-check that the contents of the dumped file is not empty. It usually contains more than 4000 lines.
Copy the file with the database dump to a local machine. Since tar
may not be present in the pod and kubectl cp
will not work without tar
, use the following command:
kubectl exec -n security ${postgresql_pod} -- cat /tmp/keycloak_wildfly_db_dump.sql > keycloak_wildfly_db_dump.sql\n
Note
Please find below the alternative commands for exporting the database to the local machine without copying the file to a pod for Postgres and admin users:
kubectl exec -n security ${postgresql_pod} \"--\" sh -c \"PGPASSWORD='\"${postgresql_postgres-password}\"' pg_dumpall -h localhost -p 5432 -U postgres\" > keycloak_wildfly_db_dump.sql\nkubectl exec -n security ${postgresql_pod} \"--\" sh -c \"PGPASSWORD='\"${postgresql_password}\"' pg_dump -h localhost -p 5432 -U admin -d keycloak\" > keycloak_wildfly_db_dump.sql\n
Delete the dumped file from the pod for security reasons:
kubectl exec -n security ${postgresql_pod} \"--\" sh -c \"rm /tmp/keycloak_wildfly_db_dump.sql\"\n
Delete all previous Keycloak resources along with the Postgres database and keycloak StatefulSets
, Ingress
, and custom resources via Helm, or via the tool used for their deployment.
helm list -n security\nhelm delete keycloak -n security\n
Warning
Don't delete the whole namespace. Keep the keycloak-postgresql
and keycloak-admin-creds
secrets.
Delete the volume in AWS, from which a snapshot has been created. Then delete the PVC:
kubectl delete pvc data-keycloak-postgresql-0 -n security\n
Add Bitnami chart repository and update Helm repos:
helm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n
Create Postgres values:
Note
fullnameOverride: \"keycloak-postgresql\"
sets the name of the Postgres StatefulSet. It must be same as in the previous StatefulSet
.
nameOverride: \"keycloak-postgresql\"\n\n# PostgreSQL read only replica parameters\nreadReplicas:\n # Number of PostgreSQL read only replicas\n replicaCount: 1\n\nglobal:\n postgresql:\n auth:\n username: admin\n existingSecret: keycloak-postgresql\n secretKeys:\n adminPasswordKey: postgres-password\n userPasswordKey: password\n database: keycloak\n\nauth:\n existingSecret: keycloak-postgresql\n secretKeys:\n adminPasswordKey: postgres-password\n userPasswordKey: password\n\nprimary:\n persistence:\n enabled: true\n size: 3Gi\n # If the StorageClass with reclaimPolicy: Retain is used, install an additional StorageClass before installing PostgreSQL\n # (the code is given below).\n # If the default StorageClass will be used - change \"gp2-retain\" to \"gp2\"\n storageClass: \"gp2-retain\"\n
Install the Postgres database:
Note
Change the namespace and the values file name if required.
helm install postgresql bitnami/postgresql \\\n--version 11.7.6 \\\n--values postgres-values.yaml \\\n--namespace security\n
Wait for the database to be ready.
Upload the database dump to the new Keycloak Postgres pod:
cat keycloak_wildfly_db_dump.sql | kubectl exec -i -n security ${postgresql_pod} \"--\" sh -c \"cat > /tmp/keycloak_wildfly_db_dump.sql\"\n
Warning
Database import must be done before deploying Keycloak, because Keycloak will write its own data to the database during the start, and the import will partially fail. If that happened, scale down the keycloak StatefulSet
, and try to drop the Keycloak database in the Postgres pod:
dropdb -i -e keycloak -p 5432 -h localhost -U postgres\n
If there still are some conflicting objects like roles, drop them via the DROP ROLE command.
If the previous steps do not help, downscale the Keycloak and Postgres StatefulSets
and delete the attached PVC
(save the volumeID
before removing), and delete the volume on AWS if using gp2-retain
. In case of using gp2
, the volume will be deleted automatically after removing PVC. After that, redeploy the Postgres database, so that the new PVC
is automatically created.
Import the SQL dump file to the Postgres database cluster:
Info
Since the databases were exported in the sql
format, the psql tool will be used to restore (reload) them. pg_restore does not support this plain-text format.
If the entire Postgres database cluster was migrated with the postgres
Superuser using pg_dumpall
, use the import command without indicating the database:
psql -U postgres -f /tmp/keycloak_wildfly_db_dump.sql\n
If the database was migrated with the admin
user using pg_dump
, the postgres
Superuser still can be used to restore it, but, in this case, a database must be indicated:
Warning
If the database name was not indicated during the import for the file dumped with pg_dump
, the psql
tool will import this database to a default Postgres database called postgres
.
psql -U postgres -d keycloak -f /tmp/keycloak_wildfly_db_dump.sql\n
If the postgres
Superuser is not accessible in the Postgres pod, run the command under the admin
or any other user that has the database permissions. In this case, indicate the database as well:
psql -U admin -d keycloak -f /tmp/keycloak_wildfly_db_dump.sql\n
After a successful import, delete the dump file from the pod for security reasons:
kubectl exec -n security ${postgresql_pod} \"--\" sh -c \"rm /tmp/keycloak_wildfly_db_dump.sql\"\n
Note
Please find below the alternative commands for importing the database from the local machine to the pod without storing the backup on a pod for postgres
or admin
users:
cat \"keycloak_wildfly_db_dump.sql\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" sh -c \"cat | PGPASSWORD='\"${postgresql_superuser_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\"\"\ncat \"keycloak_wildfly_db_dump.sql\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" sh -c \"cat | PGPASSWORD='\"${postgresql_superuser_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\ncat \"keycloak_wildfly_db_dump.sql\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" sh -c \"cat | PGPASSWORD='\"${postgresql_admin_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\n
Make sure the Keycloak chart repository is added:
helm repo add codecentric https://codecentric.github.io/helm-charts\nhelm repo update\n
Create Keycloak values:
Note
nameOverride: \"keycloak\"
sets the name of the Keycloak pod. It must be the same Keycloak name as in the previous StatefulSet
.hostname: keycloak-postgresql
is the hostname of the pod with the Postgres database that is the same as Postgres StatefulSet name, for example, keycloak-postgresql
.\"/opt/keycloak/bin/kc.sh start --auto-build\"
was used in the legacy Keycloak version. However, it is no longer required in the new Keycloak version since it is deprecated and used by default.Optionally, use the following command for applying the old Keycloak theme:
bin/kc.sh start --features-disabled=admin2\n
Info
Automatic database migration will start after the Keycloak installation.
View: keycloak-values.yamlnameOverride: \"keycloak\"\n\nreplicas: 1\n\n# Deploy the latest verion\nimage:\n tag: \"19.0.1\"\n\n# start: create OpenShift realm which is required by EDP\nextraInitContainers: |\n - name: realm-provider\n image: busybox\n imagePullPolicy: IfNotPresent\n command:\n - sh\n args:\n - -c\n - |\n echo '{\"realm\": \"openshift\",\"enabled\": true}' > /opt/keycloak/data/import/openshift.json\n volumeMounts:\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumeMounts: |\n - name: realm\n mountPath: /opt/keycloak/data/import\n\nextraVolumes: |\n - name: realm\n emptyDir: {}\n\ncommand:\n - \"/opt/keycloak/bin/kc.sh\"\n - \"--verbose\"\n - \"start\"\n - \"--http-enabled=true\"\n - \"--http-port=8080\"\n - \"--hostname-strict=false\"\n - \"--hostname-strict-https=false\"\n - \"--spi-events-listener-jboss-logging-success-level=info\"\n - \"--spi-events-listener-jboss-logging-error-level=warn\"\n - \"--import-realm\"\n\nextraEnv: |\n - name: KC_PROXY\n value: \"passthrough\"\n - name: KEYCLOAK_ADMIN\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: username\n - name: KEYCLOAK_ADMIN_PASSWORD\n valueFrom:\n secretKeyRef:\n name: keycloak-admin-creds\n key: password\n - name: JAVA_OPTS_APPEND\n value: >-\n -XX:+UseContainerSupport\n -XX:MaxRAMPercentage=50.0\n -Djava.awt.headless=true\n -Djgroups.dns.query={{ include \"keycloak.fullname\" . }}-headless\n\n# This block should be uncommented if you install Keycloak on Kubernetes\ningress:\n enabled: true\n annotations:\n kubernetes.io/ingress.class: nginx\n ingress.kubernetes.io/affinity: cookie\n rules:\n - host: keycloak.<ROOT_DOMAIN>\n paths:\n - path: '{{ tpl .Values.http.relativePath $ | trimSuffix \"/\" }}/'\n pathType: Prefix\n\n# This block should be uncommented if you set Keycloak to OpenShift and change the host field\n# route:\n# enabled: false\n# # Path for the Route\n# path: '/'\n# # Host name for the Route\n# host: \"keycloak.<ROOT_DOMAIN>\"\n# # TLS configuration\n# tls:\n# enabled: true\n\nresources:\n limits:\n memory: \"2048Mi\"\n requests:\n cpu: \"50m\"\n memory: \"512Mi\"\n\n# Check database readiness at startup\ndbchecker:\n enabled: true\n\ndatabase:\n vendor: postgres\n existingSecret: keycloak-postgresql\n hostname: keycloak-postgresql\n port: 5432\n username: admin\n database: keycloak\n
Deploy Keycloak:
Note
Change the namespace and the values file name if required.
helm install keycloak codecentric/keycloakx --version 1.6.0 --values keycloak-values.yaml -n security\n
Log in to Keycloak and check if everything has been imported correctly.
Optionally, run the vacuumdb application on the database, to analyze the contents of database tables and collect statistics for the Postgres query optimizer:
PGPASSWORD=\"${postgresql_postgres-password}\" vacuumdb --analyze --verbose -d keycloak -U postgres\n
For all databases, run the following command: PGPASSWORD=\"${postgresql_postgres-password}\" vacuumdb --analyze --verbose --all -U postgres\n
"},{"location":"operator-guide/upgrade-keycloak-19.0/#postgres-database-migration-script","title":"Postgres Database Migration Script","text":"Info
Please read the Migrate Postgres Database From Postgres v.11.x to v.14.5 section of this tutorial before using the script.
Note
kubectl
tool is required for using this script.pg_dump
, pg_dumpall
, psql
, and vacuumdb
commands under the hood.The following script can be used for exporting and importing Postgres databases as well as optimizing them with the vacuumdb application. Please examine the code and make the adjustments if required.
By default, the following command exports Keycloak Postgres databases from a Kubernetes pod to a local machine:
./script.sh\n
After running the command, please follow the prompt.
./script.sh path-to/db_dump.sql\n
-h
flag prints help, and -c|-v
runs the vacuumdb
garbage collector and analyzer.#!/bin/bash\n\n# set -x\n\ndb_migration_help(){\n echo \"Keycloak Postgres database migration\"\n echo\n echo \"Usage:\"\n echo \"------------------------------------------\"\n echo \"Export Keycloak Postgres database from pod\"\n echo \"Run without parameters:\"\n echo \" $0\"\n echo \"------------------------------------------\"\n echo \"Import Keycloak Postgres database to pod\"\n echo \"Pass filename to script:\"\n echo \" $0 path/to/db_dump.sql\"\n echo \"------------------------------------------\"\n echo \"Additional options: \"\n echo \" $0 [OPTIONS...]\"\n echo \"Options:\"\n echo \"h Print Help.\"\n echo \"c|v Run garbage collector and analyzer.\"\n}\n\nkeycloak_ns(){\n printf '%s\\n' 'Enter keycloak namespace: '\n read -r keycloak_namespace\n\n if [ -z \"${keycloak_namespace}\" ]; then\n echo \"Don't skip namespace\"\n exit 1\n fi\n}\n\npostgres_pod(){\n printf '%s\\n' 'Enter postgres pod name: '\n read -r postgres_pod_name\n\n if [ -z \"${postgres_pod_name}\" ]; then\n echo \"Don't skip pod name\"\n exit 1\n fi\n}\n\npostgres_user(){\n printf '%s\\n' 'Enter postgres username: '\n printf '%s' \"Skip to use [postgres] superuser: \"\n read -r postgres_username\n\n if [ -z \"${postgres_username}\" ]; then\n postgres_username='postgres'\n fi\n}\n\npgdb_host_info(){\n database_name='keycloak'\n db_host='localhost'\n db_port='5432'\n}\n\npostgresql_admin_pass(){\n postgresql_password='POSTGRES_PASSWORD'\n postgresql_admin_password=\"$(kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"printenv ${postgresql_password}\")\"\n}\n\npostgresql_su_pass(){\n postgresql_postgres_password='POSTGRES_POSTGRES_PASSWORD'\n postgresql_superuser_password=\"$(kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"printenv ${postgresql_postgres_password}\")\"\n\n if [ -z \"${postgresql_superuser_password}\" ]; then\n echo \"SuperUser password variable does not exist. Using user password instead...\"\n postgresql_admin_pass\n postgresql_superuser_password=\"${postgresql_admin_password}\"\n fi\n}\n\nkeycloak_pgdb_export(){\n current_cluster=\"$(kubectl config current-context | tr -dc '[:alnum:]-')\"\n exported_db_name=\"keycloak_db_dump_${current_cluster}_${keycloak_namespace}_${postgres_username}_$(date +\"%Y%m%d%H%M\").sql\"\n\n if [ \"${postgres_username}\" == 'postgres' ]; then\n # call a function to get a pass for postgres user\n postgresql_su_pass\n kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"PGPASSWORD='\"${postgresql_superuser_password}\"' pg_dumpall -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\"\" > \"${exported_db_name}\"\n else\n # call a function to get a pass for admin user\n postgresql_admin_pass\n kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"PGPASSWORD='\"${postgresql_admin_password}\"' pg_dump -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\" > \"${exported_db_name}\"\n fi\n\n separate_lines=\"---------------\"\n\n if [ ! -s \"${exported_db_name}\" ]; then\n rm -f \"${exported_db_name}\"\n echo \"${separate_lines}\"\n echo \"Something went wrong. The database dump file is empty and was not saved.\"\n else\n echo \"${separate_lines}\"\n grep 'Dumped' \"${exported_db_name}\" | sort -u\n echo \"Database has been exported to $(pwd)/${exported_db_name}\"\n fi\n}\n\nkeycloak_pgdb_import(){\n echo \"Preparing Import\"\n echo \"----------------\"\n\n if [ ! -f \"$1\" ]; then\n echo \"The file $1 does not exist.\"\n exit 1\n fi\n\n keycloak_ns\n postgres_pod\n postgres_user\n pgdb_host_info\n\n if [ \"${postgres_username}\" == 'postgres' ]; then\n # restore full backup with all databases and roles as superuser or a single database\n postgresql_su_pass\n if [ -n \"$(cat \"$1\" | grep 'CREATE ROLE')\" ]; then\n cat \"$1\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"cat | PGPASSWORD='\"${postgresql_superuser_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\"\"\n else\n cat \"$1\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"cat | PGPASSWORD='\"${postgresql_superuser_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\n fi\n else\n # restore a single database\n postgresql_admin_pass\n cat \"$1\" | kubectl exec -i -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"cat | PGPASSWORD='\"${postgresql_admin_password}\"' psql -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\n fi\n}\n\nvacuum_pgdb(){\n echo \"Preparing garbage collector and analyzer\"\n echo \"----------------------------------------\"\n\n keycloak_ns\n postgres_pod\n postgres_user\n pgdb_host_info\n\n if [ \"${postgres_username}\" == 'postgres' ]; then\n postgresql_su_pass\n kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"PGPASSWORD='\"${postgresql_superuser_password}\"' vacuumdb --analyze --all -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\"\"\n else\n postgresql_admin_pass\n kubectl exec -n \"${keycloak_namespace}\" \"${postgres_pod_name}\" \"--\" \\\n sh -c \"PGPASSWORD='\"${postgresql_admin_password}\"' vacuumdb --analyze -h \"${db_host}\" -p \"${db_port}\" -U \"${postgres_username}\" -d \"${database_name}\"\"\n fi\n}\n\nwhile [ \"$#\" -eq 1 ]; do\n case \"$1\" in\n -h | --help)\n db_migration_help\n exit 0\n ;;\n -c | --clean | -v | --vacuum)\n vacuum_pgdb\n exit 0\n ;;\n --)\n break\n ;;\n -*)\n echo \"Invalid option '$1'. Use -h|--help to see the valid options\" >&2\n exit 1\n ;;\n *)\n keycloak_pgdb_import \"$1\"\n exit 0\n ;;\n esac\n shift\ndone\n\nif [ \"$#\" -gt 1 ]; then\n echo \"Please pass a single file to the script\"\n exit 1\nfi\n\necho \"Preparing Export\"\necho \"----------------\"\nkeycloak_ns\npostgres_pod\npostgres_user\npgdb_host_info\nkeycloak_pgdb_export\n
"},{"location":"operator-guide/upgrade-keycloak-19.0/#related-articles","title":"Related Articles","text":"The Version Control Systems (VCS) section is dedicated to delivering comprehensive information on VCS within the EPAM Delivery Platform. This section comprises detailed descriptions of all the deployment strategies, along with valuable recommendations for their optimal usage, and the list of supported VCS, facilitating seamless integration with EDP.
"},{"location":"operator-guide/vcs/#supported-vcs","title":"Supported VCS","text":"EDP can be integrated with the following Version Control Systems:
Note
So far, EDP doesn't support authorization mechanisms in the upstream GitLab.
"},{"location":"operator-guide/vcs/#vcs-deployment-strategies","title":"VCS Deployment Strategies","text":"EDP offers the following strategies to work with repositories:
Note
Under the hood, all the built-in application frameworks, build tools and frameworks are stored in our public GitHub repository.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitHub/GitLab in Jenkins or Integrate GitHub/GitLab in Tekton page. The Import project strategy is not applicable for Gerrit. Also, it is impossible to choose the Empty project field when using the Import project strategy while creating appication since it is implied that you already have a ready-to-work application in your own repository, whereas the \"Empty project\" option creates a repository but doesn't put anything in it.
Note
Make sure that IRSA is enabled and amazon-eks-pod-identity-webhook is deployed according to the Associate IAM Roles With Service Accounts documentation.
Velero AWS plugin requires access to AWS resources. Follow the steps below to create a required role:
Create AWS IAM Policy \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero_policy\":
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"ec2:DescribeVolumes\",\n \"ec2:DescribeSnapshots\",\n \"ec2:CreateTags\",\n \"ec2:CreateVolume\",\n \"ec2:CreateSnapshot\",\n \"ec2:DeleteSnapshot\"\n ],\n \"Resource\": \"*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:GetObject\",\n \"s3:DeleteObject\",\n \"s3:PutObject\",\n \"s3:AbortMultipartUpload\",\n \"s3:ListMultipartUploadParts\"\n ],\n \"Resource\": [\n \"arn:aws:s3:::velero-*/*\"\n ]\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ListBucket\"\n ],\n \"Resource\": [\n \"arn:aws:s3:::velero-*\"\n ]\n }\n ]\n}\n
Create AWS IAM Role \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero\" with trust relationships:
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Federated\": \"arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/<OIDC_PROVIDER>\"\n },\n \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n \"Condition\": {\n \"StringEquals\": {\n \"<OIDC_PROVIDER>:sub\": \"system:serviceaccount:<VELERO_NAMESPACE>:edp-velero\"\n }\n }\n }\n ]\n}\n
Attach the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero_policy\" policy to the \"AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero\" role.
Make sure that Amazon S3 bucket with name velero-\u2039CLUSTER_NAME\u203a exists.
Provide key value eks.amazonaws.com/role-arn: \"arn:aws:iam:::role/AWSIRSA\u2039CLUSTER_NAME\u203a\u2039VELERO_NAMESPACE\u203aVelero\" into the serviceAccount.server.annotations parameter in values.yaml during the Velero Installation.
This page contains accurate information on how to configure AWS WAF using Terraform with the aim to have a secured traffic exposure and to prevent the Host Header vulnerabilities.
"},{"location":"operator-guide/waf-tf-configuration/#prerequisites","title":"Prerequisites","text":"To follow the instruction, check the following prerequisites:
The solution includes two parts:
The WAF ACL resource is the main resource used for the configuration; The default web ACL option is Block.
Overview WAF Solution
The ACL includes three managed AWS rules that secure the exposed traffic:
AWS provides a lot of rules such as baseline and use-case specific rules, for details, please refer to the Baseline rule groups.
There is the PreventHostInjections rule that prevents the Host Header vulnerabilities. This rule includes one statement that declares that the Host Header should match Regex Pattern Set, thus only in this case it will be passed.
The Regex Pattern Set is another resource that helps to organize regexes, in fact, is a set of regexes. All regexes added to the single set are matched by the OR statement, i.e. when exposing several URLs, it is necessary to add this statement to the set and refer to it in the rule.
"},{"location":"operator-guide/waf-tf-configuration/#waf-acl-configuration","title":"WAF ACL Configuration","text":"To create the Regex Pattern Set, inspect the following code:
resource \"aws_wafv2_regex_pattern_set\" \"common\" {\n name = \"Common\"\n scope = \"REGIONAL\"\n\n regular_expression {\n regex_string = \"^.*(some-url).*((.edp-epam)+)\\\\.com$\"\n }\n\n # Add here additional regular expressions for other endpoints, they are merging with OR operator, e.g.\n\n /*\n regular_expression {\n regex_string = \"^.*(keycloak).*((.edp-epam)+)\\\\.com$\"\n }\n */\n\n tags = var.tags\n}\n
It includes 'regex_string', for example: url - some-url.edp-epam.com, In addition, it is possible to add other links to the same resource using the regular_expression element.
There is the Terraform code for the aws_wafv2_web_acl resource:
resource \"aws_wafv2_web_acl\" \"external\" {\n name = \"ExternalACL\"\n scope = \"REGIONAL\"\n\n default_action {\n block {}\n }\n\n rule {\n name = \"AWS-AWSManagedRulesCommonRuleSet\"\n priority = 1\n\n override_action {\n none {}\n }\n\n statement {\n managed_rule_group_statement {\n name = \"AWSManagedRulesCommonRuleSet\"\n vendor_name = \"AWS\"\n }\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"AWS-AWSManagedRulesCommonRuleSet\"\n sampled_requests_enabled = true\n }\n }\n\n rule {\n name = \"AWS-AWSManagedRulesLinuxRuleSet\"\n priority = 2\n\n statement {\n managed_rule_group_statement {\n name = \"AWSManagedRulesLinuxRuleSet\"\n vendor_name = \"AWS\"\n }\n }\n\n override_action {\n none {}\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"AWS-AWSManagedRulesLinuxRuleSet\"\n sampled_requests_enabled = true\n }\n }\n\n rule {\n name = \"AWS-AWSManagedRulesKnownBadInputsRuleSet\"\n priority = 3\n\n override_action {\n none {}\n }\n\n statement {\n managed_rule_group_statement {\n name = \"AWSManagedRulesKnownBadInputsRuleSet\"\n vendor_name = \"AWS\"\n }\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"AWS-AWSManagedRulesKnownBadInputsRuleSet\"\n sampled_requests_enabled = true\n }\n }\n\n rule {\n name = \"PreventHostInjections\"\n priority = 0\n\n statement {\n regex_pattern_set_reference_statement {\n arn = aws_wafv2_regex_pattern_set.common.arn\n\n field_to_match {\n single_header {\n name = \"host\"\n }\n }\n\n text_transformation {\n priority = 0\n type = \"NONE\"\n }\n }\n }\n\n action {\n allow {}\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"PreventHostInjections\"\n sampled_requests_enabled = true\n }\n }\n\n visibility_config {\n cloudwatch_metrics_enabled = true\n metric_name = \"ExternalACL\"\n sampled_requests_enabled = true\n }\n\n tags = var.tags\n}\n
As mentioned previously, ACL includes three managed AWS rules (group rules), for visibility, enabling sampling, and CloudWatch in the config. The 'PreventHostInjections' custom rule refers to the created pattern set and declares the Host Header, as well as sets the 'Action' if matched to 'Allow'.
"},{"location":"operator-guide/waf-tf-configuration/#associate-aws-resource","title":"Associate AWS Resource","text":"To have the created ACL working, it is necessary to associate an AWS resource with it, in this case, it is AWS ALB:
resource \"aws_wafv2_web_acl_association\" \"waf_alb\" {\n resource_arn = aws_lb.<aws_alb_for_waf>.arn\n web_acl_arn = aws_wafv2_web_acl.external.arn\n}\n
Note
AWS ALB can be created in the scope of this Terraform code or created previously. When creating ALB to expose links, the ALB should have a security group that allows some external traffic.
When ALB is associated with the WAF ACL, direct the traffic to the ALB by the Route53 CNAME record:
module \"some_url_exposure\" {\n source = \"terraform-aws-modules/route53/aws//modules/records\"\n version = \"2.0.0\"\n\n zone_name = \"edp-epam.com\"\n\n records = [\n {\n name = \"some-url\"\n type = \"CNAME\"\n ttl = 300\n records = [aws_lb.<aws_alb_for_waf>.dns_name]\n }\n ]\n}\n
In the sample above, the module is used, but it is also possible to use a Terraform resource.
"},{"location":"use-cases/","title":"Overview","text":""},{"location":"use-cases/#overview","title":"Overview","text":"The Use Cases section provides useful recommendations of how to operate with the EPAM Delivery Platform tools and manage the custom resources. Get acquainted with the description of technical scenarios and solutions.
This use case describes the creation and deployment of a FastAPI application to enable a developer to quickly generate a functional code structure for a FastAPI web application (with basic read functionality), customize it to meet specific requirements, and deploy it to a development environment. By using a scaffolding tool and a standardized process for code review, testing and deployment, developers can reduce the time and effort required to build and deploy a new application while improving the quality and reliability of the resulting code. Ultimately, the goal is to enable the development team to release new features and applications more quickly and efficiently while maintaining high code quality and reliability.
"},{"location":"use-cases/application-scaffolding/#roles","title":"Roles","text":"This documentation is tailored for the Developers and Team Leads.
"},{"location":"use-cases/application-scaffolding/#goals","title":"Goals","text":"Administrator
role (to perform merge in Gerrit).To scaffold and deploy FastAPI Application, follow the steps below.
"},{"location":"use-cases/application-scaffolding/#scaffold-the-new-fastapi-application","title":"Scaffold the New FastAPI Application","text":"Open EDP Portal URL. Use the Sign-In option.
Logging screen
Ensure Namespace
value in the User Settings
tab points to the namespace with the EDP installation.
Settings button
Create the new Codebase
with the Application
type using the Create
strategy. To do this, open EDP tab.
Cluster overview
Select the Components
Section under the EDP tab and push the create +
button.
Components tab
Select the Application
Codebase type because we are going to deliver our application as a container and deploy it inside the Kubernetes cluster. Choose the Create
strategy to scaffold our application from the template provided by the EDP and press the Proceed
button.
Step codebase info
On the Application Info tab, define the following values and press the Proceed
button:
fastapi-demo
main
Python
FastAPI
Python
Application info
On the Advances Settings
tab, define the below values and push the Apply
button:
Tekton
edp
0.0.1
and SNAPSHOT
Advanced settings
Check the application status. It should be green:
Application status
This section describes the application deployment approach from the latest branch commit. The general steps are:
main
branch.CD Pipeline
to establish continuous delivery to the development environment. To succeed with the steps above, follow the instructions below:
Build Container from the latest branch commit. To build the initial version of the application's main branch, go to the fastapi-demo application -> branches -> main and select the Build
menu.
Application building
Build pipeline for the fastapi-demo
application starts.
Pipeline building
Track Pipeline's status by accessing Tekton Dashboard by clicking the fastapi-demo-main-build-lb57m
application link.
Console logs
Ensure that Build Pipeline was successfully completed.
Create CD Pipeline. To enable application deployment create a CD Pipeline with a single environment - Development (with the name dev
).
Go to EDP Portal -> EDP -> CD Pipelines tab and push the +
button to create pipeline. In the Create CD Pipeline
dialog, define the below values:
Pipeline tab:
mypipe
Container
, since we are going to deploy containersPipeline tab with parameters
Applications tab. Add fastapi-demo
application, select main
branch, and leave Promote in pipeline
unchecked:
Applications tab with parameters
Stages tab. Add the dev
stage with the values below:
dev
Development Environment
Manual
. We plan to deploy applications to this environment manuallyManual
approve
Apply
buttonStages tab with parameters
Deploy the initial version of the application to the development environment:
mypipe
.dev
stage from the Stages tab.Image stream version
select version 0.0.1-SNAPSHOT.1
and push the Deploy
button.CD Pipeline deploy
To ensure the application is deployed successfully, follow the steps below:
Ensure application status is Healthy
and Synced
, and the Deployed version
points to 0.0.1-SNAPSHOT.1
:
Pipeline health status
Check that the selected version of the container is deployed on the dev
environment. ${EDP_ENV}
- is the EDP namespace name:
# Check the deployment status of fastapi-demo application\n$ kubectl get deployments -n ${EDP_ENV}-mypipe-dev\nNAME READY UP-TO-DATE AVAILABLE AGE\nfastapi-demo-dl1ft 1/1 1 1 30m\n\n# Check the image version of fastapi-demo application\n$ kubectl get pods -o jsonpath=\"{.items[*].spec.containers[*].image}\" -n ${EDP_ENV}-mypipe-dev\n012345678901.dkr.ecr.eu-central-1.amazonaws.com/${EDP_ENV}/fastapi-demo:0.0.1-SNAPSHOT.1\n
This section describes the Code Review
process for a new code. We need to deploy a new version of our fastapi-demo
application that deploys Ingress
object to expose API outside the Kubernetes cluster.
Perform the below steps to merge new code (Pull Request) that passes the Code Review flow. For the steps below, we use Gerrit UI but the same actions can be performed using the command line and git tool:
Login to Gerrit UI, select fastapi-demo
project, and create a change request.
Browse Gerrit Repositories and select fastapi-demo
project.
Browse Gerrit repositories
In the Commands
section of the project, push the Create Change
button.
Create Change request
In the Create Change
dialog, provide the branch main
and the Description
(commit message):
Enable ingress for application\n\nCloses: #xyz\n
Push the Create
button.
Create Change
Push the Edit
button of the merge request and add deployment-templates/values.yaml
for modification.
Update values.yaml file
Review the deployment-templates/values.yaml
file and change the ingress.enabled
flag from false
to true
. Then push the SAVE & PUBLISH
button. As soon as you get Verified +1
from CI, you are ready for review: Push the Mark as Active
button.
Review Change
You can always check your pipelines status from:
Pipeline Status Gerrit
Pipeline Status EDP Portal
With no Code Review Pipeline issues, set Code-Review +2
for the patchset and push the Submit
button. Then, your code is merged to the main
branch, triggering the Build Pipeline. The build Pipeline produces the new version of artifact: 0.0.1-SNAPSHOT.2
, which is available for the deployment.
Gerrit Code Review screen
Deliver the New Version to the Environment. Before the new version deployment, check the ingress object in dev
namespace:
$ kubectl get ingress -n ${EDP_ENV}-mypipe-dev\nNo resources found in ${EDP_ENV}-mypipe-dev namespace.\n
No ingress object exists as expected.
Deploy the new version 0.0.1-SNAPSHOT.2
which has the ingress object in place. Since we use Manual
deployment approach, we perform version upgrade by hand.
CD Pipelines
section of the EDP Portal
, select mypipe
pipeline and choose dev
stage.Image stream version
select the new version 0.0.1-SNAPSHOT.2
and push the Update
button.Healthy
and Synced
, and the Deployed version
points to 0.0.1-SNAPSHOT.2
.CD Pipeline Deploy New Version
Check that the new version with Ingress is deployed:
# Check the version of the deployed image\nkubectl get pods -o jsonpath=\"{.items[*].spec.containers[*].image}\" -n ${EDP_ENV}-mypipe-dev\n012345678901.dkr.ecr.eu-central-1.amazonaws.com/edp-delivery-tekton-dev/fastapi-demo:0.0.1-SNAPSHOT.2\n\n# Check Ingress object\nkubectl get ingress -n ${EDP_ENV}-mypipe-dev\nNAME CLASS HOSTS ADDRESS PORTS AGE\nfastapi-demo-ko1zs <none> fastapi-demo-ko1zs-example.com 12.123.123.123 80 115s\n\n# Check application external URL\ncurl https://your-hostname-appeared-in-hosts-column-above.example.com/\n{\"Hello\":\"World\"}\n
This use case describes the flow of adding an autotest as a quality gate to a newly created CD pipeline with a selected build version of an application to be promoted. The purpose of autotests is to check if application meets predefined criteria for stability and functionality, ensuring that only reliable versions are promoted. The promotion feature allows users to implement complicated testing, thus improving application stability.
"},{"location":"use-cases/autotest-as-quality-gate/#roles","title":"Roles","text":"This documentation is tailored for the Developers and Quality Assurance specialists.
"},{"location":"use-cases/autotest-as-quality-gate/#goals","title":"Goals","text":"To implement autotests as Quality Gates, follow the steps below:
Ensure the namespace is specified in the cluster settings. Click the Settings icon in the top right corner and select Cluster settings:
Cluster settings
Enter the name of the default namespace, then enter your default namespace in the Allowed namespaces field and click the + button. You can also add other namespaces to the Allowed namespaces:
Specify namespace
Create several applications using the Create strategy. Navigate to the EDP tab, choose Components, click the + button:
Add component
Select Application and Create from template:
Create new component menu
Note
Please refer to the Add Application section for details.
On the Codebase info tab, define the following values and press the Proceed button:
gerrit
js-application
js-application
js application
JavaScript
Vue
NPM
Codebase info tab
On the Advanced settings tab, define the below values and push the Apply button:
main
default
Advanced settings tab
Repeat the procedure twice to create the go-application and python-application applications. These applications will have the following parameters:
go-application:
gerrit
go-application
go-application
go application
Go
Gin
Go
main
default
python-application:
gerrit
python-application
python-application
python application
Python
FastAPI
Python
main
default
In the Components tab, click one of the applications name to enter the application menu:
Components list
Click the three dots (⋮) button, select Build:
Application menu
Click the down arrow (v) to observe and wait for the application to be built:
Application building
Click the application run name to watch the building logs in Tekton:
Tekton pipeline run
Wait till the build is successful:
Successful build
Repeat steps 8-12 for the rest of the applications.
The steps below instruct how to create autotests in EDP:
Create a couple of autotests using the Create strategy. Navigate to the EDP tab, choose Components, click on the + button. Select Autotest and Clone project:
Add autotest
Note
Please refer to the Add Autotest section for details.
On the Codebase info tab, define the following values and press the Proceed button:
https://github.com/SergK/autotests.git
gerrit
demo-autotest-gradle
demo-autotest-gradle
demo-autotest-gradle
Java
Java11
Gradle
Allure
Codebase info tab for autotests
On the Advanced settings tab, leave the settings as is and click the Apply button:
Advanced settings tab for autotests
Repeat the steps 1-3 to create one more autotest with the parameters below:
https://github.com/Rolika4/autotests.git
gerrit
demo-autotest-maven
demo-autotest-maven
demo-autotest-maven
Java
Java11
Maven
Allure
Now that applications and autotests are created, create pipeline for them by following the steps below:
Navigate to the CD Pipelines tab and click the + button:
CD pipelines tab
On the Pipeline tab, in the Pipeline name field, enter demo-pipeline:
Pipeline tab
On the Applications tab, add all the three applications, specify the main branch for all for them and check Promote in pipeline for Go and JavaScript applications:
Applications tab
On the Stages tab, click the Add stage button to open the Create stage menu:
Stages tab
In the Create stage menu, specify the following parameters and click Apply:
In cluster
dev
dev
manual
Autotests
dev
demo-autotest-gradle
main
Create stage menu
After the dev stage is added, click Apply:
Create stage menu
After the pipeline is created, click its name to open the pipeline details page:
Enter pipeline
In the pipeline details page, click the Create button to create a new stage:
Create a new stage
In the Create stage menu, specify the following parameters:
In cluster
sit
sit
manual
Autotests
dev
demo-autotest-maven
main
After the CD pipeline is created, deploy applications and run autotests by following the steps below:
Click the dev stage name to expand its details, specify image versions for each of the applications in the Image stream version field and click Deploy:
Deploy applications
Once applications are built, scroll down to Quality Gates and click Promote:
Promote in pipeline
Once promotion procedure is finished, the promoted applications will become available in the Sit stage. You will be able to select image stream versions for the promoted applications. The non-promoted application will stay grey in the stage and won't be allowed to get deployed:
Sit stage
This Use Case demonstrates how to securely manage sensitive data, such as passwords, API keys, and other credentials, that are consumed by application during development or runtime in production. The approach involves storing sensitive data in an external secret store that is located in a \"vault\" namespace (but can be Vault, AWS Secret Store or any other provider). The process implies transmitting confidential information from the vault namespace to the deployed namespace for the purpose of establishing a connection to a database.
"},{"location":"use-cases/external-secrets/#roles","title":"Roles","text":"This documentation is tailored for the Developers and Team Leads.
"},{"location":"use-cases/external-secrets/#goals","title":"Goals","text":"Administrator
role (to perform merge in Gerrit);To use External Secret in EDP approach, follow the steps below:
"},{"location":"use-cases/external-secrets/#add-application","title":"Add Application","text":"To begin, you will need an application first. Here are the steps to create it:
Open EDP Portal URL. Use the Sign-In
option:
Logging screen
In the top right corner, enter the Cluster settings
and ensure that both Default namespace
and Allowed namespace
are set:
Cluster settings
Create the new Codebase
with the Application
type using the Create
strategy. To do this, click the EDP
tab:
Cluster overview
Select the Components
section under the EDP tab and push the +
button:
Components tab
Select the Application
Codebase type because we are going to deliver our application as a container and deploy it inside the Kubernetes cluster. Select the Create
strategy to use predefined template:
Step codebase info
On the Application Info
tab, define the following values and press the Proceed
button:
es-usage
master
Java
Java 17
Maven
Step application info
On the Advanced Settings
tab, define the below values and push the Apply
button:
Tekton
default
Step application info
Check the application status. It should be green:
Application status
This section outlines the process of establishing a CD pipeline within EDP Portal. There are two fundamental steps in this procedure:
master
branch;CD Pipeline
to establish continuous delivery to the SIT environment.To succeed with the steps above, follow the instructions below:
Create CD Pipeline. To enable application deployment, create a CD Pipeline with a single environment - System Integration Testing (SIT for short). Select the CD Pipelines
section under the EDP
tab and push the +
button:
CD-Pipeline tab
On the Pipeline
tab, define the following values and press the Proceed
button:
deploy
Container
Pipeline tab
On the Applications
tab, add es-usage
application, select master
branch, leave Promote in pipeline
unchecked and press the Proceed
button:
Pipeline tab
On the Stage
tab, add the sit
stage with the values below and push the Apply
button:
sit
System integration testing
Manual
. We plan to deploy applications to this environment manuallyManual
Step name: approve
Stage tab
Note
In this scenario, three namespaces are used: demo
, which is the namespace where EDP is deployed, demo-vault
, which is the vault where developers store secrets, anddemo-deploy-sit
, which is the namespace used for deploying the application. The target namespace name for deploying application is formed with the pattern: edp-<cd_pipeline_name>-<stage_name>
.
To make the system to function properly, it is imperative to create the following resources:
Create namespace demo-vault
to store secrets:
kubectl create namespace demo-vault\n
Create Secret:
apiVersion: v1\nkind: Secret\nmetadata:\n name: mongo\n namespace: demo-vault\nstringData:\n password: pass\n username: user\ntype: Opaque\n
Create Role to access the secret:
apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n namespace: demo-vault\n name: external-secret-store\nrules:\n- apiGroups: [\"\"]\n resources:\n - secrets\n verbs:\n - get\n - list\n - watch\n- apiGroups:\n - authorization.k8s.io\n resources:\n - selfsubjectrulesreviews\n verbs:\n - create\n
Create RoleBinding:
apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n name: eso-from-edp\n namespace: demo-vault\nsubjects:\n - kind: ServiceAccount\n name: secret-manager\n namespace: demo-deploy-sit\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: Role\n name: external-secret-store\n
Now that RBAC is configured properly, it is time to add external secrets templates to application Helm chart. Follow the instructions provided below:
Navigate to EDP Portal
-> EDP
-> Overview
, and push the Gerrit link:
Overview page
Log in to Gerrit UI, select Repositories
and select es-usage
project:
Browse Gerrit repositories
In the Commands
section of the project, push the Create Change
button:
Create Change request
In the Create Change
dialog, provide the branch master
and fill in the Description
(commit message) field and push the Create
button:
Add external secrets templates\n
Create Change
Push the Edit
button of the merge request and then the ADD/OPEN/UPLOAD
button and add files:
Add files to repository
Once the file menu is opened, and click SAVE
after editing each of the files:
deploy-templates/templates/sa.yaml:
apiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: secret-manager\n namespace: demo-deploy-sit\n
deploy-templates/templates/secret-store.yaml:
apiVersion: external-secrets.io/v1beta1\nkind: SecretStore\nmetadata:\n name: demo\n namespace: demo-deploy-sit\nspec:\n provider:\n kubernetes:\n remoteNamespace: demo-vault\n auth:\n serviceAccount:\n name: secret-manager\n server:\n caProvider:\n type: ConfigMap\n name: kube-root-ca.crt\n key: ca.crt\n
deploy-templates/templates/external-secret.yaml:
apiVersion: external-secrets.io/v1beta1\nkind: ExternalSecret\nmetadata:\n name: mongo # target secret name\n namespace: demo-deploy-sit # target namespace\nspec:\n refreshInterval: 1h\n secretStoreRef:\n kind: SecretStore\n name: demo\n data:\n - secretKey: username # target value property\n remoteRef:\n key: mongo # remote secret key\n property: username # value will be fetched from this field\n - secretKey: password # target value property\n remoteRef:\n key: mongo # remote secret key\n property: password # value will be fetched from this field\n
deploy-templates/templates/deployment.yaml. Add the environment variable for mongodb to the existing deployment configuration that used the secret:
env:\n - name: MONGO_USERNAME\n valueFrom:\n secretKeyRef:\n name: mongo\n key: username\n - name: MONGO_PASSWORD\n valueFrom:\n secretKeyRef:\n name: mongo\n key: password\n
Push the Publish Edit
button.
As soon as review pipeline finished, and you get Verified +1
from CI, you are ready for review. Click Mark as Active
-> Code-Review +2
-> Submit
:
Apply change
Deploy the application by following the steps provided below:
When build pipeline is finished, navigate to EDP Portal
-> EDP
-> CD-Pipeline
and select deploy
pipeline.
Deploy the initial version of the application to the SIT environment:
sit
stage from the Stages tab;Image stream version
, select latest version and push the Deploy
button.Ensure application status is Healthy
and Synced
:
CD-Pipeline status
To ensure the application is deployed successfully, do the following:
Check that the resources are deployed:
kubectl get secretstore -n demo-deploy-sit\nNAME AGE STATUS READY\ndemo 5m57s Valid True\n
kubectl get externalsecret -n demo-deploy-sit\nNAME STORE REFRESH INTERVAL STATUS READY\nmongo demo 1h SecretSynced True\n
In the top right corner, enter the Cluster settings
and add demo-deploy-sit
to the Allowed namespace
.
Navigate EDP Portal
-> Configuration
-> Secrets
and ensure that secret was created:
Secrets
Navigate EDP Portal
-> Workloads
-> Pods
and select deployed application:
Pod information
This Use Case describes the procedure of adding custom Tekton libraries that include pipelines with tasks. In addition to it, the process of modifying custom pipelines and tasks is enlightened as well.
"},{"location":"use-cases/tekton-custom-pipelines/#goals","title":"Goals","text":"Administrator
role to perform merge in Gerrit.Note
This case is based on our predefined repository and application. Your case may be different.
To create and then modify a custom Tekton library, please follow the steps below:
"},{"location":"use-cases/tekton-custom-pipelines/#add-custom-application-to-edp","title":"Add Custom Application to EDP","text":"Open EDP Portal URL. Use the Sign-In option:
Logging screen
In the top right corner, enter the Cluster settings
and ensure that both Default namespace
and Allowed namespace
are set:
Cluster settings
Create the new Codebase
with the Application
type using the Clone
strategy. To do this, click the EDP tab:
Cluster overview
Select the Components
section under the EDP tab and push the create +
button:
Components tab
Select the Application
codebase type because is meant to be delivered as a container and deployed inside the Kubernetes cluster. Choose the Clone
strategy and this example repository:
Step codebase info
In the Application Info tab, define the following values and click the Proceed
button:
tekton-hello-world
master
Other
go
shell
Application info
Note
These application details are required to match the Pipeline name gerrit-shell-go-app-build-default
.
The PipelineRun name is formed with the help of TriggerTemplates in pipelines-library
so the Pipeline name should correspond to the following structure:
pipelineRef:\n name: gerrit-$(tt.params.buildtool)-$(tt.params.framework)-$(tt.params.cbtype)-build-$(tt.params.versioning-type)\n
The PipelineRun is created as soon as Gerrit (or, if configured, GitHub, GitLab) sends a payload during Merge Request events. In the Advances Settings
tab, define the below values and click the Apply
button:
Tekton
default
Specify the pattern to validate a commit message
empty.Advanced settings
Check the application status. It should be green:
Application status
Now that the application is created successfully, proceed to adding the Tekton library.
Select the Components
section under the EDP tab and push the create +
button:
Components tab
Create a new Codebase with the Library
type using the Create
strategy:
Step codebase info
Note
The EDP Create strategy will automatically pull the code for the Tekton Helm application from here.
In the Application Info tab, define the following values and click the Proceed
button:
custom-tekton-chart
master
Helm
Pipeline
Helm
Step codebase info
In the Advances Settings
tab, define the below values and click the Apply
button:
Tekton
default
Specify the pattern to validate a commit message
empty.Advanced settings
Check the codebase status:
Codebase status
Note
Our recommendation is to avoid modifying the default Tekton resources. Instead, we suggest creating and modifying your own custom Tekton library.
Now that the Tekton Helm library is created, it is time to clone, modify and then apply it to the Kubernetes cluster.
Generate SSH key to work with Gerrit repositories:
ssh-keygen -t ed25519 -C \"your_email@example.com\"\n
Log into Gerrit UI.
Go to Gerrit Settings
-> SSH keys
, paste your generated public SSH key to the New SSH key
field and click ADD NEW SSH KEY
:
Gerrit settings Gerrit settings
Browse Gerrit Repositories and select custom-tekton-chart
project:
Browse Gerrit repositories
Clone the repository with SSH
using Clone with commit-msg hook
command:
Gerrit clone
Note
In case of the strict firewall configurations, please use the HTTP
protocol to pull and configure the HTTP Credentials
in Gerrit.
Examine the repository structure. It should look this way by default:
custom-tekton-chart\n \u251c\u2500\u2500 Chart.yaml\n \u251c\u2500\u2500 chart_schema.yaml\n \u251c\u2500\u2500 ct.yaml\n \u251c\u2500\u2500 lintconf.yaml\n \u251c\u2500\u2500 templates\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 pipelines\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 hello-world\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-build-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-build-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-build-lib-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-build-lib-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-review-lib.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gerrit-review.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-build-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-build-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-build-lib-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-build-lib-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-review-lib.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 github-review.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-build-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-build-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-build-lib-default.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-build-lib-edp.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 gitlab-review-lib.yaml\n \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 gitlab-review.yaml\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 tasks\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 task-hello-world.yaml\n \u2514\u2500\u2500 values.yaml\n
Note
Change the values in the values.yaml
file.
The gitProvider
parameter is the git hosting provider, Gerrit in this example. The similar approach be made with GitHub, or GitLab.
The dnsWildCard parameter is the cluster DNS address.
The gerritSSHPort parameter is the SSH port of the Gerrit service on Kubernetes. Check the Gerrit port in your edp installation global section.
Note
Our custom Helm chart includes edp-tekton-common-library dependencies in the Chart.yaml
file. This library allows to use our predefined code snippets.
Here is an example of the filled in values.yaml
file:
nameOverride: \"\"\nfullnameOverride: \"\"\n\nglobal:\n gitProvider: gerrit\n dnsWildCard: \"example.domain.com\"\n gerritSSHPort: \"30009\"\n
Modify and add tasks or pipelines.
As an example, let's assume that we need to add the helm-lint
pipeline task to the review pipeline. To implement this, insert the code below to the gerrit-review.yaml file underneath the hello task:
- name: hello\n taskRef:\n name: hello\n runAfter:\n - init-values\n params:\n - name: BASE_IMAGE\n value: \"$(params.shell-image-version)\"\n - name: username\n value: \"$(params.username)\"\n workspaces:\n - name: source\n workspace: shared-workspace\n\n - name: helm-lint\n taskRef:\n kind: Task\n name: helm-lint\n runAfter:\n - hello\n params:\n - name: EXTRA_COMMANDS\n value: |\n ct lint --validate-maintainers=false --charts deploy-templates/\n workspaces:\n - name: source\n workspace: shared-workspace\n
Note
The helm-lint
task references to the default pipeline-library
Helm chart which is applied to the cluster during EDP installation.
The runAfter
parameter shows that this Pipeline task will be run after the hello
pipeline task.
Build Helm dependencies in the custom chart:
helm dependency update .\n
Ensure that the chart is valid and all the indentations are fine:
helm lint .\n
To validate if the values are substituted in the templates correctly, render the templated YAML files with the values using the following command. It generates and displays all the manifest files with the substituted values:
helm template .\n
Install the custom chart with the command below. You can also use the --dry-run
flag to simulate the chart installation and catch possible errors:
helm upgrade --install edp-tekton-custom . -n edp --dry-run\n
helm upgrade --install edp-tekton-custom . -n edp\n
Check the created pipelines and tasks in the cluster:
kubectl get tasks -n edp\nkubectl get pipelines -n edp\n
Commit and push the modified Tekton Helm chart to Gerrit:
git add .\ngit commit -m \"Add Helm chart testing for go-shell application\"\ngit push origin HEAD:refs/for/master\n
Check the Gerrit code review for the custom Helm chart pipelines repository in Tekton:
Gerrit code review status
Go to Changes
-> Open
, click CODE-REVIEW
and submit the merge request:
Gerrit merge Gerrit merge
Check the build Pipeline status for the custom Pipelines Helm chart repository in Tekton:
Tekton status
Since we applied the Tekton library to the Kubernetes cluster in the previous step, let's test the review and build pipelines for our tekton-hello-world
application.
Perform the below steps to merge new code (Merge Request) that passes the Code Review flow. For the steps below, we use Gerrit UI but the same actions can be performed using the command line and Git tool:
Log into Gerrit UI, select tekton-hello-world
project, and create a change request.
Browse Gerrit Repositories and select tekton-hello-world
project:
Browse Gerrit repositories
Clone the tekton-hello-world
repository to make the necessary changes or click the Create Change
button in the Commands
section of the project to make changes via Gerrit GUI:
Create Change request
In the Create Change
dialog, provide the branch master
, write some text in the Description
(commit message) and click the Create
button:
Create Change
Click the Edit
button of the merge request and add deployment-templates/values.yaml
to modify it and change the ingress.enabled flag
from false
to true
:
Update values.yaml file Update values.yaml file
Check the Review Pipeline status. The helm-lint
pipeline task should be displayed there:
Review Change
Review the deployment-templates/values.yaml
file and push the SAVE & PUBLISH
button. As soon as you get Verified +1
from CI bot, the change is ready for review. Click the Mark as Active
and Code-review
buttons:
Review Change
Click the Submit
button. Then, your code is merged to the main branch, triggering the Build Pipeline.
Review Change
Note
If the build is added and configured, push steps in the pipeline, it will produce a new version of artifact, which will be available for the deployment in EDP Portal.
Check the pipelines in the Tekton dashboard:
Tekton custom pipelines Tekton custom pipelines
What happens under the hood: 1) Gerrit sends a payload during Merge Request event to the Tekton EventListener; 2) EventListener catches it with the help of Interceptor; 3) TriggerTemplate creates a PipelineRun.
The detailed scheme is shown below:
graph LR;\n A[Gerrit events] --> |Payload| B(Tekton EventListener) --> C(Tekton Interceptor CEL filter) --> D(TriggerTemplate)--> E(PipelineRun)
This chart will be using the core of common-library
and pipelines-library
and custom resources on the top of them.
The EDP Portal user guide is intended for developers and provides details on working with EDP Portal, different codebase types, and EDP CI/CD flow.
"},{"location":"user-guide/#edp-portal","title":"EDP Portal","text":"EDP Portal is a central management tool in the EDP ecosystem that provides the ability to define pipelines, project resources and new technologies in a simple way. Using EDP Portal enables to manage business entities:
Overview page
EDP Portal is a complete tool allowing to manage and control the codebases (applications, autotests, libraries and infrastructures) added to the environment as well as to create a CD pipeline.
Inspect the main features available in EDP Portal by following the corresponding link:
EDP Portal allows you to create an application, clone an existing repository with the application to your Version Control System (VCS), or using an external repository and importing an application to the environment. When an application is created or cloned, the system automatically generates a corresponding repository within the integrated Version Control System.
To add an application, navigate to the Components section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create new component dialog will appear, then select Application and choose one of the strategies which will be described later in this page. You can create an Application in YAML or via the two-step menu in the dialog.
"},{"location":"user-guide/add-application/#create-application-in-yaml","title":"Create Application in YAML","text":"Click Edit YAML in the upper-right corner of the Create Application dialog to open the YAML editor and create the Application.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Application dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-application/#create-application-via-ui","title":"Create Application via UI","text":"The Create Application dialog contains the two steps:
Follow the instructions below to fill in the fields of the Codebase Info menu:
In the Create new component menu, select Application:
Application info
Select the necessary configuration strategy. There are three configuration strategies:
Import project - allows using existing VCS repository to integrate with EDP. While importing the existing repository, select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitLab/GitHub With Tekton page.
Clone project \u2013 clones the indicated repository into EPAM Delivery Platform. While cloning the existing repository, it is required to fill in the Repository URL field as well:
Clone application
In our example, we will use the Create from template strategy:
Create application
Select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example
.
Type the name of the application in the Component name field by entering at least two characters and by using the lower-case letters, numbers and inner dashes.
Type the application description.
To create an application with an empty repository in Gerrit, select the Empty project check box.
Select any of the supported application languages with their providers in the Application Code Language field:
Note
The Create from template strategy does not allow to customize the default code language set.
Select necessary Language version/framework depending on the Application code language field.
Choose the necessary build tool in the Build Tool field:
Note
The Select Build Tool field disposes of the default tools and can be changed in accordance with the selected code language.
Note
Tekton pipelines offer built-in support for Java Maven Multi-Module projects. These pipelines are capable of recognizing Java deployable modules based on the information in the pom.xml file and performing relevant deployment actions. It's important to note that although the Dockerfile is typically located in the root directory, Kaniko, the tool used for building container images, uses the targets folder within the deployable module's context. For a clear illustration of a Multi-Module project structure, please refer to this example on GitHub, which showcases a commonly used structure for Java Maven Multi-Module projects.
The Advanced Settings menu should look similar to the picture below:
Advanced settings
Follow the instructions below to fill in the fields of the Advanced Setting menu:
a. Specify the name of the Default branch where you want the development to be performed.
Note
The default branch cannot be deleted. For the Clone project and Import project strategies: if you want to use the existing branch, enter its name into this field.
b. Select the necessary codebase versioning type:
edp - using the edp versioning type, a developer indicates the version number that will be used for all the artifacts stored in artifactory: binaries, pom.xml, metadata, etc. The version stored in repository (e.g. pom.xml) will not be affected or used. Using this versioning overrides any version stored in the repository files without changing actual file.
When selecting the edp versioning type, the extra field will appear:
Edp versioning
Type the version number from which you want the artifacts to be versioned.
Note
The Start Version From field should be filled out in compliance with the semantic versioning rules, e.g. 1.2.3 or 10.10.10. Please refer to the Semantic Versioning page for details.
c. Specify the pattern to validate a commit message. Use regular expression to indicate the pattern that is followed on the project to validate a commit message in the code review pipeline. An example of the pattern: ^[PROJECT_NAME-d{4}]:.*$
.
JIRA integration
d. Select the Integrate with Jira Server check box in case it is required to connect Jira tickets with the commits and have a respective label in the Fix Version field.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration page.
e. In the Jira Server field, select the Jira server.
f. Specify the pattern to find a Jira ticket number in a commit message. Based on this pattern, the value from EDP will be displayed in Jira. Combine several variables to obtain the desired value.
Mapping fields
g. In the Mapping field name section, specify the names of the Jira fields that should be filled in with attributes from EDP:
Select the name of the field in a Jira ticket from the Mapping field name drop-down menu. The available fields are the following: Fix Version/s, Component/s and Labels.
Click the Add button to add the mapping field name.
Enter Jira pattern for the field name:
Click the bin icon to remove the Jira field name.
h. Click the Apply button to add the application to the Applications list.
Note
After the complete adding of the application, inspect the Application Overview part.
"},{"location":"user-guide/add-application/#related-articles","title":"Related Articles","text":"EDP Portal allows you to clone an existing repository with the autotest to your Version Control System (VCS), or using an external repository and adding an autotest for further running in stages or using them as quality gates for applications. When an autotest is cloned, the system automatically generates a corresponding repository within the integrated VCS.
Info
Please refer to the Add Application section for the details on how to add an application codebase type. For the details on how to use autotests as quality gates, please refer to the Stages Menu section of the Add Environment documentation.
To add an autotest, navigate to the Components section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create new component dialog will appear, then select Autotest and choose one of the strategies which will be described later in this page. You can create an autotest in YAML or via the two-step menu in the dialog.
"},{"location":"user-guide/add-autotest/#create-autotest-in-yaml","title":"Create Autotest in YAML","text":"Click Edit YAML in the upper-right corner of the Create Autotest dialog to open the YAML editor and create an autotest:
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Autotest dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-autotest/#create-autotest-via-ui","title":"Create Autotest via UI","text":"The Create Autotest dialog contains the two steps:
There are two available strategies: clone and import.
The Create new component menu should look like the picture below:
Create new component menu
In the Create new component menu, select the necessary configuration strategy. The choice will define the parameters you will need to specify:
Import project - allows using existing VCS repository to integrate with EDP. While importing the existing repository, select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitLab/GitHub With Tekton page.
In our example, we will use the Clone project strategy:
Clone autotest
While cloning the existing repository, it is required to fill in the Repository URL field.
Select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example
.
Select the Repository credentials check box in case you clone the private repository, and fill in the repository login and password/access token.
Fill in the Component name field by entering at least two characters and by using the lower-case letters, numbers and inner dashes.
Type the necessary description in the Description field.
In the Autotest code language field, select the Java code language with its framework (specify Java 8 or Java 11 to be used) and get the default Maven build tool OR add another code language. Selecting Other allows extending the default code languages and get the necessary build tool, for details, inspect the Add Other Code Language section.
Note
Using the Create strategy does not allow to customize the default code language set.
Select the Java framework if Java is selected above.
The Build Tool field can dispose of the default Maven tool, Gradle or other built tool in accordance with the selected code language.
All the autotest reports will be created in the Allure framework that is available in the Autotest Report Framework field by default.
Click the Proceed button to switch to the next menu.
The Advanced Settings menu should look like the picture below:
Advanced settings
a. Specify the name of the default branch where you want the development to be performed.
Note
The default branch cannot be deleted.
b. Select the necessary codebase versioning type:
edp: Using the edp versioning type, a developer indicates the version number from which all the artifacts will be versioned and, as a result, automatically registered in the corresponding file (e.g. pom.xml).
When selecting the edp versioning type, the extra field will appear:
Edp versioning
Type the version number from which you want the artifacts to be versioned.
Note
The Start Version From field must be filled out in compliance with the semantic versioning rules, e.g. 1.2.3 or 10.10.10. Please refer to the Semantic Versioning page for details.
c. Specify the pattern to validate a commit message. Use regular expression to indicate the pattern that is followed on the project to validate a commit message in the code review pipeline. An example of the pattern: ^[PROJECT_NAME-d{4}]:.*$
Jira integration
d. Select the Integrate with Jira Server check box in case it is required to connect Jira tickets with the commits and have a respective label in the Fix Version field.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration page, and Adjust VCS Integration With Jira. Pay attention that the Jira integration feature is not available when using the GitLab CI tool.
e. As soon as the Jira server is set, select it in the Jira Server field.
f. Specify the pattern to find a Jira ticket number in a commit message. Based on this pattern, the value from EDP will be displayed in Jira.
Mapping field name
g. In the Advanced Mapping section, specify the names of the Jira fields that should be filled in with attributes from EDP:
Select the name of the field in a Jira ticket. The available fields are the following: Fix Version/s, Component/s and Labels.
Click the Add button to add the mapping field name.
Enter Jira pattern for the field name:
Click the bin icon to remove the Jira field name.
h. Click the Apply button to add the library to the Libraries list.
Note
After the complete adding of the autotest, inspect the Autotest Overview part.
"},{"location":"user-guide/add-autotest/#the-advanced-settings-menu","title":"The Advanced Settings Menu","text":""},{"location":"user-guide/add-autotest/#related-articles","title":"Related Articles","text":"Portal provides the ability to deploy an environment on your own and specify the essential components.
Navigate to the Environments section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create CD Pipeline dialog will appear.
The creation of the environment becomes available as soon as an application is created including its provisioning in a branch and the necessary entities for the environment. You can create the environment in YAML or via the three-step menu in the dialog.
"},{"location":"user-guide/add-cd-pipeline/#create-environment-in-yaml","title":"Create Environment in YAML","text":"Click Edit YAML in the upper-right corner of the Create CD Pipeline dialog to open the YAML editor and create the environment.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create CD Pipeline dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-cd-pipeline/#create-environment-in-the-dialog","title":"Create Environment in the Dialog","text":"The Create CD Pipeline dialog contains the three steps:
To create an environment, follow the steps below:
Navigate to EDP -> Environments and click the + Create button:
Environments menu
The Pipeline tab of the Create CD Pipeline menu should look like the picture below:
Create CD pipeline
Enter the Environment name that will be displayed in the Environments list.
Select the Deployment type. It can be either container or custom.
Click the Proceed button to move onto the Applications tab.
Type the name of the pipeline in the Pipeline Name field by entering at least two characters and by using the lower-case letters, numbers and inner dashes.
Note
The namespace created by the environment has the following pattern combination: [edp namespace]-[environment name]-[stage name]. Please be aware that the namespace length should not exceed 63 symbols.
Select the deployment type from the drop-down list:
Click the Proceed button to switch to the next menu.
The Pipeline tab of the Create CD Pipeline menu should look like the picture below:
Environment applications
Select the Promote in pipeline check box in order to transfer the application from one to another stage by the specified codebase Docker branch. If the Promote in pipeline check box is not selected, the same codebase Docker stream will be deployed regardless of the stage, i.e. the codebase Docker stream input, which was selected for the pipeline, will always be used.
Note
If there is another deployed environment stage with the respective codebase Docker stream (= image stream as an OpenShift term), the pattern combination will be as follows: [pipeline name]-[stage name]-[application name]-[verified].
Click the Proceed button to switch to the next menu.
Stages are created the following way:
On the Stages menu, click the Add Stage button and fill in the necessary fields in the Adding Stage window :
CD stages
Adding stage
a. Choose the cluster to deploy the stage;
b. Enter the stage name;
c. Enter the description for this stage;
d. Select the trigger type. The key benefit of the automatic deploy feature is to keep environments up-to-date. The available trigger types are Manual and Auto. When the Auto trigger type is chosen, the environment will initiate automatically once the image is built. Manual implies that user has to perform deploy manually by clicking the Deploy button in the environment menu. Please refer to the Architecture Scheme of CD Pipeline Operator page for additional details.
Note
Automatic deploy will start working only after the first manual deploy.
e. Select the quality gate type:
f. Type the step name, which will be displayed in Tekton, for every quality gate;
g. Add an unlimited number of quality gates by clicking the Add button and remove them as well by clicking the recycle bin icon;
In the additional fields, select the previously created autotest name (h) and specify its branch for the autotest that will be launched on the current stage (i).
Note
Execution sequence. The image promotion and execution of the pipelines depend on the sequence in which the environments are added.
j. Click the Apply button to display the stage in the Stages menu.
Continuous delivery menu
Edit the stage by clicking its name and applying changes, and remove the added stage by clicking the recycle bin icon next to its name.
Click the Apply button to start the provisioning of the pipeline.
As a result, a new environment will be created in the environments list.
"},{"location":"user-guide/add-cd-pipeline/#related-articles","title":"Related Articles","text":"Adding other clusters allows deploying applications to several clusters when creating a stage of CD pipeline in EDP Portal.
Note
Before proceeding with the content on this documentation page, it's essential to ensure that Argo CD is integrated into the same cluster with an identical name. At present, EDP operates with the shared Argo CD, necessitating the copying of the secret to the namespace where Argo CD is installed. The command sample is below:
kubectl get secret <SECRET_NAME> --namespace=edp -o yaml | sed 's/namespace: .*/namespace: argocd/' | kubectl apply -f -\n
To add a cluster, follow the steps below:
Navigate to the Configuration section on the navigation bar and select Clusters. The appearance differs depending on the chosen display option:
List optionTiled optionConfiguration menu (List option)
Configuration menu (Tiled option)
Click the + button to enter the Create new cluster menu:
Add Cluster
Once clicked, the Create new cluster dialog will appear. You can create a Cluster in YAML or via UI:
To add cluster in YAML, follow the steps below:
Edit YAML
To add cluster in YAML, follow the steps below:
Add Cluster
As a result, the Kubernetes secret will be created for further integration.
"},{"location":"user-guide/add-cluster/#related-articles","title":"Related Articles","text":"In order to add a new custom global pipeline library, perform the steps below:
Navigate to Jenkins and go to Manage Jenkins -> Configure System -> Global Pipeline Libraries.
Note
It is possible to configure as many libraries as necessary. Since these libraries will be globally usable, any pipeline in the system can utilize the functionality implemented in these libraries.
Specify the following values:
Add custom library
a. Library name: The name of a custom library.
b. Default version: The version which can be branched, tagged or hashed of a commit.
c. Load implicitly: If checked, scripts will automatically have access to this library without needing to request it via @Library. It means that there is no need to upload the library manually because it will be downloaded automatically during the build for each job.
d. Allow default version to be overridden: If checked, scripts may select a custom version of the library by appending @someversion in the @Library annotation. Otherwise, they are restricted to using the version selected here.
e. Include @Library changes in job recent changes: If checked, any changes in the library will be included in the changesets of a build, and changing the library would cause new builds to run for Pipelines that include this library. This can be overridden in the jenkinsfile: @Library(value=\"name@version\", changelog=true|false).
f. Cache fetched versions on controller for quick retrieval: If checked, versions fetched using this library will be cached on the controller. If a new library version is not downloaded during the build for some reason, remove the previous library version from cache in the Jenkins workspace.
Note
If the Default version check box is not defined, the pipeline must specify a version, for example, @Library('my-shared-library@master')
. If the Allow default version to be overridden check box is enabled in the Shared Library\u2019s configuration, a @Library annotation may also override the default version defined for the library.
Source code management
g. Project repository: The URL of the repository
h. Credentials: The credentials for the repository.
Use the Custom Global Pipeline Libraries on the pipeline, for example:
Pipeline
@Library(['edp-library-stages', 'edp-library-pipelines', 'edp-custom-shared-library-name'])_\n\nBuild()\n
Note
edp-custom-shared-library-name
is the name of the Custom Global Pipeline Library that should be added to the Jenkins Global Settings.
Important
This article describes how to add a Git Server when deploying EDP with Jenkins. When deploying EDP with Tekton, Git Server is created automatically.
Add Git servers to use the Import strategy for Jenkins and Tekton when creating an application, autotest or library in EDP Portal (Codebase Info step of the Create Application/Autotest/Library dialog). Enabling the Import strategy is a prerequisite to integrate EDP with Gitlab or GitHub.
Note
GitServer
Custom Resource can be also created manually. See step 3 for Jenkins import strategy in the Integrate GitHub/GitLab in Jenkins article.
To add a Git server, navigate to the Git servers section on the navigation bar and click Create (the plus sign icon in the lower-right corner of the screen). Once clicked, the Create Git server dialog will appear. You can create a Git server in YAML or via the three-step menu in the dialog.
"},{"location":"user-guide/add-git-server/#create-git-server-in-yaml","title":"Create Git Server in YAML","text":"Click Edit YAML in the upper-right corner of the Create Git server dialog to open the YAML editor and create a Git server.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Git server dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-git-server/#create-git-server-in-the-dialog","title":"Create Git Server in the Dialog","text":"Fill in the following fields:
Create Git server
Click the Apply button to add the Git server to the Git servers list. As a result, the Git Server object and the corresponding secret for further integration will be created.
"},{"location":"user-guide/add-git-server/#related-articles","title":"Related Articles","text":"EDP Portal allows you to create an application, clone an existing repository with the application to your Version Control System (VCS), or using an external repository and importing an application to the environment. When an application is created or cloned, the system automatically generates a corresponding repository within the integrated Version Control System. The functionality of the Infrastructure codebase type is to create resources in cloud provider.
To add an application, navigate to the Components section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create new component dialog will appear, then select Application and choose one of the strategies which will be described later in this page. You can create an Application in YAML or via the two-step menu in the dialog.
"},{"location":"user-guide/add-infrastructure/#create-infrastructure-in-yaml","title":"Create Infrastructure in YAML","text":"Click Edit YAML in the upper-right corner of the Create Infrastructure dialog to open the YAML editor and create the Infrastructure.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Infrastructure dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-infrastructure/#create-infrastructure-via-ui","title":"Create Infrastructure via UI","text":"The Create Infrastructure dialog contains the two steps:
Follow the instructions below to fill in the fields of the Codebase Info menu:
In the Create new component menu, select Infrastructure:
Infrastructure info
Select the necessary configuration strategy:
Import project - allows using existing VCS repository to integrate with EDP. While importing the existing repository, select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitLab/GitHub With Tekton page.
Clone project \u2013 clones the indicated repository into EPAM Delivery Platform. While cloning the existing repository, it is required to fill in the Repository URL field as well:
In our example, we will use the Create from template strategy:
Create infrastructure
Select the Git server from the drop-down list and define the Git repo relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example
.
Type the name of the infrastructure in the Component name field by entering at least two characters and by using the lower-case letters, numbers and inner dashes.
Write the description in the Description field.
To create an application with an empty repository in Gerrit, select the Empty project check box.
Select any of the supported application languages with their providers in the Infrastructure Code Language field. So far, only HCL is supported.
Note
The Create from template strategy does not allow to customize the default code language set.
Select necessary Language version/framework depending on the Infrastructure code language field. So far, only AWS is supported.
Choose the necessary build tool in the Build Tool field. So far, only Terraform is supported.\\
Note
The Select Build Tool field disposes of the default tools and can be changed in accordance with the selected code language.
The Advanced Settings menu should look similar to the picture below:
Advanced settings
Follow the instructions below to fill in the fields of the Advanced Setting menu:
a. Specify the name of the Default branch where you want the development to be performed.
Note
The default branch cannot be deleted. For the Clone project and Import project strategies: if you want to use the existing branch, enter its name into this field.
b. Select the necessary codebase versioning type:
edp - using the edp versioning type, a developer indicates the version number that will be used for all the artifacts stored in artifactory: binaries, pom.xml, metadata, etc. The version stored in repository (e.g. pom.xml) will not be affected or used. Using this versioning overrides any version stored in the repository files without changing actual file.
When selecting the edp versioning type, the extra field will appear:
Edp versioning
Type the version number from which you want the artifacts to be versioned.
Note
The Start Version From field should be filled out in compliance with the semantic versioning rules, e.g. 1.2.3 or 10.10.10. Please refer to the Semantic Versioning page for details.
c. Specify the pattern to validate a commit message. Use regular expression to indicate the pattern that is followed on the project to validate a commit message in the code review pipeline. An example of the pattern: ^[PROJECT_NAME-d{4}]:.*$
.
JIRA integration
d. Select the Integrate with Jira Server check box in case it is required to connect Jira tickets with the commits and have a respective label in the Fix Version field.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration page, and setup the Adjust VCS Integration With Jira. Pay attention that the Jira integration feature is not available when using the GitLab CI tool.
e. In the Jira Server field, select the Jira server.
f. Specify the pattern to find a Jira ticket number in a commit message. Based on this pattern, the value from EDP will be displayed in Jira. Combine several variables to obtain the desired value.
Note
The GitLab CI tool is available only with the Import strategy and makes the Jira integration feature unavailable.
Mapping fields
g. In the Mapping field name section, specify the names of the Jira fields that should be filled in with attributes from EDP:
Select the name of the field in a Jira ticket from the Mapping field name drop-down menu. The available fields are the following: Fix Version/s, Component/s and Labels.
Click the Add button to add the mapping field name.
Enter Jira pattern for the field name:
Click the bin icon to remove the Jira field name.
h. Click the Apply button to add the application to the Applications list.
Note
After the complete adding of the application, inspect the Application Overview part.
"},{"location":"user-guide/add-infrastructure/#related-articles","title":"Related Articles","text":"EDP Portal allows you to create a library, clone an existing repository with the library to your Version Control System (VCS), or using an external repository and importing a library to the environment. When a library is created or cloned, the system automatically generates a corresponding repository within the integrated VCS.
To add a library, navigate to the Components section on the navigation bar and click Create (the plus sign icon on the right side of the screen). Once clicked, the Create new component dialog will appear, then select Library and choose one of the strategies which will be described later in this page. You can create a library in YAML or via the two-step menu in the dialog.
Create new component menu
"},{"location":"user-guide/add-library/#create-library-in-yaml","title":"Create Library in YAML","text":"Click Edit YAML in the upper-right corner of the Create Library dialog to open the YAML editor and create the Library.
Edit YAML
To edit YAML in the minimal editor, turn on the Use minimal editor toggle in the upper-right corner of the Create Application dialog.
To save the changes, select the Save & Apply button.
"},{"location":"user-guide/add-library/#create-library-via-ui","title":"Create Library via UI","text":"The Create Library dialog contains the two steps:
The Create new component menu should look like the following:
Create new component menu
In the Create new component menu, select the necessary configuration strategy. The choice will define the parameters you will need to specify:
Import project - allows using existing VCS repository to integrate with EDP. While importing the existing repository, select the Git server from the drop-down list and define the relative path to the repository, such as /epmd-edp/examples/basic/edp-auto-tests-simple-example.
Note
In order to use the Import project strategy, make sure to adjust it with the Integrate GitLab/GitHub With Tekton page.
Clone project \u2013 clones the indicated repository into EPAM Delivery Platform. While cloning the existing repository, it is required to fill in the Repository URL field as well:
Clone library
In our example, we will use the Create from template strategy:
Create library
/epmd-edp/examples/basic/edp-auto-tests-simple-example
Select any of the supported code languages with its framework in the Library code language field:
Note
The Create strategy does not allow to customize the default code language set.
Select necessary Language version/framework depending on the Library code language field.
The Select Build Tool field disposes of the default tools and can be changed in accordance with the selected code language.
Click the Proceed button to switch to the next menu.
The Advanced Settings menu should look like the picture below:
Advanced settings
a. Specify the name of the default branch where you want the development to be performed.
Note
The default branch cannot be deleted.
b. Select the necessary codebase versioning type:
When selecting the edp versioning type, the extra field will appear:
EDP versioning
Type the version number from which you want the artifacts to be versioned.
Note
The Start Version From field should be filled out in compliance with the semantic versioning rules, e.g. 1.2.3 or 10.10.10. Please refer to the Semantic Versioning page for details.
c. Specify the pattern to validate a commit message. Use regular expression to indicate the pattern that is followed on the project to validate a commit message in the code review pipeline. An example of the pattern: ^[PROJECT_NAME-d{4}]:.*$
Integrate with Jira server
d. Select the Integrate with Jira server check box in case it is required to connect Jira tickets with the commits and have a respective label in the Fix Version field.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration page, and Adjust VCS Integration With Jira. Pay attention that the Jira integration feature is not available when using the GitLab CI tool.
e. As soon as the Jira server is set, select it in the Jira Server field.
f. Specify the pattern to find a Jira ticket number in a commit message. Based on this pattern, the value from EDP will be displayed in Jira.
Mapping fields
g. In the Advanced Mapping section, specify the names of the Jira fields that should be filled in with attributes from EDP:
Select the name of the field in a Jira ticket. The available fields are the following: Fix Version/s, Component/s and Labels.
Click the Add button to add the mapping field name.
Enter Jira pattern for the field name:
Click the bin icon to remove the Jira field name.
h. Click the Apply button to add the library to the Libraries list.
Note
After the complete adding of the library, inspect the Library Overview part.
"},{"location":"user-guide/add-library/#related-articles","title":"Related Articles","text":"With the built-in Marketplace, users can easily create a new application by clicking several buttons. This page contains detailed guidelines on how to create a new component with the help of the Marketplace feature.
"},{"location":"user-guide/add-marketplace/#add-component","title":"Add Component","text":"To create a component from template, follow the instructions below:
Navigate to the Marketplace section on the navigation bar to see the Marketplace overview page.
Click the component name to open its details window and click Create from template:
Create from template
Fill in the required fields and click Apply:
Creating from template window
As a result, new component will appear in the Components section:
Creating from template window
This section describes how to use quality gate in EDP and how to customize the quality gate for the CD pipeline with the selected build version of the promoted application between stages.
"},{"location":"user-guide/add-quality-gate/#apply-new-quality-gate-to-pipelines","title":"Apply New Quality Gate to Pipelines","text":"Quality gate pipeline is a usual Tekton pipeline but with a specific label: app.edp.epam.com/pipelinetype: deploy
. To add and apply the quality gate to your pipelines, follow the steps below:
1. To use the Tekton pipeline as a quality gate pipeline, add this label to the pipelines:
metadata:\n labels:\n app.edp.epam.com/pipelinetype: deploy\n
2. Insert the value that is the quality gate name displayed in the quality gate drop-down list of the CD pipeline menu: metadata:\n name: <name-of-quality-gate>\n
3. Ensure the task promote-images
contains steps and logic to apply to the project. Also ensure that the last task is promote-images
which parameters are mandatory: spec:\n params:\n - default: ''\n description: Codebases with a tag separated with a space.\n name: CODEBASE_TAG\n type: string\n - default: ''\n name: CDPIPELINE_CR\n type: string\n - default: ''\n name: CDPIPELINE_STAGE\n type: string\n tasks:\n - name: promote-images\n params:\n - name: CODEBASE_TAG\n value: $(params.CODEBASE_TAG)\n - name: CDPIPELINE_STAGE\n value: $(params.CDPIPELINE_STAGE)\n - name: CDPIPELINE_CR\n value: $(params.CDPIPELINE_CR)\n runAfter:\n - <last-task-name>\n taskRef:\n kind: Task\n name: promote-images\n
4. Create a new pipeline with a unique name or modify your created pipeline with the command below. Please be aware that the \u2039edp-project\u203a value is the name of the EDP tenant: kubectl apply -f <file>.yaml --namespace edp\n
Example: file.yaml apiVersion: tekton.dev/v1beta1\n kind: Pipeline\n metadata:\n labels:\n app.edp.epam.com/pipelinetype: deploy\n name: <name-of-quality-gate>\n namespace: edp\n spec:\n params:\n - default: >-\n https://<CI-pipeline-provisioner>-edp.<cluster-name>.aws.main.edp.projects.epam.com/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)\n name: pipelineUrl\n type: string\n - default: ''\n description: Codebases with a tag separated with a space.\n name: CODEBASE_TAG\n type: string\n - default: ''\n name: CDPIPELINE_CR\n type: string\n - default: ''\n name: CDPIPELINE_STAGE\n type: string\n tasks:\n - name: autotests\n params:\n - name: BASE_IMAGE\n value: bitnami/kubectl:1.25.4\n - name: EXTRA_COMMANDS\n value: echo \"Hello World\"\n taskRef:\n kind: Task\n name: run-quality-gate\n - name: promote-images\n params:\n - name: CODEBASE_TAG\n value: $(params.CODEBASE_TAG)\n - name: CDPIPELINE_STAGE\n value: $(params.CDPIPELINE_STAGE)\n - name: CDPIPELINE_CR\n value: $(params.CDPIPELINE_CR)\n runAfter:\n - autotests\n taskRef:\n kind: Task\n name: promote-images\n
"},{"location":"user-guide/add-quality-gate/#run-quality-gate","title":"Run Quality Gate","text":"Before running the quality gate, first of all, ensure that the environment has deployed the created CD pipeline and then ensure that the application is successfully deployed and ready to run the quality gate. To run quality gate, please follow the steps below:
Check the CD pipeline status. To do this, open the created CD pipeline, select Image stream version
, click DEPLOY
button and wait until Applications
, Health
and Sync
statuses become green
. This implies that the application is successfully deployed and ready to run the quality gate.
CD pipeline stage overview
Select the name-of-quality-gate of Quality gates
from the drop-down list and click the RUN
button.The execution process should be started in the Pipelines
menu:
Quality gate pipeline status
For a better understanding of this section, please read the documentation about how to add a new stage for quality gate. The scheme below illustrates two approaches of adding quality gates:
Types of adding quality gate
Promote in pipelines
option while creating a CD Pipeline to pass the quality gate in a certain sequence.As a result, after the quality gate is successfully passed, the projected image is promoted to the next stage.
"},{"location":"user-guide/add-quality-gate/#related-articles","title":"Related Articles","text":"This section describes the subsequent possible actions that can be performed with the newly added or existing applications.
"},{"location":"user-guide/application/#check-and-remove-application","title":"Check and Remove Application","text":"As soon as the application is successfully provisioned, the following will be created:
The added application will be listed in the Applications list allowing you to do the following:
Applications menu
Delete application - remove application by clicking the vertical ellipsis button and then selecting Delete.
Note
The application that is used in a CD pipeline cannot be removed.
There are also options to sort the applications:
Select a number of applications displayed per page (15, 25 or 50 rows) and navigate between pages if the number of applications exceeds the capacity of a single page:
Applications pages
EDP Portal provides the ability to enable, disable or edit the Jira Integration functionality for applications.
To edit an application directly from the Applications overview page or when viewing the application data:
Edit application on the Applications overview page
Edit application when viewing the application data
To enable Jira integration, in the Edit Application dialog do the following:
Edit application
a. Mark the Integrate with Jira server check box and fill in the necessary fields. Please see steps d-h of the Add Application page.
b. Select the Apply button to apply the changes.
To disable Jira integration, in the Edit Application dialog do the following:
a. Uncheck the Integrate with Jira server check box.
b. Select the Apply button to apply the changes.
To create, edit and delete application branches, please refer to the Manage Branches page.
This section describes the subsequent possible actions that can be performed with the newly added or existing autotests.
"},{"location":"user-guide/autotest/#check-and-remove-autotest","title":"Check and Remove Autotest","text":"As soon as the autotest is successfully provisioned, the following will be created:
Info
To navigate quickly to Tekton, Version Control System, SonarQube, Nexus, and other resources, click the Overview section on the navigation bar and hit the necessary link.
The added autotest will be listed in the Autotests list allowing you to do the following:
Autotests page
Delete autotest - remove autotest by clicking the vertical ellipsis button and then selecting Delete.
Note
The autotest that is used in a CD pipeline cannot be removed.
There are also options to sort the applications:
EDP Portal provides the ability to enable, disable or edit the Jira Integration functionality for autotests.
To edit an autotest directly from the Autotests overview page or when viewing the autotest data:
Select Edit in the options icon menu:
Edit autotest on the autotests overview page
Edit autotest when viewing the autotest data
To enable Jira integration, on the Edit Autotest page do the following:
Edit library
a. Mark the Integrate with Jira server check box and fill in the necessary fields. Please see steps d-h on the Add Autotests page.
b. Select the Apply button to apply the changes.
Note
Pay attention that the Jira integration feature is not available when using the GitLab CI tool.
Note
To adjust the Jira integration functionality, first apply the necessary changes described on the Adjust Jira Integration and Adjust VCS Integration With Jira pages.
To disable Jira integration, in the Edit Autotest dialog do the following:
a. Uncheck the Integrate with Jira server check box.
b. Select the Apply button to apply the changes.
As a result, the necessary changes will be applied.
To create, edit and delete application branches, please refer to the Manage Branches page.
In order to add an autotest as a quality gate to a newly added CD pipeline, do the following:
Create a CD pipeline with the necessary parameters. Please refer to the Add CD Pipeline section for the details.
In the Stages menu, select the Autotest quality gate type. It means the promoting process should be confirmed by the successful passing of the autotests.
In the additional fields, select the previously created autotest name and specify its branch.
After filling in all the necessary fields, click the Create button to start the provisioning of the pipeline. After the CD pipeline is added, the new namespace containing the stage name will be created in Kubernetes (in OpenShift, a new project will be created) with the following name pattern: [cluster name]-[cd pipeline name]-[stage name].
In order to configure the added autotest launch at the specific stage with necessary parameters, do the following:
Add the necessary stage to the CD pipeline. Please refer to the Add CD Pipeline documentation for the details.
Navigate to the run.json file and add the stage name and the specific parameters.
There is an ability to run the autotests locally using the IDEA (Integrated Development Environment Application, such as IntelliJ, NetBeans etc.). To launch the autotest project for the local verification, perform the following steps:
Clone the project to the local machine.
Open the project in IDEA and find the run.json file to copy out the necessary command value.
Paste the copied command value into the Command line field and run it with the necessary values and namespace.
As a result, all the launched tests will be executed.
This section provides details on the Build pipeline of the EDP CI/CD pipeline framework. Explore below the pipeline purpose, stages and possible actions to perform.
"},{"location":"user-guide/build-pipeline/#build-pipeline-purpose","title":"Build Pipeline Purpose","text":"The purpose of the Build pipeline contains the following points:
Find below the functional diagram of the Build pipeline with the default stages:
flowchart TD\n build --> get-nexus-repository-url\n compile --> test\n start([fa:fa-circle]) --> fetch-repository\n fetch-repository --> init-values\n get-nexus-repository-url --> push\n get-version --> update-build-number\n git-tag --> update-cbis\n init-values --> get-version\n kaniko-build --> git-tag\n push --> kaniko-build\n sast --> compile\n sonar --> build\n test --> sonar\n update-build-number --> sast\n update-cbis --> stop([fa:fa-circle])
"},{"location":"user-guide/build-pipeline/#build-pipeline-for-application-and-library","title":"Build Pipeline for Application and Library","text":"The Build pipeline is triggered automatically after the Code Review pipeline is completed and the changes are submitted.
To review the Build pipeline, take the following steps:
Open Jenkins via the created link in Gerrit or via the Admin Console Overview page.
Click the Build pipeline link to open its stages for the application and library codebases:
Note
For more details on stages, please refer to the Pipeline Stages documentation.
After the Build pipeline runs all the stages successfully, the corresponding tag numbers will be created in Kubernetes/OpenShift and Nexus.
"},{"location":"user-guide/build-pipeline/#check-the-tag-in-kubernetesopenshift-and-nexus","title":"Check the Tag in Kubernetes/OpenShift and Nexus","text":"After the Build pipeline is completed, check the tag name and the same with the commit revision. Simply navigate to Gerrit \u2192 Projects \u2192 List \u2192 select the project \u2192 Tags.
Note
For the Import strategy, navigate to the repository from which a codebase is imported \u2192 Tags. It is actual both for GitHub and GitLab.
Open the Kubernetes/OpenShift Overview page and click the link to Nexus and check the build of a new version.
Switch to Kubernetes \u2192 CodebaseImageStream (or OpenShift \u2192 Builds \u2192 Images) \u2192 click the image stream that will be used for deployment.
Check the corresponding tag.
The Build pipeline can be started manually. To set the necessary stages and trigger the pipeline manually, take the following steps:
Open the Build pipeline for the created library.
Click the Build with parameters option from the left-side menu. Modify the stages by removing the whole objects massive:{\"name\". \"tests\"} where name is a key and tests is a stage name that should be executed.
Open Jenkins and check the successful execution of all stages.
CD Pipeline (Continuous Delivery Pipeline) - an EDP business entity that describes the whole delivery process of the selected application set via the respective stages. The main idea of the CD pipeline is to promote the application build version between the stages by applying the sequential verification (i.e. the second stage will be available if the verification on the first stage is successfully completed). The CD pipeline can include the essential set of applications with its specific stages as well.
In other words, the CD pipeline allows the selected image stream (Docker container in Kubernetes terms) to pass a set of stages for the verification process (SIT - system integration testing with the automatic type of a quality gate, QA - quality assurance, UAT - user acceptance testing with the manual testing).
Note
It is possible to change the image stream for the application in the CD pipeline. Please refer to the Edit CD Pipeline section for the details.
A CI/CD pipeline helps to automate steps in a software delivery process, such as the code build initialization, automated tests running, and deploying to a staging or production environment. Automated pipelines remove manual errors, provide standardized development feedback cycle, and enable the fast product iterations. To get more information on the CI pipeline, please refer to the CI Pipeline Details chapter.
The codebase stream is used as a holder for the output of the stage, i.e. after the Docker container (or an image stream in OpenShift terms) passes the stage verification, it will be placed to the new codebase stream. Every codebase has a branch that has its own codebase stream - a Docker container that is an output of the build for the corresponding branch.
Note
For more information on the main terms used in EPAM Delivery Platform, please refer to the EDP Glossary
EDP CD pipeline
Explore the details of the CD pipeline below.
"},{"location":"user-guide/cd-pipeline-details/#deploy-pipeline","title":"Deploy Pipeline","text":"The Deploy pipeline is used by default on any stage of the Continuous Delivery pipeline. It addresses the following concerns:
Find below the functional diagram of the Deploy pipeline with the default stages:
Note
The input for a CD pipeline depends on the Trigger Type for a deploy stage and can be either Manual or Auto.
Deploy pipeline stages
"},{"location":"user-guide/cd-pipeline-details/#related-articles","title":"Related Articles","text":"CI Pipeline (Continuous Integration Pipeline) - an EDP business entity that describes the integration of changes made to a codebase into a single project. The main idea of the CI pipeline is to review the changes in the code submitted through a Version Control System (VCS) and build a new codebase version so that it can be transmitted to the Continuous Delivery Pipeline for the rest of the delivery process.
There are three codebase types in EPAM Delivery Platform:
Note
For more information on the above mentioned codebase types, please refer to the Add Application, Add Library, Add Autotests and Autotest as Quality Gate pages.
EDP CI pipeline
"},{"location":"user-guide/ci-pipeline-details/#related-articles","title":"Related Articles","text":"This chapter provides information on CI/CD basic definitions and flow, as well as its components and process.
"},{"location":"user-guide/cicd-overview/#cicd-basic-definitions","title":"CI/CD Basic Definitions","text":"The Continuous Integration part means the following:
The Code Review
and Build
pipelines are used before the code is delivered. An important part of both of them is the integration tests that are launched during the testing stage.
Many applications (SonarQube, Gerrit, etc,) used by the project need databases for their performance.
The Continuous Delivery comprises an approach allowing to produce an application in short cycles so that it can be reliably released at any time point. This part is tightly bound with the usage of the Code Review
, Build
, and Deploy
pipelines.
The Deploy
pipelines deploy the applications configuration and their specific versions, launch automated tests and control quality gates for the specified environment. As a result of the successfully completed process, the specific versions of images are promoted to the next environment. All environments are sequential and promote the build versions of applications one-by-one. The logic of each stage is described as a code of Jenkins pipelines and stored in the VCS.
During the CI/CD, there are several continuous processes that run in the repository, find below the list of possible actions:
Note
For the details on autotests, please refer to the Autotest, Add Autotest, and Autotest as Quality Gate pages.
The release process is divided into cycles and provides regular delivery of completed pieces of functionality while continuing the development and integration of new functionality into the product mainline.
Explore the main flow that is displayed on the diagram below:
EDP CI/CD pipeline
"},{"location":"user-guide/cicd-overview/#related-articles","title":"Related Articles","text":"This section describes the subsequent possible actions that can be performed with the newly added or existing clusters.
In a nutshell, cluster in EDP Portal is a Kubernetes secret that stores credentials and endpoint to connect to the another cluster. Adding new clusters allows users to deploy applications in several clusters, thus improving flexibility of your infrastructure.
The added cluster will be listed in the clusters list allowing you to do the following:
Clusters list
"},{"location":"user-guide/cluster/#view-authentication-data","title":"View Authentication Data","text":"To view authentication data that is used to log in to the cluster, run the kubectl describe
command:
kubectl describe secret cluster_name -n edp\n
"},{"location":"user-guide/cluster/#delete-cluster","title":"Delete Cluster","text":"To delete cluster, use the kubectl delete
command as follows:
kubectl delete secret cluster_name -n edp\n
"},{"location":"user-guide/cluster/#related-articles","title":"Related Articles","text":"This section provides details on the Code Review pipeline of the EDP CI/CD framework. Explore below the pipeline purpose, stages and possible actions to perform.
"},{"location":"user-guide/code-review-pipeline/#code-review-pipeline-purpose","title":"Code Review Pipeline Purpose","text":"The purpose of the Code Review pipeline contains the following points:
Find below the functional diagram of the Code Review pipeline with the default stages:
flowchart TD\n build --> dockerbuild-verify\n compile --> test\n dockerbuild-verify --> stop([fa:fa-circle])\n dockerfile-lint --> dockerbuild-verify\n fetch-repository --> init-values\n fetch-repository --> helm-docs\n fetch-repository --> dockerfile-lint\n fetch-repository --> helm-lint\n helm-docs --> stop([fa:fa-circle])\n helm-lint --> stop([fa:fa-circle])\n init-values --> compile\n start([fa:fa-circle]) --> report-pipeline-start-to-gitlab\n report-pipeline-start-to-gitlab --> fetch-repository\n sonar --> build\n test --> sonar
"},{"location":"user-guide/code-review-pipeline/#code-review-pipeline-for-applications-and-libraries","title":"Code Review Pipeline for Applications and Libraries","text":"Note
Make sure the necessary applications or libraries are added to the Admin Console. For the details on how to add a codebase, please refer to the Add Application or Add Library pages accordingly.
To discover the Code Review pipeline, apply changes that will trigger the Code Review pipeline automatically and take the following steps:
Navigate to Jenkins. In Admin Console, go to the Overview section on the left-side navigation bar and click the link to Jenkins.
Link to Jenkins
or
In Gerrit, go to the Patch Set page and click the CI Jenkins link in the Change Log section
Link from Gerrit
Note
The Code Review pipeline starts automatically for every codebase type (Application, Autotests, Library).
Check the Code Review pipeline for the application of for the library. Click the application name in Jenkins and switch to the additional release-01 branch that is created with the respective Code Review and Build pipelines.
Click the Code Review pipeline link to open the Code Review pipeline stages for the application:
Note
For more details on EDP pipeline stages, please refer to the Pipeline Stages section.
"},{"location":"user-guide/code-review-pipeline/#code-review-pipeline-for-autotests","title":"Code Review Pipeline for Autotests","text":"To discover the Code Review pipeline for autotests, first, apply changes to a codebase that will trigger the Code Review pipeline automatically. The flow for the autotest is similar for that for applications and libraries, however, there are some differences. Explore them below.
Open the run.json file for the created autotest.
Note
Please refer to the Add Autotest page for the details on how to create an autotest.
The run.json file keeps a command that is executed on this stage.
Open the Code Review pipeline in Jenkins (via the link in Gerrit or via the Admin Console Overview page) and click the Configure option from the left side. There are only four stages available: Initialization - Gerrit-checkout - tests - sonar (the launch of the static code analyzer that checks the whole code).
Open the Code Review pipeline in Jenkins with the successfully passed stages.
The Code Review pipeline can be retriggered manually, especially if the pipeline failed before. To retrigger it, take the following steps:
In Jenkins, click the Retrigger option from the drop-down menu for the specific Code Review pipeline version number. Alternatively, click the Jenkins main page and select the Query and Trigger Gerrit Patches option.
Click Search and select the check box of the necessary change and patch set and then click Trigger Selected.
As a result, the Code Review pipeline will be retriggered.
"},{"location":"user-guide/code-review-pipeline/#configure-code-review-pipeline","title":"Configure Code Review Pipeline","text":"The Configure option allows adding/removing the stage from the Code Review pipeline if needed. To configure the Code Review pipeline, take the following steps:
Being in Jenkins, click the Configure option from the left-side menu.
Define the stages set that will be executed for the current pipeline.
Note
All stages are launched from the shared library on GitHub. The list of libraries is located in the edp-library-stages repository.
To apply the new stage process, retrigger the Code Review pipeline. For details, please refer to the Retrigger Code Review Pipeline section.
Open Jenkins and check that there is no removed stage in the Code Review pipeline.
In this section, we will introduce you to the different types of codebases and strategies for onboarding codebases onto the EDP platform.
"},{"location":"user-guide/components/#component-and-codebase","title":"Component and Codebase","text":"From a business perspective, Components
represent the functional building blocks of software projects. They define the purpose and functionality of different parts of a business application, such as core applications, libraries, automated tests, and infrastructure settings. Components are about what software does and how it aligns with business goals.
From a technical implementation perspective, Codebases
are the Kubernetes custom resources that manage the technical aspects of these Components. They serve as the bridge between the business logic represented by Components and the underlying Git repositories. Codebases are responsible for the technical implementation, ensuring that the Components are efficiently stored, versioned, and synchronized with the version control system. They represent the state of Components from a technical standpoint.
Components are the building blocks of software projects. They come in different types, such as Applications
, Libraries
, Autotests
, and Infrastructure
. Each component type serves a specific purpose in the development process. Applications are the deployable unit of projects, libraries contain reusable code, autotests facilitate automated testing, and infrastructure defines a project's infrastructure settings.
Codebases are Kubernetes custom resources (CR) that represent the state of the components. They are a crucial link between component's state and underlying Git repositories. In essence, each codebase corresponds to a specific component and reflects its current state within a single Git repository. This one-to-one mapping ensures that the component's state is efficiently managed and versioned.
"},{"location":"user-guide/components/#types","title":"Types","text":"EDP accommodates a variety of codebase types, each serving a specific purpose in the development process. The codebase types available in EDP are:
Infrastructure as Code
approach, ensuring consistency and reproducibility.The platform supports the following strategies to onboard codebases on the platform:
The codebase-operator is responsible for creating and managing the codebase custom resource on the EPAM Delivery Platform. The codebase CR defines the metadata and configuration of the codebase, such as the name, description, type, repository URL, branch, path, CD tool, etc. The codebase-operator watches for changes in the codebase CR and synchronizes them with the corresponding Git repository and EDP components. Learn more about the codebase-operator and the custom resource (CR) API.
"},{"location":"user-guide/container-stages/","title":"CI Pipeline for Container","text":""},{"location":"user-guide/container-stages/#ci-pipeline-for-container","title":"CI Pipeline for Container","text":"EPAM Delivery Platform ensures the implemented Container support allowing to work with Dockerfile that is processed by means of stages in the Code-Review and Build pipelines. These pipelines are expected to be created after the Container Library is added.
"},{"location":"user-guide/container-stages/#code-review-pipeline-stages","title":"Code Review Pipeline Stages","text":"In the Code Review pipeline, the following stages are available:
checkout stage is a standard step during which all files are checked out from a selected branch of the Git repository.
dockerfile-lint stage uses the hadolint tool to perform linting tests for the Dockerfile.
dockerbuild-verify stage collects artifacts and builds an image from the Dockerfile without pushing to registry. This stage is intended to check if the image is built.
In the Build pipeline, the following stages are available:
checkout stage is a standard step during which all files are checked out from a master branch of the Git repository.
get-version stage where the library version is determined either via:
2.1. EDP versioning functionality.
2.2. Default versioning functionality.
dockerfile-lint stage uses the hadolint tool to perform linting tests for Dockerfile.
build-image-kaniko stage builds Dockerfile using the Kaniko tool.
git-tag stage that is intended for tagging a repository in Git.
EPAM Delivery Platform ensures the implemented Kaniko tool and BuildConfig
object support. Using Kaniko tool allows building the container images from a Dockerfile both on the Kubernetes and OpenShift platforms. The BuildConfig
object enables the building of the container images only on the OpenShift platform.
EDP uses the BuildConfig
object and the Kaniko tool for creating containers from a Dockerfile and pushing them to the internal container image registry. For Kaniko, it is also possible to change the Docker config file and push the containers to different container image registries.
By default, EPAM Delivery Platform uses the build-image-kaniko
stage for building container images on the Kubernetes platform and the build-image-from-dockerfile
stage for building container images on the OpenShift platform.
In order to change a build tool for the OpenShift Platform from the default buildConfig
object to the Kaniko tool, perform the following steps:
stages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-from-dockerfile\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n
stages['Build-library-kaniko'] = '[{\"name\": \"checkout\"},{\"name\": \"get-version\"}' +\n',{\"name\": \"dockerfile-lint\"},{\"name\": \"build-image-kaniko\"}' + \"${createJIMStage}\" + ',{\"name\": \"git-tag\"}]'\n
The Copy Shared Secrets stage provides the ability to copy secrets from the current Kubernetes namespace into a namespace created during CD pipeline.
Shared secrets
Please follow the steps described below to copy the secrets:
Create a secret in the current Kubernetes namespace that should be used in the deployment. The secret label must be app.edp.epam.com/use: cicd
, since the pipeline script will attempt to copy the secret by its label. For example:
kind: Secret\nmetadata:\n labels:\n app.edp.epam.com/use: cicd\n
Add the following step to the CD pipeline {\"name\":\"copy-secrets\",\"step_name\":\"copy-secrets\"}
. Alternatively, it is possible to create a custom job provisioner with this step.
Run the job. The pipeline script will create a secret with the same data in the namespace generated by the cd pipeline.
Note
Service account tokens are not supported.
Apart from running CD pipeline stages with the default logic, there is the ability to perform the following:
In order to have the ability to customize a stage logic, create a CD pipeline stage source as a Library:
Navigate to the Libraries section of the Admin Console and create a library with the Groovy-pipeline code language:
Note
If you clone the library, make sure that the correct source branch is selected.
Create library
Select the required fields to build your library:
Advanced settings
Go to the Continuous Delivery section of the Admin Console and create a CD pipeline with the library stage source and its branch:
Library source
Follow the steps below to add a new stage:
@Library(['edp-library-stages', 'edp-library-pipelines']) _\n\nDeploy()\n
import com.epam.edp.stages.impl.cd.Stage\n\n@Stage(name = \"notify\")\nclass Notify {\n Script script\n void run(context) {\n --------------- Put your own logic here ------------------\n script.println(\"Send notification logic\")\n --------------- Put your own logic here ------------------\n }\n}\nreturn Notify\n
Add a new stage to the STAGES parameter of the Jenkins job of your CD pipeline:
Stages parameter
Warning
To make this stage permanently present, please modify the job provisioner.
By default, the following stages are implemented in EDP pipeline framework:
Using one of these names for annotation in your own class will lead to redefining the default logic with your own.
Find below a sample of the possible flow of the redefining deploy stage:
@Library(['edp-library-stages', 'edp-library-pipelines']) _\n\nDeploy()\n
import com.epam.edp.stages.impl.cd.Stage\n\n@Stage(name = \"deploy\")\nclass CustomDeployStage {\n Script script\n\n void run(context) {\n --------------- Put your own logic here ------------------\n script.println(\"Custom deploy stage logic\")\n --------------- Put your own logic here ------------------\n }\n}\nreturn CustomDeployStage\n
Note
To add a new Custom Global Pipeline Library, please refer to the Add a New Custom Global Pipeline Library page.
To redefine any stage and add custom logic using global pipeline libraries, perform the steps below:
Navigate to the Libraries section of the Admin Console and create a library with the Groovy-pipeline code language:
Create library
Select the required fields to build your library:
Advanced settings
src/com/epam/edp/customStages/impl/cd/impl/
in the library repository, for instance: src/com/epam/edp/customStages/impl/cd/impl/EmailNotify.groovy
;EmailNotify.groovy
:package com.epam.edp.customStages.impl.cd.impl\n\nimport com.epam.edp.stages.impl.cd.Stage\n\n@Stage(name = \"notify\")\nclass Notify {\n Script script\n void run(context) {\n --------------- Put your own logic here ------------------\n script.println(\"Send notification logic\")\n --------------- Put your own logic here ------------------\n }\n}\n
Create a Jenkinsfile with default content and the added custom library to Jenkins:
@Library(['edp-library-stages', 'edp-library-pipelines', 'edp-custom-shared-library-name']) _\n\nDeploy()\n
Note
edp-custom-shared-library-name
is the name of your Custom Global Pipeline Library that should be added to the Jenkins Global Settings.
Add a new stage to the STAGES parameter of the Jenkins job of your CD pipeline:
Stages parameter
Warning
To make this stage permanently present, please modify the job provisioner.
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
Note
To add a new Custom Global Pipeline Library, please refer to the Add a New Custom Global Pipeline Library page.
By default, the following stages are implemented in EDP pipeline framework:
Using one of these names for annotation in your own class will lead to redefining the default logic with your own.
To redefine any stage and add custom logic using global pipeline libraries, perform the steps below:
Navigate to the Libraries section of the Admin Console and create a library with the Groovy-pipeline code language:
Create library
Select the required fields to build your library:
Advanced settings
src/com/epam/edp/customStages/impl/cd/impl/
in the library repository, for instance: src/com/epam/edp/customStages/impl/cd/impl/CustomDeployStage.groovy;
;CustomDeployStage.groovy
:package com.epam.edp.customStages.impl.cd.impl\n\nimport com.epam.edp.stages.impl.cd.Stage\n\n@Stage(name = \"deploy\")\nclass CustomDeployStage {\n Script script\n\n void run(context) {\n --------------- Put your own logic here ------------------\n script.println(\"Custom deploy stage logic\")\n --------------- Put your own logic here ------------------\n }\n}\n
Create a Jenkinsfile with default content and the added custom library to Jenkins:
@Library(['edp-library-stages', 'edp-library-pipelines', 'edp-custom-shared-library-name']) _\n\nDeploy()\n
Note
edp-custom-shared-library-name
is the name of your Custom Global Pipeline Library that should be added to the Jenkins Global Settings.
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
This chapter describes the main steps that should be followed when customizing a CI pipeline.
"},{"location":"user-guide/customize-ci-pipeline/#redefine-a-default-stage-logic-for-a-particular-application","title":"Redefine a Default Stage Logic for a Particular Application","text":"To redefine any stage and add custom logic, perform the steps below:
Open the GitHub repository:
Paste the copied skeleton from the reference stage and insert the necessary logic.
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
The stage logic structure is the following:
CustomSonar.groovy
import com.epam.edp.stages.impl.ci.ProjectType\nimport com.epam.edp.stages.impl.ci.Stage\n\n@Stage(name = \"sonar\", buildTool = [\"maven\"], type = [ProjectType.APPLICATION, ProjectType.AUTOTESTS, ProjectType.LIBRARY])\nclass CustomSonar {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn CustomSonar\n
Info
There is the ability to redefine the predefined EDP stage as well as to create it from scratch, it depends on the name that is used in the @Stage annotation. For example, using name = \"sonar\" will redefine an existing sonar stage with the same name, but using name=\"new-sonar\" will create a new stage.
By default, the following stages are implemented in EDP:
Mandatory points:
Open Jenkins and make sure that all the changes are correct after the completion of the customized pipeline.
To add a new stage for a particular application, perform the steps below:
Copy the part of a pipeline framework logic that cannot be predefined;
The stage logic structure is the following:
EmailNotify.groovy
import com.epam.edp.stages.impl.ci.ProjectType\nimport com.epam.edp.stages.impl.ci.Stage\n\n@Stage(name = \"email-notify\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass EmailNotify {\n Script script\n void run(context) {\n -------------------'Your custom logic here'\n }\n}\nreturn EmailNotify\n
Open the default set of stages and add a new one into the Default Value field by saving the respective type {\"name\": \"email-notify\"}, save the changes: Add stage
Open Jenkins to check the pipeline; as soon as the checkout stage is passed, the new stage will appear in the pipeline: Check stage
Warning
To make this stage permanently present, please modify the job provisioner.
Note
To add a new Custom Global Pipeline Library, please refer to the Add a New Custom Global Pipeline Library page.
To redefine any stage and add custom logic using global pipeline libraries, perform the steps below:
Open the GitHub repository:
/src/com/epam/edp/customStages/impl/ci/impl/stageName/
in the library repository, for instance: /src/com/epam/edp/customStages/impl/ci/impl/sonar/
;CustomSonar.groovy
.Paste the copied skeleton from the reference stage and insert the necessary logic.
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
The stage logic structure is the following:
CustomSonar.groovy
package com.epam.edp.customStages.impl.ci.impl.sonar\n\nimport com.epam.edp.stages.impl.ci.ProjectType\nimport com.epam.edp.stages.impl.ci.Stage\n\n@Stage(name = \"sonar\", buildTool = [\"maven\"], type = [ProjectType.APPLICATION, ProjectType.AUTOTESTS, ProjectType.LIBRARY])\nclass CustomSonar {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\n
Info
There is the ability to redefine the predefined EDP stage as well as to create it from scratch, it depends on the name that is used in the @Stage annotation. For example, using name = \"sonar\" will redefine an existing sonar stage with the same name, but using name=\"new-sonar\" will create a new stage.
By default, the following stages are implemented in EDP:
Mandatory points:
3.Open Jenkins and make sure that all the changes are correct after the completion of the customized pipeline.
"},{"location":"user-guide/customize-ci-pipeline/#add-a-new-stage-using-shared-library-via-custom-global-pipeline-libraries","title":"Add a New Stage Using Shared Library via Custom Global Pipeline Libraries","text":"Note
To add a new Custom Global Pipeline Library, please refer to the Add a New Custom Global Pipeline Library page.
To redefine any stage and add custom logic using global pipeline libraries, perform the steps below:
Open the GitHub repository:
/src/com/epam/edp/customStages/impl/ci/impl/stageName/
in the library repository, for instance: /src/com/epam/edp/customStages/impl/ci/impl/emailNotify/
;EmailNotify.groovy
.Copy the part of a pipeline framework logic that cannot be predefined;
Note
Pay attention to the appropriate annotation (EDP versions of all stages can be found on GitHub).
The stage logic structure is the following:
EmailNotify.groovy
package com.epam.edp.customStages.impl.ci.impl.emailNotify\n\nimport com.epam.edp.stages.impl.ci.ProjectType\nimport com.epam.edp.stages.impl.ci.Stage\n\n@Stage(name = \"email-notify\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass EmailNotify {\n Script script\n void run(context) {\n -------------------'Your custom logic here'\n }\n}\n
Open the default set of stages and add a new one into the Default Value field by saving the respective type {\"name\": \"email-notify\"}, save the changes: Add stage
Open Jenkins to check the pipeline; as soon as the checkout stage is passed, the new stage will appear in the pipeline: Check stage
Warning
To make this stage permanently present, please modify the job provisioner.
This section contains the description of dockerbuild-verify, dockerfile-lint stages which one can use in Code Review pipeline.
These stages help to obtain a quick response on the validity of the code in the Code Review pipeline in Kubernetes for all types of applications supported by EDP out of the box.
Add stages
Inspect the functions performed by the following stages:
dockerbuild-verify stage collects artifacts and builds an image from the Dockerfile without push to registry. This stage is intended to check if the image is built.
dockerfile-lint stage launches the hadolint command in order to check the Dockerfile.
This section contains the description of the ecr-to-docker stage, available in the Build pipeline.
The ecr-to-docker stage is intended to perform the push of Docker images collected from the Amazon ECR cluster storage to Docker Hub repositories, where the image becomes accessible to everyone who wants to use it. This stage is optional and is designed for working with various EDP components.
Note
When pushing the image from ECR to Docker Hub using crane, the SHA-256 value remains unchanged.
To run the ecr-to-docker stage just for once, navigate to the Build with Parameters option, add this stage to the stages list, and click Build. To add the ecr-to-docker stage to the pipeline, modify the job provisioner.
Note
To push properly the Docker image from the ECR storage, the ecr-to-docker stage should follow the build-image-kaniko stage. Add custom lib2
The ecr-to-docker stage contains a specific script that launches the following actions:
Checks whether a similar image exists in the Docker Hub in order to avoid its overwriting.
The ecr-to-docker stage expects the authorization credentials to be added as Kubernetes secret into EDP-installed namespace. To create the dockerhub-credentials secret, run the following command:
kubectl -n edp create secret generic dockerhub-credentials \\\n --from-literal=accesstoken=<dockerhub_access_token> \\\n --from-literal=account=<dockerhub_account_name> \\\n --from-literal=username=<dockerhub_user_name>\n
Note
Git Server is responsible for integration with Version Control System, whether it is GitHub, GitLab or Gerrit.
The Git Server is set via the global.gitProvider parameter of the values.yaml file.
To view the current Git Server, you can open EDP
-> Configuration
-> Git Servers
and inspect the following properties:
Git Server menu
To view authentication data that is used to connect to the Git server, use kubectl describe
command as follows:
kubectl describe GitServer git_server_name -n edp\n
"},{"location":"user-guide/git-server-overview/#delete-git-server","title":"Delete Git Server","text":"To remove a Git Server from the Git Servers list, utilize the kubectl delete
command as follows:
kubectl delete GitServer git_server_name -n edp\n
"},{"location":"user-guide/git-server-overview/#related-articles","title":"Related Articles","text":"This page is dedicated to the GitOps section of the Configuration tab, the process of establishing the GitOps repository, outline benefits it extends to users within the platform capabilities. GitOps, short for \"Git Operations\", is a modern approach to managing and automating infrastructure and application deployments. In GitOps, the desired state of your environment is declared and stored in a Git repository. With GitOps, you can ensure that your infrastructure and applications are always in sync with your intended configurations and readily adapt to changing requirements.
"},{"location":"user-guide/gitops/#overview","title":"Overview","text":"The purpose of the GitOps section is to provide users with the ability to customize the state of their environments with the help of GitOps approach that enables you to store your entire deployment configuration in a Git repository, providing version control for changes, consistent collaboration, and automated deployments. Enforcing GitOps allows you to declaratively define and automate your configurations, ensuring consistency, version control, and collaboration within your team.
To open the GitOps subsection, navigate to EDP Portal
-> EDP
-> Components
-> GitOps
:
GitOps section
"},{"location":"user-guide/gitops/#add-gitops-repository","title":"Add GitOps Repository","text":"To add a GitOps repository, follow the steps below:
Navigate to EDP
-> Components
-> GitOps
. Click the + Add GitOps Repository button:
Add GitOps repository
Fill in the required fields (in case VCS supports nesting) and click Save:
Required fields
Check the GitOps repository connected to the platform:
System Codebase
In addition to it, the system Codebase is called the same as the GitOps repository will be added to the Codebase list of the Components section:
GitOps Codebase
Note
The platform allows only one GitOps repository at a time.
"},{"location":"user-guide/gitops/#gitops-usage","title":"GitOps Usage","text":"Once the GitOps repository is added to the platform, you can set custom parameters for the deployed Helm Chart. To redefine the parameters, follow the steps below:
In the GitOps repository, create the values.yaml file according to the <pipeline-name>/<stage-name>/<application-name>-values.yaml
pattern.
In the created values.yaml file, enter the parameters with their custom values.
Navigate to the Environments section. Open the created environment, open its stage and deploy it with the Values override checkbox selected as it is shown below:
GitOps Codebase
In case you need to delete the GitOps repository, do the following:
Delete the GitOps repository in the Git provider.
Delete the Codebase custom resource using the kubectl delete
command:
kubectl delete Codebase edp-gitops -n edp\n
The Helm release deletion stage provides the ability to remove Helm releases from the namespace.
Note
Pay attention that this stages will remove all Helm releases from the namespace. To avoid loss of important data, before using this stage, make the necessary backups.
To remove Helm releases, follow the steps below:
Add the following step to the CD pipeline {\"name\":\"helm-uninstall\",\"step_name\":\"helm-uninstall\"}
. Alternatively, with this step, it is possible to create a custom job provisioner.
Run the job. The pipeline script will remove Helm releases from the namespace.
This section contains the description of the helm-lint and helm-docs stages that can be used in the Code Review pipeline.
The stages help to obtain a quick response on the validity of the helm chart code and documentation in the Code Review pipeline.
Inspect the functions performed by the following stages:
helm-lint stage launches the ct lint --charts-deploy-templates/ command in order to validate the chart.
Helm lint
See the current scheme:
View: chart_schema.yamlname: str()\nhome: str()\nversion: str()\ntype: str()\napiVersion: str()\nappVersion: any(str(), num())\ndescription: str()\nkeywords: list(str(), required=False)\nsources: list(str(), required=True)\nmaintainers: list(include('maintainer'), required=True)\ndependencies: list(include('dependency'), required=False)\nicon: str(required=False)\nengine: str(required=False)\ncondition: str(required=False)\ntags: str(required=False)\ndeprecated: bool(required=False)\nkubeVersion: str(required=False)\nannotations: map(str(), str(), required=False)\n---\nmaintainer:\n name: str(required=True)\n email: str(required=False)\n url: str(required=False)\n---\ndependency:\n name: str()\n version: str()\n repository: str()\n condition: str(required=False)\n tags: list(str(), required=False)\n enabled: bool(required=False)\n import-values: any(list(str()), list(include('import-value')), required=False)\n alias: str(required=False)\n
To get more information about the chart testing lint, please refer to the ct_lint documentation.
helm-docs stage helps to validate the generated documentation for the Helm deployment templates in the Code Review pipeline for all types of applications supported by EDP. This stage launches the helm-docs command in order to validate the chart documentation file existence and verify its relevance.
Requirements: helm-docs v1.10.0
Note
The helm-docs stage is optional. To extend the pipeline with an additional stage, please refer to the Configure Code Review Pipeline page.
Helm docs
Note
The example of the generated documentation.
This section describes the subsequent possible actions that can be performed with the newly added or existing infrastructures.
"},{"location":"user-guide/infrastructure/#check-and-remove-application","title":"Check and Remove Application","text":"As soon as the infrastructure is successfully provisioned, the following will be created:
The added application will be listed in the Applications list allowing you to do the following:
Applications menu
There are also options to sort the infrastructures:
EDP Portal provides the ability to enable, disable or edit the Jira Integration functionality for infrastructures.
To edit an infrastructure directly from the infrastructures overview page or when viewing the infrastructure data:
Edit infrastructure on the Infrastructures overview page
Edit infrastructure when viewing the infrastructure data
To enable Jira integration, in the Edit Infrastructure dialog do the following:
Edit infrastructure
a. Mark the Integrate with Jira server check box and fill in the necessary fields. Please see steps d-h on the Add Infrastructure page.
b. Select the Apply button to apply the changes.
To disable Jira integration, in the Edit Infrastructure dialog do the following:
a. Uncheck the Integrate with Jira server check box.
b. Select the Apply button to apply the changes.
To create, edit and delete infrastructure branches, please refer to the Manage Branches page.
This section describes the subsequent possible actions that can be performed with the newly added or existing libraries.
"},{"location":"user-guide/library/#check-and-remove-library","title":"Check and Remove Library","text":"As soon as the library is successfully provisioned, the following will be created:
Info
To navigate quickly to OpenShift, Tekton, Gerrit, SonarQube, Nexus, and other resources, click the Overview section on the navigation bar and hit the necessary link.
The added library will be listed in the Libraries list allowing to do the following:
Library menu
Create another library by clicking the plus sign icon on the right side of the screen and performing the same steps as described on the Add Library page.
Open library data by clicking its link name. Once clicked, the following blocks will be displayed:
Delete Library - remove library by clicking the vertical ellipsis button and then selecting Delete.
Note
The library that is used in a CD pipeline cannot be removed.
There are also options to sort the libraries:
EDP Portal provides the ability to enable, disable or edit the Jira Integration functionality for libraries.
To edit a library directly from the Libraries overview page or when viewing the library data:
Select Edit in the options icon menu:
Edit library on the libraries overview page
Edit library when viewing the library data
To enable Jira integration, in the Edit Library dialog do the following:
Edit library
a. Mark the Integrate with Jira server check box and fill in the necessary fields. Please see the steps d-h of the Add Library page.
b. Select the Apply button to apply the changes.
To disable Jira integration, in the Edit Library dialog do the following:
a. Uncheck the Integrate with Jira server check box.
b. Select the Apply button to apply the changes.
As a result, the necessary changes will be applied.
To create, edit and delete library branches, please refer to the Manage Branches page.
This page describes how to manage branches in the created component, whether it is an application, library, autotest or infrastructure.
"},{"location":"user-guide/manage-branches/#add-new-branch","title":"Add New Branch","text":"Note
When working with libraries, pay attention when specifying the branch name: the branch name is involved in the formation of the library version, so it must comply with the Semantic Versioning rules for the library.
When adding a component, the default branch is a master branch. In order to add a new branch, follow the steps below:
Navigate to the Branches block by clicking the component name link in the Components list.
Select the options icon related to the necessary branch and then select Create:
Add branch
Click Edit YAML in the upper-right corner of the dialog to open the YAML editor and add a branch. Otherwise, fill in the required fields in the dialog:
New branch
a. Release Branch - select the Release Branch check box if you need to create a release branch.
b. Branch name - type the branch name. Pay attention that this field remains static if you create a release branch. For the Clone and Import strategies: if you want to use the existing branch, enter its name into this field.
c. From Commit Hash - paste the commit hash from which the branch will be created. For the Clone and Import strategies: Note that if the From Commit Hash field is empty, the latest commit from the branch name will be used.
d. Branch version - enter the necessary branch version for the artifact. The Release Candidate (RC) postfix is concatenated to the branch version number.
e. Default branch version - type the branch version that will be used in a master branch after the release creation. The Snapshot postfix is concatenated to the master branch version number.
f. Click the Apply button and wait until the new branch will be added to the list.
Info
Adding of a new branch is indicated in the context of the EDP versioning type.
The default component repository is cloned and changed to the new indicated version before the build, i.e. the new indicated version will not be committed to the repository; thus, the existing repository will keep the default version.
"},{"location":"user-guide/manage-branches/#build-branch","title":"Build Branch","text":"In order to build branch from the latest commit, do the following:
Select the options icon related to the necessary branch and then select Build:
Build branch
The pipeline run status is displayed near the branch name in the Branches block:
Pipeline run status in EDP Portal
The corresponding item appears on the Tekton Dashboard in the PipelineRuns section:
Pipeline run status in Tekton
"},{"location":"user-guide/manage-branches/#delete-branch","title":"Delete Branch","text":"Note
The default master branch cannot be removed.
In order to delete the added branch with the corresponding record in the EDP Portal database, do the following:
Select the options icon related to the necessary branch and then select Delete:
Delete branch
This page describes actions that can be performed to an already created environment. If no environments are created yet, navigate to the Add Environment page.
Environments page
Open environment data by clicking its link name.
Edit the environment by selecting the options icon next to its name in the environments list, and then selecting Edit. For details see the Edit Existing Environment section.
Delete the added environment by selecting the options icon next to its name in the environment list, and then selecting Delete.
Note
Please keep in mind that after deleting the environment, all the created resources within the environment will be deleted.
Sort the existing environments in a table by clicking the sorting icons in the table header. When sorting by name, the environments will be displayed in alphabetical order. You can also sort the environments by their status.
Search the necessary environment by the namespace or by entering the corresponding name, language or the build tool into the Filter tool.
Select a number of environment displayed per page (15, 25 or 50 rows) and navigate between pages if the number of environments exceeds the capacity of a single page.
To view environment details, click the environment name in the environments list. Once clicked, the following data will be displayed:
Environment details
a. Allows to view environment in Argo CD, view its metadata (generation, finalizers, namespace, etc.).
b. Shows application/stage status.
c. Shows application/stage names. Once clicked, navigates you to the application data or stage details.
d. Allows to create a new stage.
e. Allows to view environment data in Argo CD, Grafana, Kibana and shows in which cluster the environment is deployed in.
f. Allows to edit or delete a stage.
"},{"location":"user-guide/manage-environments/#edit-existing-environment","title":"Edit Existing Environment","text":"Edit the environment directly from the environment overview page or when viewing the environment data:
Select Edit in the options icon menu next to the environment name:
Edit environment on the environment overview page
Edit environment when viewing the environment data
Apply the necessary changes (edit the list of applications for deploy, application branches, and promotion in the pipeline). Add new extra stages by clicking the plus sign icon and filling in the application branch and promotion in the pipeline.
Edit environment dialog
Select the Apply button to confirm the changes.
In order to create a new stage for the existing environment, follow the steps below:
Navigate to the Stages block by clicking the environment name link in the environments list.
Add environment stage
Select Create to open the Create stage dialog.
Fill in the required fields in the dialog. Alternatively, click Edit YAML in the upper-right corner of the Create stage dialog to open the YAML editor and add a stage. Please see the Stages Menu section for details.
Click the Apply button.
In order to edit a stage for the existing environment, follow the steps below:
Navigate to the Stages block by clicking the environment name link in the environments list.
Edit environment stage
Select the options icon related to the necessary stage and then select Edit.
Edit environment stage dialog
In the Edit Stage dialog, change the stage trigger type. See more about this field in the Stages Menu section.
Click the Apply button.
Note
You cannot remove the last stage, as the environment does not exist without at least one.
In order to delete a stage for the existing environment, follow the steps below:
Navigate to the Stages block by clicking the environment name link in the environments list.
Delete environment stage
Select the options icon related to the necessary stage and then select Delete. After the confirmation, the CD stage is deleted with all its components: database record, Tekton pipeline, and cluster namespace.
To view the environment stage data for the existing environment, follow the steps below:
Navigate to the Stages block by clicking the environment name link in the environments list.
Expand environment stage
Click stage name. The following blocks will be displayed:
environment stage overview
To deploy an application, follow the steps below:
Deploy the promoted application
Navigate to the Applications block of the stage and select an application.
Select the image stream version from the drop-down list.
(Optional) Enable setting custom values for Helm Charts. For more details, please refer to the Manage GitOps page.
Click Deploy. The application will be deployed in the Argo CD tool as well.
Info
In case of using OpenShift internal registry, if the deployment fails with the ImagePullBackOff error, delete the pod that was created for this application.
To update or uninstall the application, select Update or Uninstall.
Update or uninstall the application
As a result, the application will be updated or uninstalled in the Argo CD tool as well.
Note
In a nutshell, the Update button updates your image version in the Helm chart, whereas the Uninstall button deletes the Helm chart from the namespace where the Argo CD application is deployed.
"},{"location":"user-guide/manage-environments/#troubleshoot-application","title":"Troubleshoot Application","text":"There is a couple of EDP Portal capabilities that will help in monitoring and troubleshooting deployed applications, namely, terminal and logs.
To inspect the deployed application in EDP Portal, take the following steps:
Open the application logs by clicking the Show Logs
button:
Show Logs button
Inspect the shown logs:
Inspect Logs
Open the application terminal by clicking the Show Terminal
button:
Show Terminal button
Operate the terminal to fix the problem if any:
Inspect application
The EDP Marketplace offers a range of Templates, predefined tools and settings for creating software. These Templates speed up development, minimize errors, and ensure consistency. A key EDP Marketplace feature is customization. Organizations can create and share their own Templates, finely tuned to their needs. Each Template serves as a tailored blueprint of tools and settings.
These tailored Templates include preset CI/CD pipelines, automating your development workflows. From initial integration to final deployment, these processes are efficiently managed. Whether for new applications or existing ones, these templates enhance processes, save time, and ensure consistency.
To see the Marketplace section, navigate to the Main menu -> EDP -> Marketplace. General look of the Marketplace section is described below:
Marketplace section (listed view)
There is also a possibility to switch into the tiled view instead of the listed one:
Marketplace section (tiled view)
To view the details of a marketplace item, simply click on its name:
Item details
The details window shows supplemental information, such as item's author, keywords, release version and the link to the repository it is located in. The window also contains the Create from template button that allows users to create the component by the chosen template. The procedure of creating new components is described in the Add Component via Marketplace page.
"},{"location":"user-guide/marketplace/#related-articles","title":"Related Articles","text":"Open Policy Agent (OPA) is a policy engine that provides:
EPAM Delivery Platform ensures the implemented Open Policy Agent support allowing to work with Open Policy Agent bundles that is processed by means of stages in the Code Review and Build pipelines. These pipelines are expected to be created after the Rego OPA Library is added.
"},{"location":"user-guide/opa-stages/#code-review-pipeline-stages","title":"Code Review Pipeline Stages","text":"In the Code Review pipeline, the following stages are available:
checkout stage, a standard step during which all files are checked out from a selected branch of the Git repository.
tests stage containing a script that performs the following actions:
2.1. Runs policy tests.
2.2. Converts OPA test results into JUnit format.
2.3. Publishes JUnit-formatted results to Jenkins.
In the Build pipeline, the following stages are available:
checkout stage, a standard step during which all files are checked out from a selected branch of the Git repository.
get-version optional stage, a step where library version is determined either via:
2.1. Standard EDP versioning functionality.
2.2. Manually specified version. In this case .manifest file in a root directory MUST be provided. File must contain a JSON document with revision field. Minimal example: { \"revision\": \"1.0.0\" }\"
.
tests stage containing a script that performs the following actions: 3.1. Runs policy tests. 3.2. Converts OPA test results into JUnit format. 3.3. Publishes JUnit-formatted results to Jenkins.
git-tag stage, a standard step where git branch is tagged with a version.
This chapter provides detailed information about the EDP pipeline framework concepts and parts, as well as the accurate data about the Code Review
, Build
and Deploy
pipelines with the respective stages.
Note
The whole logic is applied to Jenkins as it is the main tool for the CI/CD processes organization.
EDP pipeline framework basic
The general EDP Pipeline Framework consists of several parts:
Jenkinsfile example
Pipeline script
"},{"location":"user-guide/pipeline-framework/#cicd-jobs-comparison","title":"CI/CD Jobs Comparison","text":"Explore the CI and CD job comparison. Please note that the dynamic stages order can be changed, meanwhile, the predefined stages order in the reference pipeline cannot be changed, i.e. only the predefined stages set can be run.
CI/CD jobs comparison
"},{"location":"user-guide/pipeline-framework/#context","title":"Context","text":"Context - a variable that stores and transfers all necessary parameters between stages that are used by pipeline during performing.
Note
If the input context isn't transferred, the stage will be failed.
"},{"location":"user-guide/pipeline-framework/#annotations-for-cicd-stages","title":"Annotations for CI/CD Stages","text":"Annotation for CI Stages:
Annotation for CD Stages:
CodeReview() \u2013 a function that allows using the EDP implementation for the Code Review pipeline.
Note
All values of different parameters that are used during the pipeline execution are stored in the \"Map\" context.
The Code Review pipeline consists of several steps:
On the master:
On a particular Jenkins agent that depends on the build tool:
Using in pipelines - @Library(['edp-library-pipelines@version'])
The corresponding enums, interfaces, classes, and their methods can be used separately from the EDP Pipelines library function (please refer to Table 1 and Table 2).
Table 1. Enums and Interfaces with the respective properties, methods, and examples.
Enums Interfaces PlatformType: - OPENSHIFT - KUBERNETES JobType: - CODEREVIEW - BUILD - DEPLOY BuildToolType: - MAVEN - GRADLE - NPM - DOTNET Platform() - contains methods for working with platform CLI. At the moment only OpenShift is supported. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Methods: getJsonPathValue(String k8s_kind, String k8s_kind_name, String jsonPath): return String value of specific parameter of particular object using jsonPath utility. Example:context.platform.getJsonPathValue(''cm'',
''project-settings'', ''.data.username'')
. BuildTool() - contains methods for working with different buildTool from ENUM BuildToolType. Should be invoked on Jenkins build agents. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Nexus object - Object of class Nexus. Methods: init: return parameters of buildTool that are needed for running stages. Example: context.buildTool = new BuildToolFactory().
getBuildToolImpl
(context.application.config.build_tool, this,
context.nexus) context.buildTool.init()
. Table 2. Classes with the respective properties, methods, and examples.
Classes Description (properties, methods, and examples) PlatformFactory() - Class that contains methods getting an implementation of CLI of the platform. At the moment OpenShift and Kubernetes are supported. Methods:getPlatformImpl(PlatformType platform, Script script): return Class Platform
. Example: context.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)
. Application(String name, Platform platform, Script script) - Class that describes the application object. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Platform platform - Object of a class Platform(). String name - Name for the application for creating an object. Map config - Map of configuration settings for the particular application that is loaded from config map project-settings. String version - Application version, initially empty. Is set on the get-version step. String deployableModule - The name of the deployable module for multi-module applications, initially empty. String buildVersion - Version of the built artifact, contains build number of Job initially empty. String deployableModuleDir - The name of deployable module directory for multi-module applications, initially empty. Array imageBuildArgs - List of arguments for building an application Docker image. Methods: setConfig(String gerrit_autouser, String gerrit_host, String gerrit_sshPort, String gerrit_project): set the config property with values from config map. Example: context.application = new Application(context.job, context.gerrit.project, context.platform, this) context.application.setConfig(context.gerrit.autouser, context.gerrit.host, context.gerrit.sshPort, context.gerrit.project)
Job(type: JobType.value, platform: Platform, script: Script) - Class that describes the Gerrit tool. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Platform platform - Object of a class Platform(). JobType.value type. String deployTemplatesDirectory - The name of the directory in application repository where deploy templates are located. It can be set for a particular Job through DEPLOY_TEMPLATES_DIRECTORY parameter. String edpName - The name of the EDP Project. Map stages - Contains all stages in JSON format that is retrieved from Jenkins job env variable. String envToPromote - The name of the environment for promoting images. Boolean promoteImages - Defines whether images should be promoted or not. Methods: getParameterValue(String parameter, String defaultValue = null): return parameter of ENV variable of Jenkins job. init(): set all the properties of the Job object. setDisplayName(String displayName): set display name of the Jenkins job. setDescription(String description, Boolean addDescription = false): set new or add to the existing description of the Jenkins job. printDebugInfo(Map context): print context info to the log of Jenkins' job. runStage(String stage_name, Map context): run the particular stage according to its name. Example: context.job = new Job(JobType.CODEREVIEW.value,
context.platform, this)
context.job.init()
context.job.printDebugInfo(context)
context.job.setDisplayName(\"test\")
context.job.setDescription(\"Name: ${context.application.config.name}\")
Gerrit(Job job, Platform platform, Script script) - Class that describes the Gerrit tool. Properties: Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String credentialsId - Credential Id in Jenkins for Gerrit.String autouser - Username of an auto user in Gerrit for integration with Jenkins.String host - Gerrit host.String project - the project name of the built application.String branch - branch to build the application from.String changeNumber - change number of Gerrit commit.String changeName - change name of Gerrit commit.String refspecName - refspecName of Gerrit commit.String sshPort - Gerrit ssh port number.String patchsetNumber - patchsetNumber of Gerrit commit.Methods: init(): set all the properties of Gerrit object. Example: context.gerrit = new Gerrit(context.job, context.platform, this)
context.gerrit.init()
Nexus(Job job, Platform platform, Script script) - Class that describes the Nexus tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String autouser - Username of an auto user in Nexus for integration with Jenkins.String credentialsId - Credential Id in Jenkins for Nexus.String host - Nexus host.String port - Nexus http(s) port.String repositoriesUrl - Base URL of repositories in Nexus.String restUrl - URL of Rest API.Methods:init(): set all the properties of Nexus objectExample: context.nexus = new Nexus(context.job, context.platform, this)
context.nexus.init()
Sonar(Job job, Platform platform, Script script) - Class that describes the Sonar tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String route - External route of the sonar application.Methods:init(): set all the properties of Sonar objectExample: context.sonar = new Sonar(context.job, context.platform, this)
context.sonar.init()
"},{"location":"user-guide/pipeline-framework/#code-review-pipeline-stages","title":"Code Review Pipeline Stages","text":"Each EDP stage implementation has run method that is as input parameter required to pass the \"Map\" context with different keys. Some stages can implement the logic for several build tools and application types, some of them are specific.
The Code Review pipeline includes the following default stages: Checkout \u2192 Gerrit Checkout \u2192 Compile \u2192 Tests \u2192 Sonar.
Info
To get the full description of every stage, please refer to the EDP Stages Framework section.
"},{"location":"user-guide/pipeline-framework/#how-to-redefine-or-extend-the-edp-pipeline-stages-library","title":"How to Redefine or Extend the EDP Pipeline Stages Library","text":"Inspect the points below to redefine or extend the EDP Pipeline Stages Library:
Redefinition:
import com.epam.edp.stages.ProjectType\nimport com.epam.edp.stages.Stage\n@Stage(name = \"compile\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass CustomBuildMavenApplication {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn CustomBuildMavenApplication\n
Extension:
import com.epam.edp.stages.ProjectType\nimport com.epam.edp.stages.Stage\n@Stage(name = \"new-stage\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass NewStageMavenApplication {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn NewStageMavenApplication\n
"},{"location":"user-guide/pipeline-framework/#using-edp-stages-library-in-the-pipeline","title":"Using EDP Stages Library in the Pipeline","text":"In order to use the EDP stages, the created pipeline should fit some requirements, that`s why a developer has to do the following:
context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n
After that, there is the ability to run any EDP stage beforehand by defining a necessary context: context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)
For instance, the pipeline can look like:
@Library(['edp-library-stages']) _\n\nimport com.epam.edp.stages.StageFactory\nimport org.apache.commons.lang.RandomStringUtils\n\ncontext = [:]\n\nnode('maven') {\n context.workDir = new File(\"/tmp/${RandomStringUtils.random(10, true, true)}\")\n context.workDir.deleteDir()\n\n context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n\n context.gerrit = [:]\n context.application = [:]\n context.application.config = [:]\n context.buildTool = [:]\n context.nexus = [:]\n\n\n\n stage(\"checkout\") {\n context.gerrit.branch = \"master\"\n context.gerrit.credentialsId = \"jenkins\"\n context.application.config.cloneUrl = \"ssh://jenkins@gerrit:32092/sit-718-cloned-java-maven-project\"\n context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)\n }\n\n\n stage(\"compile\") {\n context.buildTool.command = \"mvn\"\n context.nexus.credentialsId = \"nexus\"\n context.factory.getStage(\"compile\",\"maven\",\"application\").run(context)\n }\n}\n
Or in a declarative way:
@Library(['edp-library-stages']) _\n\nimport com.epam.edp.stages.StageFactory\nimport org.apache.commons.lang.RandomStringUtils\n\ncontext = [:]\n\npipeline {\n agent { label 'maven' }\n stages {\n stage('Init'){\n steps {\n script {\n context.workDir = new File(\"/tmp/${RandomStringUtils.random(10, true, true)}\")\n context.workDir.deleteDir()\n context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n\n context.gerrit = [:]\n context.application = [:]\n context.application.config = [:]\n context.buildTool = [:]\n context.nexus = [:]\n }\n }\n }\n\n stage(\"Checkout\") {\n steps {\n script {\n context.gerrit.branch = \"master\"\n context.gerrit.credentialsId = \"jenkins\"\n context.application.config.cloneUrl = \"ssh://jenkins@gerrit:32092/sit-718-cloned-java-maven-project\"\n context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)\n }\n }\n }\n\n stage('Compile') {\n steps {\n script {\n context.buildTool.command = \"mvn\"\n context.nexus.credentialsId = \"nexus\"\n context.factory.getStage(\"compile\",\"maven\",\"application\").run(context)\n }\n }\n }\n }\n}\n
"},{"location":"user-guide/pipeline-framework/#build-pipeline","title":"Build Pipeline","text":"Build() \u2013 a function that allows using the EDP implementation for the Build pipeline. All values of different parameters that are used during the pipeline execution are stored in the \"Map\" context.
The Build pipeline consists of several steps:
On the master:
On a particular Jenkins agent that depends on the build tool:
Using in pipelines - @Library(['edp-library-pipelines@version'])
The corresponding enums, interfaces, classes, and their methods can be used separately from the EDP Pipelines library function (please refer to Table 3 and Table 4).
Table 3. Enums and Interfaces with the respective properties, methods, and examples.
Enums Interfaces PlatformType:- OPENSHIFT- KUBERNETESJobType:- CODEREVIEW- BUILD- DEPLOYBuildToolType:- MAVEN- GRADLE- NPM- DOTNET Platform() - contains methods for working with platform CLI. At the moment only OpenShift is supported.Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Methods:getJsonPathValue(String k8s_kind, String k8s_kind_name, String jsonPath): return String value of specific parameter of particular object using jsonPath utility.Example:context.platform.getJsonPathValue(\"cm\",\"project-settings\",
\".data.username\")
BuildTool() - contains methods for working with different buildTool from ENUM BuildToolType. Should be invoked on Jenkins build agents.Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Nexus object - Object of class Nexus. See description below:Methods:init: return parameters of buildTool that are needed for running stages.Example:context.buildTool = new BuildToolFactory().getBuildToolImpl
(context.application.config.build_tool, this,
context.nexus)context.buildTool.init()
Table 4. Classes with the respective properties, methods, and examples. Classes Description (properties, methods, and examples) PlatformFactory() - Class that contains methods getting an implementation of CLI of the platform. At the moment OpenShift and Kubernetes are supported. Methods:getPlatformImpl(PlatformType platform, Script script): return Class PlatformExample:context.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)
Application(String name, Platform platform, Script script) - Class that describes the application object. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().String name - Name for the application for creating an object.Map config - Map of configuration settings for the particular application that is loaded from config map project-settings.String version - Application version, initially empty. Is set on the get-version step.String deployableModule - The name of the deployable module for multi-module applications, initially empty.String buildVersion - Version of the built artifact, contains build number of Job initially empty.String deployableModuleDir - The name of deployable module directory for multi-module applications, initially empty.Array imageBuildArgs - List of arguments for building the application Docker image.Methods:setConfig(String gerrit_autouser, String gerrit_host, String gerrit_sshPort, String gerrit_project): set the config property with values from config map.Example:context.application = new Application(context.job, context.gerrit.project, context.platform, this) context.application.setConfig(context.gerrit.autouser, context.gerrit.host, context.gerrit.sshPort, context.gerrit.project)
Job(type: JobType.value, platform: Platform, script: Script) - Class that describes the Gerrit tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().JobType.value type.String deployTemplatesDirectory - The name of the directory in application repository, where deploy templates are located. It can be set for a particular Job through DEPLOY_TEMPLATES_DIRECTORY parameter.String edpName - The name of the EDP Project.Map stages - Contains all stages in JSON format that is retrieved from Jenkins job env variable.String envToPromote - The name of the environment for promoting images.Boolean promoteImages - Defines whether images should be promoted or not.Methods:getParameterValue(String parameter, String defaultValue = null): return parameter of ENV variable of Jenkins job.init(): set all the properties of the Job object.setDisplayName(String displayName): set display name of the Jenkins job.setDescription(String description, Boolean addDescription = false): set new or add to the existing description of the Jenkins job.printDebugInfo(Map context): print context info to the log of Jenkins' job.runStage(String stage_name, Map context): run the particular stage according to its name.Example:context.job = new Job(JobType.CODEREVIEW.value, context.platform, this) context.job.init() context.job.printDebugInfo(context) context.job.setDisplayName(\"test\") context.job.setDescription(\"Name: ${context.application.config.name}\")
Gerrit(Job job, Platform platform, Script script) - Class that describes the Gerrit tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String credentialsId - Credentials Id in Jenkins for Gerrit.String autouser - Username of an auto user in Gerrit for integration with Jenkins.String host - Gerrit host.String project - the project name of the built application.String branch - branch to build an application from.String changeNumber - change number of Gerrit commit.String changeName - change name of Gerrit commit.String refspecName - refspecName of Gerrit commit.String sshPort - Gerrit ssh port number.String patchsetNumber - patchsetNumber of Gerrit commit.Methods:init(): set all the properties of Gerrit objectExample: context.gerrit = new Gerrit(context.job, context.platform, this) context.gerrit.init()
Nexus(Job job, Platform platform, Script script) - Class that describes the Nexus tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String autouser - Username of an auto user in Nexus for integration with Jenkins.String credentialsId - Credentials Id in Jenkins for Nexus.String host - Nexus host.String port - Nexus http(s) port.String repositoriesUrl - Base URL of repositories in Nexus.String restUrl - URL of Rest API.Methods:init(): set all the properties of the Nexus object.Example:context.nexus = new Nexus(context.job, context.platform, this) context.nexus.init()
Sonar(Job job, Platform platform, Script script) - Class that describes the Sonar tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform().Job job - Object of a class Job().String route - External route of the sonar application.Methods:init(): set all the properties of Sonar object.Example:context.sonar = new Sonar(context.job, context.platform, this) context.sonar.init()
"},{"location":"user-guide/pipeline-framework/#build-pipeline-stages","title":"Build Pipeline Stages","text":"Each EDP stage implementation has run method that is as input parameter required to pass a context map with different keys. Some stages can implement the logic for several build tools and application types, some of them are specific.
The Build pipeline includes the following default stages: Checkout \u2192 Gerrit Checkout \u2192 Compile \u2192 Get version \u2192 Tests \u2192 Sonar \u2192 Build \u2192 Build Docker Image \u2192 Push \u2192 Git tag.
Info
To get the full description of every stage, please refer to the EDP Stages Framework section.
"},{"location":"user-guide/pipeline-framework/#how-to-redefine-or-extend-edp-pipeline-stages-library","title":"How to Redefine or Extend EDP Pipeline Stages Library","text":"Inspect the points below to redefine or extend the EDP Pipeline Stages Library:
Redefinition:
import com.epam.edp.stages.ProjectType\nimport com.epam.edp.stages.Stage\n@Stage(name = \"compile\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass CustomBuildMavenApplication {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn CustomBuildMavenApplication\n
Extension:
import com.epam.edp.stages.ProjectType\nimport com.epam.edp.stages.Stage\n@Stage(name = \"new-stage\", buildTool = \"maven\", type = ProjectType.APPLICATION)\nclass NewStageMavenApplication {\n Script script\n void run(context) {\n script.sh \"echo 'Your custom logic of the stage'\"\n }\n}\nreturn NewStageMavenApplication\n
"},{"location":"user-guide/pipeline-framework/#using-edp-stages-library-in-the-pipeline_1","title":"Using EDP Stages Library in the Pipeline","text":"In order to use the EDP stages, the created pipeline should fit some requirements, that`s why a developer has to do the following:
context.factory = new StageFactory(script: this)\ncontext.factory.loadEdpStages().each() { context.factory.add(it) }\n
After that, there is the ability to run any EDP stage beforehand by defining a requirement context context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)
For instance, the pipeline can look like:
@Library(['edp-library-stages']) _\n\nimport com.epam.edp.stages.StageFactory\nimport org.apache.commons.lang.RandomStringUtils\n\ncontext = [:]\n\nnode('maven') {\n context.workDir = new File(\"/tmp/${RandomStringUtils.random(10, true, true)}\")\n context.workDir.deleteDir()\n\n context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n\n context.gerrit = [:]\n context.application = [:]\n context.application.config = [:]\n context.buildTool = [:]\n context.nexus = [:]\n\n\n\n stage(\"checkout\") {\n context.gerrit.branch = \"master\"\n context.gerrit.credentialsId = \"jenkins\"\n context.application.config.cloneUrl = \"ssh://jenkins@gerrit:32092/sit-718-cloned-java-maven-project\"\n context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)\n }\n\n\n stage(\"compile\") {\n context.buildTool.command = \"mvn\"\n context.nexus.credentialsId = \"nexus\"\n context.factory.getStage(\"compile\",\"maven\",\"application\").run(context)\n }\n}\n
Or in a declarative way:
@Library(['edp-library-stages']) _\n\nimport com.epam.edp.stages.StageFactory\nimport org.apache.commons.lang.RandomStringUtils\n\ncontext = [:]\n\npipeline {\n agent { label 'maven' }\n stages {\n stage('Init'){\n steps {\n script {\n context.workDir = new File(\"/tmp/${RandomStringUtils.random(10, true, true)}\")\n context.workDir.deleteDir()\n context.factory = new StageFactory(script: this)\n context.factory.loadEdpStages().each() { context.factory.add(it) }\n\n context.gerrit = [:]\n context.application = [:]\n context.application.config = [:]\n context.buildTool = [:]\n context.nexus = [:]\n }\n }\n }\n\n stage(\"Checkout\") {\n steps {\n script {\n context.gerrit.branch = \"master\"\n context.gerrit.credentialsId = \"jenkins\"\n context.application.config.cloneUrl = \"ssh://jenkins@gerrit:32092/sit-718-cloned-java-maven-project\"\n context.factory.getStage(\"checkout\",\"maven\",\"application\").run(context)\n }\n }\n }\n\n stage('Compile') {\n steps {\n script {\n context.buildTool.command = \"mvn\"\n context.nexus.credentialsId = \"nexus\"\n context.factory.getStage(\"compile\",\"maven\",\"application\").run(context)\n }\n }\n }\n }\n}\n
"},{"location":"user-guide/pipeline-framework/#edp-library-stages-description","title":"EDP Library Stages Description","text":"Using in pipelines - @Library(['edp-library-stages@version'])
The corresponding enums, classes, interfaces and their methods can be used separately from the EDP Stages library function (please refer to Table 5).
Table 5. Enums and Classes with the respective properties, methods, and examples.
Enums Classes ProjectType: - APPLICATION - AUTOTESTS - LIBRARY StageFactory() - Class that contains methods getting an implementation of the particular stage either EDP from shared library or custom from application repository.Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Map stages - Map of stages implementations.Methods:loadEdpStages(): return a list of Classes that describes EDP stages implementations.loadCustomStages(String directory): return a list of Classes that describes EDP custom stages from application repository from \"directory\". The \"directory\" should have an absolute path to files with classes of custom stages implementations. Should be run from a Jenkins agent.add(Class clazz): register class for some particular stage in stages map of StageFactory class.getStage(String name, String buildTool, String type): return an object of the class for a particular stage from stages property based on stage name and buildTool, type of application.Example:context.factory = new StageFactory(script: this)
context.factory.loadEdpStages().each() { context.factory.add(it) }
context.factory.loadCustomStages(\"${context.workDir}/stages\").each() { context.factory.add(it) }
context.factory.getStage(stageName.toLowerCase(),context.application.config.build_tool.toLowerCase(),
context.application.config.type).run(context)
"},{"location":"user-guide/pipeline-framework/#edp-stages-framework","title":"EDP Stages Framework","text":"Each EDP stage implementation has run method that is as input parameter required to pass a context map with different keys. Some stages can implement the logic for several build tools and application types, some of them are specific.
Inspect the Table 6 and Table 7 that contain the full description of every stage that can be included in Code Review and Build pipelines: Checkout \u2192 Gerrit Checkout \u2192 Compile \u2192 Get version \u2192 Tests \u2192 Sonar \u2192 Build \u2192 Build Docker Image \u2192 Push \u2192 Git tag.
Table 6. The Checkout, Gerrit Checkout, Compile, Get version, and Tests stages description.
Checkout Gerrit Checkout Compile Get version Tests name = \"checkout\",buildTool = [\"maven\", \"npm\", \"dotnet\",\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- StageFactory context.factory- String context.gerrit.branch- String context.gerrit.credentialsId- String context.application.config.cloneUrl name = \"gerrit-checkout\",buildTool = [\"maven\", \"npm\", \"dotnet\",\"gradle\"]type = [ProjectType.APPLICATION, ProjectType.AUTOTESTS, ProjectType.LIBRARY]context required:- String context.workDir- StageFactory context.factory- String context.gerrit.changeName- String context.gerrit.refspecName- String context.gerrit.credentialsId- String context.application.config.cloneUrl name = \"compile\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.sln_filenameoutput:- String context.buildTool.sln_filenamebuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.command- String context.nexus.credentialsIdbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.command- String context.nexus.credentialsIdbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.groupRepository name = \"get-version\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- Map(empty) context.application- String context.gerrit.branch- Job context.joboutput:-String context.application.deplyableModule- String context.application.deplyableModuleDir- String context.application.version- String context.application.buildVersionbuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.command- Job context.job- String context.gerrit.branchoutput:- String context.application.deplyableModuleDir- String context.application.version- String context.application.buildVersionbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.command- Job context.job- String context.gerrit.branchoutput:- String context.application.deplyableModule- String context.application.deplyableModuleDir- String context.application.version- String context.application.buildVersionbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- Job context.job- String context.gerrit.branchoutput:- String context.application.deplyableModuleDir- String context.application.version- String context.application.buildVersion name = \"tests\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDirbuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.commandbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.commandtype = [ProjectType.AUTOTESTS]context required:- String context.workDir- String context.buildTool.command- String context.application.config.report_frameworkbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDirTable 7. The Sonar, Build, Build Docker Image, Push, and Git tag stages description.
Sonar Build Build Docker Image Push Git tag name = \"sonar\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.job.type- String context.application.name- String context.buildTool.sln_filename- String context.sonar.route- String context.gerrit.changeName(Only for codereview pipeline)- String context.gerrit.branch(Only for build pipeline)buildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.job.type- String context.nexus.credentialsId- String context.buildTool.command- String context.application.name- String context.sonarRoute- String context.gerrit.changeName(Only for codereview pipeline)- String context.gerrit.branch(Only for build pipeline)buildTool = [\"maven\"]type = [ProjectType.APPLICATION, ProjectType.AUTOTESTS, ProjectType.LIBRARY]context required:- String context.workDir- String context.job.type- String context.nexus.credentialsId- String context.application.name- String context.buildTool.command- String context.sonar.route- String context.gerrit.changeName(Only for codereview pipeline)- String context.gerrit.branch(Only for build pipeline)buildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.job.type- String context.sonar.route- String context.application.name- String context.gerrit.changeName(Only for codereview pipeline)- String context.gerrit.branch(Only for build pipeline) name = \"build\"buildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.command- String context.nexus.credentialsIdbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.buildTool.command- String context.nexus.credentialsIdbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.groupRepository name = \"build-image\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.application.deployableModule- String context.application.deployableModuleDir- String context.application.name- String context.application.config.language- String context.application.buildVersion- Boolean context.job.promoteImages- String context.job.envToPromotebuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.application.deployableModule- String context.application.deployableModuleDir- String context.application.name- String context.application.config.language- String context.application.buildVersion- Boolean context.job.promoteImages- String context.job.envToPromotebuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.application.deployableModule- String context.application.deployableModuleDir- String context.application.name- String context.application.config.language- String context.application.buildVersion- Boolean context.job.promoteImages- String context.job.envToPromotebuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.application.deployableModule- String context.application.deployableModuleDir- String context.application.name- String context.application.config.language- String context.application.buildVersion- Boolean context.job.promoteImages- String context.job.envToPromote name = \"push\"buildTool = [\"dotnet\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.gerrit.project- String context.buildTool.sln_filename- String context.buildTool.snugetApiKey- String context.buildTool.hostedRepositorybuildTool = [\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.application.version- String context.buildTool.hostedRepository- String context. buildTool.settingsbuildTool = [\"maven\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.application.version- String context.buildTool.hostedRepository- String context.buildTool.commandbuildTool = [\"npm\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.nexus.credentialsId- String context.buildTool.hostedRepository- String context.gerrit.autouser name = \"git-tag\"buildTool = [\"maven\", \"npm\", \"dotnet\",\"gradle\"]type = [ProjectType.APPLICATION]context required:- String context.workDir- String context.gerrit.credentialsId- String context.gerrit.sshPort- String context.gerrit.host- String context.gerrit.autouser- String context.application.buildVersion"},{"location":"user-guide/pipeline-framework/#deploy-pipeline","title":"Deploy Pipeline","text":"Deploy() \u2013 a function that allows using the EDP implementation for the deploy pipeline. All values of different parameters that are used during the pipeline execution are stored in the \"Map\" context.
The deploy pipeline consists of several steps:
On the master:
On a particular autotest Jenkins agent that depends on the build tool:
_Using in pipelines - @Library(['edp-library-pipelines@version']) _
The corresponding enums and interfaces with their methods can be used separately from the EDP Pipelines library function (please refer to Table 8 and Table 9).
Table 8. Enums and Interfaces with the respective properties, methods, and examples.
Enums Interfaces PlatformType:- OPENSHIFT- KUBERNETESJobType:- CODEREVIEW- BUILD- DEPLOYBuildToolType:- MAVEN- GRADLE- NPM- DOTNET Platform() - contains methods for working with platform CLI. At the moment only OpenShift is supported.Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Methods:getJsonPathValue(String k8s_kind, String k8s_kind_name, String jsonPath): return String value of specific parameter of particular object using jsonPath utility. Example:context.platform.getJsonPathValue(\"cm\",\"project-settings\",
\".data.username\")
BuildTool() - contains methods for working with different buildTool from ENUM BuildToolType. (Should be invoked on Jenkins build agents)Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Nexus object - Object of class Nexus.Methods:init: return parameters of buildTool that are needed for running stages. Example:context.buildTool = new BuildToolFactory().getBuildToolImpl
(context.application.config.build_tool, this, context.nexus)
context.buildTool.init()
Table 9. Classes with the respective properties, methods, and examples. Classes Description (properties, methods, and examples) PlatformFactory() - Class that contains methods getting implementation of CLI of platform. At the moment OpenShift and Kubernetes are supported. Methods:getPlatformImpl(PlatformType platform, Script script): return Class PlatformExample: context.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)
Application(String name, Platform platform, Script script) - Class that describe the application object. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Platform platform - Object of a class Platform()String name - Name for the application for creating objectMap config - Map of configuration settings for particular application that is loaded from config map project-settingsString version - Application version, initially empty. Is set on get-version step.String deployableModule - The name of deployable module for multi module applications, initially empty.String buildVersion - Version of built artifact, contains build number of Job initially emptyString deployableModuleDir - The name of deployable module directory for multi module applications, initially empty.Array imageBuildArgs - List of arguments for building application Docker imageMethods: setConfig(String gerrit_autouser, String gerrit_host, String gerrit_sshPort, String gerrit_project): set the config property with values from config mapExample: context.application = new Application(context.job, context.gerrit.project, context.platform, this)
context.application.setConfig(context.gerrit.autouser, context.gerrit.host, context.gerrit.sshPort, context.gerrit.project)
Job(type: JobType.value, platform: Platform, script: Script) - Class that describe the Gerrit tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\"Platform platform - Object of a class Platform().JobType.value type.String deployTemplatesDirectory - The name of the directory in application repository, where deploy templates are located. Can be set for particular Job through DEPLOY_TEMPLATES_DIRECTORY parameter.String edpName - The name of the EDP Project.Map stages - Contains all stages in JSON format that is retrieved from Jenkins job env variable.String envToPromote - The name of the environment for promoting images.Boolean promoteImages - Defines whether images should be promoted or not. Methods:getParameterValue(String parameter, String defaultValue = null): return parameter of ENV variable of Jenkins job. init(): set all the properties of Job object. setDisplayName(String displayName): set display name of the Jenkins job. setDescription(String description, Boolean addDescription = false): set new or add to existing description of the Jenkins job. printDebugInfo(Map context): print context info to log of Jenkins job. runStage(String stage_name, Map context): run the particular stage according to its name. Example: context.job = new Job(JobType.DEPLOY.value, context.platform, this)
context.job.init()
context.job.printDebugInfo(context)
context.job.setDisplayName(\"test\")
context.job.setDescription(\"Name: ${context.application.config.name}\")
Gerrit(Job job, Platform platform, Script script) - Class that describe the Gerrit tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\".Platform platform - Object of a class Platform(). Job job - Object of a class Job().String credentialsId - Credential Id in Jenkins for Gerrit. String autouser - Username of autouser in Gerrit for integration with Jenkins. String host - Gerrit host. String project - project name of built application. String branch - branch to build application from. String changeNumber - change number of Gerrit commit. String changeName - change name of Gerrit commit. String refspecName - refspecName of Gerrit commit. String sshPort - gerrit ssh port number. String patchsetNumber - patchsetNumber of Gerrit commit.Methods:init(): set all the properties of Gerrit object. Example:context.gerrit = new Gerrit(context.job, context.platform, this)
context.gerrit.init()
. Nexus(Job job, Platform platform, Script script) - Class that describe the Nexus tool. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\". Platform platform - Object of a class Platform(). Job job - Object of a class Job(). String autouser - Username of autouser in Nexus for integration with Jenkins. String credentialsId - Credential Id in Jenkins for Nexus. String host - Nexus host. String port - Nexus http(s) port. String repositoriesUrl - Base URL of repositories in Nexus. String restUrl - URL of Rest API. Methods:init(): set all the properties of Nexus object. Example: context.nexus = new Nexus(context.job, context.platform, this)
context.nexus.init()
."},{"location":"user-guide/pipeline-framework/#edp-library-stages-description_1","title":"EDP Library Stages Description","text":"Using in pipelines - @Library(['edp-library-stages@version']) _
The corresponding classes with methods can be used separately from the EDP Pipelines library function (please refer to Table 10).
Table 10. Classes with the respective properties, methods, and examples.
Classes Description (properties, methods, and examples) StageFactory() - Class that contains methods getting implementation of particular stage either EDP from shared library or custom from application repository. Properties:Script script - Object with type script, in most cases if class created from Jenkins pipelines it is \"this\"Map stages - Map of stages implementationsMethods:loadEdpStages(): return list of Classes that describes EDP stages implementationsloadCustomStages(String directory): return list of Classes that describes EDP custom stages from application repository from \"directory\". The \"directory\" should be absolute path to files with classes of custom stages implementations. Should be run from Jenkins agent.add(Class clazz): register class for some particular stage in stages map of StageFactory classgetStage(String name, String buildTool, String type): return object of the class for particular stage from stages property based on stage name and buildTool, type of applicationExample:context.factory = new StageFactory(script: this)
context.factory.loadEdpStages().each() { context.factory.add(it) }
context.factory.loadCustomStages(\"${context.workDir}/stages\").each() { context.factory.add(it) }
context.factory.getStage(stageName.toLowerCase(),context.application.config.build_tool.toLowerCase(),
context.application.config.type).run(context)
."},{"location":"user-guide/pipeline-framework/#deploy-pipeline-stages","title":"Deploy Pipeline Stages","text":"Each EDP stage implementation has run method that is as input parameter required to pass a context map with different keys. Some stages can implement the logic for several build tools and application types, some of them are specific.
The stages for the deploy pipeline are independent of the build tool and application type. Find below (see Table 11 ) the full description of every stage: Deploy \u2192 Automated tests \u2192 Promote Images.
Table 11. The Deploy, Automated tests, and Promote Images stages description.
Deploy Automated tests Promote Images name = \"deploy\"buildTool = nulltype = nullcontext required:\u2022 String context.workDir\u2022 StageFactory context.factory\u2022 String context.gerrit.autouser\u2022 String context.gerrit.host\u2022 String context.application.config.cloneUrl\u2022 String context.jenkins.token\u2022 String context.job.edpName\u2022 String context.job.buildUrl\u2022 String context.job.jenkinsUrl\u2022 String context.job.metaProject\u2022 List context.job.applicationsList [['name':'application1_name','version':'application1_version],...]\u2022 String context.job.deployTemplatesDirectoryoutput:\u2022 List context.job.updatedApplicaions [['name':'application1_name','version':'application1_version],...] name = \"automation-tests\", buildTool = null, type = nullcontext required:- String context.workDir- StageFactory context.factory- String context.gerrit.credentialsId- String context.autotest.config.cloneUrl- String context.autotest.name- String context.job.stageWithoutPrefixName- String context.buildTool.settings- String context.autotest.config.report_framework name = \"promote-images\"buildTool = nulltype = nullcontext required:- String context.workDir- String context.buildTool.sln_filename- List context.job.updatedApplicaions [['name':'application1_name','version':'application1_version],...]"},{"location":"user-guide/pipeline-framework/#how-to-redefine-or-extend-edp-pipeline-stages-library_1","title":"How to Redefine or Extend EDP Pipeline Stages Library","text":"Info
Currently, the redefinition of Deploy pipeline stages is prohibited.
"},{"location":"user-guide/pipeline-framework/#using-edp-library-stages-in-the-pipeline","title":"Using EDP Library Stages in the Pipeline","text":"In order to use the EDP stages, the created pipeline should fit some requirements, that`s why a developer has to do the following:
After that, there is the ability to run any EDP stage beforehand by defining requirement context context.job.runStage(\"Deploy\", context)
.
For instance, the pipeline can look like:
@Library(['edp-library-stages', 'edp-library-pipelines']) _\n\nimport com.epam.edp.stages.StageFactory\nimport com.epam.edp.platform.PlatformFactory\nimport com.epam.edp.platform.PlatformType\nimport com.epam.edp.JobType\n\ncontext = [:]\n\nnode('master') {\n\tstage(\"Init\") {\n\t\tcontext.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)\n\t\tcontext.job = new com.epam.edp.Job(JobType.DEPLOY.value, context.platform, this)\n\t\tcontext.job.init()\n\t\tcontext.job.initDeployJob()\n\t\tprintln(\"[JENKINS][DEBUG] Created object job with type - ${context.job.type}\")\n\n\t\tcontext.nexus = new com.epam.edp.Nexus(context.job, context.platform, this)\n\t\tcontext.nexus.init()\n\n\t\tcontext.jenkins = new com.epam.edp.Jenkins(context.job, context.platform, this)\n\t\tcontext.jenkins.init()\n\n\t\tcontext.gerrit = new com.epam.edp.Gerrit(context.job, context.platform, this)\n\t\tcontext.gerrit.init()\n\n\t\tcontext.factory = new StageFactory(script: this)\n\t\tcontext.factory.loadEdpStages().each() { context.factory.add(it) }\n\n\t\tcontext.environment = new com.epam.edp.Environment(context.job.deployProject, context.platform, this)\n\t\tcontext.job.printDebugInfo(context)\n\t\tcontext.job.setDisplayName(\"${currentBuild.displayName}-${context.job.deployProject}\")\n\n\t\tcontext.job.generateInputDataForDeployJob()\n\t}\n\n\tstage(\"Pre Deploy Custom stage\") {\n\t\tprintln(\"Some custom pre deploy logic\")\n\t}\n\n\tcontext.job.runStage(\"Deploy\", context)\n\n\tstage(\"Post Deploy Custom stage\") {\n\t\tprintln(\"Some custom post deploy logic\")\n\t}\n}\n
Or in a declarative way:
@Library(['edp-library-stages', 'edp-library-pipelines']) _\n\nimport com.epam.edp.stages.StageFactory\nimport com.epam.edp.platform.PlatformFactory\nimport com.epam.edp.platform.PlatformType\nimport com.epam.edp.JobType\n\ncontext = [:]\n\npipeline {\n\tagent { label 'master'}\n\tstages {\n\t\tstage('Init') {\n\t\t\tsteps {\n\t\t\t\tscript {\n\t\t\t\t\tcontext.platform = new PlatformFactory().getPlatformImpl(PlatformType.OPENSHIFT, this)\n\t\t\t\t\tcontext.job = new com.epam.edp.Job(JobType.DEPLOY.value, context.platform, this)\n\t\t\t\t\tcontext.job.init()\n\t\t\t\t\tcontext.job.initDeployJob()\n\t\t\t\t\tprintln(\"[JENKINS][DEBUG] Created object job with type - ${context.job.type}\")\n\n\t\t\t\t\tcontext.nexus = new com.epam.edp.Nexus(context.job, context.platform, this)\n\t\t\t\t\tcontext.nexus.init()\n\n\t\t\t\t\tcontext.jenkins = new com.epam.edp.Jenkins(context.job, context.platform, this)\n\t\t\t\t\tcontext.jenkins.init()\n\n\t\t\t\t\tcontext.gerrit = new com.epam.edp.Gerrit(context.job, context.platform, this)\n\t\t\t\t\tcontext.gerrit.init()\n\n\t\t\t\t\tcontext.factory = new StageFactory(script: this)\n\t\t\t\t\tcontext.factory.loadEdpStages().each() { context.factory.add(it) }\n\n\t\t\t\t\tcontext.environment = new com.epam.edp.Environment(context.job.deployProject, context.platform, this)\n\t\t\t\t\tcontext.job.printDebugInfo(context)\n\t\t\t\t\tcontext.job.setDisplayName(\"${currentBuild.displayName}-${context.job.deployProject}\")\n\n\t\t\t\t\tcontext.job.generateInputDataForDeployJob()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tstage('Deploy') {\n\t\t\tsteps {\n\t\t\t\tscript {\n\t\t\t\t\tcontext.factory.getStage(\"deploy\").run(context)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tstage('Custom stage') {\n\t\t\tsteps {\n\t\t\t\tprintln(\"Some custom logic\")\n\t\t\t}\n\t\t}\n\t}\n}\n
"},{"location":"user-guide/pipeline-framework/#related-articles","title":"Related Articles","text":"Get acquainted with EDP CI/CD workflow and stages description.
"},{"location":"user-guide/pipeline-stages/#edp-cicd-workflow","title":"EDP CI/CD Workflow","text":"Within EDP, the pipeline framework comprises the following pipelines:
Note
Please refer to the EDP Pipeline Framework page for details.
The diagram below shows the delivery path through these pipelines and the respective stages. Please be aware that stages may differ for different codebase types.
stages
"},{"location":"user-guide/pipeline-stages/#stages-description","title":"Stages Description","text":"The table below provides the details on all the stages in the EDP pipeline framework:
Name Dependency Description Pipeline Application Library Autotest Source code Documentation init Initiates information gathering Create Release, Code Review, Build + + Build.groovy checkout Performs for all files the checkout from a selected branch of the Git repository. For the main branch - from HEAD, for code review - from the commit Create Release, Build + + Checkout.groovy sast Launches vulnerability testing via Semgrep scanner. Pushes a vulnerability report to the DefectDojo. Build + Security compile Compiles the code, includes individual groovy files for each type of app or lib (NPM, DotNet, Python, Maven, Gradle) Code Review, Build + + Compile tests Launches testing procedure, includes individual groovy files for each type of app or lib Code Review, Build + + + Tests sonar Launches testing via SonarQube scanner and includes individual groovy files for each type of app or lib Code Review, Build + + Sonar build Builds the application, includes individual groovy files for each type of app or lib (Go, Maven, Gradle, NPM) Code Review, Build + Build create-branch EDP create-release process Creates default branch in Gerrit during create and clone strategies Create Release + + + CreateBranch.groovy trigger-job EDP create-release process Triggers \"build\" job Create Release + + + TriggerJob.groovy gerrit-checkout Performs checkout to the current project branch in Gerrit Code Review + + + GerritCheckout.groovy commit-validate Optional in EDP Admin Console Takes Jira parameters, when \"Jira Integration\" is enabled for the project in the Admin Console. Code Review + + CommitValidate.groovy dockerfile-lint Launches linting tests for Dockerfile Code Review + LintDockerApplicationLibrary.groovy Use Dockerfile Linters for Code Review dockerbuild-verify \"Build\" stage (if there are no \"COPY\" layers in Dockerfile) Launches build procedure for Dockerfile without pushing an image to the repository Code Review + BuildDockerfileApplicationLibrary.groovy Use Dockerfile Linters for Code Review helm-lint Launches linting tests for deployment charts Code Review + LintHelmApplicationLibrary.groovy Use helm-lint for Code Review helm-docs Checks generated documentation for deployment charts Code Review + HelmDocsApplication.groovy Use helm-docs for Code Review helm-uninstall Helm release deletion step to clear Helm releases Deploy + HelmUninstall.groovy Helm release deletion semi-auto-deploy-input Provides auto deploy with timeout and manual deploy flow Deploy + SemiAutoDeployInput.groovy Semi Auto Deploy get-version Defines the versioning of the project depending on the versioning schema selected in Admin Console Build + + GetVersion terraform-plan AWS credentials added to Jenkins Checks Terraform version, and installs default version if necessary, and launches terraform init, returns AWS username which used for action, and terraform plan command is called with an output of results to .tfplan file Build + TerraformPlan.groovy Use Terraform library in EDP terraform-apply AWS credentials added to Jenkins, the \"Terraform-plan\" stage Checks Terraform version, and installs default version if necessary, and launches terraform init, launches terraform plan from saves before .tfplan file, asks to approve, and run terraform apply from .tfplan file Build + TerraformApply.groovy Use Terraform library in EDP build-image-from-dockerfile Platform: OpenShift Builds Dockerfile Build + + .groovy files for building Dockerfile image build-image-kaniko Platform: k8s Builds Dockerfile using the Kaniko tool Build + BuildImageKaniko.groovy push Pushes an artifact to the Nexus repository Build + + Push create-Jira-issue-metadata \"get-version\" stage Creates a temporary CR in the namespace and after that pushes Jira Integration data to Jira ticket, and delete CR Build + + JiraIssueMetadata.groovy ecr-to-docker DockerHub credentials added to Jenkins Copies the docker image from the ECR project registry to DockerHub via the Crane tool after it is built Build + EcrToDocker.groovy Promote Docker Images From ECR to Docker Hub git-tag \"Get-version\" stage Creates a tag in SCM for the current build Build + + GitTagApplicationLibrary.groovy deploy Deploys the application Deploy + Deploy.groovy manual Works with the manual approve to proceed Deploy + ManualApprove.groovy promote-images Promotes docker images to the registry Deploy + PromoteImage.groovyNote
The Create Release pipeline is an internal EDP mechanism for adding, importing or cloning a codebase. It is not a part of the pipeline framework.
"},{"location":"user-guide/pipeline-stages/#related-articles","title":"Related Articles","text":"After the necessary applications are added to EDP, they can be managed via the Admin Console. To prepare for the release, create a new branch from a selected commit with a set of CI pipelines (Code Review and Build pipelines), launch the Build pipeline, and add a new CD pipeline as well.
Note
Please refer to the Add Application and Add CD Pipeline for the details on how to add an application or a CD pipeline.
Become familiar with the following preparation steps for release and a CD pipeline structure:
Open Gerrit via the Admin Console Overview page to have this tab available in a web browser.
Being in Admin Console, open the Applications section and click an application from the list to create a new branch.
Once clicked the application name, scroll down to the Branches menu and click the Create button to open the Create New Branch dialog box, fill in the Branch Name field by typing a branch name.
Paste the copied hash to the From Commit Hash field and click Proceed.
Note
If the commit hash is not added to the From Commit Hash field, the new branch will be created from the head of the master branch.
"},{"location":"user-guide/prepare-for-release/#launch-the-build-pipeline","title":"Launch the Build Pipeline","text":"After the new branches are added, open the details page of every application and click the CI link that refers to Jenkins.
Note
The adding of a new branch may take some time. As soon as the new branch is created, it will be displayed in the list of the Branches menu.
To build a new version of a corresponding Docker container (an image stream in OpenShift terms) for the new branch, start the Build pipeline. Being in Jenkins, select the new branch tab and click the link to the Build pipeline.
Navigate to the Build with Parameters option and click the Build button to launch the Build pipeline.
Warning
The predefined default parameters should not be changed when triggering the Build pipeline, otherwise, it will lead to the pipeline failure.
Add a new CD pipeline and indicate the new release branch using the Admin console tool. Pay attention to the Applications menu, the necessary application(s) should be selected there, as well as the necessary branch(es) from the drop-down list.
Note
For the details on how to add a CD pipeline, please refer to the Add CD Pipeline page.
As soon as the Build pipelines are successfully passed in Jenkins, the Docker Registry, which is used in EDP by default, will have the new image streams (Docker container in Kubernetes terms) version that corresponds to the current branch.
Open the Kubernetes/OpenShift page of the project via the Admin Console Overview page \u2192 go to CodebaseImageStream (in OpenShift, go to Builds \u2192 Images) \u2192 check whether the image streams are created under the specific name (the combination of the application and branch names) and the specific tags are added. Click every image stream link.
When the CD pipeline is added through the Admin Console, it becomes available in the CD pipelines list. Every pipeline has the details page with the additional information. To explore the CD pipeline structure, follow the steps below:
Open Admin Console and navigate to Continuous Delivery section, click the newly created CD pipeline name.
Discover the CD pipeline components:
Note
Initially, an environment is empty and does not have any deployment unit. When deploying the subsequent stages, the artifacts of the selected versions will be deployed to the current project and the environment will display the current stage status. The project has a standard pattern: \u2039edp-name\u203a-\u2039pipeline-name\u203a-\u2039stage-name\u203a.
Follow the steps below to deploy the QA and UAT application stages:
As soon as the Build pipelines for both applications are successfully passed, the new version of the Docker container will appear, thus allowing to launch the CD pipeline. Simply navigate to Continuous Delivery and click the pipeline name to open it in Jenkins.
Click the QA stage link.
Deploy the QA stage by clicking the Build Now option.
After the initialization step starts, in case another menu is opened, the Pause for Input option will appear. Select the application version in the drop-down list and click Proceed. The pipeline passes the following stages:
After all the stages are passed, the new image streams will be created in the Kubernetes/OpenShift with the new names.
Deploy the UAT stage, which takes the versions that were verified during the QA stage, by clicking the Build Now option, and select the necessary application versions. The launch process is the same as for all the deploy pipelines.
To get the status of the pipeline deployment, open the CD pipeline details page and check the Deployed versions state.
Admin Console allows creating a CD pipeline with a part of the application set as a team environment. To do this, perform the following steps;
As a result, the team will have the same abilities to verify the code changes when developing and during the release.
"},{"location":"user-guide/prepare-for-release/#related-articles","title":"Related Articles","text":"The Semi Auto Deploy stage provides the ability to deploy applications with the custom logic that comprises the following behavior:
To enable the Semi Auto Deploy stage during the deploy process, follow the steps below:
{\"name\":\"auto-deploy-input\",\"step_name\":\"auto-deploy-input\"}
step to the {\"name\":\"semi-auto-deploy-input\",\"step_name\":\"semi-auto-deploy-input\"}
step in the CD pipeline. Alternatively, it is possible to create a custom job provisioner with this step.After the timeout starts and in case the pipeline has been interrupted not from the Input requested menu, the automatic deployment will be proceeding. To resolve the issue and stop the pipeline, click the Input requested menu -> Abort or being on the pipeline UI, click the Abort button.
"},{"location":"user-guide/semi-auto-deploy/#related-articles","title":"Related Articles","text":"EPAM Delivery Platform ensures the implemented Terraform support by adding a separate component type called Infrastructure. The Infrastructure codebase type allows to work with Terraform code that is processed by means of stages in the Code-Review and Build pipelines.
"},{"location":"user-guide/terraform-stages/#pipeline-stages-for-terraform","title":"Pipeline Stages for Terraform","text":"Under the hood, Infrastructure codebase type, namely Terraform, looks quite similar to other codebase types. The distinguishing characterstic of the Infrastructure codebase type is that there is a stage called terraform-check in both of Code Review and Build pipelines. This stage runs the pre-commit activities which in their turn run the following commands and tools:
Terraform fmt - the first step of the stage is basically the terraform fmt
command. The terraform fmt
command automatically updates the formatting of Terraform configuration files to follow the standard conventions and make the code more readable and consistent.
Lock provider versions - locks the versions of the Terraform providers used in the project. This ensures that the project uses specific versions of the providers and prevents unexpected changes from impacting the infrastructure due to newer provider versions.
Terraform validate - checks the syntax and validity of the Terraform configuration files. It scans the configuration files for all possible issues.
Terraform docs - generates human-readable documentation for the Terraform project.
Tflint - additional validation step using the tflint
linter to provide more in-depth checks in addition to what the terraform validate
command does.
Checkov - runs the checkov
command against the Terraform codebase to identify any security misconfigurations or compliance issues.
Tfsec - another security-focused validation step using the tfsec
command. Tfsec is a security scanner for Terraform templates that detects potential security issues and insecure configurations in the Terraform code.
Note
The commands and their attributes are displayed in the .pre-commit-config.yaml file.
"},{"location":"user-guide/terraform-stages/#related-articles","title":"Related Articles","text":"