diff --git a/.github/ISSUE_TEMPLATE/enhancement_proposal.md b/.github/ISSUE_TEMPLATE/enhancement_proposal.md index c0136f12a6..4e82594543 100644 --- a/.github/ISSUE_TEMPLATE/enhancement_proposal.md +++ b/.github/ISSUE_TEMPLATE/enhancement_proposal.md @@ -16,3 +16,7 @@ Please give examples of your use case, e.g. when would you use this. # Proposal How do you think this should be implemented? + +# Testing Guideline [Optional] + +How this feature will need to be tested. What all areas should be covered diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 8661304d40..5df63cfa5f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -26,5 +26,7 @@ Please describe the tests that you ran to verify your changes. Provide instructi * [ ] I have performed a self-review of my own code * [ ] I have commented my code, particularly in hard-to-understand areas * [ ] I have tested it for all user roles +* [ ] I have added all the required unit/api test cases + diff --git a/.gitignore b/.gitignore index be6e07a5b4..082d018f3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea devtron .DS_Store +/cmd/external-app/devtron-ea diff --git a/COMMUNITY_CONTRIBUTIONS.md b/COMMUNITY_CONTRIBUTIONS.md index 60ece59916..bcdf1e736c 100644 --- a/COMMUNITY_CONTRIBUTIONS.md +++ b/COMMUNITY_CONTRIBUTIONS.md @@ -19,6 +19,8 @@ * https://gochronicles.com/devtron-deploy/ - By Go-Chronicals (Part-3) * https://community.codenewbie.org/varghesejose2020/opensourcekubernetesdevtron-3fjj -By Varghese Jose +* https://www.financialexpress.com/industry/sme/devtron-a-business-opportunity-in-developers-needs/2274094/ - By Srinath Srinivasan + ## Videos diff --git a/README.md b/README.md index b995f537a0..f3d20e8b11 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,22 @@

-

Web based CI/CD Platform for Kubernetes

+

No-Code CI/CD Orchestrator for Kubernetes

-

A Web based CI/CD platform leveraging open source tools to provide a No-Code SaaS-like experience for Kubernetes. +

A web based CI/CD Orchestrator leveraging Open Source tools to provide a No-Code, SaaS-like experience for Kubernetes
Explore documentation »
Website · -Blog +Blogs · -Join Discord +Join Discord channel · Twitter . YouTube -

Join Discord @@ -28,356 +27,282 @@ Website devtron.ai Tweet - - -

-🔥 Want to accelerate K8s adoption? Our core team would love to help 30 companies do it the Devtron way! 🔥 Apply Now 👋

- -## :book: Menu - -- [Devtron?](https://github.com/devtron-labs/devtron#bulb-devtron) -- [Devtron](https://github.com/devtron-labs/devtron#computer-devtron) -- [Hyperion](https://github.com/devtron-labs/devtron#-hyperion) -- [Documentation](https://docs.devtron.ai/) -- [Compatibility Notes](https://github.com/devtron-labs/devtron#memo-compatibility-notes) -- [Community](https://github.com/devtron-labs/devtron#busts_in_silhouette-community) -- [Trusted By](https://github.com/devtron-labs/devtron#muscle-Trusted-By) -- [FAQ & Troubleshooting](https://github.com/devtron-labs/devtron#question-faq--troubleshooting) -- [Contribute](https://github.com/devtron-labs/devtron#handshake-contribute) - -## :bulb: Devtron? - -### Why use it? - -Devtron is a Web-Based CI/CD Platform for Kubernetes. It integrates various OpenSource tools to provide a modular CI/CD platform that also includes Security Scanning, GitOps, Access Control, and Debugging/Observability. +🔥 Want to accelerate K8s adoption? Our team would love to help 100 companies do it the Devtron way! 🔥 +
+
+ Apply Now 👋 +
+

+

+Devtron is a web based CI/CD orchestrator for Kubernetes. It integrates various Open Source tools to provide AppOps, that also includes Security Scanning, GitOps, Access Control, Debugging and Observability. +

- Devtron is built in a modular approach. These modules can be installed independently: -- [Devtron](https://github.com/devtron-labs/devtron#tada-Full-Devtron-Experience) - This option gives you all the features of Devtron as a Full Experience providing you with CI, CD, security, cost, observability, stabilization. All the modules stated below are included here. -- [Hyperion](https://github.com/devtron-labs/devtron#tada-featuresfor-hyperion) - Devtron's Web-based module to manage helm apps that can be installed seperately. Install Hyperion -> manage, Observe helm apps of all your clusters. This module is also a great way to manage existing helm apps and gradually understand how Devtron fits into your workflow. You can always switch to Devtron for all the features. +

Devtron is built in a modular fashion. It consists of the below modules which can be installed independently.

-## :computer: Devtron -Devtron provides a full feldged web based CI/CD platform including features like Security Scanning, GitOps, Access Control, and Debugging/Observability. Modules like Hyperion are included as additional modules here. +| Module | Features | +| :-----------: | :-----------: | +| [Hyperion](https://github.com/devtron-labs/devtron#-hyperion) | Deploy, Observe, Manage & Debug existing Helm apps in all your clusters | +| [Devtron](https://github.com/devtron-labs/devtron#bulb-devtron) | Perform CI/CD, Security Scanning, GitOps, Access Control, Debugging and Observability. Comes with Hyperion included. | + -## :tada: Features -
- -
+ -
- - No code self-serve DevOps platform - -
+# 🦹 Hyperion -- Workflow which understands the domain of Kubernetes, testing, CD, SecOps -- Reusable and composable pipelines so that workflows are easy to construct and visualize +Hyperion is Devtron's light weight module to manage Helm apps. It helps you deploy, observe, manage and debug applications deployed through Helm across multiple clusters, minimizing Kubernetes complexities. + +## :tada: Features -
+https://user-images.githubusercontent.com/66381465/159458292-a4d8e212-54b6-444f-bd6d-69645fddf966.mp4 -
- Multi-cloud/Multi-cluster deployment + +
Application-level Resource grouping for easier Debugging
-- Devtron gives the ability to deploy your applications to multiple clusters/cloud just with the same dashboard. +- Hyperion groups your Kubernetes objects deployed via Helm charts and display them in a slick UI, for easier monitoring or debugging. Access pod logs and resource manifests right from the Hyperion UI and even edit them!
- - -
- Built-in SecOps tools and integration + +
Centralized Access Management
-- UI driven hierarchical security policy (global, cluster, environment, and application) for efficient policy management -- Integration with [Clair](https://www.redhat.com/en/topics/containers/what-is-clair) for vulnerability scanning - -
-
- UI-enabled Application debugging dashboard -
+- Control and give customizable view-only, edit access to users on Project, Environment and Application levels - - Application-centric view for K8s components - - Built-in monitoring for CPU, RAM, http status code, and latency - - Advanced logging, with grep and json search - - Access all manifests securely for e.g. secret obfuscation - - Auto issue identification -
- -
- Enterprise grade security and compliances + +
Deploy, Manage and Observe on multiple clusters
- -- Easy to control roles and permissions for users. -- Club the users of similar roles by giving the required permissions through the User Interface. + +- Deploy and manage Helm charts, applications across multiple Kubernetes clusters (hosted on multiple clouds / on-prem) right from a single Hyperion setup
- -
- Automated GitOps based deployment using argocd + +
View and edit Kubernetes manifests
-- Automated git repository and application manifest management -- Reduces complexity(configuration, access control) in adopting GitOps practices -- GitOps backed by Postgres for easier analysis + - View and edit all the Kubernetes resources right from the Hyperion dashboard
-### :blue_heart: We Support: -In addition to the features, we love supporting platforms that devs find easy to work with. -
-

- - -## :globe_with_meridians: Architecture: -
-

- - - +Hyperion is a great way to get familiar with Devtron's UI and some of its light weight features. You can always [upgrade to Devtron full stack](https://docs.devtron.ai/hyperion/upgrade-to-devtron), that comes loaded with all the features. + ## :rocket: Getting Started -#### You can follow our detailed installation guide, using Devtron and other key functionalities, in our -[Devtron Documentation](https://docs.devtron.ai/) - -### Quick installation with default settings +### Install Hyperion using Helm3 -This installation will use Minio for storing build logs and cache. +To install Helm3, check [here](https://helm.sh/docs/intro/install/) ```bash helm repo add devtron https://helm.devtron.ai -helm install devtron devtron/devtron-operator --create-namespace --namespace devtroncd +helm install devtron devtron/devtron-operator --create-namespace --namespace devtroncd --set installer.mode=hyperion ``` -#### For detailed installation instructions and other options, check out: -[devtron installation documentation](https://docs.devtron.ai/setup/install) +For those countries/users where Github is blocked, you can download [Hyperion Helm chart](https://s3-ap-southeast-1.amazonaws.com/devtron.ai/devtron-operator-latest.tgz) +```bash +wget https://s3-ap-southeast-1.amazonaws.com/devtron.ai/devtron-operator-latest.tgz +helm install devtron devtron-operator-latest.tgz --create-namespace --namespace devtroncd --set installer.mode=hyperion +``` -### :key: Access Devtron dashboard +### Hyperion Dashboard -By default, Devtron creates a loadbalancer. Use the following command to get the dashboard url: +If you did not provide a **BASE\_URL** during install or have used the default installation, Devtron creates a load balancer for you. Use the following command to get the dashboard URL. ```text kubectl get svc -n devtroncd devtron-service -o jsonpath='{.status.loadBalancer.ingress}' ``` -*****Devtron Admin credentials***** +Please note that it may take some time for the Cloud provider to provision the load balancer and in case of on-prem installation of Kubernetes, please use port-forward or ingress. +You will get an output, something like this -For admin login, use the username:`admin`. And for the password, run the following command: +```text +[test2@server ~]$ kubectl get svc -n devtroncd devtron-service -o jsonpath='{.status.loadBalancer.ingress}' +[map[hostname:devtronsdashboardurlhere]] +``` + +The hostname mentioned here \( devtronsdashboardurlhere \) is the load balancer URL from where you can access the dashboard + +*****Hyperion admin credentials***** + +For admin login, use +
+Username:`admin` +
+and for password run the following command ```bash kubectl -n devtroncd get secret devtron-secret -o jsonpath='{.data.ACD_PASSWORD}' | base64 -d ``` -## :memo: Compatibility notes -### Current build: +# :bulb: Devtron -- Devtron uses modified version of [argo rollout](https://argoproj.github.io/argo-rollouts/) -- Application metrics only works for k8s 1.16+ +Devtron is a No-Code CI/CD Orchestrator with a complete experience - providing you with CI/CD, Security Scanning, GitOps, Access Control, Debugging and Observability from a single web-console. Hyperion module is included by default, in Devtron. - -## 🦹 Hyperion - -
- Hyperion is one of Devtron's Web-based modules to manage helm apps that can be installed seperately too. It helps you observe, manage and debug the applications deployed through Helm across multiple clusters minimizing Kubernetes Complexities. Please expand this column to find Hyperion's features and to get Started with it: +## :tada: Features +
+
- -## :tada: Features(For Hyperion) +
+ + No Code self-serve DevOps platform + -
Application-level resource grouping for easier Debugging -
+ - Understands the domain of Kubernetes, Testing, CI/CD and SecOps + - Reusable and composable Pipelines, which makes Workflows easy to construct and visualize +
-- Hyperion groups your deployed Helm charts and display them in a slick UI for easier monitoring or debugging. Access pod logs and resource manifests right from the Hyperion UI and even edit them! +
+ Multi-Cloud / Multi-Cluster Deployment +- Gives the ability to deploy your applications to multiple clusters / cloud, with unified dashboard
- -
Centralized Access Management -
- -- Control and give customizable view-only, edit access to users on Project, Environment and App level. - -
- -
Manage and observe Multiple Clusters -
- -- Manage Helm charts, Applications across multiple Kubernetes clusters (hosted on multiple cloud/on-prem) right from a single Hyperion setup. +
+ Built-in SecOps tools and Integration + +- UI driven hierarchical security policy (Global, Cluster, Environment and Application) management +- Integration with [Clair](https://www.redhat.com/en/topics/containers/what-is-clair) for vulnerability scanning
- -
View and Edit Kubernetes Manifests -
- - - View and Edit all Kubernetes resources right from the Hyperion dashboard. +
+UI enabled Application Debugging Dashboard + + - Application-centric view for K8s components + - Built-in monitoring for CPU, RAM, HTTP Status Code and Latency + - Advanced Logging, with grep and json search + - Access all the manifests securely, for e.g. secret obfuscation + - Auto Issue identification
-#### Side Note: +
+ Enterprise grade Security and Compliance -Hyperion module is also a great way to get to know Devtron's UI and some of its features. You can always switch from Hyperion to Devtron which includes all the features. [Just a Couple of Commands away.](https://github.com/devtron-labs/devtron#rocket-getting-started) - -## :rocket: Getting Started(For Hyperion) +- Easily manage Roles and Permissions for users through UI +
-### Install Hyperion using Helm3 +
+Automated GitOps based deployment using ArgoCD -To install Helm3, please check [Installing Helm3](https://helm.sh/docs/intro/install/) +- Automated Git repository and application manifest management +- Reduces complexity (configuration & access control) in adopting GitOps practices +- GitOps backed by Postgres for easier analysis +
-```bash -helm repo add devtron https://helm.devtron.ai -helm install devtron devtron/devtron-operator --create-namespace --namespace devtroncd --set installer.mode=hyperion -``` +## :globe_with_meridians: Architecture: +
+

+ +## :rocket: Getting Started -For those countries/users where Github is blocked , you can download the [Hyperion Helm chart](https://s3-ap-southeast-1.amazonaws.com/devtron.ai/devtron-operator-latest.tgz) +### Quick installation with default settings +This installation will use Minio for storing build logs and cache ```bash -wget https://s3-ap-southeast-1.amazonaws.com/devtron.ai/devtron-operator-latest.tgz -helm install devtron devtron-operator-latest.tgz --create-namespace --namespace devtroncd --set installer.mode=hyperion +helm repo add devtron https://helm.devtron.ai +helm install devtron devtron/devtron-operator --create-namespace --namespace devtroncd ``` +For detailed setup instructions and other options, check out [Devtron setup](https://docs.devtron.ai/setup/install) -### Access Hyperion dashboard +### :key: Devtron Dashboard -If you did not provide a **BASE\_URL** during install or have used the default installation, Devtron creates a loadbalancer for you on its own. Use the following command to get the dashboard url. +By default, Devtron creates a load balancer. Use the following command to get the dashboard URL. ```text kubectl get svc -n devtroncd devtron-service -o jsonpath='{.status.loadBalancer.ingress}' ``` -You will get result something like below - -```text -[test2@server ~]$ kubectl get svc -n devtroncd devtron-service -o jsonpath='{.status.loadBalancer.ingress}' -[map[hostname:devtronsdashboardurlhere]] -``` +Please note that it may take some time for the Cloud provider to provision the load balancer and in case of on-prem installation of Kubernetes, please use port-forward or ingress. -The hostname mentioned here \( devtronsdashboardurlhere \) is the Loadbalancer URL where you can access the Devtron dashboard. - -### Hyperion Admin credentials +*****Devtron admin credentials***** -For admin login use username:`admin` and for password run the following command. +For admin login, use +
+Username:`admin` +
+And for the password, run the following command ```bash kubectl -n devtroncd get secret devtron-secret -o jsonpath='{.data.ACD_PASSWORD}' | base64 -d ``` -#### If you want to perform CI/CD, App creation present in Devtron you are always few commands away: - -[Getting Started for Devtron](https://github.com/devtron-labs/devtron#rocket-getting-started) - -
+# :blue_heart: Technology +Devtron is built on some of the most trusted and loved technologies +
+

-## :video_camera: Videos: +# :video_camera: Videos - [Devtron - A Comprehensive Overview](https://youtu.be/FB5BI3Ef7uw?t=363) -- [Viktor Farcic(YouTuber) Review](https://youtu.be/ZKcfZC-zSMM) +- [Viktor Farcic's review](https://youtu.be/ZKcfZC-zSMM) - [Running an application on Devtron](https://youtu.be/bA6zgjPD_yA?t=2927) - [Devtron Demo](https://youtu.be/ekxHV2Gje-E?t=7856) +# :muscle: Trusted By -## :busts_in_silhouette: Community - -Get updates on Devtron's development and chat with the project maintainers, contributors, and community members. -- Follow [@DevtronL on Twitter](https://twitter.com/DevtronL) -- Raise feature requests, suggest enhancements, report bugs in our [GitHub issues](https://github.com/devtron-labs/devtron/issues) -- Read the [Devtron blog](https://devtron.ai/blog/) - -### Join Our Discord Community -

- - Join Devtron : Heroku for Kubernetes - -

- -## :muscle: Trusted By - -
- Devtron has been trusted by the Enterprises and community all across the globe: +Devtron is trusted by Enterprises and Community, all across the globe:
-- [Delhivery:](https://www.delhivery.com/) Delhivery Limited is one the largest and most profitable logistics company in India -- [BharatPe:](https://bharatpe.com/) Bharatpe is a business utility app to accept payments transactions in settlements. -- [Livspace:](https://www.livspace.com/in) Livspace is one-stop shop for all things home interiors and renovation services. -- [Moglix:](https://www.moglix.com/) It is an Asia-based B2B commerce company intensively inclined towards B2B procurement of industrial supplies -- [Xoxoday:](https://www.xoxoday.com/) Xoxoday helps to send rewards, perks & incentives to employees, customers and partners.
+- [Delhivery:](https://www.delhivery.com/) Delhivery is an Indian delivery and e-commerce logistics company, that provides end-to-end Supply Chain solutions through cutting-edge technology +- [BharatPe:](https://bharatpe.com/) Bharatpe is a Indian fintech company that offers a range of products including interoperable QR code for UPI payments, POS machines for card acceptance, and small business financing +- [Livspace:](https://www.livspace.com/in) Livspace is a home interior and renovation company, that provides interior design and renovation services in Singapore and India +- [Moglix:](https://www.moglix.com/) Moglix is an industrial B2B marketplace and an e-commerce platform for industrial tools and equipment, used largely by businesses in India +- [Xoxoday:](https://www.xoxoday.com/) Xoxoday provides technology infrastructure to enable businesses to automate rewards, incentives & payouts for employees, customers & channel partners -
+# :question: FAQ & Troubleshooting +- Hyperion - [see here](https://docs.devtron.ai/hyperion/faqs-and-troubleshooting/hyperion-troubleshoot) +- Devtron - [see here](https://docs.devtron.ai/devtron/faqs-and-troubleshooting/devtron-troubleshoot) +# :memo: Compatibility -## :question: FAQ & Troubleshooting: -### FAQ: +## Current build -
- 1.How to resolve unauthorized error/s, while trying to save global configurations like hostname, GitOps etc. after successful devtron installation -
-A. This occurs most of the time because any one or multiple jobs get failed during installation. To resolve this, you'll need to first check which jobs have failed. Follow these steps: +- Devtron uses modified version of [Argo Rollout](https://argoproj.github.io/argo-rollouts/) +- Application metrics only works for k8s version 1.16+ -- Run the following command and check which are the jobs with 0/1 completions: -```bash -kubectl get jobs -n devtroncd -``` -- Note the names of the jobs with 0/1 completions and check if their pods are in running state or not by running the command: -kubectl get pods -n devtroncd -- If they are in running condition, please wait for the jobs to be completed. This may be due to internet issue. If the job is not in running condition, delete those incomplete jobs using: -kubectl delete jobs -n devtroncd..[Read More](https://github.com/devtron-labs/devtron/blob/main/Troubleshooting.md#1-how-to-resolve-unauthorized-error-while-trying-to-save-global-configurations-like-hostname-gitops-etc-after-successful-devtron-installation) -

-
- -
- 2.What to do if devtron dashboard is not accessible on browser, even after successful completion of all jobs and all pods are in running mode? -
+# Support, Contribution and Community -A. Check if nats-cluster is created or not, you can check it using the following command: -```bash -kubectl get natscluster -n devtroncd -``` -- You should see a natscluster with the name devtron-nats. If not, run the following command: -```bash -kubectl apply -f https://raw.githubusercontent.com/devtron-labs/devtron/main/manifests/yamls/nats-server.yaml -n devtroncd -``` -- Wait util all nats pods are created, and the pods are in running condition. Once complete, delete devtron and dashboard pods. Then you should be able to access the devtron dashboard without any issues. -- If your problem is still not resolved, you can post your query in our [discord](https://discord.gg/jsRG5qx2gp) channel -

-
+## :busts_in_silhouette: Community -
- 3.Not able to see deployment metrics on production environment or Not able to enable application-metrics or Not able to deploy the app after creating a configmap or secret with data-volume option enabled -
-A. Update the rollout crds to latest version, run the following command -```bash -kubectl apply -f https://raw.githubusercontent.com/devtron-labs/devtron/main/manifests/yamls/rollout.yaml -n devtroncd -``` -
+Get updates on Devtron's development and chat with project maintainers, contributors and community members -### Troubleshooting: -- For Installation Troubleshooting, check this [documentation](https://docs.devtron.ai/setup/install) -- For other troubleshooting, Check the [Common troubleshooting documentation](https://docs.devtron.ai/user-guide/command-bar) - +- Follow [@DevtronL on Twitter](https://twitter.com/DevtronL) +- Raise feature requests, suggest enhancements, report bugs in our [GitHub Issues](https://github.com/devtron-labs/devtron/issues) +- Articles, Howtos, Tutorials - [Devtron Blogs](https://devtron.ai/blog/) +### Join us at Discord channel +

+ + Join Devtron : Heroku for Kubernetes + +

+ ## :handshake: Contribute -Check out our [contributing guidelines](CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on our development processes. We deeply appreciate your contributions. +Check out our [contributing guidelines](CONTRIBUTING.md). Included, are directions for opening issues, coding standards and notes on our development processes. We deeply appreciate your contribution. -Also please checkout our [community contributions](COMMUNITY_CONTRIBUTIONS.md) and feel free to create a video or blog around Devtron and add your valuable contribution in the list. +Please look at our [community contributions](COMMUNITY_CONTRIBUTIONS.md) and feel free to create a video or blog around Devtron and add your valuable contribution in the list. -### Our Contributors: +### Contributors: -We are deeply grateful for all our amazing contributors! +We are deeply grateful to all our amazing contributors! @@ -385,7 +310,8 @@ We are deeply grateful for all our amazing contributors! ## :bug: Vulnerability Reporting -We at Devtron take security and our users' trust very seriously. If you believe you have found a security issue in Devtron, please responsibly disclose this to us at security@devtron.ai. +We at Devtron, take security and our users' trust very seriously. If you believe you have found a security issue, please report to security@devtron.ai. + +# :bookmark: License -## :bookmark: License -Devtron is available under the [Apache License, Version 2.0](LICENSE) +Devtron is licensed under [Apache License, Version 2.0](LICENSE) diff --git a/Wire.go b/Wire.go index dafcafad16..8a694396cd 100644 --- a/Wire.go +++ b/Wire.go @@ -28,6 +28,8 @@ import ( chartRepo "github.com/devtron-labs/devtron/api/chartRepo" "github.com/devtron-labs/devtron/api/cluster" "github.com/devtron-labs/devtron/api/connector" + "github.com/devtron-labs/devtron/api/dashboardEvent" + "github.com/devtron-labs/devtron/api/deployment" client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/restHandler" pipeline2 "github.com/devtron-labs/devtron/api/restHandler/app" @@ -63,11 +65,11 @@ import ( "github.com/devtron-labs/devtron/pkg/app" "github.com/devtron-labs/devtron/pkg/appClone" "github.com/devtron-labs/devtron/pkg/appClone/batch" - appStore "github.com/devtron-labs/devtron/pkg/appStore" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" + repository4 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" appStoreDeploymentGitopsTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool/gitops" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" "github.com/devtron-labs/devtron/pkg/appWorkflow" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/commonService" @@ -80,6 +82,8 @@ import ( jira2 "github.com/devtron-labs/devtron/pkg/jira" "github.com/devtron-labs/devtron/pkg/notifier" "github.com/devtron-labs/devtron/pkg/pipeline" + history3 "github.com/devtron-labs/devtron/pkg/pipeline/history" + repository3 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" "github.com/devtron-labs/devtron/pkg/projectManagementService/jira" "github.com/devtron-labs/devtron/pkg/security" "github.com/devtron-labs/devtron/pkg/sql" @@ -161,6 +165,18 @@ func InitializeApp() (*App, error) { wire.Bind(new(chartConfig.PipelineOverrideRepository), new(*chartConfig.PipelineOverrideRepositoryImpl)), util.MergeUtil{}, util.NewSugardLogger, + + deployment.NewDeploymentConfigRestHandlerImpl, + wire.Bind(new(deployment.DeploymentConfigRestHandler), new(*deployment.DeploymentConfigRestHandlerImpl)), + deployment.NewDeploymentRouterImpl, + wire.Bind(new(deployment.DeploymentConfigRouter), new(*deployment.DeploymentConfigRouterImpl)), + + dashboardEvent.NewDashboardTelemetryRestHandlerImpl, + wire.Bind(new(dashboardEvent.DashboardTelemetryRestHandler), new(*dashboardEvent.DashboardTelemetryRestHandlerImpl)), + dashboardEvent.NewDashboardTelemetryRouterImpl, + wire.Bind(new(dashboardEvent.DashboardTelemetryRouter), + new(*dashboardEvent.DashboardTelemetryRouterImpl)), + router.NewMuxRouter, app2.NewAppRepositoryImpl, @@ -298,6 +314,7 @@ func InitializeApp() (*App, error) { pipeline.GetEcrConfig, NewApp, //session.NewK8sClient, + util.NewK8sUtil, argocdServer.NewVersionServiceImpl, wire.Bind(new(argocdServer.VersionService), new(*argocdServer.VersionServiceImpl)), @@ -413,8 +430,8 @@ func InitializeApp() (*App, error) { appStoreRestHandler.NewInstalledAppRestHandlerImpl, wire.Bind(new(appStoreRestHandler.InstalledAppRestHandler), new(*appStoreRestHandler.InstalledAppRestHandlerImpl)), - appStore.NewInstalledAppServiceImpl, - wire.Bind(new(appStore.InstalledAppService), new(*appStore.InstalledAppServiceImpl)), + service.NewInstalledAppServiceImpl, + wire.Bind(new(service.InstalledAppService), new(*service.InstalledAppServiceImpl)), appStoreRestHandler.NewAppStoreRouterImpl, wire.Bind(new(appStoreRestHandler.AppStoreRouter), new(*appStoreRestHandler.AppStoreRouterImpl)), @@ -481,7 +498,6 @@ func InitializeApp() (*App, error) { pubsub2.NewNatsPublishClientImpl, wire.Bind(new(pubsub2.NatsPublishClient), new(*pubsub2.NatsPublishClientImpl)), - //Batch actions batch.NewWorkflowActionImpl, wire.Bind(new(batch.WorkflowAction), new(*batch.WorkflowActionImpl)), @@ -498,18 +514,18 @@ func InitializeApp() (*App, error) { router.NewBatchOperationRouterImpl, wire.Bind(new(router.BatchOperationRouter), new(*router.BatchOperationRouterImpl)), - appStoreRepository.NewChartGroupReposotoryImpl, - wire.Bind(new(appStoreRepository.ChartGroupReposotory), new(*appStoreRepository.ChartGroupReposotoryImpl)), - appStoreRepository.NewChartGroupEntriesRepositoryImpl, - wire.Bind(new(appStoreRepository.ChartGroupEntriesRepository), new(*appStoreRepository.ChartGroupEntriesRepositoryImpl)), - appStore.NewChartGroupServiceImpl, - wire.Bind(new(appStore.ChartGroupService), new(*appStore.ChartGroupServiceImpl)), + repository4.NewChartGroupReposotoryImpl, + wire.Bind(new(repository4.ChartGroupReposotory), new(*repository4.ChartGroupReposotoryImpl)), + repository4.NewChartGroupEntriesRepositoryImpl, + wire.Bind(new(repository4.ChartGroupEntriesRepository), new(*repository4.ChartGroupEntriesRepositoryImpl)), + service.NewChartGroupServiceImpl, + wire.Bind(new(service.ChartGroupService), new(*service.ChartGroupServiceImpl)), restHandler.NewChartGroupRestHandlerImpl, wire.Bind(new(restHandler.ChartGroupRestHandler), new(*restHandler.ChartGroupRestHandlerImpl)), router.NewChartGroupRouterImpl, wire.Bind(new(router.ChartGroupRouter), new(*router.ChartGroupRouterImpl)), - appStoreRepository.NewChartGroupDeploymentRepositoryImpl, - wire.Bind(new(appStoreRepository.ChartGroupDeploymentRepository), new(*appStoreRepository.ChartGroupDeploymentRepositoryImpl)), + repository4.NewChartGroupDeploymentRepositoryImpl, + wire.Bind(new(repository4.ChartGroupDeploymentRepository), new(*repository4.ChartGroupDeploymentRepositoryImpl)), commonService.NewCommonServiceImpl, wire.Bind(new(commonService.CommonService), new(*commonService.CommonServiceImpl)), @@ -581,8 +597,8 @@ func InitializeApp() (*App, error) { wire.Bind(new(restHandler.TelemetryRestHandler), new(*restHandler.TelemetryRestHandlerImpl)), telemetry.NewPosthogClient, - telemetry.NewTelemetryEventClientImpl, - wire.Bind(new(telemetry.TelemetryEventClient), new(*telemetry.TelemetryEventClientImpl)), + telemetry.NewTelemetryEventClientImplExtended, + wire.Bind(new(telemetry.TelemetryEventClient), new(*telemetry.TelemetryEventClientImplExtended)), router.NewBulkUpdateRouterImpl, wire.Bind(new(router.BulkUpdateRouter), new(*router.BulkUpdateRouterImpl)), @@ -625,18 +641,46 @@ func InitializeApp() (*App, error) { wire.Bind(new(app.AppLabelService), new(*app.AppLabelServiceImpl)), pipelineConfig.NewAppLabelRepositoryImpl, wire.Bind(new(pipelineConfig.AppLabelRepository), new(*pipelineConfig.AppLabelRepositoryImpl)), - util2.NewGoJsonSchemaCustomFormatChecker, delete2.NewDeleteServiceExtendedImpl, wire.Bind(new(delete2.DeleteService), new(*delete2.DeleteServiceExtendedImpl)), delete2.NewDeleteServiceFullModeImpl, wire.Bind(new(delete2.DeleteServiceFullMode), new(*delete2.DeleteServiceFullModeImpl)), - appStoreDeploymentFullMode.NewAppStoreDeploymentFullModeServiceImpl, wire.Bind(new(appStoreDeploymentFullMode.AppStoreDeploymentFullModeService), new(*appStoreDeploymentFullMode.AppStoreDeploymentFullModeServiceImpl)), appStoreDeploymentGitopsTool.NewAppStoreDeploymentArgoCdServiceImpl, wire.Bind(new(appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdService), new(*appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdServiceImpl)), + // util2.NewGoJsonSchemaCustomFormatChecker, + + //history starts + restHandler.NewPipelineHistoryRestHandlerImpl, + wire.Bind(new(restHandler.PipelineHistoryRestHandler), new(*restHandler.PipelineHistoryRestHandlerImpl)), + + repository3.NewConfigMapHistoryRepositoryImpl, + wire.Bind(new(repository3.ConfigMapHistoryRepository), new(*repository3.ConfigMapHistoryRepositoryImpl)), + repository3.NewDeploymentTemplateHistoryRepositoryImpl, + wire.Bind(new(repository3.DeploymentTemplateHistoryRepository), new(*repository3.DeploymentTemplateHistoryRepositoryImpl)), + repository3.NewPrePostCiScriptHistoryRepositoryImpl, + wire.Bind(new(repository3.PrePostCiScriptHistoryRepository), new(*repository3.PrePostCiScriptHistoryRepositoryImpl)), + repository3.NewPrePostCdScriptHistoryRepositoryImpl, + wire.Bind(new(repository3.PrePostCdScriptHistoryRepository), new(*repository3.PrePostCdScriptHistoryRepositoryImpl)), + repository3.NewPipelineStrategyHistoryRepositoryImpl, + wire.Bind(new(repository3.PipelineStrategyHistoryRepository), new(*repository3.PipelineStrategyHistoryRepositoryImpl)), + + history3.NewPrePostCdScriptHistoryServiceImpl, + wire.Bind(new(history3.PrePostCdScriptHistoryService), new(*history3.PrePostCdScriptHistoryServiceImpl)), + history3.NewPrePostCiScriptHistoryServiceImpl, + wire.Bind(new(history3.PrePostCiScriptHistoryService), new(*history3.PrePostCiScriptHistoryServiceImpl)), + history3.NewDeploymentTemplateHistoryServiceImpl, + wire.Bind(new(history3.DeploymentTemplateHistoryService), new(*history3.DeploymentTemplateHistoryServiceImpl)), + history3.NewConfigMapHistoryServiceImpl, + wire.Bind(new(history3.ConfigMapHistoryService), new(*history3.ConfigMapHistoryServiceImpl)), + history3.NewPipelineStrategyHistoryServiceImpl, + wire.Bind(new(history3.PipelineStrategyHistoryService), new(*history3.PipelineStrategyHistoryServiceImpl)), + + //history ends + // AuthWireSet, ) return &App{}, nil } diff --git a/api/appStore/AppStoreRouter.go b/api/appStore/AppStoreRouter.go index 45c36e917f..cfe055e93e 100644 --- a/api/appStore/AppStoreRouter.go +++ b/api/appStore/AppStoreRouter.go @@ -39,48 +39,42 @@ func NewAppStoreRouterImpl(restHandler InstalledAppRestHandler, appStoreValuesRouter appStoreValues.AppStoreValuesRouter, appStoreDiscoverRouter appStoreDiscover.AppStoreDiscoverRouter, appStoreDeploymentRouter appStoreDeployment.AppStoreDeploymentRouter) *AppStoreRouterImpl { return &AppStoreRouterImpl{ - deployRestHandler: restHandler, - appStoreValuesRouter: appStoreValuesRouter, - appStoreDiscoverRouter: appStoreDiscoverRouter, + deployRestHandler: restHandler, + appStoreValuesRouter: appStoreValuesRouter, + appStoreDiscoverRouter: appStoreDiscoverRouter, appStoreDeploymentRouter: appStoreDeploymentRouter, } } func (router AppStoreRouterImpl) Init(configRouter *mux.Router) { - - configRouter.Path("/application/update"). - HandlerFunc(router.deployRestHandler.UpdateInstalledApp).Methods("PUT") - // deployment router starts appStoreDeploymentSubRouter := configRouter.PathPrefix("/deployment").Subrouter() router.appStoreDeploymentRouter.Init(appStoreDeploymentSubRouter) // deployment router ends - configRouter.Path("/application/exists"). - HandlerFunc(router.deployRestHandler.CheckAppExists).Methods("POST") - configRouter.Path("/group/install"). - HandlerFunc(router.deployRestHandler.DeployBulk).Methods("POST") + // values router starts + appStoreValuesSubRouter := configRouter.PathPrefix("/values").Subrouter() + router.appStoreValuesRouter.Init(appStoreValuesSubRouter) + // values router ends // discover router starts appStoreDiscoverSubRouter := configRouter.PathPrefix("/discover").Subrouter() router.appStoreDiscoverRouter.Init(appStoreDiscoverSubRouter) // discover router ends + configRouter.Path("/application/update"). + HandlerFunc(router.deployRestHandler.UpdateInstalledApp).Methods("PUT") + configRouter.Path("/application/exists"). + HandlerFunc(router.deployRestHandler.CheckAppExists).Methods("POST") + configRouter.Path("/group/install"). + HandlerFunc(router.deployRestHandler.DeployBulk).Methods("POST") configRouter.Path("/installed-app/detail").Queries("installed-app-id", "{installed-app-id}").Queries("env-id", "{env-id}"). HandlerFunc(router.deployRestHandler.FetchAppDetailsForInstalledApp). Methods("GET") - configRouter.Path("/installed-app"). HandlerFunc(router.deployRestHandler.GetAllInstalledApp).Methods("GET") - configRouter.Path("/application/version/{installedAppVersionId}"). HandlerFunc(router.deployRestHandler.GetInstalledAppVersion).Methods("GET") - - // values router starts - appStoreValuesSubRouter := configRouter.PathPrefix("/values").Subrouter() - router.appStoreValuesRouter.Init(appStoreValuesSubRouter) - // values router ends - configRouter.Path("/cluster-component/install/{clusterId}"). HandlerFunc(router.deployRestHandler.DefaultComponentInstallation).Methods("POST") } diff --git a/api/appStore/AppStoreDeploymentRestHandler.go b/api/appStore/InstalledAppRestHandler.go similarity index 97% rename from api/appStore/AppStoreDeploymentRestHandler.go rename to api/appStore/InstalledAppRestHandler.go index a8a206d970..6059ce39bb 100644 --- a/api/appStore/AppStoreDeploymentRestHandler.go +++ b/api/appStore/InstalledAppRestHandler.go @@ -28,9 +28,8 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/constants" "github.com/devtron-labs/devtron/internal/util" - "github.com/devtron-labs/devtron/pkg/appStore" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDeployment "github.com/devtron-labs/devtron/pkg/appStore/deployment" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/cluster" "github.com/devtron-labs/devtron/pkg/user" "github.com/devtron-labs/devtron/pkg/user/casbin" @@ -60,17 +59,17 @@ type InstalledAppRestHandlerImpl struct { userAuthService user.UserService enforcer casbin.Enforcer enforcerUtil rbac.EnforcerUtil - installedAppService appStore.InstalledAppService + installedAppService service.InstalledAppService validator *validator.Validate clusterService cluster.ClusterService acdServiceClient application.ServiceClient - appStoreDeploymentService appStoreDeployment.AppStoreDeploymentService + appStoreDeploymentService service.AppStoreDeploymentService } func NewInstalledAppRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, - enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, installedAppService appStore.InstalledAppService, + enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, installedAppService service.InstalledAppService, validator *validator.Validate, clusterService cluster.ClusterService, acdServiceClient application.ServiceClient, - appStoreDeploymentService appStoreDeployment.AppStoreDeploymentService, + appStoreDeploymentService service.AppStoreDeploymentService, ) *InstalledAppRestHandlerImpl { return &InstalledAppRestHandlerImpl{ Logger: Logger, @@ -466,4 +465,4 @@ func (handler *InstalledAppRestHandlerImpl) FetchAppDetailsForInstalledApp(w htt handler.Logger.Infow("appName and envName not found - avoiding resource tree call", "app", appDetail.AppName, "env", appDetail.EnvironmentName) } common.WriteJsonResp(w, err, appDetail, http.StatusOK) -} +} \ No newline at end of file diff --git a/api/appStore/deployment/AppStoreDeploymentRestHandler.go b/api/appStore/deployment/AppStoreDeploymentRestHandler.go index ecaea22d8f..1c588d6e29 100644 --- a/api/appStore/deployment/AppStoreDeploymentRestHandler.go +++ b/api/appStore/deployment/AppStoreDeploymentRestHandler.go @@ -20,11 +20,15 @@ package appStoreDeployment import ( "context" "encoding/json" + "errors" "fmt" + client "github.com/devtron-labs/devtron/api/helm-app" + openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDeployment "github.com/devtron-labs/devtron/pkg/appStore/deployment" + appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/user" "github.com/devtron-labs/devtron/pkg/user/casbin" util2 "github.com/devtron-labs/devtron/util" @@ -38,37 +42,43 @@ import ( ) type AppStoreDeploymentRestHandler interface { - CreateInstalledApp(w http.ResponseWriter, r *http.Request) + InstallApp(w http.ResponseWriter, r *http.Request) GetInstalledAppsByAppStoreId(w http.ResponseWriter, r *http.Request) DeleteInstalledApp(w http.ResponseWriter, r *http.Request) + LinkHelmApplicationToChartStore(w http.ResponseWriter, r *http.Request) } type AppStoreDeploymentRestHandlerImpl struct { - Logger *zap.SugaredLogger - userAuthService user.UserService - enforcer casbin.Enforcer - enforcerUtil rbac.EnforcerUtil - enforcerUtilHelm rbac.EnforcerUtilHelm - appStoreDeploymentService appStoreDeployment.AppStoreDeploymentService - validator *validator.Validate + Logger *zap.SugaredLogger + userAuthService user.UserService + enforcer casbin.Enforcer + enforcerUtil rbac.EnforcerUtil + enforcerUtilHelm rbac.EnforcerUtilHelm + appStoreDeploymentService service.AppStoreDeploymentService + appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService + validator *validator.Validate + helmAppService client.HelmAppService + helmAppRestHandler client.HelmAppRestHandler } func NewAppStoreDeploymentRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, - enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, enforcerUtilHelm rbac.EnforcerUtilHelm, appStoreDeploymentService appStoreDeployment.AppStoreDeploymentService, - validator *validator.Validate, + enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, enforcerUtilHelm rbac.EnforcerUtilHelm, appStoreDeploymentService service.AppStoreDeploymentService, + validator *validator.Validate, helmAppService client.HelmAppService, appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService, ) *AppStoreDeploymentRestHandlerImpl { return &AppStoreDeploymentRestHandlerImpl{ - Logger: Logger, - userAuthService: userAuthService, - enforcer: enforcer, - enforcerUtil: enforcerUtil, - enforcerUtilHelm: enforcerUtilHelm, - appStoreDeploymentService: appStoreDeploymentService, - validator: validator, + Logger: Logger, + userAuthService: userAuthService, + enforcer: enforcer, + enforcerUtil: enforcerUtil, + enforcerUtilHelm: enforcerUtilHelm, + appStoreDeploymentService: appStoreDeploymentService, + validator: validator, + helmAppService: helmAppService, + appStoreDeploymentServiceC: appStoreDeploymentServiceC, } } -func (handler AppStoreDeploymentRestHandlerImpl) CreateInstalledApp(w http.ResponseWriter, r *http.Request) { +func (handler AppStoreDeploymentRestHandlerImpl) InstallApp(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { @@ -95,8 +105,8 @@ func (handler AppStoreDeploymentRestHandlerImpl) CreateInstalledApp(w http.Respo var rbacObject string if util2.GetDevtronVersion().ServerMode == util2.SERVER_MODE_HYPERION { rbacObject = handler.enforcerUtilHelm.GetHelmObjectByClusterId(request.ClusterId, request.Namespace, request.AppName) - }else{ - rbacObject = handler.enforcerUtil.GetHelmObjectByAppNameAndEnvId(request.AppName, request.EnvironmentId) + } else { + rbacObject = handler.enforcerUtil.GetHelmObjectByProjectIdAndEnvId(request.TeamId, request.EnvironmentId) } if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionCreate, rbacObject); !ok { common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), nil, http.StatusForbidden) @@ -171,7 +181,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) GetInstalledAppsByAppStoreId(w var rbacObject string if app.AppOfferingMode == util2.SERVER_MODE_HYPERION { rbacObject = handler.enforcerUtilHelm.GetHelmObjectByClusterId(app.ClusterId, app.Namespace, app.AppName) - }else{ + } else { rbacObject = handler.enforcerUtil.GetHelmObjectByAppNameAndEnvId(app.AppName, app.EnvironmentId) } if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject); !ok { @@ -223,7 +233,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo var rbacObject string if installedApp.AppOfferingMode == util2.SERVER_MODE_HYPERION { rbacObject = handler.enforcerUtilHelm.GetHelmObjectByClusterId(installedApp.ClusterId, installedApp.Namespace, installedApp.AppName) - }else{ + } else { rbacObject = handler.enforcerUtil.GetHelmObjectByAppNameAndEnvId(installedApp.AppName, installedApp.EnvironmentId) } if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionDelete, rbacObject); !ok { @@ -261,3 +271,45 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo } common.WriteJsonResp(w, err, res, http.StatusOK) } + +func (handler *AppStoreDeploymentRestHandlerImpl) LinkHelmApplicationToChartStore(w http.ResponseWriter, r *http.Request) { + request := &openapi.UpdateReleaseWithChartLinkingRequest{} + decoder := json.NewDecoder(r.Body) + err := decoder.Decode(request) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + appIdentifier, err := handler.helmAppService.DecodeAppId(*request.AppId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + + // RBAC enforcer applying + rbacObject := handler.enforcerUtilHelm.GetHelmObjectByClusterId(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) + token := r.Header.Get("token") + if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject); !ok { + common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) + return + } + //RBAC enforcer Ends + + res, isChartRepoActive, err := handler.appStoreDeploymentService.LinkHelmApplicationToChartStore(context.Background(), request, appIdentifier, userId) + if err != nil { + handler.Logger.Errorw("Error in UpdateApplicationWithChartStoreLinking", "err", err, "payload", request) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } else if !isChartRepoActive { + common.WriteJsonResp(w, fmt.Errorf("chart repo is disabled"), nil, http.StatusNotAcceptable) + return + } + + common.WriteJsonResp(w, err, res, http.StatusOK) +} \ No newline at end of file diff --git a/api/appStore/deployment/AppStoreDeploymentRouter.go b/api/appStore/deployment/AppStoreDeploymentRouter.go index 58b94cb096..c35dbdcf07 100644 --- a/api/appStore/deployment/AppStoreDeploymentRouter.go +++ b/api/appStore/deployment/AppStoreDeploymentRouter.go @@ -38,7 +38,7 @@ func NewAppStoreDeploymentRouterImpl(appStoreDeploymentRestHandler AppStoreDeplo func (router AppStoreDeploymentRouterImpl) Init(configRouter *mux.Router) { configRouter.Path("/application/install"). - HandlerFunc(router.appStoreDeploymentRestHandler.CreateInstalledApp).Methods("POST") + HandlerFunc(router.appStoreDeploymentRestHandler.InstallApp).Methods("POST") configRouter.Path("/installed-app/{appStoreId}"). HandlerFunc(router.appStoreDeploymentRestHandler.GetInstalledAppsByAppStoreId).Methods("GET") @@ -46,4 +46,6 @@ func (router AppStoreDeploymentRouterImpl) Init(configRouter *mux.Router) { configRouter.Path("/application/delete/{id}"). HandlerFunc(router.appStoreDeploymentRestHandler.DeleteInstalledApp).Methods("DELETE") + configRouter.Path("/application/helm/link-to-chart-store"). + HandlerFunc(router.appStoreDeploymentRestHandler.LinkHelmApplicationToChartStore).Methods("PUT") } diff --git a/api/appStore/deployment/CommonDeploymentRestHandler.go b/api/appStore/deployment/CommonDeploymentRestHandler.go new file mode 100644 index 0000000000..3c81350858 --- /dev/null +++ b/api/appStore/deployment/CommonDeploymentRestHandler.go @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2020 Devtron Labs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package appStoreDeployment + +import ( + "context" + "encoding/json" + "fmt" + client "github.com/devtron-labs/devtron/api/helm-app" + openapi2 "github.com/devtron-labs/devtron/api/openapi/openapiClient" + "github.com/devtron-labs/devtron/api/restHandler/common" + "github.com/devtron-labs/devtron/internal/util" + appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" + "github.com/devtron-labs/devtron/pkg/user" + "github.com/devtron-labs/devtron/pkg/user/casbin" + util2 "github.com/devtron-labs/devtron/util" + "github.com/devtron-labs/devtron/util/k8sObjectsUtil" + "github.com/devtron-labs/devtron/util/rbac" + "github.com/gorilla/mux" + "go.uber.org/zap" + "gopkg.in/go-playground/validator.v9" + "net/http" + "strconv" + "time" +) + +type CommonDeploymentRestHandler interface { + GetDeploymentHistory(w http.ResponseWriter, r *http.Request) + GetDeploymentHistoryValues(w http.ResponseWriter, r *http.Request) + RollbackApplication(w http.ResponseWriter, r *http.Request) +} + +type CommonDeploymentRestHandlerImpl struct { + Logger *zap.SugaredLogger + userAuthService user.UserService + enforcer casbin.Enforcer + enforcerUtil rbac.EnforcerUtil + enforcerUtilHelm rbac.EnforcerUtilHelm + appStoreDeploymentService service.AppStoreDeploymentService + appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService + validator *validator.Validate + helmAppService client.HelmAppService + helmAppRestHandler client.HelmAppRestHandler +} + +func NewCommonDeploymentRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, + enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, enforcerUtilHelm rbac.EnforcerUtilHelm, appStoreDeploymentService service.AppStoreDeploymentService, + validator *validator.Validate, helmAppService client.HelmAppService, appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService, + helmAppRestHandler client.HelmAppRestHandler) *CommonDeploymentRestHandlerImpl { + return &CommonDeploymentRestHandlerImpl{ + Logger: Logger, + userAuthService: userAuthService, + enforcer: enforcer, + enforcerUtil: enforcerUtil, + enforcerUtilHelm: enforcerUtilHelm, + appStoreDeploymentService: appStoreDeploymentService, + validator: validator, + helmAppService: helmAppService, + appStoreDeploymentServiceC: appStoreDeploymentServiceC, + helmAppRestHandler: helmAppRestHandler, + } +} +func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppId string, appId string) (string, *appStoreBean.InstallAppVersionDTO, error) { + installedAppDto := &appStoreBean.InstallAppVersionDTO{} + var appOfferingMode string + if len(appId) > 0 { + appIdentifier, err := handler.helmAppService.DecodeAppId(appId) + if err != nil { + err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "invalid app id"} + return appOfferingMode, installedAppDto, err + } + installedAppDto, err = handler.appStoreDeploymentServiceC.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) + if err != nil { + err = &util.ApiError{HttpStatusCode: http.StatusInternalServerError, UserMessage: "unable to find app in database"} + return appOfferingMode, installedAppDto, err + } + // this is the case when hyperion apps does not linked yet + if installedAppDto == nil { + installedAppDto = &appStoreBean.InstallAppVersionDTO{} + appOfferingMode = util2.SERVER_MODE_HYPERION + installedAppDto.InstalledAppId = 0 + installedAppDto.AppOfferingMode = appOfferingMode + appIdentifier, err := handler.helmAppService.DecodeAppId(appId) + if err != nil { + err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "invalid app id"} + return appOfferingMode, installedAppDto, err + } + installedAppDto.ClusterId = appIdentifier.ClusterId + installedAppDto.Namespace = appIdentifier.Namespace + installedAppDto.AppName = appIdentifier.ReleaseName + } + } else if len(installedAppId) > 0 { + installedAppId, err := strconv.Atoi(installedAppId) + if err != nil { + err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "invalid installed app id"} + return appOfferingMode, installedAppDto, err + } + installedAppDto, err = handler.appStoreDeploymentServiceC.GetInstalledAppByInstalledAppId(installedAppId) + if err != nil { + err = &util.ApiError{HttpStatusCode: http.StatusInternalServerError, UserMessage: "unable to find app in database"} + return appOfferingMode, installedAppDto, err + } + } else { + err := &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "app id missing in request"} + return appOfferingMode, installedAppDto, err + } + if installedAppDto != nil && installedAppDto.InstalledAppId > 0 { + appOfferingMode = installedAppDto.AppOfferingMode + } + return appOfferingMode, installedAppDto, nil +} + +func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistory(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + v := r.URL.Query() + installedAppId := v.Get("installedAppId") + appId := v.Get("appId") + appOfferingMode, installedAppDto, err := handler.getAppOfferingMode(installedAppId, appId) + if err != nil { + common.WriteJsonResp(w, err, "bad request", http.StatusBadRequest) + return + } + installedAppDto.UserId = userId + //rbac block starts from here + var rbacObject string + token := r.Header.Get("token") + if appOfferingMode == util2.SERVER_MODE_HYPERION { + rbacObject = handler.enforcerUtilHelm.GetHelmObjectByClusterId(installedAppDto.ClusterId, installedAppDto.Namespace, installedAppDto.AppName) + } else { + rbacObject = handler.enforcerUtil.GetHelmObjectByAppNameAndEnvId(installedAppDto.AppName, installedAppDto.EnvironmentId) + } + if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), nil, http.StatusForbidden) + return + } + //rbac block ends here + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + res, err := handler.appStoreDeploymentService.GetDeploymentHistory(ctx, installedAppDto) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler *CommonDeploymentRestHandlerImpl) GetDeploymentHistoryValues(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + v := r.URL.Query() + installedAppId := v.Get("installedAppId") + appId := v.Get("appId") + appOfferingMode, installedAppDto, err := handler.getAppOfferingMode(installedAppId, appId) + if err != nil { + common.WriteJsonResp(w, err, "bad request", http.StatusBadRequest) + return + } + installedAppDto.UserId = userId + installedAppVersionHistoryId, err := strconv.Atoi(vars["version"]) + if err != nil { + handler.Logger.Errorw("request err", "error", err, "installedAppVersionHistoryId", installedAppVersionHistoryId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + //rbac block starts from here + var rbacObject string + token := r.Header.Get("token") + if appOfferingMode == util2.SERVER_MODE_HYPERION { + rbacObject = handler.enforcerUtilHelm.GetHelmObjectByClusterId(installedAppDto.ClusterId, installedAppDto.Namespace, installedAppDto.AppName) + } else { + rbacObject = handler.enforcerUtil.GetHelmObjectByAppNameAndEnvId(installedAppDto.AppName, installedAppDto.EnvironmentId) + } + if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), nil, http.StatusForbidden) + return + } + //rbac block ends here + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + res, err := handler.appStoreDeploymentService.GetDeploymentHistoryInfo(ctx, installedAppDto, installedAppVersionHistoryId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + if appOfferingMode == util2.SERVER_MODE_HYPERION { + canUpdate := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject) + if !canUpdate && res != nil && res.Manifest != nil { + modifiedManifest, err := k8sObjectsUtil.HideValuesIfSecretForWholeYamlInput(*res.Manifest) + if err != nil { + handler.Logger.Errorw("error in hiding secret values", "err", err) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + res.Manifest = &modifiedManifest + } + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler *CommonDeploymentRestHandlerImpl) RollbackApplication(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + request := &openapi2.RollbackReleaseRequest{} + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(request) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + installedAppId := "" + if request.GetInstalledAppId() > 0 { + installedAppId = fmt.Sprint(request.GetInstalledAppId()) + } + appOfferingMode, installedAppDto, err := handler.getAppOfferingMode(installedAppId, *request.HAppId) + if err != nil { + common.WriteJsonResp(w, err, "bad request", http.StatusBadRequest) + } + installedAppDto.UserId = userId + //rbac block starts from here + var rbacObject string + token := r.Header.Get("token") + if appOfferingMode == util2.SERVER_MODE_HYPERION { + rbacObject = handler.enforcerUtilHelm.GetHelmObjectByClusterId(installedAppDto.ClusterId, installedAppDto.Namespace, installedAppDto.AppName) + } else { + rbacObject = handler.enforcerUtil.GetHelmObjectByAppNameAndEnvId(installedAppDto.AppName, installedAppDto.EnvironmentId) + } + if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), nil, http.StatusForbidden) + return + } + //rbac block ends here + + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + success, err := handler.appStoreDeploymentService.RollbackApplication(ctx, request, installedAppDto, userId) + if err != nil { + handler.Logger.Errorw("Error in Rollback release", "err", err, "payload", request) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + res := &openapi2.RollbackReleaseResponse{ + Success: &success, + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} diff --git a/api/appStore/deployment/CommonDeploymentRouter.go b/api/appStore/deployment/CommonDeploymentRouter.go new file mode 100644 index 0000000000..a5cd1cf03e --- /dev/null +++ b/api/appStore/deployment/CommonDeploymentRouter.go @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020 Devtron Labs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package appStoreDeployment + +import ( + "github.com/gorilla/mux" +) + +type CommonDeploymentRouter interface { + Init(configRouter *mux.Router) +} + +type CommonDeploymentRouterImpl struct { + commonDeploymentRestHandler CommonDeploymentRestHandler +} + +func NewCommonDeploymentRouterImpl(commonDeploymentRestHandler CommonDeploymentRestHandler) *CommonDeploymentRouterImpl { + return &CommonDeploymentRouterImpl{ + commonDeploymentRestHandler: commonDeploymentRestHandler, + } +} + +func (router CommonDeploymentRouterImpl) Init(configRouter *mux.Router) { + configRouter.Path("/deployment-history"). + HandlerFunc(router.commonDeploymentRestHandler.GetDeploymentHistory).Methods("GET") + + configRouter.Path("/deployment-history/info"). + Queries("version", "{version}"). + HandlerFunc(router.commonDeploymentRestHandler.GetDeploymentHistoryValues).Methods("GET") + + configRouter.Path("/rollback"). + HandlerFunc(router.commonDeploymentRestHandler.RollbackApplication).Methods("PUT") +} diff --git a/api/appStore/deployment/wire_appStoreDeployment.go b/api/appStore/deployment/wire_appStoreDeployment.go index 4348c05aeb..188f060065 100644 --- a/api/appStore/deployment/wire_appStoreDeployment.go +++ b/api/appStore/deployment/wire_appStoreDeployment.go @@ -1,24 +1,31 @@ package appStoreDeployment import ( - appStoreDeployment "github.com/devtron-labs/devtron/pkg/appStore/deployment" appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" appStoreDeploymentTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" "github.com/google/wire" ) var AppStoreDeploymentWireSet = wire.NewSet( - appStoreRepository.NewClusterInstalledAppsRepositoryImpl, - wire.Bind(new(appStoreRepository.ClusterInstalledAppsRepository), new(*appStoreRepository.ClusterInstalledAppsRepositoryImpl)), + repository.NewClusterInstalledAppsRepositoryImpl, + wire.Bind(new(repository.ClusterInstalledAppsRepository), new(*repository.ClusterInstalledAppsRepositoryImpl)), appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl, wire.Bind(new(appStoreDeploymentCommon.AppStoreDeploymentCommonService), new(*appStoreDeploymentCommon.AppStoreDeploymentCommonServiceImpl)), appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl, - wire.Bind(new(appStoreDeploymentTool.AppStoreDeploymentHelmService),new(*appStoreDeploymentTool.AppStoreDeploymentHelmServiceImpl)), - appStoreDeployment.NewAppStoreDeploymentServiceImpl, - wire.Bind(new(appStoreDeployment.AppStoreDeploymentService), new(*appStoreDeployment.AppStoreDeploymentServiceImpl)), + wire.Bind(new(appStoreDeploymentTool.AppStoreDeploymentHelmService), new(*appStoreDeploymentTool.AppStoreDeploymentHelmServiceImpl)), + service.NewAppStoreDeploymentServiceImpl, + wire.Bind(new(service.AppStoreDeploymentService), new(*service.AppStoreDeploymentServiceImpl)), NewAppStoreDeploymentRestHandlerImpl, wire.Bind(new(AppStoreDeploymentRestHandler), new(*AppStoreDeploymentRestHandlerImpl)), NewAppStoreDeploymentRouterImpl, wire.Bind(new(AppStoreDeploymentRouter), new(*AppStoreDeploymentRouterImpl)), + repository.NewInstalledAppVersionHistoryRepositoryImpl, + wire.Bind(new(repository.InstalledAppVersionHistoryRepository), new(*repository.InstalledAppVersionHistoryRepositoryImpl)), + + NewCommonDeploymentRestHandlerImpl, + wire.Bind(new(CommonDeploymentRestHandler), new(*CommonDeploymentRestHandlerImpl)), + NewCommonDeploymentRouterImpl, + wire.Bind(new(CommonDeploymentRouter), new(*CommonDeploymentRouterImpl)), ) diff --git a/api/appStore/discover/AppStoreRestHandler.go b/api/appStore/discover/AppStoreRestHandler.go index 7b2c9123c9..f49bc892d3 100644 --- a/api/appStore/discover/AppStoreRestHandler.go +++ b/api/appStore/discover/AppStoreRestHandler.go @@ -20,7 +20,7 @@ package appStoreDiscover import ( "github.com/devtron-labs/devtron/api/restHandler/common" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDiscover "github.com/devtron-labs/devtron/pkg/appStore/discover" + "github.com/devtron-labs/devtron/pkg/appStore/discover/service" "github.com/devtron-labs/devtron/pkg/user" "github.com/devtron-labs/devtron/pkg/user/casbin" "github.com/gorilla/mux" @@ -39,13 +39,13 @@ type AppStoreRestHandler interface { } type AppStoreRestHandlerImpl struct { - Logger *zap.SugaredLogger - appStoreService appStoreDiscover.AppStoreService - userAuthService user.UserService - enforcer casbin.Enforcer + Logger *zap.SugaredLogger + appStoreService service.AppStoreService + userAuthService user.UserService + enforcer casbin.Enforcer } -func NewAppStoreRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, appStoreService appStoreDiscover.AppStoreService, +func NewAppStoreRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, appStoreService service.AppStoreService, enforcer casbin.Enforcer) *AppStoreRestHandlerImpl { return &AppStoreRestHandlerImpl{ Logger: Logger, diff --git a/api/appStore/discover/wire_appStoreDiscover.go b/api/appStore/discover/wire_appStoreDiscover.go index def82f098c..1469d42d68 100644 --- a/api/appStore/discover/wire_appStoreDiscover.go +++ b/api/appStore/discover/wire_appStoreDiscover.go @@ -1,8 +1,8 @@ package appStoreDiscover import ( - appStoreDiscover "github.com/devtron-labs/devtron/pkg/appStore/discover" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" + "github.com/devtron-labs/devtron/pkg/appStore/discover/service" "github.com/google/wire" ) @@ -11,8 +11,8 @@ var AppStoreDiscoverWireSet = wire.NewSet( wire.Bind(new(appStoreDiscoverRepository.AppStoreRepository), new(*appStoreDiscoverRepository.AppStoreRepositoryImpl)), appStoreDiscoverRepository.NewAppStoreApplicationVersionRepositoryImpl, wire.Bind(new(appStoreDiscoverRepository.AppStoreApplicationVersionRepository), new(*appStoreDiscoverRepository.AppStoreApplicationVersionRepositoryImpl)), - appStoreDiscover.NewAppStoreServiceImpl, - wire.Bind(new(appStoreDiscover.AppStoreService), new(*appStoreDiscover.AppStoreServiceImpl)), + service.NewAppStoreServiceImpl, + wire.Bind(new(service.AppStoreService), new(*service.AppStoreServiceImpl)), NewAppStoreRestHandlerImpl, wire.Bind(new(AppStoreRestHandler), new(*AppStoreRestHandlerImpl)), NewAppStoreDiscoverRouterImpl, diff --git a/api/appStore/values/AppStoreValuesRestHandler.go b/api/appStore/values/AppStoreValuesRestHandler.go index 91c97d42bf..09d0938a10 100644 --- a/api/appStore/values/AppStoreValuesRestHandler.go +++ b/api/appStore/values/AppStoreValuesRestHandler.go @@ -21,7 +21,7 @@ import ( "encoding/json" "github.com/devtron-labs/devtron/api/restHandler/common" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreValues "github.com/devtron-labs/devtron/pkg/appStore/values" + "github.com/devtron-labs/devtron/pkg/appStore/values/service" "github.com/devtron-labs/devtron/pkg/user" "github.com/gorilla/mux" "go.uber.org/zap" @@ -43,11 +43,11 @@ type AppStoreValuesRestHandler interface { type AppStoreValuesRestHandlerImpl struct { Logger *zap.SugaredLogger userAuthService user.UserService - appStoreValuesService appStoreValues.AppStoreValuesService + appStoreValuesService service.AppStoreValuesService } func NewAppStoreValuesRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, - appStoreValuesService appStoreValues.AppStoreValuesService) *AppStoreValuesRestHandlerImpl { + appStoreValuesService service.AppStoreValuesService) *AppStoreValuesRestHandlerImpl { return &AppStoreValuesRestHandlerImpl{ Logger: Logger, userAuthService: userAuthService, @@ -224,7 +224,7 @@ func (handler AppStoreValuesRestHandlerImpl) GetSelectedChartMetadata(w http.Res return } decoder := json.NewDecoder(r.Body) - var request appStoreValues.ChartMetaDataRequestWrapper + var request service.ChartMetaDataRequestWrapper err = decoder.Decode(&request) if err != nil { handler.Logger.Errorw("request err, GetSelectedChartMetadata", "err", err, "request", request) diff --git a/api/appStore/values/wire_appStoreValues.go b/api/appStore/values/wire_appStoreValues.go index a5f84bdbb1..7a21a676e8 100644 --- a/api/appStore/values/wire_appStoreValues.go +++ b/api/appStore/values/wire_appStoreValues.go @@ -1,9 +1,9 @@ package appStoreValues import ( - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" - appStoreValues "github.com/devtron-labs/devtron/pkg/appStore/values" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreValuesRepository "github.com/devtron-labs/devtron/pkg/appStore/values/repository" + "github.com/devtron-labs/devtron/pkg/appStore/values/service" "github.com/google/wire" ) @@ -12,10 +12,10 @@ var AppStoreValuesWireSet = wire.NewSet( wire.Bind(new(AppStoreValuesRouter), new(*AppStoreValuesRouterImpl)), NewAppStoreValuesRestHandlerImpl, wire.Bind(new(AppStoreValuesRestHandler), new(*AppStoreValuesRestHandlerImpl)), - appStoreValues.NewAppStoreValuesServiceImpl, - wire.Bind(new(appStoreValues.AppStoreValuesService), new(*appStoreValues.AppStoreValuesServiceImpl)), + service.NewAppStoreValuesServiceImpl, + wire.Bind(new(service.AppStoreValuesService), new(*service.AppStoreValuesServiceImpl)), appStoreValuesRepository.NewAppStoreVersionValuesRepositoryImpl, wire.Bind(new(appStoreValuesRepository.AppStoreVersionValuesRepository), new(*appStoreValuesRepository.AppStoreVersionValuesRepositoryImpl)), - appStoreRepository.NewInstalledAppRepositoryImpl, - wire.Bind(new(appStoreRepository.InstalledAppRepository), new(*appStoreRepository.InstalledAppRepositoryImpl)), + repository.NewInstalledAppRepositoryImpl, + wire.Bind(new(repository.InstalledAppRepository), new(*repository.InstalledAppRepositoryImpl)), ) diff --git a/api/chartRepo/ChartRepositoryRestHandler.go b/api/chartRepo/ChartRepositoryRestHandler.go index 18ce8c6edc..f93891b664 100644 --- a/api/chartRepo/ChartRepositoryRestHandler.go +++ b/api/chartRepo/ChartRepositoryRestHandler.go @@ -23,18 +23,27 @@ import ( "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/chartRepo" + chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" delete2 "github.com/devtron-labs/devtron/pkg/delete" + "github.com/devtron-labs/devtron/pkg/pipeline" "github.com/devtron-labs/devtron/pkg/user" "github.com/devtron-labs/devtron/pkg/user/casbin" "github.com/gorilla/mux" "go.uber.org/zap" "gopkg.in/go-playground/validator.v9" + "mime/multipart" "net/http" "strconv" ) const CHART_REPO_DELETE_SUCCESS_RESP = "Chart repo deleted successfully." +type ChartBinary struct { + Version string `json:"binaryVersion" validate:"required"` + BinaryFile multipart.File `json:"binaryFile" validate:"required"` + BinaryFileName string `json:"binaryFileName" validate:"required"` +} + type ChartRepositoryRestHandler interface { GetChartRepoById(w http.ResponseWriter, r *http.Request) GetChartRepoList(w http.ResponseWriter, r *http.Request) @@ -52,10 +61,13 @@ type ChartRepositoryRestHandlerImpl struct { enforcer casbin.Enforcer validator *validator.Validate deleteService delete2.DeleteService + chartRefRepository chartRepoRepository.ChartRefRepository + refChartDir pipeline.RefChartDir } func NewChartRepositoryRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, chartRepositoryService chartRepo.ChartRepositoryService, - enforcer casbin.Enforcer, validator *validator.Validate, deleteService delete2.DeleteService) *ChartRepositoryRestHandlerImpl { + enforcer casbin.Enforcer, validator *validator.Validate, deleteService delete2.DeleteService, + chartRefRepository chartRepoRepository.ChartRefRepository, refChartDir pipeline.RefChartDir) *ChartRepositoryRestHandlerImpl { return &ChartRepositoryRestHandlerImpl{ Logger: Logger, chartRepositoryService: chartRepositoryService, @@ -63,6 +75,8 @@ func NewChartRepositoryRestHandlerImpl(Logger *zap.SugaredLogger, userAuthServic enforcer: enforcer, validator: validator, deleteService: deleteService, + chartRefRepository: chartRefRepository, + refChartDir: refChartDir, } } @@ -283,4 +297,4 @@ func (handler *ChartRepositoryRestHandlerImpl) DeleteChartRepo(w http.ResponseWr return } common.WriteJsonResp(w, nil, CHART_REPO_DELETE_SUCCESS_RESP, http.StatusOK) -} \ No newline at end of file +} diff --git a/api/dashboardEvent/DashboardTelemetryRestHandler.go b/api/dashboardEvent/DashboardTelemetryRestHandler.go new file mode 100644 index 0000000000..a5471a8914 --- /dev/null +++ b/api/dashboardEvent/DashboardTelemetryRestHandler.go @@ -0,0 +1,50 @@ +package dashboardEvent + +import ( + "github.com/devtron-labs/devtron/api/restHandler/common" + "github.com/devtron-labs/devtron/client/telemetry" + "go.uber.org/zap" + "net/http" +) + +type DashboardTelemetryRestHandler interface { + SendDashboardAccessedEvent(w http.ResponseWriter, r *http.Request) + SendDashboardLoggedInEvent(w http.ResponseWriter, r *http.Request) +} + +type DashboardTelemetryRestHandlerImpl struct { + logger *zap.SugaredLogger + telemetry telemetry.TelemetryEventClient +} + +func NewDashboardTelemetryRestHandlerImpl(logger *zap.SugaredLogger, + telemetry telemetry.TelemetryEventClient) *DashboardTelemetryRestHandlerImpl { + return &DashboardTelemetryRestHandlerImpl{ + logger: logger, + telemetry: telemetry, + } +} + +func (handler *DashboardTelemetryRestHandlerImpl) SendDashboardAccessedEvent(w http.ResponseWriter, r *http.Request) { + err := handler.telemetry.SendTelemetryDashboardAccessEvent() + if err != nil { + handler.logger.Warnw("Sending Telemetry Event failed", "error", err) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Infow("Event Sent Successfully") + common.WriteJsonResp(w, err, "Event Sent Successfully", http.StatusOK) + return +} + +func (handler *DashboardTelemetryRestHandlerImpl) SendDashboardLoggedInEvent(w http.ResponseWriter, r *http.Request) { + err := handler.telemetry.SendTelemetryDashboardLoggedInEvent() + if err != nil { + handler.logger.Warnw("Sending Telemetry Event failed", "error", err) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Infow("Event Sent Successfully") + common.WriteJsonResp(w, err, "Event Sent Successfully", http.StatusOK) + return +} diff --git a/api/dashboardEvent/DashboardTelemetryRouter.go b/api/dashboardEvent/DashboardTelemetryRouter.go new file mode 100644 index 0000000000..315f684156 --- /dev/null +++ b/api/dashboardEvent/DashboardTelemetryRouter.go @@ -0,0 +1,24 @@ +package dashboardEvent + +import "github.com/gorilla/mux" + +type DashboardTelemetryRouter interface { + Init(configRouter *mux.Router) +} + +type DashboardTelemetryRouterImpl struct { + deploymentRestHandler DashboardTelemetryRestHandler +} + +func NewDashboardTelemetryRouterImpl(deploymentRestHandler DashboardTelemetryRestHandler) *DashboardTelemetryRouterImpl { + return &DashboardTelemetryRouterImpl{ + deploymentRestHandler: deploymentRestHandler, + } +} + +func (router DashboardTelemetryRouterImpl) Init(configRouter *mux.Router) { + configRouter.Path("/dashboardAccessed"). + HandlerFunc(router.deploymentRestHandler.SendDashboardAccessedEvent).Methods("GET") + configRouter.Path("/dashboardLoggedIn"). + HandlerFunc(router.deploymentRestHandler.SendDashboardLoggedInEvent).Methods("GET") +} diff --git a/api/deployment/DeploymentConfigRestHandler.go b/api/deployment/DeploymentConfigRestHandler.go new file mode 100644 index 0000000000..1a514a2440 --- /dev/null +++ b/api/deployment/DeploymentConfigRestHandler.go @@ -0,0 +1,124 @@ +package deployment + +import ( + "fmt" + "github.com/devtron-labs/devtron/api/restHandler/common" + chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" + "github.com/devtron-labs/devtron/pkg/pipeline" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/devtron-labs/devtron/pkg/user" + "github.com/devtron-labs/devtron/pkg/user/casbin" + "github.com/juju/errors" + "go.uber.org/zap" + "gopkg.in/go-playground/validator.v9" + "io/ioutil" + "net/http" + "os" + "time" +) + +type DeploymentConfigRestHandler interface { + CreateChartFromFile(w http.ResponseWriter, r *http.Request) +} + +type DeploymentConfigRestHandlerImpl struct { + Logger *zap.SugaredLogger + userAuthService user.UserService + enforcer casbin.Enforcer + validator *validator.Validate + refChartDir pipeline.RefChartDir + chartService pipeline.ChartService + chartRefRepository chartRepoRepository.ChartRefRepository +} + +func NewDeploymentConfigRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, enforcer casbin.Enforcer, validator *validator.Validate, + refChartDir pipeline.RefChartDir, chartService pipeline.ChartService, chartRefRepository chartRepoRepository.ChartRefRepository) *DeploymentConfigRestHandlerImpl { + return &DeploymentConfigRestHandlerImpl{ + Logger: Logger, + userAuthService: userAuthService, + enforcer: enforcer, + validator: validator, + refChartDir: refChartDir, + chartService: chartService, + chartRefRepository: chartRefRepository, + } +} + +func (handler *DeploymentConfigRestHandlerImpl) CreateChartFromFile(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, nil, http.StatusUnauthorized) + return + } + + token := r.Header.Get("token") + if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*"); !ok { + common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) + return + } + + file, fileHeader, err := r.FormFile("BinaryFile") + if err != nil { + handler.Logger.Errorw("request err, File parsing error", "err", err, "payload", file) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + + if err := r.ParseForm(); err != nil { + handler.Logger.Errorw("request err, Corrupted form data", "err", err, "payload", file) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + + err = handler.chartService.ValidateUploadedFileFormat(fileHeader.Filename) + if err != nil { + handler.Logger.Errorw("request err, Unsupported format", "err", err, "payload", file) + common.WriteJsonResp(w, errors.New("Unsupported format file is uploaded, please upload file with .tar.gz extension"), nil, http.StatusBadRequest) + return + } + + fileBytes, err := ioutil.ReadAll(file) + if err != nil { + handler.Logger.Errorw("request err, File parsing error", "err", err, "payload", file) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + + chartInfo, err := handler.chartService.ExtractChartIfMissing(fileBytes, string(handler.refChartDir), "") + + if chartInfo.TemporaryFolder != "" { + err1 := os.RemoveAll(chartInfo.TemporaryFolder) + if err1 != nil { + handler.Logger.Errorw("error in deleting temp dir ", "err", err) + } + } + + if err != nil { + common.WriteJsonResp(w, fmt.Errorf(err.Error()), nil, http.StatusBadRequest) + return + } + + chartRefs := &chartRepoRepository.ChartRef{ + Name: chartInfo.ChartName, + Version: chartInfo.ChartVersion, + Location: chartInfo.ChartLocation, + Active: true, + Default: false, + ChartData: fileBytes, + AuditLog: sql.AuditLog{ + CreatedBy: userId, + CreatedOn: time.Now(), + UpdatedOn: time.Now(), + UpdatedBy: userId, + }, + } + + err = handler.chartRefRepository.Save(chartRefs) + if err != nil { + handler.Logger.Errorw("error in saving ConfigMap, CallbackConfigMap", "err", err) + common.WriteJsonResp(w, err, "Chart couldn't be saved", http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, "Chart Saved Successfully", http.StatusOK) + return +} diff --git a/api/deployment/DeploymentConfigRouter.go b/api/deployment/DeploymentConfigRouter.go new file mode 100644 index 0000000000..75213a5692 --- /dev/null +++ b/api/deployment/DeploymentConfigRouter.go @@ -0,0 +1,22 @@ +package deployment + +import "github.com/gorilla/mux" + +type DeploymentConfigRouter interface { + Init(configRouter *mux.Router) +} + +type DeploymentConfigRouterImpl struct { + deploymentRestHandler DeploymentConfigRestHandler +} + +func NewDeploymentRouterImpl(deploymentRestHandler DeploymentConfigRestHandler) *DeploymentConfigRouterImpl { + return &DeploymentConfigRouterImpl{ + deploymentRestHandler: deploymentRestHandler, + } +} + +func (router DeploymentConfigRouterImpl) Init(configRouter *mux.Router) { + configRouter.Path("/upload"). + HandlerFunc(router.deploymentRestHandler.CreateChartFromFile).Methods("POST") +} diff --git a/api/helm-app/HelmAppRestHandler.go b/api/helm-app/HelmAppRestHandler.go index c9ddec8052..d5b1a5f74f 100644 --- a/api/helm-app/HelmAppRestHandler.go +++ b/api/helm-app/HelmAppRestHandler.go @@ -24,12 +24,10 @@ type HelmAppRestHandler interface { GetApplicationDetail(w http.ResponseWriter, r *http.Request) Hibernate(w http.ResponseWriter, r *http.Request) UnHibernate(w http.ResponseWriter, r *http.Request) - GetDeploymentHistory(w http.ResponseWriter, r *http.Request) - GetValuesYaml(w http.ResponseWriter, r *http.Request) + GetReleaseInfo(w http.ResponseWriter, r *http.Request) GetDesiredManifest(w http.ResponseWriter, r *http.Request) DeleteApplication(w http.ResponseWriter, r *http.Request) UpdateApplication(w http.ResponseWriter, r *http.Request) - GetDeploymentDetail(w http.ResponseWriter, r *http.Request) } type HelmAppRestHandlerImpl struct { @@ -72,7 +70,7 @@ func (handler *HelmAppRestHandlerImpl) ListApplications(w http.ResponseWriter, r clusterIds = append(clusterIds, j) } token := r.Header.Get("token") - handler.helmAppService.ListHelmApplications(clusterIds, w, token, handler.CheckHelmAuth) + handler.helmAppService.ListHelmApplications(clusterIds, w, token, handler.checkHelmAuth) } func (handler *HelmAppRestHandlerImpl) GetApplicationDetail(w http.ResponseWriter, r *http.Request) { @@ -129,7 +127,7 @@ func (handler *HelmAppRestHandlerImpl) Hibernate(w http.ResponseWriter, r *http. // RBAC enforcer applying rbacObject := handler.enforcerUtil.GetHelmObjectByClusterId(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) token := r.Header.Get("token") - if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject); !ok { + if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject); !ok { common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) return } @@ -143,7 +141,7 @@ func (handler *HelmAppRestHandlerImpl) Hibernate(w http.ResponseWriter, r *http. } func (handler *HelmAppRestHandlerImpl) UnHibernate(w http.ResponseWriter, r *http.Request) { - var hibernateRequest *openapi.HibernateRequest + hibernateRequest := &openapi.HibernateRequest{} decoder := json.NewDecoder(r.Body) err := decoder.Decode(hibernateRequest) if err != nil { @@ -158,7 +156,7 @@ func (handler *HelmAppRestHandlerImpl) UnHibernate(w http.ResponseWriter, r *htt // RBAC enforcer applying rbacObject := handler.enforcerUtil.GetHelmObjectByClusterId(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) token := r.Header.Get("token") - if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject); !ok { + if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject); !ok { common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) return } @@ -171,32 +169,7 @@ func (handler *HelmAppRestHandlerImpl) UnHibernate(w http.ResponseWriter, r *htt common.WriteJsonResp(w, err, res, http.StatusOK) } -func (handler *HelmAppRestHandlerImpl) GetDeploymentHistory(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - appId := vars["appId"] - appIdentifier, err := handler.helmAppService.DecodeAppId(appId) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - // RBAC enforcer applying - rbacObject := handler.enforcerUtil.GetHelmObjectByClusterId(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) - token := r.Header.Get("token") - if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject); !ok { - common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) - return - } - //RBAC enforcer Ends - res, err := handler.helmAppService.GetDeploymentHistory(context.Background(), appIdentifier) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) - return - } - - common.WriteJsonResp(w, err, res, http.StatusOK) -} - -func (handler *HelmAppRestHandlerImpl) GetValuesYaml(w http.ResponseWriter, r *http.Request) { +func (handler *HelmAppRestHandlerImpl) GetReleaseInfo(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) appId := vars["appId"] appIdentifier, err := handler.helmAppService.DecodeAppId(appId) @@ -351,7 +324,7 @@ func (handler *HelmAppRestHandlerImpl) UpdateApplication(w http.ResponseWriter, common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) return } - }else{ + } else { res, err = handler.helmAppService.UpdateApplication(context.Background(), appIdentifier, request) if err != nil { common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) @@ -362,49 +335,8 @@ func (handler *HelmAppRestHandlerImpl) UpdateApplication(w http.ResponseWriter, common.WriteJsonResp(w, err, res, http.StatusOK) } -func (handler *HelmAppRestHandlerImpl) GetDeploymentDetail(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - appId := vars["appId"] - version, err := strconv.ParseInt(vars["version"], 10, 32) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - appIdentifier, err := handler.helmAppService.DecodeAppId(appId) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - // RBAC enforcer applying - rbacObject := handler.enforcerUtil.GetHelmObjectByClusterId(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) - token := r.Header.Get("token") - if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, rbacObject); !ok { - common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden) - return - } - //RBAC enforcer Ends - res, err := handler.helmAppService.GetDeploymentDetail(context.Background(), appIdentifier, int32(version)) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) - return - } - - // Obfuscate secrets if user does not have edit access - canUpdate := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionUpdate, rbacObject) - if !canUpdate && res != nil && res.Manifest != nil { - modifiedManifest, err := k8sObjectsUtil.HideValuesIfSecretForWholeYamlInput(*res.Manifest) - if err != nil { - handler.logger.Errorw("error in hiding secret values", "err", err) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) - return - } - res.Manifest = &modifiedManifest - } - - common.WriteJsonResp(w, err, res, http.StatusOK) -} -func (handler *HelmAppRestHandlerImpl) CheckHelmAuth(token string, object string) bool { +func (handler *HelmAppRestHandlerImpl) checkHelmAuth(token string, object string) bool { if ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, strings.ToLower(object)); !ok { return false } @@ -417,11 +349,14 @@ func convertToInstalledAppInfo(installedApp *appStoreBean.InstallAppVersionDTO) } return &InstalledAppInfo{ - AppId: installedApp.AppId, - EnvironmentName: installedApp.EnvironmentName, - AppOfferingMode: installedApp.AppOfferingMode, - InstalledAppId: installedApp.InstalledAppId, - AppStoreChartId: installedApp.InstallAppVersionChartDTO.AppStoreChartId, + AppId: installedApp.AppId, + EnvironmentName: installedApp.EnvironmentName, + AppOfferingMode: installedApp.AppOfferingMode, + InstalledAppId: installedApp.InstalledAppId, + InstalledAppVersionId: installedApp.InstalledAppVersionId, + AppStoreChartId: installedApp.InstallAppVersionChartDTO.AppStoreChartId, + ClusterId: installedApp.ClusterId, + EnvironmentId: installedApp.EnvironmentId, } } @@ -435,10 +370,18 @@ type ReleaseAndInstalledAppInfo struct { ReleaseInfo *ReleaseInfo `json:"releaseInfo"` } +type DeploymentHistoryAndInstalledAppInfo struct { + InstalledAppInfo *InstalledAppInfo `json:"installedAppInfo"` + DeploymentHistory []*HelmAppDeploymentDetail `json:"deploymentHistory"` +} + type InstalledAppInfo struct { - AppId int `json:"appId"` - InstalledAppId int `json:"installedAppId"` - AppStoreChartId int `json:"appStoreChartId"` - EnvironmentName string `json:"environmentName"` - AppOfferingMode string `json:"appOfferingMode"` + AppId int `json:"appId"` + InstalledAppId int `json:"installedAppId"` + InstalledAppVersionId int `json:"installedAppVersionId"` + AppStoreChartId int `json:"appStoreChartId"` + EnvironmentName string `json:"environmentName"` + AppOfferingMode string `json:"appOfferingMode"` + ClusterId int `json:"clusterId"` + EnvironmentId int `json:"environmentId"` } diff --git a/api/helm-app/HelmAppRouter.go b/api/helm-app/HelmAppRouter.go index 83a767e826..97774b2d2e 100644 --- a/api/helm-app/HelmAppRouter.go +++ b/api/helm-app/HelmAppRouter.go @@ -23,11 +23,8 @@ func (impl *HelmAppRouterImpl) InitAppListRouter(helmRouter *mux.Router) { helmRouter.Path("/hibernate").HandlerFunc(impl.helmAppRestHandler.Hibernate).Methods("POST") helmRouter.Path("/unhibernate").HandlerFunc(impl.helmAppRestHandler.UnHibernate).Methods("POST") - helmRouter.Path("/deployment-history").Queries("appId", "{appId}"). - HandlerFunc(impl.helmAppRestHandler.GetDeploymentHistory).Methods("GET") - helmRouter.Path("/release-info").Queries("appId", "{appId}"). - HandlerFunc(impl.helmAppRestHandler.GetValuesYaml).Methods("GET") + HandlerFunc(impl.helmAppRestHandler.GetReleaseInfo).Methods("GET") helmRouter.Path("/desired-manifest").HandlerFunc(impl.helmAppRestHandler.GetDesiredManifest).Methods("POST") @@ -35,7 +32,4 @@ func (impl *HelmAppRouterImpl) InitAppListRouter(helmRouter *mux.Router) { helmRouter.Path("/delete").Queries("appId", "{appId}"). HandlerFunc(impl.helmAppRestHandler.DeleteApplication).Methods("DELETE") - - helmRouter.Path("/deployment-detail").Queries("appId", "{appId}").Queries("version", "{version}"). - HandlerFunc(impl.helmAppRestHandler.GetDeploymentDetail).Methods("GET") } diff --git a/api/helm-app/HelmAppService.go b/api/helm-app/HelmAppService.go index e86b5f4919..66f7431a57 100644 --- a/api/helm-app/HelmAppService.go +++ b/api/helm-app/HelmAppService.go @@ -31,6 +31,9 @@ type HelmAppService interface { GetDeploymentDetail(ctx context.Context, app *AppIdentifier, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) InstallRelease(ctx context.Context, clusterId int, installReleaseRequest *InstallReleaseRequest) (*InstallReleaseResponse, error) UpdateApplicationWithChartInfo(ctx context.Context, clusterId int, updateReleaseRequest *InstallReleaseRequest) (*openapi.UpdateReleaseResponse, error) + IsReleaseInstalled(ctx context.Context, app *AppIdentifier) (bool, error) + RollbackRelease(ctx context.Context, app *AppIdentifier, version int32) (bool, error) + GetClusterConf(clusterId int) (*ClusterConfig, error) } type HelmAppServiceImpl struct { @@ -132,7 +135,7 @@ func (impl *HelmAppServiceImpl) hibernateResponseAdaptor(in []*HibernateStatus) return resStatus } func (impl *HelmAppServiceImpl) HibernateApplication(ctx context.Context, app *AppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { - conf, err := impl.getClusterConf(app.ClusterId) + conf, err := impl.GetClusterConf(app.ClusterId) if err != nil { return nil, err } @@ -148,7 +151,7 @@ func (impl *HelmAppServiceImpl) HibernateApplication(ctx context.Context, app *A func (impl *HelmAppServiceImpl) UnHibernateApplication(ctx context.Context, app *AppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { - conf, err := impl.getClusterConf(app.ClusterId) + conf, err := impl.GetClusterConf(app.ClusterId) if err != nil { return nil, err } @@ -162,7 +165,7 @@ func (impl *HelmAppServiceImpl) UnHibernateApplication(ctx context.Context, app return response, nil } -func (impl *HelmAppServiceImpl) getClusterConf(clusterId int) (*ClusterConfig, error) { +func (impl *HelmAppServiceImpl) GetClusterConf(clusterId int) (*ClusterConfig, error) { cluster, err := impl.clusterService.FindById(clusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) @@ -177,7 +180,7 @@ func (impl *HelmAppServiceImpl) getClusterConf(clusterId int) (*ClusterConfig, e return config, nil } func (impl *HelmAppServiceImpl) GetApplicationDetail(ctx context.Context, app *AppIdentifier) (*AppDetail, error) { - config, err := impl.getClusterConf(app.ClusterId) + config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err @@ -193,7 +196,7 @@ func (impl *HelmAppServiceImpl) GetApplicationDetail(ctx context.Context, app *A } func (impl *HelmAppServiceImpl) GetDeploymentHistory(ctx context.Context, app *AppIdentifier) (*HelmAppDeploymentHistory, error) { - config, err := impl.getClusterConf(app.ClusterId) + config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err @@ -208,7 +211,7 @@ func (impl *HelmAppServiceImpl) GetDeploymentHistory(ctx context.Context, app *A } func (impl *HelmAppServiceImpl) GetValuesYaml(ctx context.Context, app *AppIdentifier) (*ReleaseInfo, error) { - config, err := impl.getClusterConf(app.ClusterId) + config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err @@ -223,7 +226,7 @@ func (impl *HelmAppServiceImpl) GetValuesYaml(ctx context.Context, app *AppIdent } func (impl *HelmAppServiceImpl) GetDesiredManifest(ctx context.Context, app *AppIdentifier, resource *openapi.ResourceIdentifier) (*openapi.DesiredManifestResponse, error) { - config, err := impl.getClusterConf(app.ClusterId) + config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", app.ClusterId, "err", err) return nil, err @@ -255,7 +258,7 @@ func (impl *HelmAppServiceImpl) GetDesiredManifest(ctx context.Context, app *App } func (impl *HelmAppServiceImpl) DeleteApplication(ctx context.Context, app *AppIdentifier) (*openapi.UninstallReleaseResponse, error) { - config, err := impl.getClusterConf(app.ClusterId) + config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", app.ClusterId, "err", err) return nil, err @@ -280,7 +283,7 @@ func (impl *HelmAppServiceImpl) DeleteApplication(ctx context.Context, app *AppI } func (impl *HelmAppServiceImpl) UpdateApplication(ctx context.Context, app *AppIdentifier, request *openapi.UpdateReleaseRequest) (*openapi.UpdateReleaseResponse, error) { - config, err := impl.getClusterConf(app.ClusterId) + config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", app.ClusterId, "err", err) return nil, err @@ -308,7 +311,7 @@ func (impl *HelmAppServiceImpl) UpdateApplication(ctx context.Context, app *AppI } func (impl *HelmAppServiceImpl) GetDeploymentDetail(ctx context.Context, app *AppIdentifier, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) { - config, err := impl.getClusterConf(app.ClusterId) + config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", app.ClusterId, "err", err) return nil, err @@ -338,7 +341,7 @@ func (impl *HelmAppServiceImpl) GetDeploymentDetail(ctx context.Context, app *Ap } func (impl *HelmAppServiceImpl) InstallRelease(ctx context.Context, clusterId int, installReleaseRequest *InstallReleaseRequest) (*InstallReleaseResponse, error) { - config, err := impl.getClusterConf(clusterId) + config, err := impl.GetClusterConf(clusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", clusterId, "err", err) return nil, err @@ -356,7 +359,7 @@ func (impl *HelmAppServiceImpl) InstallRelease(ctx context.Context, clusterId in } func (impl *HelmAppServiceImpl) UpdateApplicationWithChartInfo(ctx context.Context, clusterId int, updateReleaseRequest *InstallReleaseRequest) (*openapi.UpdateReleaseResponse, error) { - config, err := impl.getClusterConf(clusterId) + config, err := impl.GetClusterConf(clusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", clusterId, "err", err) return nil, err @@ -377,6 +380,53 @@ func (impl *HelmAppServiceImpl) UpdateApplicationWithChartInfo(ctx context.Conte return response, nil } +func (impl *HelmAppServiceImpl) IsReleaseInstalled(ctx context.Context, app *AppIdentifier) (bool, error) { + config, err := impl.GetClusterConf(app.ClusterId) + if err != nil { + impl.logger.Errorw("error in fetching cluster detail", "clusterId", app.ClusterId, "err", err) + return false, err + } + + req := &ReleaseIdentifier{ + ClusterConfig: config, + ReleaseName: app.ReleaseName, + ReleaseNamespace: app.Namespace, + } + + apiResponse, err := impl.helmAppClient.IsReleaseInstalled(ctx, req) + if err != nil { + impl.logger.Errorw("error in checking if helm release is installed", "err", err) + return false, err + } + + return apiResponse.Result, nil +} + +func (impl *HelmAppServiceImpl) RollbackRelease(ctx context.Context, app *AppIdentifier, version int32) (bool, error) { + config, err := impl.GetClusterConf(app.ClusterId) + if err != nil { + impl.logger.Errorw("error in fetching cluster detail", "clusterId", app.ClusterId, "err", err) + return false, err + } + + req := &RollbackReleaseRequest{ + ReleaseIdentifier: &ReleaseIdentifier{ + ClusterConfig: config, + ReleaseName: app.ReleaseName, + ReleaseNamespace: app.Namespace, + }, + Version: version, + } + + apiResponse, err := impl.helmAppClient.RollbackRelease(ctx, req) + if err != nil { + impl.logger.Errorw("error in rollback release", "err", err) + return false, err + } + + return apiResponse.Result, nil +} + type AppIdentifier struct { ClusterId int `json:"clusterId"` Namespace string `json:"namespace"` diff --git a/api/helm-app/applicationClient.go b/api/helm-app/applicationClient.go index d91293103e..686a79710e 100644 --- a/api/helm-app/applicationClient.go +++ b/api/helm-app/applicationClient.go @@ -22,6 +22,8 @@ type HelmAppClient interface { GetDeploymentDetail(ctx context.Context, in *DeploymentDetailRequest) (*DeploymentDetailResponse, error) InstallRelease(ctx context.Context, in *InstallReleaseRequest) (*InstallReleaseResponse, error) UpdateApplicationWithChartInfo(ctx context.Context, in *InstallReleaseRequest) (*UpgradeReleaseResponse, error) + IsReleaseInstalled(ctx context.Context, in *ReleaseIdentifier) (*BooleanResponse, error) + RollbackRelease(ctx context.Context, in *RollbackReleaseRequest) (*BooleanResponse, error) } type HelmAppClientImpl struct { @@ -222,3 +224,27 @@ func (impl *HelmAppClientImpl) UpdateApplicationWithChartInfo(ctx context.Contex } return updateReleaseResponse, nil } + +func (impl *HelmAppClientImpl) IsReleaseInstalled(ctx context.Context, in *ReleaseIdentifier) (*BooleanResponse, error) { + applicationClient, err := impl.getApplicationClient() + if err != nil { + return nil, err + } + response, err := applicationClient.IsReleaseInstalled(ctx, in) + if err != nil { + return nil, err + } + return response, nil +} + +func (impl *HelmAppClientImpl) RollbackRelease(ctx context.Context, in *RollbackReleaseRequest) (*BooleanResponse, error) { + applicationClient, err := impl.getApplicationClient() + if err != nil { + return nil, err + } + response, err := applicationClient.RollbackRelease(ctx, in) + if err != nil { + return nil, err + } + return response, nil +} \ No newline at end of file diff --git a/api/helm-app/applist.pb.go b/api/helm-app/applist.pb.go index 9d2a0a1a3a..d65b0b1632 100644 --- a/api/helm-app/applist.pb.go +++ b/api/helm-app/applist.pb.go @@ -591,6 +591,8 @@ type ChartMetadata struct { Home string `protobuf:"bytes,3,opt,name=home,proto3" json:"home,omitempty"` Sources []string `protobuf:"bytes,4,rep,name=sources,proto3" json:"sources,omitempty"` Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` + // Contains the rendered templates/NOTES.txt + Notes string `protobuf:"bytes,6,opt,name=notes,proto3" json:"notes,omitempty"` } func (x *ChartMetadata) Reset() { @@ -660,6 +662,13 @@ func (x *ChartMetadata) GetDescription() string { return "" } +func (x *ChartMetadata) GetNotes() string { + if x != nil { + return x.Notes + } + return "" +} + type ResourceTreeResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2196,6 +2205,108 @@ func (x *InstallReleaseResponse) GetSuccess() bool { return false } +type BooleanResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result bool `protobuf:"varint,1,opt,name=result,proto3" json:"result,omitempty"` +} + +func (x *BooleanResponse) Reset() { + *x = BooleanResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_applist_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BooleanResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BooleanResponse) ProtoMessage() {} + +func (x *BooleanResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_applist_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BooleanResponse.ProtoReflect.Descriptor instead. +func (*BooleanResponse) Descriptor() ([]byte, []int) { + return file_grpc_applist_proto_rawDescGZIP(), []int{33} +} + +func (x *BooleanResponse) GetResult() bool { + if x != nil { + return x.Result + } + return false +} + +type RollbackReleaseRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ReleaseIdentifier *ReleaseIdentifier `protobuf:"bytes,1,opt,name=releaseIdentifier,proto3" json:"releaseIdentifier,omitempty"` + Version int32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` +} + +func (x *RollbackReleaseRequest) Reset() { + *x = RollbackReleaseRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_applist_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RollbackReleaseRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RollbackReleaseRequest) ProtoMessage() {} + +func (x *RollbackReleaseRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_applist_proto_msgTypes[34] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RollbackReleaseRequest.ProtoReflect.Descriptor instead. +func (*RollbackReleaseRequest) Descriptor() ([]byte, []int) { + return file_grpc_applist_proto_rawDescGZIP(), []int{34} +} + +func (x *RollbackReleaseRequest) GetReleaseIdentifier() *ReleaseIdentifier { + if x != nil { + return x.ReleaseIdentifier + } + return nil +} + +func (x *RollbackReleaseRequest) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + var File_grpc_applist_proto protoreflect.FileDescriptor var file_grpc_applist_proto_rawDesc = []byte{ @@ -2290,7 +2401,7 @@ var file_grpc_applist_proto_rawDesc = []byte{ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0xa1, 0x01, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, + 0x6f, 0x6e, 0x22, 0xb7, 0x01, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, @@ -2300,269 +2411,288 @@ var file_grpc_applist_proto_rawDesc = []byte{ 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6b, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, - 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x0b, 0x70, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x50, 0x6f, 0x64, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x70, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x22, 0xa4, 0x03, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, - 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x0a, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x52, 0x0a, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x6e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0e, 0x6e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x0a, 0x0f, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, - 0x69, 0x73, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, - 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x61, 0x6e, 0x42, 0x65, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, - 0x74, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x61, 0x6e, 0x42, 0x65, - 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x22, 0x40, 0x0a, 0x0c, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x90, 0x01, 0x0a, - 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, - 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0x95, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x12, - 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, - 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x91, 0x01, 0x0a, 0x0b, 0x50, 0x6f, 0x64, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x1e, 0x0a, - 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, - 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x73, 0x4e, 0x65, 0x77, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x69, 0x73, 0x4e, 0x65, 0x77, 0x22, 0x87, 0x01, 0x0a, 0x10, - 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x88, 0x01, 0x0a, 0x10, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x22, 0x6b, 0x0a, 0x14, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x0b, 0x70, 0x6f, 0x64, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x50, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x70, 0x6f, + 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xa4, 0x03, 0x0a, 0x0c, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x22, 0x7e, 0x0a, 0x0f, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x0c, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, - 0x22, 0x3d, 0x0a, 0x11, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0xc9, 0x01, 0x0a, 0x17, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x34, 0x0a, 0x0d, 0x63, - 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x49, - 0x6d, 0x61, 0x67, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x3a, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x74, 0x22, 0x62, 0x0a, 0x18, 0x48, - 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, - 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x11, 0x64, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, - 0xd9, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x40, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x11, - 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, - 0x22, 0x0a, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x64, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x0d, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, - 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, + 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, + 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x66, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, + 0x12, 0x3f, 0x0a, 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, + 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x06, 0x68, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x68, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x73, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, + 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x48, 0x69, 0x62, 0x65, + 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x61, 0x6e, 0x42, 0x65, 0x48, + 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0f, 0x63, 0x61, 0x6e, 0x42, 0x65, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x64, + 0x22, 0x40, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3b, 0x0a, + 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, + 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x95, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x91, 0x01, + 0x0a, 0x0b, 0x50, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x75, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x69, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, + 0x73, 0x4e, 0x65, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x69, 0x73, 0x4e, 0x65, + 0x77, 0x22, 0x87, 0x01, 0x0a, 0x10, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x10, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x88, 0x01, 0x0a, 0x10, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x52, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, - 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x22, 0x35, 0x0a, 0x17, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, - 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, - 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, - 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x18, 0x55, 0x6e, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x97, 0x01, - 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, + 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x7e, 0x0a, 0x0f, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, + 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x22, 0x3d, 0x0a, 0x11, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x48, 0x69, + 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x17, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, + 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x6f, 0x63, 0x6b, 0x65, + 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x64, + 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, + 0x64, 0x41, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, + 0x74, 0x22, 0x62, 0x0a, 0x18, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x46, 0x0a, + 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x48, 0x65, 0x6c, 0x6d, 0x41, + 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x52, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0xd9, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x40, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, + 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x52, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, + 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x26, 0x0a, + 0x0e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x64, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x72, + 0x67, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, + 0x64, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, + 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x0d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x72, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x79, 0x0a, 0x15, 0x55, 0x70, 0x67, 0x72, 0x61, - 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, - 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, - 0x6d, 0x6c, 0x22, 0x32, 0x0a, 0x16, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, - 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x17, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x18, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x22, 0x6f, 0x0a, 0x0f, 0x43, 0x68, - 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0xf7, 0x01, 0x0a, 0x15, - 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, - 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x3a, 0x0a, 0x0f, 0x63, 0x68, 0x61, - 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x52, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x32, 0x0a, 0x16, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x32, 0x9b, 0x06, 0x0a, 0x12, 0x41, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x39, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0f, 0x2e, 0x41, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, - 0x41, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2f, 0x0a, 0x0c, 0x47, - 0x65, 0x74, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x11, 0x2e, 0x41, 0x70, - 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0a, - 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x09, - 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x48, 0x69, 0x62, 0x65, - 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x48, - 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0b, 0x55, 0x6e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, - 0x65, 0x12, 0x11, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x14, 0x47, 0x65, - 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x48, 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, - 0x22, 0x00, 0x12, 0x32, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, - 0x61, 0x6d, 0x6c, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x65, 0x73, - 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x2e, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x44, - 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x10, 0x55, 0x6e, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x12, 0x2e, 0x52, + 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x10, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x35, 0x0a, 0x17, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, + 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a, + 0x18, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x79, 0x0a, + 0x15, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x22, 0x32, 0x0a, 0x16, 0x55, 0x70, 0x67, 0x72, + 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x89, 0x01, 0x0a, + 0x17, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x11, 0x64, 0x65, + 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x18, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, + 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, + 0x22, 0x6f, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, + 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, + 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x22, 0xf7, 0x01, 0x0a, 0x15, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x1a, 0x19, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, - 0x0e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, - 0x16, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, - 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x18, 0x2e, 0x44, 0x65, 0x70, 0x6c, - 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x43, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x12, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x1b, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, - 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x57, 0x69, 0x74, 0x68, 0x43, 0x68, 0x61, 0x72, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x55, - 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, 0x76, 0x74, 0x72, 0x6f, 0x6e, 0x2d, 0x6c, 0x61, - 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x68, 0x65, 0x6c, 0x6d, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x2f, 0x62, 0x65, 0x61, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1c, 0x0a, + 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x63, 0x68, 0x61, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, + 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, + 0x3a, 0x0a, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x0f, 0x63, 0x68, 0x61, 0x72, + 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x32, 0x0a, 0x16, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, + 0x29, 0x0a, 0x0f, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x74, 0x0a, 0x16, 0x52, 0x6f, + 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x32, 0x99, 0x07, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0f, 0x2e, 0x41, 0x70, + 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x44, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x41, 0x70, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x2f, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0a, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x09, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, + 0x12, 0x11, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0b, 0x55, 0x6e, 0x48, + 0x69, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x48, 0x69, 0x62, 0x65, 0x72, + 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x48, 0x69, + 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x46, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, 0x44, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x48, + 0x65, 0x6c, 0x6d, 0x41, 0x70, 0x70, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x0d, 0x47, 0x65, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x11, 0x2e, 0x41, 0x70, 0x70, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, + 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x40, 0x0a, + 0x12, 0x47, 0x65, 0x74, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, 0x69, 0x66, + 0x65, 0x73, 0x74, 0x12, 0x0e, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x43, 0x0a, 0x10, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x12, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x19, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x16, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, + 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x13, 0x47, 0x65, 0x74, + 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, + 0x12, 0x18, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x16, 0x2e, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x1b, + 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x57, 0x69, + 0x74, 0x68, 0x43, 0x68, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, + 0x0a, 0x12, 0x49, 0x73, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x1a, 0x10, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x65, + 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0f, + 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, + 0x17, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x65, + 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x33, 0x5a, 0x31, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, 0x76, 0x74, 0x72, + 0x6f, 0x6e, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x6c, 0x69, 0x6e, 0x6b, + 0x2f, 0x62, 0x65, 0x61, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2577,7 +2707,7 @@ func file_grpc_applist_proto_rawDescGZIP() []byte { return file_grpc_applist_proto_rawDescData } -var file_grpc_applist_proto_msgTypes = make([]protoimpl.MessageInfo, 34) +var file_grpc_applist_proto_msgTypes = make([]protoimpl.MessageInfo, 36) var file_grpc_applist_proto_goTypes = []interface{}{ (*ClusterConfig)(nil), // 0: ClusterConfig (*AppListRequest)(nil), // 1: AppListRequest @@ -2612,17 +2742,19 @@ var file_grpc_applist_proto_goTypes = []interface{}{ (*ChartRepository)(nil), // 30: ChartRepository (*InstallReleaseRequest)(nil), // 31: InstallReleaseRequest (*InstallReleaseResponse)(nil), // 32: InstallReleaseResponse - nil, // 33: ResourceNetworkingInfo.LabelsEntry - (*timestamp.Timestamp)(nil), // 34: google.protobuf.Timestamp + (*BooleanResponse)(nil), // 33: BooleanResponse + (*RollbackReleaseRequest)(nil), // 34: RollbackReleaseRequest + nil, // 35: ResourceNetworkingInfo.LabelsEntry + (*timestamp.Timestamp)(nil), // 36: google.protobuf.Timestamp } var file_grpc_applist_proto_depIdxs = []int32{ 0, // 0: AppListRequest.clusters:type_name -> ClusterConfig 3, // 1: DeployedAppList.DeployedAppDetail:type_name -> DeployedAppDetail 4, // 2: DeployedAppDetail.environmentDetail:type_name -> EnvironmentDetails - 34, // 3: DeployedAppDetail.LastDeployed:type_name -> google.protobuf.Timestamp + 36, // 3: DeployedAppDetail.LastDeployed:type_name -> google.protobuf.Timestamp 0, // 4: AppDetailRequest.clusterConfig:type_name -> ClusterConfig 7, // 5: AppDetail.releaseStatus:type_name -> ReleaseStatus - 34, // 6: AppDetail.lastDeployed:type_name -> google.protobuf.Timestamp + 36, // 6: AppDetail.lastDeployed:type_name -> google.protobuf.Timestamp 8, // 7: AppDetail.chartMetadata:type_name -> ChartMetadata 9, // 8: AppDetail.resourceTreeResponse:type_name -> ResourceTreeResponse 4, // 9: AppDetail.environmentDetails:type_name -> EnvironmentDetails @@ -2631,13 +2763,13 @@ var file_grpc_applist_proto_depIdxs = []int32{ 13, // 12: ResourceNode.parentRefs:type_name -> ResourceRef 12, // 13: ResourceNode.networkingInfo:type_name -> ResourceNetworkingInfo 11, // 14: ResourceNode.health:type_name -> HealthStatus - 33, // 15: ResourceNetworkingInfo.labels:type_name -> ResourceNetworkingInfo.LabelsEntry + 35, // 15: ResourceNetworkingInfo.labels:type_name -> ResourceNetworkingInfo.LabelsEntry 0, // 16: HibernateRequest.clusterConfig:type_name -> ClusterConfig 16, // 17: HibernateRequest.objectIdentifier:type_name -> ObjectIdentifier 16, // 18: HibernateStatus.targetObject:type_name -> ObjectIdentifier 17, // 19: HibernateResponse.status:type_name -> HibernateStatus 8, // 20: HelmAppDeploymentDetail.chartMetadata:type_name -> ChartMetadata - 34, // 21: HelmAppDeploymentDetail.deployedAt:type_name -> google.protobuf.Timestamp + 36, // 21: HelmAppDeploymentDetail.deployedAt:type_name -> google.protobuf.Timestamp 19, // 22: HelmAppDeploymentHistory.deploymentHistory:type_name -> HelmAppDeploymentDetail 3, // 23: ReleaseInfo.deployedAppDetail:type_name -> DeployedAppDetail 0, // 24: ObjectRequest.clusterConfig:type_name -> ClusterConfig @@ -2647,35 +2779,40 @@ var file_grpc_applist_proto_depIdxs = []int32{ 25, // 28: DeploymentDetailRequest.releaseIdentifier:type_name -> ReleaseIdentifier 25, // 29: InstallReleaseRequest.releaseIdentifier:type_name -> ReleaseIdentifier 30, // 30: InstallReleaseRequest.chartRepository:type_name -> ChartRepository - 1, // 31: ApplicationService.ListApplications:input_type -> AppListRequest - 5, // 32: ApplicationService.GetAppDetail:input_type -> AppDetailRequest - 15, // 33: ApplicationService.Hibernate:input_type -> HibernateRequest - 15, // 34: ApplicationService.UnHibernate:input_type -> HibernateRequest - 5, // 35: ApplicationService.GetDeploymentHistory:input_type -> AppDetailRequest - 5, // 36: ApplicationService.GetValuesYaml:input_type -> AppDetailRequest - 22, // 37: ApplicationService.GetDesiredManifest:input_type -> ObjectRequest - 25, // 38: ApplicationService.UninstallRelease:input_type -> ReleaseIdentifier - 26, // 39: ApplicationService.UpgradeRelease:input_type -> UpgradeReleaseRequest - 28, // 40: ApplicationService.GetDeploymentDetail:input_type -> DeploymentDetailRequest - 31, // 41: ApplicationService.InstallRelease:input_type -> InstallReleaseRequest - 31, // 42: ApplicationService.UpgradeReleaseWithChartInfo:input_type -> InstallReleaseRequest - 2, // 43: ApplicationService.ListApplications:output_type -> DeployedAppList - 6, // 44: ApplicationService.GetAppDetail:output_type -> AppDetail - 18, // 45: ApplicationService.Hibernate:output_type -> HibernateResponse - 18, // 46: ApplicationService.UnHibernate:output_type -> HibernateResponse - 20, // 47: ApplicationService.GetDeploymentHistory:output_type -> HelmAppDeploymentHistory - 21, // 48: ApplicationService.GetValuesYaml:output_type -> ReleaseInfo - 23, // 49: ApplicationService.GetDesiredManifest:output_type -> DesiredManifestResponse - 24, // 50: ApplicationService.UninstallRelease:output_type -> UninstallReleaseResponse - 27, // 51: ApplicationService.UpgradeRelease:output_type -> UpgradeReleaseResponse - 29, // 52: ApplicationService.GetDeploymentDetail:output_type -> DeploymentDetailResponse - 32, // 53: ApplicationService.InstallRelease:output_type -> InstallReleaseResponse - 27, // 54: ApplicationService.UpgradeReleaseWithChartInfo:output_type -> UpgradeReleaseResponse - 43, // [43:55] is the sub-list for method output_type - 31, // [31:43] is the sub-list for method input_type - 31, // [31:31] is the sub-list for extension type_name - 31, // [31:31] is the sub-list for extension extendee - 0, // [0:31] is the sub-list for field type_name + 25, // 31: RollbackReleaseRequest.releaseIdentifier:type_name -> ReleaseIdentifier + 1, // 32: ApplicationService.ListApplications:input_type -> AppListRequest + 5, // 33: ApplicationService.GetAppDetail:input_type -> AppDetailRequest + 15, // 34: ApplicationService.Hibernate:input_type -> HibernateRequest + 15, // 35: ApplicationService.UnHibernate:input_type -> HibernateRequest + 5, // 36: ApplicationService.GetDeploymentHistory:input_type -> AppDetailRequest + 5, // 37: ApplicationService.GetValuesYaml:input_type -> AppDetailRequest + 22, // 38: ApplicationService.GetDesiredManifest:input_type -> ObjectRequest + 25, // 39: ApplicationService.UninstallRelease:input_type -> ReleaseIdentifier + 26, // 40: ApplicationService.UpgradeRelease:input_type -> UpgradeReleaseRequest + 28, // 41: ApplicationService.GetDeploymentDetail:input_type -> DeploymentDetailRequest + 31, // 42: ApplicationService.InstallRelease:input_type -> InstallReleaseRequest + 31, // 43: ApplicationService.UpgradeReleaseWithChartInfo:input_type -> InstallReleaseRequest + 25, // 44: ApplicationService.IsReleaseInstalled:input_type -> ReleaseIdentifier + 34, // 45: ApplicationService.RollbackRelease:input_type -> RollbackReleaseRequest + 2, // 46: ApplicationService.ListApplications:output_type -> DeployedAppList + 6, // 47: ApplicationService.GetAppDetail:output_type -> AppDetail + 18, // 48: ApplicationService.Hibernate:output_type -> HibernateResponse + 18, // 49: ApplicationService.UnHibernate:output_type -> HibernateResponse + 20, // 50: ApplicationService.GetDeploymentHistory:output_type -> HelmAppDeploymentHistory + 21, // 51: ApplicationService.GetValuesYaml:output_type -> ReleaseInfo + 23, // 52: ApplicationService.GetDesiredManifest:output_type -> DesiredManifestResponse + 24, // 53: ApplicationService.UninstallRelease:output_type -> UninstallReleaseResponse + 27, // 54: ApplicationService.UpgradeRelease:output_type -> UpgradeReleaseResponse + 29, // 55: ApplicationService.GetDeploymentDetail:output_type -> DeploymentDetailResponse + 32, // 56: ApplicationService.InstallRelease:output_type -> InstallReleaseResponse + 27, // 57: ApplicationService.UpgradeReleaseWithChartInfo:output_type -> UpgradeReleaseResponse + 33, // 58: ApplicationService.IsReleaseInstalled:output_type -> BooleanResponse + 33, // 59: ApplicationService.RollbackRelease:output_type -> BooleanResponse + 46, // [46:60] is the sub-list for method output_type + 32, // [32:46] is the sub-list for method input_type + 32, // [32:32] is the sub-list for extension type_name + 32, // [32:32] is the sub-list for extension extendee + 0, // [0:32] is the sub-list for field type_name } func init() { file_grpc_applist_proto_init() } @@ -3080,6 +3217,30 @@ func file_grpc_applist_proto_init() { return nil } } + file_grpc_applist_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BooleanResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_applist_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RollbackReleaseRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -3087,7 +3248,7 @@ func file_grpc_applist_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_grpc_applist_proto_rawDesc, NumEnums: 0, - NumMessages: 34, + NumMessages: 36, NumExtensions: 0, NumServices: 1, }, diff --git a/api/helm-app/applist.proto b/api/helm-app/applist.proto index 8e60c32b01..11dd0fc591 100644 --- a/api/helm-app/applist.proto +++ b/api/helm-app/applist.proto @@ -3,7 +3,7 @@ syntax = "proto3"; import "google/protobuf/timestamp.proto"; -option go_package = "github.com/devtron-labs/go-helm-client/bean/grpc/client"; +option go_package = "github.com/devtron-labs/kubelink/bean/grpc/client"; message ClusterConfig { string apiServerUrl = 1; @@ -29,6 +29,8 @@ service ApplicationService { rpc GetDeploymentDetail(DeploymentDetailRequest) returns (DeploymentDetailResponse){} rpc InstallRelease(InstallReleaseRequest) returns (InstallReleaseResponse){} rpc UpgradeReleaseWithChartInfo(InstallReleaseRequest) returns (UpgradeReleaseResponse){} + rpc IsReleaseInstalled(ReleaseIdentifier) returns (BooleanResponse){} + rpc RollbackRelease(RollbackReleaseRequest) returns (BooleanResponse){} } message DeployedAppList { @@ -82,6 +84,8 @@ message ChartMetadata { string home = 3; repeated string sources = 4; string description = 5; + // Contains the rendered templates/NOTES.txt + string notes = 6; } message ResourceTreeResponse { @@ -231,4 +235,13 @@ message InstallReleaseRequest { message InstallReleaseResponse { bool success = 1; +} + +message BooleanResponse { + bool result = 1; +} + +message RollbackReleaseRequest { + ReleaseIdentifier releaseIdentifier = 1; + int32 version = 2; } \ No newline at end of file diff --git a/api/helm-app/applist_grpc.pb.go b/api/helm-app/applist_grpc.pb.go index a80b3f45b5..8d13f3891a 100644 --- a/api/helm-app/applist_grpc.pb.go +++ b/api/helm-app/applist_grpc.pb.go @@ -34,6 +34,8 @@ type ApplicationServiceClient interface { GetDeploymentDetail(ctx context.Context, in *DeploymentDetailRequest, opts ...grpc.CallOption) (*DeploymentDetailResponse, error) InstallRelease(ctx context.Context, in *InstallReleaseRequest, opts ...grpc.CallOption) (*InstallReleaseResponse, error) UpgradeReleaseWithChartInfo(ctx context.Context, in *InstallReleaseRequest, opts ...grpc.CallOption) (*UpgradeReleaseResponse, error) + IsReleaseInstalled(ctx context.Context, in *ReleaseIdentifier, opts ...grpc.CallOption) (*BooleanResponse, error) + RollbackRelease(ctx context.Context, in *RollbackReleaseRequest, opts ...grpc.CallOption) (*BooleanResponse, error) } type applicationServiceClient struct { @@ -175,6 +177,24 @@ func (c *applicationServiceClient) UpgradeReleaseWithChartInfo(ctx context.Conte return out, nil } +func (c *applicationServiceClient) IsReleaseInstalled(ctx context.Context, in *ReleaseIdentifier, opts ...grpc.CallOption) (*BooleanResponse, error) { + out := new(BooleanResponse) + err := c.cc.Invoke(ctx, "/ApplicationService/IsReleaseInstalled", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *applicationServiceClient) RollbackRelease(ctx context.Context, in *RollbackReleaseRequest, opts ...grpc.CallOption) (*BooleanResponse, error) { + out := new(BooleanResponse) + err := c.cc.Invoke(ctx, "/ApplicationService/RollbackRelease", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ApplicationServiceServer is the server API for ApplicationService service. // All implementations must embed UnimplementedApplicationServiceServer // for forward compatibility @@ -191,6 +211,8 @@ type ApplicationServiceServer interface { GetDeploymentDetail(context.Context, *DeploymentDetailRequest) (*DeploymentDetailResponse, error) InstallRelease(context.Context, *InstallReleaseRequest) (*InstallReleaseResponse, error) UpgradeReleaseWithChartInfo(context.Context, *InstallReleaseRequest) (*UpgradeReleaseResponse, error) + IsReleaseInstalled(context.Context, *ReleaseIdentifier) (*BooleanResponse, error) + RollbackRelease(context.Context, *RollbackReleaseRequest) (*BooleanResponse, error) mustEmbedUnimplementedApplicationServiceServer() } @@ -234,6 +256,12 @@ func (UnimplementedApplicationServiceServer) InstallRelease(context.Context, *In func (UnimplementedApplicationServiceServer) UpgradeReleaseWithChartInfo(context.Context, *InstallReleaseRequest) (*UpgradeReleaseResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpgradeReleaseWithChartInfo not implemented") } +func (UnimplementedApplicationServiceServer) IsReleaseInstalled(context.Context, *ReleaseIdentifier) (*BooleanResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method IsReleaseInstalled not implemented") +} +func (UnimplementedApplicationServiceServer) RollbackRelease(context.Context, *RollbackReleaseRequest) (*BooleanResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RollbackRelease not implemented") +} func (UnimplementedApplicationServiceServer) mustEmbedUnimplementedApplicationServiceServer() {} // UnsafeApplicationServiceServer may be embedded to opt out of forward compatibility for this service. @@ -466,6 +494,42 @@ func _ApplicationService_UpgradeReleaseWithChartInfo_Handler(srv interface{}, ct return interceptor(ctx, in, info, handler) } +func _ApplicationService_IsReleaseInstalled_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReleaseIdentifier) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ApplicationServiceServer).IsReleaseInstalled(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ApplicationService/IsReleaseInstalled", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ApplicationServiceServer).IsReleaseInstalled(ctx, req.(*ReleaseIdentifier)) + } + return interceptor(ctx, in, info, handler) +} + +func _ApplicationService_RollbackRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RollbackReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ApplicationServiceServer).RollbackRelease(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ApplicationService/RollbackRelease", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ApplicationServiceServer).RollbackRelease(ctx, req.(*RollbackReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ApplicationService_ServiceDesc is the grpc.ServiceDesc for ApplicationService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -517,6 +581,14 @@ var ApplicationService_ServiceDesc = grpc.ServiceDesc{ MethodName: "UpgradeReleaseWithChartInfo", Handler: _ApplicationService_UpgradeReleaseWithChartInfo_Handler, }, + { + MethodName: "IsReleaseInstalled", + Handler: _ApplicationService_IsReleaseInstalled_Handler, + }, + { + MethodName: "RollbackRelease", + Handler: _ApplicationService_RollbackRelease_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/api/helm-app/openapiClient/api_default.go b/api/helm-app/openapiClient/api_default.go index 4f1b8feaa8..2410954349 100644 --- a/api/helm-app/openapiClient/api_default.go +++ b/api/helm-app/openapiClient/api_default.go @@ -13,7 +13,6 @@ package openapi import ( "bytes" _context "context" - "golang.org/x/net/context" _ioutil "io/ioutil" _nethttp "net/http" _neturl "net/url" @@ -29,15 +28,15 @@ var ( type DefaultApiService service type ApiOrchestratorAppListGetRequest struct { - ctx _context.Context - ApiService *DefaultApiService - projectIds *[]int32 - clusterIds *[]int32 + ctx _context.Context + ApiService *DefaultApiService + projectIds *[]int32 + clusterIds *[]int32 environmentIds *[]int32 - offset *int32 - size *int32 - sortOrder *string - sortBy *string + offset *int32 + size *int32 + sortOrder *string + sortBy *string } // project ids @@ -45,37 +44,31 @@ func (r ApiOrchestratorAppListGetRequest) ProjectIds(projectIds []int32) ApiOrch r.projectIds = &projectIds return r } - // cluster ids func (r ApiOrchestratorAppListGetRequest) ClusterIds(clusterIds []int32) ApiOrchestratorAppListGetRequest { r.clusterIds = &clusterIds return r } - // environment ids func (r ApiOrchestratorAppListGetRequest) EnvironmentIds(environmentIds []int32) ApiOrchestratorAppListGetRequest { r.environmentIds = &environmentIds return r } - // offser func (r ApiOrchestratorAppListGetRequest) Offset(offset int32) ApiOrchestratorAppListGetRequest { r.offset = &offset return r } - // size func (r ApiOrchestratorAppListGetRequest) Size(size int32) ApiOrchestratorAppListGetRequest { r.size = &size return r } - // sortOrder func (r ApiOrchestratorAppListGetRequest) SortOrder(sortOrder string) ApiOrchestratorAppListGetRequest { r.sortOrder = &sortOrder return r } - // sortBy func (r ApiOrchestratorAppListGetRequest) SortBy(sortBy string) ApiOrchestratorAppListGetRequest { r.sortBy = &sortBy @@ -97,7 +90,7 @@ this api gives all devtron applications. func (a *DefaultApiService) OrchestratorAppListGet(ctx _context.Context) ApiOrchestratorAppListGetRequest { return ApiOrchestratorAppListGetRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -105,10 +98,10 @@ func (a *DefaultApiService) OrchestratorAppListGet(ctx _context.Context) ApiOrch // @return AppList func (a *DefaultApiService) OrchestratorAppListGetExecute(r ApiOrchestratorAppListGetRequest) (AppList, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodGet - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue AppList + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue AppList ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorAppListGet") @@ -235,16 +228,16 @@ func (a *DefaultApiService) OrchestratorAppListGetExecute(r ApiOrchestratorAppLi } type ApiOrchestratorAppStoreInstalledAppsGetRequest struct { - ctx _context.Context - ApiService *DefaultApiService - envIds *[]int32 - clusterIds *[]int32 + ctx _context.Context + ApiService *DefaultApiService + envIds *[]int32 + clusterIds *[]int32 onlyDeprecated *bool - chartRepoIds *int32 - offset *int32 - size *int32 - appStoreName *string - sortBy *string + chartRepoIds *int32 + offset *int32 + size *int32 + appStoreName *string + sortBy *string } // environment ids @@ -252,43 +245,36 @@ func (r ApiOrchestratorAppStoreInstalledAppsGetRequest) EnvIds(envIds []int32) A r.envIds = &envIds return r } - // cluster ids func (r ApiOrchestratorAppStoreInstalledAppsGetRequest) ClusterIds(clusterIds []int32) ApiOrchestratorAppStoreInstalledAppsGetRequest { r.clusterIds = &clusterIds return r } - // deprecated flag func (r ApiOrchestratorAppStoreInstalledAppsGetRequest) OnlyDeprecated(onlyDeprecated bool) ApiOrchestratorAppStoreInstalledAppsGetRequest { r.onlyDeprecated = &onlyDeprecated return r } - // size func (r ApiOrchestratorAppStoreInstalledAppsGetRequest) ChartRepoIds(chartRepoIds int32) ApiOrchestratorAppStoreInstalledAppsGetRequest { r.chartRepoIds = &chartRepoIds return r } - // offser func (r ApiOrchestratorAppStoreInstalledAppsGetRequest) Offset(offset int32) ApiOrchestratorAppStoreInstalledAppsGetRequest { r.offset = &offset return r } - // size func (r ApiOrchestratorAppStoreInstalledAppsGetRequest) Size(size int32) ApiOrchestratorAppStoreInstalledAppsGetRequest { r.size = &size return r } - // app store name func (r ApiOrchestratorAppStoreInstalledAppsGetRequest) AppStoreName(appStoreName string) ApiOrchestratorAppStoreInstalledAppsGetRequest { r.appStoreName = &appStoreName return r } - // app name func (r ApiOrchestratorAppStoreInstalledAppsGetRequest) SortBy(sortBy string) ApiOrchestratorAppStoreInstalledAppsGetRequest { r.sortBy = &sortBy @@ -310,7 +296,7 @@ this api gives all chart-store applications. func (a *DefaultApiService) OrchestratorAppStoreInstalledAppsGet(ctx _context.Context) ApiOrchestratorAppStoreInstalledAppsGetRequest { return ApiOrchestratorAppStoreInstalledAppsGetRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -318,10 +304,10 @@ func (a *DefaultApiService) OrchestratorAppStoreInstalledAppsGet(ctx _context.Co // @return AppList func (a *DefaultApiService) OrchestratorAppStoreInstalledAppsGetExecute(r ApiOrchestratorAppStoreInstalledAppsGetRequest) (AppList, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodGet - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue AppList + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue AppList ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorAppStoreInstalledAppsGet") @@ -442,10 +428,11 @@ func (a *DefaultApiService) OrchestratorAppStoreInstalledAppsGetExecute(r ApiOrc } type ApiOrchestratorApplicationClusterEnvDetailsGetRequest struct { - ctx _context.Context + ctx _context.Context ApiService *DefaultApiService } + func (r ApiOrchestratorApplicationClusterEnvDetailsGetRequest) Execute() ([]ClusterEnvironmentDetail, *_nethttp.Response, error) { return r.ApiService.OrchestratorApplicationClusterEnvDetailsGetExecute(r) } @@ -461,7 +448,7 @@ returns cluster environment namespace mappings func (a *DefaultApiService) OrchestratorApplicationClusterEnvDetailsGet(ctx _context.Context) ApiOrchestratorApplicationClusterEnvDetailsGetRequest { return ApiOrchestratorApplicationClusterEnvDetailsGetRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -469,10 +456,10 @@ func (a *DefaultApiService) OrchestratorApplicationClusterEnvDetailsGet(ctx _con // @return []ClusterEnvironmentDetail func (a *DefaultApiService) OrchestratorApplicationClusterEnvDetailsGetExecute(r ApiOrchestratorApplicationClusterEnvDetailsGetRequest) ([]ClusterEnvironmentDetail, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodGet - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue []ClusterEnvironmentDetail + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []ClusterEnvironmentDetail ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationClusterEnvDetailsGet") @@ -541,9 +528,9 @@ func (a *DefaultApiService) OrchestratorApplicationClusterEnvDetailsGetExecute(r } type ApiOrchestratorApplicationDeleteDeleteRequest struct { - ctx _context.Context + ctx _context.Context ApiService *DefaultApiService - appId *string + appId *string } // application Id @@ -567,7 +554,7 @@ delete application func (a *DefaultApiService) OrchestratorApplicationDeleteDelete(ctx _context.Context) ApiOrchestratorApplicationDeleteDeleteRequest { return ApiOrchestratorApplicationDeleteDeleteRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -575,10 +562,10 @@ func (a *DefaultApiService) OrchestratorApplicationDeleteDelete(ctx _context.Con // @return UninstallReleaseResponse func (a *DefaultApiService) OrchestratorApplicationDeleteDeleteExecute(r ApiOrchestratorApplicationDeleteDeleteRequest) (UninstallReleaseResponse, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodDelete - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue UninstallReleaseResponse + localVarHTTPMethod = _nethttp.MethodDelete + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue UninstallReleaseResponse ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationDeleteDelete") @@ -631,7 +618,7 @@ func (a *DefaultApiService) OrchestratorApplicationDeleteDeleteExecute(r ApiOrch } if localVarHTTPResponse.StatusCode >= 300 { - newErr := &GenericOpenAPIError{ + newErr := GenericOpenAPIError{ body: localVarBody, error: localVarHTTPResponse.Status, } @@ -640,7 +627,7 @@ func (a *DefaultApiService) OrchestratorApplicationDeleteDeleteExecute(r ApiOrch err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { - newErr := &GenericOpenAPIError{ + newErr := GenericOpenAPIError{ body: localVarBody, error: err.Error(), } @@ -651,10 +638,10 @@ func (a *DefaultApiService) OrchestratorApplicationDeleteDeleteExecute(r ApiOrch } type ApiOrchestratorApplicationDeploymentDetailGetRequest struct { - ctx context.Context + ctx _context.Context ApiService *DefaultApiService - appId *string - version *int32 + appId *string + version *int32 } // project ids @@ -662,14 +649,13 @@ func (r ApiOrchestratorApplicationDeploymentDetailGetRequest) AppId(appId string r.appId = &appId return r } - // deployment version func (r ApiOrchestratorApplicationDeploymentDetailGetRequest) Version(version int32) ApiOrchestratorApplicationDeploymentDetailGetRequest { r.version = &version return r } -func (r ApiOrchestratorApplicationDeploymentDetailGetRequest) Execute() (*HelmAppDeploymentManifestDetail, *_nethttp.Response, error) { +func (r ApiOrchestratorApplicationDeploymentDetailGetRequest) Execute() (HelmAppDeploymentManifestDetail, *_nethttp.Response, error) { return r.ApiService.OrchestratorApplicationDeploymentDetailGetExecute(r) } @@ -678,29 +664,29 @@ OrchestratorApplicationDeploymentDetailGet Method for OrchestratorApplicationDep deployment details of helm app - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @return ApiOrchestratorApplicationDeploymentDetailGetRequest */ -func (a *DefaultApiService) OrchestratorApplicationDeploymentDetailGet(ctx context.Context) ApiOrchestratorApplicationDeploymentDetailGetRequest { +func (a *DefaultApiService) OrchestratorApplicationDeploymentDetailGet(ctx _context.Context) ApiOrchestratorApplicationDeploymentDetailGetRequest { return ApiOrchestratorApplicationDeploymentDetailGetRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } // Execute executes the request // @return HelmAppDeploymentManifestDetail -func (a *DefaultApiService) OrchestratorApplicationDeploymentDetailGetExecute(r ApiOrchestratorApplicationDeploymentDetailGetRequest) (*HelmAppDeploymentManifestDetail, *_nethttp.Response, error) { +func (a *DefaultApiService) OrchestratorApplicationDeploymentDetailGetExecute(r ApiOrchestratorApplicationDeploymentDetailGetRequest) (HelmAppDeploymentManifestDetail, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodGet - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue *HelmAppDeploymentManifestDetail + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue HelmAppDeploymentManifestDetail ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationDeploymentDetailGet") if err != nil { - return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} } localVarPath := localBasePath + "/orchestrator/application/deployment-detail" @@ -772,9 +758,9 @@ func (a *DefaultApiService) OrchestratorApplicationDeploymentDetailGetExecute(r } type ApiOrchestratorApplicationDeploymentHistoryGetRequest struct { - ctx _context.Context + ctx _context.Context ApiService *DefaultApiService - appId *string + appId *string } // project ids @@ -798,7 +784,7 @@ deployment history of helm app func (a *DefaultApiService) OrchestratorApplicationDeploymentHistoryGet(ctx _context.Context) ApiOrchestratorApplicationDeploymentHistoryGetRequest { return ApiOrchestratorApplicationDeploymentHistoryGetRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -806,10 +792,10 @@ func (a *DefaultApiService) OrchestratorApplicationDeploymentHistoryGet(ctx _con // @return []HelmAppDeploymentDetail func (a *DefaultApiService) OrchestratorApplicationDeploymentHistoryGetExecute(r ApiOrchestratorApplicationDeploymentHistoryGetRequest) ([]HelmAppDeploymentDetail, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodGet - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue []HelmAppDeploymentDetail + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []HelmAppDeploymentDetail ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationDeploymentHistoryGet") @@ -882,8 +868,8 @@ func (a *DefaultApiService) OrchestratorApplicationDeploymentHistoryGetExecute(r } type ApiOrchestratorApplicationDesiredManifestGetRequest struct { - ctx _context.Context - ApiService *DefaultApiService + ctx _context.Context + ApiService *DefaultApiService desiredManifestRequest *DesiredManifestRequest } @@ -907,7 +893,7 @@ get desired manifest for an object func (a *DefaultApiService) OrchestratorApplicationDesiredManifestGet(ctx _context.Context) ApiOrchestratorApplicationDesiredManifestGetRequest { return ApiOrchestratorApplicationDesiredManifestGetRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -915,10 +901,10 @@ func (a *DefaultApiService) OrchestratorApplicationDesiredManifestGet(ctx _conte // @return []DesiredManifestResponse func (a *DefaultApiService) OrchestratorApplicationDesiredManifestGetExecute(r ApiOrchestratorApplicationDesiredManifestGetRequest) ([]DesiredManifestResponse, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodGet - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue []DesiredManifestResponse + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []DesiredManifestResponse ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationDesiredManifestGet") @@ -989,8 +975,8 @@ func (a *DefaultApiService) OrchestratorApplicationDesiredManifestGetExecute(r A } type ApiOrchestratorApplicationHibernatePostRequest struct { - ctx _context.Context - ApiService *DefaultApiService + ctx _context.Context + ApiService *DefaultApiService hibernateRequest *HibernateRequest } @@ -1014,7 +1000,7 @@ hibernate the app func (a *DefaultApiService) OrchestratorApplicationHibernatePost(ctx _context.Context) ApiOrchestratorApplicationHibernatePostRequest { return ApiOrchestratorApplicationHibernatePostRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -1022,10 +1008,10 @@ func (a *DefaultApiService) OrchestratorApplicationHibernatePost(ctx _context.Co // @return []HibernateStatus func (a *DefaultApiService) OrchestratorApplicationHibernatePostExecute(r ApiOrchestratorApplicationHibernatePostRequest) ([]HibernateStatus, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodPost - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue []HibernateStatus + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []HibernateStatus ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationHibernatePost") @@ -1096,8 +1082,8 @@ func (a *DefaultApiService) OrchestratorApplicationHibernatePostExecute(r ApiOrc } type ApiOrchestratorApplicationPostRequest struct { - ctx _context.Context - ApiService *DefaultApiService + ctx _context.Context + ApiService *DefaultApiService helmAppListRequest *HelmAppListRequest } @@ -1122,7 +1108,7 @@ this api gives all external application+ devtron helm chart applications. func (a *DefaultApiService) OrchestratorApplicationPost(ctx _context.Context) ApiOrchestratorApplicationPostRequest { return ApiOrchestratorApplicationPostRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -1130,10 +1116,10 @@ func (a *DefaultApiService) OrchestratorApplicationPost(ctx _context.Context) Ap // @return AppList func (a *DefaultApiService) OrchestratorApplicationPostExecute(r ApiOrchestratorApplicationPostRequest) (AppList, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodPost - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue AppList + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue AppList ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationPost") @@ -1207,9 +1193,9 @@ func (a *DefaultApiService) OrchestratorApplicationPostExecute(r ApiOrchestrator } type ApiOrchestratorApplicationReleaseInfoGetRequest struct { - ctx _context.Context + ctx _context.Context ApiService *DefaultApiService - appId *string + appId *string } // project ids @@ -1218,7 +1204,7 @@ func (r ApiOrchestratorApplicationReleaseInfoGetRequest) AppId(appId string) Api return r } -func (r ApiOrchestratorApplicationReleaseInfoGetRequest) Execute() (ReleaseInfo, *_nethttp.Response, error) { +func (r ApiOrchestratorApplicationReleaseInfoGetRequest) Execute() (ReleaseAndInstalledAppInfo, *_nethttp.Response, error) { return r.ApiService.OrchestratorApplicationReleaseInfoGetExecute(r) } @@ -1233,18 +1219,18 @@ deployment values.yaml/release-info func (a *DefaultApiService) OrchestratorApplicationReleaseInfoGet(ctx _context.Context) ApiOrchestratorApplicationReleaseInfoGetRequest { return ApiOrchestratorApplicationReleaseInfoGetRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } // Execute executes the request -// @return ReleaseInfo -func (a *DefaultApiService) OrchestratorApplicationReleaseInfoGetExecute(r ApiOrchestratorApplicationReleaseInfoGetRequest) (ReleaseInfo, *_nethttp.Response, error) { +// @return ReleaseAndInstalledAppInfo +func (a *DefaultApiService) OrchestratorApplicationReleaseInfoGetExecute(r ApiOrchestratorApplicationReleaseInfoGetRequest) (ReleaseAndInstalledAppInfo, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodGet - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue ReleaseInfo + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue ReleaseAndInstalledAppInfo ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationReleaseInfoGet") @@ -1317,8 +1303,8 @@ func (a *DefaultApiService) OrchestratorApplicationReleaseInfoGetExecute(r ApiOr } type ApiOrchestratorApplicationUnhibernatePostRequest struct { - ctx _context.Context - ApiService *DefaultApiService + ctx _context.Context + ApiService *DefaultApiService hibernateRequest *HibernateRequest } @@ -1342,7 +1328,7 @@ un hibernate the app func (a *DefaultApiService) OrchestratorApplicationUnhibernatePost(ctx _context.Context) ApiOrchestratorApplicationUnhibernatePostRequest { return ApiOrchestratorApplicationUnhibernatePostRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -1350,10 +1336,10 @@ func (a *DefaultApiService) OrchestratorApplicationUnhibernatePost(ctx _context. // @return []HibernateStatus func (a *DefaultApiService) OrchestratorApplicationUnhibernatePostExecute(r ApiOrchestratorApplicationUnhibernatePostRequest) ([]HibernateStatus, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodPost - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue []HibernateStatus + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []HibernateStatus ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationUnhibernatePost") @@ -1424,8 +1410,8 @@ func (a *DefaultApiService) OrchestratorApplicationUnhibernatePostExecute(r ApiO } type ApiOrchestratorApplicationUpdatePutRequest struct { - ctx _context.Context - ApiService *DefaultApiService + ctx _context.Context + ApiService *DefaultApiService updateReleaseRequest *UpdateReleaseRequest } @@ -1449,7 +1435,7 @@ update the application func (a *DefaultApiService) OrchestratorApplicationUpdatePut(ctx _context.Context) ApiOrchestratorApplicationUpdatePutRequest { return ApiOrchestratorApplicationUpdatePutRequest{ ApiService: a, - ctx: ctx, + ctx: ctx, } } @@ -1457,10 +1443,10 @@ func (a *DefaultApiService) OrchestratorApplicationUpdatePut(ctx _context.Contex // @return []UpdateReleaseResponse func (a *DefaultApiService) OrchestratorApplicationUpdatePutExecute(r ApiOrchestratorApplicationUpdatePutRequest) ([]UpdateReleaseResponse, *_nethttp.Response, error) { var ( - localVarHTTPMethod = _nethttp.MethodPut - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue []UpdateReleaseResponse + localVarHTTPMethod = _nethttp.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []UpdateReleaseResponse ) localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationUpdatePut") @@ -1529,3 +1515,113 @@ func (a *DefaultApiService) OrchestratorApplicationUpdatePutExecute(r ApiOrchest return localVarReturnValue, localVarHTTPResponse, nil } + +type ApiOrchestratorApplicationUpdateWithChartLinkingPutRequest struct { + ctx _context.Context + ApiService *DefaultApiService + updateReleaseWithChartLinkingRequest *UpdateReleaseWithChartLinkingRequest +} + +func (r ApiOrchestratorApplicationUpdateWithChartLinkingPutRequest) UpdateReleaseWithChartLinkingRequest(updateReleaseWithChartLinkingRequest UpdateReleaseWithChartLinkingRequest) ApiOrchestratorApplicationUpdateWithChartLinkingPutRequest { + r.updateReleaseWithChartLinkingRequest = &updateReleaseWithChartLinkingRequest + return r +} + +func (r ApiOrchestratorApplicationUpdateWithChartLinkingPutRequest) Execute() (UpdateReleaseResponse, *_nethttp.Response, error) { + return r.ApiService.OrchestratorApplicationUpdateWithChartLinkingPutExecute(r) +} + +/* +OrchestratorApplicationUpdateWithChartLinkingPut Method for OrchestratorApplicationUpdateWithChartLinkingPut + +update the application with chartstore linking + + @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiOrchestratorApplicationUpdateWithChartLinkingPutRequest +*/ +func (a *DefaultApiService) OrchestratorApplicationUpdateWithChartLinkingPut(ctx _context.Context) ApiOrchestratorApplicationUpdateWithChartLinkingPutRequest { + return ApiOrchestratorApplicationUpdateWithChartLinkingPutRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return UpdateReleaseResponse +func (a *DefaultApiService) OrchestratorApplicationUpdateWithChartLinkingPutExecute(r ApiOrchestratorApplicationUpdateWithChartLinkingPutRequest) (UpdateReleaseResponse, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPut + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue UpdateReleaseResponse + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.OrchestratorApplicationUpdateWithChartLinkingPut") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/orchestrator/application/update-with-chart-linking" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + if r.updateReleaseWithChartLinkingRequest == nil { + return localVarReturnValue, nil, reportError("updateReleaseWithChartLinkingRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.updateReleaseWithChartLinkingRequest + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/api/helm-app/openapiClient/model_helm_app.go b/api/helm-app/openapiClient/model_helm_app.go index 1c4bde3382..938676b107 100644 --- a/api/helm-app/openapiClient/model_helm_app.go +++ b/api/helm-app/openapiClient/model_helm_app.go @@ -28,7 +28,9 @@ type HelmApp struct { // url/location of the chart icon ChartAvatar *string `json:"chartAvatar,omitempty"` // unique identifier for the project, APP with no project will have id `0` - ProjectId *int32 `json:"projectId,omitempty"` + ProjectId *int32 `json:"projectId,omitempty"` + // chart version + ChartVersion *string `json:"chartVersion,omitempty"` EnvironmentDetail *AppEnvironmentDetail `json:"environmentDetail,omitempty"` } @@ -241,6 +243,38 @@ func (o *HelmApp) SetProjectId(v int32) { o.ProjectId = &v } +// GetChartVersion returns the ChartVersion field value if set, zero value otherwise. +func (o *HelmApp) GetChartVersion() string { + if o == nil || o.ChartVersion == nil { + var ret string + return ret + } + return *o.ChartVersion +} + +// GetChartVersionOk returns a tuple with the ChartVersion field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HelmApp) GetChartVersionOk() (*string, bool) { + if o == nil || o.ChartVersion == nil { + return nil, false + } + return o.ChartVersion, true +} + +// HasChartVersion returns a boolean if a field has been set. +func (o *HelmApp) HasChartVersion() bool { + if o != nil && o.ChartVersion != nil { + return true + } + + return false +} + +// SetChartVersion gets a reference to the given string and assigns it to the ChartVersion field. +func (o *HelmApp) SetChartVersion(v string) { + o.ChartVersion = &v +} + // GetEnvironmentDetail returns the EnvironmentDetail field value if set, zero value otherwise. func (o *HelmApp) GetEnvironmentDetail() AppEnvironmentDetail { if o == nil || o.EnvironmentDetail == nil { @@ -293,6 +327,9 @@ func (o HelmApp) MarshalJSON() ([]byte, error) { if o.ProjectId != nil { toSerialize["projectId"] = o.ProjectId } + if o.ChartVersion != nil { + toSerialize["chartVersion"] = o.ChartVersion + } if o.EnvironmentDetail != nil { toSerialize["environmentDetail"] = o.EnvironmentDetail } @@ -334,3 +371,5 @@ func (v *NullableHelmApp) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } + + diff --git a/api/helm-app/openapiClient/model_installed_app_info.go b/api/helm-app/openapiClient/model_installed_app_info.go new file mode 100644 index 0000000000..b62fe40cdf --- /dev/null +++ b/api/helm-app/openapiClient/model_installed_app_info.go @@ -0,0 +1,375 @@ +/* +Devtron Labs + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +API version: 1.0.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package openapi + +import ( + "encoding/json" +) + +// InstalledAppInfo struct for InstalledAppInfo +type InstalledAppInfo struct { + // appId + AppId *int32 `json:"appId,omitempty"` + // installedAppId + InstalledAppId *int32 `json:"installedAppId,omitempty"` + // environment Name + EnvironmentName *string `json:"environmentName,omitempty"` + // EA_ONLY/FULL + AppOfferingMode *string `json:"appOfferingMode,omitempty"` + // App store chart Id + AppStoreChartId *float32 `json:"appStoreChartId,omitempty"` + // App store installed app version Id + InstalledAppVersionId *float32 `json:"installedAppVersionId,omitempty"` + // Cluster Id + ClusterId *float32 `json:"clusterId,omitempty"` + // Environment Id + EnvironmentId *float32 `json:"environmentId,omitempty"` +} + +// NewInstalledAppInfo instantiates a new InstalledAppInfo object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInstalledAppInfo() *InstalledAppInfo { + this := InstalledAppInfo{} + return &this +} + +// NewInstalledAppInfoWithDefaults instantiates a new InstalledAppInfo object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInstalledAppInfoWithDefaults() *InstalledAppInfo { + this := InstalledAppInfo{} + return &this +} + +// GetAppId returns the AppId field value if set, zero value otherwise. +func (o *InstalledAppInfo) GetAppId() int32 { + if o == nil || o.AppId == nil { + var ret int32 + return ret + } + return *o.AppId +} + +// GetAppIdOk returns a tuple with the AppId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstalledAppInfo) GetAppIdOk() (*int32, bool) { + if o == nil || o.AppId == nil { + return nil, false + } + return o.AppId, true +} + +// HasAppId returns a boolean if a field has been set. +func (o *InstalledAppInfo) HasAppId() bool { + if o != nil && o.AppId != nil { + return true + } + + return false +} + +// SetAppId gets a reference to the given int32 and assigns it to the AppId field. +func (o *InstalledAppInfo) SetAppId(v int32) { + o.AppId = &v +} + +// GetInstalledAppId returns the InstalledAppId field value if set, zero value otherwise. +func (o *InstalledAppInfo) GetInstalledAppId() int32 { + if o == nil || o.InstalledAppId == nil { + var ret int32 + return ret + } + return *o.InstalledAppId +} + +// GetInstalledAppIdOk returns a tuple with the InstalledAppId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstalledAppInfo) GetInstalledAppIdOk() (*int32, bool) { + if o == nil || o.InstalledAppId == nil { + return nil, false + } + return o.InstalledAppId, true +} + +// HasInstalledAppId returns a boolean if a field has been set. +func (o *InstalledAppInfo) HasInstalledAppId() bool { + if o != nil && o.InstalledAppId != nil { + return true + } + + return false +} + +// SetInstalledAppId gets a reference to the given int32 and assigns it to the InstalledAppId field. +func (o *InstalledAppInfo) SetInstalledAppId(v int32) { + o.InstalledAppId = &v +} + +// GetEnvironmentName returns the EnvironmentName field value if set, zero value otherwise. +func (o *InstalledAppInfo) GetEnvironmentName() string { + if o == nil || o.EnvironmentName == nil { + var ret string + return ret + } + return *o.EnvironmentName +} + +// GetEnvironmentNameOk returns a tuple with the EnvironmentName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstalledAppInfo) GetEnvironmentNameOk() (*string, bool) { + if o == nil || o.EnvironmentName == nil { + return nil, false + } + return o.EnvironmentName, true +} + +// HasEnvironmentName returns a boolean if a field has been set. +func (o *InstalledAppInfo) HasEnvironmentName() bool { + if o != nil && o.EnvironmentName != nil { + return true + } + + return false +} + +// SetEnvironmentName gets a reference to the given string and assigns it to the EnvironmentName field. +func (o *InstalledAppInfo) SetEnvironmentName(v string) { + o.EnvironmentName = &v +} + +// GetAppOfferingMode returns the AppOfferingMode field value if set, zero value otherwise. +func (o *InstalledAppInfo) GetAppOfferingMode() string { + if o == nil || o.AppOfferingMode == nil { + var ret string + return ret + } + return *o.AppOfferingMode +} + +// GetAppOfferingModeOk returns a tuple with the AppOfferingMode field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstalledAppInfo) GetAppOfferingModeOk() (*string, bool) { + if o == nil || o.AppOfferingMode == nil { + return nil, false + } + return o.AppOfferingMode, true +} + +// HasAppOfferingMode returns a boolean if a field has been set. +func (o *InstalledAppInfo) HasAppOfferingMode() bool { + if o != nil && o.AppOfferingMode != nil { + return true + } + + return false +} + +// SetAppOfferingMode gets a reference to the given string and assigns it to the AppOfferingMode field. +func (o *InstalledAppInfo) SetAppOfferingMode(v string) { + o.AppOfferingMode = &v +} + +// GetAppStoreChartId returns the AppStoreChartId field value if set, zero value otherwise. +func (o *InstalledAppInfo) GetAppStoreChartId() float32 { + if o == nil || o.AppStoreChartId == nil { + var ret float32 + return ret + } + return *o.AppStoreChartId +} + +// GetAppStoreChartIdOk returns a tuple with the AppStoreChartId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstalledAppInfo) GetAppStoreChartIdOk() (*float32, bool) { + if o == nil || o.AppStoreChartId == nil { + return nil, false + } + return o.AppStoreChartId, true +} + +// HasAppStoreChartId returns a boolean if a field has been set. +func (o *InstalledAppInfo) HasAppStoreChartId() bool { + if o != nil && o.AppStoreChartId != nil { + return true + } + + return false +} + +// SetAppStoreChartId gets a reference to the given float32 and assigns it to the AppStoreChartId field. +func (o *InstalledAppInfo) SetAppStoreChartId(v float32) { + o.AppStoreChartId = &v +} + +// GetInstalledAppVersionId returns the InstalledAppVersionId field value if set, zero value otherwise. +func (o *InstalledAppInfo) GetInstalledAppVersionId() float32 { + if o == nil || o.InstalledAppVersionId == nil { + var ret float32 + return ret + } + return *o.InstalledAppVersionId +} + +// GetInstalledAppVersionIdOk returns a tuple with the InstalledAppVersionId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstalledAppInfo) GetInstalledAppVersionIdOk() (*float32, bool) { + if o == nil || o.InstalledAppVersionId == nil { + return nil, false + } + return o.InstalledAppVersionId, true +} + +// HasInstalledAppVersionId returns a boolean if a field has been set. +func (o *InstalledAppInfo) HasInstalledAppVersionId() bool { + if o != nil && o.InstalledAppVersionId != nil { + return true + } + + return false +} + +// SetInstalledAppVersionId gets a reference to the given float32 and assigns it to the InstalledAppVersionId field. +func (o *InstalledAppInfo) SetInstalledAppVersionId(v float32) { + o.InstalledAppVersionId = &v +} + +// GetClusterId returns the ClusterId field value if set, zero value otherwise. +func (o *InstalledAppInfo) GetClusterId() float32 { + if o == nil || o.ClusterId == nil { + var ret float32 + return ret + } + return *o.ClusterId +} + +// GetClusterIdOk returns a tuple with the ClusterId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstalledAppInfo) GetClusterIdOk() (*float32, bool) { + if o == nil || o.ClusterId == nil { + return nil, false + } + return o.ClusterId, true +} + +// HasClusterId returns a boolean if a field has been set. +func (o *InstalledAppInfo) HasClusterId() bool { + if o != nil && o.ClusterId != nil { + return true + } + + return false +} + +// SetClusterId gets a reference to the given float32 and assigns it to the ClusterId field. +func (o *InstalledAppInfo) SetClusterId(v float32) { + o.ClusterId = &v +} + +// GetEnvironmentId returns the EnvironmentId field value if set, zero value otherwise. +func (o *InstalledAppInfo) GetEnvironmentId() float32 { + if o == nil || o.EnvironmentId == nil { + var ret float32 + return ret + } + return *o.EnvironmentId +} + +// GetEnvironmentIdOk returns a tuple with the EnvironmentId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InstalledAppInfo) GetEnvironmentIdOk() (*float32, bool) { + if o == nil || o.EnvironmentId == nil { + return nil, false + } + return o.EnvironmentId, true +} + +// HasEnvironmentId returns a boolean if a field has been set. +func (o *InstalledAppInfo) HasEnvironmentId() bool { + if o != nil && o.EnvironmentId != nil { + return true + } + + return false +} + +// SetEnvironmentId gets a reference to the given float32 and assigns it to the EnvironmentId field. +func (o *InstalledAppInfo) SetEnvironmentId(v float32) { + o.EnvironmentId = &v +} + +func (o InstalledAppInfo) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.AppId != nil { + toSerialize["appId"] = o.AppId + } + if o.InstalledAppId != nil { + toSerialize["installedAppId"] = o.InstalledAppId + } + if o.EnvironmentName != nil { + toSerialize["environmentName"] = o.EnvironmentName + } + if o.AppOfferingMode != nil { + toSerialize["appOfferingMode"] = o.AppOfferingMode + } + if o.AppStoreChartId != nil { + toSerialize["appStoreChartId"] = o.AppStoreChartId + } + if o.InstalledAppVersionId != nil { + toSerialize["installedAppVersionId"] = o.InstalledAppVersionId + } + if o.ClusterId != nil { + toSerialize["clusterId"] = o.ClusterId + } + if o.EnvironmentId != nil { + toSerialize["environmentId"] = o.EnvironmentId + } + return json.Marshal(toSerialize) +} + +type NullableInstalledAppInfo struct { + value *InstalledAppInfo + isSet bool +} + +func (v NullableInstalledAppInfo) Get() *InstalledAppInfo { + return v.value +} + +func (v *NullableInstalledAppInfo) Set(val *InstalledAppInfo) { + v.value = val + v.isSet = true +} + +func (v NullableInstalledAppInfo) IsSet() bool { + return v.isSet +} + +func (v *NullableInstalledAppInfo) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInstalledAppInfo(val *InstalledAppInfo) *NullableInstalledAppInfo { + return &NullableInstalledAppInfo{value: val, isSet: true} +} + +func (v NullableInstalledAppInfo) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInstalledAppInfo) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/api/helm-app/openapiClient/model_release_and_installed_app_info.go b/api/helm-app/openapiClient/model_release_and_installed_app_info.go new file mode 100644 index 0000000000..7dba12cd91 --- /dev/null +++ b/api/helm-app/openapiClient/model_release_and_installed_app_info.go @@ -0,0 +1,151 @@ +/* +Devtron Labs + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +API version: 1.0.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package openapi + +import ( + "encoding/json" +) + +// ReleaseAndInstalledAppInfo struct for ReleaseAndInstalledAppInfo +type ReleaseAndInstalledAppInfo struct { + ReleaseInfo *ReleaseInfo `json:"releaseInfo,omitempty"` + InstalledAppInfo *InstalledAppInfo `json:"installedAppInfo,omitempty"` +} + +// NewReleaseAndInstalledAppInfo instantiates a new ReleaseAndInstalledAppInfo object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewReleaseAndInstalledAppInfo() *ReleaseAndInstalledAppInfo { + this := ReleaseAndInstalledAppInfo{} + return &this +} + +// NewReleaseAndInstalledAppInfoWithDefaults instantiates a new ReleaseAndInstalledAppInfo object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewReleaseAndInstalledAppInfoWithDefaults() *ReleaseAndInstalledAppInfo { + this := ReleaseAndInstalledAppInfo{} + return &this +} + +// GetReleaseInfo returns the ReleaseInfo field value if set, zero value otherwise. +func (o *ReleaseAndInstalledAppInfo) GetReleaseInfo() ReleaseInfo { + if o == nil || o.ReleaseInfo == nil { + var ret ReleaseInfo + return ret + } + return *o.ReleaseInfo +} + +// GetReleaseInfoOk returns a tuple with the ReleaseInfo field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseAndInstalledAppInfo) GetReleaseInfoOk() (*ReleaseInfo, bool) { + if o == nil || o.ReleaseInfo == nil { + return nil, false + } + return o.ReleaseInfo, true +} + +// HasReleaseInfo returns a boolean if a field has been set. +func (o *ReleaseAndInstalledAppInfo) HasReleaseInfo() bool { + if o != nil && o.ReleaseInfo != nil { + return true + } + + return false +} + +// SetReleaseInfo gets a reference to the given ReleaseInfo and assigns it to the ReleaseInfo field. +func (o *ReleaseAndInstalledAppInfo) SetReleaseInfo(v ReleaseInfo) { + o.ReleaseInfo = &v +} + +// GetInstalledAppInfo returns the InstalledAppInfo field value if set, zero value otherwise. +func (o *ReleaseAndInstalledAppInfo) GetInstalledAppInfo() InstalledAppInfo { + if o == nil || o.InstalledAppInfo == nil { + var ret InstalledAppInfo + return ret + } + return *o.InstalledAppInfo +} + +// GetInstalledAppInfoOk returns a tuple with the InstalledAppInfo field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseAndInstalledAppInfo) GetInstalledAppInfoOk() (*InstalledAppInfo, bool) { + if o == nil || o.InstalledAppInfo == nil { + return nil, false + } + return o.InstalledAppInfo, true +} + +// HasInstalledAppInfo returns a boolean if a field has been set. +func (o *ReleaseAndInstalledAppInfo) HasInstalledAppInfo() bool { + if o != nil && o.InstalledAppInfo != nil { + return true + } + + return false +} + +// SetInstalledAppInfo gets a reference to the given InstalledAppInfo and assigns it to the InstalledAppInfo field. +func (o *ReleaseAndInstalledAppInfo) SetInstalledAppInfo(v InstalledAppInfo) { + o.InstalledAppInfo = &v +} + +func (o ReleaseAndInstalledAppInfo) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.ReleaseInfo != nil { + toSerialize["releaseInfo"] = o.ReleaseInfo + } + if o.InstalledAppInfo != nil { + toSerialize["installedAppInfo"] = o.InstalledAppInfo + } + return json.Marshal(toSerialize) +} + +type NullableReleaseAndInstalledAppInfo struct { + value *ReleaseAndInstalledAppInfo + isSet bool +} + +func (v NullableReleaseAndInstalledAppInfo) Get() *ReleaseAndInstalledAppInfo { + return v.value +} + +func (v *NullableReleaseAndInstalledAppInfo) Set(val *ReleaseAndInstalledAppInfo) { + v.value = val + v.isSet = true +} + +func (v NullableReleaseAndInstalledAppInfo) IsSet() bool { + return v.isSet +} + +func (v *NullableReleaseAndInstalledAppInfo) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableReleaseAndInstalledAppInfo(val *ReleaseAndInstalledAppInfo) *NullableReleaseAndInstalledAppInfo { + return &NullableReleaseAndInstalledAppInfo{value: val, isSet: true} +} + +func (v NullableReleaseAndInstalledAppInfo) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableReleaseAndInstalledAppInfo) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/api/helm-app/openapiClient/model_release_info.go b/api/helm-app/openapiClient/model_release_info.go index 784da9c610..b8d8ebfee9 100644 --- a/api/helm-app/openapiClient/model_release_info.go +++ b/api/helm-app/openapiClient/model_release_info.go @@ -16,13 +16,15 @@ import ( // ReleaseInfo struct for ReleaseInfo type ReleaseInfo struct { - DeployedAppDetail *HelmAppDeploymentDetail `json:"deployedAppDetail,omitempty"` + DeployedAppDetail *HelmApp `json:"deployedAppDetail,omitempty"` // default chat values DefaultValues *string `json:"defaultValues,omitempty"` // overrides passed by user OverrideValues *string `json:"overrideValues,omitempty"` // merged values MergedValues *string `json:"mergedValues,omitempty"` + // readme of the chart + Readme *string `json:"readme,omitempty"` } // NewReleaseInfo instantiates a new ReleaseInfo object @@ -43,9 +45,9 @@ func NewReleaseInfoWithDefaults() *ReleaseInfo { } // GetDeployedAppDetail returns the DeployedAppDetail field value if set, zero value otherwise. -func (o *ReleaseInfo) GetDeployedAppDetail() HelmAppDeploymentDetail { +func (o *ReleaseInfo) GetDeployedAppDetail() HelmApp { if o == nil || o.DeployedAppDetail == nil { - var ret HelmAppDeploymentDetail + var ret HelmApp return ret } return *o.DeployedAppDetail @@ -53,7 +55,7 @@ func (o *ReleaseInfo) GetDeployedAppDetail() HelmAppDeploymentDetail { // GetDeployedAppDetailOk returns a tuple with the DeployedAppDetail field value if set, nil otherwise // and a boolean to check if the value has been set. -func (o *ReleaseInfo) GetDeployedAppDetailOk() (*HelmAppDeploymentDetail, bool) { +func (o *ReleaseInfo) GetDeployedAppDetailOk() (*HelmApp, bool) { if o == nil || o.DeployedAppDetail == nil { return nil, false } @@ -69,8 +71,8 @@ func (o *ReleaseInfo) HasDeployedAppDetail() bool { return false } -// SetDeployedAppDetail gets a reference to the given HelmAppDeploymentDetail and assigns it to the DeployedAppDetail field. -func (o *ReleaseInfo) SetDeployedAppDetail(v HelmAppDeploymentDetail) { +// SetDeployedAppDetail gets a reference to the given HelmApp and assigns it to the DeployedAppDetail field. +func (o *ReleaseInfo) SetDeployedAppDetail(v HelmApp) { o.DeployedAppDetail = &v } @@ -170,6 +172,38 @@ func (o *ReleaseInfo) SetMergedValues(v string) { o.MergedValues = &v } +// GetReadme returns the Readme field value if set, zero value otherwise. +func (o *ReleaseInfo) GetReadme() string { + if o == nil || o.Readme == nil { + var ret string + return ret + } + return *o.Readme +} + +// GetReadmeOk returns a tuple with the Readme field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ReleaseInfo) GetReadmeOk() (*string, bool) { + if o == nil || o.Readme == nil { + return nil, false + } + return o.Readme, true +} + +// HasReadme returns a boolean if a field has been set. +func (o *ReleaseInfo) HasReadme() bool { + if o != nil && o.Readme != nil { + return true + } + + return false +} + +// SetReadme gets a reference to the given string and assigns it to the Readme field. +func (o *ReleaseInfo) SetReadme(v string) { + o.Readme = &v +} + func (o ReleaseInfo) MarshalJSON() ([]byte, error) { toSerialize := map[string]interface{}{} if o.DeployedAppDetail != nil { @@ -184,6 +218,9 @@ func (o ReleaseInfo) MarshalJSON() ([]byte, error) { if o.MergedValues != nil { toSerialize["mergedValues"] = o.MergedValues } + if o.Readme != nil { + toSerialize["readme"] = o.Readme + } return json.Marshal(toSerialize) } diff --git a/api/helm-app/openapiClient/model_update_release_with_chart_linking_request.go b/api/helm-app/openapiClient/model_update_release_with_chart_linking_request.go new file mode 100644 index 0000000000..165ab38986 --- /dev/null +++ b/api/helm-app/openapiClient/model_update_release_with_chart_linking_request.go @@ -0,0 +1,264 @@ +/* +Devtron Labs + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +API version: 1.0.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package openapi + +import ( + "encoding/json" +) + +// UpdateReleaseWithChartLinkingRequest struct for UpdateReleaseWithChartLinkingRequest +type UpdateReleaseWithChartLinkingRequest struct { + // helm app id + AppId *string `json:"appId,omitempty"` + // updated values yaml string + ValuesYaml *string `json:"valuesYaml,omitempty"` + // app store application version Id + AppStoreApplicationVersionId *float32 `json:"appStoreApplicationVersionId,omitempty"` + // Reference value Id of selected chart values + ReferenceValueId *float32 `json:"referenceValueId,omitempty"` + // Reference value Kind of selected chart values \"oneof=DEFAULT TEMPLATE DEPLOYED EXISTING\" (can be null) + ReferenceValueKind *string `json:"referenceValueKind,omitempty"` +} + +// NewUpdateReleaseWithChartLinkingRequest instantiates a new UpdateReleaseWithChartLinkingRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewUpdateReleaseWithChartLinkingRequest() *UpdateReleaseWithChartLinkingRequest { + this := UpdateReleaseWithChartLinkingRequest{} + return &this +} + +// NewUpdateReleaseWithChartLinkingRequestWithDefaults instantiates a new UpdateReleaseWithChartLinkingRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewUpdateReleaseWithChartLinkingRequestWithDefaults() *UpdateReleaseWithChartLinkingRequest { + this := UpdateReleaseWithChartLinkingRequest{} + return &this +} + +// GetAppId returns the AppId field value if set, zero value otherwise. +func (o *UpdateReleaseWithChartLinkingRequest) GetAppId() string { + if o == nil || o.AppId == nil { + var ret string + return ret + } + return *o.AppId +} + +// GetAppIdOk returns a tuple with the AppId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdateReleaseWithChartLinkingRequest) GetAppIdOk() (*string, bool) { + if o == nil || o.AppId == nil { + return nil, false + } + return o.AppId, true +} + +// HasAppId returns a boolean if a field has been set. +func (o *UpdateReleaseWithChartLinkingRequest) HasAppId() bool { + if o != nil && o.AppId != nil { + return true + } + + return false +} + +// SetAppId gets a reference to the given string and assigns it to the AppId field. +func (o *UpdateReleaseWithChartLinkingRequest) SetAppId(v string) { + o.AppId = &v +} + +// GetValuesYaml returns the ValuesYaml field value if set, zero value otherwise. +func (o *UpdateReleaseWithChartLinkingRequest) GetValuesYaml() string { + if o == nil || o.ValuesYaml == nil { + var ret string + return ret + } + return *o.ValuesYaml +} + +// GetValuesYamlOk returns a tuple with the ValuesYaml field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdateReleaseWithChartLinkingRequest) GetValuesYamlOk() (*string, bool) { + if o == nil || o.ValuesYaml == nil { + return nil, false + } + return o.ValuesYaml, true +} + +// HasValuesYaml returns a boolean if a field has been set. +func (o *UpdateReleaseWithChartLinkingRequest) HasValuesYaml() bool { + if o != nil && o.ValuesYaml != nil { + return true + } + + return false +} + +// SetValuesYaml gets a reference to the given string and assigns it to the ValuesYaml field. +func (o *UpdateReleaseWithChartLinkingRequest) SetValuesYaml(v string) { + o.ValuesYaml = &v +} + +// GetAppStoreApplicationVersionId returns the AppStoreApplicationVersionId field value if set, zero value otherwise. +func (o *UpdateReleaseWithChartLinkingRequest) GetAppStoreApplicationVersionId() float32 { + if o == nil || o.AppStoreApplicationVersionId == nil { + var ret float32 + return ret + } + return *o.AppStoreApplicationVersionId +} + +// GetAppStoreApplicationVersionIdOk returns a tuple with the AppStoreApplicationVersionId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdateReleaseWithChartLinkingRequest) GetAppStoreApplicationVersionIdOk() (*float32, bool) { + if o == nil || o.AppStoreApplicationVersionId == nil { + return nil, false + } + return o.AppStoreApplicationVersionId, true +} + +// HasAppStoreApplicationVersionId returns a boolean if a field has been set. +func (o *UpdateReleaseWithChartLinkingRequest) HasAppStoreApplicationVersionId() bool { + if o != nil && o.AppStoreApplicationVersionId != nil { + return true + } + + return false +} + +// SetAppStoreApplicationVersionId gets a reference to the given float32 and assigns it to the AppStoreApplicationVersionId field. +func (o *UpdateReleaseWithChartLinkingRequest) SetAppStoreApplicationVersionId(v float32) { + o.AppStoreApplicationVersionId = &v +} + +// GetReferenceValueId returns the ReferenceValueId field value if set, zero value otherwise. +func (o *UpdateReleaseWithChartLinkingRequest) GetReferenceValueId() float32 { + if o == nil || o.ReferenceValueId == nil { + var ret float32 + return ret + } + return *o.ReferenceValueId +} + +// GetReferenceValueIdOk returns a tuple with the ReferenceValueId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdateReleaseWithChartLinkingRequest) GetReferenceValueIdOk() (*float32, bool) { + if o == nil || o.ReferenceValueId == nil { + return nil, false + } + return o.ReferenceValueId, true +} + +// HasReferenceValueId returns a boolean if a field has been set. +func (o *UpdateReleaseWithChartLinkingRequest) HasReferenceValueId() bool { + if o != nil && o.ReferenceValueId != nil { + return true + } + + return false +} + +// SetReferenceValueId gets a reference to the given float32 and assigns it to the ReferenceValueId field. +func (o *UpdateReleaseWithChartLinkingRequest) SetReferenceValueId(v float32) { + o.ReferenceValueId = &v +} + +// GetReferenceValueKind returns the ReferenceValueKind field value if set, zero value otherwise. +func (o *UpdateReleaseWithChartLinkingRequest) GetReferenceValueKind() string { + if o == nil || o.ReferenceValueKind == nil { + var ret string + return ret + } + return *o.ReferenceValueKind +} + +// GetReferenceValueKindOk returns a tuple with the ReferenceValueKind field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *UpdateReleaseWithChartLinkingRequest) GetReferenceValueKindOk() (*string, bool) { + if o == nil || o.ReferenceValueKind == nil { + return nil, false + } + return o.ReferenceValueKind, true +} + +// HasReferenceValueKind returns a boolean if a field has been set. +func (o *UpdateReleaseWithChartLinkingRequest) HasReferenceValueKind() bool { + if o != nil && o.ReferenceValueKind != nil { + return true + } + + return false +} + +// SetReferenceValueKind gets a reference to the given string and assigns it to the ReferenceValueKind field. +func (o *UpdateReleaseWithChartLinkingRequest) SetReferenceValueKind(v string) { + o.ReferenceValueKind = &v +} + +func (o UpdateReleaseWithChartLinkingRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.AppId != nil { + toSerialize["appId"] = o.AppId + } + if o.ValuesYaml != nil { + toSerialize["valuesYaml"] = o.ValuesYaml + } + if o.AppStoreApplicationVersionId != nil { + toSerialize["appStoreApplicationVersionId"] = o.AppStoreApplicationVersionId + } + if o.ReferenceValueId != nil { + toSerialize["referenceValueId"] = o.ReferenceValueId + } + if o.ReferenceValueKind != nil { + toSerialize["referenceValueKind"] = o.ReferenceValueKind + } + return json.Marshal(toSerialize) +} + +type NullableUpdateReleaseWithChartLinkingRequest struct { + value *UpdateReleaseWithChartLinkingRequest + isSet bool +} + +func (v NullableUpdateReleaseWithChartLinkingRequest) Get() *UpdateReleaseWithChartLinkingRequest { + return v.value +} + +func (v *NullableUpdateReleaseWithChartLinkingRequest) Set(val *UpdateReleaseWithChartLinkingRequest) { + v.value = val + v.isSet = true +} + +func (v NullableUpdateReleaseWithChartLinkingRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableUpdateReleaseWithChartLinkingRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableUpdateReleaseWithChartLinkingRequest(val *UpdateReleaseWithChartLinkingRequest) *NullableUpdateReleaseWithChartLinkingRequest { + return &NullableUpdateReleaseWithChartLinkingRequest{value: val, isSet: true} +} + +func (v NullableUpdateReleaseWithChartLinkingRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableUpdateReleaseWithChartLinkingRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/api/openapi/openapiClient/model_rollback_release_request.go b/api/openapi/openapiClient/model_rollback_release_request.go new file mode 100644 index 0000000000..caa0202dd7 --- /dev/null +++ b/api/openapi/openapiClient/model_rollback_release_request.go @@ -0,0 +1,227 @@ +/* +Devtron Labs + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +API version: 1.0.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package openapi + +import ( + "encoding/json" +) + +// RollbackReleaseRequest struct for RollbackReleaseRequest +type RollbackReleaseRequest struct { + // Installed App Id if the app is installed from chart store + InstalledAppId *int32 `json:"installedAppId,omitempty"` + // Installed App Version Id if the app is installed from chart store + InstalledAppVersionId *int32 `json:"installedAppVersionId,omitempty"` + // helm App Id if the application is installed from using helm (for example \"clusterId|namespace|appName\" ) + HAppId *string `json:"hAppId,omitempty"` + // rollback to this version + Version *int32 `json:"version,omitempty"` +} + +// NewRollbackReleaseRequest instantiates a new RollbackReleaseRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRollbackReleaseRequest() *RollbackReleaseRequest { + this := RollbackReleaseRequest{} + return &this +} + +// NewRollbackReleaseRequestWithDefaults instantiates a new RollbackReleaseRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRollbackReleaseRequestWithDefaults() *RollbackReleaseRequest { + this := RollbackReleaseRequest{} + return &this +} + +// GetInstalledAppId returns the InstalledAppId field value if set, zero value otherwise. +func (o *RollbackReleaseRequest) GetInstalledAppId() int32 { + if o == nil || o.InstalledAppId == nil { + var ret int32 + return ret + } + return *o.InstalledAppId +} + +// GetInstalledAppIdOk returns a tuple with the InstalledAppId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RollbackReleaseRequest) GetInstalledAppIdOk() (*int32, bool) { + if o == nil || o.InstalledAppId == nil { + return nil, false + } + return o.InstalledAppId, true +} + +// HasInstalledAppId returns a boolean if a field has been set. +func (o *RollbackReleaseRequest) HasInstalledAppId() bool { + if o != nil && o.InstalledAppId != nil { + return true + } + + return false +} + +// SetInstalledAppId gets a reference to the given int32 and assigns it to the InstalledAppId field. +func (o *RollbackReleaseRequest) SetInstalledAppId(v int32) { + o.InstalledAppId = &v +} + +// GetInstalledAppVersionId returns the InstalledAppVersionId field value if set, zero value otherwise. +func (o *RollbackReleaseRequest) GetInstalledAppVersionId() int32 { + if o == nil || o.InstalledAppVersionId == nil { + var ret int32 + return ret + } + return *o.InstalledAppVersionId +} + +// GetInstalledAppVersionIdOk returns a tuple with the InstalledAppVersionId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RollbackReleaseRequest) GetInstalledAppVersionIdOk() (*int32, bool) { + if o == nil || o.InstalledAppVersionId == nil { + return nil, false + } + return o.InstalledAppVersionId, true +} + +// HasInstalledAppVersionId returns a boolean if a field has been set. +func (o *RollbackReleaseRequest) HasInstalledAppVersionId() bool { + if o != nil && o.InstalledAppVersionId != nil { + return true + } + + return false +} + +// SetInstalledAppVersionId gets a reference to the given int32 and assigns it to the InstalledAppVersionId field. +func (o *RollbackReleaseRequest) SetInstalledAppVersionId(v int32) { + o.InstalledAppVersionId = &v +} + +// GetHAppId returns the HAppId field value if set, zero value otherwise. +func (o *RollbackReleaseRequest) GetHAppId() string { + if o == nil || o.HAppId == nil { + var ret string + return ret + } + return *o.HAppId +} + +// GetHAppIdOk returns a tuple with the HAppId field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RollbackReleaseRequest) GetHAppIdOk() (*string, bool) { + if o == nil || o.HAppId == nil { + return nil, false + } + return o.HAppId, true +} + +// HasHAppId returns a boolean if a field has been set. +func (o *RollbackReleaseRequest) HasHAppId() bool { + if o != nil && o.HAppId != nil { + return true + } + + return false +} + +// SetHAppId gets a reference to the given string and assigns it to the HAppId field. +func (o *RollbackReleaseRequest) SetHAppId(v string) { + o.HAppId = &v +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *RollbackReleaseRequest) GetVersion() int32 { + if o == nil || o.Version == nil { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RollbackReleaseRequest) GetVersionOk() (*int32, bool) { + if o == nil || o.Version == nil { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *RollbackReleaseRequest) HasVersion() bool { + if o != nil && o.Version != nil { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *RollbackReleaseRequest) SetVersion(v int32) { + o.Version = &v +} + +func (o RollbackReleaseRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.InstalledAppId != nil { + toSerialize["installedAppId"] = o.InstalledAppId + } + if o.InstalledAppVersionId != nil { + toSerialize["installedAppVersionId"] = o.InstalledAppVersionId + } + if o.HAppId != nil { + toSerialize["hAppId"] = o.HAppId + } + if o.Version != nil { + toSerialize["version"] = o.Version + } + return json.Marshal(toSerialize) +} + +type NullableRollbackReleaseRequest struct { + value *RollbackReleaseRequest + isSet bool +} + +func (v NullableRollbackReleaseRequest) Get() *RollbackReleaseRequest { + return v.value +} + +func (v *NullableRollbackReleaseRequest) Set(val *RollbackReleaseRequest) { + v.value = val + v.isSet = true +} + +func (v NullableRollbackReleaseRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableRollbackReleaseRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRollbackReleaseRequest(val *RollbackReleaseRequest) *NullableRollbackReleaseRequest { + return &NullableRollbackReleaseRequest{value: val, isSet: true} +} + +func (v NullableRollbackReleaseRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRollbackReleaseRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/api/openapi/openapiClient/model_rollback_release_response.go b/api/openapi/openapiClient/model_rollback_release_response.go new file mode 100644 index 0000000000..32eccf1235 --- /dev/null +++ b/api/openapi/openapiClient/model_rollback_release_response.go @@ -0,0 +1,116 @@ +/* +Devtron Labs + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +API version: 1.0.0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package openapi + +import ( + "encoding/json" +) + +// RollbackReleaseResponse struct for RollbackReleaseResponse +type RollbackReleaseResponse struct { + // success or failure + Success *bool `json:"success,omitempty"` +} + +// NewRollbackReleaseResponse instantiates a new RollbackReleaseResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRollbackReleaseResponse() *RollbackReleaseResponse { + this := RollbackReleaseResponse{} + return &this +} + +// NewRollbackReleaseResponseWithDefaults instantiates a new RollbackReleaseResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRollbackReleaseResponseWithDefaults() *RollbackReleaseResponse { + this := RollbackReleaseResponse{} + return &this +} + +// GetSuccess returns the Success field value if set, zero value otherwise. +func (o *RollbackReleaseResponse) GetSuccess() bool { + if o == nil || o.Success == nil { + var ret bool + return ret + } + return *o.Success +} + +// GetSuccessOk returns a tuple with the Success field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *RollbackReleaseResponse) GetSuccessOk() (*bool, bool) { + if o == nil || o.Success == nil { + return nil, false + } + return o.Success, true +} + +// HasSuccess returns a boolean if a field has been set. +func (o *RollbackReleaseResponse) HasSuccess() bool { + if o != nil && o.Success != nil { + return true + } + + return false +} + +// SetSuccess gets a reference to the given bool and assigns it to the Success field. +func (o *RollbackReleaseResponse) SetSuccess(v bool) { + o.Success = &v +} + +func (o RollbackReleaseResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Success != nil { + toSerialize["success"] = o.Success + } + return json.Marshal(toSerialize) +} + +type NullableRollbackReleaseResponse struct { + value *RollbackReleaseResponse + isSet bool +} + +func (v NullableRollbackReleaseResponse) Get() *RollbackReleaseResponse { + return v.value +} + +func (v *NullableRollbackReleaseResponse) Set(val *RollbackReleaseResponse) { + v.value = val + v.isSet = true +} + +func (v NullableRollbackReleaseResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableRollbackReleaseResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRollbackReleaseResponse(val *RollbackReleaseResponse) *NullableRollbackReleaseResponse { + return &NullableRollbackReleaseResponse{value: val, isSet: true} +} + +func (v NullableRollbackReleaseResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRollbackReleaseResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/api/restHandler/ChartGroupRestHandler.go b/api/restHandler/ChartGroupRestHandler.go index 7ebb3974cf..baedd035f1 100644 --- a/api/restHandler/ChartGroupRestHandler.go +++ b/api/restHandler/ChartGroupRestHandler.go @@ -21,7 +21,7 @@ import ( "encoding/json" "fmt" "github.com/devtron-labs/devtron/api/restHandler/common" - appStore "github.com/devtron-labs/devtron/pkg/appStore" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/user" "github.com/devtron-labs/devtron/pkg/user/casbin" "github.com/gorilla/mux" @@ -34,14 +34,14 @@ import ( const CHART_GROUP_DELETE_SUCCESS_RESP = "Chart group deleted successfully." type ChartGroupRestHandlerImpl struct { - ChartGroupService appStore.ChartGroupService + ChartGroupService service.ChartGroupService Logger *zap.SugaredLogger userAuthService user.UserService enforcer casbin.Enforcer validator *validator.Validate } -func NewChartGroupRestHandlerImpl(ChartGroupService appStore.ChartGroupService, +func NewChartGroupRestHandlerImpl(ChartGroupService service.ChartGroupService, Logger *zap.SugaredLogger, userAuthService user.UserService, enforcer casbin.Enforcer, validator *validator.Validate) *ChartGroupRestHandlerImpl { return &ChartGroupRestHandlerImpl{ @@ -71,7 +71,7 @@ func (impl *ChartGroupRestHandlerImpl) CreateChartGroup(w http.ResponseWriter, r return } decoder := json.NewDecoder(r.Body) - var request appStore.ChartGroupBean + var request service.ChartGroupBean err = decoder.Decode(&request) if err != nil { impl.Logger.Errorw("request err, CreateChartGroup", "err", err, "payload", request) @@ -112,7 +112,7 @@ func (impl *ChartGroupRestHandlerImpl) UpdateChartGroup(w http.ResponseWriter, r return } decoder := json.NewDecoder(r.Body) - var request appStore.ChartGroupBean + var request service.ChartGroupBean err = decoder.Decode(&request) if err != nil { impl.Logger.Errorw("request err, UpdateChartGroup", "err", err, "payload", request) @@ -153,7 +153,7 @@ func (impl *ChartGroupRestHandlerImpl) SaveChartGroupEntries(w http.ResponseWrit return } decoder := json.NewDecoder(r.Body) - var request appStore.ChartGroupBean + var request service.ChartGroupBean err = decoder.Decode(&request) if err != nil { impl.Logger.Errorw("request err, SaveChartGroupEntries", "err", err, "payload", request) @@ -319,7 +319,7 @@ func(impl *ChartGroupRestHandlerImpl) DeleteChartGroup(w http.ResponseWriter, r return } decoder := json.NewDecoder(r.Body) - var request appStore.ChartGroupBean + var request service.ChartGroupBean err = decoder.Decode(&request) if err != nil { impl.Logger.Errorw("request err, DeleteChartGroup", "err", err, "payload", request) diff --git a/api/restHandler/PipelineHistoryRestHandler.go b/api/restHandler/PipelineHistoryRestHandler.go new file mode 100644 index 0000000000..a09a55242a --- /dev/null +++ b/api/restHandler/PipelineHistoryRestHandler.go @@ -0,0 +1,500 @@ +package restHandler + +import ( + "fmt" + "github.com/devtron-labs/devtron/api/restHandler/common" + "github.com/devtron-labs/devtron/pkg/pipeline" + history2 "github.com/devtron-labs/devtron/pkg/pipeline/history" + "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" + "github.com/devtron-labs/devtron/pkg/user" + "github.com/devtron-labs/devtron/pkg/user/casbin" + "github.com/devtron-labs/devtron/util/rbac" + "github.com/gorilla/mux" + "go.uber.org/zap" + "net/http" + "strconv" +) + +type PipelineHistoryRestHandler interface { + FetchDeploymentDetailsForDeployedTemplatesHistory(w http.ResponseWriter, r *http.Request) + FetchDeploymentDetailsForDeployedStrategyHistory(w http.ResponseWriter, r *http.Request) + FetchDeploymentDetailsForDeployedCMHistory(w http.ResponseWriter, r *http.Request) + FetchDeploymentDetailsForDeployedCSHistory(w http.ResponseWriter, r *http.Request) + FetchDeployedTemplatesHistoryById(w http.ResponseWriter, r *http.Request) + FetchDeployedStrategyHistoryById(w http.ResponseWriter, r *http.Request) + FetchDeployedCMHistoryById(w http.ResponseWriter, r *http.Request) + FetchDeployedCSHistoryById(w http.ResponseWriter, r *http.Request) + FetchDeployedPrePostCdScriptHistory(w http.ResponseWriter, r *http.Request) +} + +type PipelineHistoryRestHandlerImpl struct { + logger *zap.SugaredLogger + userAuthService user.UserService + enforcer casbin.Enforcer + strategyHistoryService history2.PipelineStrategyHistoryService + deploymentTemplateHistoryService history2.DeploymentTemplateHistoryService + configMapHistoryService history2.ConfigMapHistoryService + prePostCiScriptHistoryService history2.PrePostCiScriptHistoryService + prePostCdScriptHistoryService history2.PrePostCdScriptHistoryService + pipelineBuilder pipeline.PipelineBuilder + enforcerUtil rbac.EnforcerUtil +} + +func NewPipelineHistoryRestHandlerImpl(logger *zap.SugaredLogger, userAuthService user.UserService, + enforcer casbin.Enforcer, strategyHistoryService history2.PipelineStrategyHistoryService, + deploymentTemplateHistoryService history2.DeploymentTemplateHistoryService, + configMapHistoryService history2.ConfigMapHistoryService, + prePostCiScriptHistoryService history2.PrePostCiScriptHistoryService, + prePostCdScriptHistoryService history2.PrePostCdScriptHistoryService, + pipelineBuilder pipeline.PipelineBuilder, + enforcerUtil rbac.EnforcerUtil) *PipelineHistoryRestHandlerImpl { + return &PipelineHistoryRestHandlerImpl{ + logger: logger, + userAuthService: userAuthService, + enforcer: enforcer, + strategyHistoryService: strategyHistoryService, + deploymentTemplateHistoryService: deploymentTemplateHistoryService, + configMapHistoryService: configMapHistoryService, + prePostCdScriptHistoryService: prePostCdScriptHistoryService, + prePostCiScriptHistoryService: prePostCiScriptHistoryService, + pipelineBuilder: pipelineBuilder, + enforcerUtil: enforcerUtil, + } +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeploymentDetailsForDeployedTemplatesHistory(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedTemplatesHistory", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedTemplatesHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Debugw("request payload, FetchDeploymentDetailsForDeployedTemplatesHistory", "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + + offsetQueryParam := r.URL.Query().Get("offset") + offset, err := strconv.Atoi(offsetQueryParam) + if offsetQueryParam == "" || err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedTemplatesHistory", "err", err, "offset", offset) + common.WriteJsonResp(w, err, "invalid offset", http.StatusBadRequest) + return + } + sizeQueryParam := r.URL.Query().Get("size") + limit, err := strconv.Atoi(sizeQueryParam) + if sizeQueryParam == "" || err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedTemplatesHistory", "err", err, "limit", limit) + common.WriteJsonResp(w, err, "invalid size", http.StatusBadRequest) + return + } + + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.deploymentTemplateHistoryService.GetDeploymentDetailsForDeployedTemplateHistory(pipelineId, offset, limit) + if err != nil { + handler.logger.Errorw("service err, GetDeploymentDetailsForDeployedTemplateHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeployedTemplatesHistoryById(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedTemplatesHistoryById", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedTemplatesHistoryById", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + id, err := strconv.Atoi(vars["id"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedTemplatesHistoryById", "err", err, "id", id) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Debugw("request payload, FetchDeployedTemplatesHistoryById", "id", id, "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.deploymentTemplateHistoryService.GetHistoryForDeployedTemplatesById(id, pipelineId) + if err != nil { + handler.logger.Errorw("service err, GetHistoryForDeployedTemplatesById", "err", err, "id", id, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeploymentDetailsForDeployedStrategyHistory(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedStrategyHistory", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedStrategyHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Debugw("request payload, FetchDeploymentDetailsForDeployedStrategyHistory", "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.strategyHistoryService.GetDeploymentDetailsForDeployedStrategyHistory(pipelineId) + if err != nil { + handler.logger.Errorw("service err, GetDeploymentDetailsForDeployedStrategyHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeployedStrategyHistoryById(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedStrategyHistoryById", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedStrategyHistoryById", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + id, err := strconv.Atoi(vars["id"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedStrategyHistoryById", "err", err, "id", id) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Debugw("request payload, FetchDeployedStrategyHistoryById", "id", id, "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.strategyHistoryService.GetHistoryForDeployedStrategyById(id, pipelineId) + if err != nil { + handler.logger.Errorw("service err, GetHistoryForDeployedStrategyById", "err", err, "id", id, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeploymentDetailsForDeployedCMHistory(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedCMHistory", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedCMHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Debugw("request payload, FetchDeploymentDetailsForDeployedCMHistory", "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.configMapHistoryService.GetDeploymentDetailsForDeployedCMCSHistory(pipelineId, repository.CONFIGMAP_TYPE) + if err != nil { + handler.logger.Errorw("service err, GetDeploymentDetailsForDeployedCMCSHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeployedCMHistoryById(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedCMHistoryById", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedCMHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + id, err := strconv.Atoi(vars["id"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedCMHistoryById", "err", err, "id", id) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Debugw("request payload, FetchDeployedCMHistoryById", "id", id, "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.configMapHistoryService.GetHistoryForDeployedCMCSById(id, pipelineId, repository.CONFIGMAP_TYPE) + if err != nil { + handler.logger.Errorw("service err, GetHistoryForDeployedCMCSById", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeploymentDetailsForDeployedCSHistory(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedCSHistory", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeploymentDetailsForDeployedCSHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Debugw("request payload, FetchDeploymentDetailsForDeployedCSHistory", "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.configMapHistoryService.GetDeploymentDetailsForDeployedCMCSHistory(pipelineId, repository.SECRET_TYPE) + if err != nil { + handler.logger.Errorw("service err, GetDeploymentDetailsForDeployedCMCSHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeployedCSHistoryById(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedCSHistoryById", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedCSHistoryById", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + id, err := strconv.Atoi(vars["id"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedCSHistoryById", "err", err, "id", id) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + handler.logger.Debugw("request payload, FetchDeployedCSHistoryById", "id", id, "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.configMapHistoryService.GetHistoryForDeployedCMCSById(id, pipelineId, repository.SECRET_TYPE) + if err != nil { + handler.logger.Errorw("service err, GetHistoryForDeployedCMCSById", "err", err, "id", id, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} + +func (handler PipelineHistoryRestHandlerImpl) FetchDeployedPrePostCdScriptHistory(w http.ResponseWriter, r *http.Request) { + userId, err := handler.userAuthService.GetLoggedInUser(r) + if userId == 0 || err != nil { + common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) + return + } + vars := mux.Vars(r) + appId, err := strconv.Atoi(vars["appId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedPrePostCdScriptHistory", "err", err, "appId", appId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + pipelineId, err := strconv.Atoi(vars["pipelineId"]) + if err != nil { + handler.logger.Errorw("request err, FetchDeployedPrePostCdScriptHistory", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + stage := r.URL.Query().Get("stage") + handler.logger.Debugw("request payload, FetchDeployedPrePostCdScriptHistory", "pipelineId", pipelineId) + + //RBAC START + token := r.Header.Get("token") + app, err := handler.pipelineBuilder.GetApp(appId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + //RBAC END + + res, err := handler.prePostCdScriptHistoryService.GetHistoryForDeployedPrePostCdScript(pipelineId, repository.CdStageType(stage)) + if err != nil { + handler.logger.Errorw("service err, GetHistoryForDeployedPrePostCdScript", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + common.WriteJsonResp(w, err, res, http.StatusOK) +} diff --git a/api/restHandler/app/DeploymentPipelineRestHandler.go b/api/restHandler/app/DeploymentPipelineRestHandler.go index 054a72cc9b..1abdc17115 100644 --- a/api/restHandler/app/DeploymentPipelineRestHandler.go +++ b/api/restHandler/app/DeploymentPipelineRestHandler.go @@ -109,6 +109,7 @@ func (handler PipelineConfigRestHandlerImpl) ConfigureDeploymentTemplateForApp(w common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) return } + ctx, cancel := context.WithCancel(r.Context()) if cn, ok := w.(http.CloseNotifier); ok { go func(done <-chan struct{}, closed <-chan bool) { @@ -302,6 +303,7 @@ func (handler PipelineConfigRestHandlerImpl) EnvConfigOverrideCreate(w http.Resp common.WriteJsonResp(w, err2, nil, http.StatusBadRequest) return } + createResp, err := handler.propertiesConfigService.CreateEnvironmentProperties(appId, &envConfigProperties) if err != nil { if err.Error() == bean2.NOCHARTEXIST { @@ -393,6 +395,7 @@ func (handler PipelineConfigRestHandlerImpl) EnvConfigOverrideUpdate(w http.Resp common.WriteJsonResp(w, err2, nil, http.StatusBadRequest) return } + createResp, err := handler.propertiesConfigService.UpdateEnvironmentProperties(appId, &envConfigProperties, userId) if err != nil { handler.Logger.Errorw("service err, EnvConfigOverrideUpdate", "err", err, "payload", envConfigProperties) @@ -432,6 +435,7 @@ func (handler PipelineConfigRestHandlerImpl) GetEnvConfigOverride(w http.Respons common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) return } + env, err := handler.propertiesConfigService.GetEnvironmentProperties(appId, environmentId, chartRefId) if err != nil { handler.Logger.Errorw("service err, GetEnvConfigOverride", "err", err, "payload", appId, environmentId, chartRefId) @@ -791,6 +795,7 @@ func (handler PipelineConfigRestHandlerImpl) UpdateAppOverride(w http.ResponseWr common.WriteJsonResp(w, err2, nil, http.StatusBadRequest) return } + createResp, err := handler.chartService.UpdateAppOverride(&templateRequest) if err != nil { handler.Logger.Errorw("service err, UpdateAppOverride", "err", err, "payload", templateRequest) diff --git a/api/router/ChartRefRouter.go b/api/router/ChartRefRouter.go index 107597a269..24e5625d45 100644 --- a/api/router/ChartRefRouter.go +++ b/api/router/ChartRefRouter.go @@ -47,5 +47,4 @@ func (router ChartRefRouterImpl) initChartRefRouter(userAuthRouter *mux.Router) userAuthRouter.Path("/autocomplete/{appId}/{environmentId}"). HandlerFunc(router.chartRefRestHandler.ChartRefAutocompleteForEnv).Methods("GET") - } diff --git a/api/router/PipelineConfigRouter.go b/api/router/PipelineConfigRouter.go index c480d0da66..5573eb76a1 100644 --- a/api/router/PipelineConfigRouter.go +++ b/api/router/PipelineConfigRouter.go @@ -27,13 +27,22 @@ type PipelineConfigRouter interface { initPipelineConfigRouter(configRouter *mux.Router) } type PipelineConfigRouterImpl struct { - restHandler app.PipelineConfigRestHandler - appWorkflowRestHandler restHandler.AppWorkflowRestHandler - webhookDataRestHandler restHandler.WebhookDataRestHandler + restHandler app.PipelineConfigRestHandler + appWorkflowRestHandler restHandler.AppWorkflowRestHandler + webhookDataRestHandler restHandler.WebhookDataRestHandler + pipelineHistoryRestHandler restHandler.PipelineHistoryRestHandler } -func NewPipelineRouterImpl(restHandler app.PipelineConfigRestHandler, appWorkflowRestHandler restHandler.AppWorkflowRestHandler, webhookDataRestHandler restHandler.WebhookDataRestHandler) *PipelineConfigRouterImpl { - return &PipelineConfigRouterImpl{restHandler: restHandler, appWorkflowRestHandler: appWorkflowRestHandler, webhookDataRestHandler: webhookDataRestHandler} +func NewPipelineRouterImpl(restHandler app.PipelineConfigRestHandler, + appWorkflowRestHandler restHandler.AppWorkflowRestHandler, + webhookDataRestHandler restHandler.WebhookDataRestHandler, + pipelineHistoryRestHandler restHandler.PipelineHistoryRestHandler) *PipelineConfigRouterImpl { + return &PipelineConfigRouterImpl{ + restHandler: restHandler, + appWorkflowRestHandler: appWorkflowRestHandler, + webhookDataRestHandler: webhookDataRestHandler, + pipelineHistoryRestHandler: pipelineHistoryRestHandler, + } } @@ -138,4 +147,38 @@ func (router PipelineConfigRouterImpl) initPipelineConfigRouter(configRouter *mu configRouter.Path("/pipeline/suggest/{type}/{appId}"). HandlerFunc(router.restHandler.PipelineNameSuggestion).Methods("GET") + + configRouter.Path("/history/cm/{appId}/{pipelineId}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeploymentDetailsForDeployedCMHistory). + Methods("GET") + configRouter.Path("/history/cs/{appId}/{pipelineId}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeploymentDetailsForDeployedCSHistory). + Methods("GET") + + configRouter.Path("/history/template/{appId}/{pipelineId}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeploymentDetailsForDeployedTemplatesHistory). + Methods("GET") + + configRouter.Path("/history/strategy/{appId}/{pipelineId}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeploymentDetailsForDeployedStrategyHistory). + Methods("GET") + + configRouter.Path("/history/cm/{appId}/{pipelineId}/{id}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeployedCMHistoryById). + Methods("GET") + configRouter.Path("/history/cs/{appId}/{pipelineId}/{id}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeployedCSHistoryById). + Methods("GET") + + configRouter.Path("/history/template/{appId}/{pipelineId}/{id}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeployedTemplatesHistoryById). + Methods("GET") + + configRouter.Path("/history/strategy/{appId}/{pipelineId}/{id}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeployedStrategyHistoryById). + Methods("GET") + + configRouter.Path("/history/cd-config/{appId}/{pipelineId}"). + HandlerFunc(router.pipelineHistoryRestHandler.FetchDeployedPrePostCdScriptHistory). + Methods("GET") } diff --git a/api/router/pubsub/ApplicationStatusUpdateHandler.go b/api/router/pubsub/ApplicationStatusUpdateHandler.go index 58f3e60f84..9ecfb28261 100644 --- a/api/router/pubsub/ApplicationStatusUpdateHandler.go +++ b/api/router/pubsub/ApplicationStatusUpdateHandler.go @@ -22,7 +22,9 @@ import ( v1alpha12 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1" "github.com/devtron-labs/devtron/client/pubsub" "github.com/devtron-labs/devtron/pkg/app" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/pipeline" + "github.com/go-pg/pg" "github.com/nats-io/stan.go" "go.uber.org/zap" "time" @@ -37,6 +39,7 @@ type ApplicationStatusUpdateHandlerImpl struct { pubsubClient *pubsub.PubSubClient appService app.AppService workflowDagExecutor pipeline.WorkflowDagExecutor + installedAppService service.InstalledAppService } const applicationStatusUpdate = "APPLICATION_STATUS_UPDATE" @@ -44,12 +47,13 @@ const applicationStatusUpdateGroup = "APPLICATION_STATUS_UPDATE_GROUP-1" const applicationStatusUpdateDurable = "APPLICATION_STATUS_UPDATE_DURABLE-1" func NewApplicationStatusUpdateHandlerImpl(logger *zap.SugaredLogger, pubsubClient *pubsub.PubSubClient, appService app.AppService, - workflowDagExecutor pipeline.WorkflowDagExecutor) *ApplicationStatusUpdateHandlerImpl { + workflowDagExecutor pipeline.WorkflowDagExecutor, installedAppService service.InstalledAppService) *ApplicationStatusUpdateHandlerImpl { appStatusUpdateHandlerImpl := &ApplicationStatusUpdateHandlerImpl{ logger: logger, pubsubClient: pubsubClient, appService: appService, workflowDagExecutor: workflowDagExecutor, + installedAppService: installedAppService, } err := appStatusUpdateHandlerImpl.Subscribe() if err != nil { @@ -73,6 +77,17 @@ func (impl *ApplicationStatusUpdateHandlerImpl) Subscribe() error { isHealthy, err := impl.appService.UpdateApplicationStatusAndCheckIsHealthy(application) if err != nil { impl.logger.Errorw("error on application status update", "err", err, "msg", string(msg.Data)) + + //TODO - check update for charts - fix this call + if err == pg.ErrNoRows { + // if not found in charts (which is for devtron apps) try to find in installed app (which is for devtron charts) + _, err := impl.installedAppService.UpdateInstalledAppVersionStatus(application) + if err != nil { + impl.logger.Errorw("error on application status update", "err", err, "msg", string(msg.Data)) + return + } + } + // return anyways weather updates or failure, no further processing for charts status update return } diff --git a/api/router/router.go b/api/router/router.go index 326d3aec23..3353f1c863 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -20,8 +20,11 @@ package router import ( "encoding/json" appStore "github.com/devtron-labs/devtron/api/appStore" + appStoreDeployment "github.com/devtron-labs/devtron/api/appStore/deployment" chartRepo "github.com/devtron-labs/devtron/api/chartRepo" "github.com/devtron-labs/devtron/api/cluster" + "github.com/devtron-labs/devtron/api/dashboardEvent" + "github.com/devtron-labs/devtron/api/deployment" client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/api/router/pubsub" @@ -92,6 +95,9 @@ type MuxRouter struct { helmAppRouter client.HelmAppRouter k8sApplicationRouter k8s.K8sApplicationRouter pProfRouter PProfRouter + deploymentConfigRouter deployment.DeploymentConfigRouter + dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter + commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter } func NewMuxRouter(logger *zap.SugaredLogger, HelmRouter HelmRouter, PipelineConfigRouter PipelineConfigRouter, @@ -113,7 +119,8 @@ func NewMuxRouter(logger *zap.SugaredLogger, HelmRouter HelmRouter, PipelineConf policyRouter PolicyRouter, gitOpsConfigRouter GitOpsConfigRouter, dashboardRouter dashboard.DashboardRouter, attributesRouter AttributesRouter, commonRouter CommonRouter, grafanaRouter GrafanaRouter, ssoLoginRouter sso.SsoLoginRouter, telemetryRouter TelemetryRouter, telemetryWatcher telemetry.TelemetryEventClient, bulkUpdateRouter BulkUpdateRouter, webhookListenerRouter WebhookListenerRouter, appLabelsRouter AppLabelRouter, coreAppRouter CoreAppRouter, helmAppRouter client.HelmAppRouter, k8sApplicationRouter k8s.K8sApplicationRouter, - pProfRouter PProfRouter) *MuxRouter { + pProfRouter PProfRouter, deploymentConfigRouter deployment.DeploymentConfigRouter, dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter, + commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter) *MuxRouter { r := &MuxRouter{ Router: mux.NewRouter(), HelmRouter: HelmRouter, @@ -166,6 +173,9 @@ func NewMuxRouter(logger *zap.SugaredLogger, HelmRouter HelmRouter, PipelineConf helmAppRouter: helmAppRouter, k8sApplicationRouter: k8sApplicationRouter, pProfRouter: pProfRouter, + deploymentConfigRouter: deploymentConfigRouter, + dashboardTelemetryRouter: dashboardTelemetryRouter, + commonDeploymentRouter: commonDeploymentRouter, } return r } @@ -314,12 +324,25 @@ func (r MuxRouter) Init() { webhookListenerRouter := r.Router.PathPrefix("/orchestrator/webhook/git").Subrouter() r.WebhookListenerRouter.InitWebhookListenerRouter(webhookListenerRouter) - helmApp := r.Router.PathPrefix("/orchestrator/application").Subrouter() - r.helmAppRouter.InitAppListRouter(helmApp) - k8sApp := r.Router.PathPrefix("/orchestrator/k8s").Subrouter() r.k8sApplicationRouter.InitK8sApplicationRouter(k8sApp) pProfListenerRouter := r.Router.PathPrefix("/orchestrator/debug/pprof").Subrouter() r.pProfRouter.initPProfRouter(pProfListenerRouter) + + // deployment router starts + deploymentConfigSubRouter := r.Router.PathPrefix("/orchestrator/deployment/template").Subrouter() + r.deploymentConfigRouter.Init(deploymentConfigSubRouter) + // deployment router ends + + // dashboard event router starts + dashboardTelemetryRouter := r.Router.PathPrefix("/orchestrator/dashboard-event").Subrouter() + r.dashboardTelemetryRouter.Init(dashboardTelemetryRouter) + // dashboard event router ends + + //GitOps,Acd + HelmCLi both apps deployment related api's + applicationSubRouter := r.Router.PathPrefix("/orchestrator/application").Subrouter() + r.commonDeploymentRouter.Init(applicationSubRouter) + //this router must placed after commonDeploymentRouter + r.helmAppRouter.InitAppListRouter(applicationSubRouter) } diff --git a/assets/Hyperion features.mp4 b/assets/Hyperion features.mp4 new file mode 100644 index 0000000000..50a25445dd Binary files /dev/null and b/assets/Hyperion features.mp4 differ diff --git a/client/k8s/informer/K8sInformerFactory.go b/client/k8s/informer/K8sInformerFactory.go index 5d15402ff6..badb37af7d 100644 --- a/client/k8s/informer/K8sInformerFactory.go +++ b/client/k8s/informer/K8sInformerFactory.go @@ -1,6 +1,13 @@ package informer import ( + "flag" + "os/user" + "path/filepath" + "sync" + "time" + + "github.com/devtron-labs/authenticator/client" "github.com/devtron-labs/devtron/api/bean" "go.uber.org/zap" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -8,8 +15,7 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" - "sync" - "time" + "k8s.io/client-go/tools/clientcmd" ) func NewGlobalMapClusterNamespace() map[string]map[string]bool { @@ -22,6 +28,7 @@ type K8sInformerFactoryImpl struct { globalMapClusterNamespace map[string]map[string]bool // {"cluster1":{"ns1":true","ns2":true"}} mutex sync.Mutex informerStopper map[string]chan struct{} + runtimeConfig *client.RuntimeConfig } type K8sInformerFactory interface { @@ -30,10 +37,11 @@ type K8sInformerFactory interface { CleanNamespaceInformer(clusterName string) } -func NewK8sInformerFactoryImpl(logger *zap.SugaredLogger, globalMapClusterNamespace map[string]map[string]bool) *K8sInformerFactoryImpl { +func NewK8sInformerFactoryImpl(logger *zap.SugaredLogger, globalMapClusterNamespace map[string]map[string]bool, runtimeConfig *client.RuntimeConfig) *K8sInformerFactoryImpl { informerFactory := &K8sInformerFactoryImpl{ logger: logger, globalMapClusterNamespace: globalMapClusterNamespace, + runtimeConfig: runtimeConfig, } informerFactory.informerStopper = make(map[string]chan struct{}) return informerFactory @@ -58,14 +66,30 @@ func (impl *K8sInformerFactoryImpl) GetLatestNamespaceListGroupByCLuster() map[s } func (impl *K8sInformerFactoryImpl) BuildInformer(clusterInfo []*bean.ClusterInfo) { + var restConfig *rest.Config for _, info := range clusterInfo { if info.ClusterName == "default_cluster" { - c, err := rest.InClusterConfig() - if err != nil { - impl.logger.Errorw("error in fetch default cluster config", "err", err) - continue + if impl.runtimeConfig.LocalDevMode { + usr, err := user.Current() + if err != nil { + impl.logger.Errorw("Error while getting user current env details", "error", err) + } + kubeconfig := flag.String("build-informer", filepath.Join(usr.HomeDir, ".kube", "config"), "(optional) absolute path to the kubeconfig file") + flag.Parse() + restConfig, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) + if err != nil { + impl.logger.Errorw("Error while building config from flags", "error", err) + } + } else { + clusterConfig, err := rest.InClusterConfig() + if err != nil { + impl.logger.Errorw("error in fetch default cluster config", "err", err, "servername", restConfig.ServerName) + continue + } + restConfig = clusterConfig } - impl.buildInformerAndNamespaceList(info.ClusterName, c, &impl.mutex) + + impl.buildInformerAndNamespaceList(info.ClusterName, restConfig, &impl.mutex) } else { c := &rest.Config{ Host: info.ServerUrl, diff --git a/client/telemetry/TelemetryEventClient.go b/client/telemetry/TelemetryEventClient.go index dd16fc03d0..1a19e4945d 100644 --- a/client/telemetry/TelemetryEventClient.go +++ b/client/telemetry/TelemetryEventClient.go @@ -37,7 +37,9 @@ type TelemetryEventClientImpl struct { type TelemetryEventClient interface { GetTelemetryMetaInfo() (*TelemetryMetaInfo, error) - SendTelemtryInstallEventEA() (*TelemetryEventType, error) + SendTelemetryInstallEventEA() (*TelemetryEventType, error) + SendTelemetryDashboardAccessEvent() error + SendTelemetryDashboardLoggedInEvent() error } func NewTelemetryEventClientImpl(logger *zap.SugaredLogger, client *http.Client, clusterService cluster.ClusterService, @@ -55,7 +57,7 @@ func NewTelemetryEventClientImpl(logger *zap.SugaredLogger, client *http.Client, } watcher.HeartbeatEventForTelemetry() - _, err := cron.AddFunc(SummaryCronExpr, watcher.SummaryEventForTelemetry) + _, err := cron.AddFunc(SummaryCronExpr, watcher.SummaryEventForTelemetryEA) if err != nil { logger.Errorw("error in starting summery event", "err", err) return nil, err @@ -92,6 +94,7 @@ type SummaryEA struct { const DevtronUniqueClientIdConfigMap = "devtron-ucid" const DevtronUniqueClientIdConfigMapKey = "UCID" const InstallEventKey = "installEvent" +const UIEventKey = "uiEventKey" type TelemetryEventType string @@ -109,6 +112,8 @@ const ( UpgradeFailure TelemetryEventType = "UpgradeFailure" Summary TelemetryEventType = "Summary" InstallationApplicationError TelemetryEventType = "InstallationApplicationError" + DashboardAccessed TelemetryEventType = "DashboardAccessed" + DashboardLoggedIn TelemetryEventType = "DashboardLoggedIn" ) func (impl *TelemetryEventClientImpl) SummaryDetailsForTelemetry() (cluster []cluster.ClusterBean, user []bean.UserInfo, k8sServerVersion *version.Info) { @@ -137,7 +142,7 @@ func (impl *TelemetryEventClientImpl) SummaryDetailsForTelemetry() (cluster []cl return clusters, users, k8sServerVersion } -func (impl *TelemetryEventClientImpl) SummaryEventForTelemetry() { +func (impl *TelemetryEventClientImpl) SummaryEventForTelemetryEA() { ucid, err := impl.getUCID() if err != nil { impl.logger.Errorw("exception caught inside telemetry summary event", "err", err) @@ -217,6 +222,7 @@ func (impl *TelemetryEventClientImpl) HeartbeatEventForTelemetry() { impl.logger.Errorw("exception caught inside telemetry heartbeat event", "err", err) return } + k8sServerVersion, err := discoveryClient.ServerVersion() if err != nil { impl.logger.Errorw("exception caught inside telemetry heartbeat event", "err", err) @@ -239,13 +245,12 @@ func (impl *TelemetryEventClientImpl) HeartbeatEventForTelemetry() { } err = impl.EnqueuePostHog(ucid, Heartbeat, prop) - if err == nil { - if err != nil { - impl.logger.Warnw("HeartbeatEventForTelemetry, failed to push event", "error", err) - } else { - impl.logger.Debugw("HeartbeatEventForTelemetry success") - } + if err != nil { + impl.logger.Warnw("HeartbeatEventForTelemetry, failed to push event", "error", err) + return } + impl.logger.Debugw("HeartbeatEventForTelemetry success") + return } func (impl *TelemetryEventClientImpl) GetTelemetryMetaInfo() (*TelemetryMetaInfo, error) { @@ -262,7 +267,7 @@ func (impl *TelemetryEventClientImpl) GetTelemetryMetaInfo() (*TelemetryMetaInfo return data, err } -func (impl *TelemetryEventClientImpl) SendTelemtryInstallEventEA() (*TelemetryEventType, error) { +func (impl *TelemetryEventClientImpl) SendTelemetryInstallEventEA() (*TelemetryEventType, error) { ucid, err := impl.getUCID() if err != nil { impl.logger.Errorw("exception while getting unique client id", "error", err) @@ -310,6 +315,102 @@ func (impl *TelemetryEventClientImpl) SendTelemtryInstallEventEA() (*TelemetryEv return nil, nil } +func (impl *TelemetryEventClientImpl) SendTelemetryDashboardAccessEvent() error { + ucid, err := impl.getUCID() + if err != nil { + impl.logger.Errorw("exception while getting unique client id", "error", err) + return err + } + + client, err := impl.K8sUtil.GetClientForInCluster() + if err != nil { + impl.logger.Errorw("exception while getting unique client id", "error", err) + return err + } + + payload := &TelemetryEventEA{UCID: ucid, Timestamp: time.Now(), EventType: DashboardAccessed, DevtronVersion: "v1"} + payload.DevtronMode = util.GetDevtronVersion().ServerMode + + reqBody, err := json.Marshal(payload) + if err != nil { + impl.logger.Errorw("DashboardAccessed EventForTelemetry, payload marshal error", "error", err) + return err + } + prop := make(map[string]interface{}) + err = json.Unmarshal(reqBody, &prop) + if err != nil { + impl.logger.Errorw("DashboardAccessed EventForTelemetry, payload unmarshal error", "error", err) + return err + } + cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) + datamap := cm.Data + + accessEventValue, installEventKeyExists := datamap[UIEventKey] + + if installEventKeyExists == false || accessEventValue <= "1" { + err = impl.EnqueuePostHog(ucid, DashboardAccessed, prop) + if err == nil { + datamap[UIEventKey] = "2" + cm.Data = datamap + _, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) + if err != nil { + impl.logger.Warnw("config map update failed for install event", "err", err) + } else { + impl.logger.Debugw("config map apply succeeded for install event") + } + } + } + return nil +} + +func (impl *TelemetryEventClientImpl) SendTelemetryDashboardLoggedInEvent() error { + ucid, err := impl.getUCID() + if err != nil { + impl.logger.Errorw("exception while getting unique client id", "error", err) + return err + } + + client, err := impl.K8sUtil.GetClientForInCluster() + if err != nil { + impl.logger.Errorw("exception while getting unique client id", "error", err) + return err + } + + payload := &TelemetryEventEA{UCID: ucid, Timestamp: time.Now(), EventType: DashboardLoggedIn, DevtronVersion: "v1"} + payload.DevtronMode = util.GetDevtronVersion().ServerMode + + reqBody, err := json.Marshal(payload) + if err != nil { + impl.logger.Errorw("DashboardLoggedIn EventForTelemetry, payload marshal error", "error", err) + return err + } + prop := make(map[string]interface{}) + err = json.Unmarshal(reqBody, &prop) + if err != nil { + impl.logger.Errorw("DashboardLoggedIn EventForTelemetry, payload unmarshal error", "error", err) + return err + } + cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, DevtronUniqueClientIdConfigMap, client) + datamap := cm.Data + + accessEventValue, installEventKeyExists := datamap[UIEventKey] + + if installEventKeyExists == false || accessEventValue != "3" { + err = impl.EnqueuePostHog(ucid, DashboardLoggedIn, prop) + if err == nil { + datamap[UIEventKey] = "3" + cm.Data = datamap + _, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) + if err != nil { + impl.logger.Warnw("config map update failed for install event", "err", err) + } else { + impl.logger.Debugw("config map apply succeeded for install event") + } + } + } + return nil +} + type TelemetryMetaInfo struct { Url string `json:"url,omitempty"` UCID string `json:"ucid,omitempty"` @@ -334,6 +435,7 @@ func (impl *TelemetryEventClientImpl) getUCID() (string, error) { data := map[string]string{} data[DevtronUniqueClientIdConfigMapKey] = util.Generate(16) // generate unique random number data[InstallEventKey] = "1" // used in operator to detect event is install or upgrade + data[UIEventKey] = "1" cm.Data = data _, err = impl.K8sUtil.CreateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client) if err != nil { diff --git a/client/telemetry/TelemetryEventClientExtended.go b/client/telemetry/TelemetryEventClientExtended.go index 46f573c078..dc959a1b42 100644 --- a/client/telemetry/TelemetryEventClientExtended.go +++ b/client/telemetry/TelemetryEventClientExtended.go @@ -24,7 +24,7 @@ type TelemetryEventClientImplExtended struct { *TelemetryEventClientImpl } -func (impl *TelemetryEventClientImplExtended) NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http.Client, clusterService cluster.ClusterService, +func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http.Client, clusterService cluster.ClusterService, K8sUtil *util2.K8sUtil, aCDAuthConfig *util3.ACDAuthConfig, environmentService cluster.EnvironmentService, userService user.UserService, appListingRepository repository.AppListingRepository, PosthogClient *PosthogClient, @@ -101,7 +101,6 @@ func (impl *TelemetryEventClientImplExtended) SummaryEventForTelemetry() { } clusters, users, k8sServerVersion := impl.SummaryDetailsForTelemetry() - payload := &TelemetryEventDto{UCID: ucid, Timestamp: time.Now(), EventType: Summary, DevtronVersion: "v1"} payload.ServerVersion = k8sServerVersion.String() diff --git a/cmd/external-app/externalApp.go b/cmd/external-app/externalApp.go index 4fcc1e3ed7..a54225c685 100644 --- a/cmd/external-app/externalApp.go +++ b/cmd/external-app/externalApp.go @@ -43,7 +43,7 @@ func (app *App) Start() { app.MuxRouter.Init() //authEnforcer := casbin2.Create() - _, err := app.telemetry.SendTelemtryInstallEventEA() + _, err := app.telemetry.SendTelemetryInstallEventEA() if err != nil { app.Logger.Warnw("telemetry installation success event failed", "err", err) diff --git a/cmd/external-app/router.go b/cmd/external-app/router.go index a05ecfa037..693bc1cc6b 100644 --- a/cmd/external-app/router.go +++ b/cmd/external-app/router.go @@ -7,6 +7,7 @@ import ( appStoreValues "github.com/devtron-labs/devtron/api/appStore/values" "github.com/devtron-labs/devtron/api/chartRepo" "github.com/devtron-labs/devtron/api/cluster" + "github.com/devtron-labs/devtron/api/dashboardEvent" client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/api/sso" @@ -36,6 +37,8 @@ type MuxRouter struct { appStoreDiscoverRouter appStoreDiscover.AppStoreDiscoverRouter appStoreValuesRouter appStoreValues.AppStoreValuesRouter appStoreDeploymentRouter appStoreDeployment.AppStoreDeploymentRouter + dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter + commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter } func NewMuxRouter( @@ -53,7 +56,8 @@ func NewMuxRouter( appStoreDiscoverRouter appStoreDiscover.AppStoreDiscoverRouter, appStoreValuesRouter appStoreValues.AppStoreValuesRouter, appStoreDeploymentRouter appStoreDeployment.AppStoreDeploymentRouter, - + dashboardTelemetryRouter dashboardEvent.DashboardTelemetryRouter, + commonDeploymentRouter appStoreDeployment.CommonDeploymentRouter, ) *MuxRouter { r := &MuxRouter{ Router: mux.NewRouter(), @@ -71,6 +75,8 @@ func NewMuxRouter( appStoreDiscoverRouter: appStoreDiscoverRouter, appStoreValuesRouter: appStoreValuesRouter, appStoreDeploymentRouter: appStoreDeploymentRouter, + dashboardTelemetryRouter: dashboardTelemetryRouter, + commonDeploymentRouter: commonDeploymentRouter, } return r } @@ -125,8 +131,10 @@ func (r *MuxRouter) Init() { dashboardRouter := r.Router.PathPrefix("/dashboard").Subrouter() r.dashboardRouter.InitDashboardRouter(dashboardRouter) - helmApp := r.Router.PathPrefix("/orchestrator/application").Subrouter() - r.helmAppRouter.InitAppListRouter(helmApp) + applicationSubRouter := r.Router.PathPrefix("/orchestrator/application").Subrouter() + r.helmAppRouter.InitAppListRouter(applicationSubRouter) + r.commonDeploymentRouter.Init(applicationSubRouter) + k8sApp := r.Router.PathPrefix("/orchestrator/k8s").Subrouter() r.k8sApplicationRouter.InitK8sApplicationRouter(k8sApp) @@ -149,4 +157,9 @@ func (r *MuxRouter) Init() { appStoreDeploymentSubRouter := r.Router.PathPrefix("/orchestrator/app-store/deployment").Subrouter() r.appStoreDeploymentRouter.Init(appStoreDeploymentSubRouter) // app-store deployment router ends + + // dashboard event router starts + dashboardTelemetryRouter := r.Router.PathPrefix("/orchestrator/dashboard-event").Subrouter() + r.dashboardTelemetryRouter.Init(dashboardTelemetryRouter) + // dashboard event router ends } diff --git a/cmd/external-app/wire.go b/cmd/external-app/wire.go index 1e6ee181b8..5402b19d76 100644 --- a/cmd/external-app/wire.go +++ b/cmd/external-app/wire.go @@ -11,6 +11,7 @@ import ( chartRepo "github.com/devtron-labs/devtron/api/chartRepo" "github.com/devtron-labs/devtron/api/cluster" "github.com/devtron-labs/devtron/api/connector" + "github.com/devtron-labs/devtron/api/dashboardEvent" client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/sso" "github.com/devtron-labs/devtron/api/team" @@ -24,6 +25,7 @@ import ( appStoreDeploymentTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" appStoreDeploymentGitopsTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool/gitops" delete2 "github.com/devtron-labs/devtron/pkg/delete" + "github.com/devtron-labs/devtron/pkg/pipeline" "github.com/devtron-labs/devtron/pkg/sql" util2 "github.com/devtron-labs/devtron/pkg/util" util3 "github.com/devtron-labs/devtron/util" @@ -83,6 +85,15 @@ func InitializeApp() (*App, error) { // binding gitops to helm (for hyperion) wire.Bind(new(appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdService), new(*appStoreDeploymentTool.AppStoreDeploymentHelmServiceImpl)), + + wire.Value(pipeline.RefChartDir("scripts/devtron-reference-helm-charts")), + + //needed for sending events + dashboardEvent.NewDashboardTelemetryRestHandlerImpl, + wire.Bind(new(dashboardEvent.DashboardTelemetryRestHandler), new(*dashboardEvent.DashboardTelemetryRestHandlerImpl)), + dashboardEvent.NewDashboardTelemetryRouterImpl, + wire.Bind(new(dashboardEvent.DashboardTelemetryRouter), + new(*dashboardEvent.DashboardTelemetryRouterImpl)), ) return &App{}, nil } diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index f2d1df66eb..ca76f46806 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -8,12 +8,13 @@ package main import ( "github.com/devtron-labs/authenticator/client" "github.com/devtron-labs/authenticator/middleware" - appStoreDeployment2 "github.com/devtron-labs/devtron/api/appStore/deployment" - appStoreDiscover2 "github.com/devtron-labs/devtron/api/appStore/discover" - appStoreValues2 "github.com/devtron-labs/devtron/api/appStore/values" + "github.com/devtron-labs/devtron/api/appStore/deployment" + "github.com/devtron-labs/devtron/api/appStore/discover" + "github.com/devtron-labs/devtron/api/appStore/values" chartRepo2 "github.com/devtron-labs/devtron/api/chartRepo" cluster2 "github.com/devtron-labs/devtron/api/cluster" "github.com/devtron-labs/devtron/api/connector" + "github.com/devtron-labs/devtron/api/dashboardEvent" client2 "github.com/devtron-labs/devtron/api/helm-app" sso2 "github.com/devtron-labs/devtron/api/sso" team2 "github.com/devtron-labs/devtron/api/team" @@ -25,19 +26,20 @@ import ( "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" "github.com/devtron-labs/devtron/internal/util" - "github.com/devtron-labs/devtron/pkg/appStore/deployment" "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" + repository3 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" + service3 "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" - "github.com/devtron-labs/devtron/pkg/appStore/discover" "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - "github.com/devtron-labs/devtron/pkg/appStore/repository" - "github.com/devtron-labs/devtron/pkg/appStore/values" + "github.com/devtron-labs/devtron/pkg/appStore/discover/service" "github.com/devtron-labs/devtron/pkg/appStore/values/repository" + service2 "github.com/devtron-labs/devtron/pkg/appStore/values/service" "github.com/devtron-labs/devtron/pkg/chartRepo" "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/pkg/cluster" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" delete2 "github.com/devtron-labs/devtron/pkg/delete" + "github.com/devtron-labs/devtron/pkg/pipeline" "github.com/devtron-labs/devtron/pkg/sql" "github.com/devtron-labs/devtron/pkg/sso" "github.com/devtron-labs/devtron/pkg/team" @@ -46,6 +48,7 @@ import ( "github.com/devtron-labs/devtron/pkg/user/casbin" "github.com/devtron-labs/devtron/pkg/user/repository" util2 "github.com/devtron-labs/devtron/pkg/util" + util3 "github.com/devtron-labs/devtron/util" "github.com/devtron-labs/devtron/util/k8s" "github.com/devtron-labs/devtron/util/rbac" ) @@ -103,7 +106,7 @@ func InitializeApp() (*App, error) { teamServiceImpl := team.NewTeamServiceImpl(sugaredLogger, teamRepositoryImpl, userAuthServiceImpl) clusterRepositoryImpl := repository2.NewClusterRepositoryImpl(db, sugaredLogger) v := informer.NewGlobalMapClusterNamespace() - k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, v) + k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, v, runtimeConfig) clusterServiceImpl := cluster.NewClusterServiceImpl(clusterRepositoryImpl, sugaredLogger, k8sUtil, k8sInformerFactoryImpl) environmentRepositoryImpl := repository2.NewEnvironmentRepositoryImpl(db) environmentServiceImpl := cluster.NewEnvironmentServiceImpl(environmentRepositoryImpl, clusterServiceImpl, sugaredLogger, k8sUtil, k8sInformerFactoryImpl, userAuthServiceImpl) @@ -140,7 +143,7 @@ func InitializeApp() (*App, error) { pumpImpl := connector.NewPumpImpl(sugaredLogger) enforcerUtilHelmImpl := rbac.NewEnforcerUtilHelmImpl(sugaredLogger, clusterRepositoryImpl) helmAppServiceImpl := client2.NewHelmAppServiceImpl(sugaredLogger, clusterServiceImpl, helmAppClientImpl, pumpImpl, enforcerUtilHelmImpl) - installedAppRepositoryImpl := appStoreRepository.NewInstalledAppRepositoryImpl(sugaredLogger, db) + installedAppRepositoryImpl := repository3.NewInstalledAppRepositoryImpl(sugaredLogger, db) appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl) helmAppRestHandlerImpl := client2.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImpl, enforcerUtilHelmImpl, appStoreDeploymentCommonServiceImpl) helmAppRouterImpl := client2.NewHelmAppRouterImpl(helmAppRestHandlerImpl) @@ -151,26 +154,32 @@ func InitializeApp() (*App, error) { terminalSessionHandlerImpl := terminal.NewTerminalSessionHandlerImpl(environmentServiceImpl, clusterServiceImpl, sugaredLogger) k8sApplicationRestHandlerImpl := k8s.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, clusterServiceImpl, helmAppServiceImpl) k8sApplicationRouterImpl := k8s.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) - chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceImpl) + chartRefRepositoryImpl := chartRepoRepository.NewChartRefRepositoryImpl(db) + refChartDir := _wireRefChartDirValue + chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceImpl, chartRefRepositoryImpl, refChartDir) chartRepositoryRouterImpl := chartRepo2.NewChartRepositoryRouterImpl(chartRepositoryRestHandlerImpl) appStoreApplicationVersionRepositoryImpl := appStoreDiscoverRepository.NewAppStoreApplicationVersionRepositoryImpl(sugaredLogger, db) - appStoreServiceImpl := appStoreDiscover.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) - appStoreRestHandlerImpl := appStoreDiscover2.NewAppStoreRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreServiceImpl, enforcerImpl) - appStoreDiscoverRouterImpl := appStoreDiscover2.NewAppStoreDiscoverRouterImpl(appStoreRestHandlerImpl) + appStoreServiceImpl := service.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) + appStoreRestHandlerImpl := appStoreDiscover.NewAppStoreRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreServiceImpl, enforcerImpl) + appStoreDiscoverRouterImpl := appStoreDiscover.NewAppStoreDiscoverRouterImpl(appStoreRestHandlerImpl) appStoreVersionValuesRepositoryImpl := appStoreValuesRepository.NewAppStoreVersionValuesRepositoryImpl(sugaredLogger, db) - appStoreValuesServiceImpl := appStoreValues.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl) - appStoreValuesRestHandlerImpl := appStoreValues2.NewAppStoreValuesRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreValuesServiceImpl) - appStoreValuesRouterImpl := appStoreValues2.NewAppStoreValuesRouterImpl(appStoreValuesRestHandlerImpl) + appStoreValuesServiceImpl := service2.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl) + appStoreValuesRestHandlerImpl := appStoreValues.NewAppStoreValuesRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreValuesServiceImpl) + appStoreValuesRouterImpl := appStoreValues.NewAppStoreValuesRouterImpl(appStoreValuesRestHandlerImpl) appRepositoryImpl := app.NewAppRepositoryImpl(db) pipelineRepositoryImpl := pipelineConfig.NewPipelineRepositoryImpl(db, sugaredLogger) ciPipelineRepositoryImpl := pipelineConfig.NewCiPipelineRepositoryImpl(db, sugaredLogger) enforcerUtilImpl := rbac.NewEnforcerUtilImpl(sugaredLogger, teamRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, ciPipelineRepositoryImpl, clusterRepositoryImpl) - clusterInstalledAppsRepositoryImpl := appStoreRepository.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) - appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl) - appStoreDeploymentServiceImpl := appStoreDeployment.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentHelmServiceImpl, environmentServiceImpl, clusterServiceImpl) - appStoreDeploymentRestHandlerImpl := appStoreDeployment2.NewAppStoreDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate) - appStoreDeploymentRouterImpl := appStoreDeployment2.NewAppStoreDeploymentRouterImpl(appStoreDeploymentRestHandlerImpl) - muxRouter := NewMuxRouter(sugaredLogger, ssoLoginRouterImpl, teamRouterImpl, userAuthRouterImpl, userRouterImpl, clusterRouterImpl, dashboardRouterImpl, helmAppRouterImpl, environmentRouterImpl, k8sApplicationRouterImpl, chartRepositoryRouterImpl, appStoreDiscoverRouterImpl, appStoreValuesRouterImpl, appStoreDeploymentRouterImpl) + clusterInstalledAppsRepositoryImpl := repository3.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) + appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, helmAppClientImpl) + globalEnvVariables, err := util3.GetGlobalEnvVariables() + if err != nil { + return nil, err + } + installedAppVersionHistoryRepositoryImpl := repository3.NewInstalledAppVersionHistoryRepositoryImpl(sugaredLogger, db) + appStoreDeploymentServiceImpl := service3.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentHelmServiceImpl, environmentServiceImpl, clusterServiceImpl, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, globalEnvVariables, installedAppVersionHistoryRepositoryImpl) + appStoreDeploymentRestHandlerImpl := appStoreDeployment.NewAppStoreDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl) + appStoreDeploymentRouterImpl := appStoreDeployment.NewAppStoreDeploymentRouterImpl(appStoreDeploymentRestHandlerImpl) posthogClient, err := telemetry.NewPosthogClient(sugaredLogger) if err != nil { return nil, err @@ -179,6 +188,15 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } + dashboardTelemetryRestHandlerImpl := dashboardEvent.NewDashboardTelemetryRestHandlerImpl(sugaredLogger, telemetryEventClientImpl) + dashboardTelemetryRouterImpl := dashboardEvent.NewDashboardTelemetryRouterImpl(dashboardTelemetryRestHandlerImpl) + commonDeploymentRestHandlerImpl := appStoreDeployment.NewCommonDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, helmAppRestHandlerImpl) + commonDeploymentRouterImpl := appStoreDeployment.NewCommonDeploymentRouterImpl(commonDeploymentRestHandlerImpl) + muxRouter := NewMuxRouter(sugaredLogger, ssoLoginRouterImpl, teamRouterImpl, userAuthRouterImpl, userRouterImpl, clusterRouterImpl, dashboardRouterImpl, helmAppRouterImpl, environmentRouterImpl, k8sApplicationRouterImpl, chartRepositoryRouterImpl, appStoreDiscoverRouterImpl, appStoreValuesRouterImpl, appStoreDeploymentRouterImpl, dashboardTelemetryRouterImpl, commonDeploymentRouterImpl) mainApp := NewApp(db, sessionManager, muxRouter, telemetryEventClientImpl, sugaredLogger) return mainApp, nil } + +var ( + _wireRefChartDirValue = pipeline.RefChartDir("scripts/devtron-reference-helm-charts") +) diff --git a/developers-guide/DeploymentTemplate.md b/developers-guide/DeploymentTemplate.md new file mode 100644 index 0000000000..7183e4fc88 --- /dev/null +++ b/developers-guide/DeploymentTemplate.md @@ -0,0 +1,36 @@ +#Global Deployment Template + +## Create (db table - charts) :- + +1. charts.Values = values.yaml(from ref chart) + charts.global_override +2. charts.GlobalOverride = charts.global_override + global_override(different for different cases, find details below) +3. charts.ReleaseOverrides = release-values.yaml(from ref chart) +4. charts.PipelineOverrides = pipeline-values.yaml(from ref chart) +5. charts.ImageDescriptorTemplate = image_descriptor_template.json (from ref chart) + +### GlobalOverride values from UI - + +1. Case 1, new app = app-values.yaml + env-values.yaml (both from ref chart) +2. Case 2, old app = Value of charts.global_override (from db) + +#Env Template + +## Create (db table - chart_env_config_override) :- + +1. Case 1, env is overridden +- chart_env_config_override.env_override_yaml = chart_env_config_override.env_override_yaml(from UI) +- In this case chart_env_config_override.env_override_yaml is used for release +2. Case 2, env is not overridden +- chart_env_config_override.env_override_yaml = "{}" +- In this case charts.global_override is used for release + +#Pipeline Strategy + +Config is stored in pipeline_strategy.Config + +#Deployment Triggered - + +## Create (db table - pipeline_config_override) :- + +1. pipeline_config_override.pipeline_override_yaml = rendered value of image descriptor template +2. pipeline_config_override.merged_values_yaml = All values merged which are going to be committed on git (Values - charts.global_override + chart_env_config_override.env_override_yaml + cm/secrets(converted to json) + pipeline_strategy.config) \ No newline at end of file diff --git a/docs/FAQs/devtron-troubleshoot.md b/docs/FAQs/devtron-troubleshoot.md index 503fa69619..46e933bf89 100644 --- a/docs/FAQs/devtron-troubleshoot.md +++ b/docs/FAQs/devtron-troubleshoot.md @@ -106,22 +106,30 @@ If using Firefox - 1. Goto login page of Devtron and open inspect. 2. Navigate to storage tab in inspect. 3. Click on url where Devtron has been installed under `Cookies` tab and you could see an argocd token with its value, something similar to below image. + ![inspect-cookies](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/devtron-troubleshooting/argocd-cookie.png) + 4. Now right click on token, and click on `Delete All Session Cookies` option. If using Chrome - 1. Goto login page of Devtron and open inspect. 2. Navigate to Application tab, and under `Storage` tab click on `Cookies`. 3. Click on url under `Cookie` and you would be able tto see an argocd token with its value, as shown in the image below. + ![chrome-cookie](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/devtron-troubleshooting/chrome-cookie.png) + 4. Now right click on token and click on `delete` option. If using Safari - 1. Goto Safari preferences >> Advanced options and check the show develop menu as shown in the image below. + ![safari-preferences](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/devtron-troubleshooting/safari-preferences.png) + 2. Now goto login page of Devtron and press `option+command+I`. It will open inspect element. 3. Then navigate to `Storage`, click on `Cookies` and you would be able to see an argocd token with its value as shown in the image below. + ![safari-cookie](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/devtron-troubleshooting/safari-cookie.png) + 4. Now right click on token and select `delete` option. After clearing `Cookies`, try again to login, you should be able to login now. @@ -129,7 +137,8 @@ After clearing `Cookies`, try again to login, you should be able to login now. #### 7. No charts found in Charts Discover Section -In the Devtron's Discover Chart section, if you are not able to see any charts available, goto `Global Configuration` >> `Chart Repositories` and click on `Refresh Chart` at the top-right as shown in the image below. After clicking the button, it might take 4-5mins to show all the charts in `Discover` section depending upon the chart repositories added. +In the Devtron's Discover Chart section, if you are not able to see any charts available, goto `Global Configuration` >> `Chart Repositories` and click on `Refresh Chart` at the top-right as shown in the image below. After clicking the button, it might take 4-5mins to show all the charts in `Discover` section depending upon the chart repositories added. + ![charts-not-found](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/devtron-troubleshooting/refresh-charts.png) diff --git a/docs/hyperion/user-guide/global-configurations/cluster-and-environments.md b/docs/hyperion/user-guide/global-configurations/cluster-and-environments.md index dd79878285..1616e39020 100644 --- a/docs/hyperion/user-guide/global-configurations/cluster-and-environments.md +++ b/docs/hyperion/user-guide/global-configurations/cluster-and-environments.md @@ -24,7 +24,7 @@ Navigate to the `Global Configurations` → `Clusters and Environments` on devtr * TLS Certificate -![](../../user-guide/global-configurations/images/cluster-1.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/cluster-and-environments/cluster-1.jpg) ### 1. Name @@ -77,11 +77,11 @@ on saving or update a cluster there is a call to fetch k8s version, it will stor Check the below screenshots to know how it looks like If you select the `Basic` authentication type -![](../../user-guide/global-configurations/images/cluster-2.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/cluster-and-environments/cluster-2.jpg) If you select the `Anonymous` authentication type -![](../../user-guide/global-configurations/images/cluster-1.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/cluster-and-environments/cluster-1.jpg) Now click on `Save Cluster` to save your cluster information. @@ -89,17 +89,17 @@ Now click on `Save Cluster` to save your cluster information. Your kubernetes cluster gets mapped with the Devtron when you save your kubernetes cluster Configuration. Now the agents of devtron will be installed on your cluster so that the components of devtron can communicate to your cluster. When the agent starts installing on your cluster, you can check the status of the agents in the Cluster & Environment tab also. -![](../../.gitbook/assets/gc-cluster-agents.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/cluster-and-environments/gc-cluster-agents.jpg) Click on `Details` to check what got installed inside the agents. A new window will be popped up displaying all the details about these agents. -![](../../.gitbook/assets/cluster_gc5.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/cluster-and-environments/cluster_gc5.jpg) ## Add Environment Once you have added your cluster in Cluster & Environment, you can add the environment also. Click on `Add Environment`, a window will be opened. Give a name to your environment in the `Environment Name` box and provide a namespace corresponding to your environment in the `Namespace` input box. Now choose if your environment is for Production purposes or for Non-production purposes. Production and Non-production options are only for tagging purposes. Click on `Save` and your environment will be created. -![](../../.gitbook/assets/gc-cluster-add-environment%20%283%29.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/cluster-and-environments/gc-cluster-add-environment.jpg) You can update an already created environment, Select and click on the environment which you want to update. You can only change Production and Non-production options here. @@ -107,7 +107,7 @@ You can update an already created environment, Select and click on the environme You can not change the Environment name and Namespace name. -![](../../.gitbook/assets/gc-cluster-update-environment%20%281%29.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/cluster-and-environments/gc-cluster-update-environment.jpg) Click on `Update` to update your environment. diff --git a/docs/hyperion/user-guide/global-configurations/sso-login.md b/docs/hyperion/user-guide/global-configurations/sso-login.md index 8b5864a6c0..884c87077d 100644 --- a/docs/hyperion/user-guide/global-configurations/sso-login.md +++ b/docs/hyperion/user-guide/global-configurations/sso-login.md @@ -1,7 +1,7 @@ # SSO LOGIN -## OVERVIEW +## Overview -Once installed DEVTRON has one built-in `admin` user with super-admin privileges that is complete access to the system. It is recommended to use `admin` user only for initial and global configuration and then switch to local users or configure SSO integration. +Once installed Devtron has one built-in `admin` user with super-admin privileges that has complete access to the system. It is recommended to use `admin` user only for initial and global configuration and then switch to local users or configure SSO integration. Only users with super-admin privileges have access to create SSO configuration. Devtron uses dex for authenticating a user against the identity provider. @@ -32,11 +32,11 @@ Fill correct `redirect URL` or `callback URL` from which you have registered wit Only single SSO login configuration can be active at one time. Whenever you create or update any SSO config, it will be activated and used by the system and previous configurations will be deleted. -URL and redirectURI should be same as provided in screenshots except domain substring. +Except for the domain substring, URL and redirectURI should be the same as in the screenshots. -![](../../user-guide/global-configurations/images/sso-login.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/sso-login-service/sso-login.jpg) -Click on `Save` bottom for creating and activating sso login on bottom right of the configuration. +Select `Save` to create and activate SSO login. ### 2. Update SSO Configuration diff --git a/docs/hyperion/user-guide/global-configurations/user-access.md b/docs/hyperion/user-guide/global-configurations/user-access.md index ab0f9d42e0..b6f7649777 100644 --- a/docs/hyperion/user-guide/global-configurations/user-access.md +++ b/docs/hyperion/user-guide/global-configurations/user-access.md @@ -20,8 +20,8 @@ Devtron supports 4 levels of access |Admin| Yes | Yes | Yes | Yes | Yes | |Super Admin| Yes | Yes | Yes | Yes | Yes |
-## Visualize using access table (Charts) +## Visualize using access table (Charts) | Access Level | View Charts | Install Charts | Edit Charts | Delete Charts | |--|--|--|--|--| | View | Yes | No | No | No| diff --git a/docs/images/creating-application/deployment-template/deployment_application_metrics.png b/docs/images/creating-application/deployment-template/deployment_application_metrics.png deleted file mode 100644 index 215df893e6..0000000000 Binary files a/docs/images/creating-application/deployment-template/deployment_application_metrics.png and /dev/null differ diff --git a/docs/images/deleting-application/deleting-delete-application-1.jpg b/docs/images/deleting-application/deleting-delete-application-1.jpg deleted file mode 100755 index 420251b8f6..0000000000 Binary files a/docs/images/deleting-application/deleting-delete-application-1.jpg and /dev/null differ diff --git a/docs/images/deleting-application/deleting-workflow-1.jpg b/docs/images/deleting-application/deleting-workflow-1.jpg deleted file mode 100755 index 1f000722aa..0000000000 Binary files a/docs/images/deleting-application/deleting-workflow-1.jpg and /dev/null differ diff --git a/docs/images/deploy-chart/overview-of-charts/chart-store.jpg b/docs/images/deploy-chart/overview-of-charts/chart-store.jpg new file mode 100644 index 0000000000..ae770e8353 Binary files /dev/null and b/docs/images/deploy-chart/overview-of-charts/chart-store.jpg differ diff --git a/docs/images/deploy-chart/overview-of-charts/custom1.jpg b/docs/images/deploy-chart/overview-of-charts/custom1.jpg new file mode 100644 index 0000000000..a5bbf7678a Binary files /dev/null and b/docs/images/deploy-chart/overview-of-charts/custom1.jpg differ diff --git a/docs/images/deploy-chart/overview-of-charts/deploy-chart.jpg b/docs/images/deploy-chart/overview-of-charts/deploy-chart.jpg new file mode 100644 index 0000000000..68df9c9cbc Binary files /dev/null and b/docs/images/deploy-chart/overview-of-charts/deploy-chart.jpg differ diff --git a/docs/images/deploy-chart/overview-of-charts/readme.jpg b/docs/images/deploy-chart/overview-of-charts/readme.jpg new file mode 100644 index 0000000000..08c4da0ca6 Binary files /dev/null and b/docs/images/deploy-chart/overview-of-charts/readme.jpg differ diff --git a/docs/images/deploy-chart/overview-of-charts/update-and-deploy.jpg b/docs/images/deploy-chart/overview-of-charts/update-and-deploy.jpg new file mode 100644 index 0000000000..8a56fb4a6b Binary files /dev/null and b/docs/images/deploy-chart/overview-of-charts/update-and-deploy.jpg differ diff --git a/docs/images/deploy-chart/overview-of-charts/values.jpg b/docs/images/deploy-chart/overview-of-charts/values.jpg new file mode 100644 index 0000000000..efe282fe78 Binary files /dev/null and b/docs/images/deploy-chart/overview-of-charts/values.jpg differ diff --git a/docs/setup/install/install-devtron-helm-2.md b/docs/setup/install/install-devtron-helm-2.md index cb402d6f94..132e06ab86 100644 --- a/docs/setup/install/install-devtron-helm-2.md +++ b/docs/setup/install/install-devtron-helm-2.md @@ -69,7 +69,13 @@ Run following command kubectl -n devtroncd get installers installer-devtron -o jsonpath='{.status.sync.status}' ``` -The install commands initiates Devtron-operator which spins up all the Devtron micro-services one by one in about 20 mins. You can use the above command to check the status of the installation if the installation is still in progress, it will print `Downloaded`. When the installation is complete, it prints `Applied`. +The install commands initiates Devtron-operator which spins up all the Devtron micro-services one by one in about 20 mins. You can use the above command to check the status of the installation. + +| Status | Description | +| :--- | :--- | +| `Downloaded` | Installer has downloaded all the manifests and installation is in progress. | +| `Applied` | Installer has successfully applied all the manifest and installation is complete. | + Meanwhile, you can check logs of the installer by executing the following command: ```bash @@ -93,6 +99,8 @@ You will get result something like below The hostname mentioned here \( aaff16e9760594a92afa0140dbfd99f7-305259315.us-east-1.elb.amazonaws.com \) is the Loadbalancer URL where you can access the Devtron dashboard. +Incase you don't see the results or get a message "service doesnt exist", it means devtron is still installing, please check again after 5 minutes. + **PS:** You can also do a CNAME entry corresponding to your domain/subdomain to point to this Loadbalancer URL to access it at a custom domain. | Host | Type | Points to | diff --git a/docs/setup/install/install-devtron-helm-3.md b/docs/setup/install/install-devtron-helm-3.md index cce1c1872b..6d83f73e2a 100644 --- a/docs/setup/install/install-devtron-helm-3.md +++ b/docs/setup/install/install-devtron-helm-3.md @@ -62,7 +62,13 @@ Run following command kubectl -n devtroncd get installers installer-devtron -o jsonpath='{.status.sync.status}' ``` -The install commands initiates Devtron-operator which spins up all the Devtron micro-services one by one in about 20 mins. You can use the above command to check the status of the installation if the installation is still in progress, it will print `Downloaded`. When the installation is complete, it prints `Applied`. +The install commands initiates Devtron-operator which spins up all the Devtron micro-services one by one in about 20 mins. You can use the above command to check the status of the installation. + +| Status | Description | +| :--- | :--- | +| `Downloaded` | Installer has downloaded all the manifests and installation is in progress. | +| `Applied` | Installer has successfully applied all the manifest and installation is complete. | + Meanwhile, you can check logs of the installer by executing the following command: ```bash @@ -86,6 +92,8 @@ You will get result something like below The hostname mentioned here \( aaff16e9760594a92afa0140dbfd99f7-305259315.us-east-1.elb.amazonaws.com \) is the Loadbalancer URL where you can access the Devtron dashboard. +Incase you don't see the results or get a message "service doesnt exist", it means devtron is still installing, please check again after 5 minutes. + **PS:** You can also do a CNAME entry corresponding to your domain/subdomain to point to this Loadbalancer URL to access it at a custom domain. | Host | Type | Points to | diff --git a/docs/setup/install/install-devtron-using-kubectl.md b/docs/setup/install/install-devtron-using-kubectl.md index 2c253afb7c..dc6dcd57ea 100644 --- a/docs/setup/install/install-devtron-using-kubectl.md +++ b/docs/setup/install/install-devtron-using-kubectl.md @@ -34,7 +34,13 @@ Run following command kubectl -n devtroncd get installers installer-devtron -o jsonpath='{.status.sync.status}' ``` -The install commands initiates Devtron-operator which spins up all the Devtron micro-services one by one in about 20 mins. You can use the above command to check the status of the installation if the installation is still in progress, it will print `Downloaded`. When the installation is complete, it prints `Applied`. +The install commands initiates Devtron-operator which spins up all the Devtron micro-services one by one in about 20 mins. You can use the above command to check the status of the installation. + +| Status | Description | +| :--- | :--- | +| `Downloaded` | Installer has downloaded all the manifests and installation is in progress. | +| `Applied` | Installer has successfully applied all the manifest and installation is complete. | + Meanwhile, you can check logs of the installer by executing the following command: ```bash @@ -57,6 +63,8 @@ You will get result something like below The hostname mentioned here \( aaff16e9760594a92afa0140dbfd99f7-305259315.us-east-1.elb.amazonaws.com \) is the Loadbalancer URL where you can access the Devtron dashboard. +Incase you don't see the results or get a message "service doesnt exist", it means devtron is still installing, please check again after 5 minutes. + **PS:** You can also do a CNAME entry corresponding to your domain/subdomain to point to this Loadbalancer URL to access it at a custom domain. | Host | Type | Points to | diff --git a/docs/setup/install/installation-configuration.md b/docs/setup/install/installation-configuration.md index f7b3771d4b..9b80983ef3 100644 --- a/docs/setup/install/installation-configuration.md +++ b/docs/setup/install/installation-configuration.md @@ -35,6 +35,22 @@ helm install devtron devtron/devtron-operator --create-namespace --namespace dev |ENABLE_INGRESS | To enable Ingress (True/False)| False| Optional| |INGRESS_ANNOTATIONS | Annotations for ingress| ""| Optional| |PROMETHEUS_URL | Existing Prometheus URL if it is installed| ""| Optional| +|CI_NODE_LABEL_SELECTOR | Label of CI worker node| "" | Optional| +|CI_NODE_TAINTS_KEY | Taint key name of CI worker node | "" | Optional| +|CI_NODE_TAINTS_VALUE |Value of taint key of CI node | "" | Optional| +|CI_DEFAULT_ADDRESS_POOL_BASE_CIDR | CIDR ranges used to allocate subnets in each IP address pool for CI | "" | Optional| +|CI_DEFAULT_ADDRESS_POOL_SIZE | The subnet size to allocate from the base pool for CI | "" | Optional| +|CD_NODE_LABEL_SELECTOR | Label of CD node | kubernetes.io/os=linux| Optional| +|CD_NODE_TAINTS_KEY| Taint key name of CD node| dedicated | Optional| +|CD_NODE_TAINTS_VALUE| Value of taint key of CD node| ci | Optional| +|CD_LIMIT_CI_CPU|CPU limit for pre and post CD Pod |0.5| Optional| +|CD_LIMIT_CI_MEM| Memory limit for pre and post CD Pod|3G|Optional| +|CD_REQ_CI_CPU|CPU request for CI Pod|0.5|Optional| +|CD_REQ_CI_MEM|Memory request for CI Pod |1G|Optional| +|CD_DEFAULT_ADDRESS_POOL_BASE_CIDR | CIDR ranges used to allocate subnets in each IP address pool for CD | "" | Optional| +|CD_DEFAULT_ADDRESS_POOL_SIZE | The subnet size to allocate from the base pool for CD | "" | Optional| +|GITOPS_REPO_PREFIX | Prefix for Gitops repository | devtron |Optional| + ### Dashboard Configurations diff --git a/docs/setup/upgrade/devtron-upgrade-0.3.x-0.3.x.md b/docs/setup/upgrade/devtron-upgrade-0.3.x-0.3.x.md index a0e447e303..03b85cc7f7 100644 --- a/docs/setup/upgrade/devtron-upgrade-0.3.x-0.3.x.md +++ b/docs/setup/upgrade/devtron-upgrade-0.3.x-0.3.x.md @@ -6,7 +6,7 @@ If you want to check the current version of Devtron you are using, please use th kubectl -n devtroncd get installers installer-devtron -o jsonpath='{.status.sync.data}' | grep "^LTAG=" | cut -d"=" -f2- ``` -## Follow the below mentioned steps to upgrade the Devtron version +## Follow the below mentioned steps to upgrade the Devtron version using Helm 1. Fetch the latest Devtron helm chart @@ -25,3 +25,18 @@ DEVTRON_TARGET_VERSION=v0.3.x ```bash helm upgrade devtron devtron/devtron-operator --namespace devtroncd --set installer.release=$DEVTRON_TARGET_VERSION ``` + + +## Follow the below mentioned steps to upgrade the Devtron version using Kubectl + +1. Input the target Devtron version that you want to upgrade to. You can find the latest releases from Devtron on Github https://github.com/devtron-labs/devtron/releases + +```bash +DEVTRON_TARGET_VERSION=v0.3.x +``` + +2. Patch Devtron Installer + +```bash +kubectl patch -n devtroncd installer installer-devtron --type='json' -p='[{"op": "add", "path": "/spec/reSync", "value": true },{"op": "replace", "path": "/spec/url", "value": "https://raw.githubusercontent.com/devtron-labs/devtron/$DEVTRON_TARGET_VERSION/manifests/installation-script"}]' +``` \ No newline at end of file diff --git a/docs/user-guide/cloning-application.md b/docs/user-guide/cloning-application.md index 12c5a4e96a..ee3f5d3039 100644 --- a/docs/user-guide/cloning-application.md +++ b/docs/user-guide/cloning-application.md @@ -1,20 +1,23 @@ # Cloning Application -![](../.gitbook/assets/d1%20%282%29.jpg) +Click on `Create New` and the select `Custom app` to create a new application. -Select `Add New App` to Create a new app. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/cloning-application/custom-app.jpg) -![](../.gitbook/assets/clone_app1.jpg) + As soon you click on `Custom app`, you will get a popup window on screen where you have to enter `app name` and `project` for the application. there are two radio buttons present on the popup window, one is for `Blank app` and another one is for `Clone an existing app`. For cloning an existing application, select the second one. After this, one more drop-down will appear on the window from which you can select the application that you want to clone. For this, you will have to type minimum three character to see the matching results in the drop-down. After typing the matching characters, select the applicaion that you want to clone. You also can add additional information about the application (eg. `created by`, `Created on`) using `tags` (only key:value allowed). + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/cloning-application/clone-app.jpg) | Key | Description | | :--- | :--- | | `App Name` | Name of the new app you want to Create | | `Project` | Project name | -| `Template` | Select the App whose template you want to use to the Create new app | +| `Select an app to clone` | Select the application that you want to clone | +| `Tags` | Additional informations about the application | -Click on `Duplicate App` to create App with a template of the Application you have selected from the Drop-down. +Now click on `Clone App` to clone the selected application. -![](../.gitbook/assets/created-clone-app.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/cloning-application/new-cloned-app.jpg) New application with a duplicate template is created. diff --git a/docs/user-guide/creating-application/config-maps.md b/docs/user-guide/creating-application/config-maps.md index 4b00d8276d..97498aec5a 100644 --- a/docs/user-guide/creating-application/config-maps.md +++ b/docs/user-guide/creating-application/config-maps.md @@ -5,7 +5,7 @@ The ConfigMap API resource holds key-value pairs of the configuration data that Click on `Add ConfigMap` to add a config map to your application. -![](../../user-guide/creating-application/images/config-maps.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/config-maps/config-map.jpg) ## Configure the ConfigMap @@ -93,16 +93,15 @@ For multiple files mount at the same location you need to check sub path bool fi Sub Path feature is not applicable in case of external configmap. ## File Permission -File permission will be provide at the configmap level not on the each key of the configmap. it will take 3 digit standard permission for the file. +File permission will be provide at the configmap level not on the each key of the configmap. It will take 3 digit standard permission for the file. ### \(B\) Kubernetes External ConfigMap -You can select `Kubernetes External ConfigMap` in the `data type` field if you have created a ConfigMap using the Kubectl command. +You can select `Kubernetes External ConfigMap` in the `data type` field if you have created a ConfigMap using the kubectl command. By default, the data type is set to `Kubernetes ConfigMap`. -Kubernetes External ConfigMap is created using the `kubectl create configmap` command. You can also use the ConfigMap generator in `kustomization.yaml` to create a ConfigMap. - +Kubernetes External ConfigMap is created using the `kubectl create configmap` command. If you are using `Kubernetes External ConfigMap`, make sure you give the name of ConfigMap the same as the name that you have given using kubectl create `Configmap ` command, otherwise, it might result in an error during the built. You have to ensure that the External ConfigMap exists and is available to the pod. diff --git a/docs/user-guide/creating-application/deployment-template/rollout-deployment.md b/docs/user-guide/creating-application/deployment-template/rollout-deployment.md index c66d4a5048..4379b0de43 100644 --- a/docs/user-guide/creating-application/deployment-template/rollout-deployment.md +++ b/docs/user-guide/creating-application/deployment-template/rollout-deployment.md @@ -374,6 +374,15 @@ This defines annotations and the type of service, optionally can define name als type: ClusterIP annotations: {} ``` +| Key | Description | +| :--- | :--- | +| `type` | Select the type of service, default `ClusterIP` | +| `annotations` | Annotations are widely used to attach metadata and configs in Kubernetes. | +| `name` | Optional field to assign name to service | +| `loadBalancerSourceRanges` | If service type is `LoadBalancer`, Provide a list of whitelisted IPs CIDR that will be allowed to use the Load Balancer. | + +Note - If `loadBalancerSourceRanges` is not set, Kubernetes allows traffic from 0.0.0.0/0 to the LoadBalancer / Node Security Group(s). + ### Volumes @@ -702,11 +711,11 @@ waitForSecondsBeforeScalingDown: 30 ``` Wait for given period of time before scaling down the container. -## 3. Show application metrics +## 3. Show Application Metrics If you want to see application metrics like different HTTP status codes metrics, application throughput, latency, response time. Enable the Application metrics from below the deployment template Save button. After enabling it, you should be able to see all metrics on App detail page. By default it remains disabled. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/deployment-template/deployment_application_metrics.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/deployment-template/application-metrics.jpg) Once all the Deployment template configurations are done, click on `Save` to save your deployment configuration. Now you are ready to create [Workflow](workflow/) to do CI/CD. @@ -827,4 +836,4 @@ topologySpreadConstraints: whenUnsatisfiable: DoNotSchedule autoLabelSelector: true customLabelSelector: {} -``` \ No newline at end of file +``` diff --git a/docs/user-guide/creating-application/docker-build-configuration.md b/docs/user-guide/creating-application/docker-build-configuration.md index 95b19f9df5..0d767c115e 100644 --- a/docs/user-guide/creating-application/docker-build-configuration.md +++ b/docs/user-guide/creating-application/docker-build-configuration.md @@ -29,7 +29,7 @@ In this field, add the name of your docker repository. The repository that you s ![](../../.gitbook/assets/docker-configuration-docker-hub.png) -![](../../user-guide/creating-application/images/docker-build-config-1.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/docker-build-configuration/docker-build-config-1.jpg) ## Checkout path diff --git a/docs/user-guide/creating-application/environment-overrides.md b/docs/user-guide/creating-application/environment-overrides.md index f79a6ca464..2d7329fad7 100644 --- a/docs/user-guide/creating-application/environment-overrides.md +++ b/docs/user-guide/creating-application/environment-overrides.md @@ -2,7 +2,7 @@ You will see all your environments associated with an application under the `Environment Overrides` section. -![](../../user-guide/creating-application/images/environment-override.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/environment-overrides/environment-override.jpg) You can customize your `Deployment template, ConfigMap, Secrets` in Environment Overrides section to add separate customizations for different environments such as dev, test, integration, prod, etc. diff --git a/docs/user-guide/creating-application/git-material.md b/docs/user-guide/creating-application/git-material.md index 2146121dc3..fbe5487091 100644 --- a/docs/user-guide/creating-application/git-material.md +++ b/docs/user-guide/creating-application/git-material.md @@ -24,7 +24,7 @@ Note: * Copy the HTTPS/SSH url of the repository * Please make sure that you've added your [dockerfile](https://docs.docker.com/engine/reference/builder/) in the repo. -![](../../user-guide/creating-application/images/git_repo.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/git-material/git-repo-1.jpg) ## 3. Checkout Path @@ -33,7 +33,7 @@ After clicking on checkbox, git checkout path field appears. The git checkout pa This field is optional in case of a single git repository application and you can leave the path as default. Devtron assigns a directory by itself when the field is left blank. The default value of this field is `./` -![](../../user-guide/creating-application/images/save_git_repo.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/git-material/save-git-repo.jpg) If you want to go with a multi-git approach, then you need to specify a separate path for each of your repositories. The first repository can be checked out at the default `./` path as explained above. But, for all the rest of the repositories, you need to ensure that you provide unique checkout paths. In failing to do so, you may cause Devtron to checkout multiple repositories in one directory and overwriting files from different repositories on each other. @@ -59,7 +59,7 @@ Few other examples, where you may want to have multiple repositories for your ap * Common Library extracted out in different repo so that it can be used via multiple other projects. * Due to security reasons you are keeping configuration files in different access restricted git repositories. -## **How Devtron's 'Checkout Path' works** +## **How Devtron's 'Checkout Path' Works** The checkout path is used by Devtron to assign a directory to each of your git repositories. Once you provide different checkout paths for your repositories, Devtron will clone your code at those locations and these checkout paths can be referenced in the docker file to create docker image for the application. Whenever a change is pushed to any the configured repositories, the CI will be triggered and a new docker image file will be built based on the latest commits of the configured repositories and pushed to the container registry. \ No newline at end of file diff --git a/docs/user-guide/creating-application/images/config-maps.jpg b/docs/user-guide/creating-application/images/config-maps.jpg deleted file mode 100755 index 074f1ae002..0000000000 Binary files a/docs/user-guide/creating-application/images/config-maps.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/docker-build-config-1.jpg b/docs/user-guide/creating-application/images/docker-build-config-1.jpg deleted file mode 100755 index d9ce1a8fb6..0000000000 Binary files a/docs/user-guide/creating-application/images/docker-build-config-1.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/docker-build-config.jpg b/docs/user-guide/creating-application/images/docker-build-config.jpg deleted file mode 100755 index 31a159eb3d..0000000000 Binary files a/docs/user-guide/creating-application/images/docker-build-config.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/environment-override.jpg b/docs/user-guide/creating-application/images/environment-override.jpg deleted file mode 100644 index 46dfb9f5da..0000000000 Binary files a/docs/user-guide/creating-application/images/environment-override.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/git_repo.jpg b/docs/user-guide/creating-application/images/git_repo.jpg deleted file mode 100644 index d64de369d4..0000000000 Binary files a/docs/user-guide/creating-application/images/git_repo.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/save_git_repo.jpg b/docs/user-guide/creating-application/images/save_git_repo.jpg deleted file mode 100644 index 61e5a088e4..0000000000 Binary files a/docs/user-guide/creating-application/images/save_git_repo.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/sequential-workflow.jpg b/docs/user-guide/creating-application/images/sequential-workflow.jpg deleted file mode 100755 index 7819b331f1..0000000000 Binary files a/docs/user-guide/creating-application/images/sequential-workflow.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/update-ci.jpg b/docs/user-guide/creating-application/images/update-ci.jpg deleted file mode 100755 index 754c4fad9d..0000000000 Binary files a/docs/user-guide/creating-application/images/update-ci.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/workflow-cd.jpg b/docs/user-guide/creating-application/images/workflow-cd.jpg deleted file mode 100755 index 551268902f..0000000000 Binary files a/docs/user-guide/creating-application/images/workflow-cd.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/images/workflow-ci.jpg b/docs/user-guide/creating-application/images/workflow-ci.jpg deleted file mode 100755 index 8a1dddb185..0000000000 Binary files a/docs/user-guide/creating-application/images/workflow-ci.jpg and /dev/null differ diff --git a/docs/user-guide/creating-application/secrets.md b/docs/user-guide/creating-application/secrets.md index df7aeeb9a3..8b80443481 100644 --- a/docs/user-guide/creating-application/secrets.md +++ b/docs/user-guide/creating-application/secrets.md @@ -6,7 +6,7 @@ Secret objects let you store and manage sensitive information, such as passwords ## Configure Secret -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/secrets/creating-applications-secrets-1.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/secrets/add-secret.jpg) Click on `Add Secret` to add a new secret. @@ -110,13 +110,13 @@ To add secrets from AWS secret manager, navigate to `Secrets` of the application 1. Click on `Add Secret` to add a new secret. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/secrets/creating-applications-secrets-9.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/secrets/aws-secret-manager.jpg) 2. Select `AWS Secret Manager` from dropdown of `Data type`. 3. Provide a name to your secret. -4. Select how you want to use the secret. You many leave it selected as environment variable and also you may leave `Role ARN` empty. +4. Select how you want to use the secret. You may leave it selected as environment variable and also you may leave `Role ARN` empty. 5. In `Data` section, you will have to provide data in key-value format. @@ -133,8 +133,8 @@ All the required field to pass your data to fetch secrets on devtron are describ To add secrets in AWS secret manager, do the following steps : -Step 1: Go to AWS secret manager console. -Step 2: Click on `Store a new secret`. -Step 3: Add and save your secret. +1. Go to AWS secret manager console. +2. Click on `Store a new secret`. +3. Add and save your secret. ![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/secrets/creating-applications-secrets-10.jpg) diff --git a/docs/user-guide/creating-application/workflow/README.md b/docs/user-guide/creating-application/workflow/README.md index 9b39deee88..1dea3f78a4 100644 --- a/docs/user-guide/creating-application/workflow/README.md +++ b/docs/user-guide/creating-application/workflow/README.md @@ -6,21 +6,21 @@ Workflow is a logical sequence of different stages used for continuous integrati Click on `New Build Pipeline` to create a new workflow +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow/new-build-pipeline-1.jpg) -![](../images/workflow-ci.jpg) - -On clicking `New Build Pipeline`. Three options appear as mentioned below: +On clicking `New Build Pipeline`, three options appear as mentioned below: * **Continuous Integration:** Choose this option if you want Devtron to build the image of source code. * **Linked CI Pipeline:** Choose this option if you want to use an image created by an existing CI pipeline in Devtron. * **Incoming Webhook:** Choose this if you want to build your image outside Devtron, it will receive a docker image from an external source via the incoming webhook. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow/workflow-ci.jpg) -Then, Create CI/CD Pipelines for your application. +Then, create CI/CD Pipelines for your application. -To know how to Create the CI Pipeline for your application Click On: [Create CI Pipelines](ci-pipeline.md) +To know how to create the CI pipeline for your application, click on: [Create CI Pipelines](ci-pipeline.md) -To know how to Create the CD Pipeline for your application Click On: [Create CD Pipelines](cd-pipeline.md) +To know how to create the CD pipeline for your application, click on: [Create CD Pipelines](cd-pipeline.md) diff --git a/docs/user-guide/creating-application/workflow/cd-pipeline.md b/docs/user-guide/creating-application/workflow/cd-pipeline.md index 263dec183e..56fa31f0b7 100644 --- a/docs/user-guide/creating-application/workflow/cd-pipeline.md +++ b/docs/user-guide/creating-application/workflow/cd-pipeline.md @@ -3,7 +3,7 @@ Once you are done creating your CI pipeline, you can move start building your CD ## Creating CD Pipeline -![](../images/workflow-cd.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow-cd-pipeline/workflow-cd.jpg) Click on **“+”** sign on CI Pipeline to attach a CD Pipeline to it. A basic `Create deployment modal` will pop up. @@ -225,6 +225,6 @@ Please follow the steps mentioned below to create sequential pipelines : 2. To add another CD Pipeline sequentially after previous one, again click on + sign on the last CD pipeline. 3. Similarly, you can add multiple CD pipelines by clicking + sign of the last CD pipeline, each deploying in different environments. -![](../images/sequential-workflow.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow-cd-pipeline/sequential-workflow.jpg) > Note: Deleting a CD pipeline also deletes all the K8s resources associated with it and will bring a disruption in the deployed micro-service. Before deleting a CD pipeline, please ensure that the associated resources are not being used in any production workload. diff --git a/docs/user-guide/creating-application/workflow/ci-pipeline.md b/docs/user-guide/creating-application/workflow/ci-pipeline.md index 0cb9029281..3be257468d 100644 --- a/docs/user-guide/creating-application/workflow/ci-pipeline.md +++ b/docs/user-guide/creating-application/workflow/ci-pipeline.md @@ -1,8 +1,10 @@ # CI Pipeline -CI Pipeline can be created in three different ways, Continuous Integration, Linked CI Pipeline and Incoming Webhook. Each of these methods have different use-cases which can be used according to the needs of the organization. Let’s begin with Continuous Integration. +CI Pipeline can be created in three different ways, `Continuous Integration`, `Linked CI Pipeline` and `Incoming Webhook`. -![](../images/workflow-ci.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow-ci-pipeline/workflow-ci.jpg) + +Each of these methods have different use-cases which can be used according to the needs of the organization. Let’s begin with Continuous Integration. ## A. Continuous Integration @@ -158,9 +160,9 @@ You have provided all the details required to create a CI pipeline, now click on You can also update any configuration of an already created CI Pipeline, except the pipeline name. The pipeline name can not be edited. -![](../images/update-ci.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow-ci-pipeline/ci-pipeline-update.jpg) -Click on your CI Pipeline, to update your CI Pipeline. A window will be popped up with all the details of the current pipeline. +Click on your CI pipeline, to update your CI Pipeline. A window will be popped up with all the details of the current pipeline. ![](../../../.gitbook/assets/ca-workflow-update.png) @@ -168,17 +170,17 @@ Make your changes and click on `Update Pipeline` at the bottom to update your Pi #### Delete CI Pipeline -You can only delete CI Pipeline if you have no CD Pipeline created in your workflow. +You can only delete CI pipeline if you have no CD pipeline created in your workflow. -To Delete a CI Pipeline, go to the `App Configurations` and then click on `Workflow` editor +To delete a CI pipeline, go to the `App Configurations` and then click on `Workflow` editor -Click on `Delete Pipeline` at the bottom to delete the CD Pipeline +Click on `Delete Pipeline` at the bottom to delete the CD pipeline #### Automated Test suite integration in the CI step using devtron-ci.yaml -Users can run the Test case using the Devtron Dashboard or by including the Test cases in the devtron.ci.yaml file in the source git repository. For reference, check: [https://github.com/kumarnishant/getting-started-nodejs/blob/master/devtron-ci.yaml](https://github.com/kumarnishant/getting-started-nodejs/blob/master/devtron-ci.yaml) +Users can run the test case using the Devtron dashboard or by including the test cases in the devtron.ci.yaml file in the source git repository. For reference, check: [https://github.com/kumarnishant/getting-started-nodejs/blob/master/devtron-ci.yaml](https://github.com/kumarnishant/getting-started-nodejs/blob/master/devtron-ci.yaml) -The test cases given in the script will run before the Test Cases given in the devtron.ci.yaml +The test cases given in the script will run before the test cases given in the devtron.ci.yaml ![](../../../.gitbook/assets/yaml%20%283%29.jpg) @@ -195,13 +197,36 @@ The test cases given in the script will run before the Test Cases given in the d ## B. Linked CI Pipeline -If one code is shared across multiple applications, Linked CI Pipeline can be used, and only one image will be built for multiple applications because if there is only one build, it is not advisable to create multiple CI Pipelines. +If one code is shared across multiple applications, `Linked CI Pipeline` can be used, and only one image will be built for multiple applications because if there is only one build, it is not advisable to create multiple CI Pipelines. ![](../../../.gitbook/assets/ca-workflow-linked.png) +To create a `Linked CI Pipeline`, please follow the steps mentioned below : + +1. Click on `+ New Build Pipeline` button. + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow-ci-pipeline/linked-ci-pipeline-1.png) + +2. Select `Linked CI Pipeline`. + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow-ci-pipeline/linked-ci-pipeline-2.png) + +3. Select the application in which the source CI pipeline is present. + +4. Select the source CI pipeline. + +5. Provide a name for linked CI pipeline. + +6. Click on `Create Linked CI Pipeline` button to create linked CI pipeline. + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/creating-application/workflow-ci-pipeline/linked-ci-pipeline-3.png) + +After creating a linked CI pipeline, you can create a CD pipeline. +You cannot trigger build from linked CI pipeline, it can be triggered only from source CI pipeline. Initially you will not see any images to deploy in CD pipeline created from `linked CI pipeline`. Trigger build in source CI pipeline to see the images in CD pipeline of linked CI pipeline. After this, whenever you trigger buld in source CI pipeline, the build images will be listed in CD pipeline of `linked CI pipeline` too. + ## C. Incoming Webhook -You can use Devtron for Deployments on Kubernetes while using your own CI tool such as Jenkins. External CI features can be used for cases where the CI tool is hosted outside the Devtron platform. +You can use Devtron for deployments on Kubernetes while using your own CI tool such as Jenkins. External CI features can be used for cases where the CI tool is hosted outside the Devtron platform. ![](../../../.gitbook/assets/ca-workflow-external.png) diff --git a/docs/user-guide/debugging-deployment-and-monitoring.md b/docs/user-guide/debugging-deployment-and-monitoring.md index 7abee75e90..a2c53ecd4e 100644 --- a/docs/user-guide/debugging-deployment-and-monitoring.md +++ b/docs/user-guide/debugging-deployment-and-monitoring.md @@ -10,7 +10,7 @@ Over here, you can see the status of the app as Healthy. If there are some error ### Events -![](../.gitbook/assets/events1%20%281%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/debugging-deployment-and-monitoring/events.jpg) Events of the application are accessible from the bottom left corner. @@ -18,19 +18,19 @@ Events section displays you the events that took place during the deployment of ### Logs -![](../.gitbook/assets/events2%20%281%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/debugging-deployment-and-monitoring/logs.jpg) Logs contain the logs of the Pods and Containers deployed which you can use for the process of debugging. ### Manifest -![](../.gitbook/assets/events3%20%282%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/debugging-deployment-and-monitoring/manifest.jpg) The Manifest shows the critical information such as Container-image, restartCount, state, phase, podIP, startTime etc. and status of the pods deployed. ### Deleting Pods -![](../.gitbook/assets/events5%20%281%29.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/debugging-deployment-and-monitoring/delete-pod.jpg) You might run into a situation where you need to delete Pods. You may need to bounce or restart a pod. @@ -49,15 +49,15 @@ You can view `Application Objects` in this section of `App Details`, such as: | `Config & Storage` | _ConfigMap_\( API object used to store non-confidential data in key-value pairs\) | | `Custom Resource` | _Rollout_\(new Pods will be scheduled on Nodes with available resources\), _ServiceMonitor_\(specifies how groups of services should be monitored\) | -![](../.gitbook/assets/app-details-application-object-ingress.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/debugging-deployment-and-monitoring/ingress.jpg) ## Monitoring -![](../.gitbook/assets/events4%20%282%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/debugging-deployment-and-monitoring/monitoring.jpg) -You can monitor the application in the `App Details`section. +You can monitor the application in the `App Details` section. -Metrics like CPU Usage, Memory Usage, Throughput and Latency can be viewed here. +Metrics like `CPU Usage`, `Memory Usage`, `Throughput` and `Latency` can be viewed here. | Key | Description | | :--- | :--- | diff --git a/docs/user-guide/deleting-application.md b/docs/user-guide/deleting-application.md index d1b38b6922..dd313f0d77 100644 --- a/docs/user-guide/deleting-application.md +++ b/docs/user-guide/deleting-application.md @@ -4,21 +4,21 @@ Delete the Application, when you are sure you no longer need it. Clicking on `Delete Application` will not delete your application if you have workflows in the application. -If your Application contains workflows in the Workflow Editor. So,when you Click on `Delete Application`, you will see the following prompt. +If your Application contains workflows in the Workflow Editor. So, when you click on `Delete Application`, you will see the following prompt. -![](../.gitbook/assets/deleting-warnning%20%281%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deleting-application/app-delete-warning.jpg) Click on `View Workflows` to view and delete your workflows in the application. -To delete the workflows in your application, you must first delete all the pipelines\(CD Pipeline, CI Pipeline or Linked CI Pipeline or External CI Pipeline if there are any\). +To delete the workflows in your application, you must first delete all the pipelines \(CD Pipeline, CI Pipeline or Linked CI Pipeline or External CI Pipeline if there are any\). -![](../images/deleting-application/deleting-workflow-1.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deleting-application/delete-workflows-new.jpg) After you have deleted all the pipelines in the workflow, you can delete that particular workflow. Similarly, delete all the workflows in the application. -![](../images/deleting-application/deleting-delete-application-1.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deleting-application/delete-application.jpg) Now, Click on `Delete Application` to delete the application. diff --git a/docs/user-guide/deploy-chart/chart-group.md b/docs/user-guide/deploy-chart/chart-group.md index 9b8b129151..714c87057a 100644 --- a/docs/user-guide/deploy-chart/chart-group.md +++ b/docs/user-guide/deploy-chart/chart-group.md @@ -2,44 +2,40 @@ ## Introduction -Create Chart Group And Deploy App store applications. - +Using Devtron UI, one or more Helm charts can be grouped and deployed together with a single click. ## 1. Create Group -Select the `Charts` section from the left pane, you will be landed to the `Chart Store` page. -Click on `Discover` and Click Button on right top `Create Group`. - -![](../../.gitbook/assets/chart-group-1.png) +1. In the left pane, select `Charts`. +2. On the `Chart Store` page, select `Create Group` from the upper-right corner. -It will pop-up a dialog, fill required data. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-1.jpg) +3. In the `Create Chart Group` screen, enter `name` and `description`(optional) for the chart group, and then select `Create Group`. -And click on right bottom button `Create Group`. -![](../../.gitbook/assets/chart-group-2.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-2.jpg) -It will land you to the page where you can discover charts to add in this group and later deploy by single click. +Once you create the group, you can now select and add the charts to this chart group. ## 2. Add Charts To Group +1. To add a chart to the group, click the `+` sign at the top-right corner of a chart, and then select `Save`. -![](../../.gitbook/assets/chart-group-3.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-3.jpg) -Choose any chart and add by plus button, save this group by pressing `Save`. - -For Running Instances and Group Detail Click on `Group Detail` from here you can Edit yous charts as well. +2. Click on `Group Detail` to see all the running instances and group details. You can also edit the chart group from here. ## 3.Bulk Deploy and Edit Option for Charts -![](../../.gitbook/assets/chart-group-4.png) - -Charts are visible in right panel you can deploy it right bottom button `Deploy To ..` +You can see all the charts in the chart group in the right panel. +1. Select `Deploy to..`. -It will open a dialog box, select project and environment where you want to deploy this specific chart. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-4.jpg) -![](../../.gitbook/assets/chart-group-5.png) +2. In the `Deploy Selected Charts`, select the `Project` and `Deploy to Environment` values where you want to deploy the chart group. -Click on `Advanced Option` for more deploy option like values yaml environment and project selection for each chart. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-5.jpg) -![](../../.gitbook/assets/chart-group-6.png) +3. Select `Advanced Options` for more deploy options, such as editing the `values.yaml` or changing the `Environment` and `Project` for each chart. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-6.jpg) diff --git a/docs/user-guide/deploy-chart/deployment-of-charts.md b/docs/user-guide/deploy-chart/deployment-of-charts.md index 98109e7ab6..db1439776e 100644 --- a/docs/user-guide/deploy-chart/deployment-of-charts.md +++ b/docs/user-guide/deploy-chart/deployment-of-charts.md @@ -11,7 +11,7 @@ Search `nginx` or any other charts in search filter. ![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-1.jpg) -Click on chart and it will redirect you to `Chart Details` page where you can see number of instances deployed by using the same chart. +Click on chart and it will redirect you to `Chart Details` page where you can see a number of instances deployed by using the same chart. ![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-2.jpg) @@ -39,37 +39,42 @@ Click on `Deploy` to deploy the Chart After clicking on `Deploy` you will land on a page that shows the status of the deployment of the Chart. -The status of the chart should be `Healthy`. It might take few seconds after initiating the deployment of the chart. -In case the status of the deployment is `Degraded` or takes a long time to get deployed, click on `Details` in `Application Status` section on same page or check the logs of the pods to debug the issue. +The status of the chart should be `Healthy`. It might take a few seconds after initiating the deployment of the chart. +In case the status of the deployment is `Degraded` or takes a long time to get deployed, click on `Details` in `Application Status` section on the same page or check the logs of the pods to debug the issue. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-4.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-4-2.jpg) -1. shows status of deployed chart. +1. Shows status of deployed chart. 2. Shows the controller service accounts being used. -3. Clicking on `values` will land you to the page where you can update, upgrade or delete chart. +3. Clicking on `values` will land you on the page where you can update, upgrade or delete chart. 4. Clicking on `View Chart` will land you to the page where you can see all the running instances of this chart. +To see deployment history of Helm application, click on `Deployment history` from `App details` page. + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/hyperion/user-guide/deploy-charts/overview-of-charts/overview-of-charts-9.jpg) + + ## 4. Update or Upgrade Chart -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-5.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-5-2.jpg) For update you can change its `chart version` or `values.yaml` and then click on `Update And Deploy`. For upgrade click on `Repo/Chart` field and search any chart name like `nginx-ingress` and change values corresponding to that chart and Click on `Update And Deploy`. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-6.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-6-2.jpg) -After update or upgrade you again will land on `App Detail` page, where you can check pods and service name. +After an update or upgrade you again will land on `App Detail` page, where you can check pods and service name. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-7.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-7-2.jpg) ## 5. Chart Details and Delete Charts -By clicking on `View Chart` in `Chart Used` section on `App Details` page, it will redirect you to `Chart Details` page where you can see number of instances installed by this chart and also you can delete chart instance from here. +By clicking on `View Chart` in `Chart Used` section on `App Details` page, it will redirect you to `Chart Details` page where you can see number of instances installed by this chart and also you can delete the chart instance from here. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-8.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/deployment-of-charts/charts-8-2.jpg) diff --git a/docs/user-guide/deploy-chart/overview-of-charts.md b/docs/user-guide/deploy-chart/overview-of-charts.md index 7c86b575ed..38b97e2e9f 100644 --- a/docs/user-guide/deploy-chart/overview-of-charts.md +++ b/docs/user-guide/deploy-chart/overview-of-charts.md @@ -2,19 +2,17 @@ ## Deploying Charts -Charts can be deployed individually or by creating a group of Charts. - -Both methods are mentioned in the given document. +Charts can be deployed individually or by creating a group of Charts. Both methods are mentioned here. ### Deploying Chart -![](../../.gitbook/assets/deploy-chart-store.jpg) +To deploy any chart or chart group, visit the `Charts` section from the left panel and then select the chart that you want to use. -Select Discover and then select the chart that you want to use. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-1.jpg) -Click on README.MD to get more idea about the configurations of the chart. +Click on `README.md` to get more ideas about the configurations of the chart. -![](../../.gitbook/assets/custom%20%283%29%20%284%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-2.jpg) Select the Chart Version that you want to use and Chart Value, you can either use the Default Values or Custom Values. @@ -24,79 +22,74 @@ The configuration values can be edited in the section given below Chart Version. | Key | Description | | :--- | :--- | -| `App Name` | The name of the app | +| `App Name` | Name of the app | | `Project` | Project of the app | -| `Environment` | Environment of the app to be deployed | +| `Environment` | Environment of the app to be deployed in | | `Chart Version` | Version of the chart to be used | -![](../../.gitbook/assets/depchart4config.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-3.jpg) -ReadMe.md present on the left can be used by the user to set configuration values. +Readme.md present on the left can be used by the user to set configuration values. -![](../../.gitbook/assets/depchart4readme.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-4.jpg) Click on `Deploy Chart` to deploy the chart. -![](../../.gitbook/assets/depchartdeployedredo%20%282%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-5-2.jpg) + +Click on `App Details` to see the status and details of the deployed chart and click on `Values` to reconfigure the deployment. -You can see the status of the chart deployed. Click on `Values.Yaml` to reconfigure the deployment. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-6-2.jpg) -![](../../.gitbook/assets/depchartreconfig.jpg) +Configuration values can be edited over here by the help of Readme.md. -Configuration values can be edited over here by the help of ReadMe.md. +Click on `Update And Deploy` to update new settings. +You can also see deployment history of Helm application and values.yaml corresponding to the deployment by clicking on `Deployment history`. + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-9-2.jpg) -Select Update And Deploy to update new settings. ### Custom Values You can use the default values or create Custom value by clicking on `Create Custom`. -![](../../.gitbook/assets/custom%20%283%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-7.jpg) You can name your Custom Value, select the Chart Version and change the configurations in YAML file. -![](../../.gitbook/assets/custom_val.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-8-2.jpg) Click on `Save Template` to save the configurations. ### Deploying Chart Groups -To deploy multiple applications and work with them simultaneously, you can use `Chart Groups`. - -To create Chart Groups Click on `Discover` and Click on `Create Group`. - -![](../../.gitbook/assets/screen2.jpg) +You can deploy multiple applications and work with them simultaneously by creating `Chart Group`. +To create chart group click on `Create Group`. -Add the Group Name and Description and Click on `Create Group`. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-1.jpg) -![](../../.gitbook/assets/create_group.jpg) +Add the `Group Name` and `Description`(optional), and select `Create Group`. -You can select the Charts that you want to add in your Chart Group by clicking on '+' sign. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-2.jpg) -You can select a particular chart multiple number of times according to your requirements. +You can select the Charts that you want to add to your Chart Group by clicking on '+' sign. You also can add multiple copies of the same chart in the chart group according to your requirements. -![](../../.gitbook/assets/select_charts%20%281%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/chart-group/chart-group-3.jpg) Select the `Version` and `Values` for your charts. +You can use Default Values or the Custom Values, just make sure the value that you select for the chart is compatible with the version of the chart that you are using. -You can use Default Values or the Custom Values, just make sure the Value that you select for your Chart is compatible with the Version of the Chart that you are using. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-9.jpg) -![](../../.gitbook/assets/select_charts2.jpg) +To edit the chart configuration, Click on `Edit`. -To edit the Chart Configuration, Click on 'Edit'. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-10.jpg) -![](../../.gitbook/assets/edit_group%20%282%29.jpg) +You can `Add` more charts or `Delete` charts from your existing Chart Group. +After making any changes, click on `Save` to save changes for the Chart Group. -You can `Add` more Charts to your existing Chart Group or `Delete` Charts from your existing Chart Group. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-11.jpg) -After making changes, Click on `Save` to save changes to your Chart Group. - -![](../../.gitbook/assets/edit_group2%20%282%29.jpg) - -If you wish to edit the Chart Configuration, Double Click on that Chart and edit the Configurations in YAML File. - -![](../../.gitbook/assets/edit_chart1%20%282%29.jpg) - -You can edit the `App Name`, `Chart Version`, `Values`, `Deploy Environment` and the YAML file. +If you wish to edit the chart configuration of any chart in the chart group, click on that Chart and edit the configurations in YAML file. You also can edit the `App Name`, `Chart Version`, `Values`, `Deploy Environment` and the YAML file from here. | Key | Description | | :--- | :--- | @@ -105,5 +98,7 @@ You can edit the `App Name`, `Chart Version`, `Values`, `Deploy Environment` and | `Environment` | Name of the Environment in which app has to be deployed | | `Chart Version` | Select the Version of the chart to be used | -Click on `Deploy` to initiate the deployment of a Chart in Chart Group. +After changing the configurations, click on `Deploy` to initiate the deployment of the chart in the Chart Group. + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploy-chart/overview-of-charts/overview-of-charts-12.jpg) diff --git a/docs/user-guide/deploying-application/triggering-cd.md b/docs/user-guide/deploying-application/triggering-cd.md index ec690a5d8c..d863b3937a 100644 --- a/docs/user-guide/deploying-application/triggering-cd.md +++ b/docs/user-guide/deploying-application/triggering-cd.md @@ -2,21 +2,21 @@ ## Triggering CD Pipelines -![](../../.gitbook/assets/trigger-select-image%20%281%29.jpg) +After CI pipeline is complete, CD pipeline can be triggered by clicking on `Select Image`. -After CI Pipeline is complete, CD Pipeline can be triggered by Clicking on _Select Image_. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-cd/select-image.jpg) -![](../../.gitbook/assets/cd-deploy-console.jpg) +Select an image to deploy and then click on `Deploy` to trigger the CD pipeline. -Select an image to deploy and then Click on **Deploy** to trigger the CD Pipeline. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-cd/deploy.jpg) -The running images are tagged as _Running_ +The current deployed images are tagged as `Deployed on `. -![](../../.gitbook/assets/tri_cd5.jpg) +The status of the current deployment can be viewed by Clicking on **App Details** that will show the `Progressing`state for 1-2 minutes and then gradually shows `Healthy` state or `Hibernating` state, based on the deployment strategy. -The status of the current deployment can be viewed by Clicking on **App Details** that will show the _Progressing_ state for 1-2 minutes and then gradually shows _Healthy_ state or _Hibernating_ state, based on the deployment strategy. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-cd/app-status.jpg) -Here, triggering CD Pipeline is successful and the deployment is in "Healthy" state. +Here, triggering CD pipeline is successful and the deployment is in "Healthy" state. [To further diagnose deployments, Click here](../debugging-deployment-and-monitoring.md) diff --git a/docs/user-guide/deploying-application/triggering-ci.md b/docs/user-guide/deploying-application/triggering-ci.md index a9322d05dc..25e3d47ddc 100644 --- a/docs/user-guide/deploying-application/triggering-ci.md +++ b/docs/user-guide/deploying-application/triggering-ci.md @@ -2,35 +2,40 @@ ## Triggering CI Pipelines -![](../../.gitbook/assets/trigger-console%20%281%29.jpg) +The CI Pipeline can be triggered by selecting `Select Material` -The CI Pipeline can be triggered by selecting **Select Material** +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-ci/select-material.jpg) -CI Pipelines that are set as Automatic are always triggered as soon as a new commit is made to the git branch they're sensing. However, CI Pipelines can always be manually triggered as and if required. +CI Pipelines that are set as automatic are always triggered as soon as a new commit is made to the git branch they're sensing. However, CI pipelines can always be manually triggered as and if required. -![](../../.gitbook/assets/tri_ci2%20%282%29.jpg) +Various commits done in the repository can be seen, here along with details like Author, Date etc. Select the commit that you want to trigger and then click on `Start Build` to trigger the CI pipeline. + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-ci/start-build-1.jpg) -Various commits done in the repository can be seen, here along with details like Author, Date etc. Select the commit that you want to trigger and then select "Start Build" to trigger the CI Pipeline. **Refresh** icon, refreshes Git Commits in the CI Pipeline and fetches the latest commits from the “Repository” **Ignore Cache** : This option will ignore the previous build cache and create a fresh build. If selected, will take a longer build time than usual. -![](../../.gitbook/assets/tri_ci3%20%281%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-ci/build-history.jpg) It can be seen that the pipeline is triggered here and is the _Running_ state. -Click on your **CI Pipeline** or Click on **Build History** to get the details about the CI Pipeline such as logs, reports etc. - -![](../../.gitbook/assets/tri_ci5%20%281%29.jpg) +Click on your `CI Pipeline` or click on `Build History` to get the details about the CI pipeline such as logs, reports etc. -You can read the **logs** of the CI Pipeline from here. +You can read the `logs` of the CI Pipeline from here. -![](../../.gitbook/assets/ci-build-histroy-source-code.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-ci/build-history-logs.jpg) -Click on **Source code** to view the details such as commit id, Author and commit message of the Git Material that you have selected for the build. +Click on `Source code` to view the details such as commit id, Author and commit message of the Git Material that you have selected for the build. -![](../../.gitbook/assets/tri_ci4%20%281%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-ci/build-history-sc.jpg) Click on `Artifacts` to download the _reports_ of the Pre-CI and Post-CI stages if any. +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-ci/build-history-artifacts.jpg) + +Click on `security` to see if there is any vulnerabilitiesin the build image. You can see the vulnerabilities here only if you have enabled `Scan for vulnerabilities` before building image from advanced options of CI pipeline. To know more about this feature, follow our [documentation](https://docs.devtron.ai/devtron/user-guide/security-features). + +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/deploying-application/triggering-ci/build-history-security.jpg) + diff --git a/docs/user-guide/global-configurations/docker-registries.md b/docs/user-guide/global-configurations/docker-registries.md index a1d11ae109..fbfd468723 100644 --- a/docs/user-guide/global-configurations/docker-registries.md +++ b/docs/user-guide/global-configurations/docker-registries.md @@ -107,4 +107,21 @@ Some popular registries which can be used using username and password mechanism: ![](../../user-guide/global-configurations/images/Container_Registry_gcr.jpg) * **Google Artifact Registry (GAR)** : JSON key file authentication method can be used to authenticate with username and password. Please follow [link](https://cloud.google.com/artifact-registry/docs/docker/authentication#json-key) for getting username and password for this registry. Please remove all the white spaces from json key and wrap it in single quote while putting in password field. -* **Azure Container Registry (ACR)** : Service principal authentication method can be used to authenticate with username and password. Please follow [link](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-service-principal) for getting username and password for this registry. \ No newline at end of file +* **Azure Container Registry (ACR)** : Service principal authentication method can be used to authenticate with username and password. Please follow [link](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-service-principal) for getting username and password for this registry. + +## Integrating With External Container Registry + +If you want to use a private registry for container registry other than ecr, this will be used to push image and then create a secret in same environment to pull the image to deploy. To create secret, go to charts section and search for chart ‘dt-secrets’ and configure the chart. Provide an App Name and select the Project and Environment in which you want to deploy this chart and then configure the values.yaml as shown in example. The given example is for DockerHub but you can configure similarly for any container registry that you want to use. + +```yaml +name: regcred +type: kubernetes.io/dockerconfigjson +labels: + test: chart +secrets: + data: + - key: .dockerconfigjson + value: '{"auths":{"https://index.docker.io/v1/":{"username":"","password":"}}}' +``` + +The `name` that you provide in values.yaml ie. `regcred` is name of the secret that will be used as `imagePullSecrets` to pull the image from docker hub to deploy. To know how `imagePullSecrets` will be used in the deployment-template, please follow the [documentation](https://docs.devtron.ai/devtron/user-guide/creating-application/deployment-template/rollout-deployment#imagepullsecrets). diff --git a/docs/user-guide/global-configurations/sso-login.md b/docs/user-guide/global-configurations/sso-login.md index 58b8ad1ae8..884c87077d 100644 --- a/docs/user-guide/global-configurations/sso-login.md +++ b/docs/user-guide/global-configurations/sso-login.md @@ -1,7 +1,7 @@ # SSO LOGIN -## OVERVIEW +## Overview -Once installed DEVTRON has one built-in `admin` user with super-admin privileges that is complete access to the system. It is recommended to use `admin` user only for initial and global configuration and then switch to local users or configure SSO integration. +Once installed Devtron has one built-in `admin` user with super-admin privileges that has complete access to the system. It is recommended to use `admin` user only for initial and global configuration and then switch to local users or configure SSO integration. Only users with super-admin privileges have access to create SSO configuration. Devtron uses dex for authenticating a user against the identity provider. @@ -32,11 +32,11 @@ Fill correct `redirect URL` or `callback URL` from which you have registered wit Only single SSO login configuration can be active at one time. Whenever you create or update any SSO config, it will be activated and used by the system and previous configurations will be deleted. -URL and redirectURI should be same as provided in screenshots except domain substring. +Except for the domain substring, URL and redirectURI should be the same as in the screenshots. ![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/sso-login-service/sso-login.jpg) -Click on `Save` bottom for creating and activating sso login on bottom right of the configuration. +Select `Save` to create and activate SSO login. ### 2. Update SSO Configuration diff --git a/docs/user-guide/global-configurations/user-access.md b/docs/user-guide/global-configurations/user-access.md index 76357bc48c..e1aac6062b 100644 --- a/docs/user-guide/global-configurations/user-access.md +++ b/docs/user-guide/global-configurations/user-access.md @@ -131,7 +131,7 @@ Similarly, you can select `Applications` from the drop-down corresponding to you There are four different view access levels/Role available for both User and Group as described [above](#access-levels): -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-configure-devtron-apps.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-permission_1.JPG) You can add multiple rows, for Devtron App Permission. @@ -163,7 +163,7 @@ Similarly, you can select `Applications` from the drop-down corresponding to you There are four different view access levels/Role available for both User and Group as described [above](#access-levels): -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-configure-helm-permission.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-permission_helm+app_2.JPG) ### Chart Group Permissions @@ -173,17 +173,17 @@ You can either give the users permission to `Create` or `Edit`. Click on the checkbox of `Create`, if you want the users to create, view, edit, or delete all the chart groups. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-chart-group-create.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/chart+group+permission_create_3.JPG) Click on the checkbox of `Edit`, if you want to `allow` or `deny` users to edit the chart groups. Select on `Deny` option from the drop-down menu, if you want to restrict the users to edit the chart groups. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-chart-group-edit.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/chart+group+permission_edit_4.JPG) Select the `Specific Charts` option from the drop-down menu, and then select the chart groups for which you want to allow users to edit, from the other drop-down menu. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-chart-edit2.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/chart+group+permission_edit+specific+chart_5.JPG) Click on `Save`, once you have configured all the required permissions for the users. @@ -191,11 +191,11 @@ Click on `Save`, once you have configured all the required permissions for the u You can edit the user permissions, by clicking on the `downward arrow`. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-edit-user-arrow.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/edit+user+permission_dropdown_1.JPG) Then you can edit the user permissions here. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-edit-user-permission.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/edit+user+permission_devtron+app_2.JPG) After you have done editing the user permissions. Click on `Save`. @@ -211,11 +211,11 @@ You can select the group which you are creating in the `Group permissions` secti Click on `Add Group`, to create a new group. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-group-create.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/Add+group+permission_dashboard_1.JPG) Enter the `Group Name` and `Description`. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-group-description.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/group+permission_description_2.JPG) ### 2. Create Group Permissions @@ -223,7 +223,7 @@ Once you have given the group name and group description. Then, control the access permissions of groups in the Devtron Apps, Helm Apps or Group Chart Permissions section. Manage the Project, Environment, Application, and Role access the same as we discuss in the above users section. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-add-group-configure.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/group+permission_devtron+app_3.JPG) You can add multiple rows, for the Devtron Apps and Helm Apps Permissions section. @@ -233,11 +233,11 @@ Once you have finished assigning the appropriate permissions for the listed user You can edit the group permissions, by clicking on the `downward arrow.` -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/gc-user-access-add-group-edit-arrow.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/group+permission_dropdown_4.JPG) Then you can edit the user permissions here. -![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/user-access-group-edit.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/global-configurations/user-access/edit+group+permission_devtron+app_5.JPG) Once you are done editing the group permissions. Click on `Save`. diff --git a/docs/user-guide/namespaces-and-environments.md b/docs/user-guide/namespaces-and-environments.md index 441726b475..8defdb5446 100644 --- a/docs/user-guide/namespaces-and-environments.md +++ b/docs/user-guide/namespaces-and-environments.md @@ -16,7 +16,7 @@ Environments in Devtron can be accessed from:- Global Configuration->Clusters & Environments -![](../.gitbook/assets/environments1%20%281%29.jpg) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/namespaces-and-environments/environments-2.jpg) Here multiple environments can be created. diff --git a/docs/user-guide/security-features.md b/docs/user-guide/security-features.md index 17d50c7e06..8a70abfd9e 100644 --- a/docs/user-guide/security-features.md +++ b/docs/user-guide/security-features.md @@ -69,7 +69,7 @@ Click on the `Show Source Info` option. A window will be expanded with two optio You can find Vulnerabilities on the `App Details` page too. Here we are displaying the total number of vulnerabilities found in the code and their Severity Level wise segregation. -![](../.gitbook/assets/security-feature-app-details-vulnerability.png) +![](https://devtron-public-asset.s3.us-east-2.amazonaws.com/images/security-features/security-feature-app-details-vulnerability.jpg) ## Security @@ -77,7 +77,7 @@ You can check Vulnerabilities for all your applications in one place. On the Hom **Note:-** -It displays the “Vulnerability count and Severity Level” on a priority basis. And critical level has the highest priority, so it displays the critical level vulnerabilities and there counts if any application is having critical Vulnerability in it. +It displays the “Vulnerability count and Severity Level” on a priority basis. And critical level has the highest priority, so it displays the critical level vulnerabilities and there counts if any application is having critical vulnerability in it. You can directly `Search` your application using the Search bar or you can `filter out` your requirement according to Severity, Clusters, and Environment. diff --git a/docs/user-guide/use-cases/connect-django-with-mysql-database.md b/docs/user-guide/use-cases/connect-django-with-mysql-database.md index 4877f490f3..9e5195b23c 100644 --- a/docs/user-guide/use-cases/connect-django-with-mysql-database.md +++ b/docs/user-guide/use-cases/connect-django-with-mysql-database.md @@ -37,7 +37,7 @@ The `settings.py` contains the configuration for your SQL database. Make sure th To learn how to create an application on Devtron, refer to our documentation on [Creating Application](../creating-application/) -#### _\*Git Material_ +#### _\*Git Repository_ In this example, we are using the url of the forked Git Repository. diff --git a/docs/user-guide/use-cases/connect-expressjs-with-mongodb-database.md b/docs/user-guide/use-cases/connect-expressjs-with-mongodb-database.md index 1c84bb0d1e..5ef76a2ff7 100644 --- a/docs/user-guide/use-cases/connect-expressjs-with-mongodb-database.md +++ b/docs/user-guide/use-cases/connect-expressjs-with-mongodb-database.md @@ -48,7 +48,7 @@ module.exports = { To learn how to create an application on Devtron, refer to our documentation on [Creating Application](../creating-application/) -### _\*Git Material_ +### _\*Git Repository_ In this example, we are using the url of the forked Git Repository. diff --git a/docs/user-guide/use-cases/connect-springboot-with-mysql-database.md b/docs/user-guide/use-cases/connect-springboot-with-mysql-database.md index 15c913ae5c..8f6c6f1435 100644 --- a/docs/user-guide/use-cases/connect-springboot-with-mysql-database.md +++ b/docs/user-guide/use-cases/connect-springboot-with-mysql-database.md @@ -55,9 +55,9 @@ ENTRYPOINT ["java","-jar", "app.jar"] To learn how to create an application on Devtron, refer to our documentation on [Creating Application](../creating-application/) -#### _\*Git Material_ +#### _\*Git Repository_ -In this example, we are using the url of the forked Git Repository. +In this example, we are using the url of the forked Git repository. #### _\*Docker configuration_ diff --git a/docs/user-guide/use-cases/devtron-generic-helm-chart-to-run-cron-job-or-one-time-job.md b/docs/user-guide/use-cases/devtron-generic-helm-chart-to-run-cron-job-or-one-time-job.md index 099b39ba50..9c68b9b1e6 100644 --- a/docs/user-guide/use-cases/devtron-generic-helm-chart-to-run-cron-job-or-one-time-job.md +++ b/docs/user-guide/use-cases/devtron-generic-helm-chart-to-run-cron-job-or-one-time-job.md @@ -12,7 +12,7 @@ Select the `Devtron-generic Helm Chart` from the Devtron Chart Store. Select the Chart Version and the Chart Value of the Chart. -And, then Click on `Deploy` +And, then click on `Deploy` ![](../../.gitbook/assets/use-case-deploy-chart%20%282%29.jpg) diff --git a/go.mod b/go.mod index 0898951352..b1bc360a62 100644 --- a/go.mod +++ b/go.mod @@ -104,6 +104,7 @@ require ( k8s.io/apimachinery v0.0.0-20190816221834-a9f1d8a9c101 k8s.io/client-go v11.0.1-0.20190820062731-7e43eff7c80a+incompatible k8s.io/helm v2.12.3+incompatible + k8s.io/klog v1.0.0 k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d // indirect k8s.io/utils v0.0.0-20191010214722-8d271d903fe4 mellium.im/sasl v0.2.1 // indirect diff --git a/go.sum b/go.sum index b9ca49ccbe..3175d285c8 100644 --- a/go.sum +++ b/go.sum @@ -1056,4 +1056,4 @@ xorm.io/builder v0.3.6 h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8= xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU= xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw= -xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= +xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= \ No newline at end of file diff --git a/internal/sql/repository/bulkUpdate/BulkUpdateRepository.go b/internal/sql/repository/bulkUpdate/BulkUpdateRepository.go index 588313235e..ea4869b94a 100644 --- a/internal/sql/repository/bulkUpdate/BulkUpdateRepository.go +++ b/internal/sql/repository/bulkUpdate/BulkUpdateRepository.go @@ -213,6 +213,7 @@ func (repositoryImpl BulkUpdateRepositoryImpl) FindBulkChartsEnvByAppNameSubstri Where("app.active = ?", true). Where("env_config_override.target_environment = ?", envId). Where("env_config_override.latest = ?", true). + Column("env_config_override.*", "Chart"). Select() return charts, err } diff --git a/internal/sql/repository/chartConfig/ConfigMapRepository.go b/internal/sql/repository/chartConfig/ConfigMapRepository.go index bed3e3ab84..d9d9cfd32d 100644 --- a/internal/sql/repository/chartConfig/ConfigMapRepository.go +++ b/internal/sql/repository/chartConfig/ConfigMapRepository.go @@ -36,6 +36,7 @@ type ConfigMapRepository interface { GetByAppIdAppLevel(appId int) (*ConfigMapAppModel, error) GetByAppIdAndEnvIdEnvLevel(appId int, envId int) (*ConfigMapEnvModel, error) + GetEnvLevelByAppId(appId int) ([]*ConfigMapEnvModel, error) } type ConfigMapRepositoryImpl struct { @@ -137,3 +138,13 @@ func (impl ConfigMapRepositoryImpl) GetByAppIdAndEnvIdEnvLevel(appId int, envId err := impl.dbConnection.Model(&model).Where("app_id = ?", appId).Where("environment_id = ?", envId).Select() return &model, err } + +func (impl ConfigMapRepositoryImpl) GetEnvLevelByAppId(appId int) ([]*ConfigMapEnvModel, error) { + var models []*ConfigMapEnvModel + err := impl.dbConnection.Model(&models).Where("app_id = ?", appId).Select() + if err != nil { + impl.Logger.Errorw("err in getting cm/cs env level", "err", err) + return models, err + } + return models, err +} diff --git a/internal/sql/repository/pipelineConfig/PipelineRepository.go b/internal/sql/repository/pipelineConfig/PipelineRepository.go index e0b17fd31b..562445257d 100644 --- a/internal/sql/repository/pipelineConfig/PipelineRepository.go +++ b/internal/sql/repository/pipelineConfig/PipelineRepository.go @@ -18,8 +18,8 @@ package pipelineConfig import ( - "github.com/devtron-labs/devtron/internal/sql/repository/appWorkflow" "github.com/devtron-labs/devtron/internal/sql/repository/app" + "github.com/devtron-labs/devtron/internal/sql/repository/appWorkflow" "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/sql" @@ -74,6 +74,7 @@ type PipelineRepository interface { FindByCiPipelineIdsIn(ciPipelineIds []int) ([]*Pipeline, error) FindAutomaticByCiPipelineId(ciPipelineId int) (pipelines []*Pipeline, err error) GetByEnvOverrideId(envOverrideId int) ([]Pipeline, error) + GetByEnvOverrideIdAndEnvId(envOverrideId, envId int) (Pipeline, error) FindActiveByAppIdAndEnvironmentId(appId int, environmentId int) (pipelines []*Pipeline, err error) UndoDelete(id int) error UniqueAppEnvironmentPipelines() ([]*Pipeline, error) @@ -85,6 +86,7 @@ type PipelineRepository interface { GetConnection() *pg.DB FindAllPipelineInLast24Hour() (pipelines []*Pipeline, err error) FindActiveByEnvId(envId int) (pipelines []*Pipeline, err error) + FindAllPipelinesByChartsOverrideAndAppIdAndChartId(chartOverridden bool, appId int, chartId int) (pipelines []*Pipeline, err error) } type CiArtifactDTO struct { @@ -275,7 +277,7 @@ func (impl PipelineRepositoryImpl) GetByEnvOverrideId(envOverrideId int) ([]Pipe query := "" + " SELECT p.*" + " FROM chart_env_config_override ceco" + - " INNER JOIN chart ch on ch.id = ceco.chart_id" + + " INNER JOIN charts ch on ch.id = ceco.chart_id" + " INNER JOIN environment env on env.id = ceco.target_environment" + " INNER JOIN app ap on ap.id = ch.app_id" + " INNER JOIN pipeline p on p.app_id = ap.id" + @@ -288,6 +290,24 @@ func (impl PipelineRepositoryImpl) GetByEnvOverrideId(envOverrideId int) ([]Pipe return pipelines, err } +func (impl PipelineRepositoryImpl) GetByEnvOverrideIdAndEnvId(envOverrideId, envId int) (Pipeline, error) { + var pipeline Pipeline + query := "" + + " SELECT p.*" + + " FROM chart_env_config_override ceco" + + " INNER JOIN charts ch on ch.id = ceco.chart_id" + + " INNER JOIN environment env on env.id = ceco.target_environment" + + " INNER JOIN app ap on ap.id = ch.app_id" + + " INNER JOIN pipeline p on p.app_id = ap.id" + + " WHERE ceco.id=? and p.environment_id=?;" + _, err := impl.dbConnection.Query(&pipeline, query, envOverrideId, envId) + + if err != nil { + return pipeline, err + } + return pipeline, err +} + func (impl PipelineRepositoryImpl) UniqueAppEnvironmentPipelines() ([]*Pipeline, error) { var pipelines []*Pipeline @@ -320,10 +340,25 @@ func (impl PipelineRepositoryImpl) FindAllPipelineInLast24Hour() (pipelines []*P Select() return pipelines, err } -func (impl PipelineRepositoryImpl) FindActiveByEnvId(envId int) (pipelines []*Pipeline, err error){ +func (impl PipelineRepositoryImpl) FindActiveByEnvId(envId int) (pipelines []*Pipeline, err error) { err = impl.dbConnection.Model(&pipelines). Where("environment_id = ?", envId). Where("deleted = ?", false). Select() return pipelines, err -} \ No newline at end of file +} + +func (impl PipelineRepositoryImpl) FindAllPipelinesByChartsOverrideAndAppIdAndChartId(hasConfigOverridden bool, appId int, chartId int) (pipelines []*Pipeline, err error) { + err = impl.dbConnection.Model(&pipelines). + Column("pipeline.*"). + Join("inner join charts on pipeline.app_id = charts.app_id"). + Join("inner join chart_env_config_override ceco on charts.id = ceco.chart_id"). + Where("pipeline.app_id = ?", appId). + Where("charts.id = ?", chartId). + Where("ceco.is_override = ?", hasConfigOverridden). + Where("pipeline.deleted = ?", false). + Where("ceco.active = ?", true). + Where("charts.active = ?", true). + Select() + return pipelines, err +} diff --git a/internal/util/ChartService.go b/internal/util/ChartService.go index 75e053f24e..aa16a753ff 100644 --- a/internal/util/ChartService.go +++ b/internal/util/ChartService.go @@ -46,6 +46,7 @@ type ChartTemplateService interface { GetChartVersion(location string) (string, error) CreateChartProxy(chartMetaData *chart.Metadata, refChartLocation string, templateName string, version string, envName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, *ChartGitAttribute, error) GitPull(clonedDir string, repoUrl string, appStoreName string) error + GetDir() string GetGitOpsRepoName(appName string) string GetGitOpsRepoNameFromUrl(gitRepoUrl string) string } @@ -81,7 +82,7 @@ func NewChartTemplateServiceImpl(logger *zap.SugaredLogger, } } -func (ChartTemplateServiceImpl) GetChartVersion(location string) (string, error) { +func (impl ChartTemplateServiceImpl) GetChartVersion(location string) (string, error) { if fi, err := os.Stat(location); err != nil { return "", err } else if !fi.IsDir() { @@ -90,7 +91,7 @@ func (ChartTemplateServiceImpl) GetChartVersion(location string) (string, error) chartYaml := filepath.Join(location, "Chart.yaml") if _, err := os.Stat(chartYaml); os.IsNotExist(err) { - return "", fmt.Errorf("no Chart.yaml exists in directory %q", location) + return "", fmt.Errorf("Chart.yaml file not present in the directory %q", location) } //chartYaml = filepath.Join(chartYaml,filepath.Clean(chartYaml)) chartYamlContent, err := ioutil.ReadFile(filepath.Clean(chartYaml)) @@ -102,12 +103,13 @@ func (ChartTemplateServiceImpl) GetChartVersion(location string) (string, error) if err != nil { return "", fmt.Errorf("cannot read Chart.Yaml in directory %q", location) } + return chartContent.Version, nil } func (impl ChartTemplateServiceImpl) CreateChart(chartMetaData *chart.Metadata, refChartLocation string, templateName string) (*ChartValues, *ChartGitAttribute, error) { chartMetaData.ApiVersion = "v1" // ensure always v1 - dir := impl.getDir() + dir := impl.GetDir() chartDir := filepath.Join(string(impl.chartWorkingDir), dir) impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling @@ -115,6 +117,7 @@ func (impl ChartTemplateServiceImpl) CreateChart(chartMetaData *chart.Metadata, impl.logger.Errorw("err in creating dir", "dir", chartDir, "err", err) return nil, nil, err } + defer impl.CleanDir(chartDir) err = dirCopy.Copy(refChartLocation, chartDir) @@ -176,7 +179,7 @@ func (impl ChartTemplateServiceImpl) createAndPushToGit(gitOpsRepoName, baseTemp } } - chartDir := fmt.Sprintf("%s-%s", gitOpsRepoName, impl.getDir()) + chartDir := fmt.Sprintf("%s-%s", gitOpsRepoName, impl.GetDir()) clonedDir := impl.gitFactory.gitService.GetCloneDirectory(chartDir) if _, err := os.Stat(clonedDir); os.IsNotExist(err) { clonedDir, err = impl.gitFactory.gitService.Clone(repoUrl, chartDir) @@ -228,38 +231,65 @@ func (impl ChartTemplateServiceImpl) createAndPushToGit(gitOpsRepoName, baseTemp } func (impl ChartTemplateServiceImpl) getValues(directory string) (values *ChartValues, err error) { - appOverrideByte, err := ioutil.ReadFile(filepath.Clean(filepath.Join(directory, "app-values.yaml"))) - if err != nil { - return nil, err - } - appOverrideByte, err = yaml.YAMLToJSON(appOverrideByte) - if err != nil { - return nil, err - } - envOverrideByte, err := ioutil.ReadFile(filepath.Clean(filepath.Join(directory, "env-values.yaml"))) - if err != nil { - return nil, err - } - envOverrideByte, err = yaml.YAMLToJSON(envOverrideByte) - if err != nil { - return nil, err - } - releaseOverrideByte, err := ioutil.ReadFile(filepath.Clean(filepath.Join(directory, "release-values.yaml"))) - if err != nil { - return nil, err - } - releaseOverrideByte, err = yaml.YAMLToJSON(releaseOverrideByte) - if err != nil { - return nil, err - } - pipelineOverrideByte, err := ioutil.ReadFile(filepath.Clean(filepath.Join(directory, "pipeline-values.yaml"))) - if err != nil { - return nil, err - } - pipelineOverrideByte, err = yaml.YAMLToJSON(pipelineOverrideByte) - if err != nil { + if fi, err := os.Stat(directory); err != nil { return nil, err + } else if !fi.IsDir() { + return nil, fmt.Errorf("%q is not a directory", directory) + } + + files, err := ioutil.ReadDir(directory) + if err != nil { + impl.logger.Errorw("failed reading directory", "err", err) + return nil, fmt.Errorf(" Couldn't read the %q", directory) + } + + var appOverrideByte, envOverrideByte, releaseOverrideByte, pipelineOverrideByte []byte + + for _, file := range files { + if !file.IsDir() { + name := strings.ToLower(file.Name()) + if name == "app-values.yaml" || name == "app-values.yml" { + appOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + } + appOverrideByte, err = yaml.YAMLToJSON(appOverrideByte) + if err != nil { + return nil, err + } + } + if name == "env-values.yaml" || name == "env-values.yml" { + envOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + } + envOverrideByte, err = yaml.YAMLToJSON(envOverrideByte) + if err != nil { + return nil, err + } + } + if name == "release-values.yaml" || name == "release-values.yml" { + releaseOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + } + releaseOverrideByte, err = yaml.YAMLToJSON(releaseOverrideByte) + if err != nil { + return nil, err + } + } + if name == "pipeline-values.yaml" || name == "pipeline-values.yml" { + pipelineOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + } + pipelineOverrideByte, err = yaml.YAMLToJSON(pipelineOverrideByte) + if err != nil { + return nil, err + } + } + } } val := &ChartValues{ @@ -317,7 +347,7 @@ func (impl ChartTemplateServiceImpl) CleanDir(dir string) { } } -func (impl ChartTemplateServiceImpl) getDir() string { +func (impl ChartTemplateServiceImpl) GetDir() string { /* #nosec */ r1 := rand.New(impl.randSource).Int63() return strconv.FormatInt(r1, 10) @@ -325,7 +355,7 @@ func (impl ChartTemplateServiceImpl) getDir() string { func (impl ChartTemplateServiceImpl) CreateChartProxy(chartMetaData *chart.Metadata, refChartLocation string, templateName string, version string, envName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, *ChartGitAttribute, error) { chartMetaData.ApiVersion = "v2" // ensure always v2 - dir := impl.getDir() + dir := impl.GetDir() chartDir := filepath.Join(string(impl.chartWorkingDir), dir) impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling @@ -388,7 +418,7 @@ func (impl ChartTemplateServiceImpl) createAndPushToGitChartProxy(appStoreName, return nil, err } } - chartDir := fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, impl.getDir()) + chartDir := fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, impl.GetDir()) clonedDir := impl.gitFactory.gitService.GetCloneDirectory(chartDir) if _, err := os.Stat(clonedDir); os.IsNotExist(err) { clonedDir, err = impl.gitFactory.gitService.Clone(repoUrl, chartDir) diff --git a/internal/util/EcrService.go b/internal/util/EcrService.go index 826f01d4bd..e2bd9f908d 100644 --- a/internal/util/EcrService.go +++ b/internal/util/EcrService.go @@ -22,19 +22,49 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ecr" "github.com/juju/errors" + "log" ) //FIXME: this code is temp func CreateEcrRepo(repoName string, reg string, accessKey string, secretKey string) error { region := reg - credentials := credentials.NewStaticCredentials(accessKey, secretKey, "") - svc := ecr.New(session.New(&aws.Config{ + //fmt.Printf("repoName %s, reg %s, accessKey %s, secretKey %s\n", repoName, reg, accessKey, secretKey) + + var creds *credentials.Credentials + + if len(accessKey) == 0 || len(secretKey) == 0 { + //fmt.Println("empty accessKey or secretKey") + sess, err := session.NewSession(&aws.Config{ + Region: ®ion, + }) + if err != nil { + log.Println(err) + return err + } + creds = ec2rolecreds.NewCredentials(sess) + } else { + creds = credentials.NewStaticCredentials(accessKey, secretKey, "") + } + + sess, err := session.NewSession(&aws.Config{ Region: ®ion, - Credentials: credentials, - })) + Credentials: creds, + }) + if err != nil { + log.Println(err) + return err + } + + svc := ecr.New(sess) + + if err != nil { + log.Println(err) + return err + } input := &ecr.CreateRepositoryInput{ RepositoryName: aws.String(repoName), } diff --git a/internal/util/K8sUtil.go b/internal/util/K8sUtil.go index 7ed07c6308..fff85eb51a 100644 --- a/internal/util/K8sUtil.go +++ b/internal/util/K8sUtil.go @@ -55,7 +55,7 @@ func NewK8sUtil(logger *zap.SugaredLogger, runTimeConfig *client.RuntimeConfig) if err != nil { return nil } - var kubeconfig *string; + var kubeconfig *string if runTimeConfig.LocalDevMode { kubeconfig = flag.String("kubeconfig-authenticator-xyz", filepath.Join(usr.HomeDir, ".kube", "config"), "(optional) absolute path to the kubeconfig file") } diff --git a/internal/util/K8sUtil_test.go b/internal/util/K8sUtil_test.go index d15ccc6b17..a1b50ff9a7 100644 --- a/internal/util/K8sUtil_test.go +++ b/internal/util/K8sUtil_test.go @@ -21,11 +21,11 @@ import ( "testing" ) -var client *K8sUtil +var k8sUtilClient *K8sUtil var clusterConfig *ClusterConfig func init() { - client = NewK8sUtil(NewSugardLogger()) + k8sUtilClient = NewK8sUtil(NewSugardLogger()) clusterConfig = &ClusterConfig{ Host: "", BearerToken: "", @@ -53,7 +53,7 @@ func TestK8sUtil_checkIfNsExists(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - impl := client + impl := k8sUtilClient k8s, _ := impl.GetClient(clusterConfig) gotExists, err := impl.checkIfNsExists(tt.namespace, k8s) if (err != nil) != tt.wantErr { @@ -81,7 +81,7 @@ func TestK8sUtil_CreateNsIfNotExists(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - impl := client + impl := k8sUtilClient if err := impl.CreateNsIfNotExists(tt.namespace, clusterConfig); (err != nil) != tt.wantErr { t.Errorf("K8sUtil.CreateNsIfNotExists() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/manifests/install/devtron-installer.yaml b/manifests/install/devtron-installer.yaml index fd3bf2d11a..b3128521f0 100644 --- a/manifests/install/devtron-installer.yaml +++ b/manifests/install/devtron-installer.yaml @@ -4,4 +4,4 @@ metadata: name: installer-devtron namespace: devtroncd spec: - url: https://raw.githubusercontent.com/devtron-labs/devtron/v0.3.18/manifests/installation-script + url: https://raw.githubusercontent.com/devtron-labs/devtron/v0.3.26/manifests/installation-script diff --git a/manifests/installation-script b/manifests/installation-script index 8f0a586b2c..c59588ddb0 100644 --- a/manifests/installation-script +++ b/manifests/installation-script @@ -1,4 +1,4 @@ -LTAG="v0.3.18"; +LTAG="v0.3.26"; REPO_RAW_URL="https://raw.githubusercontent.com/devtron-labs/devtron/"; operatorSecret = kubectl get secret -n devtroncd devtron-operator-secret; diff --git a/manifests/version.txt b/manifests/version.txt index 4f125aef4e..fdaf2b54e0 100644 --- a/manifests/version.txt +++ b/manifests/version.txt @@ -1 +1 @@ -v0.3.18 \ No newline at end of file +v0.3.26 \ No newline at end of file diff --git a/manifests/yamls/dashboard.yaml b/manifests/yamls/dashboard.yaml index 5390a0e20c..40ffbda449 100644 --- a/manifests/yamls/dashboard.yaml +++ b/manifests/yamls/dashboard.yaml @@ -231,7 +231,7 @@ spec: - name: envoy-config-volume mountPath: /etc/envoy-config/ - name: dashboard - image: "quay.io/devtron/dashboard:0a473777-136-7240" + image: "quay.io/devtron/dashboard:57632b6b-325-7998" imagePullPolicy: IfNotPresent ports: - name: app diff --git a/manifests/yamls/devtron.yaml b/manifests/yamls/devtron.yaml index ee00bcadd4..7412d2b41a 100644 --- a/manifests/yamls/devtron.yaml +++ b/manifests/yamls/devtron.yaml @@ -57,7 +57,7 @@ data: CD_NODE_TAINTS_VALUE: "ci" CD_ARTIFACT_LOCATION_FORMAT: "%d/%d.zip" DEFAULT_CD_NAMESPACE: "devtron-cd" - DEFAULT_CI_IMAGE: "quay.io/devtron/ci-runner:f948c43c-138-7243" + DEFAULT_CI_IMAGE: "quay.io/devtron/ci-runner:a92c1a6a-138-8006" DEFAULT_CD_TIMEOUT: "3600" WF_CONTROLLER_INSTANCE_ID: "devtron-runner" CI_LOGS_KEY_PREFIX: "ci-artifacts" @@ -155,7 +155,7 @@ spec: serviceAccountName: devtron containers: - name: devtron - image: "quay.io/devtron/devtron:721c9243-146-7242" + image: "quay.io/devtron/devtron:02842282-326-7999" imagePullPolicy: IfNotPresent ports: - name: devtron diff --git a/manifests/yamls/gitsensor.yaml b/manifests/yamls/gitsensor.yaml index 2356bfa59c..8904071745 100644 --- a/manifests/yamls/gitsensor.yaml +++ b/manifests/yamls/gitsensor.yaml @@ -54,7 +54,7 @@ spec: terminationGracePeriodSeconds: 10 containers: - name: git-sensor - image: "quay.io/devtron/git-sensor:5e008065-200-6835" + image: "quay.io/devtron/git-sensor:4842c981-200-7391" ports: - containerPort: 8080 name: sensor diff --git a/manifests/yamls/image-scanner.yaml b/manifests/yamls/image-scanner.yaml index 91f26a87ad..62d0480e54 100644 --- a/manifests/yamls/image-scanner.yaml +++ b/manifests/yamls/image-scanner.yaml @@ -69,7 +69,7 @@ spec: restartPolicy: Always containers: - name: image-scanner - image: quay.io/devtron/imge-scanner:c61f2aa7-141-6747 + image: "quay.io/devtron/imge-scanner:5901cb7f-141-8007" imagePullPolicy: IfNotPresent ports: - name: app diff --git a/manifests/yamls/kubelink.yaml b/manifests/yamls/kubelink.yaml index 89feb049e5..ed0b442740 100644 --- a/manifests/yamls/kubelink.yaml +++ b/manifests/yamls/kubelink.yaml @@ -21,7 +21,7 @@ spec: serviceAccount: devtron containers: - name: kubelink - image: quay.io/devtron/kubelink:b0f37018-283-7102 + image: "quay.io/devtron/kubelink:1be465ec-318-7966" imagePullPolicy: IfNotPresent ports: - name: app diff --git a/manifests/yamls/migrator.yaml b/manifests/yamls/migrator.yaml index af81c29422..0dccad4a59 100644 --- a/manifests/yamls/migrator.yaml +++ b/manifests/yamls/migrator.yaml @@ -40,7 +40,7 @@ spec: - name: MIGRATE_TO_VERSION value: "0" - name: GIT_HASH - value: 721c92435f00289b0c3218f334ca93a78051db2a + value: 02842282899755e13efb25d51248dadc04739392 envFrom: - secretRef: name: postgresql-migrator @@ -81,7 +81,7 @@ spec: - name: MIGRATE_TO_VERSION value: "0" - name: GIT_HASH - value: 721c92435f00289b0c3218f334ca93a78051db2a + value: 02842282899755e13efb25d51248dadc04739392 - name: GIT_BRANCH value: main envFrom: @@ -125,7 +125,7 @@ spec: - name: GIT_BRANCH value: main - name: GIT_HASH - value: 5e0080657ffd9ccc04889ab94a014294f57e5fe3 + value: 4842c981f4879be538276a965a7c916a81475885 envFrom: - secretRef: name: postgresql-migrator diff --git a/pkg/app/AppLabelsService.go b/pkg/app/AppLabelsService.go index 1d0eb33c58..945200dc1b 100644 --- a/pkg/app/AppLabelsService.go +++ b/pkg/app/AppLabelsService.go @@ -201,17 +201,25 @@ func (impl AppLabelServiceImpl) GetAppMetaInfo(appId int) (*bean.AppMetaInfoDto, } } - user, err := impl.userRepository.GetById(app.CreatedBy) - if err != nil { + user, err := impl.userRepository.GetByIdIncludeDeleted(app.CreatedBy) + if err != nil && err != pg.ErrNoRows { impl.logger.Errorw("error in fetching user for app meta info", "error", err) return nil, err } + userEmailId := "" + if user != nil && user.Id > 0 { + if user.Active { + userEmailId = fmt.Sprintf(user.EmailId) + } else { + userEmailId = fmt.Sprintf("%s (inactive)", user.EmailId) + } + } info := &bean.AppMetaInfoDto{ AppId: app.Id, AppName: app.AppName, ProjectId: app.TeamId, ProjectName: app.Team.Name, - CreatedBy: user.EmailId, + CreatedBy: userEmailId, CreatedOn: app.CreatedOn, Labels: labels, Active: app.Active, diff --git a/pkg/app/AppService.go b/pkg/app/AppService.go index 0079a42c24..d6e342cb0d 100644 --- a/pkg/app/AppService.go +++ b/pkg/app/AppService.go @@ -24,6 +24,7 @@ import ( "github.com/devtron-labs/devtron/internal/sql/repository/app" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + history2 "github.com/devtron-labs/devtron/pkg/pipeline/history" "github.com/devtron-labs/devtron/pkg/sql" "github.com/devtron-labs/devtron/pkg/user/casbin" util3 "github.com/devtron-labs/devtron/pkg/util" @@ -61,45 +62,48 @@ import ( ) type AppServiceImpl struct { - environmentConfigRepository chartConfig.EnvConfigOverrideRepository - pipelineOverrideRepository chartConfig.PipelineOverrideRepository - mergeUtil *MergeUtil - logger *zap.SugaredLogger - ciArtifactRepository repository.CiArtifactRepository - pipelineRepository pipelineConfig.PipelineRepository - gitFactory *GitFactory - dbMigrationConfigRepository pipelineConfig.DbMigrationConfigRepository - eventClient client.EventClient - eventFactory client.EventFactory - acdClient application.ServiceClient - tokenCache *util3.TokenCache - acdAuthConfig *util3.ACDAuthConfig - enforcer casbin.Enforcer - enforcerUtil rbac.EnforcerUtil - user user.UserService - appListingRepository repository.AppListingRepository - appRepository app.AppRepository - envRepository repository2.EnvironmentRepository - pipelineConfigRepository chartConfig.PipelineConfigRepository - configMapRepository chartConfig.ConfigMapRepository - chartRepository chartRepoRepository.ChartRepository - appRepo app.AppRepository - appLevelMetricsRepository repository.AppLevelMetricsRepository - envLevelMetricsRepository repository.EnvLevelAppMetricsRepository - ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository - cdWorkflowRepository pipelineConfig.CdWorkflowRepository - commonService commonService.CommonService - imageScanDeployInfoRepository security.ImageScanDeployInfoRepository - imageScanHistoryRepository security.ImageScanHistoryRepository - ArgoK8sClient argocdServer.ArgoK8sClient - gitOpsRepository repository.GitOpsConfigRepository + environmentConfigRepository chartConfig.EnvConfigOverrideRepository + pipelineOverrideRepository chartConfig.PipelineOverrideRepository + mergeUtil *MergeUtil + logger *zap.SugaredLogger + ciArtifactRepository repository.CiArtifactRepository + pipelineRepository pipelineConfig.PipelineRepository + gitFactory *GitFactory + dbMigrationConfigRepository pipelineConfig.DbMigrationConfigRepository + eventClient client.EventClient + eventFactory client.EventFactory + acdClient application.ServiceClient + tokenCache *util3.TokenCache + acdAuthConfig *util3.ACDAuthConfig + enforcer casbin.Enforcer + enforcerUtil rbac.EnforcerUtil + user user.UserService + appListingRepository repository.AppListingRepository + appRepository app.AppRepository + envRepository repository2.EnvironmentRepository + pipelineConfigRepository chartConfig.PipelineConfigRepository + configMapRepository chartConfig.ConfigMapRepository + chartRepository chartRepoRepository.ChartRepository + appRepo app.AppRepository + appLevelMetricsRepository repository.AppLevelMetricsRepository + envLevelMetricsRepository repository.EnvLevelAppMetricsRepository + ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository + cdWorkflowRepository pipelineConfig.CdWorkflowRepository + commonService commonService.CommonService + imageScanDeployInfoRepository security.ImageScanDeployInfoRepository + imageScanHistoryRepository security.ImageScanHistoryRepository + ArgoK8sClient argocdServer.ArgoK8sClient + gitOpsRepository repository.GitOpsConfigRepository + pipelineStrategyHistoryService history2.PipelineStrategyHistoryService + configMapHistoryService history2.ConfigMapHistoryService + deploymentTemplateHistoryService history2.DeploymentTemplateHistoryService } type AppService interface { - TriggerRelease(overrideRequest *bean.ValuesOverrideRequest, ctx context.Context) (id int, err error) + TriggerRelease(overrideRequest *bean.ValuesOverrideRequest, ctx context.Context, triggeredAt time.Time) (id int, err error) UpdateReleaseStatus(request *bean.ReleaseStatusUpdateRequest) (bool, error) UpdateApplicationStatusAndCheckIsHealthy(application v1alpha1.Application) (bool, error) - TriggerCD(artifact *repository.CiArtifact, cdWorkflowId int, pipeline *pipelineConfig.Pipeline, async bool) error + TriggerCD(artifact *repository.CiArtifact, cdWorkflowId int, pipeline *pipelineConfig.Pipeline, async bool, triggeredAt time.Time) error GetConfigMapAndSecretJson(appId int, envId int, pipelineId int) ([]byte, error) UpdateCdWorkflowRunnerByACDObject(app v1alpha1.Application, cdWorkflowId int) error GetCmSecretNew(appId int, envId int) (*bean.ConfigMapJson, *bean.ConfigSecretJson, error) @@ -129,39 +133,45 @@ func NewAppService( cdWorkflowRepository pipelineConfig.CdWorkflowRepository, commonService commonService.CommonService, imageScanDeployInfoRepository security.ImageScanDeployInfoRepository, imageScanHistoryRepository security.ImageScanHistoryRepository, ArgoK8sClient argocdServer.ArgoK8sClient, - gitFactory *GitFactory, gitOpsRepository repository.GitOpsConfigRepository) *AppServiceImpl { + gitFactory *GitFactory, gitOpsRepository repository.GitOpsConfigRepository, + pipelineStrategyHistoryService history2.PipelineStrategyHistoryService, + configMapHistoryService history2.ConfigMapHistoryService, + deploymentTemplateHistoryService history2.DeploymentTemplateHistoryService) *AppServiceImpl { appServiceImpl := &AppServiceImpl{ - environmentConfigRepository: environmentConfigRepository, - mergeUtil: mergeUtil, - pipelineOverrideRepository: pipelineOverrideRepository, - logger: logger, - ciArtifactRepository: ciArtifactRepository, - pipelineRepository: pipelineRepository, - dbMigrationConfigRepository: dbMigrationConfigRepository, - eventClient: eventClient, - eventFactory: eventFactory, - acdClient: acdClient, - tokenCache: cache, - acdAuthConfig: authConfig, - enforcer: enforcer, - enforcerUtil: enforcerUtil, - user: user, - appListingRepository: appListingRepository, - appRepository: appRepository, - envRepository: envRepository, - pipelineConfigRepository: pipelineConfigRepository, - configMapRepository: configMapRepository, - chartRepository: chartRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - envLevelMetricsRepository: envLevelMetricsRepository, - ciPipelineMaterialRepository: ciPipelineMaterialRepository, - cdWorkflowRepository: cdWorkflowRepository, - commonService: commonService, - imageScanDeployInfoRepository: imageScanDeployInfoRepository, - imageScanHistoryRepository: imageScanHistoryRepository, - ArgoK8sClient: ArgoK8sClient, - gitFactory: gitFactory, - gitOpsRepository: gitOpsRepository, + environmentConfigRepository: environmentConfigRepository, + mergeUtil: mergeUtil, + pipelineOverrideRepository: pipelineOverrideRepository, + logger: logger, + ciArtifactRepository: ciArtifactRepository, + pipelineRepository: pipelineRepository, + dbMigrationConfigRepository: dbMigrationConfigRepository, + eventClient: eventClient, + eventFactory: eventFactory, + acdClient: acdClient, + tokenCache: cache, + acdAuthConfig: authConfig, + enforcer: enforcer, + enforcerUtil: enforcerUtil, + user: user, + appListingRepository: appListingRepository, + appRepository: appRepository, + envRepository: envRepository, + pipelineConfigRepository: pipelineConfigRepository, + configMapRepository: configMapRepository, + chartRepository: chartRepository, + appLevelMetricsRepository: appLevelMetricsRepository, + envLevelMetricsRepository: envLevelMetricsRepository, + ciPipelineMaterialRepository: ciPipelineMaterialRepository, + cdWorkflowRepository: cdWorkflowRepository, + commonService: commonService, + imageScanDeployInfoRepository: imageScanDeployInfoRepository, + imageScanHistoryRepository: imageScanHistoryRepository, + ArgoK8sClient: ArgoK8sClient, + gitFactory: gitFactory, + gitOpsRepository: gitOpsRepository, + pipelineStrategyHistoryService: pipelineStrategyHistoryService, + configMapHistoryService: configMapHistoryService, + deploymentTemplateHistoryService: deploymentTemplateHistoryService, } return appServiceImpl } @@ -309,14 +319,14 @@ func (conf *EnvironmentOverride) appendEnvironmentVariable(key, value string) { conf.EnvValues = append(conf.EnvValues, item) } -func (impl *AppServiceImpl) TriggerCD(artifact *repository.CiArtifact, cdWorkflowId int, pipeline *pipelineConfig.Pipeline, async bool) error { +func (impl *AppServiceImpl) TriggerCD(artifact *repository.CiArtifact, cdWorkflowId int, pipeline *pipelineConfig.Pipeline, async bool, triggeredAt time.Time) error { impl.logger.Debugw("automatic pipeline trigger attempt async", "artifactId", artifact.Id) - return impl.triggerReleaseAsync(artifact, cdWorkflowId, pipeline) + return impl.triggerReleaseAsync(artifact, cdWorkflowId, pipeline, triggeredAt) } -func (impl *AppServiceImpl) triggerReleaseAsync(artifact *repository.CiArtifact, cdWorkflowId int, pipeline *pipelineConfig.Pipeline) error { - err := impl.validateAndTrigger(pipeline, artifact, cdWorkflowId) +func (impl *AppServiceImpl) triggerReleaseAsync(artifact *repository.CiArtifact, cdWorkflowId int, pipeline *pipelineConfig.Pipeline, triggeredAt time.Time) error { + err := impl.validateAndTrigger(pipeline, artifact, cdWorkflowId, triggeredAt) if err != nil { impl.logger.Errorw("error in trigger for pipeline", "pipelineId", strconv.Itoa(pipeline.Id)) } @@ -324,18 +334,18 @@ func (impl *AppServiceImpl) triggerReleaseAsync(artifact *repository.CiArtifact, return err } -func (impl AppServiceImpl) validateAndTrigger(p *pipelineConfig.Pipeline, artifact *repository.CiArtifact, cdWorkflowId int) error { +func (impl AppServiceImpl) validateAndTrigger(p *pipelineConfig.Pipeline, artifact *repository.CiArtifact, cdWorkflowId int, triggeredAt time.Time) error { object := impl.enforcerUtil.GetAppRBACNameByAppId(p.AppId) envApp := strings.Split(object, "/") if len(envApp) != 2 { impl.logger.Error("invalid req, app and env not found from rbac") return errors.New("invalid req, app and env not found from rbac") } - err := impl.releasePipeline(p, artifact, cdWorkflowId) + err := impl.releasePipeline(p, artifact, cdWorkflowId, triggeredAt) return err } -func (impl AppServiceImpl) releasePipeline(pipeline *pipelineConfig.Pipeline, artifact *repository.CiArtifact, cdWorkflowId int) error { +func (impl AppServiceImpl) releasePipeline(pipeline *pipelineConfig.Pipeline, artifact *repository.CiArtifact, cdWorkflowId int, triggeredAt time.Time) error { impl.logger.Debugw("triggering release for ", "cdPipelineId", pipeline.Id, "artifactId", artifact.Id) //Iterate for each even if there is error in one request := &bean.ValuesOverrideRequest{ @@ -353,7 +363,7 @@ func (impl AppServiceImpl) releasePipeline(pipeline *pipelineConfig.Pipeline, ar return err } - id, err := impl.TriggerRelease(request, ctx) + id, err := impl.TriggerRelease(request, ctx, triggeredAt) if err != nil { impl.logger.Errorw("error in auto cd pipeline trigger", "pipelineId", pipeline.Id, "artifactId", artifact.Id, "err", err) } else { @@ -443,7 +453,7 @@ func (impl AppServiceImpl) getDbMigrationOverride(overrideRequest *bean.ValuesOv return confByte, nil } -func (impl AppServiceImpl) TriggerRelease(overrideRequest *bean.ValuesOverrideRequest, ctx context.Context) (id int, err error) { +func (impl AppServiceImpl) TriggerRelease(overrideRequest *bean.ValuesOverrideRequest, ctx context.Context, triggeredAt time.Time) (id int, err error) { if overrideRequest.DeploymentType == models.DEPLOYMENTTYPE_UNKNOWN { overrideRequest.DeploymentType = models.DEPLOYMENTTYPE_DEPLOY } @@ -482,7 +492,7 @@ func (impl AppServiceImpl) TriggerRelease(overrideRequest *bean.ValuesOverrideRe Status: models.CHARTSTATUS_SUCCESS, TargetEnvironment: pipeline.EnvironmentId, ChartId: chart.Id, - AuditLog: sql.AuditLog{UpdatedBy: overrideRequest.UserId, UpdatedOn: time.Now(), CreatedOn: time.Now(), CreatedBy: overrideRequest.UserId}, + AuditLog: sql.AuditLog{UpdatedBy: overrideRequest.UserId, UpdatedOn: triggeredAt, CreatedOn: triggeredAt, CreatedBy: overrideRequest.UserId}, Namespace: environment.Namespace, IsOverride: false, EnvOverrideValues: "{}", @@ -570,7 +580,7 @@ func (impl AppServiceImpl) TriggerRelease(overrideRequest *bean.ValuesOverrideRe configMapJson = nil } - releaseId, pipelineOverrideId, saveErr := impl.mergeAndSave(envOverride, overrideRequest, dbMigrationOverride, artifact, pipeline, configMapJson, strategy, ctx) + releaseId, pipelineOverrideId, saveErr := impl.mergeAndSave(envOverride, overrideRequest, dbMigrationOverride, artifact, pipeline, configMapJson, strategy, ctx, triggeredAt) if releaseId != 0 { flag, err := impl.updateArgoPipeline(overrideRequest.AppId, pipeline.Name, envOverride, ctx) if err != nil { @@ -588,8 +598,8 @@ func (impl AppServiceImpl) TriggerRelease(overrideRequest *bean.ValuesOverrideRe AppId: pipeline.AppId, EnvId: pipeline.EnvironmentId, Status: repository.NewDeployment, - CreatedOn: time.Now(), - UpdatedOn: time.Now(), + CreatedOn: triggeredAt, + UpdatedOn: triggeredAt, } dbConnection := impl.pipelineRepository.GetConnection() tx, err := dbConnection.Begin() @@ -1041,10 +1051,11 @@ func (impl AppServiceImpl) mergeAndSave(envOverride *chartConfig.EnvConfigOverri overrideRequest *bean.ValuesOverrideRequest, dbMigrationOverride []byte, artifact *repository.CiArtifact, - pipeline *pipelineConfig.Pipeline, configMapJson []byte, strategy *chartConfig.PipelineStrategy, ctx context.Context) (releaseId int, overrideId int, err error) { + pipeline *pipelineConfig.Pipeline, configMapJson []byte, strategy *chartConfig.PipelineStrategy, ctx context.Context, + triggeredAt time.Time) (releaseId int, overrideId int, err error) { //register release , obtain release id TODO: populate releaseId to template - override, err := impl.savePipelineOverride(overrideRequest, envOverride.Id) + override, err := impl.savePipelineOverride(overrideRequest, envOverride.Id, triggeredAt) if err != nil { return 0, 0, err } @@ -1126,16 +1137,21 @@ func (impl AppServiceImpl) mergeAndSave(envOverride *chartConfig.EnvConfigOverri PipelineId: overrideRequest.PipelineId, CiArtifactId: overrideRequest.CiArtifactId, PipelineMergedValues: string(merged), - AuditLog: sql.AuditLog{UpdatedOn: time.Now(), UpdatedBy: overrideRequest.UserId}, + AuditLog: sql.AuditLog{UpdatedOn: triggeredAt, UpdatedBy: overrideRequest.UserId}, } err = impl.pipelineOverrideRepository.Update(pipelineOverride) if err != nil { return 0, 0, err } + err = impl.CreateHistoriesForDeploymentTrigger(pipeline, strategy, envOverride, overrideJson, triggeredAt, pipelineOverride.UpdatedBy) + if err != nil { + impl.logger.Errorw("error in creating history entries for deployment trigger", "err", err) + return 0, 0, err + } return override.PipelineReleaseCounter, override.Id, nil } -func (impl AppServiceImpl) savePipelineOverride(overrideRequest *bean.ValuesOverrideRequest, envOverrideId int) (override *chartConfig.PipelineOverride, err error) { +func (impl AppServiceImpl) savePipelineOverride(overrideRequest *bean.ValuesOverrideRequest, envOverrideId int, triggeredAt time.Time) (override *chartConfig.PipelineOverride, err error) { currentReleaseNo, err := impl.pipelineOverrideRepository.GetCurrentPipelineReleaseCounter(overrideRequest.PipelineId) if err != nil { return nil, err @@ -1147,7 +1163,7 @@ func (impl AppServiceImpl) savePipelineOverride(overrideRequest *bean.ValuesOver CiArtifactId: overrideRequest.CiArtifactId, PipelineReleaseCounter: currentReleaseNo + 1, CdWorkflowId: overrideRequest.CdWorkflowId, - AuditLog: sql.AuditLog{CreatedBy: overrideRequest.UserId, CreatedOn: time.Now(), UpdatedOn: time.Now(), UpdatedBy: overrideRequest.UserId}, + AuditLog: sql.AuditLog{CreatedBy: overrideRequest.UserId, CreatedOn: triggeredAt, UpdatedOn: triggeredAt, UpdatedBy: overrideRequest.UserId}, DeploymentType: overrideRequest.DeploymentType, } @@ -1330,3 +1346,23 @@ func (impl *AppServiceImpl) hpaCheckBeforeTrigger(ctx context.Context, appName s return merged } + +func (impl *AppServiceImpl) CreateHistoriesForDeploymentTrigger(pipeline *pipelineConfig.Pipeline, strategy *chartConfig.PipelineStrategy, envOverride *chartConfig.EnvConfigOverride, renderedImageTemplate string, deployedOn time.Time, deployedBy int32) error { + //creating history for deployment template + err := impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryForDeploymentTrigger(pipeline, envOverride, renderedImageTemplate, deployedOn, deployedBy) + if err != nil { + impl.logger.Errorw("error in creating deployment template history for deployment trigger", "err", err) + return err + } + err = impl.configMapHistoryService.CreateCMCSHistoryForDeploymentTrigger(pipeline, deployedOn, deployedBy) + if err != nil { + impl.logger.Errorw("error in creating CM/CS history for deployment trigger", "err", err) + return err + } + err = impl.pipelineStrategyHistoryService.CreateStrategyHistoryForDeploymentTrigger(strategy, deployedOn, deployedBy) + if err != nil { + impl.logger.Errorw("error in creating strategy history for deployment trigger", "err", err) + return err + } + return nil +} diff --git a/pkg/appStore/bean/bean.go b/pkg/appStore/bean/bean.go index f49d33a3d5..ffecf8859b 100644 --- a/pkg/appStore/bean/bean.go +++ b/pkg/appStore/bean/bean.go @@ -24,6 +24,44 @@ import ( ) //v1 +type InstallAppVersionHistoryDto struct { + InstalledAppInfo *InstalledAppDto `json:"installedAppInfo"` + IAVHistory []*IAVHistory `json:"deploymentHistory"` +} +type IAVHistory struct { + ChartMetaData IAVHistoryChartMetaData `json:"chartMetadata"` + DeployedAt IAVHistoryDeployedAt `json:"deployedAt"` + DockerImages []string `json:"dockerImages"` + Version int `json:"version"` + InstalledAppVersionId int `json:"installedAppVersionId"` +} +type IAVHistoryChartMetaData struct { + ChartName string `json:"chartName"` + ChartVersion string `json:"chartVersion"` + Description string `json:"description"` + Home string `json:"home"` + Sources []string `json:"sources"` +} + +type IAVHistoryDeployedAt struct { + Nanos int `json:"nanos,omitempty"` + Seconds int64 `json:"seconds,omitempty"` +} + +type IAVHistoryValues struct { + Manifest string `json:"manifest"` + ValuesYaml string `json:"valuesYaml"` +} + +type InstalledAppDto struct { + AppId int `json:"appId"` + InstalledAppId int `json:"installedAppId"` + EnvironmentName string `json:"environmentName"` + AppOfferingMode string `json:"appOfferingMode"` + ClusterId int `json:"clusterId"` + EnvironmentId int `json:"environmentId"` +} + type InstallAppVersionDTO struct { Id int `json:"id,omitempty"` AppId int `json:"appId,omitempty"` @@ -51,6 +89,8 @@ type InstallAppVersionDTO struct { Namespace string `json:"namespace"` // needed for hyperion mode AppOfferingMode string `json:"appOfferingMode"` GitOpsRepoName string `json:"gitOpsRepoName"` + GitOpsPath string `json:"gitOpsPath"` + GitHash string `json:"gitHash"` EnvironmentName string `json:"-"` InstallAppVersionChartDTO *InstallAppVersionChartDTO `json:"-"` } diff --git a/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go b/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go index b51452a931..255932f242 100644 --- a/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go +++ b/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go @@ -19,21 +19,22 @@ package appStoreDeploymentCommon import ( appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" "github.com/go-pg/pg" "go.uber.org/zap" ) type AppStoreDeploymentCommonService interface { GetInstalledAppByClusterNamespaceAndName(clusterId int, namespace string, appName string) (*appStoreBean.InstallAppVersionDTO, error) + GetInstalledAppByInstalledAppId(installedAppId int) (*appStoreBean.InstallAppVersionDTO, error) } type AppStoreDeploymentCommonServiceImpl struct { logger *zap.SugaredLogger - installedAppRepository appStoreRepository.InstalledAppRepository + installedAppRepository repository.InstalledAppRepository } -func NewAppStoreDeploymentCommonServiceImpl(logger *zap.SugaredLogger, installedAppRepository appStoreRepository.InstalledAppRepository) *AppStoreDeploymentCommonServiceImpl { +func NewAppStoreDeploymentCommonServiceImpl(logger *zap.SugaredLogger, installedAppRepository repository.InstalledAppRepository) *AppStoreDeploymentCommonServiceImpl { return &AppStoreDeploymentCommonServiceImpl{ logger: logger, installedAppRepository: installedAppRepository, @@ -42,7 +43,6 @@ func NewAppStoreDeploymentCommonServiceImpl(logger *zap.SugaredLogger, installed func (impl AppStoreDeploymentCommonServiceImpl) GetInstalledAppByClusterNamespaceAndName(clusterId int, namespace string, appName string) (*appStoreBean.InstallAppVersionDTO, error) { installedApp, err := impl.installedAppRepository.GetInstalledApplicationByClusterIdAndNamespaceAndAppName(clusterId, namespace, appName) - if err != nil { if err == pg.ErrNoRows { impl.logger.Warnw("no installed apps found", "clusterId", clusterId) @@ -64,20 +64,32 @@ func (impl AppStoreDeploymentCommonServiceImpl) GetInstalledAppByClusterNamespac return nil, nil } +func (impl AppStoreDeploymentCommonServiceImpl) GetInstalledAppByInstalledAppId(installedAppId int) (*appStoreBean.InstallAppVersionDTO, error) { + installedAppVersion, err := impl.installedAppRepository.GetActiveInstalledAppVersionByInstalledAppId(installedAppId) + if err != nil { + return nil, err + } + installedApp := &installedAppVersion.InstalledApp + return impl.convert(installedApp, installedAppVersion), nil + + return nil, nil +} + //converts db object to bean -func (impl AppStoreDeploymentCommonServiceImpl) convert(chart *appStoreRepository.InstalledApps, installedAppVersion *appStoreRepository.InstalledAppVersions) *appStoreBean.InstallAppVersionDTO { +func (impl AppStoreDeploymentCommonServiceImpl) convert(chart *repository.InstalledApps, installedAppVersion *repository.InstalledAppVersions) *appStoreBean.InstallAppVersionDTO { chartVersionApp := installedAppVersion.AppStoreApplicationVersion chartRepo := installedAppVersion.AppStoreApplicationVersion.AppStore.ChartRepo return &appStoreBean.InstallAppVersionDTO{ - EnvironmentId: chart.EnvironmentId, - Id: chart.Id, - AppId: chart.AppId, - AppOfferingMode: chart.App.AppOfferingMode, - ClusterId: chart.Environment.ClusterId, - Namespace: chart.Environment.Namespace, - AppName: chart.App.AppName, - EnvironmentName: chart.Environment.Name, - InstalledAppId: chart.Id, + EnvironmentId: chart.EnvironmentId, + Id: chart.Id, + AppId: chart.AppId, + AppOfferingMode: chart.App.AppOfferingMode, + ClusterId: chart.Environment.ClusterId, + Namespace: chart.Environment.Namespace, + AppName: chart.App.AppName, + EnvironmentName: chart.Environment.Name, + InstalledAppId: chart.Id, + InstalledAppVersionId: installedAppVersion.Id, InstallAppVersionChartDTO: &appStoreBean.InstallAppVersionChartDTO{ AppStoreChartId: chartVersionApp.AppStore.Id, ChartName: chartVersionApp.Name, diff --git a/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go b/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go index 576b7eced8..3d506ea076 100644 --- a/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go +++ b/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go @@ -21,6 +21,7 @@ import ( "context" "github.com/devtron-labs/devtron/client/argocdServer" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + repository4 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" repository5 "github.com/devtron-labs/devtron/pkg/cluster/repository" util2 "github.com/devtron-labs/devtron/pkg/util" @@ -56,6 +57,9 @@ type AppStoreDeploymentFullModeService interface { AppStoreDeployOperationACD(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *util.ChartGitAttribute, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) RegisterInArgo(chartGitAttribute *util.ChartGitAttribute, ctx context.Context) error SyncACD(acdAppName string, ctx context.Context) + UpdateValuesYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) + UpdateRequirementYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, appStoreAppVersion *appStoreDiscoverRepository.AppStoreApplicationVersion) error + GetGitOpsRepoName(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) string } type AppStoreDeploymentFullModeServiceImpl struct { @@ -71,6 +75,8 @@ type AppStoreDeploymentFullModeServiceImpl struct { aCDAuthConfig *util2.ACDAuthConfig gitOpsRepository repository3.GitOpsConfigRepository globalEnvVariables *util3.GlobalEnvVariables + installedAppRepository repository4.InstalledAppRepository + tokenCache *util2.TokenCache } func NewAppStoreDeploymentFullModeServiceImpl(logger *zap.SugaredLogger, @@ -81,7 +87,8 @@ func NewAppStoreDeploymentFullModeServiceImpl(logger *zap.SugaredLogger, acdClient application2.ServiceClient, argoK8sClient argocdServer.ArgoK8sClient, gitFactory *util.GitFactory, aCDAuthConfig *util2.ACDAuthConfig, - gitOpsRepository repository3.GitOpsConfigRepository, globalEnvVariables *util3.GlobalEnvVariables) *AppStoreDeploymentFullModeServiceImpl { + gitOpsRepository repository3.GitOpsConfigRepository, globalEnvVariables *util3.GlobalEnvVariables, + installedAppRepository repository4.InstalledAppRepository, tokenCache *util2.TokenCache) *AppStoreDeploymentFullModeServiceImpl { return &AppStoreDeploymentFullModeServiceImpl{ logger: logger, chartTemplateService: chartTemplateService, @@ -95,6 +102,8 @@ func NewAppStoreDeploymentFullModeServiceImpl(logger *zap.SugaredLogger, aCDAuthConfig: aCDAuthConfig, gitOpsRepository: gitOpsRepository, globalEnvVariables: globalEnvVariables, + installedAppRepository: installedAppRepository, + tokenCache: tokenCache, } } @@ -210,7 +219,7 @@ func (impl AppStoreDeploymentFullModeServiceImpl) AppStoreDeployOperationGIT(ins ChartRepoName: gitOpsRepoName, ReleaseMessage: fmt.Sprintf("release-%d-env-%d ", appStoreAppVersion.Id, environment.Id), } - _, err = impl.gitFactory.Client.CommitValues(valuesYamlConfig, gitOpsConfigBitbucket.BitBucketWorkspaceId) + commitHash, err := impl.gitFactory.Client.CommitValues(valuesYamlConfig, gitOpsConfigBitbucket.BitBucketWorkspaceId) if err != nil { impl.logger.Errorw("error in git commit", "err", err) return nil, nil, err @@ -221,6 +230,7 @@ func (impl AppStoreDeploymentFullModeServiceImpl) AppStoreDeployOperationGIT(ins impl.logger.Errorw("error in git pull", "err", err) return nil, nil, err } + installAppVersionRequest.GitHash = commitHash installAppVersionRequest.ACDAppName = argocdAppName installAppVersionRequest.Environment = environment return installAppVersionRequest, chartGitAttr, nil @@ -296,3 +306,118 @@ func (impl AppStoreDeploymentFullModeServiceImpl) createInArgo(chartGitAttribute return nil } + +func (impl AppStoreDeploymentFullModeServiceImpl) GetGitOpsRepoName(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) string { + ctx, err := impl.tokenCache.BuildACDSynchContext() + if err != nil { + impl.logger.Errorw("error in creating acd synch context", "err", err) + return "" + } + acdAppName := fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, installAppVersionRequest.EnvironmentName) + gitOpsRepoName := "" + application, err := impl.acdClient.Get(ctx, &application.ApplicationQuery{Name: &acdAppName}) + if err != nil { + impl.logger.Errorw("no argo app exists", "app", acdAppName) + return "" + } + if application != nil { + gitOpsRepoUrl := application.Spec.Source.RepoURL + gitOpsRepoName = impl.chartTemplateService.GetGitOpsRepoNameFromUrl(gitOpsRepoUrl) + } + return gitOpsRepoName +} + +func (impl AppStoreDeploymentFullModeServiceImpl) UpdateValuesYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) { + acdAppName := fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, installAppVersionRequest.EnvironmentName) + if len(installAppVersionRequest.GitOpsRepoName) == 0 { + gitOpsRepoName := impl.GetGitOpsRepoName(installAppVersionRequest) + installAppVersionRequest.GitOpsRepoName = gitOpsRepoName + } + valuesOverrideByte, err := yaml.YAMLToJSON([]byte(installAppVersionRequest.ValuesOverrideYaml)) + if err != nil { + impl.logger.Errorw("error in json patch", "err", err) + return installAppVersionRequest, err + } + var dat map[string]interface{} + err = json.Unmarshal(valuesOverrideByte, &dat) + if err != nil { + impl.logger.Errorw("error in unmarshal", "err", err) + return installAppVersionRequest, err + } + valuesMap := make(map[string]map[string]interface{}) + valuesMap[installAppVersionRequest.AppStoreName] = dat + valuesByte, err := json.Marshal(valuesMap) + if err != nil { + impl.logger.Errorw("error in marshaling", "err", err) + return installAppVersionRequest, err + } + valuesConfig := &util.ChartConfig{ + FileName: appStoreBean.VALUES_YAML_FILE, + FileContent: string(valuesByte), + ChartName: installAppVersionRequest.AppStoreName, + ChartLocation: acdAppName, + ChartRepoName: installAppVersionRequest.GitOpsRepoName, + ReleaseMessage: fmt.Sprintf("release-%d-env-%d ", installAppVersionRequest.AppStoreVersion, installAppVersionRequest.EnvironmentId), + } + gitOpsConfigBitbucket, err := impl.gitOpsRepository.GetGitOpsConfigByProvider(util.BITBUCKET_PROVIDER) + if err != nil { + if err == pg.ErrNoRows { + gitOpsConfigBitbucket.BitBucketWorkspaceId = "" + } else { + impl.logger.Errorw("error in fetching gitOps bitbucket config", "err", err) + return installAppVersionRequest, err + } + } + commitHash, err := impl.gitFactory.Client.CommitValues(valuesConfig, gitOpsConfigBitbucket.BitBucketWorkspaceId) + if err != nil { + impl.logger.Errorw("error in git commit", "err", err) + return installAppVersionRequest, err + } + installAppVersionRequest.GitHash = commitHash + return installAppVersionRequest, nil +} + +func (impl AppStoreDeploymentFullModeServiceImpl) UpdateRequirementYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, appStoreAppVersion *appStoreDiscoverRepository.AppStoreApplicationVersion) error { + acdAppName := fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, installAppVersionRequest.EnvironmentName) + dependency := appStoreBean.Dependency{ + Name: appStoreAppVersion.AppStore.Name, + Version: appStoreAppVersion.Version, + Repository: appStoreAppVersion.AppStore.ChartRepo.Url, + } + var dependencies []appStoreBean.Dependency + dependencies = append(dependencies, dependency) + requirementDependencies := &appStoreBean.Dependencies{ + Dependencies: dependencies, + } + requirementDependenciesByte, err := json.Marshal(requirementDependencies) + if err != nil { + return err + } + requirementDependenciesByte, err = yaml.JSONToYAML(requirementDependenciesByte) + if err != nil { + return err + } + requirmentYamlConfig := &util.ChartConfig{ + FileName: appStoreBean.REQUIREMENTS_YAML_FILE, + FileContent: string(requirementDependenciesByte), + ChartName: appStoreAppVersion.AppStore.Name, + ChartLocation: acdAppName, + ChartRepoName: installAppVersionRequest.GitOpsRepoName, + ReleaseMessage: fmt.Sprintf("release-%d-env-%d ", appStoreAppVersion.Id, installAppVersionRequest.EnvironmentId), + } + gitOpsConfigBitbucket, err := impl.gitOpsRepository.GetGitOpsConfigByProvider(util.BITBUCKET_PROVIDER) + if err != nil { + if err == pg.ErrNoRows { + gitOpsConfigBitbucket.BitBucketWorkspaceId = "" + } else { + impl.logger.Errorw("error in fetching gitOps bitbucket config", "err", err) + return err + } + } + _, err = impl.gitFactory.Client.CommitValues(requirmentYamlConfig, gitOpsConfigBitbucket.BitBucketWorkspaceId) + if err != nil { + impl.logger.Errorw("error in git commit", "err", err) + return err + } + return nil +} diff --git a/pkg/appStore/repository/ChartGroup.go b/pkg/appStore/deployment/repository/ChartGroup.go similarity index 99% rename from pkg/appStore/repository/ChartGroup.go rename to pkg/appStore/deployment/repository/ChartGroup.go index 802c7ac09d..057b252fac 100644 --- a/pkg/appStore/repository/ChartGroup.go +++ b/pkg/appStore/deployment/repository/ChartGroup.go @@ -15,7 +15,7 @@ * */ -package appStoreRepository +package repository import ( "github.com/devtron-labs/devtron/pkg/sql" diff --git a/pkg/appStore/repository/ChartGroupDeployment.go b/pkg/appStore/deployment/repository/ChartGroupDeployment.go similarity index 99% rename from pkg/appStore/repository/ChartGroupDeployment.go rename to pkg/appStore/deployment/repository/ChartGroupDeployment.go index a3ad4c7b79..e54dfe9011 100644 --- a/pkg/appStore/repository/ChartGroupDeployment.go +++ b/pkg/appStore/deployment/repository/ChartGroupDeployment.go @@ -15,7 +15,7 @@ * */ -package appStoreRepository +package repository import ( "github.com/devtron-labs/devtron/pkg/sql" diff --git a/pkg/appStore/repository/ChartGroupEntry.go b/pkg/appStore/deployment/repository/ChartGroupEntry.go similarity index 99% rename from pkg/appStore/repository/ChartGroupEntry.go rename to pkg/appStore/deployment/repository/ChartGroupEntry.go index 6ef2c65142..de71ac0044 100644 --- a/pkg/appStore/repository/ChartGroupEntry.go +++ b/pkg/appStore/deployment/repository/ChartGroupEntry.go @@ -15,7 +15,7 @@ * */ -package appStoreRepository +package repository import ( appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" diff --git a/pkg/appStore/repository/ClusterInstalledAppsRepository.go b/pkg/appStore/deployment/repository/ClusterInstalledAppsRepository.go similarity index 99% rename from pkg/appStore/repository/ClusterInstalledAppsRepository.go rename to pkg/appStore/deployment/repository/ClusterInstalledAppsRepository.go index 4f1b3b2000..c8e5c7a7e1 100644 --- a/pkg/appStore/repository/ClusterInstalledAppsRepository.go +++ b/pkg/appStore/deployment/repository/ClusterInstalledAppsRepository.go @@ -15,7 +15,7 @@ * */ -package appStoreRepository +package repository import ( "github.com/devtron-labs/devtron/pkg/sql" diff --git a/pkg/appStore/repository/AppStoreDeploymentRepository.go b/pkg/appStore/deployment/repository/InstalledAppRepository.go similarity index 91% rename from pkg/appStore/repository/AppStoreDeploymentRepository.go rename to pkg/appStore/deployment/repository/InstalledAppRepository.go index cc0b9e7da4..bee6275edd 100644 --- a/pkg/appStore/repository/AppStoreDeploymentRepository.go +++ b/pkg/appStore/deployment/repository/InstalledAppRepository.go @@ -15,7 +15,7 @@ * */ -package appStoreRepository +package repository import ( "github.com/devtron-labs/devtron/internal/sql/repository/app" @@ -47,7 +47,9 @@ type InstalledAppRepository interface { DeleteInstalledAppVersion(model *InstalledAppVersions) (*InstalledAppVersions, error) GetInstalledAppVersionByInstalledAppId(id int) ([]*InstalledAppVersions, error) GetConnection() (dbConnection *pg.DB) - GetInstalledAppVersionByInstalledAppIdMeta(appStoreApplicationId int) ([]*InstalledAppVersions, error) + GetInstalledAppVersionByInstalledAppIdMeta(installedAppId int) ([]*InstalledAppVersions, error) + GetActiveInstalledAppVersionByInstalledAppId(installedAppId int) (*InstalledAppVersions, error) + GetLatestInstalledAppVersionByGitHash(gitHash string) (*InstalledAppVersions, error) GetClusterComponentByClusterId(clusterId int) ([]*InstalledApps, error) //unused GetClusterComponentByClusterIds(clusterIds []int) ([]*InstalledApps, error) //unused GetInstalledAppVersionByAppIdAndEnvId(appId int, envId int) (*InstalledAppVersions, error) @@ -152,7 +154,12 @@ func (impl InstalledAppRepositoryImpl) UpdateInstalledApp(model *InstalledApps, } func (impl InstalledAppRepositoryImpl) UpdateInstalledAppVersion(model *InstalledAppVersions, tx *pg.Tx) (*InstalledAppVersions, error) { - err := tx.Update(model) + var err error + if tx == nil { + err = impl.dbConnection.Update(model) + } else { + err = tx.Update(model) + } if err != nil { impl.Logger.Error(err) return model, err @@ -184,7 +191,28 @@ func (impl InstalledAppRepositoryImpl) GetInstalledAppVersionByInstalledAppIdMet Column("installed_app_versions.*", "InstalledApp", "InstalledApp.App", "InstalledApp.Environment", "AppStoreApplicationVersion", "AppStoreApplicationVersion.AppStore"). Column("AppStoreApplicationVersion.AppStore.ChartRepo"). Where("installed_app_versions.installed_app_id = ?", installedAppId). - Where("installed_app_versions.active = true").Select() + Order("installed_app_versions.id desc"). + Select() + return model, err +} + +func (impl InstalledAppRepositoryImpl) GetActiveInstalledAppVersionByInstalledAppId(installedAppId int) (*InstalledAppVersions, error) { + model := &InstalledAppVersions{} + err := impl.dbConnection.Model(model). + Column("installed_app_versions.*", "InstalledApp", "InstalledApp.App", "InstalledApp.Environment", "AppStoreApplicationVersion", "AppStoreApplicationVersion.AppStore"). + Column("AppStoreApplicationVersion.AppStore.ChartRepo"). + Where("installed_app_versions.installed_app_id = ?", installedAppId). + Where("installed_app_versions.active = true").Order("installed_app_versions.id desc").Limit(1).Select() + return model, err +} + +func (impl InstalledAppRepositoryImpl) GetLatestInstalledAppVersionByGitHash(gitHash string) (*InstalledAppVersions, error) { + model := &InstalledAppVersions{} + err := impl.dbConnection.Model(model). + Column("installed_app_versions.*", "InstalledApp"). + Column("AppStoreApplicationVersion.AppStore.ChartRepo"). + Where("installed_app_versions.git_hash = ?", gitHash). + Where("installed_app_versions.active = true").Order("installed_app_versions.id desc").Limit(1).Select() return model, err } @@ -197,6 +225,7 @@ func (impl InstalledAppRepositoryImpl) GetInstalledAppVersion(id int) (*Installe return model, err } +//it returns enable and disabled both version func (impl InstalledAppRepositoryImpl) GetInstalledAppVersionAny(id int) (*InstalledAppVersions, error) { model := &InstalledAppVersions{} err := impl.dbConnection.Model(model). @@ -333,11 +362,11 @@ func (impl InstalledAppRepositoryImpl) DeleteInstalledAppVersion(model *Installe return model, nil } -func (impl InstalledAppRepositoryImpl) GetInstalledAppVersionByInstalledAppId(id int) ([]*InstalledAppVersions, error) { +func (impl InstalledAppRepositoryImpl) GetInstalledAppVersionByInstalledAppId(installedAppId int) ([]*InstalledAppVersions, error) { model := make([]*InstalledAppVersions, 0) err := impl.dbConnection.Model(&model). Column("installed_app_versions.*"). - Where("installed_app_versions.installed_app_id = ?", id). + Where("installed_app_versions.installed_app_id = ?", installedAppId). Where("installed_app_versions.active = true").Select() return model, err diff --git a/pkg/appStore/deployment/repository/InstalledAppVersionHistory.go b/pkg/appStore/deployment/repository/InstalledAppVersionHistory.go new file mode 100644 index 0000000000..15345058d4 --- /dev/null +++ b/pkg/appStore/deployment/repository/InstalledAppVersionHistory.go @@ -0,0 +1,88 @@ +package repository + +import ( + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.uber.org/zap" +) + +type InstalledAppVersionHistoryRepository interface { + CreateInstalledAppVersionHistory(model *InstalledAppVersionHistory, tx *pg.Tx) (*InstalledAppVersionHistory, error) + UpdateInstalledAppVersionHistory(model *InstalledAppVersionHistory, tx *pg.Tx) (*InstalledAppVersionHistory, error) + GetInstalledAppVersionHistory(id int) (*InstalledAppVersionHistory, error) + GetInstalledAppVersionHistoryByVersionId(installAppVersionId int) ([]*InstalledAppVersionHistory, error) + GetLatestInstalledAppVersionHistory(installAppVersionId int) (*InstalledAppVersionHistory, error) + GetLatestInstalledAppVersionHistoryByGitHash(gitHash string) (*InstalledAppVersionHistory, error) +} + +type InstalledAppVersionHistoryRepositoryImpl struct { + dbConnection *pg.DB + Logger *zap.SugaredLogger +} + +func NewInstalledAppVersionHistoryRepositoryImpl(Logger *zap.SugaredLogger, dbConnection *pg.DB) *InstalledAppVersionHistoryRepositoryImpl { + return &InstalledAppVersionHistoryRepositoryImpl{dbConnection: dbConnection, Logger: Logger} +} + +type InstalledAppVersionHistory struct { + TableName struct{} `sql:"installed_app_version_history" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + InstalledAppVersionId int `sql:"installed_app_version_id,notnull"` + ValuesYamlRaw string `sql:"values_yaml_raw"` + Status string `sql:"status"` + GitHash string `sql:"git_hash"` + sql.AuditLog +} + +func (impl InstalledAppVersionHistoryRepositoryImpl) CreateInstalledAppVersionHistory(model *InstalledAppVersionHistory, tx *pg.Tx) (*InstalledAppVersionHistory, error) { + err := tx.Insert(model) + if err != nil { + impl.Logger.Error(err) + return model, err + } + return model, nil +} +func (impl InstalledAppVersionHistoryRepositoryImpl) UpdateInstalledAppVersionHistory(model *InstalledAppVersionHistory, tx *pg.Tx) (*InstalledAppVersionHistory, error) { + err := tx.Update(model) + if err != nil { + impl.Logger.Error(err) + return model, err + } + return model, nil +} +func (impl InstalledAppVersionHistoryRepositoryImpl) GetInstalledAppVersionHistory(id int) (*InstalledAppVersionHistory, error) { + model := &InstalledAppVersionHistory{} + err := impl.dbConnection.Model(model). + Column("installed_app_version_history.*"). + Where("installed_app_version_history.id = ?", id).Select() + return model, err +} +func (impl InstalledAppVersionHistoryRepositoryImpl) GetInstalledAppVersionHistoryByVersionId(installAppVersionId int) ([]*InstalledAppVersionHistory, error) { + var model []*InstalledAppVersionHistory + err := impl.dbConnection.Model(&model). + Column("installed_app_version_history.*"). + Where("installed_app_version_history.installed_app_version_id = ?", installAppVersionId). + Order("installed_app_version_history.id desc"). + Select() + return model, err +} + +func (impl InstalledAppVersionHistoryRepositoryImpl) GetLatestInstalledAppVersionHistory(installAppVersionId int) (*InstalledAppVersionHistory, error) { + model := &InstalledAppVersionHistory{} + err := impl.dbConnection.Model(model). + Column("installed_app_version_history.*"). + Where("installed_app_version_history.installed_app_version_id = ?", installAppVersionId). + Order("installed_app_version_history.id desc").Limit(1). + Select() + return model, err +} + +func (impl InstalledAppVersionHistoryRepositoryImpl) GetLatestInstalledAppVersionHistoryByGitHash(gitHash string) (*InstalledAppVersionHistory, error) { + model := &InstalledAppVersionHistory{} + err := impl.dbConnection.Model(model). + Column("installed_app_version_history.*"). + Where("installed_app_version_history.git_hash = ?", gitHash). + Order("installed_app_version_history.id desc").Limit(1). + Select() + return model, err +} diff --git a/pkg/appStore/deployment/AppStoreDeploymentService.go b/pkg/appStore/deployment/service/AppStoreDeploymentService.go similarity index 56% rename from pkg/appStore/deployment/AppStoreDeploymentService.go rename to pkg/appStore/deployment/service/AppStoreDeploymentService.go index 8c2f522f97..7d3a72b248 100644 --- a/pkg/appStore/deployment/AppStoreDeploymentService.go +++ b/pkg/appStore/deployment/service/AppStoreDeploymentService.go @@ -15,19 +15,24 @@ * */ -package appStoreDeployment +package service import ( "context" + "errors" "fmt" + client "github.com/devtron-labs/devtron/api/helm-app" + openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" + openapi2 "github.com/devtron-labs/devtron/api/openapi/openapiClient" "github.com/devtron-labs/devtron/internal/constants" "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDeploymentTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" appStoreDeploymentGitopsTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool/gitops" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" "github.com/devtron-labs/devtron/pkg/bean" "github.com/devtron-labs/devtron/pkg/cluster" cluster2 "github.com/devtron-labs/devtron/pkg/cluster" @@ -48,28 +53,38 @@ type AppStoreDeploymentService interface { GetInstalledApp(id int) (*appStoreBean.InstallAppVersionDTO, error) GetAllInstalledAppsByAppStoreId(w http.ResponseWriter, r *http.Request, token string, appStoreId int) ([]appStoreBean.InstalledAppsResponse, error) DeleteInstalledApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) + LinkHelmApplicationToChartStore(ctx context.Context, request *openapi.UpdateReleaseWithChartLinkingRequest, appIdentifier *client.AppIdentifier, userId int32) (*openapi.UpdateReleaseResponse, bool, error) + RollbackApplication(ctx context.Context, request *openapi2.RollbackReleaseRequest, installedApp *appStoreBean.InstallAppVersionDTO, userId int32) (bool, error) + UpdateInstallAppVersionHistory(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error + GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.DeploymentHistoryAndInstalledAppInfo, error) + GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, installedAppVersionHistoryId int) (*openapi.HelmAppDeploymentManifestDetail, error) } type AppStoreDeploymentServiceImpl struct { logger *zap.SugaredLogger - installedAppRepository appStoreRepository.InstalledAppRepository + installedAppRepository repository.InstalledAppRepository appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository environmentRepository clusterRepository.EnvironmentRepository - clusterInstalledAppsRepository appStoreRepository.ClusterInstalledAppsRepository + clusterInstalledAppsRepository repository.ClusterInstalledAppsRepository appRepository app.AppRepository appStoreDeploymentHelmService appStoreDeploymentTool.AppStoreDeploymentHelmService appStoreDeploymentArgoCdService appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdService environmentService cluster.EnvironmentService clusterService cluster.ClusterService + helmAppService client.HelmAppService + appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService globalEnvVariables *util2.GlobalEnvVariables + installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository } -func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRepository appStoreRepository.InstalledAppRepository, +func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRepository repository.InstalledAppRepository, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, environmentRepository clusterRepository.EnvironmentRepository, - clusterInstalledAppsRepository appStoreRepository.ClusterInstalledAppsRepository, appRepository app.AppRepository, + clusterInstalledAppsRepository repository.ClusterInstalledAppsRepository, appRepository app.AppRepository, appStoreDeploymentHelmService appStoreDeploymentTool.AppStoreDeploymentHelmService, appStoreDeploymentArgoCdService appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdService, environmentService cluster.EnvironmentService, - clusterService cluster.ClusterService, globalEnvVariables *util2.GlobalEnvVariables) *AppStoreDeploymentServiceImpl { + clusterService cluster.ClusterService, helmAppService client.HelmAppService, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, + globalEnvVariables *util2.GlobalEnvVariables, + installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository) *AppStoreDeploymentServiceImpl { return &AppStoreDeploymentServiceImpl{ logger: logger, installedAppRepository: installedAppRepository, @@ -81,20 +96,29 @@ func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRep appStoreDeploymentArgoCdService: appStoreDeploymentArgoCdService, environmentService: environmentService, clusterService: clusterService, + helmAppService: helmAppService, + appStoreDeploymentCommonService: appStoreDeploymentCommonService, globalEnvVariables: globalEnvVariables, + installedAppRepositoryHistory: installedAppRepositoryHistory, } } func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationDB(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { - appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) if err != nil { impl.logger.Errorw("fetching error", "err", err) return nil, err } + var appInstallationMode string + if util2.GetDevtronVersion().ServerMode == util2.SERVER_MODE_HYPERION || installAppVersionRequest.AppOfferingMode == util2.SERVER_MODE_HYPERION { + appInstallationMode = util2.SERVER_MODE_HYPERION + } else { + appInstallationMode = util2.SERVER_MODE_FULL + } + // create env if env not exists for clusterId and namespace for hyperion mode - if util2.GetDevtronVersion().ServerMode == util2.SERVER_MODE_HYPERION { + if appInstallationMode == util2.SERVER_MODE_HYPERION { envId, err := impl.createEnvironmentIfNotExists(installAppVersionRequest) if err != nil { return nil, err @@ -115,14 +139,14 @@ func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationDB(installAppVe UserId: installAppVersionRequest.UserId, } - appCreateRequest, err = impl.createAppForAppStore(appCreateRequest, tx) + appCreateRequest, err = impl.createAppForAppStore(appCreateRequest, tx, appInstallationMode) if err != nil { impl.logger.Errorw("error while creating app", "error", err) return nil, err } installAppVersionRequest.AppId = appCreateRequest.Id - installedAppModel := &appStoreRepository.InstalledApps{ + installedAppModel := &repository.InstalledApps{ AppId: appCreateRequest.Id, EnvironmentId: environment.Id, Status: appStoreBean.DEPLOY_INIT, @@ -143,7 +167,7 @@ func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationDB(installAppVe } installAppVersionRequest.InstalledAppId = installedApp.Id - installedAppVersions := &appStoreRepository.InstalledAppVersions{ + installedAppVersions := &repository.InstalledAppVersions{ InstalledAppId: installAppVersionRequest.InstalledAppId, AppStoreApplicationVersionId: appStoreAppVersion.Id, ValuesYaml: installAppVersionRequest.ValuesOverrideYaml, @@ -162,9 +186,9 @@ func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationDB(installAppVe return nil, err } installAppVersionRequest.InstalledAppVersionId = installedAppVersions.Id - + installAppVersionRequest.Id = installedAppVersions.Id if installAppVersionRequest.DefaultClusterComponent { - clusterInstalledAppsModel := &appStoreRepository.ClusterInstalledApps{ + clusterInstalledAppsModel := &repository.ClusterInstalledApps{ ClusterId: environment.ClusterId, InstalledAppId: installAppVersionRequest.InstalledAppId, } @@ -245,10 +269,10 @@ func (impl AppStoreDeploymentServiceImpl) InstallApp(installAppVersionRequest *a return nil, err } - if util2.GetDevtronVersion().ServerMode == util2.SERVER_MODE_HYPERION { - err = impl.appStoreDeploymentHelmService.InstallApp(installAppVersionRequest, ctx) + if util2.GetDevtronVersion().ServerMode == util2.SERVER_MODE_HYPERION || installAppVersionRequest.AppOfferingMode == util2.SERVER_MODE_HYPERION { + _, err = impl.appStoreDeploymentHelmService.InstallApp(installAppVersionRequest, ctx) } else { - err = impl.appStoreDeploymentArgoCdService.InstallApp(installAppVersionRequest, ctx) + installAppVersionRequest, err = impl.appStoreDeploymentArgoCdService.InstallApp(installAppVersionRequest, ctx) } if err != nil { @@ -261,17 +285,45 @@ func (impl AppStoreDeploymentServiceImpl) InstallApp(installAppVersionRequest *a return nil, err } - //step 4 db operation status update to deploy success - _, err = impl.AppStoreDeployOperationStatusUpdate(installAppVersionRequest.InstalledAppId, appStoreBean.DEPLOY_SUCCESS) + err = impl.installAppPostDbOperation(installAppVersionRequest) if err != nil { - impl.logger.Errorw(" error", "err", err) return nil, err } return installAppVersionRequest, nil } +func (impl AppStoreDeploymentServiceImpl) UpdateInstallAppVersionHistory(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error { + dbConnection := impl.installedAppRepository.GetConnection() + tx, err := dbConnection.Begin() + if err != nil { + return err + } + // Rollback tx on error. + defer tx.Rollback() + installedAppVersionHistory := &repository.InstalledAppVersionHistory{ + InstalledAppVersionId: installAppVersionRequest.Id, + } + installedAppVersionHistory.ValuesYamlRaw = installAppVersionRequest.ValuesOverrideYaml + installedAppVersionHistory.CreatedBy = installAppVersionRequest.UserId + installedAppVersionHistory.CreatedOn = time.Now() + installedAppVersionHistory.UpdatedBy = installAppVersionRequest.UserId + installedAppVersionHistory.UpdatedOn = time.Now() + installedAppVersionHistory.GitHash = installAppVersionRequest.GitHash + installedAppVersionHistory.Status = "Unknown" + _, err = impl.installedAppRepositoryHistory.CreateInstalledAppVersionHistory(installedAppVersionHistory, tx) + if err != nil { + impl.logger.Errorw("error while fetching from db", "error", err) + return err + } + err = tx.Commit() + if err != nil { + impl.logger.Errorw("error while committing transaction to db", "error", err) + return err + } + return nil +} -func (impl AppStoreDeploymentServiceImpl) createAppForAppStore(createRequest *bean.CreateAppDTO, tx *pg.Tx) (*bean.CreateAppDTO, error) { +func (impl AppStoreDeploymentServiceImpl) createAppForAppStore(createRequest *bean.CreateAppDTO, tx *pg.Tx, appInstallationMode string) (*bean.CreateAppDTO, error) { app1, err := impl.appRepository.FindActiveByName(createRequest.AppName) if err != nil && err != pg.ErrNoRows { return nil, err @@ -290,7 +342,7 @@ func (impl AppStoreDeploymentServiceImpl) createAppForAppStore(createRequest *be AppName: createRequest.AppName, TeamId: createRequest.TeamId, AppStore: true, - AppOfferingMode: util2.GetDevtronVersion().ServerMode, + AppOfferingMode: appInstallationMode, AuditLog: sql.AuditLog{UpdatedBy: createRequest.UserId, CreatedBy: createRequest.UserId, UpdatedOn: time.Now(), CreatedOn: time.Now()}, } err = impl.appRepository.SaveWithTxn(pg, tx) @@ -328,7 +380,6 @@ func (impl AppStoreDeploymentServiceImpl) createAppForAppStore(createRequest *be } func (impl AppStoreDeploymentServiceImpl) GetInstalledApp(id int) (*appStoreBean.InstallAppVersionDTO, error) { - app, err := impl.installedAppRepository.GetInstalledApp(id) if err != nil { impl.logger.Errorw("error while fetching from db", "error", err) @@ -339,10 +390,10 @@ func (impl AppStoreDeploymentServiceImpl) GetInstalledApp(id int) (*appStoreBean } //converts db object to bean -func (impl AppStoreDeploymentServiceImpl) chartAdaptor2(chart *appStoreRepository.InstalledApps) *appStoreBean.InstallAppVersionDTO { +func (impl AppStoreDeploymentServiceImpl) chartAdaptor2(chart *repository.InstalledApps) *appStoreBean.InstallAppVersionDTO { return &appStoreBean.InstallAppVersionDTO{ EnvironmentId: chart.EnvironmentId, - Id: chart.Id, + InstalledAppId: chart.Id, AppId: chart.AppId, AppOfferingMode: chart.App.AppOfferingMode, ClusterId: chart.Environment.ClusterId, @@ -462,6 +513,9 @@ func (impl AppStoreDeploymentServiceImpl) DeleteInstalledApp(ctx context.Context } if util2.GetDevtronVersion().ServerMode == util2.SERVER_MODE_HYPERION || app.AppOfferingMode == util2.SERVER_MODE_HYPERION { + // there might be a case if helm release gets uninstalled from helm cli. + //in this case on deleting the app from API, it should not give error as it should get deleted from db, otherwise due to delete error, db does not get clean + // so in helm, we need to check first if the release exists or not, if exists then only delete err = impl.appStoreDeploymentHelmService.DeleteInstalledApp(ctx, app.AppName, environment.Name, installAppVersionRequest, model, tx) } else { err = impl.appStoreDeploymentArgoCdService.DeleteInstalledApp(ctx, app.AppName, environment.Name, installAppVersionRequest, model, tx) @@ -470,7 +524,6 @@ func (impl AppStoreDeploymentServiceImpl) DeleteInstalledApp(ctx context.Context if err != nil { return nil, err } - err = tx.Commit() if err != nil { impl.logger.Errorw("error in commit db transaction on delete", "err", err) @@ -480,6 +533,58 @@ func (impl AppStoreDeploymentServiceImpl) DeleteInstalledApp(ctx context.Context return installAppVersionRequest, nil } +func (impl AppStoreDeploymentServiceImpl) LinkHelmApplicationToChartStore(ctx context.Context, request *openapi.UpdateReleaseWithChartLinkingRequest, + appIdentifier *client.AppIdentifier, userId int32) (*openapi.UpdateReleaseResponse, bool, error) { + + impl.logger.Infow("Linking helm application to chart store", "appId", request.GetAppId()) + + // check if chart repo is active starts + isChartRepoActive, err := impl.IsChartRepoActive(int(request.GetAppStoreApplicationVersionId())) + if err != nil { + impl.logger.Errorw("Error in checking if chart repo is active or not", "err", err) + return nil, isChartRepoActive, err + } + if !isChartRepoActive { + return nil, isChartRepoActive, nil + } + // check if chart repo is active ends + + // STEP-1 check if the app is installed or not + isInstalled, err := impl.helmAppService.IsReleaseInstalled(ctx, appIdentifier) + if err != nil { + impl.logger.Errorw("error while checking if the release is installed", "error", err) + return nil, isChartRepoActive, err + } + if !isInstalled { + return nil, isChartRepoActive, errors.New("release is not installed. so can not be updated") + } + // STEP-1 ends + + // Initialise bean + installAppVersionRequestDto := &appStoreBean.InstallAppVersionDTO{ + AppName: appIdentifier.ReleaseName, + UserId: userId, + AppOfferingMode: util2.SERVER_MODE_HYPERION, + ClusterId: appIdentifier.ClusterId, + Namespace: appIdentifier.Namespace, + AppStoreVersion: int(request.GetAppStoreApplicationVersionId()), + ValuesOverrideYaml: request.GetValuesYaml(), + ReferenceValueId: int(request.GetReferenceValueId()), + ReferenceValueKind: request.GetReferenceValueKind(), + } + + // STEP-2 InstallApp with only DB operations + // STEP-3 update APP with chart info + res, err := impl.linkHelmApplicationToChartStore(installAppVersionRequestDto, ctx) + if err != nil { + impl.logger.Errorw("error while linking helm app with chart store", "error", err) + return nil, isChartRepoActive, err + } + // STEP-2 and STEP-3 ends + + return res, isChartRepoActive, nil +} + func (impl AppStoreDeploymentServiceImpl) createEnvironmentIfNotExists(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (int, error) { clusterId := installAppVersionRequest.ClusterId namespace := installAppVersionRequest.Namespace @@ -513,3 +618,205 @@ func (impl AppStoreDeploymentServiceImpl) createEnvironmentIfNotExists(installAp return envCreateRes.Id, nil } + +func (impl AppStoreDeploymentServiceImpl) RollbackApplication(ctx context.Context, request *openapi2.RollbackReleaseRequest, + installedApp *appStoreBean.InstallAppVersionDTO, userId int32) (bool, error) { + dbConnection := impl.installedAppRepository.GetConnection() + tx, err := dbConnection.Begin() + if err != nil { + return false, err + } + // Rollback tx on error. + defer tx.Rollback() + + // Rollback starts + var success bool + if installedApp.AppOfferingMode == util2.SERVER_MODE_HYPERION { + installedApp, success, err = impl.appStoreDeploymentHelmService.RollbackRelease(ctx, installedApp, request.GetVersion()) + if err != nil { + impl.logger.Errorw("error while rollback helm release", "error", err) + return false, err + } + } else { + installedApp, success, err = impl.appStoreDeploymentArgoCdService.RollbackRelease(ctx, installedApp, request.GetVersion()) + if err != nil { + impl.logger.Errorw("error while rollback helm release", "error", err) + return false, err + } + } + if !success { + return false, fmt.Errorf("rollback request failed") + } + //DB operation + if installedApp.InstalledAppId > 0 && installedApp.InstalledAppVersionId > 0 { + installedAppVersion, err := impl.installedAppRepository.GetInstalledAppVersionAny(installedApp.InstalledAppVersionId) + if err != nil { + impl.logger.Errorw("error while fetching chart installed version", "error", err) + return false, err + } + installedApp.Id = installedAppVersion.Id + installedAppVersion.Active = true + installedAppVersion.ValuesYaml = installedApp.ValuesOverrideYaml + installedAppVersion.UpdatedOn = time.Now() + installedAppVersion.UpdatedBy = userId + _, err = impl.installedAppRepository.UpdateInstalledAppVersion(installedAppVersion, tx) + if err != nil { + impl.logger.Errorw("error while updating db", "error", err) + return false, err + } + } + //STEP 8: finish with return response + err = tx.Commit() + if err != nil { + impl.logger.Errorw("error while committing transaction to db", "error", err) + return false, err + } + + if installedApp.AppOfferingMode == util2.SERVER_MODE_FULL { + // create build history for version upgrade, chart upgrade or simple update + err = impl.UpdateInstallAppVersionHistory(installedApp) + if err != nil { + impl.logger.Errorw("error on creating history for chart deployment", "error", err) + return false, err + } + } + return success, nil +} + +func (impl AppStoreDeploymentServiceImpl) linkHelmApplicationToChartStore(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*openapi.UpdateReleaseResponse, error) { + dbConnection := impl.installedAppRepository.GetConnection() + tx, err := dbConnection.Begin() + if err != nil { + return nil, err + } + // Rollback tx on error. + defer tx.Rollback() + + //step 1 db operation initiated + installAppVersionRequest, err = impl.AppStoreDeployOperationDB(installAppVersionRequest, tx) + if err != nil { + impl.logger.Errorw(" error", "err", err) + return nil, err + } + + // fetch app store application version from DB + appStoreApplicationVersionId := installAppVersionRequest.AppStoreVersion + appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(appStoreApplicationVersionId) + if err != nil { + impl.logger.Errorw("Error in fetching app store application version", "err", err, "appStoreApplicationVersionId", appStoreApplicationVersionId) + return nil, err + } + + // STEP-2 update APP with chart info + chartRepoInfo := appStoreAppVersion.AppStore.ChartRepo + updateReleaseRequest := &client.InstallReleaseRequest{ + ValuesYaml: installAppVersionRequest.ValuesOverrideYaml, + ChartName: appStoreAppVersion.Name, + ChartVersion: appStoreAppVersion.Version, + ReleaseIdentifier: &client.ReleaseIdentifier{ + ReleaseNamespace: installAppVersionRequest.Namespace, + ReleaseName: installAppVersionRequest.AppName, + }, + ChartRepository: &client.ChartRepository{ + Name: chartRepoInfo.Name, + Url: chartRepoInfo.Url, + Username: chartRepoInfo.UserName, + Password: chartRepoInfo.Password, + }, + } + res, err := impl.helmAppService.UpdateApplicationWithChartInfo(ctx, installAppVersionRequest.ClusterId, updateReleaseRequest) + if err != nil { + return nil, err + } + // STEP-2 ends + + // tx commit here because next operation will be process after this commit. + err = tx.Commit() + if err != nil { + return nil, err + } + + // STEP-3 install app DB post operations + err = impl.installAppPostDbOperation(installAppVersionRequest) + if err != nil { + return nil, err + } + // STEP-3 ends + + return res, nil +} + +func (impl AppStoreDeploymentServiceImpl) installAppPostDbOperation(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error { + //step 4 db operation status update to deploy success + _, err := impl.AppStoreDeployOperationStatusUpdate(installAppVersionRequest.InstalledAppId, appStoreBean.DEPLOY_SUCCESS) + if err != nil { + impl.logger.Errorw(" error", "err", err) + return err + } + + //step 5 create build history first entry for install app version + if len(installAppVersionRequest.GitHash) > 0 { + err = impl.UpdateInstallAppVersionHistory(installAppVersionRequest) + if err != nil { + impl.logger.Errorw("error on creating history for chart deployment", "error", err) + return err + } + } + + return nil +} + +func (impl AppStoreDeploymentServiceImpl) GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.DeploymentHistoryAndInstalledAppInfo, error) { + result := &client.DeploymentHistoryAndInstalledAppInfo{} + var err error + if installedApp.AppOfferingMode == util2.SERVER_MODE_HYPERION { + deploymentHistory, err := impl.appStoreDeploymentHelmService.GetDeploymentHistory(ctx, installedApp) + if err != nil { + impl.logger.Errorw("error while getting deployment history", "error", err) + return nil, err + } + result.DeploymentHistory = deploymentHistory.GetDeploymentHistory() + } else { + deploymentHistory, err := impl.appStoreDeploymentArgoCdService.GetDeploymentHistory(ctx, installedApp) + if err != nil { + impl.logger.Errorw("error while getting deployment history", "error", err) + return nil, err + } + result.DeploymentHistory = deploymentHistory.GetDeploymentHistory() + } + + if installedApp.InstalledAppId > 0 { + result.InstalledAppInfo = &client.InstalledAppInfo{ + AppId: installedApp.AppId, + EnvironmentName: installedApp.EnvironmentName, + AppOfferingMode: installedApp.AppOfferingMode, + InstalledAppId: installedApp.InstalledAppId, + InstalledAppVersionId: installedApp.InstalledAppVersionId, + AppStoreChartId: installedApp.InstallAppVersionChartDTO.AppStoreChartId, + ClusterId: installedApp.ClusterId, + EnvironmentId: installedApp.EnvironmentId, + } + } + + return result, err +} + +func (impl AppStoreDeploymentServiceImpl) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int) (*openapi.HelmAppDeploymentManifestDetail, error) { + //var result interface{} + result := &openapi.HelmAppDeploymentManifestDetail{} + var err error + if installedApp.AppOfferingMode == util2.SERVER_MODE_HYPERION { + result, err = impl.appStoreDeploymentHelmService.GetDeploymentHistoryInfo(ctx, installedApp, int32(version)) + if err != nil { + impl.logger.Errorw("error while getting deployment history info", "error", err) + return nil, err + } + } else { + result, err = impl.appStoreDeploymentArgoCdService.GetDeploymentHistoryInfo(ctx, installedApp, int32(version)) + if err != nil { + impl.logger.Errorw("error while getting deployment history info", "error", err) + return nil, err + } + } + return result, err +} diff --git a/pkg/appStore/ChartGroupService.go b/pkg/appStore/deployment/service/ChartGroupService.go similarity index 92% rename from pkg/appStore/ChartGroupService.go rename to pkg/appStore/deployment/service/ChartGroupService.go index 11a6a580db..4e0fac4075 100644 --- a/pkg/appStore/ChartGroupService.go +++ b/pkg/appStore/deployment/service/ChartGroupService.go @@ -15,11 +15,11 @@ * */ -package appStore +package service import ( appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreValuesRepository "github.com/devtron-labs/devtron/pkg/appStore/values/repository" "github.com/devtron-labs/devtron/pkg/sql" "github.com/devtron-labs/devtron/pkg/user" @@ -30,19 +30,19 @@ import ( ) type ChartGroupServiceImpl struct { - chartGroupEntriesRepository appStoreRepository.ChartGroupEntriesRepository - chartGroupRepository appStoreRepository.ChartGroupReposotory + chartGroupEntriesRepository repository.ChartGroupEntriesRepository + chartGroupRepository repository.ChartGroupReposotory Logger *zap.SugaredLogger - chartGroupDeploymentRepository appStoreRepository.ChartGroupDeploymentRepository - installedAppRepository appStoreRepository.InstalledAppRepository + chartGroupDeploymentRepository repository.ChartGroupDeploymentRepository + installedAppRepository repository.InstalledAppRepository appStoreVersionValuesRepository appStoreValuesRepository.AppStoreVersionValuesRepository userAuthService user.UserAuthService } -func NewChartGroupServiceImpl(chartGroupEntriesRepository appStoreRepository.ChartGroupEntriesRepository, - chartGroupRepository appStoreRepository.ChartGroupReposotory, - Logger *zap.SugaredLogger, chartGroupDeploymentRepository appStoreRepository.ChartGroupDeploymentRepository, - installedAppRepository appStoreRepository.InstalledAppRepository, appStoreVersionValuesRepository appStoreValuesRepository.AppStoreVersionValuesRepository, userAuthService user.UserAuthService) *ChartGroupServiceImpl { +func NewChartGroupServiceImpl(chartGroupEntriesRepository repository.ChartGroupEntriesRepository, + chartGroupRepository repository.ChartGroupReposotory, + Logger *zap.SugaredLogger, chartGroupDeploymentRepository repository.ChartGroupDeploymentRepository, + installedAppRepository repository.InstalledAppRepository, appStoreVersionValuesRepository appStoreValuesRepository.AppStoreVersionValuesRepository, userAuthService user.UserAuthService) *ChartGroupServiceImpl { return &ChartGroupServiceImpl{ chartGroupEntriesRepository: chartGroupEntriesRepository, chartGroupRepository: chartGroupRepository, @@ -110,7 +110,7 @@ type InstalledChart struct { func (impl *ChartGroupServiceImpl) CreateChartGroup(req *ChartGroupBean) (*ChartGroupBean, error) { impl.Logger.Debugw("chart group create request", "req", req) - chartGrouModel := &appStoreRepository.ChartGroup{ + chartGrouModel := &repository.ChartGroup{ Name: req.Name, Description: req.Description, AuditLog: sql.AuditLog{ @@ -131,7 +131,7 @@ func (impl *ChartGroupServiceImpl) CreateChartGroup(req *ChartGroupBean) (*Chart func (impl *ChartGroupServiceImpl) UpdateChartGroup(req *ChartGroupBean) (*ChartGroupBean, error) { impl.Logger.Debugw("chart group update request", "req", req) - chartGrouModel := &appStoreRepository.ChartGroup{ + chartGrouModel := &repository.ChartGroup{ Name: req.Name, Description: req.Description, Id: req.Id, @@ -167,7 +167,7 @@ func (impl *ChartGroupServiceImpl) SaveChartGroupEntries(req *ChartGroupBean) (* newEntries = append(newEntries, entryBean) } } - var updateEntries []*appStoreRepository.ChartGroupEntry + var updateEntries []*repository.ChartGroupEntry for _, existingEntry := range group.ChartGroupEntries { if entry, ok := oldEntriesMap[existingEntry.Id]; ok { //update @@ -182,9 +182,9 @@ func (impl *ChartGroupServiceImpl) SaveChartGroupEntries(req *ChartGroupBean) (* updateEntries = append(updateEntries, existingEntry) } - var createEntries []*appStoreRepository.ChartGroupEntry + var createEntries []*repository.ChartGroupEntry for _, entryBean := range newEntries { - entry := &appStoreRepository.ChartGroupEntry{ + entry := &repository.ChartGroupEntry{ AppStoreValuesVersionId: entryBean.AppStoreValuesVersionId, AppStoreApplicationVersionId: entryBean.AppStoreApplicationVersionId, ChartGroupId: group.Id, @@ -228,7 +228,7 @@ func (impl *ChartGroupServiceImpl) GetChartGroupWithChartMetaData(chartGroupId i return chartGroupRes, err } -func (impl *ChartGroupServiceImpl) charterEntryAdopter(chartGroupEntry *appStoreRepository.ChartGroupEntry) *ChartGroupEntryBean { +func (impl *ChartGroupServiceImpl) charterEntryAdopter(chartGroupEntry *repository.ChartGroupEntry) *ChartGroupEntryBean { var referenceType string var valueVersionName string @@ -317,7 +317,7 @@ func (impl *ChartGroupServiceImpl) GetChartGroupWithInstallationDetail(chartGrou impl.Logger.Errorw("error in finding deployment", "chartGroupId", chartGroupId, "err", err) return nil, err } - groupDeploymentMap := make(map[string][]*appStoreRepository.ChartGroupDeployment) + groupDeploymentMap := make(map[string][]*repository.ChartGroupDeployment) for _, deployment := range deployments { groupDeploymentMap[deployment.GroupInstallationId] = append(groupDeploymentMap[deployment.GroupInstallationId], deployment) } diff --git a/pkg/appStore/AppStoreDeploymentService.go b/pkg/appStore/deployment/service/InstalledAppService.go similarity index 83% rename from pkg/appStore/AppStoreDeploymentService.go rename to pkg/appStore/deployment/service/InstalledAppService.go index c069cf8314..893b28efa4 100644 --- a/pkg/appStore/AppStoreDeploymentService.go +++ b/pkg/appStore/deployment/service/InstalledAppService.go @@ -15,7 +15,7 @@ * */ -package appStore +package service import ( "bytes" @@ -24,11 +24,10 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/internal/sql/repository/app" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDeployment "github.com/devtron-labs/devtron/pkg/appStore/deployment" appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" + repository2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" - appStoreValues "github.com/devtron-labs/devtron/pkg/appStore/values" + "github.com/devtron-labs/devtron/pkg/appStore/values/service" repository5 "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/sql" repository4 "github.com/devtron-labs/devtron/pkg/team" @@ -76,11 +75,12 @@ type InstalledAppService interface { CheckAppExists(appNames []*appStoreBean.AppNames) ([]*appStoreBean.AppNames, error) DeployDefaultChartOnCluster(bean *cluster2.ClusterBean, userId int32) (bool, error) FindAppDetailsForAppstoreApplication(installedAppId, envId int) (bean2.AppDetailContainer, error) + UpdateInstalledAppVersionStatus(application v1alpha1.Application) (bool, error) } type InstalledAppServiceImpl struct { logger *zap.SugaredLogger - installedAppRepository appStoreRepository.InstalledAppRepository + installedAppRepository repository2.InstalledAppRepository chartTemplateService util.ChartTemplateService refChartDir appStoreBean.RefChartProxyDir repositoryService repository.ServiceClient @@ -89,36 +89,38 @@ type InstalledAppServiceImpl struct { teamRepository repository4.TeamRepository appRepository app.AppRepository acdClient application2.ServiceClient - appStoreValuesService appStoreValues.AppStoreValuesService - pubsubClient *pubsub.PubSubClient - tokenCache *util2.TokenCache - chartGroupDeploymentRepository appStoreRepository.ChartGroupDeploymentRepository - envService cluster2.EnvironmentService - ArgoK8sClient argocdServer.ArgoK8sClient - gitFactory *util.GitFactory - aCDAuthConfig *util2.ACDAuthConfig - gitOpsRepository repository3.GitOpsConfigRepository - userService user.UserService - appStoreDeploymentService appStoreDeployment.AppStoreDeploymentService - appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService + appStoreValuesService service.AppStoreValuesService + pubsubClient *pubsub.PubSubClient + tokenCache *util2.TokenCache + chartGroupDeploymentRepository repository2.ChartGroupDeploymentRepository + envService cluster2.EnvironmentService + ArgoK8sClient argocdServer.ArgoK8sClient + gitFactory *util.GitFactory + aCDAuthConfig *util2.ACDAuthConfig + gitOpsRepository repository3.GitOpsConfigRepository + userService user.UserService + appStoreDeploymentService AppStoreDeploymentService + appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService + installedAppRepositoryHistory repository2.InstalledAppVersionHistoryRepository } func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, - installedAppRepository appStoreRepository.InstalledAppRepository, + installedAppRepository repository2.InstalledAppRepository, chartTemplateService util.ChartTemplateService, refChartDir appStoreBean.RefChartProxyDir, repositoryService repository.ServiceClient, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, environmentRepository repository5.EnvironmentRepository, teamRepository repository4.TeamRepository, appRepository app.AppRepository, acdClient application2.ServiceClient, - appStoreValuesService appStoreValues.AppStoreValuesService, + appStoreValuesService service.AppStoreValuesService, pubsubClient *pubsub.PubSubClient, tokenCache *util2.TokenCache, - chartGroupDeploymentRepository appStoreRepository.ChartGroupDeploymentRepository, + chartGroupDeploymentRepository repository2.ChartGroupDeploymentRepository, envService cluster2.EnvironmentService, argoK8sClient argocdServer.ArgoK8sClient, gitFactory *util.GitFactory, aCDAuthConfig *util2.ACDAuthConfig, gitOpsRepository repository3.GitOpsConfigRepository, userService user.UserService, - appStoreDeploymentService appStoreDeployment.AppStoreDeploymentService, - appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService) (*InstalledAppServiceImpl, error) { + appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService, + appStoreDeploymentService AppStoreDeploymentService, + installedAppRepositoryHistory repository2.InstalledAppVersionHistoryRepository) (*InstalledAppServiceImpl, error) { impl := &InstalledAppServiceImpl{ logger: logger, installedAppRepository: installedAppRepository, @@ -142,6 +144,7 @@ func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, userService: userService, appStoreDeploymentService: appStoreDeploymentService, appStoreDeploymentFullModeService: appStoreDeploymentFullModeService, + installedAppRepositoryHistory: installedAppRepositoryHistory, } err := impl.Subscribe() if err != nil { @@ -151,7 +154,6 @@ func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, } func (impl InstalledAppServiceImpl) UpdateInstalledApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) { - dbConnection := impl.installedAppRepository.GetConnection() tx, err := dbConnection.Begin() if err != nil { @@ -166,48 +168,35 @@ func (impl InstalledAppServiceImpl) UpdateInstalledApp(ctx context.Context, inst } installAppVersionRequest.EnvironmentId = installedApp.EnvironmentId installAppVersionRequest.AppName = installedApp.App.AppName - + installAppVersionRequest.EnvironmentName = installedApp.Environment.Name environment, err := impl.environmentRepository.FindById(installedApp.EnvironmentId) if err != nil { impl.logger.Errorw("fetching error", "err", err) return nil, err } - team, err := impl.teamRepository.FindOne(installedApp.App.TeamId) - if err != nil { - impl.logger.Errorw("fetching error", "err", err) - return nil, err - } - impl.logger.Info(team) - argocdAppName := installedApp.App.AppName + "-" + environment.Name + argocdAppName := installedApp.App.AppName + "-" + installedApp.Environment.Name gitOpsRepoName := installedApp.GitOpsRepoName if len(gitOpsRepoName) == 0 { - application, err := impl.acdClient.Get(ctx, &application.ApplicationQuery{Name: &argocdAppName}) - if err != nil { - impl.logger.Errorw("no argo app exists", "app", argocdAppName) - return nil, err - } - if application != nil { - gitOpsRepoUrl := application.Spec.Source.RepoURL - gitOpsRepoName = impl.chartTemplateService.GetGitOpsRepoNameFromUrl(gitOpsRepoUrl) - } + gitOpsRepoName = impl.appStoreDeploymentFullModeService.GetGitOpsRepoName(installAppVersionRequest) } installAppVersionRequest.GitOpsRepoName = gitOpsRepoName + var installedAppVersion *repository2.InstalledAppVersions if installAppVersionRequest.Id == 0 { // upgrade chart to other repo - _, _, err := impl.upgradeInstalledApp(ctx, installAppVersionRequest, installedApp, tx) + _, installedAppVersion, err = impl.upgradeInstalledApp(ctx, installAppVersionRequest, installedApp, tx) if err != nil { impl.logger.Errorw("error while upgrade the chart", "error", err) return nil, err } } else { // update same chart or upgrade its version only - var installedAppVersion *appStoreRepository.InstalledAppVersions installedAppVersionModel, err := impl.installedAppRepository.GetInstalledAppVersion(installAppVersionRequest.Id) if err != nil { impl.logger.Errorw("error while fetching chart installed version", "error", err) return nil, err } if installedAppVersionModel.AppStoreApplicationVersionId != installAppVersionRequest.AppStoreVersion { + // upgrade to new version of same chart installedAppVersionModel.Active = false installedAppVersionModel.UpdatedOn = time.Now() installedAppVersionModel.UpdatedBy = installAppVersionRequest.UserId @@ -221,7 +210,7 @@ func (impl InstalledAppServiceImpl) UpdateInstalledApp(ctx context.Context, inst impl.logger.Errorw("fetching error", "err", err) return nil, err } - installedAppVersion = &appStoreRepository.InstalledAppVersions{ + installedAppVersion = &repository2.InstalledAppVersions{ InstalledAppId: installAppVersionRequest.InstalledAppId, AppStoreApplicationVersionId: installAppVersionRequest.AppStoreVersion, ValuesYaml: installAppVersionRequest.ValuesOverrideYaml, @@ -246,13 +235,13 @@ func (impl InstalledAppServiceImpl) UpdateInstalledApp(ctx context.Context, inst impl.logger.Errorw("error while commit required dependencies to git", "error", err) return nil, err } - + installAppVersionRequest.Id = installedAppVersion.Id } else { installedAppVersion = installedAppVersionModel } //update values yaml in chart - err = impl.updateValuesYaml(environment, installedAppVersion, installAppVersionRequest) + installAppVersionRequest, err = impl.updateValuesYaml(environment, installedAppVersion, installAppVersionRequest) if err != nil { impl.logger.Errorw("error while commit values to git", "error", err) return nil, err @@ -275,17 +264,23 @@ func (impl InstalledAppServiceImpl) UpdateInstalledApp(ctx context.Context, inst return nil, err } } - //STEP 8: finish with return response err = tx.Commit() if err != nil { impl.logger.Errorw("error while committing transaction to db", "error", err) return nil, err } + + // create build history for version upgrade, chart upgrade or simple update + err = impl.appStoreDeploymentService.UpdateInstallAppVersionHistory(installAppVersionRequest) + if err != nil { + impl.logger.Errorw("error on creating history for chart deployment", "error", err) + return nil, err + } return installAppVersionRequest, nil } -func (impl InstalledAppServiceImpl) updateRequirementDependencies(environment *repository5.Environment, installedAppVersion *appStoreRepository.InstalledAppVersions, +func (impl InstalledAppServiceImpl) updateRequirementDependencies(environment *repository5.Environment, installedAppVersion *repository2.InstalledAppVersions, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, appStoreAppVersion *appStoreDiscoverRepository.AppStoreApplicationVersion) error { argocdAppName := installAppVersionRequest.AppName + "-" + environment.Name @@ -332,27 +327,27 @@ func (impl InstalledAppServiceImpl) updateRequirementDependencies(environment *r return nil } -func (impl InstalledAppServiceImpl) updateValuesYaml(environment *repository5.Environment, installedAppVersion *appStoreRepository.InstalledAppVersions, - installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error { +func (impl InstalledAppServiceImpl) updateValuesYaml(environment *repository5.Environment, installedAppVersion *repository2.InstalledAppVersions, + installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) { argocdAppName := installAppVersionRequest.AppName + "-" + environment.Name valuesOverrideByte, err := yaml.YAMLToJSON([]byte(installAppVersionRequest.ValuesOverrideYaml)) if err != nil { impl.logger.Errorw("error in json patch", "err", err) - return err + return installAppVersionRequest, err } var dat map[string]interface{} err = json.Unmarshal(valuesOverrideByte, &dat) if err != nil { impl.logger.Errorw("error in unmarshal", "err", err) - return err + return installAppVersionRequest, err } valuesMap := make(map[string]map[string]interface{}) valuesMap[installedAppVersion.AppStoreApplicationVersion.AppStore.Name] = dat valuesByte, err := json.Marshal(valuesMap) if err != nil { impl.logger.Errorw("error in marshaling", "err", err) - return err + return installAppVersionRequest, err } valuesConfig := &util.ChartConfig{ FileName: appStoreBean.VALUES_YAML_FILE, @@ -368,19 +363,20 @@ func (impl InstalledAppServiceImpl) updateValuesYaml(environment *repository5.En gitOpsConfigBitbucket.BitBucketWorkspaceId = "" } else { impl.logger.Errorw("error in fetching gitOps bitbucket config", "err", err) - return err + return installAppVersionRequest, err } } - _, err = impl.gitFactory.Client.CommitValues(valuesConfig, gitOpsConfigBitbucket.BitBucketWorkspaceId) + commitHash, err := impl.gitFactory.Client.CommitValues(valuesConfig, gitOpsConfigBitbucket.BitBucketWorkspaceId) if err != nil { impl.logger.Errorw("error in git commit", "err", err) - return err + return installAppVersionRequest, err } - return nil + installAppVersionRequest.GitHash = commitHash + return installAppVersionRequest, nil } -func (impl InstalledAppServiceImpl) upgradeInstalledApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApp *appStoreRepository.InstalledApps, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, *appStoreRepository.InstalledAppVersions, error) { - var installedAppVersion *appStoreRepository.InstalledAppVersions +func (impl InstalledAppServiceImpl) upgradeInstalledApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApp *repository2.InstalledApps, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, *repository2.InstalledAppVersions, error) { + var installedAppVersion *repository2.InstalledAppVersions installedAppVersions, err := impl.installedAppRepository.GetInstalledAppVersionByInstalledAppId(installAppVersionRequest.InstalledAppId) if err != nil { impl.logger.Errorw("error while fetching installed version", "error", err) @@ -402,7 +398,7 @@ func (impl InstalledAppServiceImpl) upgradeInstalledApp(ctx context.Context, ins impl.logger.Errorw("fetching error", "err", err) return installAppVersionRequest, installedAppVersion, err } - installedAppVersion = &appStoreRepository.InstalledAppVersions{ + installedAppVersion = &repository2.InstalledAppVersions{ InstalledAppId: installAppVersionRequest.InstalledAppId, AppStoreApplicationVersionId: installAppVersionRequest.AppStoreVersion, ValuesYaml: installAppVersionRequest.ValuesOverrideYaml, @@ -420,7 +416,7 @@ func (impl InstalledAppServiceImpl) upgradeInstalledApp(ctx context.Context, ins return installAppVersionRequest, installedAppVersion, err } installedAppVersion.AppStoreApplicationVersion = *appStoreAppVersion - + installAppVersionRequest.InstalledAppVersionId = installedAppVersion.Id //step 2 git operation pull push installAppVersionRequest, chartGitAttr, err := impl.appStoreDeploymentFullModeService.AppStoreDeployOperationGIT(installAppVersionRequest) if err != nil { @@ -522,7 +518,7 @@ func (impl InstalledAppServiceImpl) GetAll(filter *appStoreBean.AppStoreFilter) } //converts db object to bean -func (impl InstalledAppServiceImpl) chartAdaptor(chart *appStoreRepository.InstalledAppVersions) (*appStoreBean.InstallAppVersionDTO, error) { +func (impl InstalledAppServiceImpl) chartAdaptor(chart *repository2.InstalledAppVersions) (*appStoreBean.InstallAppVersionDTO, error) { return &appStoreBean.InstallAppVersionDTO{ InstalledAppId: chart.InstalledAppId, @@ -633,8 +629,8 @@ func (impl InstalledAppServiceImpl) getInstallationId(installAppVersions []*appS return fmt.Sprintf("%x", bs), nil } -func (impl InstalledAppServiceImpl) createChartGroupEntryObject(installAppVersionDTO *appStoreBean.InstallAppVersionDTO, chartGroupId int, groupINstallationId string) *appStoreRepository.ChartGroupDeployment { - return &appStoreRepository.ChartGroupDeployment{ +func (impl InstalledAppServiceImpl) createChartGroupEntryObject(installAppVersionDTO *appStoreBean.InstallAppVersionDTO, chartGroupId int, groupINstallationId string) *repository2.ChartGroupDeployment { + return &repository2.ChartGroupDeployment{ ChartGroupId: chartGroupId, ChartGroupEntryId: installAppVersionDTO.ChartGroupEntryId, InstalledAppId: installAppVersionDTO.InstalledAppId, @@ -670,7 +666,7 @@ func (impl InstalledAppServiceImpl) performDeployStage(installedAppVersionId int installedAppVersion.Status == appStoreBean.QUE_ERROR || installedAppVersion.Status == appStoreBean.GIT_ERROR { //step 2 git operation pull push - _, chartGitAttrDB, err := impl.appStoreDeploymentFullModeService.AppStoreDeployOperationGIT(installedAppVersion) + installedAppVersion, chartGitAttrDB, err := impl.appStoreDeploymentFullModeService.AppStoreDeployOperationGIT(installedAppVersion) if err != nil { impl.logger.Errorw(" error", "err", err) _, err = impl.appStoreDeploymentService.AppStoreDeployOperationStatusUpdate(installedAppVersion.InstalledAppId, appStoreBean.GIT_ERROR) @@ -752,6 +748,13 @@ func (impl InstalledAppServiceImpl) performDeployStage(installedAppVersionId int impl.logger.Errorw(" error", "err", err) return nil, err } + + // create build history for chart on default component + err = impl.appStoreDeploymentService.UpdateInstallAppVersionHistory(installedAppVersion) + if err != nil { + impl.logger.Errorw("error on creating history for chart deployment", "error", err) + return nil, err + } return installedAppVersion, nil } @@ -1074,3 +1077,105 @@ func (impl *InstalledAppServiceImpl) FindAppDetailsForAppstoreApplication(instal } return appDetail, nil } + +func (impl InstalledAppServiceImpl) GetInstalledAppVersionHistory(installedAppId int) (*appStoreBean.InstallAppVersionHistoryDto, error) { + result := &appStoreBean.InstallAppVersionHistoryDto{} + var history []*appStoreBean.IAVHistory + //TODO - response setup + + installedAppVersions, err := impl.installedAppRepository.GetInstalledAppVersionByInstalledAppIdMeta(installedAppId) + if err != nil { + impl.logger.Errorw("error while fetching installed version", "error", err) + return result, err + } + for _, installedAppVersionModel := range installedAppVersions { + versionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistoryByVersionId(installedAppVersionModel.Id) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error while fetching installed version history", "error", err) + return result, err + } + for _, updateHistory := range versionHistory { + history = append(history, &appStoreBean.IAVHistory{ + ChartMetaData: appStoreBean.IAVHistoryChartMetaData{ + ChartName: installedAppVersionModel.AppStoreApplicationVersion.AppStore.Name, + ChartVersion: installedAppVersionModel.AppStoreApplicationVersion.Version, + Description: installedAppVersionModel.AppStoreApplicationVersion.Description, + Home: installedAppVersionModel.AppStoreApplicationVersion.Home, + Sources: []string{installedAppVersionModel.AppStoreApplicationVersion.Source}, + }, + DockerImages: []string{installedAppVersionModel.AppStoreApplicationVersion.AppVersion}, + DeployedAt: appStoreBean.IAVHistoryDeployedAt{ + Nanos: updateHistory.CreatedOn.Nanosecond(), + Seconds: updateHistory.CreatedOn.Unix(), + }, + Version: updateHistory.Id, + InstalledAppVersionId: installedAppVersionModel.Id, + }) + } + } + + if len(history) == 0 { + history = make([]*appStoreBean.IAVHistory, 0) + } + result.IAVHistory = history + installedApp, err := impl.installedAppRepository.GetInstalledApp(installedAppId) + if err != nil { + impl.logger.Errorw("error while fetching installed version", "error", err) + return result, err + } + result.InstalledAppInfo = &appStoreBean.InstalledAppDto{ + AppId: installedApp.AppId, + EnvironmentName: installedApp.Environment.Name, + AppOfferingMode: installedApp.App.AppOfferingMode, + InstalledAppId: installedApp.Id, + ClusterId: installedApp.Environment.ClusterId, + EnvironmentId: installedApp.EnvironmentId, + } + return result, err +} + +func (impl InstalledAppServiceImpl) UpdateInstalledAppVersionStatus(application v1alpha1.Application) (bool, error) { + isHealthy := false + dbConnection := impl.installedAppRepository.GetConnection() + tx, err := dbConnection.Begin() + if err != nil { + return isHealthy, err + } + // Rollback tx on error. + defer tx.Rollback() + gitHash := "" + if application.Operation != nil && application.Operation.Sync != nil { + gitHash = application.Operation.Sync.Revision + } else if application.Status.OperationState != nil && application.Status.OperationState.Operation.Sync != nil { + gitHash = application.Status.OperationState.Operation.Sync.Revision + } + versionHistory, err := impl.installedAppRepositoryHistory.GetLatestInstalledAppVersionHistoryByGitHash(gitHash) + if err != nil { + impl.logger.Errorw("error while fetching installed version history", "error", err) + return isHealthy, err + } + if versionHistory.Status != (application2.Healthy) { + versionHistory.Status = application.Status.Health.Status + versionHistory.UpdatedOn = time.Now() + versionHistory.UpdatedBy = 1 + impl.installedAppRepositoryHistory.UpdateInstalledAppVersionHistory(versionHistory, tx) + } + err = tx.Commit() + if err != nil { + impl.logger.Errorw("error while committing transaction to db", "error", err) + return isHealthy, err + } + + return true, nil +} + +func (impl InstalledAppServiceImpl) GetInstalledAppVersionHistoryValues(installedAppVersionHistoryId int) (*appStoreBean.IAVHistoryValues, error) { + values := &appStoreBean.IAVHistoryValues{} + versionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistory(installedAppVersionHistoryId) + if err != nil { + impl.logger.Errorw("error while fetching installed version history", "error", err) + return nil, err + } + values.ValuesYaml = versionHistory.ValuesYamlRaw + return values, err +} diff --git a/pkg/appStore/AppStoreDeploymentService_test.go b/pkg/appStore/deployment/service/InstalledAppService_test.go similarity index 77% rename from pkg/appStore/AppStoreDeploymentService_test.go rename to pkg/appStore/deployment/service/InstalledAppService_test.go index 811e590ae6..270268f69d 100644 --- a/pkg/appStore/AppStoreDeploymentService_test.go +++ b/pkg/appStore/deployment/service/InstalledAppService_test.go @@ -1,4 +1,4 @@ -package appStore +package service import ( "github.com/devtron-labs/devtron/client/argocdServer" @@ -9,11 +9,10 @@ import ( "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDeployment "github.com/devtron-labs/devtron/pkg/appStore/deployment" appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" + repository4 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" - appStoreValues "github.com/devtron-labs/devtron/pkg/appStore/values" + "github.com/devtron-labs/devtron/pkg/appStore/values/service" "github.com/devtron-labs/devtron/pkg/cluster" "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/team" @@ -26,7 +25,7 @@ import ( func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { type fields struct { logger *zap.SugaredLogger - installedAppRepository appStoreRepository.InstalledAppRepository + installedAppRepository repository4.InstalledAppRepository chartTemplateService util.ChartTemplateService refChartDir appStoreBean.RefChartProxyDir repositoryService repository2.ServiceClient @@ -35,18 +34,18 @@ func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { teamRepository team.TeamRepository appRepository app.AppRepository acdClient application.ServiceClient - appStoreValuesService appStoreValues.AppStoreValuesService - pubsubClient *pubsub.PubSubClient - tokenCache *util2.TokenCache - chartGroupDeploymentRepository appStoreRepository.ChartGroupDeploymentRepository - envService cluster.EnvironmentService - ArgoK8sClient argocdServer.ArgoK8sClient - gitFactory *util.GitFactory - aCDAuthConfig *util2.ACDAuthConfig - gitOpsRepository repository3.GitOpsConfigRepository - userService user.UserService - appStoreDeploymentService appStoreDeployment.AppStoreDeploymentService - appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService + appStoreValuesService service.AppStoreValuesService + pubsubClient *pubsub.PubSubClient + tokenCache *util2.TokenCache + chartGroupDeploymentRepository repository4.ChartGroupDeploymentRepository + envService cluster.EnvironmentService + ArgoK8sClient argocdServer.ArgoK8sClient + gitFactory *util.GitFactory + aCDAuthConfig *util2.ACDAuthConfig + gitOpsRepository repository3.GitOpsConfigRepository + userService user.UserService + appStoreDeploymentService AppStoreDeploymentService + appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService } type args struct { bean *cluster.ClusterBean diff --git a/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go b/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go index 1cd50fe015..93ea017a90 100644 --- a/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go +++ b/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go @@ -2,11 +2,16 @@ package appStoreDeploymentTool import ( "context" + "errors" client "github.com/devtron-labs/devtron/api/helm-app" + openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" + "github.com/devtron-labs/devtron/internal/constants" + "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" clusterRepository "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/ghodss/yaml" "github.com/go-pg/pg" "go.uber.org/zap" "net/http" @@ -14,9 +19,12 @@ import ( ) type AppStoreDeploymentHelmService interface { - InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) error - GetAppStatus(installedAppAndEnvDetails appStoreRepository.InstalledAppAndEnvDetails, w http.ResponseWriter, r *http.Request, token string) (string, error) - DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *appStoreRepository.InstalledApps, dbTransaction *pg.Tx) error + InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) + GetAppStatus(installedAppAndEnvDetails repository.InstalledAppAndEnvDetails, w http.ResponseWriter, r *http.Request, token string) (string, error) + DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error + RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, deploymentVersion int32) (*appStoreBean.InstallAppVersionDTO, bool, error) + GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) + GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) } type AppStoreDeploymentHelmServiceImpl struct { @@ -24,23 +32,25 @@ type AppStoreDeploymentHelmServiceImpl struct { helmAppService client.HelmAppService appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository environmentRepository clusterRepository.EnvironmentRepository + helmAppClient client.HelmAppClient } func NewAppStoreDeploymentHelmServiceImpl(logger *zap.SugaredLogger, helmAppService client.HelmAppService, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, - environmentRepository clusterRepository.EnvironmentRepository) *AppStoreDeploymentHelmServiceImpl { + environmentRepository clusterRepository.EnvironmentRepository, helmAppClient client.HelmAppClient) *AppStoreDeploymentHelmServiceImpl { return &AppStoreDeploymentHelmServiceImpl{ Logger: logger, helmAppService: helmAppService, appStoreApplicationVersionRepository: appStoreApplicationVersionRepository, environmentRepository: environmentRepository, + helmAppClient: helmAppClient, } } -func (impl AppStoreDeploymentHelmServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) error { +func (impl AppStoreDeploymentHelmServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) { appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) if err != nil { impl.Logger.Errorw("fetching error", "err", err) - return err + return installAppVersionRequest, err } installReleaseRequest := &client.InstallReleaseRequest{ @@ -61,16 +71,17 @@ func (impl AppStoreDeploymentHelmServiceImpl) InstallApp(installAppVersionReques _, err = impl.helmAppService.InstallRelease(ctx, installAppVersionRequest.ClusterId, installReleaseRequest) if err != nil { - return err + return installAppVersionRequest, err } - return nil + return installAppVersionRequest, nil } -func (impl AppStoreDeploymentHelmServiceImpl) GetAppStatus(installedAppAndEnvDetails appStoreRepository.InstalledAppAndEnvDetails, w http.ResponseWriter, r *http.Request, token string) (string, error) { +func (impl AppStoreDeploymentHelmServiceImpl) GetAppStatus(installedAppAndEnvDetails repository.InstalledAppAndEnvDetails, w http.ResponseWriter, r *http.Request, token string) (string, error) { environment, err := impl.environmentRepository.FindById(installedAppAndEnvDetails.EnvironmentId) if err != nil { + impl.Logger.Errorw("Error in getting environment", "err", err) return "", err } @@ -85,13 +96,20 @@ func (impl AppStoreDeploymentHelmServiceImpl) GetAppStatus(installedAppAndEnvDet appDetail, err := impl.helmAppService.GetApplicationDetail(ctx, appIdentifier) if err != nil { + // handling like argocd + impl.Logger.Errorw("error fetching helm app resource tree", "error", err, "appIdentifier", appIdentifier) + err = &util.ApiError{ + Code: constants.AppDetailResourceTreeNotFound, + InternalMessage: "Failed to get resource tree from helm", + UserMessage: "Failed to get resource tree from helm", + } return "", err } return appDetail.ApplicationStatus, nil } -func (impl AppStoreDeploymentHelmServiceImpl) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *appStoreRepository.InstalledApps, dbTransaction *pg.Tx) error { +func (impl AppStoreDeploymentHelmServiceImpl) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error { appIdentifier := &client.AppIdentifier{ ClusterId: installAppVersionRequest.ClusterId, @@ -99,6 +117,111 @@ func (impl AppStoreDeploymentHelmServiceImpl) DeleteInstalledApp(ctx context.Con Namespace: installAppVersionRequest.Namespace, } - _, err := impl.helmAppService.DeleteApplication(ctx, appIdentifier) - return err + isInstalled, err := impl.helmAppService.IsReleaseInstalled(ctx, appIdentifier) + if err != nil { + impl.Logger.Errorw("error in checking if helm release is installed or not", "error", err, "appIdentifier", appIdentifier) + return err + } + + if isInstalled { + deleteResponse, err := impl.helmAppService.DeleteApplication(ctx, appIdentifier) + if err != nil { + impl.Logger.Errorw("error in deleting helm application", "error", err, "appIdentifier", appIdentifier) + return err + } + if deleteResponse == nil || !deleteResponse.GetSuccess() { + return errors.New("delete application response unsuccessful") + } + } + + return nil +} + +// returns - valuesYamlStr, success, error +func (impl AppStoreDeploymentHelmServiceImpl) RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, deploymentVersion int32) (*appStoreBean.InstallAppVersionDTO, bool, error) { + + // TODO : fetch values yaml from DB instead of fetching from helm cli + // TODO Dependency : on updating helm APP, DB is not being updated. values yaml is sent directly to helm cli. After DB updatation development, we can fetch values yaml from DB, not from CLI. + + helmAppIdeltifier := &client.AppIdentifier{ + ClusterId: installedApp.ClusterId, + Namespace: installedApp.Namespace, + ReleaseName: installedApp.AppName, + } + + helmAppDeploymentDetail, err := impl.helmAppService.GetDeploymentDetail(ctx, helmAppIdeltifier, deploymentVersion) + if err != nil { + impl.Logger.Errorw("Error in getting helm application deployment detail", "err", err) + return installedApp, false, err + } + valuesYamlJson := helmAppDeploymentDetail.GetValuesYaml() + valuesYamlByteArr, err := yaml.JSONToYAML([]byte(valuesYamlJson)) + if err != nil { + impl.Logger.Errorw("Error in converting json to yaml", "err", err) + return installedApp, false, err + } + + // send to helm + success, err := impl.helmAppService.RollbackRelease(ctx, helmAppIdeltifier, deploymentVersion) + if err != nil { + impl.Logger.Errorw("Error in helm rollback release", "err", err) + return installedApp, false, err + } + installedApp.ValuesOverrideYaml = string(valuesYamlByteArr) + return installedApp, success, nil +} + +func (impl *AppStoreDeploymentHelmServiceImpl) GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) { + helmAppIdeltifier := &client.AppIdentifier{ + ClusterId: installedApp.ClusterId, + Namespace: installedApp.Namespace, + ReleaseName: installedApp.AppName, + } + config, err := impl.helmAppService.GetClusterConf(helmAppIdeltifier.ClusterId) + if err != nil { + impl.Logger.Errorw("error in fetching cluster detail", "err", err) + return nil, err + } + req := &client.AppDetailRequest{ + ClusterConfig: config, + Namespace: helmAppIdeltifier.Namespace, + ReleaseName: helmAppIdeltifier.ReleaseName, + } + history, err := impl.helmAppClient.GetDeploymentHistory(ctx, req) + return history, err +} + +func (impl *AppStoreDeploymentHelmServiceImpl) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) { + helmAppIdeltifier := &client.AppIdentifier{ + ClusterId: installedApp.ClusterId, + Namespace: installedApp.Namespace, + ReleaseName: installedApp.AppName, + } + config, err := impl.helmAppService.GetClusterConf(helmAppIdeltifier.ClusterId) + if err != nil { + impl.Logger.Errorw("error in fetching cluster detail", "clusterId", helmAppIdeltifier.ClusterId, "err", err) + return nil, err + } + + req := &client.DeploymentDetailRequest{ + ReleaseIdentifier: &client.ReleaseIdentifier{ + ClusterConfig: config, + ReleaseName: helmAppIdeltifier.ReleaseName, + ReleaseNamespace: helmAppIdeltifier.Namespace, + }, + DeploymentVersion: version, + } + + deploymentDetail, err := impl.helmAppClient.GetDeploymentDetail(ctx, req) + if err != nil { + impl.Logger.Errorw("error in getting deployment detail", "err", err) + return nil, err + } + + response := &openapi.HelmAppDeploymentManifestDetail{ + Manifest: &deploymentDetail.Manifest, + ValuesYaml: &deploymentDetail.ValuesYaml, + } + + return response, nil } diff --git a/pkg/appStore/deployment/tool/gitops/AppStoreDeploymentArgoCdService.go b/pkg/appStore/deployment/tool/gitops/AppStoreDeploymentArgoCdService.go index e866b4ded9..351c41e4d1 100644 --- a/pkg/appStore/deployment/tool/gitops/AppStoreDeploymentArgoCdService.go +++ b/pkg/appStore/deployment/tool/gitops/AppStoreDeploymentArgoCdService.go @@ -2,16 +2,20 @@ package appStoreDeploymentGitopsTool import ( "context" + "encoding/json" "errors" "fmt" "github.com/argoproj/argo-cd/pkg/apiclient/application" + client "github.com/devtron-labs/devtron/api/helm-app" + openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" application2 "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/constants" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" "github.com/go-pg/pg" + "github.com/golang/protobuf/ptypes/timestamp" "go.uber.org/zap" "net/http" "strings" @@ -19,48 +23,56 @@ import ( ) type AppStoreDeploymentArgoCdService interface { - InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) error - GetAppStatus(installedAppAndEnvDetails appStoreRepository.InstalledAppAndEnvDetails, w http.ResponseWriter, r *http.Request, token string) (string, error) - DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *appStoreRepository.InstalledApps, dbTransaction *pg.Tx) error + InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) + GetAppStatus(installedAppAndEnvDetails repository.InstalledAppAndEnvDetails, w http.ResponseWriter, r *http.Request, token string) (string, error) + DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error + RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, deploymentVersion int32) (*appStoreBean.InstallAppVersionDTO, bool, error) + GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) + GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) } type AppStoreDeploymentArgoCdServiceImpl struct { Logger *zap.SugaredLogger appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService acdClient application2.ServiceClient - chartGroupDeploymentRepository appStoreRepository.ChartGroupDeploymentRepository + chartGroupDeploymentRepository repository.ChartGroupDeploymentRepository + installedAppRepository repository.InstalledAppRepository + installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository } func NewAppStoreDeploymentArgoCdServiceImpl(logger *zap.SugaredLogger, appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService, - acdClient application2.ServiceClient, chartGroupDeploymentRepository appStoreRepository.ChartGroupDeploymentRepository) *AppStoreDeploymentArgoCdServiceImpl { + acdClient application2.ServiceClient, chartGroupDeploymentRepository repository.ChartGroupDeploymentRepository, + installedAppRepository repository.InstalledAppRepository, installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository) *AppStoreDeploymentArgoCdServiceImpl { return &AppStoreDeploymentArgoCdServiceImpl{ Logger: logger, appStoreDeploymentFullModeService: appStoreDeploymentFullModeService, acdClient: acdClient, chartGroupDeploymentRepository: chartGroupDeploymentRepository, + installedAppRepository: installedAppRepository, + installedAppRepositoryHistory: installedAppRepositoryHistory, } } -func (impl AppStoreDeploymentArgoCdServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) error { +func (impl AppStoreDeploymentArgoCdServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) { //step 2 git operation pull push installAppVersionRequest, chartGitAttr, err := impl.appStoreDeploymentFullModeService.AppStoreDeployOperationGIT(installAppVersionRequest) if err != nil { impl.Logger.Errorw(" error", "err", err) - return err + return installAppVersionRequest, err } //step 3 acd operation register, sync installAppVersionRequest, err = impl.appStoreDeploymentFullModeService.AppStoreDeployOperationACD(installAppVersionRequest, chartGitAttr, ctx) if err != nil { impl.Logger.Errorw(" error", "err", err) - return err + return installAppVersionRequest, err } - return nil + return installAppVersionRequest, nil } // TODO: Test ACD to get status -func (impl AppStoreDeploymentArgoCdServiceImpl) GetAppStatus(installedAppAndEnvDetails appStoreRepository.InstalledAppAndEnvDetails, w http.ResponseWriter, r *http.Request, token string) (string, error) { +func (impl AppStoreDeploymentArgoCdServiceImpl) GetAppStatus(installedAppAndEnvDetails repository.InstalledAppAndEnvDetails, w http.ResponseWriter, r *http.Request, token string) (string, error) { if len(installedAppAndEnvDetails.AppName) > 0 && len(installedAppAndEnvDetails.EnvironmentName) > 0 { acdAppName := installedAppAndEnvDetails.AppName + "-" + installedAppAndEnvDetails.EnvironmentName query := &application.ResourcesQuery{ @@ -98,7 +110,7 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) GetAppStatus(installedAppAndEnvD return "", errors.New("invalid app name or env name") } -func (impl AppStoreDeploymentArgoCdServiceImpl) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *appStoreRepository.InstalledApps, dbTransaction *pg.Tx) error { +func (impl AppStoreDeploymentArgoCdServiceImpl) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error { acdAppName := appName + "-" + environmentName err := impl.deleteACD(acdAppName, ctx) if err != nil { @@ -141,6 +153,66 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) DeleteInstalledApp(ctx context.C return nil } +// returns - valuesYamlStr, success, error +func (impl AppStoreDeploymentArgoCdServiceImpl) RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, installedAppVersionHistoryId int32) (*appStoreBean.InstallAppVersionDTO, bool, error) { + //request version id for + versionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistory(int(installedAppVersionHistoryId)) + if err != nil { + impl.Logger.Errorw("error", "err", err) + err = &util.ApiError{Code: "404", HttpStatusCode: 404, UserMessage: fmt.Sprintf("No deployment history version found for id: %d", installedAppVersionHistoryId), InternalMessage: err.Error()} + return installedApp, false, err + } + installedAppVersion, err := impl.installedAppRepository.GetInstalledAppVersionAny(versionHistory.InstalledAppVersionId) + if err != nil { + impl.Logger.Errorw("error", "err", err) + err = &util.ApiError{Code: "404", HttpStatusCode: 404, UserMessage: fmt.Sprintf("No installed app version found for id: %d", versionHistory.InstalledAppVersionId), InternalMessage: err.Error()} + return installedApp, false, err + } + activeInstalledAppVersion, err := impl.installedAppRepository.GetActiveInstalledAppVersionByInstalledAppId(installedApp.InstalledAppId) + if err != nil { + impl.Logger.Errorw("error", "err", err) + return installedApp, false, err + } + + //validate relations + if installedApp.InstalledAppId != installedAppVersion.InstalledAppId { + err = &util.ApiError{Code: "400", HttpStatusCode: 400, UserMessage: "bad request, requested version are not belongs to each other", InternalMessage: ""} + return installedApp, false, err + } + + installedApp.InstalledAppVersionId = installedAppVersion.Id + installedApp.AppStoreVersion = installedAppVersion.AppStoreApplicationVersionId + installedApp.ValuesOverrideYaml = versionHistory.ValuesYamlRaw + installedApp.AppStoreId = installedAppVersion.AppStoreApplicationVersion.AppStoreId + installedApp.AppStoreName = installedAppVersion.AppStoreApplicationVersion.AppStore.Name + installedApp.GitOpsRepoName = installedAppVersion.InstalledApp.GitOpsRepoName + installedApp.ACDAppName = fmt.Sprintf("%s-%s", installedApp.AppName, installedApp.EnvironmentName) + //If current version upgrade/degrade to another, update requirement dependencies + if versionHistory.InstalledAppVersionId != activeInstalledAppVersion.Id { + err = impl.appStoreDeploymentFullModeService.UpdateRequirementYaml(installedApp, &installedAppVersion.AppStoreApplicationVersion) + if err != nil { + impl.Logger.Errorw("error", "err", err) + return installedApp, false, nil + } + + activeInstalledAppVersion.Active = false + _, err = impl.installedAppRepository.UpdateInstalledAppVersion(activeInstalledAppVersion, nil) + if err != nil { + impl.Logger.Errorw("error", "err", err) + return installedApp, false, nil + } + } + //Update Values config + installedApp, err = impl.appStoreDeploymentFullModeService.UpdateValuesYaml(installedApp) + if err != nil { + impl.Logger.Errorw("error", "err", err) + return installedApp, false, nil + } + //ACD sync operation + impl.appStoreDeploymentFullModeService.SyncACD(installedApp.ACDAppName, ctx) + return installedApp, true, nil +} + func (impl AppStoreDeploymentArgoCdServiceImpl) deleteACD(acdAppName string, ctx context.Context) error { req := new(application.ApplicationDeleteRequest) req.Name = &acdAppName @@ -154,3 +226,77 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) deleteACD(acdAppName string, ctx } return nil } +func (impl AppStoreDeploymentArgoCdServiceImpl) getSourcesFromManifest(chartYaml string) ([]string, error) { + var b map[string]interface{} + var sources []string + err := json.Unmarshal([]byte(chartYaml), &b) + if err != nil { + impl.Logger.Errorw("error while unmarshal chart yaml", "error", err) + return sources, err + } + if b != nil && b["sources"] != nil { + slice := b["sources"].([]interface{}) + for _, item := range slice { + sources = append(sources, item.(string)) + } + } + return sources, nil +} +func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistory(ctx context.Context, installedAppDto *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) { + result := &client.HelmAppDeploymentHistory{} + var history []*client.HelmAppDeploymentDetail + //TODO - response setup + + installedAppVersions, err := impl.installedAppRepository.GetInstalledAppVersionByInstalledAppIdMeta(installedAppDto.InstalledAppId) + if err != nil { + impl.Logger.Errorw("error while fetching installed version", "error", err) + return result, err + } + for _, installedAppVersionModel := range installedAppVersions { + + sources, err := impl.getSourcesFromManifest(installedAppVersionModel.AppStoreApplicationVersion.ChartYaml) + if err != nil { + impl.Logger.Errorw("error while fetching sources", "error", err) + //continues here, skip error in case found issue on fetching source + } + versionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistoryByVersionId(installedAppVersionModel.Id) + if err != nil && err != pg.ErrNoRows { + impl.Logger.Errorw("error while fetching installed version history", "error", err) + return result, err + } + for _, updateHistory := range versionHistory { + history = append(history, &client.HelmAppDeploymentDetail{ + ChartMetadata: &client.ChartMetadata{ + ChartName: installedAppVersionModel.AppStoreApplicationVersion.AppStore.Name, + ChartVersion: installedAppVersionModel.AppStoreApplicationVersion.Version, + Description: installedAppVersionModel.AppStoreApplicationVersion.Description, + Home: installedAppVersionModel.AppStoreApplicationVersion.Home, + Sources: sources, + }, + DockerImages: []string{installedAppVersionModel.AppStoreApplicationVersion.AppVersion}, + DeployedAt: ×tamp.Timestamp{ + Seconds: updateHistory.UpdatedOn.Unix(), + Nanos: int32(updateHistory.UpdatedOn.Nanosecond()), + }, + Version: int32(updateHistory.Id), + }) + } + } + + if len(history) == 0 { + history = make([]*client.HelmAppDeploymentDetail, 0) + } + result.DeploymentHistory = history + return result, err +} + +func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) { + values := &openapi.HelmAppDeploymentManifestDetail{} + versionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistory(int(version)) + if err != nil { + impl.Logger.Errorw("error while fetching installed version history", "error", err) + return nil, err + } + values.ValuesYaml = &versionHistory.ValuesYamlRaw + return values, err +} diff --git a/pkg/appStore/discover/AppStoreService.go b/pkg/appStore/discover/service/AppStoreService.go similarity index 99% rename from pkg/appStore/discover/AppStoreService.go rename to pkg/appStore/discover/service/AppStoreService.go index 4e2b182222..f66966cc7e 100644 --- a/pkg/appStore/discover/AppStoreService.go +++ b/pkg/appStore/discover/service/AppStoreService.go @@ -15,7 +15,7 @@ * */ -package appStoreDiscover +package service import ( "github.com/devtron-labs/devtron/internal/util" diff --git a/pkg/appStore/values/AppStoreValuesService.go b/pkg/appStore/values/service/AppStoreValuesService.go similarity index 97% rename from pkg/appStore/values/AppStoreValuesService.go rename to pkg/appStore/values/service/AppStoreValuesService.go index e45ae6ac74..da93778524 100644 --- a/pkg/appStore/values/AppStoreValuesService.go +++ b/pkg/appStore/values/service/AppStoreValuesService.go @@ -15,14 +15,14 @@ * */ -package appStoreValues +package service import ( "fmt" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" appStoreValuesRepository "github.com/devtron-labs/devtron/pkg/appStore/values/repository" "go.uber.org/zap" "time" @@ -42,12 +42,12 @@ type AppStoreValuesService interface { type AppStoreValuesServiceImpl struct { logger *zap.SugaredLogger appStoreApplicationRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository - installedAppRepository appStoreRepository.InstalledAppRepository + installedAppRepository repository.InstalledAppRepository appStoreVersionValuesRepository appStoreValuesRepository.AppStoreVersionValuesRepository } func NewAppStoreValuesServiceImpl(logger *zap.SugaredLogger, - appStoreApplicationRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, installedAppRepository appStoreRepository.InstalledAppRepository, + appStoreApplicationRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, installedAppRepository repository.InstalledAppRepository, appStoreVersionValuesRepository appStoreValuesRepository.AppStoreVersionValuesRepository) *AppStoreValuesServiceImpl { return &AppStoreValuesServiceImpl{ logger: logger, @@ -292,7 +292,7 @@ func (impl AppStoreValuesServiceImpl) adapter(values *appStoreValuesRepository.A }, nil } -/*func (impl AppStoreValuesServiceImpl) adaptorForValuesCategoryWise(values *appstore.AppStoreVersionValues) (val *AppStoreVersionValuesCategoryWiseDTO) { +/*func (impl AppStoreValuesServiceImpl) adaptorForValuesCategoryWise(values *appStore.AppStoreVersionValues) (val *AppStoreVersionValuesCategoryWiseDTO) { version := "" if values.AppStoreApplicationVersion != nil { version = values.AppStoreApplicationVersion.Version diff --git a/pkg/chartRepo/ChartRepositoryService.go b/pkg/chartRepo/ChartRepositoryService.go index b8b9b2febe..f0ea5e195b 100644 --- a/pkg/chartRepo/ChartRepositoryService.go +++ b/pkg/chartRepo/ChartRepositoryService.go @@ -560,4 +560,4 @@ func (impl *ChartRepositoryServiceImpl) DeleteChartRepo(request *ChartRepoDto) e return err } return nil -} \ No newline at end of file +} diff --git a/pkg/chartRepo/ChartRepositoryService_test.go b/pkg/chartRepo/ChartRepositoryService_test.go new file mode 100644 index 0000000000..3e6a07037a --- /dev/null +++ b/pkg/chartRepo/ChartRepositoryService_test.go @@ -0,0 +1,63 @@ +package chartRepo + +import ( + "github.com/devtron-labs/devtron/internal/util" + "github.com/stretchr/testify/mock" + "testing" +) + +type ChartRepositoryServiceMock struct { + mock.Mock +} + +func TestChartRepositoryServiceImpl_ValidateChartDetails(t *testing.T) { + sugaredLogger := util.NewSugardLogger() + impl := &ChartRepositoryServiceImpl{ + logger: sugaredLogger, + repoRepository: new(ChartRepoRepositoryImplMock), + K8sUtil: nil, + clusterService: new(ClusterServiceImplMock), + aCDAuthConfig: nil, + client: nil, + } + + type args struct { + FileName string + chartVersion string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "Test file format", + args: struct { + FileName string + chartVersion string + }{FileName: "test.tar.gz", chartVersion: "1.0.0"}, + want: "test_1-0-0", + }, + { + name: "Test file format", + args: struct { + FileName string + chartVersion string + }{FileName: "test.pdf", chartVersion: "1.0.0"}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := impl.ValidateChartDetails(tt.args.FileName, tt.args.chartVersion) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateChartDetails() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("ValidateChartDetails() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/chartRepo/Mock_test.go b/pkg/chartRepo/Mock_test.go new file mode 100644 index 0000000000..4606734245 --- /dev/null +++ b/pkg/chartRepo/Mock_test.go @@ -0,0 +1,88 @@ +package chartRepo + +import ( + "context" + "github.com/devtron-labs/devtron/internal/util" + chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" + cluster2 "github.com/devtron-labs/devtron/pkg/cluster" + "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/go-pg/pg" + "github.com/stretchr/testify/mock" +) + +type ChartRepoRepositoryImplMock struct { + mock.Mock +} + +func (impl ChartRepoRepositoryImplMock) Save(chartRepo *chartRepoRepository.ChartRepo, tx *pg.Tx) error { + panic("implement me") +} +func (impl ChartRepoRepositoryImplMock) Update(chartRepo *chartRepoRepository.ChartRepo, tx *pg.Tx) error { + panic("implement me") +} +func (impl ChartRepoRepositoryImplMock) GetDefault() (*chartRepoRepository.ChartRepo, error) { + panic("implement me") +} +func (impl ChartRepoRepositoryImplMock) FindById(id int) (*chartRepoRepository.ChartRepo, error) { + panic("implement me") +} +func (impl ChartRepoRepositoryImplMock) FindAll() ([]*chartRepoRepository.ChartRepo, error) { + panic("implement me") +} +func (impl ChartRepoRepositoryImplMock) GetConnection() *pg.DB { + panic("implement me") +} +func (impl ChartRepoRepositoryImplMock) MarkChartRepoDeleted(chartRepo *chartRepoRepository.ChartRepo, tx *pg.Tx) error { + panic("implement me") +} + +//---------- +type ClusterServiceImplMock struct { + mock.Mock +} + +//func (impl ClusterServiceImplMock) Save(chartRepo *chartRepoRepository.ChartRepo, tx *pg.Tx) error { +// panic("implement me") +//} + +func (impl ClusterServiceImplMock) Save(parent context.Context, bean *cluster2.ClusterBean, userId int32) (*cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) FindOne(clusterName string) (*cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) FindOneActive(clusterName string) (*cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) FindAll() ([]*cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) FindAllActive() ([]cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) DeleteFromDb(bean *cluster2.ClusterBean, userId int32) error { + panic("implement me") +} + +func (impl ClusterServiceImplMock) FindById(id int) (*cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) FindByIds(id []int) ([]cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) Update(ctx context.Context, bean *cluster2.ClusterBean, userId int32) (*cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) Delete(bean *cluster2.ClusterBean, userId int32) error { + panic("implement me") +} + +func (impl ClusterServiceImplMock) FindAllForAutoComplete() ([]cluster2.ClusterBean, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) CreateGrafanaDataSource(clusterBean *cluster2.ClusterBean, env *repository.Environment) (int, error) { + panic("implement me") +} +func (impl ClusterServiceImplMock) GetClusterConfig(cluster *cluster2.ClusterBean) (*util.ClusterConfig, error) { + panic("implement me") +} diff --git a/pkg/chartRepo/repository/ChartRepoRepository.go b/pkg/chartRepo/repository/ChartRepoRepository.go index 472d62f8c3..a1b29c4f70 100644 --- a/pkg/chartRepo/repository/ChartRepoRepository.go +++ b/pkg/chartRepo/repository/ChartRepoRepository.go @@ -291,8 +291,8 @@ type ChartRef struct { Id int `sql:"id,pk"` Location string `sql:"location"` Version string `sql:"version"` - Active bool `sql:"active"` - Default bool `sql:"is_default"` + Active bool `sql:"active,notnull"` + Default bool `sql:"is_default,notnull"` Name string `sql:"name"` ChartData []byte `sql:"chart_data"` sql.AuditLog @@ -303,6 +303,7 @@ type ChartRefRepository interface { GetDefault() (*ChartRef, error) FindById(id int) (*ChartRef, error) GetAll() ([]*ChartRef, error) + CheckIfDataExists(name string, version string) (bool, error) } type ChartRefRepositoryImpl struct { dbConnection *pg.DB @@ -340,3 +341,10 @@ func (impl ChartRefRepositoryImpl) GetAll() ([]*ChartRef, error) { Where("active = ?", true).Select() return chartRefs, err } + +func (impl ChartRefRepositoryImpl) CheckIfDataExists(name string, version string) (bool, error) { + repo := &ChartRef{} + return impl.dbConnection.Model(repo). + Where("name = ?", name). + Where("version = ? ", version).Exists() +} diff --git a/pkg/cluster/ClusterServiceExtended.go b/pkg/cluster/ClusterServiceExtended.go index 34bf4d0c30..ee4392ccec 100644 --- a/pkg/cluster/ClusterServiceExtended.go +++ b/pkg/cluster/ClusterServiceExtended.go @@ -11,7 +11,7 @@ import ( "github.com/devtron-labs/devtron/internal/constants" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" + repository2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" "github.com/devtron-labs/devtron/pkg/cluster/repository" "go.uber.org/zap" "net/http" @@ -23,14 +23,14 @@ import ( type ClusterServiceImplExtended struct { environmentRepository repository.EnvironmentRepository grafanaClient grafana.GrafanaClient - installedAppRepository appStoreRepository.InstalledAppRepository + installedAppRepository repository2.InstalledAppRepository clusterServiceCD cluster2.ServiceClient K8sInformerFactory informer.K8sInformerFactory *ClusterServiceImpl } func NewClusterServiceImplExtended(repository repository.ClusterRepository, environmentRepository repository.EnvironmentRepository, - grafanaClient grafana.GrafanaClient, logger *zap.SugaredLogger, installedAppRepository appStoreRepository.InstalledAppRepository, + grafanaClient grafana.GrafanaClient, logger *zap.SugaredLogger, installedAppRepository repository2.InstalledAppRepository, K8sUtil *util.K8sUtil, clusterServiceCD cluster2.ServiceClient, K8sInformerFactory informer.K8sInformerFactory) *ClusterServiceImplExtended { clusterServiceExt := &ClusterServiceImplExtended{ @@ -59,7 +59,7 @@ func (impl *ClusterServiceImplExtended) FindAll() ([]*ClusterBean, error) { for _, cluster := range beans { clusterIds = append(clusterIds, cluster.Id) } - clusterComponentsMap := make(map[int][]*appStoreRepository.InstalledAppVersions) + clusterComponentsMap := make(map[int][]*repository2.InstalledAppVersions) charts, err := impl.installedAppRepository.GetInstalledAppVersionByClusterIdsV2(clusterIds) if err != nil { impl.logger.Errorw("error on fetching installed apps for cluster ids", "err", err, "clusterIds", clusterIds) @@ -67,7 +67,7 @@ func (impl *ClusterServiceImplExtended) FindAll() ([]*ClusterBean, error) { } for _, item := range charts { if _, ok := clusterComponentsMap[item.InstalledApp.Environment.ClusterId]; !ok { - var charts []*appStoreRepository.InstalledAppVersions + var charts []*repository2.InstalledAppVersions charts = append(charts, item) clusterComponentsMap[item.InstalledApp.Environment.ClusterId] = charts } else { diff --git a/pkg/delete/DeleteServiceExtended.go b/pkg/delete/DeleteServiceExtended.go index 61315a7a5e..33b2cabd41 100644 --- a/pkg/delete/DeleteServiceExtended.go +++ b/pkg/delete/DeleteServiceExtended.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" - appStoreRepository "github.com/devtron-labs/devtron/pkg/appStore/repository" + repository2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" "github.com/devtron-labs/devtron/pkg/chartRepo" "github.com/devtron-labs/devtron/pkg/cluster" "github.com/devtron-labs/devtron/pkg/cluster/repository" @@ -17,7 +17,7 @@ type DeleteServiceExtendedImpl struct { appRepository app.AppRepository environmentRepository repository.EnvironmentRepository pipelineRepository pipelineConfig.PipelineRepository - installedAppRepository appStoreRepository.InstalledAppRepository + installedAppRepository repository2.InstalledAppRepository *DeleteServiceImpl } @@ -27,7 +27,7 @@ func NewDeleteServiceExtendedImpl(logger *zap.SugaredLogger, environmentService cluster.EnvironmentService, appRepository app.AppRepository, environmentRepository repository.EnvironmentRepository, - pipelineRepository pipelineConfig.PipelineRepository, chartRepositoryService chartRepo.ChartRepositoryService, installedAppRepository appStoreRepository.InstalledAppRepository, + pipelineRepository pipelineConfig.PipelineRepository, chartRepositoryService chartRepo.ChartRepositoryService, installedAppRepository repository2.InstalledAppRepository, ) *DeleteServiceExtendedImpl { return &DeleteServiceExtendedImpl{ appRepository: appRepository, diff --git a/pkg/pipeline/BulkUpdateService.go b/pkg/pipeline/BulkUpdateService.go index 575c847ce1..03e148b213 100644 --- a/pkg/pipeline/BulkUpdateService.go +++ b/pkg/pipeline/BulkUpdateService.go @@ -6,6 +6,9 @@ import ( "github.com/devtron-labs/devtron/internal/sql/repository/app" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/devtron-labs/devtron/pkg/pipeline/history" + repository4 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" + "github.com/go-pg/pg" "net/http" "github.com/devtron-labs/devtron/client/argocdServer/repository" @@ -110,24 +113,27 @@ type BulkUpdateService interface { } type BulkUpdateServiceImpl struct { - bulkUpdateRepository bulkUpdate.BulkUpdateRepository - chartRepository chartRepoRepository.ChartRepository - logger *zap.SugaredLogger - repoRepository chartRepoRepository.ChartRepoRepository - chartTemplateService util.ChartTemplateService - mergeUtil util.MergeUtil - repositoryService repository.ServiceClient - refChartDir RefChartDir - defaultChart DefaultChart - chartRefRepository chartRepoRepository.ChartRefRepository - envOverrideRepository chartConfig.EnvConfigOverrideRepository - pipelineConfigRepository chartConfig.PipelineConfigRepository - configMapRepository chartConfig.ConfigMapRepository - environmentRepository repository2.EnvironmentRepository - pipelineRepository pipelineConfig.PipelineRepository - appLevelMetricsRepository repository3.AppLevelMetricsRepository - client *http.Client - appRepository app.AppRepository + bulkUpdateRepository bulkUpdate.BulkUpdateRepository + chartRepository chartRepoRepository.ChartRepository + logger *zap.SugaredLogger + repoRepository chartRepoRepository.ChartRepoRepository + chartTemplateService util.ChartTemplateService + mergeUtil util.MergeUtil + repositoryService repository.ServiceClient + refChartDir RefChartDir + defaultChart DefaultChart + chartRefRepository chartRepoRepository.ChartRefRepository + envOverrideRepository chartConfig.EnvConfigOverrideRepository + pipelineConfigRepository chartConfig.PipelineConfigRepository + configMapRepository chartConfig.ConfigMapRepository + environmentRepository repository2.EnvironmentRepository + pipelineRepository pipelineConfig.PipelineRepository + appLevelMetricsRepository repository3.AppLevelMetricsRepository + envLevelAppMetricsRepository repository3.EnvLevelAppMetricsRepository + client *http.Client + appRepository app.AppRepository + deploymentTemplateHistoryService history.DeploymentTemplateHistoryService + configMapHistoryService history.ConfigMapHistoryService } func NewBulkUpdateServiceImpl(bulkUpdateRepository bulkUpdate.BulkUpdateRepository, @@ -146,28 +152,33 @@ func NewBulkUpdateServiceImpl(bulkUpdateRepository bulkUpdate.BulkUpdateReposito environmentRepository repository2.EnvironmentRepository, pipelineRepository pipelineConfig.PipelineRepository, appLevelMetricsRepository repository3.AppLevelMetricsRepository, + envLevelAppMetricsRepository repository3.EnvLevelAppMetricsRepository, client *http.Client, appRepository app.AppRepository, -) *BulkUpdateServiceImpl { + deploymentTemplateHistoryService history.DeploymentTemplateHistoryService, + configMapHistoryService history.ConfigMapHistoryService) *BulkUpdateServiceImpl { return &BulkUpdateServiceImpl{ - bulkUpdateRepository: bulkUpdateRepository, - chartRepository: chartRepository, - logger: logger, - chartTemplateService: chartTemplateService, - repoRepository: repoRepository, - mergeUtil: mergeUtil, - refChartDir: refChartDir, - defaultChart: defaultChart, - repositoryService: repositoryService, - chartRefRepository: chartRefRepository, - envOverrideRepository: envOverrideRepository, - pipelineConfigRepository: pipelineConfigRepository, - configMapRepository: configMapRepository, - environmentRepository: environmentRepository, - pipelineRepository: pipelineRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - client: client, - appRepository: appRepository, + bulkUpdateRepository: bulkUpdateRepository, + chartRepository: chartRepository, + logger: logger, + chartTemplateService: chartTemplateService, + repoRepository: repoRepository, + mergeUtil: mergeUtil, + refChartDir: refChartDir, + defaultChart: defaultChart, + repositoryService: repositoryService, + chartRefRepository: chartRefRepository, + envOverrideRepository: envOverrideRepository, + pipelineConfigRepository: pipelineConfigRepository, + configMapRepository: configMapRepository, + environmentRepository: environmentRepository, + pipelineRepository: pipelineRepository, + appLevelMetricsRepository: appLevelMetricsRepository, + envLevelAppMetricsRepository: envLevelAppMetricsRepository, + client: client, + appRepository: appRepository, + deploymentTemplateHistoryService: deploymentTemplateHistoryService, + configMapHistoryService: configMapHistoryService, } } @@ -439,6 +450,21 @@ func (impl BulkUpdateServiceImpl) BulkUpdateDeploymentTemplate(bulkUpdatePayload Message: "Updated Successfully", } deploymentTemplateBulkUpdateResponse.Successful = append(deploymentTemplateBulkUpdateResponse.Successful, bulkUpdateSuccessResponse) + + //creating history entry for deployment template + appLevelAppMetricsEnabled := false + appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(chart.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting app level metrics app level", "error", err) + } else if err == nil { + appLevelAppMetricsEnabled = appLevelMetrics.AppMetrics + } + chart.GlobalOverride = modified + chart.Values = modified + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromGlobalTemplate(chart, nil, appLevelAppMetricsEnabled) + if err != nil { + impl.logger.Errorw("error in creating entry for deployment template history", "err", err, "chart", chart) + } } } } @@ -486,6 +512,27 @@ func (impl BulkUpdateServiceImpl) BulkUpdateDeploymentTemplate(bulkUpdatePayload Message: "Updated Successfully", } deploymentTemplateBulkUpdateResponse.Successful = append(deploymentTemplateBulkUpdateResponse.Successful, bulkUpdateSuccessResponse) + + //creating history entry for deployment template + envLevelAppMetricsEnabled := false + envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(chartEnv.Chart.AppId, chartEnv.TargetEnvironment) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", chartEnv.Chart.AppId, "envId", chartEnv.TargetEnvironment) + } else if err == pg.ErrNoRows { + appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(chartEnv.Chart.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", chartEnv.Chart.AppId) + } else if err == nil { + envLevelAppMetricsEnabled = appLevelAppMetrics.AppMetrics + } + } else { + envLevelAppMetricsEnabled = *envLevelAppMetrics.AppMetrics + } + chartEnv.EnvOverrideValues = modified + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(chartEnv, nil, envLevelAppMetricsEnabled, 0) + if err != nil { + impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", chartEnv) + } } } } @@ -564,6 +611,11 @@ func (impl BulkUpdateServiceImpl) BulkUpdateConfigMap(bulkUpdatePayload *BulkUpd messageCmNamesMap[fmt.Sprintf("Error in updating in db : %s", err.Error())] = messageCmNamesMap["Updated Successfully"] delete(messageCmNamesMap, "Updated Successfully") } + //creating history for config map history + err = impl.configMapHistoryService.CreateHistoryFromAppLevelConfig(configMapAppModel, repository4.CONFIGMAP_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for configmap history", "err", err) + } } if len(messageCmNamesMap) != 0 { appDetailsById, _ := impl.appRepository.FindById(configMapAppModel.AppId) @@ -651,6 +703,11 @@ func (impl BulkUpdateServiceImpl) BulkUpdateConfigMap(bulkUpdatePayload *BulkUpd messageCmNamesMap[fmt.Sprintf("Error in updating in db : %s", err.Error())] = messageCmNamesMap["Updated Successfully"] delete(messageCmNamesMap, "Updated Successfully") } + //creating history for config map history + err = impl.configMapHistoryService.CreateHistoryFromEnvLevelConfig(configMapEnvModel, repository4.CONFIGMAP_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for configmap history", "err", err) + } } if len(messageCmNamesMap) != 0 { appDetailsById, _ := impl.appRepository.FindById(configMapEnvModel.AppId) @@ -751,6 +808,11 @@ func (impl BulkUpdateServiceImpl) BulkUpdateSecret(bulkUpdatePayload *BulkUpdate messageSecretNamesMap[fmt.Sprintf("Error in updating in db : %s", err.Error())] = messageSecretNamesMap["Updated Successfully"] delete(messageSecretNamesMap, "Updated Successfully") } + //creating history for config map history + err = impl.configMapHistoryService.CreateHistoryFromAppLevelConfig(secretAppModel, repository4.SECRET_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for secret history", "err", err) + } } if len(messageSecretNamesMap) != 0 { appDetailsById, _ := impl.appRepository.FindById(secretAppModel.AppId) @@ -838,6 +900,11 @@ func (impl BulkUpdateServiceImpl) BulkUpdateSecret(bulkUpdatePayload *BulkUpdate messageSecretNamesMap[fmt.Sprintf("Error in updating in db : %s", err.Error())] = messageSecretNamesMap["Updated Successfully"] delete(messageSecretNamesMap, "Updated Successfully") } + //creating history for config map history + err = impl.configMapHistoryService.CreateHistoryFromEnvLevelConfig(secretEnvModel, repository4.SECRET_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for secret history", "err", err) + } } if len(messageSecretNamesMap) != 0 { appDetailsById, _ := impl.appRepository.FindById(secretEnvModel.AppId) diff --git a/pkg/pipeline/ChartService.go b/pkg/pipeline/ChartService.go index 010a1813a7..4b1d0046a1 100644 --- a/pkg/pipeline/ChartService.go +++ b/pkg/pipeline/ChartService.go @@ -22,12 +22,14 @@ import ( "context" "encoding/json" "fmt" - chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/internal/sql/repository/app" + chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" + "github.com/devtron-labs/devtron/pkg/pipeline/history" repository4 "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/sql" + dirCopy "github.com/otiai10/copy" "io/ioutil" "net/http" "os" @@ -128,25 +130,32 @@ type ChartService interface { DeploymentTemplateValidate(templatejson interface{}, chartRefId int) (bool, error) JsonSchemaExtractFromFile(chartRefId int) (map[string]interface{}, error) GetSchemaAndReadmeForTemplateByChartRefId(chartRefId int) (schema []byte, readme []byte, err error) + ExtractChartIfMissing(chartData []byte, refChartDir string, location string) (*ChartDataInfo, error) + CheckChartExists(chartRefId int) error + GetLocationFromChartNameAndVersion(chartName string, chartVersion string) string + ValidateUploadedFileFormat(fileName string) error + ReadChartMetaDataForLocation(chartDir string, fileName string) (string, string, error) } type ChartServiceImpl struct { - chartRepository chartRepoRepository.ChartRepository - logger *zap.SugaredLogger - repoRepository chartRepoRepository.ChartRepoRepository - chartTemplateService util.ChartTemplateService - pipelineGroupRepository app.AppRepository - mergeUtil util.MergeUtil - repositoryService repository.ServiceClient - refChartDir RefChartDir - defaultChart DefaultChart - chartRefRepository chartRepoRepository.ChartRefRepository - envOverrideRepository chartConfig.EnvConfigOverrideRepository - pipelineConfigRepository chartConfig.PipelineConfigRepository - configMapRepository chartConfig.ConfigMapRepository - environmentRepository repository4.EnvironmentRepository - pipelineRepository pipelineConfig.PipelineRepository - appLevelMetricsRepository repository3.AppLevelMetricsRepository - client *http.Client + chartRepository chartRepoRepository.ChartRepository + logger *zap.SugaredLogger + repoRepository chartRepoRepository.ChartRepoRepository + chartTemplateService util.ChartTemplateService + pipelineGroupRepository app.AppRepository + mergeUtil util.MergeUtil + repositoryService repository.ServiceClient + refChartDir RefChartDir + defaultChart DefaultChart + chartRefRepository chartRepoRepository.ChartRefRepository + envOverrideRepository chartConfig.EnvConfigOverrideRepository + pipelineConfigRepository chartConfig.PipelineConfigRepository + configMapRepository chartConfig.ConfigMapRepository + environmentRepository repository4.EnvironmentRepository + pipelineRepository pipelineConfig.PipelineRepository + appLevelMetricsRepository repository3.AppLevelMetricsRepository + envLevelAppMetricsRepository repository3.EnvLevelAppMetricsRepository + client *http.Client + deploymentTemplateHistoryService history.DeploymentTemplateHistoryService } func NewChartServiceImpl(chartRepository chartRepoRepository.ChartRepository, @@ -165,27 +174,29 @@ func NewChartServiceImpl(chartRepository chartRepoRepository.ChartRepository, environmentRepository repository4.EnvironmentRepository, pipelineRepository pipelineConfig.PipelineRepository, appLevelMetricsRepository repository3.AppLevelMetricsRepository, + envLevelAppMetricsRepository repository3.EnvLevelAppMetricsRepository, client *http.Client, - CustomFormatCheckers *util2.CustomFormatCheckers, -) *ChartServiceImpl { + deploymentTemplateHistoryService history.DeploymentTemplateHistoryService) *ChartServiceImpl { return &ChartServiceImpl{ - chartRepository: chartRepository, - logger: logger, - chartTemplateService: chartTemplateService, - repoRepository: repoRepository, - pipelineGroupRepository: pipelineGroupRepository, - mergeUtil: mergeUtil, - refChartDir: refChartDir, - defaultChart: defaultChart, - repositoryService: repositoryService, - chartRefRepository: chartRefRepository, - envOverrideRepository: envOverrideRepository, - pipelineConfigRepository: pipelineConfigRepository, - configMapRepository: configMapRepository, - environmentRepository: environmentRepository, - pipelineRepository: pipelineRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - client: client, + chartRepository: chartRepository, + logger: logger, + chartTemplateService: chartTemplateService, + repoRepository: repoRepository, + pipelineGroupRepository: pipelineGroupRepository, + mergeUtil: mergeUtil, + refChartDir: refChartDir, + defaultChart: defaultChart, + repositoryService: repositoryService, + chartRefRepository: chartRefRepository, + envOverrideRepository: envOverrideRepository, + pipelineConfigRepository: pipelineConfigRepository, + configMapRepository: configMapRepository, + environmentRepository: environmentRepository, + pipelineRepository: pipelineRepository, + appLevelMetricsRepository: appLevelMetricsRepository, + envLevelAppMetricsRepository: envLevelAppMetricsRepository, + client: client, + deploymentTemplateHistoryService: deploymentTemplateHistoryService, } } @@ -209,6 +220,12 @@ func (impl ChartServiceImpl) GetSchemaAndReadmeForTemplateByChartRefId(chartRefI } func (impl ChartServiceImpl) GetAppOverrideForDefaultTemplate(chartRefId int) (map[string]interface{}, error) { + err := impl.CheckChartExists(chartRefId) + if err != nil { + impl.logger.Errorw("error in getting missing chart for chartRefId", "err", err, "chartRefId") + return nil, err + } + refChart, _, err, _ := impl.getRefChart(TemplateRequest{ChartRefId: chartRefId}) if err != nil { return nil, err @@ -246,6 +263,11 @@ type AppMetricsEnabled struct { } func (impl ChartServiceImpl) Create(templateRequest TemplateRequest, ctx context.Context) (*TemplateRequest, error) { + err := impl.CheckChartExists(templateRequest.ChartRefId) + if err != nil { + impl.logger.Errorw("error in getting missing chart for chartRefId", "err", err, "chartRefId") + return nil, err + } chartMeta, err := impl.getChartMetaData(templateRequest) if err != nil { return nil, err @@ -376,12 +398,20 @@ func (impl ChartServiceImpl) Create(templateRequest TemplateRequest, ctx context return nil, err } + //creating history entry for deployment template + //TODO : remove default value(false) app metrics flag for history when app metrics request is combined with template save request + appLevelAppMetricsEnabled := false appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(templateRequest.AppId) if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in app metrics app level flag", "error", err) + impl.logger.Errorw("error in getting app level metrics app level", "error", err) + } else if err == nil { + appLevelAppMetricsEnabled = appLevelMetrics.AppMetrics + } + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromGlobalTemplate(chart, nil, appLevelAppMetricsEnabled) + if err != nil { + impl.logger.Errorw("error in creating entry for deployment template history", "err", err, "chart", chart) return nil, err } - if !(chartMajorVersion >= 3 && chartMinorVersion >= 1) { appMetricsRequest := AppMetricEnableDisableRequest{UserId: templateRequest.UserId, AppId: templateRequest.AppId, IsAppMetricsEnabled: false} _, err = impl.updateAppLevelMetrics(&appMetricsRequest) @@ -396,6 +426,12 @@ func (impl ChartServiceImpl) Create(templateRequest TemplateRequest, ctx context } func (impl ChartServiceImpl) CreateChartFromEnvOverride(templateRequest TemplateRequest, ctx context.Context) (*TemplateRequest, error) { + err := impl.CheckChartExists(templateRequest.ChartRefId) + if err != nil { + impl.logger.Errorw("error in getting missing chart for chartRefId", "err", err, "chartRefId") + return nil, err + } + chartMeta, err := impl.getChartMetaData(templateRequest) if err != nil { return nil, err @@ -492,10 +528,18 @@ func (impl ChartServiceImpl) CreateChartFromEnvOverride(templateRequest Template impl.logger.Errorw("error in saving chart ", "chart", chart, "error", err) return nil, err } - + //creating history entry for deployment template + //TODO : remove default value(false) app metrics flag for history when app metrics request is combined with template save request + appLevelAppMetricsEnabled := false appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(templateRequest.AppId) if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in app metrics app level flag", "error", err) + impl.logger.Errorw("error in getting app level metrics app level", "error", err) + } else if err == nil { + appLevelAppMetricsEnabled = appLevelMetrics.AppMetrics + } + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromGlobalTemplate(chart, nil, appLevelAppMetricsEnabled) + if err != nil { + impl.logger.Errorw("error in creating entry for deployment template history", "err", err, "chart", chart) return nil, err } chartVal, err := impl.chartAdaptor(chart, appLevelMetrics) @@ -759,7 +803,20 @@ func (impl ChartServiceImpl) UpdateAppOverride(templateRequest *TemplateRequest) return nil, err } } - + //creating history entry for deployment template + //TODO : remove fetching and setting app metrics flag for history when app metrics update request is combined with template update request + appLevelAppMetricsEnabled := false + appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(template.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting app level metrics app level", "error", err) + } else if err == nil { + appLevelAppMetricsEnabled = appLevelMetrics.AppMetrics + } + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromGlobalTemplate(template, nil, appLevelAppMetricsEnabled) + if err != nil { + impl.logger.Errorw("error in creating entry for deployment template history", "err", err, "chart", template) + return nil, err + } return templateRequest, nil } @@ -847,6 +904,18 @@ type chartRefResponse struct { LatestEnvChartRef int `json:"latestEnvChartRef,omitempty"` } +type ChartYamlStruct struct { + Name string `yaml:"name"` + Version string `yaml:"version"` +} + +type ChartDataInfo struct { + ChartLocation string `json:"chartLocation"` + ChartName string `json:"chartName"` + ChartVersion string `json:"chartVersion"` + TemporaryFolder string `json:"temporaryFolder"` +} + func (impl ChartServiceImpl) ChartRefAutocomplete() ([]chartRef, error) { var chartRefs []chartRef results, err := impl.chartRefRepository.GetAll() @@ -980,6 +1049,29 @@ func (impl ChartServiceImpl) UpgradeForApp(appId int, chartRefId int, newAppOver impl.logger.Errorw("error in creating env config", "data", envOverride, "error", err) return false, err } + //creating history entry for deployment template + //TODO : remove fetching and setting app metrics flag for history when app metrics update request is combined with template update request + isAppMetricsEnabled := false + envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(appId, envOverrideNew.TargetEnvironment) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", appId, "envId", envOverrideNew.TargetEnvironment) + return false, err + } else if err == pg.ErrNoRows { + appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", appId) + return false, err + } else if err == nil { + isAppMetricsEnabled = appLevelAppMetrics.AppMetrics + } + } else { + isAppMetricsEnabled = *envLevelAppMetrics.AppMetrics + } + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(envOverrideNew, nil, isAppMetricsEnabled, 0) + if err != nil { + impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", envOverrideNew) + return false, err + } } return true, nil @@ -1027,23 +1119,22 @@ func (impl ChartServiceImpl) filterDeploymentTemplateForBackground(deploymentTem } func (impl ChartServiceImpl) AppMetricsEnableDisable(appMetricRequest AppMetricEnableDisableRequest) (*AppMetricEnableDisableRequest, error) { - + currentChart, err := impl.chartRepository.FindLatestChartForAppByAppId(appMetricRequest.AppId) + if err != nil && pg.ErrNoRows != err { + impl.logger.Error(err) + return nil, err + } + if pg.ErrNoRows == err { + impl.logger.Errorw("no chart configured for this app", "appId", appMetricRequest.AppId) + err = &util.ApiError{ + HttpStatusCode: http.StatusNotFound, + InternalMessage: "no chart configured for this app", + UserMessage: "no chart configured for this app", + } + return nil, err + } // validate app metrics compatibility if appMetricRequest.IsAppMetricsEnabled == true { - currentChart, err := impl.chartRepository.FindLatestChartForAppByAppId(appMetricRequest.AppId) - if err != nil && pg.ErrNoRows != err { - impl.logger.Error(err) - return nil, err - } - if pg.ErrNoRows == err { - impl.logger.Errorw("no chart configured for this app", "appId", appMetricRequest.AppId) - err = &util.ApiError{ - HttpStatusCode: http.StatusNotFound, - InternalMessage: "no chart configured for this app", - UserMessage: "no chart configured for this app", - } - return nil, err - } chartMajorVersion, chartMinorVersion, err := util2.ExtractChartVersion(currentChart.ChartVersion) if err != nil { impl.logger.Errorw("chart version parsing", "err", err) @@ -1058,13 +1149,18 @@ func (impl ChartServiceImpl) AppMetricsEnableDisable(appMetricRequest AppMetricE return nil, err } } - //update or create app level app metrics appLevelMetrics, err := impl.updateAppLevelMetrics(&appMetricRequest) if err != nil { impl.logger.Errorw("error in saving app level metrics flag", "error", err) return nil, err } + //creating history entry for deployment template + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromGlobalTemplate(currentChart, nil, appMetricRequest.IsAppMetricsEnabled) + if err != nil { + impl.logger.Errorw("error in creating entry for deployment template history", "err", err, "chart", currentChart) + return nil, err + } if appLevelMetrics.Id > 0 { return &appMetricRequest, nil } @@ -1167,3 +1263,149 @@ func (impl ChartServiceImpl) JsonSchemaExtractFromFile(chartRefId int) (map[stri return schemajson, nil } } + +func (impl ChartServiceImpl) CheckChartExists(chartRefId int) error { + chartRef, err := impl.chartRefRepository.FindById(chartRefId) + if err != nil { + impl.logger.Errorw("error in finding ref chart by id", "err", err) + return err + } + refChartDir := filepath.Clean(filepath.Join(string(impl.refChartDir), chartRef.Location)) + if _, err := os.Stat(refChartDir); os.IsNotExist(err) { + chartInfo, err := impl.ExtractChartIfMissing(chartRef.ChartData, string(impl.refChartDir), chartRef.Location) + if chartInfo.TemporaryFolder != "" { + err1 := os.RemoveAll(chartInfo.TemporaryFolder) + if err1 != nil { + impl.logger.Errorw("error in deleting temp dir ", "err", err) + } + } + return err + } + return nil +} + +func (impl *ChartServiceImpl) GetLocationFromChartNameAndVersion(chartName string, chartVersion string) string { + var chartLocation string + + chartname := strings.ReplaceAll(chartName, ".", "-") + chartname = strings.ReplaceAll(chartname, " ", "_") + chartversion := strings.ReplaceAll(chartVersion, ".", "-") + if !strings.Contains(chartname, chartversion) { + chartLocation = chartname + "_" + chartversion + } else { + chartLocation = chartname + } + return chartLocation +} + +func (impl *ChartServiceImpl) ValidateUploadedFileFormat(fileName string) error { + if !strings.HasSuffix(fileName, ".tar.gz") { + return errors.New("unsupported format") + } + return nil +} + +func (impl ChartServiceImpl) ReadChartMetaDataForLocation(chartDir string, fileName string) (string, string, error) { + chartLocation := filepath.Clean(filepath.Join(chartDir, fileName)) + + chartYamlPath := filepath.Clean(filepath.Join(chartLocation, "Chart.yaml")) + if _, err := os.Stat(chartYamlPath); os.IsNotExist(err) { + return "", "", fmt.Errorf("Chart.yaml file not present in the directory") + } + + data, err := ioutil.ReadFile(chartYamlPath) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + return "", "", err + } + //println(data) + var chartYaml ChartYamlStruct + err = yaml.Unmarshal(data, &chartYaml) + if err != nil { + impl.logger.Errorw("Unmarshal error of yaml file", "err", err) + return "", "", err + } + if chartYaml.Name == "" || chartYaml.Version == "" { + impl.logger.Errorw("Missing values in yaml file either name or version", "err", err) + return "", "", errors.New("Missing values in yaml file either name or version") + } + return chartYaml.Name, chartYaml.Version, nil +} + +func (impl ChartServiceImpl) ExtractChartIfMissing(chartData []byte, refChartDir string, location string) (*ChartDataInfo, error) { + binaryDataReader := bytes.NewReader(chartData) + dir := impl.chartTemplateService.GetDir() + chartInfo := &ChartDataInfo{ + ChartName: "", + ChartVersion: "", + ChartLocation: "", + TemporaryFolder: "", + } + temporaryChartWorkingDir := filepath.Clean(filepath.Join(refChartDir, dir)) + err := os.MkdirAll(temporaryChartWorkingDir, os.ModePerm) + if err != nil { + impl.logger.Errorw("error in creating directory, CallbackConfigMap", "err", err) + return chartInfo, err + } + chartInfo.TemporaryFolder = temporaryChartWorkingDir + err = util2.ExtractTarGz(binaryDataReader, temporaryChartWorkingDir) + if err != nil { + impl.logger.Errorw("error in extracting binary data of charts", "err", err) + return chartInfo, err + } + + var chartLocation string + var chartName string + var chartVersion string + var fileName string + + files, err := ioutil.ReadDir(temporaryChartWorkingDir) + if err != nil { + impl.logger.Errorw("error in reading err dir", "err", err) + return chartInfo, err + } + + fileName = files[0].Name() + if strings.HasPrefix(files[0].Name(), ".") { + fileName = files[1].Name() + } + + currentChartWorkingDir := filepath.Clean(filepath.Join(temporaryChartWorkingDir, fileName)) + + if location == "" { + chartName, chartVersion, err = impl.ReadChartMetaDataForLocation(temporaryChartWorkingDir, fileName) + if err != nil { + impl.logger.Errorw("Chart yaml file not found") + return chartInfo, err + } + exists, err := impl.chartRefRepository.CheckIfDataExists(chartName, chartVersion) + if exists { + impl.logger.Errorw("request err, chart name and version exists already in the database") + return chartInfo, errors.New("chart name and version exists already in the database") + } + if err != nil { + impl.logger.Errorw("Error in searching the database") + return chartInfo, err + } + chartLocation = impl.GetLocationFromChartNameAndVersion(chartName, chartVersion) + if err != nil { + impl.logger.Errorw("error in fetching name and version in Chart yaml", "err", err) + return chartInfo, err + } + err = util2.CheckForMissingFiles(currentChartWorkingDir) + if err != nil { + impl.logger.Errorw("Missing files in the folder", "err", err) + return chartInfo, err + } + location = chartLocation + } + err = dirCopy.Copy(currentChartWorkingDir, filepath.Clean(filepath.Join(refChartDir, location))) + if err != nil { + impl.logger.Errorw("error in copying chart from temp dir to ref chart dir", "err", err) + return chartInfo, err + } + chartInfo.ChartLocation = location + chartInfo.ChartName = chartName + chartInfo.ChartVersion = chartVersion + return chartInfo, nil +} diff --git a/pkg/pipeline/CiService.go b/pkg/pipeline/CiService.go index 3e196a1f25..900ff334ba 100644 --- a/pkg/pipeline/CiService.go +++ b/pkg/pipeline/CiService.go @@ -19,6 +19,7 @@ package pipeline import ( "fmt" + "github.com/devtron-labs/devtron/pkg/pipeline/history" "path/filepath" "strconv" "time" @@ -39,29 +40,34 @@ type CiService interface { } type CiServiceImpl struct { - Logger *zap.SugaredLogger - workflowService WorkflowService - ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository - ciWorkflowRepository pipelineConfig.CiWorkflowRepository - ciConfig *CiConfig - eventClient client.EventClient - eventFactory client.EventFactory - mergeUtil *util.MergeUtil - ciPipelineRepository pipelineConfig.CiPipelineRepository + Logger *zap.SugaredLogger + workflowService WorkflowService + ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository + ciWorkflowRepository pipelineConfig.CiWorkflowRepository + ciConfig *CiConfig + eventClient client.EventClient + eventFactory client.EventFactory + mergeUtil *util.MergeUtil + ciPipelineRepository pipelineConfig.CiPipelineRepository + prePostCiScriptHistoryService history.PrePostCiScriptHistoryService } -func NewCiServiceImpl(Logger *zap.SugaredLogger, workflowService WorkflowService, ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository, - ciWorkflowRepository pipelineConfig.CiWorkflowRepository, ciConfig *CiConfig, eventClient client.EventClient, eventFactory client.EventFactory, mergeUtil *util.MergeUtil, ciPipelineRepository pipelineConfig.CiPipelineRepository) *CiServiceImpl { +func NewCiServiceImpl(Logger *zap.SugaredLogger, workflowService WorkflowService, + ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository, + ciWorkflowRepository pipelineConfig.CiWorkflowRepository, ciConfig *CiConfig, eventClient client.EventClient, + eventFactory client.EventFactory, mergeUtil *util.MergeUtil, ciPipelineRepository pipelineConfig.CiPipelineRepository, + prePostCiScriptHistoryService history.PrePostCiScriptHistoryService) *CiServiceImpl { return &CiServiceImpl{ - Logger: Logger, - workflowService: workflowService, - ciPipelineMaterialRepository: ciPipelineMaterialRepository, - ciWorkflowRepository: ciWorkflowRepository, - ciConfig: ciConfig, - eventClient: eventClient, - eventFactory: eventFactory, - mergeUtil: mergeUtil, - ciPipelineRepository: ciPipelineRepository, + Logger: Logger, + workflowService: workflowService, + ciPipelineMaterialRepository: ciPipelineMaterialRepository, + ciWorkflowRepository: ciWorkflowRepository, + ciConfig: ciConfig, + eventClient: eventClient, + eventFactory: eventFactory, + mergeUtil: mergeUtil, + ciPipelineRepository: ciPipelineRepository, + prePostCiScriptHistoryService: prePostCiScriptHistoryService, } } @@ -129,6 +135,14 @@ func (impl *CiServiceImpl) TriggerCiPipeline(trigger Trigger) (int, error) { impl.Logger.Debugw("ci triggered", "wf name ", createdWf.Name, " pipeline ", trigger.PipelineId) middleware.CiTriggerCounter.WithLabelValues(strconv.Itoa(pipeline.AppId), strconv.Itoa(trigger.PipelineId)).Inc() go impl.WriteCITriggerEvent(trigger, pipeline, workflowRequest) + //creating entry of ci script history for build details + for _, ciPipelineScript := range ciPipelineScripts { + _, err = impl.prePostCiScriptHistoryService.CreatePrePostCiScriptHistory(ciPipelineScript, nil, true, trigger.TriggeredBy, time.Now()) + if err != nil { + impl.Logger.Errorw("error in creating ci script history entry", "err", err, "ciPipelineScript", ciPipelineScript) + return 0, err + } + } return savedCiWf.Id, err } diff --git a/pkg/pipeline/ConfigMapService.go b/pkg/pipeline/ConfigMapService.go index 79d1bb5224..226e646c5d 100644 --- a/pkg/pipeline/ConfigMapService.go +++ b/pkg/pipeline/ConfigMapService.go @@ -25,6 +25,8 @@ import ( "github.com/devtron-labs/devtron/internal/util" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/pkg/commonService" + history2 "github.com/devtron-labs/devtron/pkg/pipeline/history" + "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" util2 "github.com/devtron-labs/devtron/util" "github.com/go-pg/pg" "go.uber.org/zap" @@ -149,6 +151,7 @@ type ConfigMapServiceImpl struct { environmentConfigRepository chartConfig.EnvConfigOverrideRepository commonService commonService.CommonService appRepository app.AppRepository + configMapHistoryService history2.ConfigMapHistoryService } func NewConfigMapServiceImpl(chartRepository chartRepoRepository.ChartRepository, @@ -157,7 +160,8 @@ func NewConfigMapServiceImpl(chartRepository chartRepoRepository.ChartRepository mergeUtil util.MergeUtil, pipelineConfigRepository chartConfig.PipelineConfigRepository, configMapRepository chartConfig.ConfigMapRepository, environmentConfigRepository chartConfig.EnvConfigOverrideRepository, - commonService commonService.CommonService, appRepository app.AppRepository) *ConfigMapServiceImpl { + commonService commonService.CommonService, appRepository app.AppRepository, + configMapHistoryService history2.ConfigMapHistoryService) *ConfigMapServiceImpl { return &ConfigMapServiceImpl{ chartRepository: chartRepository, logger: logger, @@ -168,6 +172,7 @@ func NewConfigMapServiceImpl(chartRepository chartRepoRepository.ChartRepository environmentConfigRepository: environmentConfigRepository, commonService: commonService, appRepository: appRepository, + configMapHistoryService: configMapHistoryService, } } @@ -201,8 +206,9 @@ func (impl ConfigMapServiceImpl) CMGlobalAddUpdate(configMapRequest *ConfigDataR impl.logger.Errorw("error in validating", "error", err) return configMapRequest, err } + var model *chartConfig.ConfigMapAppModel if configMapRequest.Id > 0 { - model, err := impl.configMapRepository.GetByIdAppLevel(configMapRequest.Id) + model, err = impl.configMapRepository.GetByIdAppLevel(configMapRequest.Id) if err != nil { impl.logger.Errorw("error while fetching from db", "error", err) return nil, err @@ -258,7 +264,7 @@ func (impl ConfigMapServiceImpl) CMGlobalAddUpdate(configMapRequest *ConfigDataR if err != nil { return nil, err } - model := &chartConfig.ConfigMapAppModel{ + model = &chartConfig.ConfigMapAppModel{ AppId: configMapRequest.AppId, ConfigMapData: string(configDataByte), } @@ -274,7 +280,11 @@ func (impl ConfigMapServiceImpl) CMGlobalAddUpdate(configMapRequest *ConfigDataR } configMapRequest.Id = configMap.Id } - + err = impl.configMapHistoryService.CreateHistoryFromAppLevelConfig(model, repository.CONFIGMAP_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for configmap history", "err", err) + return nil, err + } return configMapRequest, nil } @@ -324,8 +334,9 @@ func (impl ConfigMapServiceImpl) CMEnvironmentAddUpdate(configMapRequest *Config impl.logger.Errorw("error in validating", "error", err) return configMapRequest, err } + var model *chartConfig.ConfigMapEnvModel if configMapRequest.Id > 0 { - model, err := impl.configMapRepository.GetByIdEnvLevel(configMapRequest.Id) + model, err = impl.configMapRepository.GetByIdEnvLevel(configMapRequest.Id) if err != nil { impl.logger.Errorw("error while fetching from db", "error", err) return nil, err @@ -381,7 +392,7 @@ func (impl ConfigMapServiceImpl) CMEnvironmentAddUpdate(configMapRequest *Config if err != nil { return nil, err } - model := &chartConfig.ConfigMapEnvModel{ + model = &chartConfig.ConfigMapEnvModel{ AppId: configMapRequest.AppId, EnvironmentId: configMapRequest.EnvironmentId, ConfigMapData: string(configDataByte), @@ -398,7 +409,11 @@ func (impl ConfigMapServiceImpl) CMEnvironmentAddUpdate(configMapRequest *Config } configMapRequest.Id = configMap.Id } - + err = impl.configMapHistoryService.CreateHistoryFromEnvLevelConfig(model, repository.CONFIGMAP_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for CM/CS history in bulk update", "err", err) + return nil, err + } return configMapRequest, nil } @@ -504,9 +519,9 @@ func (impl ConfigMapServiceImpl) CSGlobalAddUpdate(configMapRequest *ConfigDataR impl.logger.Errorw("error in validating", "error", err) return configMapRequest, err } - + var model *chartConfig.ConfigMapAppModel if configMapRequest.Id > 0 { - model, err := impl.configMapRepository.GetByIdAppLevel(configMapRequest.Id) + model, err = impl.configMapRepository.GetByIdAppLevel(configMapRequest.Id) if err != nil { impl.logger.Errorw("error while fetching from db", "error", err) return nil, err @@ -564,7 +579,7 @@ func (impl ConfigMapServiceImpl) CSGlobalAddUpdate(configMapRequest *ConfigDataR if err != nil { return nil, err } - model := &chartConfig.ConfigMapAppModel{ + model = &chartConfig.ConfigMapAppModel{ AppId: configMapRequest.AppId, SecretData: string(secretDataByte), } @@ -580,7 +595,11 @@ func (impl ConfigMapServiceImpl) CSGlobalAddUpdate(configMapRequest *ConfigDataR } configMapRequest.Id = secret.Id } - + err = impl.configMapHistoryService.CreateHistoryFromAppLevelConfig(model, repository.SECRET_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for secret history", "err", err) + return nil, err + } return configMapRequest, nil } @@ -673,9 +692,9 @@ func (impl ConfigMapServiceImpl) CSEnvironmentAddUpdate(configMapRequest *Config impl.logger.Errorw("error in validating", "error", err) return configMapRequest, err } - + var model *chartConfig.ConfigMapEnvModel if configMapRequest.Id > 0 { - model, err := impl.configMapRepository.GetByIdEnvLevel(configMapRequest.Id) + model, err = impl.configMapRepository.GetByIdEnvLevel(configMapRequest.Id) if err != nil { impl.logger.Errorw("error while fetching from db", "error", err) return nil, err @@ -733,7 +752,7 @@ func (impl ConfigMapServiceImpl) CSEnvironmentAddUpdate(configMapRequest *Config if err != nil { return nil, err } - model := &chartConfig.ConfigMapEnvModel{ + model = &chartConfig.ConfigMapEnvModel{ AppId: configMapRequest.AppId, EnvironmentId: configMapRequest.EnvironmentId, SecretData: string(secretDataByte), @@ -750,7 +769,11 @@ func (impl ConfigMapServiceImpl) CSEnvironmentAddUpdate(configMapRequest *Config } configMapRequest.Id = configMap.Id } - + err = impl.configMapHistoryService.CreateHistoryFromEnvLevelConfig(model, repository.SECRET_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for CM/CS history in bulk update", "err", err) + return nil, err + } return configMapRequest, nil } @@ -967,6 +990,11 @@ func (impl ConfigMapServiceImpl) CMGlobalDelete(name string, id int, userId int3 impl.logger.Errorw("error while updating at app level", "error", err) return false, err } + err = impl.configMapHistoryService.CreateHistoryFromAppLevelConfig(model, repository.CONFIGMAP_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for configmap history", "err", err) + return false, err + } } else { impl.logger.Debugw("no config map found for delete with this name", "name", name) @@ -1014,6 +1042,11 @@ func (impl ConfigMapServiceImpl) CMEnvironmentDelete(name string, id int, userId impl.logger.Errorw("error while updating at env level", "error", err) return false, err } + err = impl.configMapHistoryService.CreateHistoryFromEnvLevelConfig(model, repository.CONFIGMAP_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for configmap env history", "err", err) + return false, err + } } else { impl.logger.Debugw("no config map found for delete with this name", "name", name) } @@ -1060,6 +1093,11 @@ func (impl ConfigMapServiceImpl) CSGlobalDelete(name string, id int, userId int3 impl.logger.Errorw("error while updating at app level", "error", err) return false, err } + err = impl.configMapHistoryService.CreateHistoryFromAppLevelConfig(model, repository.SECRET_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for secret history", "err", err) + return false, err + } } else { impl.logger.Debugw("no config map found for delete with this name", "name", name) @@ -1107,6 +1145,11 @@ func (impl ConfigMapServiceImpl) CSEnvironmentDelete(name string, id int, userId impl.logger.Errorw("error while updating at env level ", "error", err) return false, err } + err = impl.configMapHistoryService.CreateHistoryFromEnvLevelConfig(model, repository.SECRET_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for secret env history", "err", err) + return false, err + } } else { impl.logger.Debugw("no config map found for delete with this name", "name", name) } @@ -1523,6 +1566,11 @@ func (impl ConfigMapServiceImpl) ConfigSecretGlobalBulkPatch(bulkPatchRequest *B impl.logger.Errorw("error while fetching from db", "error", err) return nil, err } + err = impl.configMapHistoryService.CreateHistoryFromAppLevelConfig(model, repository.CONFIGMAP_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for global CM/CS history in bulk update", "err", err) + return nil, err + } } return bulkPatchRequest, nil } @@ -1608,6 +1656,11 @@ func (impl ConfigMapServiceImpl) ConfigSecretEnvironmentBulkPatch(bulkPatchReque impl.logger.Errorw("error while fetching from db", "error", err) return nil, err } + err = impl.configMapHistoryService.CreateHistoryFromEnvLevelConfig(model, repository.CONFIGMAP_TYPE) + if err != nil { + impl.logger.Errorw("error in creating entry for env CM/CS history in bulk update", "err", err) + return nil, err + } } return bulkPatchRequest, nil } diff --git a/pkg/pipeline/DbPipelineOrchestrator.go b/pkg/pipeline/DbPipelineOrchestrator.go index ee6b402c26..3e6618e783 100644 --- a/pkg/pipeline/DbPipelineOrchestrator.go +++ b/pkg/pipeline/DbPipelineOrchestrator.go @@ -27,6 +27,8 @@ import ( "fmt" app2 "github.com/devtron-labs/devtron/internal/sql/repository/app" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + history3 "github.com/devtron-labs/devtron/pkg/pipeline/history" + repository4 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" "github.com/devtron-labs/devtron/pkg/sql" "github.com/devtron-labs/devtron/pkg/user" repository3 "github.com/devtron-labs/devtron/pkg/user/repository" @@ -63,23 +65,26 @@ type DbPipelineOrchestrator interface { GetCdPipelinesForApp(appId int) (cdPipelines *bean.CdPipelines, err error) GetCdPipelinesForAppAndEnv(appId int, envId int) (cdPipelines *bean.CdPipelines, err error) GetByEnvOverrideId(envOverrideId int) (*bean.CdPipelines, error) + BuildCiPipelineScript(userId int32, ciScript *bean.CiScript, scriptStage string, ciPipeline *bean.CiPipeline) *pipelineConfig.CiPipelineScript } type DbPipelineOrchestratorImpl struct { - appRepository app2.AppRepository - logger *zap.SugaredLogger - materialRepository pipelineConfig.MaterialRepository - pipelineRepository pipelineConfig.PipelineRepository - ciPipelineRepository pipelineConfig.CiPipelineRepository - CiPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository - GitSensorClient gitSensor.GitSensorClient - ciConfig *CiConfig - appWorkflowRepository appWorkflow.AppWorkflowRepository - envRepository repository2.EnvironmentRepository - attributesService attributes.AttributesService - appListingRepository repository.AppListingRepository - appLabelsService app.AppLabelService - userAuthService user.UserAuthService + appRepository app2.AppRepository + logger *zap.SugaredLogger + materialRepository pipelineConfig.MaterialRepository + pipelineRepository pipelineConfig.PipelineRepository + ciPipelineRepository pipelineConfig.CiPipelineRepository + CiPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository + GitSensorClient gitSensor.GitSensorClient + ciConfig *CiConfig + appWorkflowRepository appWorkflow.AppWorkflowRepository + envRepository repository2.EnvironmentRepository + attributesService attributes.AttributesService + appListingRepository repository.AppListingRepository + appLabelsService app.AppLabelService + userAuthService user.UserAuthService + prePostCdScriptHistoryService history3.PrePostCdScriptHistoryService + prePostCiScriptHistoryService history3.PrePostCiScriptHistoryService } func NewDbPipelineOrchestrator( @@ -95,22 +100,26 @@ func NewDbPipelineOrchestrator( attributesService attributes.AttributesService, appListingRepository repository.AppListingRepository, appLabelsService app.AppLabelService, - userAuthService user.UserAuthService) *DbPipelineOrchestratorImpl { + userAuthService user.UserAuthService, + prePostCdScriptHistoryService history3.PrePostCdScriptHistoryService, + prePostCiScriptHistoryService history3.PrePostCiScriptHistoryService) *DbPipelineOrchestratorImpl { return &DbPipelineOrchestratorImpl{ - appRepository: pipelineGroupRepository, - logger: logger, - materialRepository: materialRepository, - pipelineRepository: pipelineRepository, - ciPipelineRepository: ciPipelineRepository, - CiPipelineMaterialRepository: CiPipelineMaterialRepository, - GitSensorClient: GitSensorClient, - ciConfig: ciConfig, - appWorkflowRepository: appWorkflowRepository, - envRepository: envRepository, - attributesService: attributesService, - appListingRepository: appListingRepository, - appLabelsService: appLabelsService, - userAuthService: userAuthService, + appRepository: pipelineGroupRepository, + logger: logger, + materialRepository: materialRepository, + pipelineRepository: pipelineRepository, + ciPipelineRepository: ciPipelineRepository, + CiPipelineMaterialRepository: CiPipelineMaterialRepository, + GitSensorClient: GitSensorClient, + ciConfig: ciConfig, + appWorkflowRepository: appWorkflowRepository, + envRepository: envRepository, + attributesService: attributesService, + appListingRepository: appListingRepository, + appLabelsService: appLabelsService, + userAuthService: userAuthService, + prePostCdScriptHistoryService: prePostCdScriptHistoryService, + prePostCiScriptHistoryService: prePostCiScriptHistoryService, } } @@ -283,7 +292,7 @@ func (impl DbPipelineOrchestratorImpl) PatchMaterialValue(createRequest *bean.Ci func (impl DbPipelineOrchestratorImpl) patchCiScripts(userId int32, pipeline *bean.CiPipeline, existingCiScriptMap map[int]bool, existingCiScriptModelMap map[int]*pipelineConfig.CiPipelineScript, tx *pg.Tx) error { for _, ciScript := range pipeline.BeforeDockerBuildScripts { - ciPipelineScript := impl.buildCiPipelineScript(userId, ciScript, BEFORE_DOCKER_BUILD, pipeline) + ciPipelineScript := impl.BuildCiPipelineScript(userId, ciScript, BEFORE_DOCKER_BUILD, pipeline) if _, ok := existingCiScriptMap[ciScript.Id]; ok { // Update err := impl.ciPipelineRepository.UpdateCiPipelineScript(ciPipelineScript, tx) if err != nil { @@ -298,10 +307,16 @@ func (impl DbPipelineOrchestratorImpl) patchCiScripts(userId int32, pipeline *be return err } } + //creating history entry + _, err := impl.prePostCiScriptHistoryService.CreatePrePostCiScriptHistory(ciPipelineScript, tx, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating ci script history entry", "err", err, "ciPipelineScript", ciPipelineScript) + return err + } } for _, ciScript := range pipeline.AfterDockerBuildScripts { - ciPipelineScript := impl.buildCiPipelineScript(userId, ciScript, AFTER_DOCKER_BUILD, pipeline) + ciPipelineScript := impl.BuildCiPipelineScript(userId, ciScript, AFTER_DOCKER_BUILD, pipeline) if _, ok := existingCiScriptMap[ciScript.Id]; ok { // Update err := impl.ciPipelineRepository.UpdateCiPipelineScript(ciPipelineScript, tx) if err != nil { @@ -316,6 +331,12 @@ func (impl DbPipelineOrchestratorImpl) patchCiScripts(userId int32, pipeline *be return err } } + //creating history entry + _, err := impl.prePostCiScriptHistoryService.CreatePrePostCiScriptHistory(ciPipelineScript, tx, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating ci script history entry", "err", err, "ciPipelineScript", ciPipelineScript) + return err + } } for k, v := range existingCiScriptMap { @@ -425,22 +446,34 @@ func (impl DbPipelineOrchestratorImpl) CreateCiConf(createRequest *bean.CiConfig } for i, ciScript := range ciPipeline.BeforeDockerBuildScripts { - ciPipelineScript := impl.buildCiPipelineScript(createRequest.UserId, ciScript, BEFORE_DOCKER_BUILD, ciPipeline) + ciPipelineScript := impl.BuildCiPipelineScript(createRequest.UserId, ciScript, BEFORE_DOCKER_BUILD, ciPipeline) err = impl.ciPipelineRepository.SaveCiPipelineScript(ciPipelineScript, tx) if err != nil { impl.logger.Errorw("error while saving ci script", "err", err) return nil, err } + //creating history entry + _, err = impl.prePostCiScriptHistoryService.CreatePrePostCiScriptHistory(ciPipelineScript, tx, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating ci script history entry", "err", err, "ciPipelineScript", ciPipelineScript) + return nil, err + } ciPipeline.BeforeDockerBuildScripts[i].Id = ciPipelineScript.Id } for i, ciScript := range ciPipeline.AfterDockerBuildScripts { - ciPipelineScript := impl.buildCiPipelineScript(createRequest.UserId, ciScript, AFTER_DOCKER_BUILD, ciPipeline) + ciPipelineScript := impl.BuildCiPipelineScript(createRequest.UserId, ciScript, AFTER_DOCKER_BUILD, ciPipeline) err = impl.ciPipelineRepository.SaveCiPipelineScript(ciPipelineScript, tx) if err != nil { impl.logger.Errorw("error while saving ci script", "err", err) return nil, err } + //creating history entry + _, err = impl.prePostCiScriptHistoryService.CreatePrePostCiScriptHistory(ciPipelineScript, tx, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating ci script history entry", "err", err, "ciPipelineScript", ciPipelineScript) + return nil, err + } ciPipeline.AfterDockerBuildScripts[i].Id = ciPipelineScript.Id } @@ -527,7 +560,7 @@ func (impl DbPipelineOrchestratorImpl) CreateCiConf(createRequest *bean.CiConfig return createRequest, nil } -func (impl DbPipelineOrchestratorImpl) buildCiPipelineScript(userId int32, ciScript *bean.CiScript, scriptStage string, ciPipeline *bean.CiPipeline) *pipelineConfig.CiPipelineScript { +func (impl DbPipelineOrchestratorImpl) BuildCiPipelineScript(userId int32, ciScript *bean.CiScript, scriptStage string, ciPipeline *bean.CiPipeline) *pipelineConfig.CiPipelineScript { ciPipelineScript := &pipelineConfig.CiPipelineScript{ Name: ciScript.Name, Index: ciScript.Index, @@ -1028,7 +1061,25 @@ func (impl DbPipelineOrchestratorImpl) CreateCDPipelines(pipelineRequest *bean.C AuditLog: sql.AuditLog{UpdatedBy: userId, CreatedBy: userId, UpdatedOn: time.Now(), CreatedOn: time.Now()}, } err = impl.pipelineRepository.Save([]*pipelineConfig.Pipeline{pipeline}, tx) - return pipeline.Id, err + if err != nil { + impl.logger.Errorw("error in saving cd pipeline", "err", err, "pipeline", pipeline) + return 0, err + } + if pipeline.PreStageConfig != "" { + err = impl.prePostCdScriptHistoryService.CreatePrePostCdScriptHistory(pipeline, tx, repository4.PRE_CD_TYPE, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating pre cd script entry", "err", err, "pipeline", pipeline) + return 0, err + } + } + if pipeline.PostStageConfig != "" { + err = impl.prePostCdScriptHistoryService.CreatePrePostCdScriptHistory(pipeline, tx, repository4.POST_CD_TYPE, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating post cd script entry", "err", err, "pipeline", pipeline) + return 0, err + } + } + return pipeline.Id, nil } func (impl DbPipelineOrchestratorImpl) UpdateCDPipeline(pipelineRequest *bean.CDPipelineConfigObject, userId int32, tx *pg.Tx) (err error) { @@ -1079,8 +1130,23 @@ func (impl DbPipelineOrchestratorImpl) UpdateCDPipeline(pipelineRequest *bean.CD pipeline.UpdatedOn = time.Now() err = impl.pipelineRepository.Update(pipeline, tx) if err != nil { + impl.logger.Errorw("error in updating cd pipeline", "err", err, "pipeline", pipeline) return err } + if pipeline.PreStageConfig != "" { + err = impl.prePostCdScriptHistoryService.CreatePrePostCdScriptHistory(pipeline, tx, repository4.PRE_CD_TYPE, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating pre cd script entry", "err", err, "pipeline", pipeline) + return err + } + } + if pipeline.PostStageConfig != "" { + err = impl.prePostCdScriptHistoryService.CreatePrePostCdScriptHistory(pipeline, tx, repository4.POST_CD_TYPE, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating post cd script entry", "err", err, "pipeline", pipeline) + return err + } + } return err } diff --git a/pkg/pipeline/PipelineBuilder.go b/pkg/pipeline/PipelineBuilder.go index 58c1328b74..fe8b13895f 100644 --- a/pkg/pipeline/PipelineBuilder.go +++ b/pkg/pipeline/PipelineBuilder.go @@ -24,6 +24,8 @@ import ( app2 "github.com/devtron-labs/devtron/internal/sql/repository/app" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/devtron-labs/devtron/pkg/pipeline/history" + repository4 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" "github.com/devtron-labs/devtron/pkg/sql" util3 "github.com/devtron-labs/devtron/pkg/util" "net/http" @@ -103,33 +105,38 @@ type PipelineBuilder interface { } type PipelineBuilderImpl struct { - logger *zap.SugaredLogger - dbPipelineOrchestrator DbPipelineOrchestrator - dockerArtifactStoreRepository repository.DockerArtifactStoreRepository - materialRepo pipelineConfig.MaterialRepository - appRepo app2.AppRepository - pipelineRepository pipelineConfig.PipelineRepository - propertiesConfigService PropertiesConfigService - ciTemplateRepository pipelineConfig.CiTemplateRepository - ciPipelineRepository pipelineConfig.CiPipelineRepository - application application.ServiceClient - chartRepository chartRepoRepository.ChartRepository - ciArtifactRepository repository.CiArtifactRepository - ecrConfig *EcrConfig - envConfigOverrideRepository chartConfig.EnvConfigOverrideRepository - environmentRepository repository2.EnvironmentRepository - pipelineConfigRepository chartConfig.PipelineConfigRepository - mergeUtil util.MergeUtil - appWorkflowRepository appWorkflow.AppWorkflowRepository - ciConfig *CiConfig - cdWorkflowRepository pipelineConfig.CdWorkflowRepository - appService app.AppService - imageScanResultRepository security.ImageScanResultRepository - GitFactory *util.GitFactory - ArgoK8sClient argocdServer.ArgoK8sClient - attributesService attributes.AttributesService - aCDAuthConfig *util3.ACDAuthConfig - gitOpsRepository repository.GitOpsConfigRepository + logger *zap.SugaredLogger + dbPipelineOrchestrator DbPipelineOrchestrator + dockerArtifactStoreRepository repository.DockerArtifactStoreRepository + materialRepo pipelineConfig.MaterialRepository + appRepo app2.AppRepository + pipelineRepository pipelineConfig.PipelineRepository + propertiesConfigService PropertiesConfigService + ciTemplateRepository pipelineConfig.CiTemplateRepository + ciPipelineRepository pipelineConfig.CiPipelineRepository + application application.ServiceClient + chartRepository chartRepoRepository.ChartRepository + ciArtifactRepository repository.CiArtifactRepository + ecrConfig *EcrConfig + envConfigOverrideRepository chartConfig.EnvConfigOverrideRepository + environmentRepository repository2.EnvironmentRepository + pipelineConfigRepository chartConfig.PipelineConfigRepository + mergeUtil util.MergeUtil + appWorkflowRepository appWorkflow.AppWorkflowRepository + ciConfig *CiConfig + cdWorkflowRepository pipelineConfig.CdWorkflowRepository + appService app.AppService + imageScanResultRepository security.ImageScanResultRepository + GitFactory *util.GitFactory + ArgoK8sClient argocdServer.ArgoK8sClient + attributesService attributes.AttributesService + aCDAuthConfig *util3.ACDAuthConfig + gitOpsRepository repository.GitOpsConfigRepository + pipelineStrategyHistoryService history.PipelineStrategyHistoryService + prePostCiScriptHistoryService history.PrePostCiScriptHistoryService + prePostCdScriptHistoryService history.PrePostCdScriptHistoryService + deploymentTemplateHistoryService history.DeploymentTemplateHistoryService + appLevelMetricsRepository repository.AppLevelMetricsRepository } func NewPipelineBuilderImpl(logger *zap.SugaredLogger, @@ -156,35 +163,45 @@ func NewPipelineBuilderImpl(logger *zap.SugaredLogger, imageScanResultRepository security.ImageScanResultRepository, ArgoK8sClient argocdServer.ArgoK8sClient, GitFactory *util.GitFactory, attributesService attributes.AttributesService, - aCDAuthConfig *util3.ACDAuthConfig, gitOpsRepository repository.GitOpsConfigRepository) *PipelineBuilderImpl { + aCDAuthConfig *util3.ACDAuthConfig, gitOpsRepository repository.GitOpsConfigRepository, + pipelineStrategyHistoryService history.PipelineStrategyHistoryService, + prePostCiScriptHistoryService history.PrePostCiScriptHistoryService, + prePostCdScriptHistoryService history.PrePostCdScriptHistoryService, + deploymentTemplateHistoryService history.DeploymentTemplateHistoryService, + appLevelMetricsRepository repository.AppLevelMetricsRepository) *PipelineBuilderImpl { return &PipelineBuilderImpl{ - logger: logger, - dbPipelineOrchestrator: dbPipelineOrchestrator, - dockerArtifactStoreRepository: dockerArtifactStoreRepository, - materialRepo: materialRepo, - appService: appService, - appRepo: pipelineGroupRepo, - pipelineRepository: pipelineRepository, - propertiesConfigService: propertiesConfigService, - ciTemplateRepository: ciTemplateRepository, - ciPipelineRepository: ciPipelineRepository, - application: application, - chartRepository: chartRepository, - ciArtifactRepository: ciArtifactRepository, - ecrConfig: ecrConfig, - envConfigOverrideRepository: envConfigOverrideRepository, - environmentRepository: environmentRepository, - pipelineConfigRepository: pipelineConfigRepository, - mergeUtil: mergeUtil, - appWorkflowRepository: appWorkflowRepository, - ciConfig: ciConfig, - cdWorkflowRepository: cdWorkflowRepository, - imageScanResultRepository: imageScanResultRepository, - ArgoK8sClient: ArgoK8sClient, - GitFactory: GitFactory, - attributesService: attributesService, - aCDAuthConfig: aCDAuthConfig, - gitOpsRepository: gitOpsRepository, + logger: logger, + dbPipelineOrchestrator: dbPipelineOrchestrator, + dockerArtifactStoreRepository: dockerArtifactStoreRepository, + materialRepo: materialRepo, + appService: appService, + appRepo: pipelineGroupRepo, + pipelineRepository: pipelineRepository, + propertiesConfigService: propertiesConfigService, + ciTemplateRepository: ciTemplateRepository, + ciPipelineRepository: ciPipelineRepository, + application: application, + chartRepository: chartRepository, + ciArtifactRepository: ciArtifactRepository, + ecrConfig: ecrConfig, + envConfigOverrideRepository: envConfigOverrideRepository, + environmentRepository: environmentRepository, + pipelineConfigRepository: pipelineConfigRepository, + mergeUtil: mergeUtil, + appWorkflowRepository: appWorkflowRepository, + ciConfig: ciConfig, + cdWorkflowRepository: cdWorkflowRepository, + imageScanResultRepository: imageScanResultRepository, + ArgoK8sClient: ArgoK8sClient, + GitFactory: GitFactory, + attributesService: attributesService, + aCDAuthConfig: aCDAuthConfig, + gitOpsRepository: gitOpsRepository, + pipelineStrategyHistoryService: pipelineStrategyHistoryService, + prePostCiScriptHistoryService: prePostCiScriptHistoryService, + prePostCdScriptHistoryService: prePostCdScriptHistoryService, + deploymentTemplateHistoryService: deploymentTemplateHistoryService, + appLevelMetricsRepository: appLevelMetricsRepository, } } @@ -917,6 +934,24 @@ func (impl PipelineBuilderImpl) deletePipeline(request *bean.CiPatchRequest) (*b return nil, err } } + for _, ciScript := range request.CiPipeline.BeforeDockerBuildScripts { + ciPipelineScript := impl.dbPipelineOrchestrator.BuildCiPipelineScript(request.UserId, ciScript, BEFORE_DOCKER_BUILD, request.CiPipeline) + //creating history entry + _, err := impl.prePostCiScriptHistoryService.CreatePrePostCiScriptHistory(ciPipelineScript, tx, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating ci script history entry", "err", err, "ciPipelineScript", ciPipelineScript) + return nil, err + } + } + for _, ciScript := range request.CiPipeline.AfterDockerBuildScripts { + ciPipelineScript := impl.dbPipelineOrchestrator.BuildCiPipelineScript(request.UserId, ciScript, AFTER_DOCKER_BUILD, request.CiPipeline) + //creating history entry + _, err := impl.prePostCiScriptHistoryService.CreatePrePostCiScriptHistory(ciPipelineScript, tx, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating ci script history entry", "err", err, "ciPipelineScript", ciPipelineScript) + return nil, err + } + } err = tx.Commit() if err != nil { return nil, err @@ -1096,6 +1131,20 @@ func (impl PipelineBuilderImpl) deleteCdPipeline(pipelineId int, userId int32, c } } + if pipeline.PreStageConfig != "" { + err = impl.prePostCdScriptHistoryService.CreatePrePostCdScriptHistory(pipeline, tx, repository4.PRE_CD_TYPE, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating pre cd script entry", "err", err, "pipeline", pipeline) + return err + } + } + if pipeline.PostStageConfig != "" { + err = impl.prePostCdScriptHistoryService.CreatePrePostCdScriptHistory(pipeline, tx, repository4.POST_CD_TYPE, false, 0, time.Time{}) + if err != nil { + impl.logger.Errorw("error in creating post cd script entry", "err", err, "pipeline", pipeline) + return err + } + } //delete app from argo cd envModel, err := impl.environmentRepository.FindById(pipeline.EnvironmentId) if err != nil { @@ -1234,9 +1283,9 @@ func (impl PipelineBuilderImpl) createCdPipeline(ctx context.Context, app *app2. //new pipeline impl.logger.Debugw("new pipeline found", "pipeline", pipeline) name, err := impl.createArgoPipelineIfRequired(ctx, app, pipeline, envOverride) - if err != nil { - return 0, err - } + //if err != nil { + // return 0, err + //} impl.logger.Debugw("argocd application created", "name", name) // Get pipeline override based on Deployment strategy @@ -1276,7 +1325,19 @@ func (impl PipelineBuilderImpl) createCdPipeline(ctx context.Context, app *app2. return 0, err } } - + //getting global app metrics for cd pipeline create because env level metrics is not created yet + appLevelAppMetricsEnabled := false + appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(app.Id) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting app level metrics app level", "error", err) + } else if err == nil { + appLevelAppMetricsEnabled = appLevelMetrics.AppMetrics + } + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(envOverride, tx, appLevelAppMetricsEnabled, pipelineId) + if err != nil { + impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", envOverride) + return 0, err + } // strategies for pipeline ids, there is only one is default defaultCount := 0 for _, item := range pipeline.Strategies { @@ -1300,6 +1361,13 @@ func (impl PipelineBuilderImpl) createCdPipeline(ctx context.Context, app *app2. impl.logger.Errorw("error in saving strategy", "strategy", item.DeploymentTemplate) return pipelineId, fmt.Errorf("pipeline created but failed to add strategy") } + //creating history entry for strategy + _, err = impl.pipelineStrategyHistoryService.CreatePipelineStrategyHistory(strategy, tx) + if err != nil { + impl.logger.Errorw("error in creating strategy history entry", "err", err) + return 0, err + } + } err = tx.Commit() @@ -1390,6 +1458,12 @@ func (impl PipelineBuilderImpl) updateCdPipeline(ctx context.Context, pipeline * impl.logger.Errorw("error in updating strategy", "strategy", item.DeploymentTemplate) return fmt.Errorf("pipeline updated but failed to update one strategy") } + //creating history entry for strategy + _, err = impl.pipelineStrategyHistoryService.CreatePipelineStrategyHistory(strategy, tx) + if err != nil { + impl.logger.Errorw("error in creating strategy history entry", "err", err) + return err + } } else { strategy := &chartConfig.PipelineStrategy{ PipelineId: pipeline.Id, @@ -1404,6 +1478,12 @@ func (impl PipelineBuilderImpl) updateCdPipeline(ctx context.Context, pipeline * impl.logger.Errorw("error in saving strategy", "strategy", item.DeploymentTemplate) return fmt.Errorf("pipeline created but failed to add strategy") } + //creating history entry for strategy + _, err = impl.pipelineStrategyHistoryService.CreatePipelineStrategyHistory(strategy, tx) + if err != nil { + impl.logger.Errorw("error in creating strategy history entry", "err", err) + return err + } } } err = tx.Commit() diff --git a/pkg/pipeline/PropertiesConfig.go b/pkg/pipeline/PropertiesConfig.go index 947a670f8f..737d86d521 100644 --- a/pkg/pipeline/PropertiesConfig.go +++ b/pkg/pipeline/PropertiesConfig.go @@ -22,6 +22,7 @@ import ( "fmt" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/devtron-labs/devtron/pkg/pipeline/history" "github.com/devtron-labs/devtron/pkg/sql" "time" @@ -61,7 +62,7 @@ type EnvironmentPropertiesResponse struct { ChartRefId int `json:"chartRefId,omitempty" validate:"number"` Namespace string `json:"namespace" validate:"name-component"` Schema json.RawMessage `json:"schema"` - Readme string `json:"readme"` + Readme string `json:"readme"` } type PropertiesConfigService interface { @@ -80,15 +81,16 @@ type PropertiesConfigService interface { EnvMetricsEnableDisable(appMetricRequest *AppMetricEnableDisableRequest) (*AppMetricEnableDisableRequest, error) } type PropertiesConfigServiceImpl struct { - logger *zap.SugaredLogger - envConfigRepo chartConfig.EnvConfigOverrideRepository - chartRepo chartRepoRepository.ChartRepository - mergeUtil util.MergeUtil - environmentRepository repository2.EnvironmentRepository - dbPipelineOrchestrator DbPipelineOrchestrator - application application.ServiceClient - envLevelAppMetricsRepository repository.EnvLevelAppMetricsRepository - appLevelMetricsRepository repository.AppLevelMetricsRepository + logger *zap.SugaredLogger + envConfigRepo chartConfig.EnvConfigOverrideRepository + chartRepo chartRepoRepository.ChartRepository + mergeUtil util.MergeUtil + environmentRepository repository2.EnvironmentRepository + dbPipelineOrchestrator DbPipelineOrchestrator + application application.ServiceClient + envLevelAppMetricsRepository repository.EnvLevelAppMetricsRepository + appLevelMetricsRepository repository.AppLevelMetricsRepository + deploymentTemplateHistoryService history.DeploymentTemplateHistoryService } func NewPropertiesConfigServiceImpl(logger *zap.SugaredLogger, @@ -100,17 +102,18 @@ func NewPropertiesConfigServiceImpl(logger *zap.SugaredLogger, application application.ServiceClient, envLevelAppMetricsRepository repository.EnvLevelAppMetricsRepository, appLevelMetricsRepository repository.AppLevelMetricsRepository, -) *PropertiesConfigServiceImpl { + deploymentTemplateHistoryService history.DeploymentTemplateHistoryService) *PropertiesConfigServiceImpl { return &PropertiesConfigServiceImpl{ - logger: logger, - envConfigRepo: envConfigRepo, - chartRepo: chartRepo, - mergeUtil: mergeUtil, - environmentRepository: environmentRepository, - dbPipelineOrchestrator: dbPipelineOrchestrator, - application: application, - envLevelAppMetricsRepository: envLevelAppMetricsRepository, - appLevelMetricsRepository: appLevelMetricsRepository, + logger: logger, + envConfigRepo: envConfigRepo, + chartRepo: chartRepo, + mergeUtil: mergeUtil, + environmentRepository: environmentRepository, + dbPipelineOrchestrator: dbPipelineOrchestrator, + application: application, + envLevelAppMetricsRepository: envLevelAppMetricsRepository, + appLevelMetricsRepository: appLevelMetricsRepository, + deploymentTemplateHistoryService: deploymentTemplateHistoryService, } } @@ -313,10 +316,12 @@ func (impl PropertiesConfigServiceImpl) UpdateEnvironmentProperties(appId int, p override := &chartConfig.EnvConfigOverride{ Active: propertiesRequest.Active, Id: propertiesRequest.Id, + ChartId: oldEnvOverride.ChartId, EnvOverrideValues: string(overrideByte), Status: propertiesRequest.Status, ManualReviewed: propertiesRequest.ManualReviewed, Namespace: propertiesRequest.Namespace, + TargetEnvironment: propertiesRequest.EnvironmentId, AuditLog: sql.AuditLog{UpdatedBy: propertiesRequest.UserId, UpdatedOn: time.Now()}, } @@ -344,6 +349,30 @@ func (impl PropertiesConfigServiceImpl) UpdateEnvironmentProperties(appId int, p } } + //creating history + //TODO : remove fetching and setting app metrics flag for history when app metrics update request is combined with template update request + isAppMetricsEnabled := false + envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(appId, propertiesRequest.EnvironmentId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", appId, "envId", propertiesRequest.EnvironmentId) + return nil, err + } else if err == pg.ErrNoRows { + appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", appId) + return nil, err + } else if err == nil { + isAppMetricsEnabled = appLevelAppMetrics.AppMetrics + } + } else { + isAppMetricsEnabled = *envLevelAppMetrics.AppMetrics + } + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(override, nil, isAppMetricsEnabled, 0) + if err != nil { + impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", override) + return nil, err + } + return propertiesRequest, err } @@ -425,6 +454,28 @@ func (impl PropertiesConfigServiceImpl) CreateIfRequired(chart *chartRepoReposit impl.logger.Errorw("error in creating envconfig", "data", envOverride, "error", err) return nil, err } + //TODO : remove fetching and setting app metrics flag for history when app metrics update request is combined with template update request + isAppMetricsEnabled := false + envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(chart.AppId, environmentId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", chart.AppId, "envId", environmentId) + return nil, err + } else if err == pg.ErrNoRows { + appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(chart.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", chart.AppId) + return nil, err + } else if err == nil { + isAppMetricsEnabled = appLevelAppMetrics.AppMetrics + } + } else { + isAppMetricsEnabled = *envLevelAppMetrics.AppMetrics + } + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(envOverride, tx, isAppMetricsEnabled, 0) + if err != nil { + impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", envOverride) + return nil, err + } } return envOverride, nil } @@ -512,7 +563,6 @@ func (impl PropertiesConfigServiceImpl) ResetEnvironmentProperties(id int) (bool if err != nil { impl.logger.Warnw("error in update envOverride", "envOverrideId", id) } - envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(envOverride.Chart.AppId, envOverride.TargetEnvironment) if err != nil && !util.IsErrNoRows(err) { impl.logger.Errorw("error while fetching env level app metric", "err", err) @@ -587,23 +637,23 @@ func (impl PropertiesConfigServiceImpl) CreateEnvironmentPropertiesWithNamespace } func (impl PropertiesConfigServiceImpl) EnvMetricsEnableDisable(appMetricRequest *AppMetricEnableDisableRequest) (*AppMetricEnableDisableRequest, error) { - // validate app metrics compatibility - if appMetricRequest.IsAppMetricsEnabled == true { - currentChart, err := impl.envConfigRepo.FindLatestChartForAppByAppIdAndEnvId(appMetricRequest.AppId, appMetricRequest.EnvironmentId) - if err != nil && !errors.IsNotFound(err) { - impl.logger.Error(err) - return nil, err - } - if errors.IsNotFound(err) { - impl.logger.Errorw("no chart configured for this app", "appId", appMetricRequest.AppId) - err = &util.ApiError{ - InternalMessage: "no chart configured for this app", - UserMessage: "no chart configured for this app", - } - return nil, err + var currentChart *chartConfig.EnvConfigOverride + var err error + currentChart, err = impl.envConfigRepo.FindLatestChartForAppByAppIdAndEnvId(appMetricRequest.AppId, appMetricRequest.EnvironmentId) + if err != nil && !errors.IsNotFound(err) { + impl.logger.Error(err) + return nil, err + } + if errors.IsNotFound(err) { + impl.logger.Errorw("no chart configured for this app", "appId", appMetricRequest.AppId) + err = &util.ApiError{ + InternalMessage: "no chart configured for this app", + UserMessage: "no chart configured for this app", } - + return nil, err + } + if appMetricRequest.IsAppMetricsEnabled == true { chartMajorVersion, chartMinorVersion, err := util2.ExtractChartVersion(currentChart.Chart.ChartVersion) if err != nil { impl.logger.Errorw("chart version parsing", "err", err) @@ -652,5 +702,11 @@ func (impl PropertiesConfigServiceImpl) EnvMetricsEnableDisable(appMetricRequest return nil, err } } + //creating history entry + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(currentChart, nil, appMetricRequest.IsAppMetricsEnabled, 0) + if err != nil { + impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", currentChart) + return nil, err + } return appMetricRequest, err } diff --git a/pkg/pipeline/WorkflowDagExecutor.go b/pkg/pipeline/WorkflowDagExecutor.go index c9cfbb6fcc..460e39410d 100644 --- a/pkg/pipeline/WorkflowDagExecutor.go +++ b/pkg/pipeline/WorkflowDagExecutor.go @@ -23,6 +23,8 @@ import ( "fmt" "github.com/devtron-labs/devtron/internal/sql/repository/appWorkflow" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + history2 "github.com/devtron-labs/devtron/pkg/pipeline/history" + repository3 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" "github.com/devtron-labs/devtron/pkg/sql" "github.com/devtron-labs/devtron/pkg/user/casbin" util3 "github.com/devtron-labs/devtron/pkg/util" @@ -65,29 +67,30 @@ type WorkflowDagExecutor interface { } type WorkflowDagExecutorImpl struct { - logger *zap.SugaredLogger - pipelineRepository pipelineConfig.PipelineRepository - cdWorkflowRepository pipelineConfig.CdWorkflowRepository - pubsubClient *pubsub.PubSubClient - appService app.AppService - cdWorkflowService CdWorkflowService - ciPipelineRepository pipelineConfig.CiPipelineRepository - materialRepository pipelineConfig.MaterialRepository - cdConfig *CdConfig - pipelineOverrideRepository chartConfig.PipelineOverrideRepository - ciArtifactRepository repository.CiArtifactRepository - user user.UserService - enforcer casbin.Enforcer - enforcerUtil rbac.EnforcerUtil - groupRepository repository.DeploymentGroupRepository - tokenCache *util3.TokenCache - acdAuthConfig *util3.ACDAuthConfig - envRepository repository2.EnvironmentRepository - eventFactory client.EventFactory - eventClient client.EventClient - cvePolicyRepository security.CvePolicyRepository - scanResultRepository security.ImageScanResultRepository - appWorkflowRepository appWorkflow.AppWorkflowRepository + logger *zap.SugaredLogger + pipelineRepository pipelineConfig.PipelineRepository + cdWorkflowRepository pipelineConfig.CdWorkflowRepository + pubsubClient *pubsub.PubSubClient + appService app.AppService + cdWorkflowService CdWorkflowService + ciPipelineRepository pipelineConfig.CiPipelineRepository + materialRepository pipelineConfig.MaterialRepository + cdConfig *CdConfig + pipelineOverrideRepository chartConfig.PipelineOverrideRepository + ciArtifactRepository repository.CiArtifactRepository + user user.UserService + enforcer casbin.Enforcer + enforcerUtil rbac.EnforcerUtil + groupRepository repository.DeploymentGroupRepository + tokenCache *util3.TokenCache + acdAuthConfig *util3.ACDAuthConfig + envRepository repository2.EnvironmentRepository + eventFactory client.EventFactory + eventClient client.EventClient + cvePolicyRepository security.CvePolicyRepository + scanResultRepository security.ImageScanResultRepository + appWorkflowRepository appWorkflow.AppWorkflowRepository + prePostCdScriptHistoryService history2.PrePostCdScriptHistoryService } type CiArtifactDTO struct { @@ -140,30 +143,32 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi acdAuthConfig *util3.ACDAuthConfig, eventFactory client.EventFactory, eventClient client.EventClient, cvePolicyRepository security.CvePolicyRepository, scanResultRepository security.ImageScanResultRepository, - appWorkflowRepository appWorkflow.AppWorkflowRepository) *WorkflowDagExecutorImpl { + appWorkflowRepository appWorkflow.AppWorkflowRepository, + prePostCdScriptHistoryService history2.PrePostCdScriptHistoryService) *WorkflowDagExecutorImpl { wde := &WorkflowDagExecutorImpl{logger: Logger, - pipelineRepository: pipelineRepository, - cdWorkflowRepository: cdWorkflowRepository, - pubsubClient: pubsubClient, - appService: appService, - cdWorkflowService: cdWorkflowService, - ciPipelineRepository: ciPipelineRepository, - cdConfig: cdConfig, - ciArtifactRepository: ciArtifactRepository, - materialRepository: materialRepository, - pipelineOverrideRepository: pipelineOverrideRepository, - user: user, - enforcer: enforcer, - enforcerUtil: enforcerUtil, - groupRepository: groupRepository, - tokenCache: tokenCache, - acdAuthConfig: acdAuthConfig, - envRepository: envRepository, - eventFactory: eventFactory, - eventClient: eventClient, - cvePolicyRepository: cvePolicyRepository, - scanResultRepository: scanResultRepository, - appWorkflowRepository: appWorkflowRepository, + pipelineRepository: pipelineRepository, + cdWorkflowRepository: cdWorkflowRepository, + pubsubClient: pubsubClient, + appService: appService, + cdWorkflowService: cdWorkflowService, + ciPipelineRepository: ciPipelineRepository, + cdConfig: cdConfig, + ciArtifactRepository: ciArtifactRepository, + materialRepository: materialRepository, + pipelineOverrideRepository: pipelineOverrideRepository, + user: user, + enforcer: enforcer, + enforcerUtil: enforcerUtil, + groupRepository: groupRepository, + tokenCache: tokenCache, + acdAuthConfig: acdAuthConfig, + envRepository: envRepository, + eventFactory: eventFactory, + eventClient: eventClient, + cvePolicyRepository: cvePolicyRepository, + scanResultRepository: scanResultRepository, + appWorkflowRepository: appWorkflowRepository, + prePostCdScriptHistoryService: prePostCdScriptHistoryService, } err := wde.Subscribe() if err != nil { @@ -303,6 +308,8 @@ func (impl *WorkflowDagExecutorImpl) HandlePreStageSuccessEvent(cdStageCompleteE } func (impl *WorkflowDagExecutorImpl) TriggerPreStage(cdWf *pipelineConfig.CdWorkflow, artifact *repository.CiArtifact, pipeline *pipelineConfig.Pipeline, triggeredBy int32, applyAuth bool) error { + //setting triggeredAt variable to have consistent data for various audit log places in db for deployment time + triggeredAt := time.Now() //in case of pre stage manual trigger auth is already applied if applyAuth { @@ -324,7 +331,7 @@ func (impl *WorkflowDagExecutorImpl) TriggerPreStage(cdWf *pipelineConfig.CdWork cdWf = &pipelineConfig.CdWorkflow{ CiArtifactId: artifact.Id, PipelineId: pipeline.Id, - AuditLog: sql.AuditLog{CreatedOn: time.Now(), CreatedBy: 1, UpdatedOn: time.Now(), UpdatedBy: 1}, + AuditLog: sql.AuditLog{CreatedOn: triggeredAt, CreatedBy: 1, UpdatedOn: triggeredAt, UpdatedBy: 1}, } err := impl.cdWorkflowRepository.SaveWorkFlow(cdWf) if err != nil { @@ -337,7 +344,7 @@ func (impl *WorkflowDagExecutorImpl) TriggerPreStage(cdWf *pipelineConfig.CdWork ExecutorType: pipelineConfig.WORKFLOW_EXECUTOR_TYPE_AWF, Status: WorkflowStarting, //starting TriggeredBy: triggeredBy, - StartedOn: time.Now(), + StartedOn: triggeredAt, Namespace: impl.cdConfig.DefaultNamespace, CdWorkflowId: cdWf.Id, } @@ -376,8 +383,13 @@ func (impl *WorkflowDagExecutorImpl) TriggerPreStage(cdWf *pipelineConfig.CdWork if evtErr != nil { impl.logger.Errorw("CD trigger event not sent", "error", evtErr) } - return err - + //creating cd config history entry + err = impl.prePostCdScriptHistoryService.CreatePrePostCdScriptHistory(pipeline, nil, repository3.PRE_CD_TYPE, true, triggeredBy, triggeredAt) + if err != nil { + impl.logger.Errorw("error in creating pre cd script entry", "err", err, "pipeline", pipeline) + return err + } + return nil } func convert(ts string) (*time.Time, error) { @@ -389,21 +401,24 @@ func convert(ts string) (*time.Time, error) { return &t, nil } -func (impl *WorkflowDagExecutorImpl) TriggerPostStage(cdWf *pipelineConfig.CdWorkflow, cpipeline *pipelineConfig.Pipeline, triggeredBy int32) error { +func (impl *WorkflowDagExecutorImpl) TriggerPostStage(cdWf *pipelineConfig.CdWorkflow, pipeline *pipelineConfig.Pipeline, triggeredBy int32) error { + //setting triggeredAt variable to have consistent data for various audit log places in db for deployment time + triggeredAt := time.Now() + runner := &pipelineConfig.CdWorkflowRunner{ - Name: cpipeline.Name, + Name: pipeline.Name, WorkflowType: bean.CD_WORKFLOW_TYPE_POST, ExecutorType: pipelineConfig.WORKFLOW_EXECUTOR_TYPE_AWF, Status: WorkflowStarting, TriggeredBy: triggeredBy, - StartedOn: time.Now(), + StartedOn: triggeredAt, Namespace: impl.cdConfig.DefaultNamespace, CdWorkflowId: cdWf.Id, } var env *repository2.Environment var err error - if cpipeline.RunPostStageInEnv { - env, err = impl.envRepository.FindById(cpipeline.EnvironmentId) + if pipeline.RunPostStageInEnv { + env, err = impl.envRepository.FindById(pipeline.EnvironmentId) if err != nil { impl.logger.Errorw(" unable to find env ", "err", err) return err @@ -415,12 +430,12 @@ func (impl *WorkflowDagExecutorImpl) TriggerPostStage(cdWf *pipelineConfig.CdWor if err != nil { return err } - cdStageWorkflowRequest, err := impl.buildWFRequest(runner, cdWf, cpipeline, triggeredBy) + cdStageWorkflowRequest, err := impl.buildWFRequest(runner, cdWf, pipeline, triggeredBy) if err != nil { return err } cdStageWorkflowRequest.StageType = POST - _, err = impl.cdWorkflowService.SubmitWorkflow(cdStageWorkflowRequest, cpipeline, env) + _, err = impl.cdWorkflowService.SubmitWorkflow(cdStageWorkflowRequest, pipeline, env) if err != nil { return err } @@ -430,14 +445,20 @@ func (impl *WorkflowDagExecutorImpl) TriggerPostStage(cdWf *pipelineConfig.CdWor return err } - event := impl.eventFactory.Build(util2.Trigger, &cpipeline.Id, cpipeline.AppId, &cpipeline.EnvironmentId, util2.CD) + event := impl.eventFactory.Build(util2.Trigger, &pipeline.Id, pipeline.AppId, &pipeline.EnvironmentId, util2.CD) impl.logger.Debugw("event Cd Post Trigger", "event", event) event = impl.eventFactory.BuildExtraCDData(event, &wfr, 0, bean.CD_WORKFLOW_TYPE_POST) _, evtErr := impl.eventClient.WriteEvent(event) if evtErr != nil { impl.logger.Errorw("CD trigger event not sent", "error", evtErr) } - return err + //creating cd config history entry + err = impl.prePostCdScriptHistoryService.CreatePrePostCdScriptHistory(pipeline, nil, repository3.POST_CD_TYPE, true, triggeredBy, triggeredAt) + if err != nil { + impl.logger.Errorw("error in creating post cd script entry", "err", err, "pipeline", pipeline) + return err + } + return nil } func (impl *WorkflowDagExecutorImpl) buildArtifactLocation(cdWorkflowConfig *pipelineConfig.CdWorkflowConfig, cdWf *pipelineConfig.CdWorkflow, runner *pipelineConfig.CdWorkflowRunner) string { cdArtifactLocationFormat := cdWorkflowConfig.CdArtifactLocationFormat @@ -690,11 +711,14 @@ func (impl *WorkflowDagExecutorImpl) TriggerDeployment(cdWf *pipelineConfig.CdWo } } + //setting triggeredAt variable to have consistent data for various audit log places in db for deployment time + triggeredAt := time.Now() + if cdWf == nil { cdWf = &pipelineConfig.CdWorkflow{ CiArtifactId: artifact.Id, PipelineId: pipeline.Id, - AuditLog: sql.AuditLog{CreatedOn: time.Now(), CreatedBy: 1, UpdatedOn: time.Now(), UpdatedBy: 1}, + AuditLog: sql.AuditLog{CreatedOn: triggeredAt, CreatedBy: 1, UpdatedOn: triggeredAt, UpdatedBy: 1}, } err := impl.cdWorkflowRepository.SaveWorkFlow(cdWf) if err != nil { @@ -708,7 +732,7 @@ func (impl *WorkflowDagExecutorImpl) TriggerDeployment(cdWf *pipelineConfig.CdWo ExecutorType: pipelineConfig.WORKFLOW_EXECUTOR_TYPE_SYSTEM, Status: WorkflowStarting, //starting TriggeredBy: 1, - StartedOn: time.Now(), + StartedOn: triggeredAt, Namespace: impl.cdConfig.DefaultNamespace, CdWorkflowId: cdWf.Id, } @@ -759,8 +783,8 @@ func (impl *WorkflowDagExecutorImpl) TriggerDeployment(cdWf *pipelineConfig.CdWo return nil } - err = impl.appService.TriggerCD(artifact, cdWf.Id, pipeline, async) - err1 := impl.updatePreviousDeploymentStatus(runner, pipeline.Id, err) + err = impl.appService.TriggerCD(artifact, cdWf.Id, pipeline, async, triggeredAt) + err1 := impl.updatePreviousDeploymentStatus(runner, pipeline.Id, err, triggeredAt) if err1 != nil || err != nil { impl.logger.Errorw("error while update previous cd workflow runners", "err", err, "runner", runner, "pipelineId", pipeline.Id) return err @@ -768,12 +792,12 @@ func (impl *WorkflowDagExecutorImpl) TriggerDeployment(cdWf *pipelineConfig.CdWo return nil } -func (impl *WorkflowDagExecutorImpl) updatePreviousDeploymentStatus(currentRunner *pipelineConfig.CdWorkflowRunner, pipelineId int, err error) error { +func (impl *WorkflowDagExecutorImpl) updatePreviousDeploymentStatus(currentRunner *pipelineConfig.CdWorkflowRunner, pipelineId int, err error, triggeredAt time.Time) error { if err != nil { impl.logger.Errorw("error in triggering cd WF, setting wf status as fail ", "wfId", currentRunner.Id, "err", err) currentRunner.Status = WorkflowFailed currentRunner.Message = err.Error() - currentRunner.FinishedOn = time.Now() + currentRunner.FinishedOn = triggeredAt err = impl.cdWorkflowRepository.UpdateWorkFlowRunner(currentRunner) if err != nil { impl.logger.Errorw("error updating cd wf runner status", "err", err, "currentRunner", currentRunner) @@ -802,7 +826,7 @@ func (impl *WorkflowDagExecutorImpl) updatePreviousDeploymentStatus(currentRunne return nil } impl.logger.Infow("updating cd wf runner status as previous runner status is", "status", previousRunner.Status) - previousRunner.FinishedOn = time.Now() + previousRunner.FinishedOn = triggeredAt previousRunner.Message = "triggered new deployment" previousRunner.Status = WorkflowAborted } @@ -882,6 +906,8 @@ func (impl *WorkflowDagExecutorImpl) StopStartApp(stopRequest *StopAppRequest, c } func (impl *WorkflowDagExecutorImpl) ManualCdTrigger(overrideRequest *bean.ValuesOverrideRequest, ctx context.Context) (int, error) { + //setting triggeredAt variable to have consistent data for various audit log places in db for deployment time + triggeredAt := time.Now() releaseId := 0 var err error cdPipeline, err := impl.pipelineRepository.FindById(overrideRequest.PipelineId) @@ -916,7 +942,7 @@ func (impl *WorkflowDagExecutorImpl) ManualCdTrigger(overrideRequest *bean.Value cdWf := &pipelineConfig.CdWorkflow{ CiArtifactId: overrideRequest.CiArtifactId, PipelineId: overrideRequest.PipelineId, - AuditLog: sql.AuditLog{CreatedOn: time.Now(), CreatedBy: overrideRequest.UserId, UpdatedOn: time.Now(), UpdatedBy: overrideRequest.UserId}, + AuditLog: sql.AuditLog{CreatedOn: triggeredAt, CreatedBy: overrideRequest.UserId, UpdatedOn: triggeredAt, UpdatedBy: overrideRequest.UserId}, } err := impl.cdWorkflowRepository.SaveWorkFlow(cdWf) if err != nil { @@ -932,7 +958,7 @@ func (impl *WorkflowDagExecutorImpl) ManualCdTrigger(overrideRequest *bean.Value ExecutorType: pipelineConfig.WORKFLOW_EXECUTOR_TYPE_AWF, Status: WorkflowStarting, TriggeredBy: overrideRequest.UserId, - StartedOn: time.Now(), + StartedOn: triggeredAt, Namespace: impl.cdConfig.DefaultNamespace, CdWorkflowId: cdWorkflowId, } @@ -976,7 +1002,7 @@ func (impl *WorkflowDagExecutorImpl) ManualCdTrigger(overrideRequest *bean.Value ExecutorType: pipelineConfig.WORKFLOW_EXECUTOR_TYPE_SYSTEM, Status: WorkflowFailed, //starting TriggeredBy: 1, - StartedOn: time.Now(), + StartedOn: triggeredAt, Namespace: impl.cdConfig.DefaultNamespace, CdWorkflowId: cdWorkflowId, Message: "Found vulnerability on image", @@ -989,12 +1015,12 @@ func (impl *WorkflowDagExecutorImpl) ManualCdTrigger(overrideRequest *bean.Value return 0, fmt.Errorf("found vulnerability for image digest %s", artifact.ImageDigest) } - releaseId, err = impl.appService.TriggerRelease(overrideRequest, ctx) + releaseId, err = impl.appService.TriggerRelease(overrideRequest, ctx, triggeredAt) // return after error handling /*if err != nil { return 0, err }*/ - err1 := impl.updatePreviousDeploymentStatus(runner, cdPipeline.Id, err) + err1 := impl.updatePreviousDeploymentStatus(runner, cdPipeline.Id, err, triggeredAt) if err1 != nil || err != nil { impl.logger.Errorw("error while update previous cd workflow runners", "err", err, "runner", runner, "pipelineId", cdPipeline.Id) return 0, err @@ -1010,7 +1036,7 @@ func (impl *WorkflowDagExecutorImpl) ManualCdTrigger(overrideRequest *bean.Value cdWf := &pipelineConfig.CdWorkflow{ CiArtifactId: overrideRequest.CiArtifactId, PipelineId: overrideRequest.PipelineId, - AuditLog: sql.AuditLog{CreatedOn: time.Now(), CreatedBy: overrideRequest.UserId, UpdatedOn: time.Now(), UpdatedBy: overrideRequest.UserId}, + AuditLog: sql.AuditLog{CreatedOn: triggeredAt, CreatedBy: overrideRequest.UserId, UpdatedOn: triggeredAt, UpdatedBy: overrideRequest.UserId}, } err := impl.cdWorkflowRepository.SaveWorkFlow(cdWf) if err != nil { diff --git a/pkg/pipeline/history/ConfigMapHistoryService.go b/pkg/pipeline/history/ConfigMapHistoryService.go new file mode 100644 index 0000000000..29a9e93805 --- /dev/null +++ b/pkg/pipeline/history/ConfigMapHistoryService.go @@ -0,0 +1,380 @@ +package history + +import ( + "encoding/json" + "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" + "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/devtron-labs/devtron/pkg/user" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type ConfigMapHistoryService interface { + CreateHistoryFromAppLevelConfig(appLevelConfig *chartConfig.ConfigMapAppModel, configType repository.ConfigType) error + CreateHistoryFromEnvLevelConfig(envLevelConfig *chartConfig.ConfigMapEnvModel, configType repository.ConfigType) error + CreateCMCSHistoryForDeploymentTrigger(pipeline *pipelineConfig.Pipeline, deployedOn time.Time, deployedBy int32) error + MergeAppLevelAndEnvLevelConfigs(appLevelConfig *chartConfig.ConfigMapAppModel, envLevelConfig *chartConfig.ConfigMapEnvModel, configType repository.ConfigType, configMapSecretNames []string) (string, error) + GetHistoryForDeployedCMCSById(id, pipelineId int, configType repository.ConfigType) (*ConfigMapAndSecretHistoryDto, error) + GetDeploymentDetailsForDeployedCMCSHistory(pipelineId int, configType repository.ConfigType) ([]*ConfigMapAndSecretHistoryDto, error) +} + +type ConfigMapHistoryServiceImpl struct { + logger *zap.SugaredLogger + configMapHistoryRepository repository.ConfigMapHistoryRepository + pipelineRepository pipelineConfig.PipelineRepository + configMapRepository chartConfig.ConfigMapRepository + userService user.UserService +} + +func NewConfigMapHistoryServiceImpl(logger *zap.SugaredLogger, + configMapHistoryRepository repository.ConfigMapHistoryRepository, + pipelineRepository pipelineConfig.PipelineRepository, + configMapRepository chartConfig.ConfigMapRepository, + userService user.UserService) *ConfigMapHistoryServiceImpl { + return &ConfigMapHistoryServiceImpl{ + logger: logger, + configMapHistoryRepository: configMapHistoryRepository, + pipelineRepository: pipelineRepository, + configMapRepository: configMapRepository, + userService: userService, + } +} + +func (impl ConfigMapHistoryServiceImpl) CreateHistoryFromAppLevelConfig(appLevelConfig *chartConfig.ConfigMapAppModel, configType repository.ConfigType) error { + pipelines, err := impl.pipelineRepository.FindActiveByAppId(appLevelConfig.AppId) + if err != nil { + impl.logger.Errorw("err in getting pipelines, CreateHistoryFromAppLevelConfig", "err", err, "appLevelConfig", appLevelConfig) + return err + } + //creating history for global + configData, err := impl.MergeAppLevelAndEnvLevelConfigs(appLevelConfig, nil, configType, nil) + if err != nil { + impl.logger.Errorw("err in merging app and env level configs", "err", err) + return err + } + historyModel := &repository.ConfigmapAndSecretHistory{ + AppId: appLevelConfig.AppId, + DataType: configType, + Deployed: false, + Data: configData, + AuditLog: sql.AuditLog{ + CreatedBy: appLevelConfig.CreatedBy, + CreatedOn: appLevelConfig.CreatedOn, + UpdatedBy: appLevelConfig.UpdatedBy, + UpdatedOn: appLevelConfig.UpdatedOn, + }, + } + _, err = impl.configMapHistoryRepository.CreateHistory(historyModel) + if err != nil { + impl.logger.Errorw("error in creating new entry for CM/CS history", "historyModel", historyModel) + return err + } + for _, pipeline := range pipelines { + envLevelConfig, err := impl.configMapRepository.GetByAppIdAndEnvIdEnvLevel(pipeline.AppId, pipeline.EnvironmentId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("err in getting env level config", "err", err, "appId", appLevelConfig.AppId) + return err + } + configData, err := impl.MergeAppLevelAndEnvLevelConfigs(appLevelConfig, envLevelConfig, configType, nil) + if err != nil { + impl.logger.Errorw("err in merging app and env level configs", "err", err) + return err + } + historyModel := &repository.ConfigmapAndSecretHistory{ + AppId: appLevelConfig.AppId, + PipelineId: pipeline.Id, + DataType: configType, + Deployed: false, + Data: configData, + AuditLog: sql.AuditLog{ + CreatedBy: appLevelConfig.CreatedBy, + CreatedOn: appLevelConfig.CreatedOn, + UpdatedBy: appLevelConfig.UpdatedBy, + UpdatedOn: appLevelConfig.UpdatedOn, + }, + } + _, err = impl.configMapHistoryRepository.CreateHistory(historyModel) + if err != nil { + impl.logger.Errorw("error in creating new entry for CM/CS history", "historyModel", historyModel) + return err + } + } + + return nil +} + +func (impl ConfigMapHistoryServiceImpl) CreateHistoryFromEnvLevelConfig(envLevelConfig *chartConfig.ConfigMapEnvModel, configType repository.ConfigType) error { + pipelines, err := impl.pipelineRepository.FindActiveByAppIdAndEnvironmentId(envLevelConfig.AppId, envLevelConfig.EnvironmentId) + if err != nil { + impl.logger.Errorw("err in getting pipelines, CreateHistoryFromEnvLevelConfig", "err", err, "envLevelConfig", envLevelConfig) + return err + } + appLevelConfig, err := impl.configMapRepository.GetByAppIdAppLevel(envLevelConfig.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("err in getting app level config", "err", err, "appId", envLevelConfig.AppId) + return err + } + for _, pipeline := range pipelines { + configData, err := impl.MergeAppLevelAndEnvLevelConfigs(appLevelConfig, envLevelConfig, configType, nil) + if err != nil { + impl.logger.Errorw("err in merging app and env level configs", "err", err) + return err + } + historyModel := &repository.ConfigmapAndSecretHistory{ + AppId: envLevelConfig.AppId, + PipelineId: pipeline.Id, + DataType: configType, + Deployed: false, + Data: configData, + AuditLog: sql.AuditLog{ + CreatedBy: envLevelConfig.CreatedBy, + CreatedOn: envLevelConfig.CreatedOn, + UpdatedBy: envLevelConfig.UpdatedBy, + UpdatedOn: envLevelConfig.UpdatedOn, + }, + } + _, err = impl.configMapHistoryRepository.CreateHistory(historyModel) + if err != nil { + impl.logger.Errorw("error in creating new entry for CM/CS history", "historyModel", historyModel) + return err + } + } + return nil +} + +func (impl ConfigMapHistoryServiceImpl) CreateCMCSHistoryForDeploymentTrigger(pipeline *pipelineConfig.Pipeline, deployedOn time.Time, deployedBy int32) error { + //creating history for configmaps, secrets(if any) + appLevelConfig, err := impl.configMapRepository.GetByAppIdAppLevel(pipeline.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("err in getting app level config", "err", err, "appId", pipeline.AppId) + return err + } + envLevelConfig, err := impl.configMapRepository.GetByAppIdAndEnvIdEnvLevel(pipeline.AppId, pipeline.EnvironmentId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("err in getting env level config", "err", err, "appId", pipeline.AppId) + return err + } + configMapData, err := impl.MergeAppLevelAndEnvLevelConfigs(appLevelConfig, envLevelConfig, repository.CONFIGMAP_TYPE, nil) + if err != nil { + impl.logger.Errorw("err in merging app and env level configs", "err", err) + return err + } + historyModel := &repository.ConfigmapAndSecretHistory{ + AppId: pipeline.AppId, + PipelineId: pipeline.Id, + DataType: repository.CONFIGMAP_TYPE, + Deployed: true, + DeployedBy: deployedBy, + DeployedOn: deployedOn, + Data: configMapData, + AuditLog: sql.AuditLog{ + CreatedBy: deployedBy, + CreatedOn: deployedOn, + UpdatedBy: deployedBy, + UpdatedOn: deployedOn, + }, + } + _, err = impl.configMapHistoryRepository.CreateHistory(historyModel) + if err != nil { + impl.logger.Errorw("error in creating new entry for cm history", "historyModel", historyModel) + return err + } + secretData, err := impl.MergeAppLevelAndEnvLevelConfigs(appLevelConfig, envLevelConfig, repository.SECRET_TYPE, nil) + if err != nil { + impl.logger.Errorw("err in merging app and env level configs", "err", err) + return err + } + //using old model, updating secret data + historyModel.DataType = repository.SECRET_TYPE + historyModel.Id = 0 + historyModel.Data = secretData + _, err = impl.configMapHistoryRepository.CreateHistory(historyModel) + if err != nil { + impl.logger.Errorw("error in creating new entry for secret history", "historyModel", historyModel) + return err + } + return nil +} + +func (impl ConfigMapHistoryServiceImpl) MergeAppLevelAndEnvLevelConfigs(appLevelConfig *chartConfig.ConfigMapAppModel, envLevelConfig *chartConfig.ConfigMapEnvModel, configType repository.ConfigType, configMapSecretNames []string) (string, error) { + var err error + var appLevelConfigData []*ConfigData + var envLevelConfigData []*ConfigData + if configType == repository.CONFIGMAP_TYPE { + var configDataAppLevel string + var configDataEnvLevel string + if appLevelConfig != nil { + configDataAppLevel = appLevelConfig.ConfigMapData + } + if envLevelConfig != nil { + configDataEnvLevel = envLevelConfig.ConfigMapData + } + configListAppLevel := &ConfigList{} + if len(configDataAppLevel) > 0 { + err = json.Unmarshal([]byte(configDataAppLevel), configListAppLevel) + if err != nil { + impl.logger.Debugw("error while Unmarshal", "err", err) + return "", err + } + } + configListEnvLevel := &ConfigList{} + if len(configDataEnvLevel) > 0 { + err = json.Unmarshal([]byte(configDataEnvLevel), configListEnvLevel) + if err != nil { + impl.logger.Debugw("error while Unmarshal", "err", err) + return "", err + } + } + appLevelConfigData = configListAppLevel.ConfigData + envLevelConfigData = configListEnvLevel.ConfigData + } else if configType == repository.SECRET_TYPE { + var secretDataAppLevel string + var secretDataEnvLevel string + if appLevelConfig != nil { + secretDataAppLevel = appLevelConfig.SecretData + } + if envLevelConfig != nil { + secretDataEnvLevel = envLevelConfig.SecretData + } + secretListAppLevel := &SecretList{} + if len(secretDataAppLevel) > 0 { + err = json.Unmarshal([]byte(secretDataAppLevel), secretListAppLevel) + if err != nil { + impl.logger.Debugw("error while Unmarshal", "err", err) + return "", err + } + } + secretListEnvLevel := &SecretList{} + if len(secretDataEnvLevel) > 0 { + err = json.Unmarshal([]byte(secretDataEnvLevel), secretListEnvLevel) + if err != nil { + impl.logger.Debugw("error while Unmarshal", "err", err) + return "", err + } + } + appLevelConfigData = secretListAppLevel.ConfigData + envLevelConfigData = secretListEnvLevel.ConfigData + } + + var finalConfigs []*ConfigData + envLevelConfigs := make(map[string]bool) + filterNameMap := make(map[string]bool) + for _, name := range configMapSecretNames { + filterNameMap[name] = true + } + //if filter name map is not empty, to add configs by filtering names + //if filter name map is empty, adding all env level configs to final configs + for _, item := range envLevelConfigData { + if _, ok := filterNameMap[item.Name]; ok || len(filterNameMap) == 0 { + //adding all env configs whose name is in filter name map + envLevelConfigs[item.Name] = true + finalConfigs = append(finalConfigs, item) + } + } + for _, item := range appLevelConfigData { + //if filter name map is not empty, adding all global configs which are not present in env level and are present in filter name map to final configs + //if filter name map is empty,adding all global configs which are not present in env level to final configs + if _, ok := envLevelConfigs[item.Name]; !ok { + if _, ok = filterNameMap[item.Name]; ok || len(filterNameMap) == 0 { + finalConfigs = append(finalConfigs, item) + } + } + } + var finalConfigDataByte []byte + if configType == repository.CONFIGMAP_TYPE { + var finalConfigList ConfigList + finalConfigList.ConfigData = finalConfigs + finalConfigDataByte, err = json.Marshal(finalConfigList) + if err != nil { + impl.logger.Errorw("error in marshaling config", "err", err) + return "", err + } + } else if configType == repository.SECRET_TYPE { + var finalConfigList SecretList + finalConfigList.ConfigData = finalConfigs + finalConfigDataByte, err = json.Marshal(finalConfigList) + if err != nil { + impl.logger.Errorw("error in marshaling config", "err", err) + return "", err + } + } + return string(finalConfigDataByte), err +} + +func (impl ConfigMapHistoryServiceImpl) GetHistoryForDeployedCMCSById(id, pipelineId int, configType repository.ConfigType) (*ConfigMapAndSecretHistoryDto, error) { + history, err := impl.configMapHistoryRepository.GetHistoryForDeployedCMCSById(id, pipelineId, configType) + if err != nil { + impl.logger.Errorw("error in getting histories for cm/cs", "err", err, "id", id, "pipelineId", pipelineId) + return nil, err + } + var configData []*ConfigData + if configType == repository.CONFIGMAP_TYPE { + configList := ConfigList{} + if len(history.Data) > 0 { + err := json.Unmarshal([]byte(history.Data), &configList) + if err != nil { + impl.logger.Debugw("error while Unmarshal", "err", err) + return nil, err + } + } + configData = configList.ConfigData + } else if configType == repository.SECRET_TYPE { + secretList := ConfigList{} + if len(history.Data) > 0 { + err := json.Unmarshal([]byte(history.Data), &secretList) + if err != nil { + impl.logger.Debugw("error while Unmarshal", "err", err) + return nil, err + } + } + configData = secretList.ConfigData + } + + userInfo, err := impl.userService.GetById(history.DeployedBy) + if err != nil { + impl.logger.Errorw("unable to find user by id", "err", err, "id", history.Id) + return nil, err + } + historyDto := &ConfigMapAndSecretHistoryDto{ + Id: history.Id, + PipelineId: history.PipelineId, + AppId: history.AppId, + DataType: string(history.DataType), + ConfigData: configData, + Deployed: history.Deployed, + DeployedOn: history.DeployedOn, + DeployedBy: history.DeployedBy, + EmailId: userInfo.EmailId, + } + return historyDto, nil +} + +func (impl ConfigMapHistoryServiceImpl) GetDeploymentDetailsForDeployedCMCSHistory(pipelineId int, configType repository.ConfigType) ([]*ConfigMapAndSecretHistoryDto, error) { + histories, err := impl.configMapHistoryRepository.GetDeploymentDetailsForDeployedCMCSHistory(pipelineId, configType) + if err != nil { + impl.logger.Errorw("error in getting histories for cm/cs", "err", err, "pipelineId", pipelineId) + return nil, err + } + var historiesDto []*ConfigMapAndSecretHistoryDto + for _, history := range histories { + userInfo, err := impl.userService.GetById(history.DeployedBy) + if err != nil { + impl.logger.Errorw("unable to find user by id", "err", err, "id", history.Id) + return nil, err + } + historyDto := &ConfigMapAndSecretHistoryDto{ + Id: history.Id, + AppId: history.AppId, + PipelineId: history.PipelineId, + Deployed: history.Deployed, + DeployedOn: history.DeployedOn, + DeployedBy: history.DeployedBy, + EmailId: userInfo.EmailId, + } + historiesDto = append(historiesDto, historyDto) + } + return historiesDto, nil +} diff --git a/pkg/pipeline/history/DeploymentTemplateHistoryService.go b/pkg/pipeline/history/DeploymentTemplateHistoryService.go new file mode 100644 index 0000000000..5c14bc669e --- /dev/null +++ b/pkg/pipeline/history/DeploymentTemplateHistoryService.go @@ -0,0 +1,312 @@ +package history + +import ( + repository2 "github.com/devtron-labs/devtron/internal/sql/repository" + "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" + "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" + "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/devtron-labs/devtron/pkg/user" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type DeploymentTemplateHistoryService interface { + CreateDeploymentTemplateHistoryFromGlobalTemplate(chart *chartRepoRepository.Chart, tx *pg.Tx, IsAppMetricsEnabled bool) error + CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(envOverride *chartConfig.EnvConfigOverride, tx *pg.Tx, IsAppMetricsEnabled bool, pipelineId int) error + CreateDeploymentTemplateHistoryForDeploymentTrigger(pipeline *pipelineConfig.Pipeline, envOverride *chartConfig.EnvConfigOverride, renderedImageTemplate string, deployedOn time.Time, deployedBy int32) error + GetHistoryForDeployedTemplatesById(id, pipelineId int) (*DeploymentTemplateHistoryDto, error) + GetDeploymentDetailsForDeployedTemplateHistory(pipelineId, offset, limit int) ([]*DeploymentTemplateHistoryDto, error) +} + +type DeploymentTemplateHistoryServiceImpl struct { + logger *zap.SugaredLogger + deploymentTemplateHistoryRepository repository.DeploymentTemplateHistoryRepository + pipelineRepository pipelineConfig.PipelineRepository + chartRepository chartRepoRepository.ChartRepository + chartRefRepository chartRepoRepository.ChartRefRepository + envLevelAppMetricsRepository repository2.EnvLevelAppMetricsRepository + appLevelMetricsRepository repository2.AppLevelMetricsRepository + userService user.UserService + cdWorkflowRepository pipelineConfig.CdWorkflowRepository +} + +func NewDeploymentTemplateHistoryServiceImpl(logger *zap.SugaredLogger, deploymentTemplateHistoryRepository repository.DeploymentTemplateHistoryRepository, + pipelineRepository pipelineConfig.PipelineRepository, + chartRepository chartRepoRepository.ChartRepository, + chartRefRepository chartRepoRepository.ChartRefRepository, + envLevelAppMetricsRepository repository2.EnvLevelAppMetricsRepository, + appLevelMetricsRepository repository2.AppLevelMetricsRepository, + userService user.UserService, + cdWorkflowRepository pipelineConfig.CdWorkflowRepository) *DeploymentTemplateHistoryServiceImpl { + return &DeploymentTemplateHistoryServiceImpl{ + logger: logger, + deploymentTemplateHistoryRepository: deploymentTemplateHistoryRepository, + pipelineRepository: pipelineRepository, + chartRepository: chartRepository, + chartRefRepository: chartRefRepository, + envLevelAppMetricsRepository: envLevelAppMetricsRepository, + appLevelMetricsRepository: appLevelMetricsRepository, + userService: userService, + cdWorkflowRepository: cdWorkflowRepository, + } +} + +func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistoryFromGlobalTemplate(chart *chartRepoRepository.Chart, tx *pg.Tx, IsAppMetricsEnabled bool) (err error) { + //getting all pipelines without overridden charts + pipelines, err := impl.pipelineRepository.FindAllPipelinesByChartsOverrideAndAppIdAndChartId(false, chart.AppId, chart.Id) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("err in getting pipelines, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chart", chart) + return err + } + chartRef, err := impl.chartRefRepository.FindById(chart.ChartRefId) + if err != nil { + impl.logger.Errorw("err in getting chartRef, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chart", chart) + return err + } + if len(chartRef.Name) == 0 { + chartRef.Name = "Rollout Deployment" + } + //creating history without pipeline id + historyModel := &repository.DeploymentTemplateHistory{ + AppId: chart.AppId, + ImageDescriptorTemplate: chart.ImageDescriptorTemplate, + Template: chart.GlobalOverride, + Deployed: false, + TemplateName: chartRef.Name, + TemplateVersion: chartRef.Version, + IsAppMetricsEnabled: IsAppMetricsEnabled, + AuditLog: sql.AuditLog{ + CreatedOn: chart.CreatedOn, + CreatedBy: chart.CreatedBy, + UpdatedOn: chart.UpdatedOn, + UpdatedBy: chart.UpdatedBy, + }, + } + //creating new entry + if tx != nil { + _, err = impl.deploymentTemplateHistoryRepository.CreateHistoryWithTxn(historyModel, tx) + } else { + _, err = impl.deploymentTemplateHistoryRepository.CreateHistory(historyModel) + } + if err != nil { + impl.logger.Errorw("err in creating history entry for deployment template", "err", err, "history", historyModel) + return err + } + for _, pipeline := range pipelines { + historyModel := &repository.DeploymentTemplateHistory{ + AppId: chart.AppId, + PipelineId: pipeline.Id, + ImageDescriptorTemplate: chart.ImageDescriptorTemplate, + Template: chart.GlobalOverride, + Deployed: false, + TemplateName: chartRef.Name, + TemplateVersion: chartRef.Version, + IsAppMetricsEnabled: IsAppMetricsEnabled, + AuditLog: sql.AuditLog{ + CreatedOn: chart.CreatedOn, + CreatedBy: chart.CreatedBy, + UpdatedOn: chart.UpdatedOn, + UpdatedBy: chart.UpdatedBy, + }, + } + //creating new entry + if tx != nil { + _, err = impl.deploymentTemplateHistoryRepository.CreateHistoryWithTxn(historyModel, tx) + } else { + _, err = impl.deploymentTemplateHistoryRepository.CreateHistory(historyModel) + } + if err != nil { + impl.logger.Errorw("err in creating history entry for deployment template", "err", err, "history", historyModel) + return err + } + } + return err +} + +func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(envOverride *chartConfig.EnvConfigOverride, tx *pg.Tx, IsAppMetricsEnabled bool, pipelineId int) (err error) { + chart, err := impl.chartRepository.FindById(envOverride.ChartId) + if err != nil { + impl.logger.Errorw("err in getting global deployment template", "err", err, "chart", chart) + return err + } + chartRef, err := impl.chartRefRepository.FindById(chart.ChartRefId) + if err != nil { + impl.logger.Errorw("err in getting chartRef, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chartRef", chartRef) + return err + } + if len(chartRef.Name) == 0 { + chartRef.Name = "Rollout Deployment" + } + if pipelineId == 0 { + pipeline, err := impl.pipelineRepository.GetByEnvOverrideIdAndEnvId(envOverride.Id, envOverride.TargetEnvironment) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("err in getting pipelines, CreateDeploymentTemplateHistoryFromEnvOverrideTemplate", "err", err, "envOverrideId", envOverride.Id) + return err + } + pipelineId = pipeline.Id + } + historyModel := &repository.DeploymentTemplateHistory{ + AppId: chart.AppId, + PipelineId: pipelineId, + ImageDescriptorTemplate: chart.ImageDescriptorTemplate, + TargetEnvironment: envOverride.TargetEnvironment, + Deployed: false, + TemplateName: chartRef.Name, + TemplateVersion: chartRef.Version, + IsAppMetricsEnabled: IsAppMetricsEnabled, + AuditLog: sql.AuditLog{ + CreatedOn: envOverride.CreatedOn, + CreatedBy: envOverride.CreatedBy, + UpdatedOn: envOverride.UpdatedOn, + UpdatedBy: envOverride.UpdatedBy, + }, + } + if envOverride.IsOverride { + historyModel.Template = envOverride.EnvOverrideValues + } else { + //this is for the case when env override is created for new cd pipelines with template = "{}" + historyModel.Template = chart.GlobalOverride + } + //creating new entry + if tx != nil { + _, err = impl.deploymentTemplateHistoryRepository.CreateHistoryWithTxn(historyModel, tx) + } else { + _, err = impl.deploymentTemplateHistoryRepository.CreateHistory(historyModel) + } + if err != nil { + impl.logger.Errorw("err in creating history entry for deployment template", "err", err, "history", historyModel) + return err + } + return nil +} + +func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistoryForDeploymentTrigger(pipeline *pipelineConfig.Pipeline, envOverride *chartConfig.EnvConfigOverride, renderedImageTemplate string, deployedOn time.Time, deployedBy int32) error { + chartRef, err := impl.chartRefRepository.FindById(envOverride.Chart.ChartRefId) + if err != nil { + impl.logger.Errorw("err in getting chartRef, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chartRef", chartRef) + return err + } + if len(chartRef.Name) == 0 { + chartRef.Name = "Rollout Deployment" + } + isAppMetricsEnabled := false + envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(pipeline.AppId, pipeline.EnvironmentId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", pipeline.AppId, "envId", pipeline.EnvironmentId) + return err + } else if err == pg.ErrNoRows { + appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(pipeline.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", pipeline.AppId) + return err + } else if err == nil { + isAppMetricsEnabled = appLevelAppMetrics.AppMetrics + } + } else { + isAppMetricsEnabled = *envLevelAppMetrics.AppMetrics + } + historyModel := &repository.DeploymentTemplateHistory{ + AppId: pipeline.AppId, + PipelineId: pipeline.Id, + TargetEnvironment: pipeline.EnvironmentId, + ImageDescriptorTemplate: renderedImageTemplate, + Deployed: true, + DeployedBy: deployedBy, + DeployedOn: deployedOn, + TemplateName: chartRef.Name, + TemplateVersion: chartRef.Version, + IsAppMetricsEnabled: isAppMetricsEnabled, + AuditLog: sql.AuditLog{ + CreatedOn: deployedOn, + CreatedBy: deployedBy, + UpdatedOn: deployedOn, + UpdatedBy: deployedBy, + }, + } + if envOverride.IsOverride { + historyModel.Template = envOverride.EnvOverrideValues + } else { + historyModel.Template = envOverride.Chart.GlobalOverride + } + //creating new entry + _, err = impl.deploymentTemplateHistoryRepository.CreateHistory(historyModel) + if err != nil { + impl.logger.Errorw("err in creating history entry for deployment template", "err", err, "history", historyModel) + return err + } + return nil +} + +func (impl DeploymentTemplateHistoryServiceImpl) GetHistoryForDeployedTemplatesById(id, pipelineId int) (*DeploymentTemplateHistoryDto, error) { + history, err := impl.deploymentTemplateHistoryRepository.GetHistoryForDeployedTemplateById(id, pipelineId) + if err != nil { + impl.logger.Errorw("error in getting deployment template history", "err", err, "id", id, "pipelineId", pipelineId) + return nil, err + } + user, err := impl.userService.GetById(history.DeployedBy) + if err != nil { + impl.logger.Errorw("unable to find user by id", "err", err, "id", history.Id) + return nil, err + } + historyDto := &DeploymentTemplateHistoryDto{ + Id: history.Id, + PipelineId: history.PipelineId, + AppId: history.AppId, + ImageDescriptorTemplate: history.ImageDescriptorTemplate, + Template: history.Template, + TemplateVersion: history.TemplateVersion, + TemplateName: history.TemplateName, + TargetEnvironment: history.TargetEnvironment, + IsAppMetricsEnabled: history.IsAppMetricsEnabled, + Deployed: history.Deployed, + DeployedOn: history.DeployedOn, + DeployedBy: history.DeployedBy, + EmailId: user.EmailId, + } + return historyDto, nil +} + +func (impl DeploymentTemplateHistoryServiceImpl) GetDeploymentDetailsForDeployedTemplateHistory(pipelineId, offset, limit int) ([]*DeploymentTemplateHistoryDto, error) { + histories, err := impl.deploymentTemplateHistoryRepository.GetDeploymentDetailsForDeployedTemplateHistory(pipelineId, offset, limit) + if err != nil { + impl.logger.Errorw("error in getting deployment template history", "err", err, "pipelineId", pipelineId) + return nil, err + } + //getting wfrList for status of history + wfrList, err := impl.cdWorkflowRepository.FindCdWorkflowMetaByPipelineId(pipelineId, offset, limit) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting ") + return nil, err + } + deploymentTimeStatusMap := make(map[time.Time]int) + for index, wfr := range wfrList { + deploymentTimeStatusMap[wfr.StartedOn] = index + } + var historiesDto []*DeploymentTemplateHistoryDto + for _, history := range histories { + if wfrIndex, ok := deploymentTimeStatusMap[history.DeployedOn]; ok { + user, err := impl.userService.GetById(history.DeployedBy) + if err != nil { + impl.logger.Errorw("unable to find user by id", "err", err, "id", history.Id) + return nil, err + } + historyDto := &DeploymentTemplateHistoryDto{ + Id: history.Id, + AppId: history.AppId, + PipelineId: history.PipelineId, + Deployed: history.Deployed, + DeployedOn: history.DeployedOn, + DeployedBy: history.DeployedBy, + EmailId: user.EmailId, + DeploymentStatus: wfrList[wfrIndex].Status, + WfrId: wfrList[wfrIndex].Id, + WorkflowType: string(wfrList[wfrIndex].WorkflowType), + } + historiesDto = append(historiesDto, historyDto) + } + } + return historiesDto, nil +} diff --git a/pkg/pipeline/history/PipelineStrategyHistoryService.go b/pkg/pipeline/history/PipelineStrategyHistoryService.go new file mode 100644 index 0000000000..8436fa9e15 --- /dev/null +++ b/pkg/pipeline/history/PipelineStrategyHistoryService.go @@ -0,0 +1,137 @@ +package history + +import ( + "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" + "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/devtron-labs/devtron/pkg/user" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type PipelineStrategyHistoryService interface { + CreatePipelineStrategyHistory(pipelineStrategy *chartConfig.PipelineStrategy, tx *pg.Tx) (historyModel *repository.PipelineStrategyHistory, err error) + CreateStrategyHistoryForDeploymentTrigger(strategy *chartConfig.PipelineStrategy, deployedOn time.Time, deployedBy int32) error + GetHistoryForDeployedStrategyById(id, pipelineId int) (*PipelineStrategyHistoryDto, error) + GetDeploymentDetailsForDeployedStrategyHistory(pipelineId int) ([]*PipelineStrategyHistoryDto, error) +} + +type PipelineStrategyHistoryServiceImpl struct { + logger *zap.SugaredLogger + pipelineStrategyHistoryRepository repository.PipelineStrategyHistoryRepository + userService user.UserService +} + +func NewPipelineStrategyHistoryServiceImpl(logger *zap.SugaredLogger, + pipelineStrategyHistoryRepository repository.PipelineStrategyHistoryRepository, + userService user.UserService) *PipelineStrategyHistoryServiceImpl { + return &PipelineStrategyHistoryServiceImpl{ + logger: logger, + pipelineStrategyHistoryRepository: pipelineStrategyHistoryRepository, + userService: userService, + } +} + +func (impl PipelineStrategyHistoryServiceImpl) CreatePipelineStrategyHistory(pipelineStrategy *chartConfig.PipelineStrategy, tx *pg.Tx) (historyModel *repository.PipelineStrategyHistory, err error) { + //creating new entry + historyModel = &repository.PipelineStrategyHistory{ + PipelineId: pipelineStrategy.PipelineId, + Strategy: pipelineStrategy.Strategy, + Config: pipelineStrategy.Config, + Default: pipelineStrategy.Default, + Deployed: false, + AuditLog: sql.AuditLog{ + CreatedOn: pipelineStrategy.CreatedOn, + CreatedBy: pipelineStrategy.CreatedBy, + UpdatedOn: pipelineStrategy.UpdatedOn, + UpdatedBy: pipelineStrategy.UpdatedBy, + }, + } + if tx != nil { + _, err = impl.pipelineStrategyHistoryRepository.CreateHistoryWithTxn(historyModel, tx) + } else { + _, err = impl.pipelineStrategyHistoryRepository.CreateHistory(historyModel) + } + if err != nil { + impl.logger.Errorw("err in creating history entry for pipeline strategy", "err", err) + return nil, err + } + return historyModel, err +} + +func (impl PipelineStrategyHistoryServiceImpl) CreateStrategyHistoryForDeploymentTrigger(pipelineStrategy *chartConfig.PipelineStrategy, deployedOn time.Time, deployedBy int32) error { + //creating new entry + historyModel := &repository.PipelineStrategyHistory{ + PipelineId: pipelineStrategy.PipelineId, + Strategy: pipelineStrategy.Strategy, + Config: pipelineStrategy.Config, + Default: pipelineStrategy.Default, + Deployed: true, + DeployedBy: deployedBy, + DeployedOn: deployedOn, + AuditLog: sql.AuditLog{ + CreatedOn: deployedOn, + CreatedBy: deployedBy, + UpdatedOn: deployedOn, + UpdatedBy: deployedBy, + }, + } + _, err := impl.pipelineStrategyHistoryRepository.CreateHistory(historyModel) + if err != nil { + impl.logger.Errorw("err in creating history entry for pipeline strategy", "err", err) + return err + } + return err +} + +func (impl PipelineStrategyHistoryServiceImpl) GetHistoryForDeployedStrategyById(id, pipelineId int) (*PipelineStrategyHistoryDto, error) { + history, err := impl.pipelineStrategyHistoryRepository.GetHistoryForDeployedStrategyById(id, pipelineId) + if err != nil { + impl.logger.Errorw("error in getting history for strategy", "err", err, "id", id, "pipelineId", pipelineId) + return nil, err + } + user, err := impl.userService.GetById(history.DeployedBy) + if err != nil { + impl.logger.Errorw("unable to find user by id", "err", err, "id", history.Id) + return nil, err + } + historyDto := &PipelineStrategyHistoryDto{ + Id: history.Id, + PipelineId: history.PipelineId, + Strategy: string(history.Strategy), + Config: history.Config, + Default: history.Default, + Deployed: history.Deployed, + DeployedOn: history.DeployedOn, + DeployedBy: history.DeployedBy, + EmailId: user.EmailId, + } + return historyDto, nil +} + +func (impl PipelineStrategyHistoryServiceImpl) GetDeploymentDetailsForDeployedStrategyHistory(pipelineId int) ([]*PipelineStrategyHistoryDto, error) { + histories, err := impl.pipelineStrategyHistoryRepository.GetDeploymentDetailsForDeployedStrategyHistory(pipelineId) + if err != nil { + impl.logger.Errorw("error in getting history for strategy", "err", err, "pipelineId", pipelineId) + return nil, err + } + var historiesDto []*PipelineStrategyHistoryDto + for _, history := range histories { + user, err := impl.userService.GetById(history.DeployedBy) + if err != nil { + impl.logger.Errorw("unable to find user by id", "err", err, "id", history.Id) + return nil, err + } + historyDto := &PipelineStrategyHistoryDto{ + Id: history.Id, + PipelineId: history.PipelineId, + Deployed: history.Deployed, + DeployedOn: history.DeployedOn, + DeployedBy: history.DeployedBy, + EmailId: user.EmailId, + } + historiesDto = append(historiesDto, historyDto) + } + return historiesDto, nil +} diff --git a/pkg/pipeline/history/PrePostCdScriptHistoryService.go b/pkg/pipeline/history/PrePostCdScriptHistoryService.go new file mode 100644 index 0000000000..5fab4fa535 --- /dev/null +++ b/pkg/pipeline/history/PrePostCdScriptHistoryService.go @@ -0,0 +1,180 @@ +package history + +import ( + "encoding/json" + "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" + "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type PrePostCdScriptHistoryService interface { + CreatePrePostCdScriptHistory(pipeline *pipelineConfig.Pipeline, tx *pg.Tx, stage repository.CdStageType, deployed bool, deployedBy int32, deployedOn time.Time) error + GetHistoryForDeployedPrePostCdScript(pipelineId int, stage repository.CdStageType) ([]*PrePostCdScriptHistoryDto, error) +} + +type PrePostCdScriptHistoryServiceImpl struct { + logger *zap.SugaredLogger + prePostCdScriptHistoryRepository repository.PrePostCdScriptHistoryRepository + configMapRepository chartConfig.ConfigMapRepository + configMapHistoryService ConfigMapHistoryService +} + +func NewPrePostCdScriptHistoryServiceImpl(logger *zap.SugaredLogger, prePostCdScriptHistoryRepository repository.PrePostCdScriptHistoryRepository, + configMapRepository chartConfig.ConfigMapRepository, configMapHistoryService ConfigMapHistoryService) *PrePostCdScriptHistoryServiceImpl { + return &PrePostCdScriptHistoryServiceImpl{ + logger: logger, + prePostCdScriptHistoryRepository: prePostCdScriptHistoryRepository, + configMapRepository: configMapRepository, + configMapHistoryService: configMapHistoryService, + } +} + +func (impl PrePostCdScriptHistoryServiceImpl) CreatePrePostCdScriptHistory(pipeline *pipelineConfig.Pipeline, tx *pg.Tx, stage repository.CdStageType, deployed bool, deployedBy int32, deployedOn time.Time) (err error) { + historyModel := &repository.PrePostCdScriptHistory{ + PipelineId: pipeline.Id, + Deployed: deployed, + DeployedBy: deployedBy, + DeployedOn: deployedOn, + AuditLog: sql.AuditLog{ + CreatedOn: pipeline.CreatedOn, + CreatedBy: pipeline.CreatedBy, + UpdatedOn: pipeline.UpdatedOn, + UpdatedBy: pipeline.UpdatedBy, + }, + } + if stage == repository.PRE_CD_TYPE { + historyModel.Stage = repository.PRE_CD_TYPE + historyModel.Script = pipeline.PreStageConfig + historyModel.ConfigMapSecretNames = pipeline.PreStageConfigMapSecretNames + historyModel.ExecInEnv = pipeline.RunPreStageInEnv + historyModel.TriggerType = pipeline.PreTriggerType + } else if stage == repository.POST_CD_TYPE { + historyModel.Stage = repository.POST_CD_TYPE + historyModel.Script = pipeline.PostStageConfig + historyModel.ConfigMapSecretNames = pipeline.PostStageConfigMapSecretNames + historyModel.ExecInEnv = pipeline.RunPostStageInEnv + historyModel.TriggerType = pipeline.PostTriggerType + } + configMapData, secretData, err := impl.GetConfigMapSecretData(pipeline, stage) + if err != nil { + impl.logger.Errorw("err in getting cm and cs data for cd config history entry", "err", err) + return err + } + historyModel.ConfigMapData = configMapData + historyModel.SecretData = secretData + if tx != nil { + _, err = impl.prePostCdScriptHistoryRepository.CreateHistoryWithTxn(historyModel, tx) + } else { + _, err = impl.prePostCdScriptHistoryRepository.CreateHistory(historyModel) + } + if err != nil { + impl.logger.Errorw("err in creating history entry for pre/post cd script", "err", err) + return err + } + return nil +} + +func (impl PrePostCdScriptHistoryServiceImpl) GetHistoryForDeployedPrePostCdScript(pipelineId int, stage repository.CdStageType) ([]*PrePostCdScriptHistoryDto, error) { + histories, err := impl.prePostCdScriptHistoryRepository.GetHistoryForDeployedPrePostScriptByStage(pipelineId, stage) + if err != nil { + impl.logger.Errorw("error in getting pre/post cd script history", "err", err, "pipelineId", pipelineId) + return nil, err + } + var historiesDto []*PrePostCdScriptHistoryDto + for _, history := range histories { + configMapList := ConfigList{} + if len(history.ConfigMapData) > 0 { + err := json.Unmarshal([]byte(history.ConfigMapData), &configMapList) + if err != nil { + impl.logger.Debugw("error while Unmarshal", "err", err) + return nil, err + } + } + secretList := ConfigList{} + if len(history.SecretData) > 0 { + err := json.Unmarshal([]byte(history.SecretData), &secretList) + if err != nil { + impl.logger.Debugw("error while Unmarshal", "err", err) + return nil, err + } + } + var configMapSecretNames PrePostStageConfigMapSecretNames + if history.ConfigMapSecretNames != "" { + err = json.Unmarshal([]byte(history.ConfigMapSecretNames), &configMapSecretNames) + if err != nil { + impl.logger.Error("error in un-marshaling config map secret names", "err", err) + return nil, err + } + } + + historyDto := &PrePostCdScriptHistoryDto{ + Id: history.Id, + PipelineId: history.PipelineId, + Script: history.Script, + Stage: string(history.Stage), + ConfigMapSecretNames: configMapSecretNames, + ConfigMapData: configMapList.ConfigData, + SecretData: secretList.ConfigData, + TriggerType: string(history.TriggerType), + ExecInEnv: history.ExecInEnv, + Deployed: history.Deployed, + DeployedOn: history.DeployedOn, + DeployedBy: history.DeployedBy, + } + historiesDto = append(historiesDto, historyDto) + } + return historiesDto, nil +} + +func (impl PrePostCdScriptHistoryServiceImpl) GetConfigMapSecretData(pipeline *pipelineConfig.Pipeline, stage repository.CdStageType) (configMapData, secretData string, err error) { + var configMapSecretNames PrePostStageConfigMapSecretNames + if stage == repository.PRE_CD_TYPE { + if pipeline.PreStageConfigMapSecretNames != "" { + err = json.Unmarshal([]byte(pipeline.PreStageConfigMapSecretNames), &configMapSecretNames) + if err != nil { + impl.logger.Error("error in un-marshaling pre stage config map secret names", "err", err) + return "", "", err + } + } + } else if stage == repository.POST_CD_TYPE { + if pipeline.PostStageConfigMapSecretNames != "" { + err = json.Unmarshal([]byte(pipeline.PostStageConfigMapSecretNames), &configMapSecretNames) + if err != nil { + impl.logger.Error("error in un-marshaling post stage config map secret names", "err", err) + return "", "", err + } + } + } + if len(configMapSecretNames.ConfigMaps) == 0 && len(configMapSecretNames.Secrets) == 0 { + return "", "", nil + } + appLevelConfig, err := impl.configMapRepository.GetByAppIdAppLevel(pipeline.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("err in getting app level config", "err", err, "appId", pipeline.AppId) + return "", "", err + } + envLevelConfig, err := impl.configMapRepository.GetByAppIdAndEnvIdEnvLevel(pipeline.AppId, pipeline.EnvironmentId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("err in getting env level config", "err", err, "appId", pipeline.AppId, "envId", pipeline.EnvironmentId) + return "", "", err + } + if len(configMapSecretNames.ConfigMaps) > 0 { + configMapData, err = impl.configMapHistoryService.MergeAppLevelAndEnvLevelConfigs(appLevelConfig, envLevelConfig, repository.CONFIGMAP_TYPE, configMapSecretNames.ConfigMaps) + if err != nil { + impl.logger.Errorw("error in getting filtered config map data", "err", err) + return "", "", err + } + } + if len(configMapSecretNames.Secrets) > 0 { + secretData, err = impl.configMapHistoryService.MergeAppLevelAndEnvLevelConfigs(appLevelConfig, envLevelConfig, repository.SECRET_TYPE, configMapSecretNames.Secrets) + if err != nil { + impl.logger.Errorw("error in getting filtered secret data", "err", err) + return "", "", err + } + } + return configMapData, secretData, nil +} diff --git a/pkg/pipeline/history/PrePostCiScriptHistoryService.go b/pkg/pipeline/history/PrePostCiScriptHistoryService.go new file mode 100644 index 0000000000..35cb965a4b --- /dev/null +++ b/pkg/pipeline/history/PrePostCiScriptHistoryService.go @@ -0,0 +1,56 @@ +package history + +import ( + "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type PrePostCiScriptHistoryService interface { + CreatePrePostCiScriptHistory(ciPipelineScript *pipelineConfig.CiPipelineScript, tx *pg.Tx, built bool, builtBy int32, builtOn time.Time) (historyModel *repository.PrePostCiScriptHistory, err error) +} + +type PrePostCiScriptHistoryServiceImpl struct { + logger *zap.SugaredLogger + prePostCiScriptHistoryRepository repository.PrePostCiScriptHistoryRepository +} + +func NewPrePostCiScriptHistoryServiceImpl(logger *zap.SugaredLogger, prePostCiScriptHistoryRepository repository.PrePostCiScriptHistoryRepository) *PrePostCiScriptHistoryServiceImpl { + return &PrePostCiScriptHistoryServiceImpl{ + logger: logger, + prePostCiScriptHistoryRepository: prePostCiScriptHistoryRepository, + } +} + +func (impl PrePostCiScriptHistoryServiceImpl) CreatePrePostCiScriptHistory(ciPipelineScript *pipelineConfig.CiPipelineScript, tx *pg.Tx, built bool, builtBy int32, builtOn time.Time) (historyModel *repository.PrePostCiScriptHistory, err error) { + //creating new entry + historyModel = &repository.PrePostCiScriptHistory{ + CiPipelineScriptsId: ciPipelineScript.Id, + Script: ciPipelineScript.Script, + Stage: ciPipelineScript.Stage, + Name: ciPipelineScript.Name, + OutputLocation: ciPipelineScript.OutputLocation, + Built: built, + BuiltBy: builtBy, + BuiltOn: builtOn, + AuditLog: sql.AuditLog{ + CreatedOn: ciPipelineScript.CreatedOn, + CreatedBy: ciPipelineScript.CreatedBy, + UpdatedOn: ciPipelineScript.UpdatedOn, + UpdatedBy: ciPipelineScript.UpdatedBy, + }, + } + if tx != nil { + _, err = impl.prePostCiScriptHistoryRepository.CreateHistoryWithTxn(historyModel, tx) + } else { + _, err = impl.prePostCiScriptHistoryRepository.CreateHistory(historyModel) + } + if err != nil { + impl.logger.Errorw("err in creating history entry for ci script", "err", err) + return nil, err + } + return historyModel, err +} diff --git a/pkg/pipeline/history/bean.go b/pkg/pipeline/history/bean.go new file mode 100644 index 0000000000..731e575d94 --- /dev/null +++ b/pkg/pipeline/history/bean.go @@ -0,0 +1,103 @@ +package history + +import ( + "encoding/json" + "time" +) + +type ConfigMapAndSecretHistoryDto struct { + Id int `json:"id"` + PipelineId int `json:"pipelineId"` + AppId int `json:"appId"` + DataType string `json:"dataType,omitempty"` + ConfigData []*ConfigData `json:"configData,omitempty"` + Deployed bool `json:"deployed"` + DeployedOn time.Time `json:"deployedOn"` + DeployedBy int32 `json:"deployedBy"` + EmailId string `json:"emailId"` +} + +type PrePostCdScriptHistoryDto struct { + Id int `json:"id"` + PipelineId int `json:"pipelineId"` + Script string `json:"script"` + Stage string `json:"stage"` + ConfigMapSecretNames PrePostStageConfigMapSecretNames `json:"configmapSecretNames"` + ConfigMapData []*ConfigData `json:"configmapData"` + SecretData []*ConfigData `json:"secretData"` + TriggerType string `json:"triggerType"` + ExecInEnv bool `json:"execInEnv"` + Deployed bool `json:"deployed"` + DeployedOn time.Time `json:"deployedOn"` + DeployedBy int32 `json:"deployedBy"` +} + +type PrePostStageConfigMapSecretNames struct { + ConfigMaps []string `json:"configMaps"` + Secrets []string `json:"secrets"` +} + +type DeploymentTemplateHistoryDto struct { + Id int `json:"id"` + PipelineId int `json:"pipelineId"` + AppId int `json:"appId"` + ImageDescriptorTemplate string `json:"imageDescriptorTemplate,omitempty"` + Template string `json:"template,omitempty"` + TemplateName string `json:"templateName,omitempty"` + TemplateVersion string `json:"templateVersion,omitempty"` + IsAppMetricsEnabled bool `json:"isAppMetricsEnabled"` + TargetEnvironment int `json:"targetEnvironment,omitempty"` + Deployed bool `json:"deployed"` + DeployedOn time.Time `json:"deployedOn"` + DeployedBy int32 `json:"deployedBy"` + EmailId string `json:"emailId"` + DeploymentStatus string `json:"deploymentStatus,omitempty"` + WfrId int `json:"wfrId,omitempty"` + WorkflowType string `json:"workflowType,omitempty"` +} + +type PipelineStrategyHistoryDto struct { + Id int `json:"id"` + PipelineId int `json:"pipelineId"` + Strategy string `json:"strategy,omitempty"` + Config string `json:"config,omitempty"` + Default bool `json:"default,omitempty"` + Deployed bool `json:"deployed"` + DeployedOn time.Time `json:"deployedOn"` + DeployedBy int32 `json:"deployedBy"` + EmailId string `json:"emailId"` +} + +// duplicate structs below, because importing from pkg/pipeline was resulting in circular dependency + +type ConfigList struct { + ConfigData []*ConfigData `json:"maps"` +} + +type SecretList struct { + ConfigData []*ConfigData `json:"secrets"` +} + +type ConfigData struct { + Name string `json:"name"` + Type string `json:"type"` + External bool `json:"external"` + MountPath string `json:"mountPath,omitempty"` + Data json.RawMessage `json:"data"` + DefaultData json.RawMessage `json:"defaultData,omitempty"` + DefaultMountPath string `json:"defaultMountPath,omitempty"` + Global bool `json:"global"` + ExternalSecretType string `json:"externalType"` + ExternalSecret []ExternalSecret `json:"secretData"` + DefaultExternalSecret []ExternalSecret `json:"defaultSecretData,omitempty"` + RoleARN string `json:"roleARN"` + SubPath bool `json:"subPath"` + FilePermission string `json:"filePermission"` +} + +type ExternalSecret struct { + Key string `json:"key"` + Name string `json:"name"` + Property string `json:"property,omitempty"` + IsBinary bool `json:"isBinary"` +} diff --git a/pkg/pipeline/history/repository/ConfigMapHistoryRepository.go b/pkg/pipeline/history/repository/ConfigMapHistoryRepository.go new file mode 100644 index 0000000000..ab0a303564 --- /dev/null +++ b/pkg/pipeline/history/repository/ConfigMapHistoryRepository.go @@ -0,0 +1,77 @@ +package repository + +import ( + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type ConfigType string + +const ( + CONFIGMAP_TYPE ConfigType = "CONFIGMAP" + SECRET_TYPE ConfigType = "SECRET" +) + +type ConfigMapHistoryRepository interface { + CreateHistory(model *ConfigmapAndSecretHistory) (*ConfigmapAndSecretHistory, error) + GetHistoryForDeployedCMCSById(id, pipelineId int, configType ConfigType) (*ConfigmapAndSecretHistory, error) + GetDeploymentDetailsForDeployedCMCSHistory(pipelineId int, configType ConfigType) ([]*ConfigmapAndSecretHistory, error) +} + +type ConfigMapHistoryRepositoryImpl struct { + dbConnection *pg.DB + logger *zap.SugaredLogger +} + +func NewConfigMapHistoryRepositoryImpl(logger *zap.SugaredLogger, dbConnection *pg.DB) *ConfigMapHistoryRepositoryImpl { + return &ConfigMapHistoryRepositoryImpl{dbConnection: dbConnection, logger: logger} +} + +type ConfigmapAndSecretHistory struct { + TableName struct{} `sql:"config_map_history" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + PipelineId int `sql:"pipeline_id"` + AppId int `sql:"app_id"` + DataType ConfigType `sql:"data_type"` + Data string `sql:"data"` + Deployed bool `sql:"deployed"` + DeployedOn time.Time `sql:"deployed_on"` + DeployedBy int32 `sql:"deployed_by"` + sql.AuditLog +} + +func (impl ConfigMapHistoryRepositoryImpl) CreateHistory(model *ConfigmapAndSecretHistory) (*ConfigmapAndSecretHistory, error) { + err := impl.dbConnection.Insert(model) + if err != nil { + impl.logger.Errorw("err in creating env config map/secret history entry", "err", err) + return model, err + } + return model, nil +} + +func (impl ConfigMapHistoryRepositoryImpl) GetHistoryForDeployedCMCSById(id, pipelineId int, configType ConfigType) (*ConfigmapAndSecretHistory, error) { + var history ConfigmapAndSecretHistory + err := impl.dbConnection.Model(&history).Where("id = ?", id). + Where("pipeline_id = ?", pipelineId). + Where("data_type = ?", configType). + Where("deployed = ?", true).Select() + if err != nil { + impl.logger.Errorw("error in getting CM/CS history", "err", err) + return &history, err + } + return &history, nil +} + +func (impl ConfigMapHistoryRepositoryImpl) GetDeploymentDetailsForDeployedCMCSHistory(pipelineId int, configType ConfigType) ([]*ConfigmapAndSecretHistory, error) { + var histories []*ConfigmapAndSecretHistory + err := impl.dbConnection.Model(&histories).Where("pipeline_id = ?", pipelineId). + Where("data_type = ?", configType). + Where("deployed = ?", true).Select() + if err != nil { + impl.logger.Errorw("error in getting deployed CM/CS history", "err", err) + return histories, err + } + return histories, nil +} diff --git a/pkg/pipeline/history/repository/DeploymentTemplateHistoryRepository.go b/pkg/pipeline/history/repository/DeploymentTemplateHistoryRepository.go new file mode 100644 index 0000000000..a0f172eb26 --- /dev/null +++ b/pkg/pipeline/history/repository/DeploymentTemplateHistoryRepository.go @@ -0,0 +1,83 @@ +package repository + +import ( + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type DeploymentTemplateHistoryRepository interface { + CreateHistory(chart *DeploymentTemplateHistory) (*DeploymentTemplateHistory, error) + CreateHistoryWithTxn(chart *DeploymentTemplateHistory, tx *pg.Tx) (*DeploymentTemplateHistory, error) + GetHistoryForDeployedTemplateById(id, pipelineId int) (*DeploymentTemplateHistory, error) + GetDeploymentDetailsForDeployedTemplateHistory(pipelineId, offset, limit int) ([]*DeploymentTemplateHistory, error) +} + +type DeploymentTemplateHistoryRepositoryImpl struct { + dbConnection *pg.DB + logger *zap.SugaredLogger +} + +func NewDeploymentTemplateHistoryRepositoryImpl(logger *zap.SugaredLogger, dbConnection *pg.DB) *DeploymentTemplateHistoryRepositoryImpl { + return &DeploymentTemplateHistoryRepositoryImpl{dbConnection: dbConnection, logger: logger} +} + +type DeploymentTemplateHistory struct { + tableName struct{} `sql:"deployment_template_history" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + PipelineId int `sql:"pipeline_id"` + AppId int `sql:"app_id"` + ImageDescriptorTemplate string `sql:"image_descriptor_template"` + Template string `sql:"template"` + TargetEnvironment int `sql:"target_environment"` + TemplateName string `sql:"template_name"` + TemplateVersion string `sql:"template_version"` + IsAppMetricsEnabled bool `sql:"is_app_metrics_enabled,notnull"` + Deployed bool `sql:"deployed"` + DeployedOn time.Time `sql:"deployed_on"` + DeployedBy int32 `sql:"deployed_by"` + sql.AuditLog +} + +func (impl DeploymentTemplateHistoryRepositoryImpl) CreateHistory(chart *DeploymentTemplateHistory) (*DeploymentTemplateHistory, error) { + err := impl.dbConnection.Insert(chart) + if err != nil { + impl.logger.Errorw("err in creating deployment template history entry", "err", err, "history", chart) + return chart, err + } + return chart, nil +} + +func (impl DeploymentTemplateHistoryRepositoryImpl) CreateHistoryWithTxn(chart *DeploymentTemplateHistory, tx *pg.Tx) (*DeploymentTemplateHistory, error) { + err := tx.Insert(chart) + if err != nil { + impl.logger.Errorw("err in creating deployment template history entry", "err", err, "history", chart) + return chart, err + } + return chart, nil +} + +func (impl DeploymentTemplateHistoryRepositoryImpl) GetHistoryForDeployedTemplateById(id, pipelineId int) (*DeploymentTemplateHistory, error) { + var history DeploymentTemplateHistory + err := impl.dbConnection.Model(&history).Where("id = ?", id). + Where("pipeline_id = ?", pipelineId). + Where("deployed = ?", true).Select() + if err != nil { + impl.logger.Errorw("error in getting deployment template history", "err", err) + return &history, err + } + return &history, nil +} + +func (impl DeploymentTemplateHistoryRepositoryImpl) GetDeploymentDetailsForDeployedTemplateHistory(pipelineId, offset, limit int) ([]*DeploymentTemplateHistory, error) { + var histories []*DeploymentTemplateHistory + err := impl.dbConnection.Model(&histories).Where("pipeline_id = ?", pipelineId). + Where("deployed = ?", true). + Offset(offset).Limit(limit).Select() + if err != nil { + impl.logger.Errorw("error in getting deployment template history", "err", err) + return histories, err + } + return histories, nil +} diff --git a/pkg/pipeline/history/repository/PipelineStrategyHistoryRepository.go b/pkg/pipeline/history/repository/PipelineStrategyHistoryRepository.go new file mode 100644 index 0000000000..dd6de81a01 --- /dev/null +++ b/pkg/pipeline/history/repository/PipelineStrategyHistoryRepository.go @@ -0,0 +1,79 @@ +package repository + +import ( + "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type PipelineStrategyHistoryRepository interface { + CreateHistory(model *PipelineStrategyHistory) (*PipelineStrategyHistory, error) + CreateHistoryWithTxn(model *PipelineStrategyHistory, tx *pg.Tx) (*PipelineStrategyHistory, error) + GetHistoryForDeployedStrategyById(id, pipelineId int) (*PipelineStrategyHistory, error) + GetDeploymentDetailsForDeployedStrategyHistory(pipelineId int) ([]*PipelineStrategyHistory, error) +} + +type PipelineStrategyHistoryRepositoryImpl struct { + dbConnection *pg.DB + logger *zap.SugaredLogger +} + +func NewPipelineStrategyHistoryRepositoryImpl(logger *zap.SugaredLogger, dbConnection *pg.DB) *PipelineStrategyHistoryRepositoryImpl { + return &PipelineStrategyHistoryRepositoryImpl{dbConnection: dbConnection, logger: logger} +} + +type PipelineStrategyHistory struct { + TableName struct{} `sql:"pipeline_strategy_history" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + PipelineId int `sql:"pipeline_id, notnull"` + Strategy pipelineConfig.DeploymentTemplate `sql:"strategy,notnull"` + Config string `sql:"config"` + Default bool `sql:"default,notnull"` + Deployed bool `sql:"deployed"` + DeployedOn time.Time `sql:"deployed_on"` + DeployedBy int32 `sql:"deployed_by"` + sql.AuditLog +} + +func (impl PipelineStrategyHistoryRepositoryImpl) CreateHistory(model *PipelineStrategyHistory) (*PipelineStrategyHistory, error) { + err := impl.dbConnection.Insert(model) + if err != nil { + impl.logger.Errorw("err in creating strategy history entry", "err", err) + return model, err + } + return model, nil +} + +func (impl PipelineStrategyHistoryRepositoryImpl) CreateHistoryWithTxn(model *PipelineStrategyHistory, tx *pg.Tx) (*PipelineStrategyHistory, error) { + err := tx.Insert(model) + if err != nil { + impl.logger.Errorw("err in creating strategy history entry", "err", err) + return model, err + } + return model, nil +} + +func (impl PipelineStrategyHistoryRepositoryImpl) GetHistoryForDeployedStrategyById(id, pipelineId int) (*PipelineStrategyHistory, error) { + var history PipelineStrategyHistory + err := impl.dbConnection.Model(&history).Where("id = ?", id). + Where("pipeline_id = ?", pipelineId). + Where("deployed = ?", true).Select() + if err != nil { + impl.logger.Errorw("error in getting strategy history", "err", err) + return &history, err + } + return &history, nil +} + +func (impl PipelineStrategyHistoryRepositoryImpl) GetDeploymentDetailsForDeployedStrategyHistory(pipelineId int) ([]*PipelineStrategyHistory, error) { + var histories []*PipelineStrategyHistory + err := impl.dbConnection.Model(&histories).Where("pipeline_id = ?", pipelineId). + Where("deployed = ?", true).Select() + if err != nil { + impl.logger.Errorw("error in getting strategy history", "err", err) + return histories, err + } + return histories, nil +} diff --git a/pkg/pipeline/history/repository/PrePostCdScriptHistoryRepository.go b/pkg/pipeline/history/repository/PrePostCdScriptHistoryRepository.go new file mode 100644 index 0000000000..4dd6c46123 --- /dev/null +++ b/pkg/pipeline/history/repository/PrePostCdScriptHistoryRepository.go @@ -0,0 +1,78 @@ +package repository + +import ( + "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type CdStageType string + +const ( + PRE_CD_TYPE CdStageType = "PRE_CD" + POST_CD_TYPE CdStageType = "POST_CD" +) + +type PrePostCdScriptHistory struct { + tableName struct{} `sql:"pre_post_cd_script_history" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + PipelineId int `sql:"pipeline_id, notnull"` + Script string `sql:"script"` + Stage CdStageType `sql:"stage"` + TriggerType pipelineConfig.TriggerType `sql:"trigger_type"` + ConfigMapSecretNames string `sql:"configmap_secret_names"` + ConfigMapData string `sql:"configmap_data"` + SecretData string `sql:"secret_data"` + ExecInEnv bool `sql:"exec_in_env,notnull"` + Deployed bool `sql:"deployed"` + DeployedOn time.Time `sql:"deployed_on"` + DeployedBy int32 `sql:"deployed_by"` + sql.AuditLog +} + +type PrePostCdScriptHistoryRepository interface { + CreateHistoryWithTxn(history *PrePostCdScriptHistory, tx *pg.Tx) (*PrePostCdScriptHistory, error) + CreateHistory(history *PrePostCdScriptHistory) (*PrePostCdScriptHistory, error) + GetHistoryForDeployedPrePostScriptByStage(pipelineId int, stage CdStageType) ([]*PrePostCdScriptHistory, error) +} + +type PrePostCdScriptHistoryRepositoryImpl struct { + dbConnection *pg.DB + logger *zap.SugaredLogger +} + +func NewPrePostCdScriptHistoryRepositoryImpl(logger *zap.SugaredLogger, dbConnection *pg.DB) *PrePostCdScriptHistoryRepositoryImpl { + return &PrePostCdScriptHistoryRepositoryImpl{dbConnection: dbConnection, logger: logger} +} + +func (impl PrePostCdScriptHistoryRepositoryImpl) CreateHistoryWithTxn(history *PrePostCdScriptHistory, tx *pg.Tx) (*PrePostCdScriptHistory, error) { + err := tx.Insert(history) + if err != nil { + impl.logger.Errorw("err in creating cd script history entry", "err", err, "history", history) + return nil, err + } + return history, nil +} + +func (impl PrePostCdScriptHistoryRepositoryImpl) CreateHistory(history *PrePostCdScriptHistory) (*PrePostCdScriptHistory, error) { + err := impl.dbConnection.Insert(history) + if err != nil { + impl.logger.Errorw("err in creating cd script history entry", "err", err, "history", history) + return nil, err + } + return history, nil +} + +func (impl PrePostCdScriptHistoryRepositoryImpl) GetHistoryForDeployedPrePostScriptByStage(pipelineId int, stage CdStageType) ([]*PrePostCdScriptHistory, error) { + var histories []*PrePostCdScriptHistory + err := impl.dbConnection.Model(&histories).Where("pipeline_id = ?", pipelineId). + Where("stage = ?", stage). + Where("deployed = ?", true).Select() + if err != nil { + impl.logger.Errorw("err in getting cd script history", "err", err, "pipelineId", pipelineId) + return nil, err + } + return histories, nil +} diff --git a/pkg/pipeline/history/repository/PrePostCiScriptHistoryRepository.go b/pkg/pipeline/history/repository/PrePostCiScriptHistoryRepository.go new file mode 100644 index 0000000000..c843a6f590 --- /dev/null +++ b/pkg/pipeline/history/repository/PrePostCiScriptHistoryRepository.go @@ -0,0 +1,53 @@ +package repository + +import ( + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.uber.org/zap" + "time" +) + +type PrePostCiScriptHistory struct { + tableName struct{} `sql:"pre_post_ci_script_history" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + CiPipelineScriptsId int `sql:"ci_pipeline_scripts_id, notnull"` + Script string `sql:"script"` + Stage string `sql:"stage"` + Name string `sql:"name"` + OutputLocation string `sql:"output_location"` + Built bool `sql:"built"` + BuiltOn time.Time `sql:"built_on"` + BuiltBy int32 `sql:"built_by"` + sql.AuditLog +} + +type PrePostCiScriptHistoryRepository interface { + CreateHistoryWithTxn(history *PrePostCiScriptHistory, tx *pg.Tx) (*PrePostCiScriptHistory, error) + CreateHistory(history *PrePostCiScriptHistory) (*PrePostCiScriptHistory, error) +} + +type PrePostCiScriptHistoryRepositoryImpl struct { + dbConnection *pg.DB + logger *zap.SugaredLogger +} + +func NewPrePostCiScriptHistoryRepositoryImpl(logger *zap.SugaredLogger, dbConnection *pg.DB) *PrePostCiScriptHistoryRepositoryImpl { + return &PrePostCiScriptHistoryRepositoryImpl{dbConnection: dbConnection, logger: logger} +} + +func (impl PrePostCiScriptHistoryRepositoryImpl) CreateHistoryWithTxn(history *PrePostCiScriptHistory, tx *pg.Tx) (*PrePostCiScriptHistory, error) { + err := tx.Insert(history) + if err != nil { + impl.logger.Errorw("err in creating ci script history entry", "err", err) + return nil, err + } + return history, nil +} +func (impl PrePostCiScriptHistoryRepositoryImpl) CreateHistory(history *PrePostCiScriptHistory) (*PrePostCiScriptHistory, error) { + err := impl.dbConnection.Insert(history) + if err != nil { + impl.logger.Errorw("err in creating ci script history entry", "err", err) + return nil, err + } + return history, nil +} diff --git a/pkg/user/UserAuthService.go b/pkg/user/UserAuthService.go index 0487fa0f9b..6d85810c2b 100644 --- a/pkg/user/UserAuthService.go +++ b/pkg/user/UserAuthService.go @@ -425,6 +425,8 @@ func WhitelistChecker(url string) bool { "/orchestrator/security/policy/verify/webhook", "/orchestrator/sso/list", "/", + "/orchestrator/dashboard-event/dashboardAccessed", + "/orchestrator/dashboard-event/dashboardLoggedIn", } for _, a := range urls { if a == url { diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/app-values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/app-values.yaml index 79a5ed5529..3213be400f 100644 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/app-values.yaml +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/app-values.yaml @@ -18,7 +18,6 @@ cronjobConfigs: failedJobsHistoryLimit: 1 restartPolicy: OnFailure -replicaCount: 1 MinReadySeconds: 60 GracePeriod: 30 image: @@ -62,79 +61,6 @@ resources: # Optional configs -LivenessProbe: - Path: "" - port: 8080 - scheme: "" - httpHeader: - name: "" - value: "" - tcp: false - command: [] - initialDelaySeconds: 20 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - failureThreshold: 3 - -ReadinessProbe: - Path: "" - port: 8080 - scheme: "" - httpHeader: - name: "" - value: "" - tcp: false - command: [] - initialDelaySeconds: 20 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - failureThreshold: 3 - -ingress: - enabled: false - annotations: - nginx.ingress.kubernetes.io/force-ssl-redirect: 'false' - nginx.ingress.kubernetes.io/ssl-redirect: 'false' - kubernetes.io/ingress.class: nginx -# nginx.ingress.kubernetes.io/rewrite-target: /$2 -# nginx.ingress.kubernetes.io/canary: "true" -# nginx.ingress.kubernetes.io/canary-weight: "10" - - hosts: - - host: chart-example1.local - paths: - - /example1 - - host: chart-example2.local - paths: - - /example2 - - /example2/healthz - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -ingressInternal: - enabled: false - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - # nginx.ingress.kubernetes.io/canary: "true" - # nginx.ingress.kubernetes.io/canary-weight: "10" - - hosts: - - host: chart-example1.internal - paths: - - /example1 - - host: chart-example2.internal - paths: - - /example2 - - /example2/healthz - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local command: enabled: false @@ -184,8 +110,6 @@ volumes: [] # - name: log-volume # emptyDir: {} -dbMigrationConfig: - enabled: false tolerations: [] @@ -195,22 +119,6 @@ Spec: # Key: kops.k8s.io/instancegroup Values: -autoscaling: - enabled: false - MinReplicas: 1 - MaxReplicas: 2 - TargetCPUUtilizationPercentage: 70 - TargetMemoryUtilizationPercentage: 80 - extraMetrics: [] -# - external: -# metricName: pubsub.googleapis.com|subscription|num_undelivered_messages -# metricSelector: -# matchLabels: -# resource.labels.subscription_id: echo-read -# targetAverageValue: "2" -# type: External -# - prometheus: release: monitoring @@ -222,18 +130,6 @@ server: servicemonitor: additionalLabels: {} -envoyproxy: - image: envoyproxy/envoy:v1.14.1 - configMapName: "" - resources: - limits: - cpu: 50m - memory: 50Mi - requests: - cpu: 50m - memory: 50Mi - - imagePullSecrets: [] # - test1 # - test2 diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/Cronjob.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/Cronjob.yaml index 976e6ec95c..929e9e6bd4 100644 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/Cronjob.yaml +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/Cronjob.yaml @@ -25,11 +25,7 @@ {{- end }} {{ if eq .Values.kind "CronJob" }} -{{ if semverCompare "<=1.20" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: batch/v1beta1 -{{- else -}} apiVersion: batch/v1 -{{- end }} kind: CronJob metadata: name: {{ include ".Chart.Name .fullname" $ }} @@ -123,26 +119,6 @@ spec: {{- end}} {{- end}} containers: - {{- if $.Values.appMetrics }} - - name: envoy - image: {{ $.Values.envoyproxy.image | default "envoyproxy/envoy:v1.14.1"}} - resources: - {{- toYaml $.Values.envoyproxy.resources | trim | nindent 14 }} - ports: - - containerPort: 9901 - protocol: TCP - name: envoy-admin - {{- range $index, $element := .Values.ContainerPort }} - - name: {{ $element.name}} - containerPort: {{ $element.envoyPort | default (add 8790 $index) }} - protocol: TCP - {{- end }} - command: ["/usr/local/bin/envoy"] - args: ["-c", "/etc/envoy-config/envoy-config.json", "-l", "info", "--log-format", "[METADATA][%Y-%m-%d %T.%e][%t][%l][%n] %v"] - volumeMounts: - - name: {{ $.Values.envoyproxy.configMapName | default "envoy-config-volume" }} - mountPath: /etc/envoy-config/ - {{- end}} {{- if $.Values.containers }} {{- toYaml $.Values.containers | nindent 12 -}} {{- end}} @@ -225,50 +201,6 @@ spec: {{- end }} {{- end }} - {{- if or $.Values.LivenessProbe.Path $.Values.LivenessProbe.command $.Values.LivenessProbe.tcp }} - livenessProbe: - {{- if $.Values.LivenessProbe.Path }} - httpGet: - path: {{ $.Values.LivenessProbe.Path }} - port: {{ $.Values.LivenessProbe.port }} - {{- end }} - {{- if $.Values.LivenessProbe.command }} - exec: - command: - {{- toYaml .Values.LivenessProbe.command | nindent 20 }} - {{- end}} - {{- if and $.Values.LivenessProbe.tcp }} - tcpSocket: - port: {{ $.Values.LivenessProbe.port }} - {{- end}} - initialDelaySeconds: {{ $.Values.LivenessProbe.initialDelaySeconds }} - periodSeconds: {{ $.Values.LivenessProbe.periodSeconds }} - successThreshold: {{ $.Values.LivenessProbe.successThreshold }} - timeoutSeconds: {{ $.Values.LivenessProbe.timeoutSeconds }} - failureThreshold: {{ $.Values.LivenessProbe.failureThreshold }} - {{- end }} - {{- if or $.Values.ReadinessProbe.Path $.Values.ReadinessProbe.command $.Values.ReadinessProbe.tcp }} - readinessProbe: - {{- if $.Values.ReadinessProbe.Path }} - httpGet: - path: {{ $.Values.ReadinessProbe.Path }} - port: {{ $.Values.ReadinessProbe.port }} - {{- end }} - {{- if $.Values.ReadinessProbe.command }} - exec: - command: - {{- toYaml .Values.ReadinessProbe.command | nindent 20 }} - {{- end}} - {{- if and $.Values.ReadinessProbe.tcp }} - tcpSocket: - port: {{ $.Values.ReadinessProbe.port }} - {{- end}} - initialDelaySeconds: {{ $.Values.ReadinessProbe.initialDelaySeconds }} - periodSeconds: {{ $.Values.ReadinessProbe.periodSeconds }} - successThreshold: {{ $.Values.ReadinessProbe.successThreshold }} - timeoutSeconds: {{ $.Values.ReadinessProbe.timeoutSeconds }} - failureThreshold: {{ $.Values.ReadinessProbe.failureThreshold }} - {{- end }} resources: {{- toYaml $.Values.resources | trim | nindent 16 }} volumeMounts: diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/NOTES.txt b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/NOTES.txt index 2b14478168..c6ccbb8211 100644 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/NOTES.txt +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/NOTES.txt @@ -1,11 +1,5 @@ 1. Get the application URL by running these commands: -{{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range $.Values.ingress.paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host }}{{ . }} - {{- end }} -{{- end }} -{{- else if contains "NodePort" .Values.service.type }} +{{- if contains "NodePort" .Values.service.type }} export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include ".Chart.Name .fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/hpa.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/hpa.yaml deleted file mode 100644 index 2a2937338a..0000000000 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/hpa.yaml +++ /dev/null @@ -1,34 +0,0 @@ -{{- if $.Values.autoscaling.enabled }} ---- -apiVersion: autoscaling/v2beta2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ template ".Chart.Name .fullname" $ }}-hpa -spec: - scaleTargetRef: - apiVersion: argoproj.io/v1alpha1 - kind: Rollout - name: {{ include ".Chart.Name .fullname" $ }} - minReplicas: {{ $.Values.autoscaling.MinReplicas }} - maxReplicas: {{ $.Values.autoscaling.MaxReplicas }} - {{- if $.Values.autoscaling.TargetMemoryUtilizationPercentage }} - metrics: - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ $.Values.autoscaling.TargetMemoryUtilizationPercentage }} - {{- end }} - {{- if $.Values.autoscaling.TargetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ $.Values.autoscaling.TargetCPUUtilizationPercentage }} - {{- end }} - {{- if $.Values.autoscaling.extraMetrics }} - {{toYaml $.Values.autoscaling.extraMetrics | indent 4 }} - {{- end}} - {{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/ingress.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/ingress.yaml deleted file mode 100644 index 9371d7575a..0000000000 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/ingress.yaml +++ /dev/null @@ -1,90 +0,0 @@ -{{ $svcName := include ".servicename" . }} -{{ $svcPort := (index .Values.ContainerPort 0).servicePort }} -{{- if $.Values.ingress.enabled -}} ---- -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template ".Chart.Name .fullname" . }}-ingress - namespace: {{ $.Values.NameSpace }} - labels: - app: {{ template ".Chart.Name .name" . }} - appId: {{ $.Values.app | quote }} - envId: {{ $.Values.env | quote }} - chart: {{ template ".Chart.Name .chart" . }} - release: {{ .Release.Name }} -{{- if .Values.ingress.annotations }} - annotations: -{{ toYaml .Values.ingress.annotations | indent 4 }} -{{- end }} -spec: - rules: - {{- if or .Values.ingress.host .Values.ingress.path }} - - host: {{ .Values.ingress.host }} - http: - paths: - - path: {{ .Values.ingress.path }} - backend: - serviceName: {{ $svcName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ . }} - backend: - serviceName: {{ $svcName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: -{{ toYaml .Values.ingress.tls | indent 4 }} - {{- end -}} -{{- end }} -{{- if $.Values.ingressInternal.enabled }} ---- -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template ".Chart.Name .fullname" . }}-ingress-internal - namespace: {{ $.Values.NameSpace }} - labels: - app: {{ template ".Chart.Name .name" . }} - appId: {{ $.Values.app | quote }} - envId: {{ $.Values.env | quote }} - chart: {{ template ".Chart.Name .chart" . }} - release: {{ .Release.Name }} -{{- if .Values.ingressInternal.annotations }} - annotations: -{{ toYaml .Values.ingressInternal.annotations | indent 4 }} -{{- end }} -spec: - rules: - {{- if or .Values.ingressInternal.host .Values.ingressInternal.path }} - - host: {{ .Values.ingressInternal.host }} - http: - paths: - - path: {{ .Values.ingressInternal.path }} - backend: - serviceName: {{ $svcName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- range .Values.ingressInternal.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ . }} - backend: - serviceName: {{ $svcName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- if .Values.ingressInternal.tls }} - tls: -{{ toYaml .Values.ingressInternal.tls | indent 4 }} - {{- end -}} -{{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/job.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/job.yaml index a9d0a20311..1209ef073e 100644 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/job.yaml +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/job.yaml @@ -28,7 +28,7 @@ apiVersion: batch/v1 kind: Job metadata: - name: {{ include ".Chart.Name .fullname" $ }} + name: {{ include ".Chart.Name .fullname" $ }}-{{ .Release.Revision }} labels: app: {{ template ".Chart.Name .name" $ }} chart: {{ template ".Chart.Name .chart" $ }} @@ -118,26 +118,6 @@ spec: {{- end}} {{- end}} containers: -{{- if $.Values.appMetrics }} - - name: envoy - image: {{ $.Values.envoyproxy.image | default "envoyproxy/envoy:v1.14.1"}} - resources: -{{ toYaml $.Values.envoyproxy.resources | trim | indent 12 }} - ports: - - containerPort: 9901 - protocol: TCP - name: envoy-admin - {{- range $index, $element := .Values.ContainerPort }} - - name: {{ $element.name}} - containerPort: {{ $element.envoyPort | default (add 8790 $index) }} - protocol: TCP - {{- end }} - command: ["/usr/local/bin/envoy"] - args: ["-c", "/etc/envoy-config/envoy-config.json", "-l", "info", "--log-format", "[METADATA][%Y-%m-%d %T.%e][%t][%l][%n] %v"] - volumeMounts: - - name: {{ $.Values.envoyproxy.configMapName | default "envoy-config-volume" }} - mountPath: /etc/envoy-config/ -{{- end}} {{- if $.Values.containers }} {{ toYaml $.Values.containers | indent 8 -}} {{- end}} @@ -219,51 +199,6 @@ spec: {{- end }} {{- end }} {{- end }} - -{{- if or $.Values.LivenessProbe.Path $.Values.LivenessProbe.command $.Values.LivenessProbe.tcp }} - livenessProbe: -{{- if $.Values.LivenessProbe.Path }} - httpGet: - path: {{ $.Values.LivenessProbe.Path }} - port: {{ $.Values.LivenessProbe.port }} -{{- end }} -{{- if $.Values.LivenessProbe.command }} - exec: - command: -{{ toYaml .Values.LivenessProbe.command | indent 16 }} -{{- end}} -{{- if and $.Values.LivenessProbe.tcp }} - tcpSocket: - port: {{ $.Values.LivenessProbe.port }} -{{- end}} - initialDelaySeconds: {{ $.Values.LivenessProbe.initialDelaySeconds }} - periodSeconds: {{ $.Values.LivenessProbe.periodSeconds }} - successThreshold: {{ $.Values.LivenessProbe.successThreshold }} - timeoutSeconds: {{ $.Values.LivenessProbe.timeoutSeconds }} - failureThreshold: {{ $.Values.LivenessProbe.failureThreshold }} -{{- end }} -{{- if or $.Values.ReadinessProbe.Path $.Values.ReadinessProbe.command $.Values.ReadinessProbe.tcp }} - readinessProbe: -{{- if $.Values.ReadinessProbe.Path }} - httpGet: - path: {{ $.Values.ReadinessProbe.Path }} - port: {{ $.Values.ReadinessProbe.port }} -{{- end }} -{{- if $.Values.ReadinessProbe.command }} - exec: - command: -{{ toYaml .Values.ReadinessProbe.command | indent 16 }} -{{- end}} -{{- if and $.Values.ReadinessProbe.tcp }} - tcpSocket: - port: {{ $.Values.ReadinessProbe.port }} -{{- end}} - initialDelaySeconds: {{ $.Values.ReadinessProbe.initialDelaySeconds }} - periodSeconds: {{ $.Values.ReadinessProbe.periodSeconds }} - successThreshold: {{ $.Values.ReadinessProbe.successThreshold }} - timeoutSeconds: {{ $.Values.ReadinessProbe.timeoutSeconds }} - failureThreshold: {{ $.Values.ReadinessProbe.failureThreshold }} -{{- end }} resources: {{ toYaml $.Values.resources | trim | indent 12 }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/poddisruptionbudget.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/poddisruptionbudget.yaml deleted file mode 100644 index 4808b3970c..0000000000 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if .Values.podDisruptionBudget }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ include ".Chart.Name .fullname" $ }} - labels: - app: {{ template ".Chart.Name .name" $ }} - appId: {{ $.Values.app | quote }} - envId: {{ $.Values.env | quote }} -spec: - {{- if .Values.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} - {{- end }} - {{- if .Values.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} - {{- end }} - selector: - matchLabels: - appId: {{ $.Values.app | quote }} - envId: {{ $.Values.env | quote }} - {{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/pre-sync-job.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/pre-sync-job.yaml deleted file mode 100644 index cd733d4857..0000000000 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/templates/pre-sync-job.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if $.Values.dbMigrationConfig.enabled }} ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ template ".Chart.Name .fullname" $ }}-migrator - annotations: - argocd.argoproj.io/hook: PreSync -# argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - template: - spec: - containers: - - name: migrator - image: 686244538589.dkr.ecr.us-east-2.amazonaws.com/migrator:0.0.1-rc14 - env: - {{- range $.Values.dbMigrationConfig.envValues }} - - name: {{ .key}} - value: {{ .value | quote }} - {{- end}} - restartPolicy: Never - backoffLimit: 0 -{{- end }} \ No newline at end of file diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/test_values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/test_values.yaml index 49b60fc420..1bb182a422 100644 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/test_values.yaml +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/test_values.yaml @@ -23,7 +23,6 @@ cronjobConfigs: imagePullSecrets: - test1 - test2 -replicaCount: 1 MinReadySeconds: 5 MaxSurge: 1 MaxUnavailable: 0 @@ -47,7 +46,6 @@ ContainerPort: regex: '(.*)' replacement: myapp targetLabel: target_namespace - - name: app1 port: 8090 servicePort: 8080 @@ -73,22 +71,6 @@ Spec: image: pullPolicy: IfNotPresent -autoscaling: - enabled: true - MinReplicas: 1 - MaxReplicas: 2 - TargetCPUUtilizationPercentage: 90 - TargetMemoryUtilizationPercentage: 80 - extraMetrics: [] -# - external: -# metricName: pubsub.googleapis.com|subscription|num_undelivered_messages -# metricSelector: -# matchLabels: -# resource.labels.subscription_id: echo-read -# targetAverageValue: "2" -# type: External -# - secret: enabled: false @@ -110,24 +92,6 @@ EnvVariables: - name: FLASK_ENV value: qa -LivenessProbe: - Path: / - port: 8080 - initialDelaySeconds: 20 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - failureThreshold: 3 - -ReadinessProbe: - Path: / - port: 8080 - initialDelaySeconds: 20 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - failureThreshold: 3 - prometheus: release: monitoring @@ -158,55 +122,6 @@ prometheusRule: description: Too many 4XXs summary: More than 5% of the all requests did return 4XX, this require your attention - -ingress: - enabled: false - annotations: {} -# nginx.ingress.kubernetes.io/rewrite-target: / -# nginx.ingress.kubernetes.io/ssl-redirect: "false" -# kubernetes.io/ingress.class: nginx -# kubernetes.io/tls-acme: "true" -# nginx.ingress.kubernetes.io/canary: "true" -# nginx.ingress.kubernetes.io/canary-weight: "10" - - hosts: - - host: chart-example1.local - paths: - - /example1 - - host: chart-example2.local - paths: - - /example2 - - /example2/healthz - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -ingressInternal: - enabled: false - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - # nginx.ingress.kubernetes.io/canary: "true" - # nginx.ingress.kubernetes.io/canary-weight: "10" - - hosts: - - host: chart-example1.internal - paths: - - /example1 - - host: chart-example2.internal - paths: - - /example2 - - /example2/healthz - tls: [] - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -dbMigrationConfig: - enabled: false - command: enabled: true value: @@ -391,17 +306,6 @@ rawYaml: [] # sessionAffinity: None # type: ClusterIP -envoyproxy: - image: envoyproxy/envoy:v1.14.1 - configMapName: "" - resources: - limits: - cpu: 50m - memory: 50Mi - requests: - cpu: 50m - memory: 50Mi - podDisruptionBudget: {} # minAvailable: 1 # maxUnavailable: 1 diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/values.yaml index 439e4cc9d2..8a68e713e4 100644 --- a/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/values.yaml +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-2-0/values.yaml @@ -2,7 +2,6 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -replicaCount: 1 MinReadySeconds: 5 MaxSurge: 1 MaxUnavailable: 0 @@ -46,22 +45,6 @@ Spec: image: pullPolicy: IfNotPresent -autoscaling: - enabled: false - MinReplicas: 1 - MaxReplicas: 2 - TargetCPUUtilizationPercentage: 90 - TargetMemoryUtilizationPercentage: 80 - extraMetrics: [] -# - external: -# metricName: pubsub.googleapis.com|subscription|num_undelivered_messages -# metricSelector: -# matchLabels: -# resource.labels.subscription_id: echo-read -# targetAverageValue: "2" -# type: External -# - secret: enabled: false @@ -86,24 +69,6 @@ EnvVariablesFromFieldPath: - name: POD_NAME fieldPath: metadata.name -LivenessProbe: - Path: / - port: 8080 - initialDelaySeconds: 20 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - failureThreshold: 3 - -ReadinessProbe: - Path: / - port: 8080 - initialDelaySeconds: 20 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - failureThreshold: 3 - prometheus: release: monitoring @@ -135,45 +100,6 @@ prometheusRule: # summary: More than 5% of the all requests did return 4XX, this require your attention # -ingress: - enabled: false - annotations: {} -# nginx.ingress.kubernetes.io/rewrite-target: / -# nginx.ingress.kubernetes.io/ssl-redirect: "false" -# kubernetes.io/ingress.class: nginx -# kubernetes.io/tls-acme: "true" -# nginx.ingress.kubernetes.io/canary: "true" -# nginx.ingress.kubernetes.io/canary-weight: "10" - - hosts: - - host: chart-example1.local - paths: - - /example1 - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -ingressInternal: - enabled: false - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - # nginx.ingress.kubernetes.io/canary: "true" - # nginx.ingress.kubernetes.io/canary-weight: "10" - - hosts: - - host: chart-example1.internal - paths: - - /example1 - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -dbMigrationConfig: - enabled: false - command: enabled: false value: [] @@ -324,17 +250,6 @@ rawYaml: [] # sessionAffinity: None # type: ClusterIP -envoyproxy: - image: envoyproxy/envoy:v1.14.1 - configMapName: "" - resources: - limits: - cpu: 50m - memory: 50Mi - requests: - cpu: 50m - memory: 50Mi - podDisruptionBudget: {} # minAvailable: 1 # maxUnavailable: 1 diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/.image_descriptor_template.json b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/.image_descriptor_template.json new file mode 100644 index 0000000000..8a99a95664 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/.image_descriptor_template.json @@ -0,0 +1 @@ +{"server":{"deployment":{"image_tag":"{{.Tag}}","image":"{{.Name}}"}},"pipelineName": "{{.PipelineName}}","releaseVersion":"{{.ReleaseVersion}}","deploymentType": "{{.DeploymentType}}", "app": "{{.App}}", "env": "{{.Env}}", "appMetrics": {{.AppMetrics}}} \ No newline at end of file diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/Chart.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/Chart.yaml new file mode 100644 index 0000000000..290292f362 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart for Kubernetes +name: cronjob-chart_1-3-0 +version: 1.3.0 diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/app-values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/app-values.yaml new file mode 100644 index 0000000000..e5bf39b3ac --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/app-values.yaml @@ -0,0 +1,145 @@ +# Mandatory configs +kind: Job + +jobConfigs: + backoffLimit: 5 + activeDeadlineSeconds: 100 + parallelism: 1 + completions: 2 + suspend: false + ttlSecondsAfterFinished: 100 + +cronjobConfigs: + schedule: "* * * * *" + startingDeadlineSeconds: 100 + concurrencyPolicy: Allow + suspend: false + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + restartPolicy: OnFailure + +MinReadySeconds: 60 +GracePeriod: 30 +image: + pullPolicy: IfNotPresent +service: + type: ClusterIP + #name: "service-1234567890" + annotations: {} + # test1: test2 + # test3: test4 +ContainerPort: + - name: app + port: 8080 + servicePort: 80 + envoyPort: 8799 + useHTTP2: true + supportStreaming: true + idleTimeout: 1800s +# servicemonitor: +# enabled: true +# path: /abc +# scheme: 'http' +# interval: 30s +# scrapeTimeout: 20s +# metricRelabelings: +# - sourceLabels: [namespace] +# regex: '(.*)' +# replacement: myapp +# targetLabel: target_namespace +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 1 + memory: 200Mi + requests: + cpu: 0.10 + memory: 100Mi + + +# Optional configs + +command: + enabled: false + value: [] + +args: + enabled: false + value: + - /bin/sh + - -c + - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 + +#For adding custom labels to pods + +podLabels: {} +# customKey: customValue +podAnnotations: {} +# customKey: customValue + +rawYaml: [] + +initContainers: [] + ## Additional init containers to run before the Scheduler pods. + ## for example, be used to run a sidecar that chown Logs storage. + #- name: volume-mount-hack + # image: busybox + # command: ["sh", "-c", "chown -R 1000:1000 logs"] + # volumeMounts: + # - mountPath: /usr/local/airflow/logs + # name: logs-data + +containers: [] + ## Additional containers to run along with application pods. + ## for example, be used to run a sidecar that chown Logs storage . + #- name: volume-mount-hack + # image: busybox + # command: ["sh", "-c", "chown -R 1000:1000 logs"] + # volumeMounts: + # - mountPath: /usr/local/airflow/logs + # name: logs-data + +volumeMounts: [] +# - name: log-volume +# mountPath: /var/log + +volumes: [] +# - name: log-volume +# emptyDir: {} + + +tolerations: [] + +Spec: + Affinity: + Key: + # Key: kops.k8s.io/instancegroup + Values: + +prometheus: + release: monitoring + +server: + deployment: + image_tag: 1-95af053 + image: "" + +servicemonitor: + additionalLabels: {} + +imagePullSecrets: [] + # - test1 + # - test2 + +containerSecurityContext: + allowPrivilegeEscalation: false + +podSecurityContext: {} + # runAsUser: 1000 + # runAsGroup: 3000 + # fsGroup: 2000 + +shareProcessNamespace: false \ No newline at end of file diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/env-values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/env-values.yaml new file mode 100644 index 0000000000..a0fcb7e26b --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/env-values.yaml @@ -0,0 +1,33 @@ +MaxSurge: 1 +MaxUnavailable: 0 +GracePeriod: 30 +pauseForSecondsBeforeSwitchActive: 30 +waitForSecondsBeforeScalingDown: 30 + +Spec: + Affinity: + key: "" + Values: nodes + +secret: + enabled: false + data: {} +# my_own_secret: S3ViZXJuZXRlcyBXb3Jrcw== + +EnvVariables: [] +# - name: FLASK_ENV +# value: qa + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: "0.05" + memory: 50Mi + requests: + cpu: "0.01" + memory: 10Mi + + diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/pipeline-values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/pipeline-values.yaml new file mode 100644 index 0000000000..40a5ec633d --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/pipeline-values.yaml @@ -0,0 +1,24 @@ +deployment: + strategy: + blueGreen: + autoPromotionSeconds: 30 + scaleDownDelaySeconds: 30 + previewReplicaCount: 1 + autoPromotionEnabled: false + rolling: + maxSurge: "25%" + maxUnavailable: 1 + canary: + maxSurge: "25%" + maxUnavailable: 1 + steps: + - setWeight: 25 + - pause: + duration: 15 # 1 min + - setWeight: 50 + - pause: + duration: 15 # 1 min + - setWeight: 75 + - pause: + duration: 15 # 1 min + recreate: {} \ No newline at end of file diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/release-values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/release-values.yaml new file mode 100644 index 0000000000..48eb3f482c --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/release-values.yaml @@ -0,0 +1,14 @@ +server: + deployment: + image_tag: IMAGE_TAG + image: IMAGE_REPO + enabled: false +dbMigrationConfig: + enabled: false + +pauseForSecondsBeforeSwitchActive: 0 +waitForSecondsBeforeScalingDown: 0 +autoPromotionSeconds: 30 + +#used for deployment algo selection +orchestrator.deploymant.algo: 1 diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/secrets-test-values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/secrets-test-values.yaml new file mode 100644 index 0000000000..4a20404db8 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/secrets-test-values.yaml @@ -0,0 +1 @@ +{"ConfigSecrets":{"enabled":true,"secrets":[{"data":{"standard_key":"c3RhbmRhcmQtdmFsdWU="},"external":false,"externalType":"","mountPath":"/test","name":"normal-secret","type":"volume"},{"data":{"secret_key":"U0VDUkVUIERBVEE="},"external":true,"externalType":"AWSSecretsManager","mountPath":"","name":"external-secret-3","type":"environment"}]}} \ No newline at end of file diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/NOTES.txt b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/NOTES.txt new file mode 100644 index 0000000000..c6ccbb8211 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/NOTES.txt @@ -0,0 +1,13 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include ".Chart.Name .fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ include ".Chart.Name .fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include ".Chart.Name .fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include ".Chart.Name .name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") +{{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/_helpers.tpl b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/_helpers.tpl new file mode 100644 index 0000000000..884c4adfed --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/_helpers.tpl @@ -0,0 +1,133 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define ".Chart.Name .name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create service name +*/}} +{{- define ".servicename" -}} +{{- if .Values.service.name -}} +{{- .Values.service.name | trunc 63 | trimSuffix "-" -}} +{{- else if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 55 | trimSuffix "-" -}}-service +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 55 | trimSuffix "-" -}}-service +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 55 | trimSuffix "-" -}}-service +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create preview service name +*/}} +{{- define ".previewservicename" -}} +{{- if .Values.service.name -}} +{{- .Values.service.name | trunc 55 | trimSuffix "-" -}}-preview +{{- else if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 47 | trimSuffix "-" -}}-preview-service +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 47 | trimSuffix "-" -}}-preview-service +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 47 | trimSuffix "-" -}}-preview-service +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define ".Chart.Name .fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define ".Chart.Name .chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define ".Chart.Name .color" -}} +{{- $active0 := (index .Values.server.deployment 0).enabled -}} +{{/* +{{- $active1 := (index .Values.server.deployment 1).enabled -}} +*/}} +{{- $active1 := include "safeenabledcheck" . -}} +{{- $active := and $active0 $active1 -}} +{{- $active -}} +{{- end -}} + +{{- define "safeenabledcheck" -}} +{{- if (eq (len .Values.server.deployment) 2) -}} + {{- if (index .Values.server.deployment 1).enabled -}} + {{- $active := true -}} + {{- $active -}} + {{- else -}} + {{- $active := false -}} + {{- $active -}} + {{- end -}} +{{- else -}} + {{- $active := false -}} + {{- $active -}} +{{- end -}} +{{- end -}} + + +{{- define "isCMVolumeExists" -}} + {{- $isCMVolumeExists := false -}} + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "volume"}} + {{- $isCMVolumeExists = true}} + {{- end }} + {{- end }} + {{- end }} + {{- $isCMVolumeExists -}} +{{- end -}} + +{{- define "isSecretVolumeExists" -}} + {{- $isSecretVolumeExists := false -}} + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "volume"}} + {{- $isSecretVolumeExists = true}} + {{- end }} + {{- end }} + {{- end }} + {{- $isSecretVolumeExists -}} +{{- end -}} + + + + +{{- define "serviceMonitorEnabled" -}} + {{- $SMenabled := false -}} + {{- range .Values.ContainerPort }} + {{- if .servicemonitor }} + {{- if and .servicemonitor.enabled }} + {{- $SMenabled = true -}} + {{- end }} + {{- end }} + {{- end }} + {{- $SMenabled -}} +{{- end -}} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/configmap.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/configmap.yaml new file mode 100644 index 0000000000..ac7f15fafb --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/configmap.yaml @@ -0,0 +1,14 @@ +{{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{if eq .external false}} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + creationTimestamp: 2019-08-12T18:38:34Z + name: {{ .name}}-{{ $.Values.app }} +data: +{{ toYaml .data | trim | indent 2 }} + {{- end}} + {{- end}} +{{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/cronjob.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/cronjob.yaml new file mode 100644 index 0000000000..520b559ecf --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/cronjob.yaml @@ -0,0 +1,303 @@ + {{- $hasCMEnvExists := false -}} + {{- $hasCMVolumeExists := false -}} + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "volume"}} + {{- $hasCMVolumeExists = true}} + {{- end }} + {{- if eq .type "environment"}} + {{- $hasCMEnvExists = true}} + {{- end }} + {{- end }} + {{- end }} + + {{- $hasSecretEnvExists := false -}} + {{- $hasSecretVolumeExists := false -}} + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "volume"}} + {{- $hasSecretVolumeExists = true}} + {{- end }} + {{- if eq .type "environment"}} + {{- $hasSecretEnvExists = true }} + {{- end }} + {{- end }} + {{- end }} + +{{ if eq .Values.kind "CronJob" }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include ".Chart.Name .fullname" $ }} + labels: + app: {{ template ".Chart.Name .name" $ }} + chart: {{ template ".Chart.Name .chart" $ }} + release: {{ $.Release.Name }} + releaseVersion: {{ $.Values.releaseVersion | quote }} +spec: + schedule: {{ $.Values.cronjobConfigs.schedule | quote }} + startingDeadlineSeconds: {{ $.Values.cronjobConfigs.startingDeadlineSeconds }} + concurrencyPolicy: {{ $.Values.cronjobConfigs.concurrencyPolicy }} + {{ if semverCompare ">1.20" .Capabilities.KubeVersion.GitVersion -}} + suspend: {{ $.Values.cronjobConfigs.suspend }} + {{- end }} + successfulJobsHistoryLimit: {{ $.Values.cronjobConfigs.successfulJobsHistoryLimit }} + failedJobsHistoryLimit: {{ $.Values.cronjobConfigs.failedJobsHistoryLimit }} + jobTemplate: + spec: + template: + metadata: + {{- if .Values.podAnnotations }} + annotations: + {{- range $key, $value := .Values.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + labels: + app: {{ template ".Chart.Name .name" $ }} + appId: {{ $.Values.app | quote }} + envId: {{ $.Values.env | quote }} + release: {{ $.Release.Name }} + {{- if .Values.podLabels }} +{{ toYaml .Values.podLabels | indent 12 }} + {{- end }} + spec: + shareProcessNamespace: {{ $.Values.shareProcessNamespace }} + terminationGracePeriodSeconds: {{ $.Values.GracePeriod }} + restartPolicy: {{ $.Values.cronjobConfigs.restartPolicy }} + {{- if and $.Values.Spec.Affinity.Key $.Values.Spec.Affinity.Values }} + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ $.Values.Spec.Affinity.Key }} + operator: In + values: + - {{ $.Values.Spec.Affinity.Values | default "nodes" }} + {{- end }} + + {{- if $.Values.serviceAccountName }} + serviceAccountName: {{ $.Values.serviceAccountName }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: + {{- toYaml .Values.tolerations | nindent 12 }} + {{- end }} + {{- if $.Values.podSecurityContext }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 12 }} + {{- end }} + {{- if $.Values.imagePullSecrets}} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end}} + {{- if $.Values.initContainers}} + initContainers: + {{- range $i, $c := .Values.initContainers }} + {{- if .reuseContainerImage}} + - name: {{ $.Chart.Name }}-init-{{ add1 $i }} + image: "{{ $.Values.server.deployment.image }}:{{ $.Values.server.deployment.image_tag }}" + imagePullPolicy: {{ $.Values.image.pullPolicy }} + {{- if .command}} + command: + {{- toYaml .command | nindent 16 -}} + {{- end}} + {{- if .resources}} + resources: + {{- toYaml .resources | nindent 16 -}} + {{- end}} + {{- if .volumeMounts}} + volumeMounts: + {{- toYaml .volumeMounts | nindent 16 -}} + {{- end}} + {{- else}} + - + {{- toYaml $c | nindent 14 -}} + {{- end}} + {{- end}} + {{- end}} + containers: + {{- if $.Values.containers }} + {{- toYaml $.Values.containers | nindent 12 -}} + {{- end}} + - name: {{ $.Chart.Name }} + image: "{{ .Values.server.deployment.image }}:{{ .Values.server.deployment.image_tag }}" + imagePullPolicy: {{ $.Values.image.pullPolicy }} + {{- if $.Values.privileged }} + securityContext: + privileged: true + {{- end}} + {{- if $.Values.containerSecurityContext }} + securityContext: + {{- toYaml .Values.containerSecurityContext | nindent 16 }} + {{- end }} + {{- if and $.Values.containerSecurityContext $.Values.privileged }} + securityContext: + privileged: true + {{- toYaml .Values.containerSecurityContext | nindent 16 }} + {{- end }} + ports: + {{- range $.Values.ContainerPort }} + - name: {{ .name}} + containerPort: {{ .port }} + protocol: TCP + {{- end}} + {{- if and $.Values.command.value $.Values.command.enabled}} + command: + {{- toYaml $.Values.command.value | nindent 16 -}} + {{- end}} + {{- if and $.Values.args.value $.Values.args.enabled}} + args: + {{- toYaml $.Values.args.value | nindent 16 -}} + {{- end }} + env: + - name: CONFIG_HASH + value: {{ include (print $.Chart.Name "/templates/configmap.yaml") . | sha256sum }} + - name: SECRET_HASH + value: {{ include (print $.Chart.Name "/templates/secret.yaml") . | sha256sum }} + - name: DEVTRON_APP_NAME + value: {{ template ".Chart.Name .name" $ }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- range $.Values.EnvVariablesFromFieldPath }} + - name: {{ .name }} + valueFrom: + fieldRef: + fieldPath: {{ .fieldPath }} + {{- end}} + {{- range $.Values.EnvVariables }} + - name: {{ .name}} + value: {{ .value | quote }} + {{- end}} + {{- if or (and ($hasCMEnvExists) (.Values.ConfigMaps.enabled)) (and ($hasSecretEnvExists) (.Values.ConfigSecrets.enabled)) }} + envFrom: + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "environment" }} + - configMapRef: + {{- if eq .external true }} + name: {{ .name }} + {{- else if eq .external false }} + name: {{ .name}}-{{ $.Values.app }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "environment" }} + - secretRef: + {{if eq .external true}} + name: {{ .name }} + {{- else if eq .external false}} + name: {{ .name}}-{{ $.Values.app }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + resources: + {{- toYaml $.Values.resources | trim | nindent 16 }} + volumeMounts: + {{- with .Values.volumeMounts }} + {{- toYaml . | trim | nindent 16 }} + {{- end }} + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "volume"}} + {{- $cmName := .name -}} + {{- $cmMountPath := .mountPath -}} + {{- if eq .subPath false }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath }} + {{- else }} + {{- range $k, $v := .data }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath }}/{{ $k}} + subPath: {{ $k}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "volume"}} + {{- $cmName := .name -}} + {{- $cmMountPath := .mountPath -}} + {{- if eq .subPath false }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath }} + {{- else if and (eq (.subPath) true) (eq (.externalType) "KubernetesSecret") }} + {{- else if and (eq (.subPath) true) (eq (.external) true) }} + {{- range .secretData }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath}}/{{ .name }} + subPath: {{ .name }} + {{- end }} + {{- else }} + {{- range $k, $v := .data }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath}}/{{ $k}} + subPath: {{ $k}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if and (eq (len .Values.volumes) 0) (or (eq (.Values.ConfigSecrets.enabled) true) (eq (.Values.ConfigMaps.enabled) true)) (eq ($hasCMVolumeExists) false) (eq ($hasSecretVolumeExists) false) }} []{{- end }} + {{- if and (eq (len .Values.volumeMounts) 0) (eq (.Values.ConfigSecrets.enabled) false) (eq (.Values.ConfigMaps.enabled) false) }} []{{- end }} + volumes: + {{- if $.Values.appMetrics }} + - name: envoy-config-volume + configMap: + name: sidecar-config-{{ template ".Chart.Name .name" $ }} + {{- end }} + {{- with .Values.volumes }} + {{- toYaml . | trim | nindent 12 }} + {{- end }} + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "volume"}} + - name: {{ .name | replace "." "-"}}-vol + configMap: + {{- if eq .external true }} + name: {{ .name }} + {{- else if eq .external false }} + name: {{ .name}}-{{ $.Values.app }} + {{- end }} + {{- if eq (len .filePermission) 0 }} + {{- else }} + defaultMode: {{ .filePermission}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "volume"}} + - name: {{ .name | replace "." "-"}}-vol + secret: + {{- if eq .external true }} + secretName: {{ .name }} + {{- else if eq .external false }} + secretName: {{ .name}}-{{ $.Values.app }} + {{- end }} + {{- if eq (len .filePermission) 0 }} + {{- else }} + defaultMode: {{ .filePermission}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if and (eq (len .Values.volumes) 0) (or (eq (.Values.ConfigSecrets.enabled) true) (eq (.Values.ConfigMaps.enabled) true)) (eq ($hasCMVolumeExists) false) (eq ($hasSecretVolumeExists) false) (eq (.Values.appMetrics) false) }} []{{- end }} + {{- if and (eq (len .Values.volumes) 0) (eq (.Values.ConfigSecrets.enabled) false) (eq (.Values.ConfigMaps.enabled) false) (eq (.Values.appMetrics) false) }} []{{- end }} +{{ end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/generic.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/generic.yaml new file mode 100644 index 0000000000..7b13e628bd --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/generic.yaml @@ -0,0 +1,4 @@ +{{- range .Values.rawYaml -}} +--- +{{ toYaml . }} + {{- end -}} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/job.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/job.yaml new file mode 100644 index 0000000000..3dc6512876 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/job.yaml @@ -0,0 +1,303 @@ + {{- $hasCMEnvExists := false -}} + {{- $hasCMVolumeExists := false -}} + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "volume"}} + {{- $hasCMVolumeExists = true}} + {{- end }} + {{- if eq .type "environment"}} + {{- $hasCMEnvExists = true}} + {{- end }} + {{- end }} + {{- end }} + + {{- $hasSecretEnvExists := false -}} + {{- $hasSecretVolumeExists := false -}} + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "volume"}} + {{- $hasSecretVolumeExists = true}} + {{- end }} + {{- if eq .type "environment"}} + {{- $hasSecretEnvExists = true}} + {{- end }} + {{- end }} + {{- end }} + +{{ if eq .Values.kind "Job" }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include ".Chart.Name .fullname" $ }}-{{ randAlphaNum 5 | lower }} + labels: + app: {{ template ".Chart.Name .name" $ }} + chart: {{ template ".Chart.Name .chart" $ }} + release: {{ $.Release.Name }} + releaseVersion: {{ $.Values.releaseVersion | quote }} + pipelineName: {{ .Values.pipelineName }} +spec: + backoffLimit: {{ .Values.jobConfigs.backoffLimit }} + activeDeadlineSeconds: {{ .Values.jobConfigs.activeDeadlineSeconds }} + parallelism: {{ .Values.jobConfigs.parallelism }} + completions: {{ .Values.jobConfigs.completions }} + {{ if semverCompare ">1.20" .Capabilities.KubeVersion.GitVersion -}} + suspend: {{ .Values.jobConfigs.suspend }} + {{- end }} + ttlSecondsAfterFinished: {{ .Values.jobConfigs.ttlSecondsAfterFinished }} + template: + metadata: + {{- if .Values.podAnnotations }} + annotations: + {{- range $key, $value := .Values.podAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} + labels: + app: {{ template ".Chart.Name .name" $ }} + appId: {{ $.Values.app | quote }} + envId: {{ $.Values.env | quote }} + release: {{ $.Release.Name }} +{{- if .Values.podLabels }} +{{ toYaml .Values.podLabels | indent 8 }} +{{- end }} + spec: + shareProcessNamespace: {{ $.Values.shareProcessNamespace }} + terminationGracePeriodSeconds: {{ $.Values.GracePeriod }} + restartPolicy: OnFailure +{{- if and $.Values.Spec.Affinity.Key $.Values.Spec.Affinity.Values }} + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ $.Values.Spec.Affinity.Key }} + operator: In + values: + - {{ $.Values.Spec.Affinity.Values | default "nodes" }} +{{- end }} + +{{- if $.Values.serviceAccountName }} + serviceAccountName: {{ $.Values.serviceAccountName }} +{{- end }} + {{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | indent 8 }} + {{- end }} +{{- if $.Values.podSecurityContext }} + securityContext: +{{ toYaml .Values.podSecurityContext | indent 8 }} +{{- end }} +{{- if $.Values.imagePullSecrets}} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} +{{- end}} +{{- if $.Values.initContainers}} + initContainers: +{{- range $i, $c := .Values.initContainers }} +{{- if .reuseContainerImage}} + - name: {{ $.Chart.Name }}-init-{{ add1 $i }} + image: "{{ $.Values.server.deployment.image }}:{{ $.Values.server.deployment.image_tag }}" + imagePullPolicy: {{ $.Values.image.pullPolicy }} +{{- if .command}} + command: +{{ toYaml .command | indent 12 -}} +{{- end}} +{{- if .resources}} + resources: +{{ toYaml .resources | indent 12 -}} +{{- end}} +{{- if .volumeMounts}} + volumeMounts: +{{ toYaml .volumeMounts | indent 12 -}} +{{- end}} +{{- else}} + - +{{ toYaml $c | indent 10 -}} +{{- end}} +{{- end}} +{{- end}} + containers: +{{- if $.Values.containers }} +{{ toYaml $.Values.containers | indent 8 -}} +{{- end}} + - name: {{ $.Chart.Name }} + image: "{{ .Values.server.deployment.image }}:{{ .Values.server.deployment.image_tag }}" + imagePullPolicy: {{ $.Values.image.pullPolicy }} +{{- if $.Values.privileged }} + securityContext: + privileged: true +{{- end}} +{{- if $.Values.containerSecurityContext }} + securityContext: +{{ toYaml .Values.containerSecurityContext | indent 12 }} +{{- end }} +{{- if and $.Values.containerSecurityContext $.Values.privileged }} + securityContext: + privileged: true +{{ toYaml .Values.containerSecurityContext | indent 12 }} +{{- end }} + ports: + {{- range $.Values.ContainerPort }} + - name: {{ .name}} + containerPort: {{ .port }} + protocol: TCP + {{- end}} +{{- if and $.Values.command.value $.Values.command.enabled}} + command: +{{ toYaml $.Values.command.value | indent 12 -}} +{{- end}} +{{- if and $.Values.args.value $.Values.args.enabled}} + args: +{{ toYaml $.Values.args.value | indent 12 -}} +{{- end }} + env: + - name: CONFIG_HASH + value: {{ include (print $.Chart.Name "/templates/configmap.yaml") . | sha256sum }} + - name: SECRET_HASH + value: {{ include (print $.Chart.Name "/templates/secret.yaml") . | sha256sum }} + - name: DEVTRON_APP_NAME + value: {{ template ".Chart.Name .name" $ }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- range $.Values.EnvVariablesFromFieldPath }} + - name: {{ .name }} + valueFrom: + fieldRef: + fieldPath: {{ .fieldPath }} + {{- end}} + {{- range $.Values.EnvVariables }} + - name: {{ .name}} + value: {{ .value | quote }} + {{- end}} + {{- if or (and ($hasCMEnvExists) (.Values.ConfigMaps.enabled)) (and ($hasSecretEnvExists) (.Values.ConfigSecrets.enabled)) }} + envFrom: + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "environment" }} + - configMapRef: + {{- if eq .external true }} + name: {{ .name }} + {{- else if eq .external false }} + name: {{ .name}}-{{ $.Values.app }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "environment" }} + - secretRef: + {{if eq .external true}} + name: {{ .name }} + {{else if eq .external false}} + name: {{ .name}}-{{ $.Values.app }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + resources: +{{ toYaml $.Values.resources | trim | indent 12 }} + + volumeMounts: +{{- with .Values.volumeMounts }} +{{ toYaml . | trim | indent 12 }} +{{- end }} + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "volume"}} + {{- $cmName := .name -}} + {{- $cmMountPath := .mountPath -}} + {{- if eq .subPath false }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath }} + {{- else }} + {{- range $k, $v := .data }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath }}/{{ $k}} + subPath: {{ $k}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "volume"}} + {{- $cmName := .name -}} + {{- $cmMountPath := .mountPath -}} + {{- if eq .subPath false }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath }} + {{- else if and (eq (.subPath) true) (eq (.externalType) "KubernetesSecret") }} + {{- else if and (eq (.subPath) true) (eq (.external) true) }} + {{- range .secretData }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath}}/{{ .name }} + subPath: {{ .name }} + {{- end }} + {{- else }} + {{- range $k, $v := .data }} + - name: {{ $cmName | replace "." "-"}}-vol + mountPath: {{ $cmMountPath}}/{{ $k}} + subPath: {{ $k}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if and (eq (len .Values.volumes) 0) (or (eq (.Values.ConfigSecrets.enabled) true) (eq (.Values.ConfigMaps.enabled) true)) (eq ($hasCMVolumeExists) false) (eq ($hasSecretVolumeExists) false) }} []{{- end }} + {{- if and (eq (len .Values.volumeMounts) 0) (eq (.Values.ConfigSecrets.enabled) false) (eq (.Values.ConfigMaps.enabled) false) }} []{{- end }} + + volumes: + {{- if $.Values.appMetrics }} + - name: envoy-config-volume + configMap: + name: sidecar-config-{{ template ".Chart.Name .name" $ }} + {{- end }} +{{- with .Values.volumes }} +{{ toYaml . | trim | indent 8 }} +{{- end }} + {{- if .Values.ConfigMaps.enabled }} + {{- range .Values.ConfigMaps.maps }} + {{- if eq .type "volume"}} + - name: {{ .name | replace "." "-"}}-vol + configMap: + {{- if eq .external true }} + name: {{ .name }} + {{- else if eq .external false }} + name: {{ .name}}-{{ $.Values.app }} + {{- end }} + {{- if eq (len .filePermission) 0 }} + {{- else }} + defaultMode: {{ .filePermission}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{- if eq .type "volume"}} + - name: {{ .name | replace "." "-"}}-vol + secret: + {{- if eq .external true }} + secretName: {{ .name }} + {{- else if eq .external false }} + secretName: {{ .name}}-{{ $.Values.app }} + {{- end }} + {{- if eq (len .filePermission) 0 }} + {{- else }} + defaultMode: {{ .filePermission}} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if and (eq (len .Values.volumes) 0) (or (eq (.Values.ConfigSecrets.enabled) true) (eq (.Values.ConfigMaps.enabled) true)) (eq ($hasCMVolumeExists) false) (eq ($hasSecretVolumeExists) false) (eq (.Values.appMetrics) false) }} []{{- end }} + {{- if and (eq (len .Values.volumes) 0) (eq (.Values.ConfigSecrets.enabled) false) (eq (.Values.ConfigMaps.enabled) false) (eq (.Values.appMetrics) false) }} []{{- end }} +{{ end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/metrics-service-monitor.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/metrics-service-monitor.yaml new file mode 100644 index 0000000000..9130dc2f80 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/metrics-service-monitor.yaml @@ -0,0 +1,30 @@ +{{- if $.Values.appMetrics -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template ".Chart.Name .fullname" $ }} + labels: + app: {{ template ".Chart.Name .name" . }} + appId: {{ $.Values.app | quote }} + envId: {{ $.Values.env | quote }} + chart: {{ template ".Chart.Name .chart" . }} + release: {{ .Values.prometheus.release }} +spec: + jobLabel: {{ template ".Chart.Name .name" $ }} + endpoints: + - port: envoy-admin + interval: 30s + path: /stats/prometheus + selector: + matchLabels: + app: {{ template ".Chart.Name .name" $ }} + appId: {{ $.Values.app | quote }} + envId: {{ $.Values.env | quote }} + namespaceSelector: + matchNames: + - {{.Release.Namespace}} + podTargetLabels: + - appId + - envId + - rollouts-pod-template-hash +{{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/prometheusrules.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/prometheusrules.yaml new file mode 100644 index 0000000000..90f398bff4 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/prometheusrules.yaml @@ -0,0 +1,22 @@ +{{- if .Values.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template ".Chart.Name .fullname" . }} + {{- if .Values.prometheusRule.namespace }} + namespace: {{ .Values.prometheusRule.namespace }} + {{- end }} + labels: + kind: Prometheus + chart: {{ template ".Chart.Name .chart" . }} + release: {{ .Values.prometheus.release }} + {{- if .Values.prometheusRule.additionalLabels }} +{{ toYaml .Values.prometheusRule.additionalLabels | indent 4 }} + {{- end }} +spec: + {{- with .Values.prometheusRule.rules }} + groups: + - name: {{ template ".Chart.Name .fullname" $ }} + rules: {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/secret.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/secret.yaml new file mode 100644 index 0000000000..9a8ab67837 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/secret.yaml @@ -0,0 +1,57 @@ +{{- if $.Values.secret.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: app-secret +type: Opaque +data: +{{ toYaml $.Values.secret.data | indent 2 }} +{{- end }} + + +{{- if .Values.ConfigSecrets.enabled }} + {{- range .Values.ConfigSecrets.secrets }} + {{if eq .external false}} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name}}-{{ $.Values.app }} +type: Opaque +data: +{{ toYaml .data | trim | indent 2 }} +{{- end}} + {{if eq .external true }} + {{if (or (eq .externalType "AWSSecretsManager") (eq .externalType "AWSSystemManager") (eq .externalType "HashiCorpVault"))}} +--- +apiVersion: kubernetes-client.io/v1 +kind: ExternalSecret +metadata: + name: {{ .name}} +spec: + {{- if .roleARN }} + roleArn: .roleARN + {{- end}} + {{- if eq .externalType "AWSSecretsManager"}} + backendType: secretsManager + {{- end}} + {{- if eq .externalType "AWSSystemManager"}} + backendType: systemManager + {{- end}} + {{- if eq .externalType "HashiCorpVault"}} + backendType: vault + {{- end}} + data: + {{- range .secretData }} + - key: {{.key}} + name: {{.name}} + {{- if .property }} + property: {{.property}} + {{- end}} + isBinary: {{.isBinary}} + {{- end}} + {{- end}} + {{- end}} + {{- end}} + {{- end}} \ No newline at end of file diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/service.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/service.yaml new file mode 100644 index 0000000000..2afbb48f8e --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/service.yaml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template ".servicename" . }} + labels: + app: {{ template ".Chart.Name .name" . }} + appId: {{ $.Values.app | quote }} + envId: {{ $.Values.env | quote }} + chart: {{ template ".Chart.Name .chart" . }} + release: {{ .Release.Name }} +{{- if .Values.service.annotations }} + annotations: +{{ toYaml .Values.service.annotations | indent 4 }} +{{- end}} +spec: + type: {{ .Values.service.type | default "ClusterIP" }} + ports: + {{- range .Values.ContainerPort }} + {{- if .servicePort }} + - port: {{ .servicePort }} + {{- else }} + - port: {{ .port }} + {{- end }} + targetPort: {{ .name }} + protocol: TCP + name: {{ .name }} + {{- end }} + {{- if $.Values.appMetrics }} + - port: 9901 + name: envoy-admin + {{- end }} + selector: + app: {{ template ".Chart.Name .name" . }} +{{- if eq .Values.deploymentType "BLUE-GREEN" }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ template ".previewservicename" . }} + labels: + app: {{ template ".Chart.Name .name" . }} + appId: {{ $.Values.app | quote }} + envId: {{ $.Values.env | quote }} + chart: {{ template ".Chart.Name .chart" . }} + release: {{ .Release.Name }} +spec: + type: ClusterIP + ports: + {{- range .Values.ContainerPort }} + {{- if .servicePort }} + - port: {{ .servicePort }} + {{- else }} + - port: {{ .port }} + {{- end }} + targetPort: {{ .name }} + protocol: TCP + name: {{ .name }} + {{- end }} + {{- if $.Values.appMetrics }} + - port: 9901 + name: envoy-admin + {{- end }} + selector: + app: {{ template ".Chart.Name .name" . }} +{{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/servicemonitor.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/servicemonitor.yaml new file mode 100644 index 0000000000..1f90c722cb --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/servicemonitor.yaml @@ -0,0 +1,48 @@ +{{ $serviceMonitorEnabled := include "serviceMonitorEnabled" . }} +{{- if eq "true" $serviceMonitorEnabled -}} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template ".Chart.Name .fullname" . }}-sm + labels: + kind: Prometheus + app: {{ template ".Chart.Name .name" . }} + appId: {{ $.Values.app | quote }} + envId: {{ $.Values.env | quote }} + chart: {{ template ".Chart.Name .chart" . }} + release: {{ .Values.prometheus.release }} + {{- if .Values.servicemonitor.additionalLabels }} +{{ toYaml .Values.servicemonitor.additionalLabels | indent 4 }} + {{- end }} +spec: + endpoints: + {{- range .Values.ContainerPort }} + {{- if .servicemonitor }} + {{- if .servicemonitor.enabled}} + {{- if .servicePort }} + - port: {{ .name }} + {{- if .servicemonitor.path }} + path: {{ .servicemonitor.path}} + {{- end }} + {{- if .servicemonitor.scheme }} + scheme: {{ .servicemonitor.scheme}} + {{- end }} + {{- if .servicemonitor.interval }} + interval: {{ .servicemonitor.interval}} + {{- end }} + {{- if .servicemonitor.scrapeTimeout }} + scrapeTimeout: {{ .servicemonitor.scrapeTimeout}} + {{- end }} + {{- if .servicemonitor.metricRelabelings}} + metricRelabelings: +{{toYaml .servicemonitor.metricRelabelings | indent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + selector: + matchLabels: + app: {{ template ".Chart.Name .name" $ }} +{{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/sidecar-configmap.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/sidecar-configmap.yaml new file mode 100644 index 0000000000..30dc74cbda --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/templates/sidecar-configmap.yaml @@ -0,0 +1,166 @@ +{{- if .Values.appMetrics }} +apiVersion: v1 +kind: ConfigMap +metadata: + creationTimestamp: 2019-08-12T18:38:34Z + name: sidecar-config-{{ template ".Chart.Name .name" $ }} +data: + envoy-config.json: | + { + "stats_config": { + "use_all_default_tags": false, + "stats_tags": [ + { + "tag_name": "cluster_name", + "regex": "^cluster\\.((.+?(\\..+?\\.svc\\.cluster\\.local)?)\\.)" + }, + { + "tag_name": "tcp_prefix", + "regex": "^tcp\\.((.*?)\\.)\\w+?$" + }, + { + "tag_name": "response_code", + "regex": "_rq(_(\\d{3}))$" + }, + { + "tag_name": "response_code_class", + "regex": ".*_rq(_(\\dxx))$" + }, + { + "tag_name": "http_conn_manager_listener_prefix", + "regex": "^listener(?=\\.).*?\\.http\\.(((?:[_.[:digit:]]*|[_\\[\\]aAbBcCdDeEfF[:digit:]]*))\\.)" + }, + { + "tag_name": "http_conn_manager_prefix", + "regex": "^http\\.(((?:[_.[:digit:]]*|[_\\[\\]aAbBcCdDeEfF[:digit:]]*))\\.)" + }, + { + "tag_name": "listener_address", + "regex": "^listener\\.(((?:[_.[:digit:]]*|[_\\[\\]aAbBcCdDeEfF[:digit:]]*))\\.)" + }, + { + "tag_name": "mongo_prefix", + "regex": "^mongo\\.(.+?)\\.(collection|cmd|cx_|op_|delays_|decoding_)(.*?)$" + } + ], + "stats_matcher": { + "inclusion_list": { + "patterns": [ + { + "regex": ".*_rq_\\dxx$" + }, + { + "regex": ".*_rq_time$" + }, + { + "regex": "cluster.*" + }, + ] + } + } + }, + "admin": { + "access_log_path": "/dev/null", + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 9901 + } + } + }, + "static_resources": { + "clusters": [ + {{- range $index, $element := .Values.ContainerPort }} + { + "name": "{{ $.Values.app }}-{{ $index }}", + "type": "STATIC", + "connect_timeout": "0.250s", + "lb_policy": "ROUND_ROBIN", +{{- if $element.idleTimeout }} + "common_http_protocol_options": { + "idle_timeout": {{ $element.idleTimeout | quote }} + }, +{{- end }} +{{- if or $element.useHTTP2 $element.useGRPC }} + "http2_protocol_options": {}, +{{- end }} +{{- if and (not $element.useGRPC) (not $element.supportStreaming) }} + "max_requests_per_connection": "1", +{{- end }} + "load_assignment": { + "cluster_name": "9", + "endpoints": { + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "protocol": "TCP", + "address": "127.0.0.1", + "port_value": {{ $element.port }} + } + } + } + } + ] + } + } + }, + {{- end }} + ], + "listeners":[ + {{- range $index, $element := .Values.ContainerPort }} + { + "address": { + "socket_address": { + "protocol": "TCP", + "address": "0.0.0.0", + "port_value": {{ $element.envoyPort | default (add 8790 $index) }} + } + }, + "filter_chains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "config": { + "codec_type": "AUTO", + "stat_prefix": "stats", + "route_config": { + "virtual_hosts": [ + { + "name": "backend", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { +{{- if $element.supportStreaming }} + "timeout": "0s", +{{- end }} + "cluster": "{{ $.Values.app }}-{{ $index }}" + } + } + ] + } + ] + }, + "http_filters": { + "name": "envoy.filters.http.router" + } + } + } + ] + } + ] + }, + {{- end }} + ] + } + } +--- +{{- end }} diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/test_values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/test_values.yaml new file mode 100644 index 0000000000..4d54b81099 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/test_values.yaml @@ -0,0 +1,343 @@ +# Default values for myapp. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +kind: Job + +jobConfigs: + backoffLimit: 5 + activeDeadlineSeconds: 100 + parallelism: 1 + completions: 2 + suspend: false + ttlSecondsAfterFinished: 100 + +cronjobConfigs: + schedule: "* * * * *" + startingDeadlineSeconds: 100 + concurrencyPolicy: Allow + suspend: false + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + restartPolicy: OnFailure + +imagePullSecrets: + - test1 + - test2 +MinReadySeconds: 5 +MaxSurge: 1 +MaxUnavailable: 0 +GracePeriod: 30 +ContainerPort: + - name: app + port: 8080 + servicePort: 80 + envoyPort: 8799 + useHTTP2: true + supportStreaming: true + idleTimeout: 1800s + servicemonitor: + enabled: true + path: /abc + scheme: 'http' + interval: 30s + scrapeTimeout: 20s + metricRelabelings: + - sourceLabels: [namespace] + regex: '(.*)' + replacement: myapp + targetLabel: target_namespace + - name: app1 + port: 8090 + servicePort: 8080 + useGRPC: true + servicemonitor: + enabled: true + - name: app2 + port: 8091 + servicePort: 8081 + useGRPC: true + +pauseForSecondsBeforeSwitchActive: 30 +waitForSecondsBeforeScalingDown: 30 +autoPromotionSeconds: 30 + +Spec: + Affinity: + Key: + # Key: kops.k8s.io/instancegroup + Values: + + +image: + pullPolicy: IfNotPresent + +secret: + enabled: false + +service: + type: ClusterIP + # name: "1234567890123456789012345678901234567890123456789012345678901234567890" + annotations: {} + # test1: test2 + # test3: test4 + +server: + deployment: + image_tag: 1-95af053 + image: "" +deploymentType: "RECREATE" + + +EnvVariables: + - name: FLASK_ENV + value: qa + +prometheus: + release: monitoring + +servicemonitor: + additionalLabels: {} + + +prometheusRule: + enabled: true + additionalLabels: {} + namespace: "" + rules: + # These are just examples rules, please adapt them to your needs + - alert: TooMany500s + expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"5.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 + for: 1m + labels: + severity: critical + annotations: + description: Too many 5XXs + summary: More than 5% of the all requests did return 5XX, this require your attention + - alert: TooMany400s + expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"4.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 + for: 1m + labels: + severity: critical + annotations: + description: Too many 4XXs + summary: More than 5% of the all requests did return 4XX, this require your attention + +command: + enabled: true + value: + - /bin/sh + +args: + enabled: false + value: [] + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 1 + memory: 200Mi + requests: + cpu: 0.10 + memory: 100Mi + +volumeMounts: + - name: log-volume + mountPath: /var/log + +volumes: + - name: log-volume + emptyDir: {} + + +nodeSelector: {} + + +#used for deployment algo selection +orchestrator.deploymant.algo: 1 + +ConfigMaps: + enabled: false + maps: [] + # - name: config-map-1 + # type: environment + # external: false + # data: + # key1: key1value-1 + # key2: key2value-1 + # key3: key3value-1 + # - name: config-map-2 + # type: volume + # external: false + # mountPath: /etc/config/2 + # subPath: false + # filePermission: "777" + # data: + # key1: | + # club : manchester utd + # nation : england + # key2: abc-2 + # key3: abc-2 +# - name: config-map-3 +# type: environment +# external: true +# mountPath: /etc/config/3 +# data: [] +# - name: config-map-4 +# type: volume +# external: true +# mountPath: /etc/config/4 +# data: [] + + +ConfigSecrets: + enabled: false + secrets: [] + # - name: config-secret-1 + # type: environment + # external: false + # data: + # key1: key1value-1 + # key2: key2value-1 + # key3: key3value-1 + # - name: config-secret-2 + # type: volume + # external: false + # mountPath: /etc/config/2 + # subPath: false + # filePermission: "777" + # data: + # key1: | + # club : manchester utd + # nation : england + # key2: abc-2 + # key3: abc-2 + + +initContainers: + ## Additional init containers to run before the Scheduler pods. + ## for example, be used to run a sidecar that chown Logs storage. + ## If reuse container image is set as true, you cannot specify an addition init container along with the image. + # - reuseContainerImage: true + # volumeMounts: + # - mountPath: /etc/ls-oms + # name: ls-oms-cm-vol + # command: + # - flyway + # - -configFiles=/etc/ls-oms/flyway.conf + # - migrate + + # - name: volume-mount-hack + # image: busybox + # command: ["sh", "-c", "chown -R 1000:1000 logs"] + # volumeMounts: + # - mountPath: /usr/local/airflow/logs + # name: logs-data + # resources: + # limits: + # cpu: 50m + # memory: 100Mi + # requests: + # cpu: 10m + # memory: 50Mi + + - name: volume-mount-hack2 + image: busybox + command: ["sh", "-c", "chown -R 1000:1000 logs"] + volumeMounts: + - mountPath: /usr/local/airflow/logs + name: logs-data + resources: + limits: + cpu: 50m + memory: 100Mi + requests: + cpu: 10m + memory: 50Mi + +containers: + ## Additional init containers to run before the Scheduler pods. + ## for example, be used to run a sidecar that chown Logs storage . + # - name: volume-mount-hack + # image: busybox + # command: ["sh", "-c", "chown -R 1000:1000 logs"] + # volumeMounts: + # - mountPath: /usr/local/airflow/logs + # name: logs-data + + +rawYaml: [] +# - apiVersion: v1 +# kind: Service +# metadata: +# annotations: +# labels: +# app: sample-metrics-app +# name: sample-metrics-app +# namespace: default +# spec: +# ports: +# - name: web +# port: 80 +# protocol: TCP +# targetPort: 8080 +# selector: +# app: sample-metrics-app +# sessionAffinity: None +# type: ClusterIP +# - apiVersion: v1 +# kind: Service +# metadata: +# annotations: +# labels: +# app: sample-metrics-app +# name: sample-metrics-app +# namespace: default +# spec: +# ports: +# - name: web +# port: 80 +# protocol: TCP +# targetPort: 8080 +# selector: +# app: sample-metrics-app +# sessionAffinity: None +# type: ClusterIP + +podDisruptionBudget: {} + # minAvailable: 1 + # maxUnavailable: 1 + + ## Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ +## + +tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + +appMetrics: false + +podAnnotations: + fluentbit.io/exclude: true + +podLabels: + severity: critical + +containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - SYS_PTRACE + + +podSecurityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 + +shareProcessNamespace: true diff --git a/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/values.yaml b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/values.yaml new file mode 100644 index 0000000000..8a68e713e4 --- /dev/null +++ b/scripts/devtron-reference-helm-charts/cronjob-chart_1-3-0/values.yaml @@ -0,0 +1,269 @@ +# Default values for myapp. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +MinReadySeconds: 5 +MaxSurge: 1 +MaxUnavailable: 0 +GracePeriod: 30 +ContainerPort: + - name: app + port: 8080 + servicePort: 80 + envoyPort: 8799 + useHTTP2: true + supportStreaming: true + idleTimeout: 1800s +# servicemonitor: +# enabled: true +# path: /abc +# scheme: 'http' +# interval: 30s +# scrapeTimeout: 20s +# metricRelabelings: +# - sourceLabels: [namespace] +# regex: '(.*)' +# replacement: myapp +# targetLabel: target_namespace + + - name: app1 + port: 8090 + servicePort: 8080 + useGRPC: true + +pauseForSecondsBeforeSwitchActive: 30 +waitForSecondsBeforeScalingDown: 30 +autoPromotionSeconds: 30 + +Spec: + Affinity: + Key: +# Key: kops.k8s.io/instancegroup + Values: + + +image: + pullPolicy: IfNotPresent + +secret: + enabled: false + +service: + type: ClusterIP +# name: "1234567890123456789012345678901234567890123456789012345678901234567890" + annotations: {} + # test1: test2 + # test3: test4 + +server: + deployment: + image_tag: 1-95af053 + image: "" + + +EnvVariables: + - name: FLASK_ENV + value: qa + +EnvVariablesFromFieldPath: +- name: POD_NAME + fieldPath: metadata.name + +prometheus: + release: monitoring + +servicemonitor: + additionalLabels: {} + + +prometheusRule: + enabled: false + additionalLabels: {} + namespace: "" +# rules: +# # These are just examples rules, please adapt them to your needs +# - alert: TooMany500s +# expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"5.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 +# for: 1m +# labels: +# severity: critical +# annotations: +# description: Too many 5XXs +# summary: More than 5% of the all requests did return 5XX, this require your attention +# - alert: TooMany400s +# expr: 100 * ( sum( nginx_ingress_controller_requests{status=~"4.+"} ) / sum(nginx_ingress_controller_requests) ) > 5 +# for: 1m +# labels: +# severity: critical +# annotations: +# description: Too many 4XXs +# summary: More than 5% of the all requests did return 4XX, this require your attention +# + +command: + enabled: false + value: [] + +args: + enabled: false + value: [] + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 1 + memory: 200Mi + requests: + cpu: 0.10 + memory: 100Mi + +volumeMounts: [] +# - name: log-volume +# mountPath: /var/log + +volumes: [] +# - name: log-volume +# emptyDir: {} + + +nodeSelector: {} + + +#used for deployment algo selection +orchestrator.deploymant.algo: 1 + +ConfigMaps: + enabled: false + maps: [] +# - name: config-map-1 +# type: environment +# external: false +# data: +# key1: key1value-1 +# key2: key2value-1 +# key3: key3value-1 +# - name: config-map-2 +# type: volume +# external: false +# mountPath: /etc/config/2 +# data: +# key1: | +# club : manchester utd +# nation : england +# key2: abc-2 +# key3: abc-2 +# - name: config-map-3 +# type: environment +# external: true +# mountPath: /etc/config/3 +# data: [] +# - name: config-map-4 +# type: volume +# external: true +# mountPath: /etc/config/4 +# data: [] + + +ConfigSecrets: + enabled: false + secrets: [] +# - name: config-secret-1 +# type: environment +# external: false +# data: +# key1: key1value-1 +# key2: key2value-1 +# key3: key3value-1 +# - name: config-secret-2 +# type: volume +# external: false +# mountPath: /etc/config/2 +# data: +# key1: | +# club : manchester utd +# nation : england +# key2: abc-2 + + +initContainers: [] + ## Additional init containers to run before the Scheduler pods. + ## for example, be used to run a sidecar that chown Logs storage . + #- name: volume-mount-hack + # image: busybox + # command: ["sh", "-c", "chown -R 1000:1000 logs"] + # volumeMounts: + # - mountPath: /usr/local/airflow/logs + # name: logs-data + ## Uncomment below line ONLY IF you want to reuse the container image. + ## This will assign your application's docker image to init container. + # reuseContainerImage: true + +containers: [] + ## Additional init containers to run before the Scheduler pods. + ## for example, be used to run a sidecar that chown Logs storage . + #- name: volume-mount-hack + # image: busybox + # command: ["sh", "-c", "chown -R 1000:1000 logs"] + # volumeMounts: + # - mountPath: /usr/local/airflow/logs + # name: logs-data + + +rawYaml: [] +# - apiVersion: v1 +# kind: Service +# metadata: +# annotations: +# labels: +# app: sample-metrics-app +# name: sample-metrics-app +# namespace: default +# spec: +# ports: +# - name: web +# port: 80 +# protocol: TCP +# targetPort: 8080 +# selector: +# app: sample-metrics-app +# sessionAffinity: None +# type: ClusterIP +# - apiVersion: v1 +# kind: Service +# metadata: +# annotations: +# labels: +# app: sample-metrics-app +# name: sample-metrics-app +# namespace: default +# spec: +# ports: +# - name: web +# port: 80 +# protocol: TCP +# targetPort: 8080 +# selector: +# app: sample-metrics-app +# sessionAffinity: None +# type: ClusterIP + +podDisruptionBudget: {} +# minAvailable: 1 +# maxUnavailable: 1 + + ## Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + +tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + +imagePullSecrets: [] + # - test1 + # - test2 \ No newline at end of file diff --git a/scripts/devtron-reference-helm-charts/reference-chart_3-10-0/app-values.yaml b/scripts/devtron-reference-helm-charts/reference-chart_3-10-0/app-values.yaml index c5959433f2..f86449c8bf 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_3-10-0/app-values.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_3-10-0/app-values.yaml @@ -7,6 +7,10 @@ image: service: type: ClusterIP #name: "service-1234567890" + loadBalancerSourceRanges: [] + # loadBalancerSourceRanges: + # - 1.2.3.4/32 + # - 1.2.5.6/23 annotations: {} # test1: test2 # test3: test4 diff --git a/scripts/devtron-reference-helm-charts/reference-chart_3-10-0/templates/service.yaml b/scripts/devtron-reference-helm-charts/reference-chart_3-10-0/templates/service.yaml index 2afbb48f8e..d360a3097e 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_3-10-0/templates/service.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_3-10-0/templates/service.yaml @@ -14,6 +14,12 @@ metadata: {{- end}} spec: type: {{ .Values.service.type | default "ClusterIP" }} +{{- if (and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges )}} + loadBalancerSourceRanges: + {{- range .Values.service.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} +{{- end }} ports: {{- range .Values.ContainerPort }} {{- if .servicePort }} diff --git a/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/app-values.yaml b/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/app-values.yaml index cd22e43d31..711f419643 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/app-values.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/app-values.yaml @@ -6,6 +6,10 @@ image: pullPolicy: IfNotPresent service: type: ClusterIP + loadBalancerSourceRanges: [] + # loadBalancerSourceRanges: + # - 1.2.3.4/32 + # - 1.2.5.6/23 #name: "service-1234567890" annotations: {} # test1: test2 diff --git a/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/templates/ingress.yaml b/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/templates/ingress.yaml index 9371d7575a..c66afae9db 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/templates/ingress.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/templates/ingress.yaml @@ -28,6 +28,7 @@ spec: serviceName: {{ $svcName }} servicePort: {{ $svcPort }} {{- end }} + {{- if .Values.ingress.hosts }} {{- range .Values.ingress.hosts }} - host: {{ .host | quote }} http: @@ -39,6 +40,7 @@ spec: servicePort: {{ $svcPort }} {{- end }} {{- end }} + {{- end }} {{- if .Values.ingress.tls }} tls: {{ toYaml .Values.ingress.tls | indent 4 }} @@ -72,6 +74,7 @@ spec: serviceName: {{ $svcName }} servicePort: {{ $svcPort }} {{- end }} + {{- if .Values.ingressInternal.hosts }} {{- range .Values.ingressInternal.hosts }} - host: {{ .host | quote }} http: @@ -83,6 +86,7 @@ spec: servicePort: {{ $svcPort }} {{- end }} {{- end }} + {{- end }} {{- if .Values.ingressInternal.tls }} tls: {{ toYaml .Values.ingressInternal.tls | indent 4 }} diff --git a/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/templates/service.yaml b/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/templates/service.yaml index 2afbb48f8e..d360a3097e 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/templates/service.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_3-11-0/templates/service.yaml @@ -14,6 +14,12 @@ metadata: {{- end}} spec: type: {{ .Values.service.type | default "ClusterIP" }} +{{- if (and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges )}} + loadBalancerSourceRanges: + {{- range .Values.service.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} +{{- end }} ports: {{- range .Values.ContainerPort }} {{- if .servicePort }} diff --git a/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/app-values.yaml b/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/app-values.yaml index cd22e43d31..217bef4834 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/app-values.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/app-values.yaml @@ -7,6 +7,10 @@ image: service: type: ClusterIP #name: "service-1234567890" + loadBalancerSourceRanges: [] + # loadBalancerSourceRanges: + # - 1.2.3.4/32 + # - 1.2.5.6/23 annotations: {} # test1: test2 # test3: test4 diff --git a/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/templates/ingress.yaml b/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/templates/ingress.yaml index 9371d7575a..c66afae9db 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/templates/ingress.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/templates/ingress.yaml @@ -28,6 +28,7 @@ spec: serviceName: {{ $svcName }} servicePort: {{ $svcPort }} {{- end }} + {{- if .Values.ingress.hosts }} {{- range .Values.ingress.hosts }} - host: {{ .host | quote }} http: @@ -39,6 +40,7 @@ spec: servicePort: {{ $svcPort }} {{- end }} {{- end }} + {{- end }} {{- if .Values.ingress.tls }} tls: {{ toYaml .Values.ingress.tls | indent 4 }} @@ -72,6 +74,7 @@ spec: serviceName: {{ $svcName }} servicePort: {{ $svcPort }} {{- end }} + {{- if .Values.ingressInternal.hosts }} {{- range .Values.ingressInternal.hosts }} - host: {{ .host | quote }} http: @@ -83,6 +86,7 @@ spec: servicePort: {{ $svcPort }} {{- end }} {{- end }} + {{- end }} {{- if .Values.ingressInternal.tls }} tls: {{ toYaml .Values.ingressInternal.tls | indent 4 }} diff --git a/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/templates/service.yaml b/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/templates/service.yaml index 2afbb48f8e..d360a3097e 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/templates/service.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_3-12-0/templates/service.yaml @@ -14,6 +14,12 @@ metadata: {{- end}} spec: type: {{ .Values.service.type | default "ClusterIP" }} +{{- if (and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges )}} + loadBalancerSourceRanges: + {{- range .Values.service.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} +{{- end }} ports: {{- range .Values.ContainerPort }} {{- if .servicePort }} diff --git a/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/app-values.yaml b/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/app-values.yaml index 704a762d8a..2a2754e738 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/app-values.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/app-values.yaml @@ -7,6 +7,10 @@ image: service: type: ClusterIP #name: "service-1234567890" + loadBalancerSourceRanges: [] + # loadBalancerSourceRanges: + # - 1.2.3.4/32 + # - 1.2.5.6/23 annotations: {} # test1: test2 # test3: test4 diff --git a/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/templates/ingress.yaml b/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/templates/ingress.yaml index f78a9718f7..cc63f652ea 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/templates/ingress.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/templates/ingress.yaml @@ -57,6 +57,7 @@ spec: servicePort: {{ $svcPort }} {{- end }} {{- end }} + {{- if .Values.ingress.hosts }} {{- range .Values.ingress.hosts }} {{ $outer := . -}} - host: {{ .host | quote }} @@ -79,6 +80,7 @@ spec: {{- end }} {{- end }} {{- end }} + {{- end }} {{- if .Values.ingress.tls }} tls: {{ toYaml .Values.ingress.tls | indent 4 }} @@ -131,6 +133,7 @@ spec: servicePort: {{ $svcPort }} {{- end }} {{- end }} + {{- if .Values.ingressInternal.hosts }} {{- range .Values.ingressInternal.hosts }} {{ $outer := . -}} - host: {{ .host | quote }} @@ -153,6 +156,7 @@ spec: {{- end }} {{- end }} {{- end }} + {{- end }} {{- if .Values.ingressInternal.tls }} tls: {{ toYaml .Values.ingressInternal.tls | indent 4 }} diff --git a/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/templates/service.yaml b/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/templates/service.yaml index 2afbb48f8e..d360a3097e 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/templates/service.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_4-10-0/templates/service.yaml @@ -14,6 +14,12 @@ metadata: {{- end}} spec: type: {{ .Values.service.type | default "ClusterIP" }} +{{- if (and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges )}} + loadBalancerSourceRanges: + {{- range .Values.service.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} +{{- end }} ports: {{- range .Values.ContainerPort }} {{- if .servicePort }} diff --git a/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/app-values.yaml b/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/app-values.yaml index bd9a89ff4b..185e2de6e6 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/app-values.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/app-values.yaml @@ -7,6 +7,10 @@ image: service: type: ClusterIP #name: "service-1234567890" + loadBalancerSourceRanges: [] + # loadBalancerSourceRanges: + # - 1.2.3.4/32 + # - 1.2.5.6/23 annotations: {} # test1: test2 # test3: test4 diff --git a/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/templates/deployment.yaml b/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/templates/deployment.yaml index 82505a118b..5a1e8d486d 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/templates/deployment.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/templates/deployment.yaml @@ -310,6 +310,7 @@ spec: {{- if eq .subPath false }} - name: {{ $cmName | replace "." "-"}}-vol mountPath: {{ $cmMountPath }} + {{- else }} {{- range $k, $v := .data }} - name: {{ $cmName | replace "." "-"}}-vol @@ -329,13 +330,7 @@ spec: {{- if eq .subPath false }} - name: {{ $cmName | replace "." "-"}}-vol mountPath: {{ $cmMountPath }} - {{- else if and (eq (.subPath) true) (eq (.externalType) "KubernetesSecret") }} - {{- else if and (eq (.subPath) true) (eq (.external) true) }} - {{- range .secretData }} - - name: {{ $cmName | replace "." "-"}}-vol - mountPath: {{ $cmMountPath}}/{{ .name }} - subPath: {{ .name }} - {{- end }} + {{- else }} {{- range $k, $v := .data }} - name: {{ $cmName | replace "." "-"}}-vol diff --git a/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/templates/service.yaml b/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/templates/service.yaml index 2afbb48f8e..d360a3097e 100644 --- a/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/templates/service.yaml +++ b/scripts/devtron-reference-helm-charts/reference-chart_4-11-0/templates/service.yaml @@ -14,6 +14,12 @@ metadata: {{- end}} spec: type: {{ .Values.service.type | default "ClusterIP" }} +{{- if (and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges )}} + loadBalancerSourceRanges: + {{- range .Values.service.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} +{{- end }} ports: {{- range .Values.ContainerPort }} {{- if .servicePort }} diff --git a/scripts/sql/1_insert.up.sql b/scripts/sql/1_insert.up.sql index 16bf5487ae..cd67b9ecaa 100644 --- a/scripts/sql/1_insert.up.sql +++ b/scripts/sql/1_insert.up.sql @@ -5429,15 +5429,15 @@ INSERT INTO "public"."chart_ref" ("id", "location", "version", "is_default", "ac INSERT INTO "public"."chart_repo" ("id", "name", "url", "is_default", "active", "created_on", "created_by", "updated_on", "updated_by", "external") VALUES ('1', 'default-chartmuseum', 'http://devtron-chartmuseum.devtroncd:8080/', 't', 't', 'now()', '1', 'now()', '1', 'f'), -('2', 'fluent', 'https://fluent.github.io/helm-charts', 'f', 't', 'now()', '1', 'now()', '1', 't'), -('3', 'devtron', 'https://helm.devtron.ai', 'f', 't', 'now()', '1', 'now()', '1', 't'), -('4', 'nginx-ingress', 'https://kubernetes.github.io/ingress-nginx', 'f', 't', 'now()', '1', 'now()', '1', 't'), -('5', 'elastic', 'https://helm.elastic.co', 'f', 't', 'now()', '1', 'now()', '1', 't'), -('6', 'bitnami', 'https://charts.bitnami.com/bitnami', 'f', 't', 'now()', '1', 'now()', '1', 't'), -('7', 'prometheus-community', 'https://prometheus-community.github.io/helm-charts', 'f', 't', 'now()', '1', 'now()', '1', 't'), -('8', 'jetstack', 'https://charts.jetstack.io', 'f', 't', 'now()', '1', 'now()', '1', 't'), -('9', 'metrics-server', 'https://kubernetes-sigs.github.io/metrics-server', 'f', 't', 'now()', '1', 'now()', '1', 't'), -('10', 'autoscaler', 'https://kubernetes.github.io/autoscaler', 'f', 't', 'now()', '1', 'now()', '1', 't'); +('2', 'devtron', 'https://helm.devtron.ai', 'f', 't', 'now()', '1', 'now()', '1', 't'), +('3', 'jetstack', 'https://charts.jetstack.io', 'f', 't', 'now()', '1', 'now()', '1', 't'), +('4', 'elastic', 'https://helm.elastic.co', 'f', 't', 'now()', '1', 'now()', '1', 't'), +('5', 'autoscaler', 'https://kubernetes.github.io/autoscaler', 'f', 't', 'now()', '1', 'now()', '1', 't'), +('6', 'fluent', 'https://fluent.github.io/helm-charts', 'f', 't', 'now()', '1', 'now()', '1', 't'), +('7', 'nginx-ingress', 'https://kubernetes.github.io/ingress-nginx', 'f', 't', 'now()', '1', 'now()', '1', 't'), +('8', 'metrics-server', 'https://kubernetes-sigs.github.io/metrics-server', 'f', 't', 'now()', '1', 'now()', '1', 't'), +('9', 'prometheus-community', 'https://prometheus-community.github.io/helm-charts', 'f', 't', 'now()', '1', 'now()', '1', 't'), +('10', 'bitnami', 'https://charts.bitnami.com/bitnami', 'f', 't', 'now()', '1', 'now()', '1', 't'); INSERT INTO "public"."cluster" ("id", "cluster_name", "active", "created_on", "created_by", "updated_on", "updated_by", "server_url", "config", "prometheus_endpoint", "cd_argo_setup", "p_username", "p_password", "p_tls_client_cert", "p_tls_client_key") VALUES diff --git a/scripts/sql/38_historical_definitions.down.sql b/scripts/sql/38_historical_definitions.down.sql new file mode 100644 index 0000000000..2a0bc74324 --- /dev/null +++ b/scripts/sql/38_historical_definitions.down.sql @@ -0,0 +1,6 @@ +DROP TABLE "public"."config_map_history" CASCADE; +DROP TABLE "public"."deployment_template_history" CASCADE; +DROP TABLE "public"."app_store_charts_history" CASCADE; +DROP TABLE "public"."pre_post_ci_script_history" CASCADE; +DROP TABLE "public"."pre_post_cd_script_history" CASCADE; +DROP TABLE "public"."pipeline_strategy_history" CASCADE; \ No newline at end of file diff --git a/scripts/sql/38_historical_definitions.up.sql b/scripts/sql/38_historical_definitions.up.sql new file mode 100644 index 0000000000..6df8a37895 --- /dev/null +++ b/scripts/sql/38_historical_definitions.up.sql @@ -0,0 +1,133 @@ +CREATE SEQUENCE IF NOT EXISTS id_seq_config_map_history; + +-- Table Definition +CREATE TABLE "public"."config_map_history" +( + "id" integer NOT NULL DEFAULT nextval('id_seq_config_map_history'::regclass), + "pipeline_id" integer, + "app_id" integer, + "data_type" varchar(255), + "data" text, + "deployed" boolean, + "deployed_on" timestamptz, + "deployed_by" int4, + "created_on" timestamptz, + "created_by" int4, + "updated_on" timestamptz, + "updated_by" int4, + CONSTRAINT "config_map_history_pipeline_id_fkey" FOREIGN KEY ("pipeline_id") REFERENCES "public"."pipeline" ("id"), + PRIMARY KEY ("id") +); + +CREATE SEQUENCE IF NOT EXISTS id_seq_deployment_template_history; + +-- Table Definition +CREATE TABLE "public"."deployment_template_history" +( + "id" integer NOT NULL DEFAULT nextval('id_seq_deployment_template_history'::regclass), + "pipeline_id" integer, + "app_id" integer, + "target_environment" integer, + "image_descriptor_template" text NOT NULL, + "template" text NOT NULL, + "template_name" text, + "template_version" text, + "is_app_metrics_enabled" bool, + "deployed" bool, + "deployed_on" timestamptz, + "deployed_by" int4, + "created_on" timestamptz, + "created_by" int4, + "updated_on" timestamptz, + "updated_by" int4, + CONSTRAINT "deployment_template_history_pipeline_id_fkey" FOREIGN KEY ("pipeline_id") REFERENCES "public"."pipeline" ("id"), + PRIMARY KEY ("id") +); + + +CREATE SEQUENCE IF NOT EXISTS id_seq_app_store_charts_history; + +-- Table Definition +CREATE TABLE "public"."app_store_charts_history" +( + "id" integer NOT NULL DEFAULT nextval('id_seq_app_store_charts_history'::regclass), + "installed_apps_id" integer NOT NULL, + "values_yaml" text, + "deployed_on" timestamptz, + "deployed_by" int4, + "created_on" timestamptz, + "created_by" int4, + "updated_on" timestamptz, + "updated_by" int4, + CONSTRAINT "app_store_charts_history_installed_apps_id_fkey" FOREIGN KEY ("installed_apps_id") REFERENCES "public"."installed_apps" ("id"), + PRIMARY KEY ("id") +); + + +CREATE SEQUENCE IF NOT EXISTS id_seq_pre_post_ci_script_history; + +-- Table Definition +CREATE TABLE "public"."pre_post_ci_script_history" +( + "id" integer NOT NULL DEFAULT nextval('id_seq_pre_post_ci_script_history'::regclass), + "ci_pipeline_scripts_id" integer NOT NULL, + "script" text, + "stage" text, + "name" text, + "output_location" text, + "built" bool, + "built_on" timestamptz, + "built_by" int4, + "created_on" timestamptz, + "created_by" int4, + "updated_on" timestamptz, + "updated_by" int4, + CONSTRAINT "pre_post_ci_script_history_ci_pipeline_scripts_id_fkey" FOREIGN KEY ("ci_pipeline_scripts_id") REFERENCES "public"."ci_pipeline_scripts" ("id"), + PRIMARY KEY ("id") +); + +CREATE SEQUENCE IF NOT EXISTS id_seq_pre_post_cd_script_history; + +-- Table Definition +CREATE TABLE "public"."pre_post_cd_script_history" +( + "id" integer NOT NULL DEFAULT nextval('id_seq_pre_post_cd_script_history'::regclass), + "pipeline_id" integer NOT NULL, + "script" text, + "stage" text, + "configmap_secret_names" text, + "configmap_data" text, + "secret_data" text, + "exec_in_env" bool, + "trigger_type" text, + "deployed" bool, + "deployed_on" timestamptz, + "deployed_by" int4, + "created_on" timestamptz, + "created_by" int4, + "updated_on" timestamptz, + "updated_by" int4, + CONSTRAINT "pre_post_cd_script_history_pipeline_id_fkey" FOREIGN KEY ("pipeline_id") REFERENCES "public"."pipeline" ("id"), + PRIMARY KEY ("id") +); + +CREATE SEQUENCE IF NOT EXISTS id_seq_pipeline_strategy_history; + +-- Table Definition +CREATE TABLE "public"."pipeline_strategy_history" +( + "id" integer NOT NULL DEFAULT nextval('id_seq_pipeline_strategy_history'::regclass), + "pipeline_id" integer NOT NULL, + "config" text, + "strategy" text NOT NULL , + "default" bool, + "deployed" bool, + "deployed_on" timestamptz, + "deployed_by" int4, + "created_on" timestamptz, + "created_by" int4, + "updated_on" timestamptz, + "updated_by" int4, + CONSTRAINT "pipeline_strategy_history_pipeline_id_fkey" FOREIGN KEY ("pipeline_id") REFERENCES "public"."pipeline" ("id"), + PRIMARY KEY ("id") +); \ No newline at end of file diff --git a/scripts/sql/39_create_installed_app_version_history.down.sql b/scripts/sql/39_create_installed_app_version_history.down.sql new file mode 100644 index 0000000000..668ff9314f --- /dev/null +++ b/scripts/sql/39_create_installed_app_version_history.down.sql @@ -0,0 +1,3 @@ +DROP INDEX "public"."version_history_git_hash_index"; + +DROP TABLE "public"."installed_app_version_history" CASCADE; \ No newline at end of file diff --git a/scripts/sql/39_create_installed_app_version_history.up.sql b/scripts/sql/39_create_installed_app_version_history.up.sql new file mode 100644 index 0000000000..3188bb4454 --- /dev/null +++ b/scripts/sql/39_create_installed_app_version_history.up.sql @@ -0,0 +1,20 @@ +-- Sequence and defined type +CREATE SEQUENCE IF NOT EXISTS id_seq_installed_app_version_history; + +-- Table Definition +CREATE TABLE "public"."installed_app_version_history" ( + "id" int4 NOT NULL DEFAULT nextval('id_seq_installed_app_version_history'::regclass), + "installed_app_version_id" int4 NOT NULL, + "created_on" timestamptz, + "created_by" int4, + "values_yaml_raw" text, + "status" varchar(100), + "updated_on" timestamptz, + "updated_by" int4, + "git_hash" varchar(255), + CONSTRAINT "installed_app_version_history_installed_app_version_id_fkey" FOREIGN KEY ("installed_app_version_id") REFERENCES "public"."installed_app_versions"("id"), + PRIMARY KEY ("id") +); + + +CREATE INDEX "version_history_git_hash_index" ON "public"."installed_app_version_history" USING BTREE ("git_hash"); \ No newline at end of file diff --git a/scripts/sql/40_chart_ref.down.sql b/scripts/sql/40_chart_ref.down.sql new file mode 100644 index 0000000000..2b42ad1813 --- /dev/null +++ b/scripts/sql/40_chart_ref.down.sql @@ -0,0 +1,5 @@ +DELETE FROM "public"."chart_ref" WHERE ("location" = 'cronjob-chart_1-3-0' AND "version" = '1.3.0'); + +UPDATE "public"."chart_ref" SET "is_default" = 't' WHERE "location" = 'cronjob-chart_1-2-0' AND "version" = '1.2.0'; + +UPDATE chart_ref SET name = replace(name, 'CronJob & Job', 'Cron Job & Job'); \ No newline at end of file diff --git a/scripts/sql/40_chart_ref.up.sql b/scripts/sql/40_chart_ref.up.sql new file mode 100644 index 0000000000..c9aa4a0b25 --- /dev/null +++ b/scripts/sql/40_chart_ref.up.sql @@ -0,0 +1,6 @@ +UPDATE chart_ref SET is_default=false; +INSERT INTO "public"."chart_ref" ("location", "version", "is_default", "active", "created_on", "created_by", "updated_on", "updated_by", "name") VALUES +('cronjob-chart_1-3-0', '1.3.0', 'f', 't', 'now()', 1, 'now()', 1, 'Cron Job & Job'); + +UPDATE "public"."chart_ref" SET "is_default" = 't' WHERE "location" = 'reference-chart_4-11-0' AND "version" = '4.11.0'; +UPDATE chart_ref SET name = replace(name, 'Cron Job & Job', 'CronJob & Job'); \ No newline at end of file diff --git a/scripts/sql/41_down_chart_history.down.sql b/scripts/sql/41_down_chart_history.down.sql new file mode 100644 index 0000000000..55172500e7 --- /dev/null +++ b/scripts/sql/41_down_chart_history.down.sql @@ -0,0 +1,14 @@ +CREATE TABLE "public"."app_store_charts_history" +( + "id" integer NOT NULL DEFAULT nextval('id_seq_app_store_charts_history'::regclass), + "installed_apps_id" integer NOT NULL, + "values_yaml" text, + "deployed_on" timestamptz, + "deployed_by" int4, + "created_on" timestamptz, + "created_by" int4, + "updated_on" timestamptz, + "updated_by" int4, + CONSTRAINT "app_store_charts_history_installed_apps_id_fkey" FOREIGN KEY ("installed_apps_id") REFERENCES "public"."installed_apps" ("id"), + PRIMARY KEY ("id") +); \ No newline at end of file diff --git a/scripts/sql/41_down_chart_history.up.sql b/scripts/sql/41_down_chart_history.up.sql new file mode 100644 index 0000000000..0157d22a96 --- /dev/null +++ b/scripts/sql/41_down_chart_history.up.sql @@ -0,0 +1 @@ +DROP TABLE "public"."app_store_charts_history" CASCADE; \ No newline at end of file diff --git a/specs/api-spec.yaml b/specs/api-spec.yaml new file mode 100644 index 0000000000..3456441472 --- /dev/null +++ b/specs/api-spec.yaml @@ -0,0 +1,49 @@ +openapi: "3.0.3" +info: + version: 1.0.0 + title: Devtron Labs +paths: + /orchestrator/application/rollback: + put: + description: Rollback application if the application is installed from the chartStore + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RollbackReleaseRequest' + responses: + "200": + description: application rollback response + content: + application/json: + schema: + $ref: "#/components/schemas/RollbackReleaseResponse" +components: + schemas: + RollbackReleaseResponse: + type: object + properties: + success: + type: boolean + description: success or failure + example: true + RollbackReleaseRequest: + type: object + properties: + installedAppId: + type: integer + description: Installed App Id if the app is installed from chart store + example: 1 + installedAppVersionId: + type: integer + description: Installed App Version Id if the app is installed from chart store + example: 2 + hAppId: + type: string + description: helm App Id if the application is installed from using helm (for example "clusterId|namespace|appName" ) + example: "1|default|someName" + version: + type: integer + description: rollback to this version + example: 10 \ No newline at end of file diff --git a/specs/deployments.yaml b/specs/deployments.yaml new file mode 100644 index 0000000000..c6f5ab3cd3 --- /dev/null +++ b/specs/deployments.yaml @@ -0,0 +1,54 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Devtron Labs +paths: + /orchestrator/deployment/template/upload: + post: + description: upload template file from this api. + requestBody: + description: form-data as request body + required: true + content: + multipart/form-data: + schema: + properties: + binaryFile: + type: object + description: zipped chart template file + responses: + '200': + description: template file upload response + content: + application/json: + schema: + properties: + code: + type: integer + description: status code + status: + type: string + description: status + result: + type: string + description: result + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + ErrorResponse: + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/external-app/applist.yaml b/specs/external-app/applist.yaml index 874892406f..bc67f5556e 100644 --- a/specs/external-app/applist.yaml +++ b/specs/external-app/applist.yaml @@ -20,25 +20,6 @@ paths: text/event-stream: schema: $ref: "#/components/schemas/AppList" - /orchestrator/application/deployment-history: - get: - description: deployment history of helm app - parameters: - - in: query - name: appId - example: "12|helm-app|cluster1-ns1" - description: project ids - required: true - allowEmptyValue: false - schema: - type: string - responses: - "200": - description: deployment history - content: - application/json: - schema: - $ref: "#/components/schemas/HelmAppDeploymentHistory" /orchestrator/application/release-info: get: description: deployment values.yaml/release-info @@ -316,22 +297,73 @@ paths: type: array items: $ref: "#/components/schemas/UpdateReleaseResponse" - /orchestrator/application/deployment-detail: + /orchestrator/app-store/deployment/application/helm/link-to-chart-store: + put: + description: update the helm EA application with chartstore linking + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateReleaseWithChartLinkingRequest' + responses: + "200": + description: application update success + content: + application/json: + schema: + $ref: "#/components/schemas/UpdateReleaseResponse" + /orchestrator/application/deployment-history: get: - description: deployment details of helm app + description: deployment history of helm app parameters: - in: query name: appId example: "12|helm-app|cluster1-ns1" description: project ids - required: true + required: false + allowEmptyValue: false + schema: + type: string + - in: query + name: installedAppId + example: "100" + description: devtron charts installed instance id + required: false + allowEmptyValue: false + schema: + type: number + responses: + "200": + description: deployment history + content: + application/json: + schema: + $ref: "#/components/schemas/DeploymentHistoryAndInstalledAppInfo" + /orchestrator/application/deployment-history/info: + get: + description: deployment history detail info, values + parameters: + - in: query + name: appId + example: "12|helm-app|cluster1-ns1" + description: project ids + required: false + allowEmptyValue: false + schema: + type: string + - in: query + name: installedAppId + example: "100" + description: devtron charts installed instance id + required: false allowEmptyValue: false schema: type: string - in: query name: version example: 1 - description: deployment version + description: installed app version id required: true allowEmptyValue: false schema: @@ -339,7 +371,7 @@ paths: format: int32 responses: "200": - description: deployment detail response + description: deployment history detail info response content: application/json: schema: @@ -599,6 +631,10 @@ components: type: string description: description of the helm chart example: description of the helm chart + notes: + type: string + description: Contains the rendered templates/NOTES.txt + example: notes of the chart HelmAppDeploymentDetail: type: object properties: @@ -619,6 +655,18 @@ components: type: string format: date-time example: "2021-12-15T05:44:05Z" + DeploymentHistoryAndInstalledAppInfo: + type: object + properties: + deploymentHistory: + type: array + description: deployment history + items: + $ref: "#/components/schemas/HelmAppDeploymentDetail" + installedAppInfo: + type: object + $ref: "#/components/schemas/InstalledAppInfo" + description: Installed app info HelmAppDeploymentHistory: type: array description: deployment history @@ -642,6 +690,15 @@ components: appStoreChartId: type: number description: App store chart Id + installedAppVersionId: + type: number + description: App store installed app version Id + clusterId: + type: number + description: Cluster Id + environmentId: + type: number + description: Environment Id ReleaseAndInstalledAppInfo: type: object properties: @@ -651,8 +708,8 @@ components: description: release info installedAppInfo: type: object - $ref: "#/components/schemas/InstalledAppInfo" - description: Installed app info + $ref: "#/components/schemas/InstalledAppInfo" + description: Installed app info ReleaseInfo: type: object properties: @@ -730,6 +787,29 @@ components: type: string description: updated values yaml string example: "" + UpdateReleaseWithChartLinkingRequest: + type: object + properties: + appId: + type: string + description: helm app id + example: "1|test|testapp" + valuesYaml: + type: string + description: updated values yaml string + example: "" + appStoreApplicationVersionId: + type: number + description: app store application version Id + example: 1 + referenceValueId: + type: number + description: Reference value Id of selected chart values + example: 1 + referenceValueKind: + type: string + description: Reference value Kind of selected chart values "oneof=DEFAULT TEMPLATE DEPLOYED EXISTING" (can be null) + example: 1 UpdateReleaseResponse: type: object properties: diff --git a/specs/historical-definitions.yaml b/specs/historical-definitions.yaml new file mode 100644 index 0000000000..495b07245d --- /dev/null +++ b/specs/historical-definitions.yaml @@ -0,0 +1,596 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Historical Task definitions +paths: + /orchestrator/app/history/cm/{appId}/{pipelineId}: + get: + description: fetch deployment details in history for deployed config maps + operationId: FetchDeploymentDetailsForDeployedCMHistory + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ConfigMapAndSecretHistoryDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/cs/{appId}/{pipelineId}: + get: + description: fetch deployment details in history for deployed secrets + operationId: FetchDeploymentDetailsForDeployedCSHistory + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ConfigMapAndSecretHistoryDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/template/{appId}/{pipelineId}: + get: + description: fetch deployment details in history for deployed deployment templates + operationId: FetchDeploymentDetailsForDeployedTemplatesHistory + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DeploymentTemplateHistoryDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/strategy/{appId}/{pipelineId}: + get: + description: fetch deployment details in history for deployed pipeline strategy + operationId: FetchDeploymentDetailsForDeployedStrategyHistory + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PipelineStrategyHistoryDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/cm/{appId}/{pipelineId}/{id}: + get: + description: fetch history for deployed config map by id + operationId: FetchDeployedCMHistoryById + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DeploymentDetailsDataType' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/cs/{appId}/{pipelineId}/{id}: + get: + description: fetch history for deployed secret by id + operationId: FetchDeployedCSHistoryById + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DeploymentDetailsDataType' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/template/{appId}/{pipelineId}/{id}: + get: + description: fetch history for deployed deployment template by id + operationId: FetchDeployedTemplatesHistoryById + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DeploymentDetailsDataType' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /orchestrator/app/history/strategy/{appId}/{pipelineId}/{id}: + get: + description: fetch history for deployed pipeline strategy by id + operationId: FetchDeployedStrategyHistoryById + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DeploymentDetailsDataType' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + + /orchestrator/app/history/cd-config/{appId}/{pipelineId}: + get: + description: fetch history for cd config (pre/post stage config) + operationId: FetchDeployedCdConfigHistory + parameters: + - name: appId + in: path + required: true + schema: + type: integer + - name: pipelineId + in: path + required: true + schema: + type: integer + - name: stage + in: query + required: true + schema: + type: string + enum: + - "PRE_CD" + - "POST_CD" + responses: + '200': + description: Successfully return history + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PrePostCdScriptHistoryDto' + '400': + description: Bad Request. Input Validation error/wrong request body. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Unauthorized User + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + DeploymentDetailsDataType: + type: object + properties: + id: + type: integer + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + ConfigMapAndSecretHistoryDto: + type: object + properties: + id: + type: integer + pipelineId: + type: integer + dataType: + type: string + configData: + $ref: '#/components/schemas/ConfigData' + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + + DeploymentTemplateHistoryDto: + type: object + properties: + id: + type: integer + pipelineId: + type: integer + imageDescriptorTemplate: + type: string + template: + type: string + templateName: + type: string + templateVersion: + type: string + isAppMetricsEnabled: + type: boolean + targetEnvironment: + type: integer + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + + PipelineStrategyHistoryDto: + type: object + properties: + id: + type: integer + pipelineId: + type: integer + strategy: + type: string + config: + type: string + default: + type: boolean + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + + PrePostCdScriptHistoryDto: + type: object + properties: + id: + type: integer + pipelineId: + type: integer + script: + type: string + stage: + type: string + configmapSecretNames: + $ref: '#/components/schemas/PrePostStageConfigMapSecretNames' + configmapData: + $ref: '#/components/schemas/ConfigData' + secretData: + $ref: '#/components/schemas/ConfigData' + triggerType: + type: string + execInEnv: + type: boolean + deployed: + type: boolean + deployedOn: + type: string + format: timestamp + deployedBy: + type: integer + + PrePostStageConfigMapSecretNames: + properties: + configMaps: + type: array + items: + type: string + secrets: + type: array + items: + type: string + + ConfigData: + properties: + name: + type: string + type: + type: string + external: + type: boolean + mountPath: + type: string + data: + type: string + defaultData: + type: string + defaultMountPath: + type: string + global: + type: boolean + externalType: + type: string + secretData: + type: array + items: + $ref: '#/components/schemas/ExternalSecret' + defaultSecretData: + type: array + items: + $ref: '#/components/schemas/ExternalSecret' + roleArn: + type: string + subPath: + type: boolean + filePermission: + type: string + ExternalSecret: + properties: + key: + type: string + name: + type: string + property: + type: string + isBinary: + type: boolean + + Error: + required: + - code + - message + properties: + code: + type: integer + description: Error code + message: + type: string + description: Error message \ No newline at end of file diff --git a/specs/openapiClient/api/openapi.yaml b/specs/openapiClient/api/openapi.yaml new file mode 100644 index 0000000000..d4eceba1c1 --- /dev/null +++ b/specs/openapiClient/api/openapi.yaml @@ -0,0 +1,77 @@ +openapi: 3.0.3 +info: + title: Devtron Labs + version: 1.0.0 +servers: +- url: / +paths: + /orchestrator/app-store/deployment/application/rollback: + put: + description: Rollback application if the application is installed from the chartStore + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RollbackReleaseRequest' + required: true + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/RollbackReleaseResponse' + description: application rollback response + /orchestrator/application/rollback: + put: + description: Rollback application if the application is installed externally + using helm (external-app) + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RollbackReleaseRequest' + required: true + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/RollbackReleaseResponse' + description: application rollback response +components: + schemas: + RollbackReleaseResponse: + example: + success: true + properties: + success: + description: success or failure + example: true + type: boolean + type: object + RollbackReleaseRequest: + example: + installedAppVersionId: 2 + installedAppId: 1 + hAppId: 1|default|someName + version: 10 + properties: + installedAppId: + description: Installed App Id if the app is installed from chart store + example: 1 + type: integer + installedAppVersionId: + description: Installed App Version Id if the app is installed from chart + store + example: 2 + type: integer + hAppId: + description: helm App Id if the application is installed from using helm + (for example "clusterId|namespace|appName" ) + example: 1|default|someName + type: string + version: + description: rollback to this version + example: 10 + type: integer + type: object diff --git a/specs/openapiClient/docs/DefaultApi.md b/specs/openapiClient/docs/DefaultApi.md new file mode 100644 index 0000000000..a6ccc99989 --- /dev/null +++ b/specs/openapiClient/docs/DefaultApi.md @@ -0,0 +1,142 @@ +# \DefaultApi + +All URIs are relative to *http://localhost* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**OrchestratorAppStoreDeploymentApplicationRollbackPut**](DefaultApi.md#OrchestratorAppStoreDeploymentApplicationRollbackPut) | **Put** /orchestrator/app-store/deployment/application/rollback | +[**OrchestratorApplicationRollbackPut**](DefaultApi.md#OrchestratorApplicationRollbackPut) | **Put** /orchestrator/application/rollback | + + + +## OrchestratorAppStoreDeploymentApplicationRollbackPut + +> RollbackReleaseResponse OrchestratorAppStoreDeploymentApplicationRollbackPut(ctx).RollbackReleaseRequest(rollbackReleaseRequest).Execute() + + + + + +### Example + +```go +package main + +import ( + "context" + "fmt" + "os" + openapiclient "./openapi" +) + +func main() { + rollbackReleaseRequest := *openapiclient.NewRollbackReleaseRequest() // RollbackReleaseRequest | + + configuration := openapiclient.NewConfiguration() + api_client := openapiclient.NewAPIClient(configuration) + resp, r, err := api_client.DefaultApi.OrchestratorAppStoreDeploymentApplicationRollbackPut(context.Background()).RollbackReleaseRequest(rollbackReleaseRequest).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `DefaultApi.OrchestratorAppStoreDeploymentApplicationRollbackPut``: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + } + // response from `OrchestratorAppStoreDeploymentApplicationRollbackPut`: RollbackReleaseResponse + fmt.Fprintf(os.Stdout, "Response from `DefaultApi.OrchestratorAppStoreDeploymentApplicationRollbackPut`: %v\n", resp) +} +``` + +### Path Parameters + + + +### Other Parameters + +Other parameters are passed through a pointer to a apiOrchestratorAppStoreDeploymentApplicationRollbackPutRequest struct via the builder pattern + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **rollbackReleaseRequest** | [**RollbackReleaseRequest**](RollbackReleaseRequest.md) | | + +### Return type + +[**RollbackReleaseResponse**](RollbackReleaseResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) +[[Back to Model list]](../README.md#documentation-for-models) +[[Back to README]](../README.md) + + +## OrchestratorApplicationRollbackPut + +> RollbackReleaseResponse OrchestratorApplicationRollbackPut(ctx).RollbackReleaseRequest(rollbackReleaseRequest).Execute() + + + + + +### Example + +```go +package main + +import ( + "context" + "fmt" + "os" + openapiclient "./openapi" +) + +func main() { + rollbackReleaseRequest := *openapiclient.NewRollbackReleaseRequest() // RollbackReleaseRequest | + + configuration := openapiclient.NewConfiguration() + api_client := openapiclient.NewAPIClient(configuration) + resp, r, err := api_client.DefaultApi.OrchestratorApplicationRollbackPut(context.Background()).RollbackReleaseRequest(rollbackReleaseRequest).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `DefaultApi.OrchestratorApplicationRollbackPut``: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + } + // response from `OrchestratorApplicationRollbackPut`: RollbackReleaseResponse + fmt.Fprintf(os.Stdout, "Response from `DefaultApi.OrchestratorApplicationRollbackPut`: %v\n", resp) +} +``` + +### Path Parameters + + + +### Other Parameters + +Other parameters are passed through a pointer to a apiOrchestratorApplicationRollbackPutRequest struct via the builder pattern + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **rollbackReleaseRequest** | [**RollbackReleaseRequest**](RollbackReleaseRequest.md) | | + +### Return type + +[**RollbackReleaseResponse**](RollbackReleaseResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) +[[Back to Model list]](../README.md#documentation-for-models) +[[Back to README]](../README.md) + diff --git a/specs/openapiClient/docs/RollbackReleaseRequest.md b/specs/openapiClient/docs/RollbackReleaseRequest.md new file mode 100644 index 0000000000..bcd4cf4da0 --- /dev/null +++ b/specs/openapiClient/docs/RollbackReleaseRequest.md @@ -0,0 +1,134 @@ +# RollbackReleaseRequest + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**InstalledAppId** | Pointer to **int32** | Installed App Id if the app is installed from chart store | [optional] +**InstalledAppVersionId** | Pointer to **int32** | Installed App Version Id if the app is installed from chart store | [optional] +**HAppId** | Pointer to **string** | helm App Id if the application is installed from using helm (for example \"clusterId|namespace|appName\" ) | [optional] +**Version** | Pointer to **int32** | rollback to this version | [optional] + +## Methods + +### NewRollbackReleaseRequest + +`func NewRollbackReleaseRequest() *RollbackReleaseRequest` + +NewRollbackReleaseRequest instantiates a new RollbackReleaseRequest object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewRollbackReleaseRequestWithDefaults + +`func NewRollbackReleaseRequestWithDefaults() *RollbackReleaseRequest` + +NewRollbackReleaseRequestWithDefaults instantiates a new RollbackReleaseRequest object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetInstalledAppId + +`func (o *RollbackReleaseRequest) GetInstalledAppId() int32` + +GetInstalledAppId returns the InstalledAppId field if non-nil, zero value otherwise. + +### GetInstalledAppIdOk + +`func (o *RollbackReleaseRequest) GetInstalledAppIdOk() (*int32, bool)` + +GetInstalledAppIdOk returns a tuple with the InstalledAppId field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetInstalledAppId + +`func (o *RollbackReleaseRequest) SetInstalledAppId(v int32)` + +SetInstalledAppId sets InstalledAppId field to given value. + +### HasInstalledAppId + +`func (o *RollbackReleaseRequest) HasInstalledAppId() bool` + +HasInstalledAppId returns a boolean if a field has been set. + +### GetInstalledAppVersionId + +`func (o *RollbackReleaseRequest) GetInstalledAppVersionId() int32` + +GetInstalledAppVersionId returns the InstalledAppVersionId field if non-nil, zero value otherwise. + +### GetInstalledAppVersionIdOk + +`func (o *RollbackReleaseRequest) GetInstalledAppVersionIdOk() (*int32, bool)` + +GetInstalledAppVersionIdOk returns a tuple with the InstalledAppVersionId field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetInstalledAppVersionId + +`func (o *RollbackReleaseRequest) SetInstalledAppVersionId(v int32)` + +SetInstalledAppVersionId sets InstalledAppVersionId field to given value. + +### HasInstalledAppVersionId + +`func (o *RollbackReleaseRequest) HasInstalledAppVersionId() bool` + +HasInstalledAppVersionId returns a boolean if a field has been set. + +### GetHAppId + +`func (o *RollbackReleaseRequest) GetHAppId() string` + +GetHAppId returns the HAppId field if non-nil, zero value otherwise. + +### GetHAppIdOk + +`func (o *RollbackReleaseRequest) GetHAppIdOk() (*string, bool)` + +GetHAppIdOk returns a tuple with the HAppId field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetHAppId + +`func (o *RollbackReleaseRequest) SetHAppId(v string)` + +SetHAppId sets HAppId field to given value. + +### HasHAppId + +`func (o *RollbackReleaseRequest) HasHAppId() bool` + +HasHAppId returns a boolean if a field has been set. + +### GetVersion + +`func (o *RollbackReleaseRequest) GetVersion() int32` + +GetVersion returns the Version field if non-nil, zero value otherwise. + +### GetVersionOk + +`func (o *RollbackReleaseRequest) GetVersionOk() (*int32, bool)` + +GetVersionOk returns a tuple with the Version field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetVersion + +`func (o *RollbackReleaseRequest) SetVersion(v int32)` + +SetVersion sets Version field to given value. + +### HasVersion + +`func (o *RollbackReleaseRequest) HasVersion() bool` + +HasVersion returns a boolean if a field has been set. + + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/specs/openapiClient/docs/RollbackReleaseResponse.md b/specs/openapiClient/docs/RollbackReleaseResponse.md new file mode 100644 index 0000000000..794eee1e40 --- /dev/null +++ b/specs/openapiClient/docs/RollbackReleaseResponse.md @@ -0,0 +1,56 @@ +# RollbackReleaseResponse + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Success** | Pointer to **bool** | success or failure | [optional] + +## Methods + +### NewRollbackReleaseResponse + +`func NewRollbackReleaseResponse() *RollbackReleaseResponse` + +NewRollbackReleaseResponse instantiates a new RollbackReleaseResponse object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewRollbackReleaseResponseWithDefaults + +`func NewRollbackReleaseResponseWithDefaults() *RollbackReleaseResponse` + +NewRollbackReleaseResponseWithDefaults instantiates a new RollbackReleaseResponse object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetSuccess + +`func (o *RollbackReleaseResponse) GetSuccess() bool` + +GetSuccess returns the Success field if non-nil, zero value otherwise. + +### GetSuccessOk + +`func (o *RollbackReleaseResponse) GetSuccessOk() (*bool, bool)` + +GetSuccessOk returns a tuple with the Success field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetSuccess + +`func (o *RollbackReleaseResponse) SetSuccess(v bool)` + +SetSuccess sets Success field to given value. + +### HasSuccess + +`func (o *RollbackReleaseResponse) HasSuccess() bool` + +HasSuccess returns a boolean if a field has been set. + + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/util/helper.go b/util/helper.go index f5ff36cd19..81bf605bcf 100644 --- a/util/helper.go +++ b/util/helper.go @@ -18,11 +18,17 @@ package util import ( + "archive/tar" + "compress/gzip" "encoding/json" "fmt" + "github.com/juju/errors" + "io" "io/ioutil" "math/rand" "net/http" + "os" + "path/filepath" "strconv" "strings" "time" @@ -119,3 +125,87 @@ func HttpRequest(url string) (map[string]interface{}, error) { } return nil, err } + +func CheckForMissingFiles(chartLocation string) error { + listofFiles := [1]string{"chart"} + + missingFilesMap := map[string]bool{ + ".image_descriptor_template.json": true, + "chart": true, + } + + files, err := ioutil.ReadDir(chartLocation) + if err != nil { + return err + } + + for _, file := range files { + if !file.IsDir() { + name := strings.ToLower(file.Name()) + if name == listofFiles[0]+".yaml" || name == listofFiles[0]+".yml" { + missingFilesMap[listofFiles[0]] = false + } else if name == ".image_descriptor_template.json" { + missingFilesMap[".image_descriptor_template.json"] = false + } + } + } + + if len(missingFilesMap) != 0 { + missingFiles := make([]string, 0, len(missingFilesMap)) + for k, v := range missingFilesMap { + if v { + missingFiles = append(missingFiles, k) + } + } + if len(missingFiles) != 0 { + return errors.New("Missing files " + strings.Join(missingFiles, ",") + " yaml or yml files") + } + } + return nil +} + +func ExtractTarGz(gzipStream io.Reader, chartDir string) error { + uncompressedStream, err := gzip.NewReader(gzipStream) + if err != nil { + return err + } + + tarReader := tar.NewReader(uncompressedStream) + for true { + header, err := tarReader.Next() + + if err == io.EOF { + break + } + + if err != nil { + return err + } + switch header.Typeflag { + case tar.TypeDir: + if _, err := os.Stat(filepath.Join(chartDir, header.Name)); os.IsNotExist(err) { + if err := os.Mkdir(filepath.Join(chartDir, header.Name), 0755); err != nil { + return err + } + } else { + break + } + + case tar.TypeReg: + outFile, err := os.Create(filepath.Join(chartDir, header.Name)) + if err != nil { + return err + } + if _, err := io.Copy(outFile, tarReader); err != nil { + return err + } + outFile.Close() + + default: + return err + + } + + } + return nil +} diff --git a/util/rbac/EnforcerUtil.go b/util/rbac/EnforcerUtil.go index 70fc89896a..774ef2b735 100644 --- a/util/rbac/EnforcerUtil.go +++ b/util/rbac/EnforcerUtil.go @@ -44,6 +44,7 @@ type EnforcerUtil interface { GetProjectAdminRBACNameBYAppName(appName string) string GetHelmObject(appId int, envId int) string GetHelmObjectByAppNameAndEnvId(appName string, envId int) string + GetHelmObjectByProjectIdAndEnvId(teamId int, envId int) string } type EnforcerUtilImpl struct { logger *zap.SugaredLogger @@ -297,3 +298,21 @@ func (impl EnforcerUtilImpl) GetHelmObjectByAppNameAndEnvId(appName string, envI }*/ return fmt.Sprintf("%s/%s/%s", strings.ToLower(application.Team.Name), environmentIdentifier, strings.ToLower(application.AppName)) } + +func (impl EnforcerUtilImpl) GetHelmObjectByProjectIdAndEnvId(teamId int, envId int) string { + team, err := impl.teamRepository.FindOne(teamId) + if err != nil { + return fmt.Sprintf("%s/%s/%s", "", "", "") + } + env, err := impl.environmentRepository.FindById(envId) + if err != nil { + return fmt.Sprintf("%s/%s/%s", "", "", "") + } + environmentIdentifier := env.EnvironmentIdentifier + //TODO - FIX required for futuristic permission for cluster__* all environment for migrated environment identifier only + /*//here cluster, env, namespace must not have double underscore in names, as we are using that for separator. + if !strings.HasPrefix(env.EnvironmentIdentifier, fmt.Sprintf("%s__", env.Cluster.ClusterName)) { + environmentIdentifier = fmt.Sprintf("%s__%s", env.Cluster.ClusterName, env.EnvironmentIdentifier) + }*/ + return fmt.Sprintf("%s/%s/%s", strings.ToLower(team.Name), environmentIdentifier, "*") +} \ No newline at end of file diff --git a/vendor/github.com/argoproj/argo-cd/assets/badge.svg b/vendor/github.com/argoproj/argo-cd/assets/badge.svg index 6870b38760..a3234cfdf5 100644 --- a/vendor/github.com/argoproj/argo-cd/assets/badge.svg +++ b/vendor/github.com/argoproj/argo-cd/assets/badge.svg @@ -19,4 +19,4 @@ - + \ No newline at end of file diff --git a/vendor/github.com/argoproj/argo-cd/assets/builtin-policy.csv b/vendor/github.com/argoproj/argo-cd/assets/builtin-policy.csv index a0351d6f90..f74c5b8002 100644 --- a/vendor/github.com/argoproj/argo-cd/assets/builtin-policy.csv +++ b/vendor/github.com/argoproj/argo-cd/assets/builtin-policy.csv @@ -31,4 +31,4 @@ p, role:admin, projects, update, *, allow p, role:admin, projects, delete, *, allow g, role:admin, role:readonly -g, admin, role:admin +g, admin, role:admin \ No newline at end of file diff --git a/vendor/github.com/argoproj/argo-cd/assets/model.conf b/vendor/github.com/argoproj/argo-cd/assets/model.conf index 92664af6ff..240a9180d3 100644 --- a/vendor/github.com/argoproj/argo-cd/assets/model.conf +++ b/vendor/github.com/argoproj/argo-cd/assets/model.conf @@ -11,4 +11,4 @@ g = _, _ e = some(where (p.eft == allow)) && !some(where (p.eft == deny)) [matchers] -m = g(r.sub, p.sub) && keyMatch(r.res, p.res) && keyMatch(r.act, p.act) && keyMatch(r.obj, p.obj) +m = g(r.sub, p.sub) && keyMatch(r.res, p.res) && keyMatch(r.act, p.act) && keyMatch(r.obj, p.obj) \ No newline at end of file diff --git a/vendor/github.com/argoproj/argo-cd/assets/swagger.json b/vendor/github.com/argoproj/argo-cd/assets/swagger.json index ebc2500e28..0ad53c18de 100644 --- a/vendor/github.com/argoproj/argo-cd/assets/swagger.json +++ b/vendor/github.com/argoproj/argo-cd/assets/swagger.json @@ -3884,4 +3884,4 @@ } } } -} +} \ No newline at end of file diff --git a/vendor/modules.txt b/vendor/modules.txt index 08c58cb28d..d6067989bd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1090,6 +1090,7 @@ k8s.io/helm/pkg/tlsutil k8s.io/helm/pkg/urlutil k8s.io/helm/pkg/version # k8s.io/klog v1.0.0 +## explicit k8s.io/klog # k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d ## explicit diff --git a/wire_gen.go b/wire_gen.go index 7f3a4d669d..828c2ddfe3 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -8,13 +8,15 @@ package main import ( client2 "github.com/devtron-labs/authenticator/client" "github.com/devtron-labs/authenticator/middleware" - appStore2 "github.com/devtron-labs/devtron/api/appStore" - appStoreDeployment2 "github.com/devtron-labs/devtron/api/appStore/deployment" - appStoreDiscover2 "github.com/devtron-labs/devtron/api/appStore/discover" - appStoreValues2 "github.com/devtron-labs/devtron/api/appStore/values" + "github.com/devtron-labs/devtron/api/appStore" + "github.com/devtron-labs/devtron/api/appStore/deployment" + "github.com/devtron-labs/devtron/api/appStore/discover" + "github.com/devtron-labs/devtron/api/appStore/values" chartRepo2 "github.com/devtron-labs/devtron/api/chartRepo" cluster3 "github.com/devtron-labs/devtron/api/cluster" "github.com/devtron-labs/devtron/api/connector" + "github.com/devtron-labs/devtron/api/dashboardEvent" + "github.com/devtron-labs/devtron/api/deployment" client4 "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/restHandler" app3 "github.com/devtron-labs/devtron/api/restHandler/app" @@ -27,7 +29,7 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/client/argocdServer/cluster" - repository4 "github.com/devtron-labs/devtron/client/argocdServer/repository" + repository5 "github.com/devtron-labs/devtron/client/argocdServer/repository" session2 "github.com/devtron-labs/devtron/client/argocdServer/session" "github.com/devtron-labs/devtron/client/dashboard" "github.com/devtron-labs/devtron/client/events" @@ -52,18 +54,17 @@ import ( app2 "github.com/devtron-labs/devtron/pkg/app" "github.com/devtron-labs/devtron/pkg/appClone" "github.com/devtron-labs/devtron/pkg/appClone/batch" - "github.com/devtron-labs/devtron/pkg/appStore" "github.com/devtron-labs/devtron/pkg/appStore/bean" - "github.com/devtron-labs/devtron/pkg/appStore/deployment" "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" + repository6 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" + service2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool/gitops" - "github.com/devtron-labs/devtron/pkg/appStore/discover" "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - "github.com/devtron-labs/devtron/pkg/appStore/repository" - "github.com/devtron-labs/devtron/pkg/appStore/values" + service3 "github.com/devtron-labs/devtron/pkg/appStore/discover/service" "github.com/devtron-labs/devtron/pkg/appStore/values/repository" + "github.com/devtron-labs/devtron/pkg/appStore/values/service" appWorkflow2 "github.com/devtron-labs/devtron/pkg/appWorkflow" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/chartRepo" @@ -80,6 +81,8 @@ import ( jira2 "github.com/devtron-labs/devtron/pkg/jira" "github.com/devtron-labs/devtron/pkg/notifier" "github.com/devtron-labs/devtron/pkg/pipeline" + "github.com/devtron-labs/devtron/pkg/pipeline/history" + repository4 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" "github.com/devtron-labs/devtron/pkg/projectManagementService/jira" security2 "github.com/devtron-labs/devtron/pkg/security" "github.com/devtron-labs/devtron/pkg/sql" @@ -206,7 +209,14 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - appServiceImpl := app2.NewAppService(envConfigOverrideRepositoryImpl, pipelineOverrideRepositoryImpl, mergeUtil, sugaredLogger, ciArtifactRepositoryImpl, pipelineRepositoryImpl, dbMigrationConfigRepositoryImpl, eventRESTClientImpl, eventSimpleFactoryImpl, serviceClientImpl, tokenCache, acdAuthConfig, enforcerImpl, enforcerUtilImpl, userServiceImpl, appListingRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, chartRepositoryImpl, ciPipelineMaterialRepositoryImpl, cdWorkflowRepositoryImpl, commonServiceImpl, imageScanDeployInfoRepositoryImpl, imageScanHistoryRepositoryImpl, argoK8sClientImpl, gitFactory, gitOpsConfigRepositoryImpl) + pipelineStrategyHistoryRepositoryImpl := repository4.NewPipelineStrategyHistoryRepositoryImpl(sugaredLogger, db) + pipelineStrategyHistoryServiceImpl := history.NewPipelineStrategyHistoryServiceImpl(sugaredLogger, pipelineStrategyHistoryRepositoryImpl, userServiceImpl) + configMapHistoryRepositoryImpl := repository4.NewConfigMapHistoryRepositoryImpl(sugaredLogger, db) + configMapHistoryServiceImpl := history.NewConfigMapHistoryServiceImpl(sugaredLogger, configMapHistoryRepositoryImpl, pipelineRepositoryImpl, configMapRepositoryImpl, userServiceImpl) + deploymentTemplateHistoryRepositoryImpl := repository4.NewDeploymentTemplateHistoryRepositoryImpl(sugaredLogger, db) + chartRefRepositoryImpl := chartRepoRepository.NewChartRefRepositoryImpl(db) + deploymentTemplateHistoryServiceImpl := history.NewDeploymentTemplateHistoryServiceImpl(sugaredLogger, deploymentTemplateHistoryRepositoryImpl, pipelineRepositoryImpl, chartRepositoryImpl, chartRefRepositoryImpl, envLevelAppMetricsRepositoryImpl, appLevelMetricsRepositoryImpl, userServiceImpl, cdWorkflowRepositoryImpl) + appServiceImpl := app2.NewAppService(envConfigOverrideRepositoryImpl, pipelineOverrideRepositoryImpl, mergeUtil, sugaredLogger, ciArtifactRepositoryImpl, pipelineRepositoryImpl, dbMigrationConfigRepositoryImpl, eventRESTClientImpl, eventSimpleFactoryImpl, serviceClientImpl, tokenCache, acdAuthConfig, enforcerImpl, enforcerUtilImpl, userServiceImpl, appListingRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, chartRepositoryImpl, ciPipelineMaterialRepositoryImpl, cdWorkflowRepositoryImpl, commonServiceImpl, imageScanDeployInfoRepositoryImpl, imageScanHistoryRepositoryImpl, argoK8sClientImpl, gitFactory, gitOpsConfigRepositoryImpl, pipelineStrategyHistoryServiceImpl, configMapHistoryServiceImpl, deploymentTemplateHistoryServiceImpl) validate, err := util.IntValidator() if err != nil { return nil, err @@ -222,7 +232,9 @@ func InitializeApp() (*App, error) { cvePolicyRepositoryImpl := security.NewPolicyRepositoryImpl(db) imageScanResultRepositoryImpl := security.NewImageScanResultRepositoryImpl(db, sugaredLogger) appWorkflowRepositoryImpl := appWorkflow.NewAppWorkflowRepositoryImpl(sugaredLogger, db) - workflowDagExecutorImpl := pipeline.NewWorkflowDagExecutorImpl(sugaredLogger, pipelineRepositoryImpl, cdWorkflowRepositoryImpl, pubSubClient, appServiceImpl, cdWorkflowServiceImpl, cdConfig, ciArtifactRepositoryImpl, ciPipelineRepositoryImpl, materialRepositoryImpl, pipelineOverrideRepositoryImpl, userServiceImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, enforcerImpl, enforcerUtilImpl, tokenCache, acdAuthConfig, eventSimpleFactoryImpl, eventRESTClientImpl, cvePolicyRepositoryImpl, imageScanResultRepositoryImpl, appWorkflowRepositoryImpl) + prePostCdScriptHistoryRepositoryImpl := repository4.NewPrePostCdScriptHistoryRepositoryImpl(sugaredLogger, db) + prePostCdScriptHistoryServiceImpl := history.NewPrePostCdScriptHistoryServiceImpl(sugaredLogger, prePostCdScriptHistoryRepositoryImpl, configMapRepositoryImpl, configMapHistoryServiceImpl) + workflowDagExecutorImpl := pipeline.NewWorkflowDagExecutorImpl(sugaredLogger, pipelineRepositoryImpl, cdWorkflowRepositoryImpl, pubSubClient, appServiceImpl, cdWorkflowServiceImpl, cdConfig, ciArtifactRepositoryImpl, ciPipelineRepositoryImpl, materialRepositoryImpl, pipelineOverrideRepositoryImpl, userServiceImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, enforcerImpl, enforcerUtilImpl, tokenCache, acdAuthConfig, eventSimpleFactoryImpl, eventRESTClientImpl, cvePolicyRepositoryImpl, imageScanResultRepositoryImpl, appWorkflowRepositoryImpl, prePostCdScriptHistoryServiceImpl) deploymentGroupAppRepositoryImpl := repository.NewDeploymentGroupAppRepositoryImpl(sugaredLogger, db) deploymentGroupServiceImpl := deploymentGroup.NewDeploymentGroupServiceImpl(appRepositoryImpl, sugaredLogger, pipelineRepositoryImpl, ciPipelineRepositoryImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, deploymentGroupAppRepositoryImpl, ciArtifactRepositoryImpl, appWorkflowRepositoryImpl, workflowDagExecutorImpl) pipelineTriggerRestHandlerImpl := restHandler.NewPipelineRestHandler(appServiceImpl, userServiceImpl, validate, enforcerImpl, teamServiceImpl, sugaredLogger, enforcerUtilImpl, workflowDagExecutorImpl, deploymentGroupServiceImpl) @@ -248,17 +260,19 @@ func InitializeApp() (*App, error) { attributesServiceImpl := attributes.NewAttributesServiceImpl(sugaredLogger, sessionSessionManager, attributesRepositoryImpl) appLabelRepositoryImpl := pipelineConfig.NewAppLabelRepositoryImpl(db) appLabelServiceImpl := app2.NewAppLabelServiceImpl(appLabelRepositoryImpl, sugaredLogger, appRepositoryImpl, userRepositoryImpl) - dbPipelineOrchestratorImpl := pipeline.NewDbPipelineOrchestrator(appRepositoryImpl, sugaredLogger, materialRepositoryImpl, pipelineRepositoryImpl, ciPipelineRepositoryImpl, ciPipelineMaterialRepositoryImpl, gitSensorClientImpl, ciConfig, appWorkflowRepositoryImpl, environmentRepositoryImpl, attributesServiceImpl, appListingRepositoryImpl, appLabelServiceImpl, userAuthServiceImpl) + prePostCiScriptHistoryRepositoryImpl := repository4.NewPrePostCiScriptHistoryRepositoryImpl(sugaredLogger, db) + prePostCiScriptHistoryServiceImpl := history.NewPrePostCiScriptHistoryServiceImpl(sugaredLogger, prePostCiScriptHistoryRepositoryImpl) + dbPipelineOrchestratorImpl := pipeline.NewDbPipelineOrchestrator(appRepositoryImpl, sugaredLogger, materialRepositoryImpl, pipelineRepositoryImpl, ciPipelineRepositoryImpl, ciPipelineMaterialRepositoryImpl, gitSensorClientImpl, ciConfig, appWorkflowRepositoryImpl, environmentRepositoryImpl, attributesServiceImpl, appListingRepositoryImpl, appLabelServiceImpl, userAuthServiceImpl, prePostCdScriptHistoryServiceImpl, prePostCiScriptHistoryServiceImpl) utilMergeUtil := util.MergeUtil{ Logger: sugaredLogger, } - propertiesConfigServiceImpl := pipeline.NewPropertiesConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, utilMergeUtil, environmentRepositoryImpl, dbPipelineOrchestratorImpl, serviceClientImpl, envLevelAppMetricsRepositoryImpl, appLevelMetricsRepositoryImpl) + propertiesConfigServiceImpl := pipeline.NewPropertiesConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, utilMergeUtil, environmentRepositoryImpl, dbPipelineOrchestratorImpl, serviceClientImpl, envLevelAppMetricsRepositoryImpl, appLevelMetricsRepositoryImpl, deploymentTemplateHistoryServiceImpl) ciTemplateRepositoryImpl := pipelineConfig.NewCiTemplateRepositoryImpl(db, sugaredLogger) ecrConfig, err := pipeline.GetEcrConfig() if err != nil { return nil, err } - pipelineBuilderImpl := pipeline.NewPipelineBuilderImpl(sugaredLogger, dbPipelineOrchestratorImpl, dockerArtifactStoreRepositoryImpl, materialRepositoryImpl, appRepositoryImpl, pipelineRepositoryImpl, propertiesConfigServiceImpl, ciTemplateRepositoryImpl, ciPipelineRepositoryImpl, serviceClientImpl, chartRepositoryImpl, ciArtifactRepositoryImpl, ecrConfig, envConfigOverrideRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, utilMergeUtil, appWorkflowRepositoryImpl, ciConfig, cdWorkflowRepositoryImpl, appServiceImpl, imageScanResultRepositoryImpl, argoK8sClientImpl, gitFactory, attributesServiceImpl, acdAuthConfig, gitOpsConfigRepositoryImpl) + pipelineBuilderImpl := pipeline.NewPipelineBuilderImpl(sugaredLogger, dbPipelineOrchestratorImpl, dockerArtifactStoreRepositoryImpl, materialRepositoryImpl, appRepositoryImpl, pipelineRepositoryImpl, propertiesConfigServiceImpl, ciTemplateRepositoryImpl, ciPipelineRepositoryImpl, serviceClientImpl, chartRepositoryImpl, ciArtifactRepositoryImpl, ecrConfig, envConfigOverrideRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, utilMergeUtil, appWorkflowRepositoryImpl, ciConfig, cdWorkflowRepositoryImpl, appServiceImpl, imageScanResultRepositoryImpl, argoK8sClientImpl, gitFactory, attributesServiceImpl, acdAuthConfig, gitOpsConfigRepositoryImpl, pipelineStrategyHistoryServiceImpl, prePostCiScriptHistoryServiceImpl, prePostCdScriptHistoryServiceImpl, deploymentTemplateHistoryServiceImpl, appLevelMetricsRepositoryImpl) chartWorkingDir := _wireChartWorkingDirValue globalEnvVariables, err := util3.GetGlobalEnvVariables() if err != nil { @@ -268,13 +282,11 @@ func InitializeApp() (*App, error) { chartRepoRepositoryImpl := chartRepoRepository.NewChartRepoRepositoryImpl(db) refChartDir := _wireRefChartDirValue defaultChart := _wireDefaultChartValue - repositoryServiceClientImpl := repository4.NewServiceClientImpl(argoCDSettings, sugaredLogger) - chartRefRepositoryImpl := chartRepoRepository.NewChartRefRepositoryImpl(db) - customFormatCheckers := util3.NewGoJsonSchemaCustomFormatChecker() - chartServiceImpl := pipeline.NewChartServiceImpl(chartRepositoryImpl, sugaredLogger, chartTemplateServiceImpl, chartRepoRepositoryImpl, appRepositoryImpl, refChartDir, defaultChart, utilMergeUtil, repositoryServiceClientImpl, chartRefRepositoryImpl, envConfigOverrideRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, appLevelMetricsRepositoryImpl, httpClient, customFormatCheckers) + repositoryServiceClientImpl := repository5.NewServiceClientImpl(argoCDSettings, sugaredLogger) + chartServiceImpl := pipeline.NewChartServiceImpl(chartRepositoryImpl, sugaredLogger, chartTemplateServiceImpl, chartRepoRepositoryImpl, appRepositoryImpl, refChartDir, defaultChart, utilMergeUtil, repositoryServiceClientImpl, chartRefRepositoryImpl, envConfigOverrideRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, httpClient, deploymentTemplateHistoryServiceImpl) dbMigrationServiceImpl := pipeline.NewDbMogrationService(sugaredLogger, dbMigrationConfigRepositoryImpl) workflowServiceImpl := pipeline.NewWorkflowServiceImpl(sugaredLogger, ciConfig) - ciServiceImpl := pipeline.NewCiServiceImpl(sugaredLogger, workflowServiceImpl, ciPipelineMaterialRepositoryImpl, ciWorkflowRepositoryImpl, ciConfig, eventRESTClientImpl, eventSimpleFactoryImpl, mergeUtil, ciPipelineRepositoryImpl) + ciServiceImpl := pipeline.NewCiServiceImpl(sugaredLogger, workflowServiceImpl, ciPipelineMaterialRepositoryImpl, ciWorkflowRepositoryImpl, ciConfig, eventRESTClientImpl, eventSimpleFactoryImpl, mergeUtil, ciPipelineRepositoryImpl, prePostCiScriptHistoryServiceImpl) ciLogServiceImpl := pipeline.NewCiLogServiceImpl(sugaredLogger, ciServiceImpl, ciConfig) ciHandlerImpl := pipeline.NewCiHandlerImpl(sugaredLogger, ciServiceImpl, ciPipelineMaterialRepositoryImpl, gitSensorClientImpl, ciWorkflowRepositoryImpl, workflowServiceImpl, ciLogServiceImpl, ciConfig, ciArtifactRepositoryImpl, userServiceImpl, eventRESTClientImpl, eventSimpleFactoryImpl, ciPipelineRepositoryImpl, appListingRepositoryImpl) grafanaClientConfig, err := grafana.GetGrafanaClientConfig() @@ -282,17 +294,17 @@ func InitializeApp() (*App, error) { return nil, err } grafanaClientImpl := grafana.NewGrafanaClientImpl(sugaredLogger, httpClient, grafanaClientConfig, attributesServiceImpl) - installedAppRepositoryImpl := appStoreRepository.NewInstalledAppRepositoryImpl(sugaredLogger, db) + installedAppRepositoryImpl := repository6.NewInstalledAppRepositoryImpl(sugaredLogger, db) k8sUtil := util.NewK8sUtil(sugaredLogger, runtimeConfig) clusterServiceClientImpl := cluster.NewServiceClientImpl(argoCDSettings, sugaredLogger) v := informer.NewGlobalMapClusterNamespace() - k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, v) + k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, v, runtimeConfig) clusterServiceImplExtended := cluster2.NewClusterServiceImplExtended(clusterRepositoryImpl, environmentRepositoryImpl, grafanaClientImpl, sugaredLogger, installedAppRepositoryImpl, k8sUtil, clusterServiceClientImpl, k8sInformerFactoryImpl) environmentServiceImpl := cluster2.NewEnvironmentServiceImpl(environmentRepositoryImpl, clusterServiceImplExtended, sugaredLogger, k8sUtil, k8sInformerFactoryImpl, userAuthServiceImpl) gitRegistryConfigImpl := pipeline.NewGitRegistryConfigImpl(sugaredLogger, gitProviderRepositoryImpl, gitSensorClientImpl) dockerRegistryConfigImpl := pipeline.NewDockerRegistryConfigImpl(dockerArtifactStoreRepositoryImpl, sugaredLogger) cdHandlerImpl := pipeline.NewCdHandlerImpl(sugaredLogger, cdConfig, userServiceImpl, cdWorkflowRepositoryImpl, cdWorkflowServiceImpl, ciLogServiceImpl, ciArtifactRepositoryImpl, ciPipelineMaterialRepositoryImpl, pipelineRepositoryImpl, environmentRepositoryImpl, ciWorkflowRepositoryImpl, ciConfig) - configMapServiceImpl := pipeline.NewConfigMapServiceImpl(chartRepositoryImpl, sugaredLogger, chartRepoRepositoryImpl, utilMergeUtil, pipelineConfigRepositoryImpl, configMapRepositoryImpl, envConfigOverrideRepositoryImpl, commonServiceImpl, appRepositoryImpl) + configMapServiceImpl := pipeline.NewConfigMapServiceImpl(chartRepositoryImpl, sugaredLogger, chartRepoRepositoryImpl, utilMergeUtil, pipelineConfigRepositoryImpl, configMapRepositoryImpl, envConfigOverrideRepositoryImpl, commonServiceImpl, appRepositoryImpl, configMapHistoryServiceImpl) appWorkflowServiceImpl := appWorkflow2.NewAppWorkflowServiceImpl(sugaredLogger, appWorkflowRepositoryImpl, dbPipelineOrchestratorImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl) appListingViewBuilderImpl := app2.NewAppListingViewBuilderImpl(sugaredLogger) linkoutsRepositoryImpl := repository.NewLinkoutsRepositoryImpl(sugaredLogger, db) @@ -306,7 +318,8 @@ func InitializeApp() (*App, error) { webhookEventDataRepositoryImpl := repository.NewWebhookEventDataRepositoryImpl(db) webhookEventDataConfigImpl := pipeline.NewWebhookEventDataConfigImpl(sugaredLogger, webhookEventDataRepositoryImpl) webhookDataRestHandlerImpl := restHandler.NewWebhookDataRestHandlerImpl(sugaredLogger, userServiceImpl, ciPipelineMaterialRepositoryImpl, enforcerUtilImpl, enforcerImpl, gitSensorClientImpl, webhookEventDataConfigImpl) - pipelineConfigRouterImpl := router.NewPipelineRouterImpl(pipelineConfigRestHandlerImpl, appWorkflowRestHandlerImpl, webhookDataRestHandlerImpl) + pipelineHistoryRestHandlerImpl := restHandler.NewPipelineHistoryRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, pipelineStrategyHistoryServiceImpl, deploymentTemplateHistoryServiceImpl, configMapHistoryServiceImpl, prePostCiScriptHistoryServiceImpl, prePostCdScriptHistoryServiceImpl, pipelineBuilderImpl, enforcerUtilImpl) + pipelineConfigRouterImpl := router.NewPipelineRouterImpl(pipelineConfigRestHandlerImpl, appWorkflowRestHandlerImpl, webhookDataRestHandlerImpl, pipelineHistoryRestHandlerImpl) dbConfigRepositoryImpl := repository.NewDbConfigRepositoryImpl(db, sugaredLogger) dbConfigServiceImpl := pipeline.NewDbConfigService(dbConfigRepositoryImpl, sugaredLogger) migrateDbRestHandlerImpl := restHandler.NewMigrateDbRestHandlerImpl(dockerRegistryConfigImpl, sugaredLogger, gitRegistryConfigImpl, dbConfigServiceImpl, userServiceImpl, validate, dbMigrationServiceImpl, enforcerImpl) @@ -377,7 +390,30 @@ func InitializeApp() (*App, error) { teamRouterImpl := team2.NewTeamRouterImpl(teamRestHandlerImpl) gitWebhookHandlerImpl := pubsub2.NewGitWebhookHandler(sugaredLogger, pubSubClient, gitWebhookServiceImpl) workflowStatusUpdateHandlerImpl := pubsub2.NewWorkflowStatusUpdateHandlerImpl(sugaredLogger, pubSubClient, ciHandlerImpl, cdHandlerImpl, eventSimpleFactoryImpl, eventRESTClientImpl, cdWorkflowRepositoryImpl) - applicationStatusUpdateHandlerImpl := pubsub2.NewApplicationStatusUpdateHandlerImpl(sugaredLogger, pubSubClient, appServiceImpl, workflowDagExecutorImpl) + refChartProxyDir := _wireRefChartProxyDirValue + appStoreApplicationVersionRepositoryImpl := appStoreDiscoverRepository.NewAppStoreApplicationVersionRepositoryImpl(sugaredLogger, db) + appStoreVersionValuesRepositoryImpl := appStoreValuesRepository.NewAppStoreVersionValuesRepositoryImpl(sugaredLogger, db) + appStoreValuesServiceImpl := service.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl) + chartGroupDeploymentRepositoryImpl := repository6.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) + appStoreDeploymentFullModeServiceImpl := appStoreDeploymentFullMode.NewAppStoreDeploymentFullModeServiceImpl(sugaredLogger, chartTemplateServiceImpl, refChartProxyDir, repositoryServiceClientImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, serviceClientImpl, argoK8sClientImpl, gitFactory, acdAuthConfig, gitOpsConfigRepositoryImpl, globalEnvVariables, installedAppRepositoryImpl, tokenCache) + clusterInstalledAppsRepositoryImpl := repository6.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) + helmClientConfig, err := client4.GetConfig() + if err != nil { + return nil, err + } + helmAppClientImpl := client4.NewHelmAppClientImpl(sugaredLogger, helmClientConfig) + enforcerUtilHelmImpl := rbac.NewEnforcerUtilHelmImpl(sugaredLogger, clusterRepositoryImpl) + helmAppServiceImpl := client4.NewHelmAppServiceImpl(sugaredLogger, clusterServiceImplExtended, helmAppClientImpl, pumpImpl, enforcerUtilHelmImpl) + appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, helmAppClientImpl) + installedAppVersionHistoryRepositoryImpl := repository6.NewInstalledAppVersionHistoryRepositoryImpl(sugaredLogger, db) + appStoreDeploymentArgoCdServiceImpl := appStoreDeploymentGitopsTool.NewAppStoreDeploymentArgoCdServiceImpl(sugaredLogger, appStoreDeploymentFullModeServiceImpl, serviceClientImpl, chartGroupDeploymentRepositoryImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl) + appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl) + appStoreDeploymentServiceImpl := service2.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentArgoCdServiceImpl, environmentServiceImpl, clusterServiceImplExtended, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, globalEnvVariables, installedAppVersionHistoryRepositoryImpl) + installedAppServiceImpl, err := service2.NewInstalledAppServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartTemplateServiceImpl, refChartProxyDir, repositoryServiceClientImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, serviceClientImpl, appStoreValuesServiceImpl, pubSubClient, tokenCache, chartGroupDeploymentRepositoryImpl, environmentServiceImpl, argoK8sClientImpl, gitFactory, acdAuthConfig, gitOpsConfigRepositoryImpl, userServiceImpl, appStoreDeploymentFullModeServiceImpl, appStoreDeploymentServiceImpl, installedAppVersionHistoryRepositoryImpl) + if err != nil { + return nil, err + } + applicationStatusUpdateHandlerImpl := pubsub2.NewApplicationStatusUpdateHandlerImpl(sugaredLogger, pubSubClient, appServiceImpl, workflowDagExecutorImpl, installedAppServiceImpl) roleGroupServiceImpl := user.NewRoleGroupServiceImpl(userAuthRepositoryImpl, sugaredLogger, userRepositoryImpl, roleGroupRepositoryImpl, userCommonServiceImpl) userRestHandlerImpl := user2.NewUserRestHandlerImpl(userServiceImpl, validate, sugaredLogger, enforcerImpl, roleGroupServiceImpl) userRouterImpl := user2.NewUserRouterImpl(userRestHandlerImpl) @@ -389,37 +425,16 @@ func InitializeApp() (*App, error) { chartRefRouterImpl := router.NewChartRefRouterImpl(chartRefRestHandlerImpl) configMapRestHandlerImpl := restHandler.NewConfigMapRestHandlerImpl(pipelineBuilderImpl, sugaredLogger, chartServiceImpl, userServiceImpl, teamServiceImpl, enforcerImpl, pipelineRepositoryImpl, enforcerUtilImpl, configMapServiceImpl) configMapRouterImpl := router.NewConfigMapRouterImpl(configMapRestHandlerImpl) - refChartProxyDir := _wireRefChartProxyDirValue - appStoreApplicationVersionRepositoryImpl := appStoreDiscoverRepository.NewAppStoreApplicationVersionRepositoryImpl(sugaredLogger, db) - appStoreVersionValuesRepositoryImpl := appStoreValuesRepository.NewAppStoreVersionValuesRepositoryImpl(sugaredLogger, db) - appStoreValuesServiceImpl := appStoreValues.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl) - chartGroupDeploymentRepositoryImpl := appStoreRepository.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) - clusterInstalledAppsRepositoryImpl := appStoreRepository.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) - helmClientConfig, err := client4.GetConfig() - if err != nil { - return nil, err - } - helmAppClientImpl := client4.NewHelmAppClientImpl(sugaredLogger, helmClientConfig) - enforcerUtilHelmImpl := rbac.NewEnforcerUtilHelmImpl(sugaredLogger, clusterRepositoryImpl) - helmAppServiceImpl := client4.NewHelmAppServiceImpl(sugaredLogger, clusterServiceImplExtended, helmAppClientImpl, pumpImpl, enforcerUtilHelmImpl) - appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl) - appStoreDeploymentFullModeServiceImpl := appStoreDeploymentFullMode.NewAppStoreDeploymentFullModeServiceImpl(sugaredLogger, chartTemplateServiceImpl, refChartProxyDir, repositoryServiceClientImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, serviceClientImpl, argoK8sClientImpl, gitFactory, acdAuthConfig, gitOpsConfigRepositoryImpl, globalEnvVariables) - appStoreDeploymentArgoCdServiceImpl := appStoreDeploymentGitopsTool.NewAppStoreDeploymentArgoCdServiceImpl(sugaredLogger, appStoreDeploymentFullModeServiceImpl, serviceClientImpl, chartGroupDeploymentRepositoryImpl) - appStoreDeploymentServiceImpl := appStoreDeployment.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentArgoCdServiceImpl, environmentServiceImpl, clusterServiceImplExtended, globalEnvVariables) - installedAppServiceImpl, err := appStore.NewInstalledAppServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartTemplateServiceImpl, refChartProxyDir, repositoryServiceClientImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, serviceClientImpl, appStoreValuesServiceImpl, pubSubClient, tokenCache, chartGroupDeploymentRepositoryImpl, environmentServiceImpl, argoK8sClientImpl, gitFactory, acdAuthConfig, gitOpsConfigRepositoryImpl, userServiceImpl, appStoreDeploymentServiceImpl, appStoreDeploymentFullModeServiceImpl) - if err != nil { - return nil, err - } - installedAppRestHandlerImpl := appStore2.NewInstalledAppRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, installedAppServiceImpl, validate, clusterServiceImplExtended, serviceClientImpl, appStoreDeploymentServiceImpl) - appStoreValuesRestHandlerImpl := appStoreValues2.NewAppStoreValuesRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreValuesServiceImpl) - appStoreValuesRouterImpl := appStoreValues2.NewAppStoreValuesRouterImpl(appStoreValuesRestHandlerImpl) - appStoreServiceImpl := appStoreDiscover.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) - appStoreRestHandlerImpl := appStoreDiscover2.NewAppStoreRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreServiceImpl, enforcerImpl) - appStoreDiscoverRouterImpl := appStoreDiscover2.NewAppStoreDiscoverRouterImpl(appStoreRestHandlerImpl) - appStoreDeploymentRestHandlerImpl := appStoreDeployment2.NewAppStoreDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate) - appStoreDeploymentRouterImpl := appStoreDeployment2.NewAppStoreDeploymentRouterImpl(appStoreDeploymentRestHandlerImpl) - appStoreRouterImpl := appStore2.NewAppStoreRouterImpl(installedAppRestHandlerImpl, appStoreValuesRouterImpl, appStoreDiscoverRouterImpl, appStoreDeploymentRouterImpl) - chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceExtendedImpl) + installedAppRestHandlerImpl := appStore.NewInstalledAppRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, installedAppServiceImpl, validate, clusterServiceImplExtended, serviceClientImpl, appStoreDeploymentServiceImpl) + appStoreValuesRestHandlerImpl := appStoreValues.NewAppStoreValuesRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreValuesServiceImpl) + appStoreValuesRouterImpl := appStoreValues.NewAppStoreValuesRouterImpl(appStoreValuesRestHandlerImpl) + appStoreServiceImpl := service3.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) + appStoreRestHandlerImpl := appStoreDiscover.NewAppStoreRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreServiceImpl, enforcerImpl) + appStoreDiscoverRouterImpl := appStoreDiscover.NewAppStoreDiscoverRouterImpl(appStoreRestHandlerImpl) + appStoreDeploymentRestHandlerImpl := appStoreDeployment.NewAppStoreDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl) + appStoreDeploymentRouterImpl := appStoreDeployment.NewAppStoreDeploymentRouterImpl(appStoreDeploymentRestHandlerImpl) + appStoreRouterImpl := appStore.NewAppStoreRouterImpl(installedAppRestHandlerImpl, appStoreValuesRouterImpl, appStoreDiscoverRouterImpl, appStoreDeploymentRouterImpl) + chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceExtendedImpl, chartRefRepositoryImpl, refChartDir) chartRepositoryRouterImpl := chartRepo2.NewChartRepositoryRouterImpl(chartRepositoryRestHandlerImpl) lensConfig, err := lens.GetLensConfig() if err != nil { @@ -441,9 +456,9 @@ func InitializeApp() (*App, error) { workflowActionImpl := batch.NewWorkflowActionImpl(sugaredLogger, appRepositoryImpl, appWorkflowServiceImpl, buildActionImpl, deploymentActionImpl) batchOperationRestHandlerImpl := restHandler.NewBatchOperationRestHandlerImpl(userServiceImpl, enforcerImpl, workflowActionImpl, teamServiceImpl, sugaredLogger, enforcerUtilImpl) batchOperationRouterImpl := router.NewBatchOperationRouterImpl(batchOperationRestHandlerImpl, sugaredLogger) - chartGroupEntriesRepositoryImpl := appStoreRepository.NewChartGroupEntriesRepositoryImpl(db, sugaredLogger) - chartGroupReposotoryImpl := appStoreRepository.NewChartGroupReposotoryImpl(db, sugaredLogger) - chartGroupServiceImpl := appStore.NewChartGroupServiceImpl(chartGroupEntriesRepositoryImpl, chartGroupReposotoryImpl, sugaredLogger, chartGroupDeploymentRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userAuthServiceImpl) + chartGroupEntriesRepositoryImpl := repository6.NewChartGroupEntriesRepositoryImpl(db, sugaredLogger) + chartGroupReposotoryImpl := repository6.NewChartGroupReposotoryImpl(db, sugaredLogger) + chartGroupServiceImpl := service2.NewChartGroupServiceImpl(chartGroupEntriesRepositoryImpl, chartGroupReposotoryImpl, sugaredLogger, chartGroupDeploymentRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userAuthServiceImpl) chartGroupRestHandlerImpl := restHandler.NewChartGroupRestHandlerImpl(chartGroupServiceImpl, sugaredLogger, userServiceImpl, enforcerImpl, validate) chartGroupRouterImpl := router.NewChartGroupRouterImpl(chartGroupRestHandlerImpl) testSuitRestHandlerImpl := restHandler.NewTestSuitRestHandlerImpl(sugaredLogger, userServiceImpl, validate, enforcerImpl, enforcerUtilImpl, eventClientConfig, httpClient) @@ -479,14 +494,14 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - telemetryEventClientImpl, err := telemetry.NewTelemetryEventClientImpl(sugaredLogger, httpClient, clusterServiceImplExtended, k8sUtil, acdAuthConfig, userServiceImpl, posthogClient) + telemetryEventClientImplExtended, err := telemetry.NewTelemetryEventClientImplExtended(sugaredLogger, httpClient, clusterServiceImplExtended, k8sUtil, acdAuthConfig, environmentServiceImpl, userServiceImpl, appListingRepositoryImpl, posthogClient, ciPipelineRepositoryImpl, pipelineRepositoryImpl) if err != nil { return nil, err } - telemetryRestHandlerImpl := restHandler.NewTelemetryRestHandlerImpl(sugaredLogger, telemetryEventClientImpl) + telemetryRestHandlerImpl := restHandler.NewTelemetryRestHandlerImpl(sugaredLogger, telemetryEventClientImplExtended) telemetryRouterImpl := router.NewTelemetryRouterImpl(sugaredLogger, telemetryRestHandlerImpl) bulkUpdateRepositoryImpl := bulkUpdate.NewBulkUpdateRepository(db, sugaredLogger) - bulkUpdateServiceImpl := pipeline.NewBulkUpdateServiceImpl(bulkUpdateRepositoryImpl, chartRepositoryImpl, sugaredLogger, chartTemplateServiceImpl, chartRepoRepositoryImpl, refChartDir, defaultChart, utilMergeUtil, repositoryServiceClientImpl, chartRefRepositoryImpl, envConfigOverrideRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, appLevelMetricsRepositoryImpl, httpClient, appRepositoryImpl) + bulkUpdateServiceImpl := pipeline.NewBulkUpdateServiceImpl(bulkUpdateRepositoryImpl, chartRepositoryImpl, sugaredLogger, chartTemplateServiceImpl, chartRepoRepositoryImpl, refChartDir, defaultChart, utilMergeUtil, repositoryServiceClientImpl, chartRefRepositoryImpl, envConfigOverrideRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, httpClient, appRepositoryImpl, deploymentTemplateHistoryServiceImpl, configMapHistoryServiceImpl) bulkUpdateRestHandlerImpl := restHandler.NewBulkUpdateRestHandlerImpl(pipelineBuilderImpl, sugaredLogger, bulkUpdateServiceImpl, chartServiceImpl, propertiesConfigServiceImpl, dbMigrationServiceImpl, serviceClientImpl, userServiceImpl, teamServiceImpl, enforcerImpl, ciHandlerImpl, validate, gitSensorClientImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, enforcerUtilImpl, environmentServiceImpl, gitRegistryConfigImpl, dockerRegistryConfigImpl, cdHandlerImpl, appCloneServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, policyServiceImpl, imageScanResultRepositoryImpl) bulkUpdateRouterImpl := router.NewBulkUpdateRouterImpl(bulkUpdateRestHandlerImpl) webhookSecretValidatorImpl := git.NewWebhookSecretValidatorImpl(sugaredLogger) @@ -496,7 +511,6 @@ func InitializeApp() (*App, error) { appLabelRouterImpl := router.NewAppLabelRouterImpl(sugaredLogger, appLabelRestHandlerImpl) coreAppRestHandlerImpl := restHandler.NewCoreAppRestHandlerImpl(sugaredLogger, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, appLabelServiceImpl, pipelineBuilderImpl, gitRegistryConfigImpl, chartServiceImpl, configMapServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, gitProviderRepositoryImpl, appWorkflowRepositoryImpl, environmentRepositoryImpl, configMapRepositoryImpl, envConfigOverrideRepositoryImpl, chartRepositoryImpl, teamServiceImpl) coreAppRouterImpl := router.NewCoreAppRouterImpl(coreAppRestHandlerImpl) - appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl) helmAppRestHandlerImpl := client4.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentCommonServiceImpl) helmAppRouterImpl := client4.NewHelmAppRouterImpl(helmAppRestHandlerImpl) k8sClientServiceImpl := application2.NewK8sClientServiceImpl(sugaredLogger, clusterRepositoryImpl) @@ -505,7 +519,13 @@ func InitializeApp() (*App, error) { k8sApplicationRouterImpl := k8s.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) pProfRestHandlerImpl := restHandler.NewPProfRestHandler(userServiceImpl) pProfRouterImpl := router.NewPProfRouter(sugaredLogger, pProfRestHandlerImpl) - muxRouter := router.NewMuxRouter(sugaredLogger, helmRouterImpl, pipelineConfigRouterImpl, migrateDbRouterImpl, appListingRouterImpl, environmentRouterImpl, clusterRouterImpl, webhookRouterImpl, userAuthRouterImpl, applicationRouterImpl, cdRouterImpl, projectManagementRouterImpl, gitProviderRouterImpl, gitHostRouterImpl, dockerRegRouterImpl, notificationRouterImpl, teamRouterImpl, gitWebhookHandlerImpl, workflowStatusUpdateHandlerImpl, applicationStatusUpdateHandlerImpl, ciEventHandlerImpl, pubSubClient, userRouterImpl, cronBasedEventReceiverImpl, chartRefRouterImpl, configMapRouterImpl, appStoreRouterImpl, chartRepositoryRouterImpl, releaseMetricsRouterImpl, deploymentGroupRouterImpl, batchOperationRouterImpl, chartGroupRouterImpl, testSuitRouterImpl, imageScanRouterImpl, policyRouterImpl, gitOpsConfigRouterImpl, dashboardRouterImpl, attributesRouterImpl, commonRouterImpl, grafanaRouterImpl, ssoLoginRouterImpl, telemetryRouterImpl, telemetryEventClientImpl, bulkUpdateRouterImpl, webhookListenerRouterImpl, appLabelRouterImpl, coreAppRouterImpl, helmAppRouterImpl, k8sApplicationRouterImpl, pProfRouterImpl) + deploymentConfigRestHandlerImpl := deployment.NewDeploymentConfigRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, validate, refChartDir, chartServiceImpl, chartRefRepositoryImpl) + deploymentConfigRouterImpl := deployment.NewDeploymentRouterImpl(deploymentConfigRestHandlerImpl) + dashboardTelemetryRestHandlerImpl := dashboardEvent.NewDashboardTelemetryRestHandlerImpl(sugaredLogger, telemetryEventClientImplExtended) + dashboardTelemetryRouterImpl := dashboardEvent.NewDashboardTelemetryRouterImpl(dashboardTelemetryRestHandlerImpl) + commonDeploymentRestHandlerImpl := appStoreDeployment.NewCommonDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, helmAppRestHandlerImpl) + commonDeploymentRouterImpl := appStoreDeployment.NewCommonDeploymentRouterImpl(commonDeploymentRestHandlerImpl) + muxRouter := router.NewMuxRouter(sugaredLogger, helmRouterImpl, pipelineConfigRouterImpl, migrateDbRouterImpl, appListingRouterImpl, environmentRouterImpl, clusterRouterImpl, webhookRouterImpl, userAuthRouterImpl, applicationRouterImpl, cdRouterImpl, projectManagementRouterImpl, gitProviderRouterImpl, gitHostRouterImpl, dockerRegRouterImpl, notificationRouterImpl, teamRouterImpl, gitWebhookHandlerImpl, workflowStatusUpdateHandlerImpl, applicationStatusUpdateHandlerImpl, ciEventHandlerImpl, pubSubClient, userRouterImpl, cronBasedEventReceiverImpl, chartRefRouterImpl, configMapRouterImpl, appStoreRouterImpl, chartRepositoryRouterImpl, releaseMetricsRouterImpl, deploymentGroupRouterImpl, batchOperationRouterImpl, chartGroupRouterImpl, testSuitRouterImpl, imageScanRouterImpl, policyRouterImpl, gitOpsConfigRouterImpl, dashboardRouterImpl, attributesRouterImpl, commonRouterImpl, grafanaRouterImpl, ssoLoginRouterImpl, telemetryRouterImpl, telemetryEventClientImplExtended, bulkUpdateRouterImpl, webhookListenerRouterImpl, appLabelRouterImpl, coreAppRouterImpl, helmAppRouterImpl, k8sApplicationRouterImpl, pProfRouterImpl, deploymentConfigRouterImpl, dashboardTelemetryRouterImpl, commonDeploymentRouterImpl) mainApp := NewApp(muxRouter, sugaredLogger, sseSSE, versionServiceImpl, enforcer, db, pubSubClient, sessionManager) return mainApp, nil }