Repository: chef/automate
Pull request #7949 (2023-06-05 17:08:29)

Syncing configuration to the new node after node add
### :nut_and_bolt: Description: What code changed, and why?

As an Automate HA user, when the user adds a new node, it should also add/sync up all the configs added in the bootstrap Frontend node.

### :chains: Related Resources
Jira ticket: https://chefio.atlassian.net/browse/CHEF-2712

### :+1: Definition of Done
**Following are the scenarios covered in testing:**

- [x] On-Prem with Chef-embedded - Add node.
- [x] On-Prem with Chef-embedded - Remove node (x) Need to check.
- [x] On-prem with Chef-embedded and custom cert - Add node.
- [x] On-prem with Chef-embedded and custom cert - Remove node.
- [x] On-prem with Manged services - Add/Remove node.
- [x] Any Infra with Chef-embedded - Add/Remove OS and PG node.
- [x] AWS with Chef-embedded - Add node.
- [x] AWS with Chef-embedded - Remove the bootstrap node (x) Not working.
- [x] AWS with Managed AWS - Add node.
- [x] AWS with Managed AWS  Remove the bootstrap node and check whether the config is still intact.

> Note: 
> - Sync-up will happen only in frontend nodes, as the BE nodes run in hab cluster
> - Sync-up will ignore the load balance tls values as that will cause issue in case the HA setup uses unique cert in each node.

#### Why testing on Remove node flow?

Because of the following behavior of nodes getting replaced, the sync up is done in remove node flow so that the newly added nod will also have all config as well.
<strong>Before removing nodes. Automate nodes:</strong>

Service | IP Address | Status | Opensearch |  
-- | -- | -- | -- | --
automate | 10.0.192.105 | OK | green (Active: 100.0) |  
automate | 10.0.192.159 | OK | green (Active: 100.0) |  
automate | 10.0.192.222 | OK | green (Active: 100.0) | <- removing this node with 'node remove' command (index:2)
automate | 10.0.192.90 | OK | green (Active: 100.0) |  
automate | 10.0.192.164 | OK | green (Active: 100.0) | <- This is being replaced (remove and create resource) from index:4 to index:2

<strong>After remove node:</strong>

Service | IP Address | Status | Opensearch |  
-- | -- | -- | -- | --
automate | 10.0.192.105 | OK | green (Active: 100.0) |  
automate | 10.0.192.159 | OK | green (Active: 100.0) |  
automate | 10.0.192.212 | OK | green (Active: 100.0) | . <- newly added node does not have dex config (this is replacement of node in index:4 before removing node )
automate | 10.0.192.90 | OK | green (Active: 100.0) |  



### :athletic_shoe: How to Build and Test the Change

### :white_check_mark: Checklist

**All PRs** must tick these:

- [ ] I have read the [CONTRIBUTING document](https://github.com/chef/automate/blob/master/CONTRIBUTING.md).
- [ ] All commits signed-off for the [Developer Certification of Origin](https://github.com/chef/chef/blob/master/CONTRIBUTING.md#developer-certification-of-origin-dco).

With occasional exceptions, all PRs **from Progress employees** must tick these:

- [ ] Is the code clear? *(complicated code or lots of comments--subdivide and use well-named methods, meaningful variable names, etc.)*
- [ ] Consistency checked? *(user notifications, user prompts, visual patterns, code patterns, variable names)*
- [ ] Repeated code blocks eliminated? *(adapt and reuse existing components, blocks, functions, etc.)*
- [ ] Spelling, grammar, typos checked? *(at a minimum use `make spell` in any component directory)*
- [ ] Code well-formatted? *(indents, line breaks, etc. improve rather than hinder readability)*

All PRs **from Progress employees** should tick these if appropriate:

- [ ] Tests added/updated? (all new code needs new tests)
- [ ] Docs added/updated? (all customer-facing changes)

*Please add a note next to any checkbox above if you are NOT ticking it.*

### :camera: Screenshots, if applicable

**Demo Videos:**
Add node in AWS:
https://progresssoftware.sharepoint.com/:v:/s/ChefCoreC/ESX5RAGEcJxDiS8JjKc4HgQBjP9rHKRU-v_HSZ9voEG-sQ?e=Ejn8xR

Add node in On-prem Managed services:
https://progresssoftware.sharepoint.com/:v:/s/ChefCoreC/Ef7rnGtWzgtPk-WZlSSB2-kB88vaVmopRaynYB2f5kCfTw?e=WKsGbw


**Docs and screenshots:**
Config of  Newly Added node **without** this PR change: https://progresssoftware-my.sharepoint.com/:u:/g/personal/archand_progress_com/EagitM3p-NtPhWfHg-ZBLh8B8-OTYU35dzn5F8e_q5vfmg?e=qy9v45

Config of  Newly Added node **with** this PR change:  https://progresssoftware-my.sharepoint.com/:u:/g/personal/archand_progress_com/EYOaHHNXdHVBmcIsIVlvolcB3vvSIqvHpKtuOl_XN-3cvw?e=lmslsy

Service status after adding node and applying the new config
![image](https://github.com/chef/automate/assets/54614142/7f4dd509-df42-41e8-8be0-d7eb03e29c4c)

Test coverage: (Overall test coverage on Sonarqube for code written in this PR: 86%)
![image](https://github.com/chef/automate/assets/54614142/58ccd864-a55c-4ca2-aa0f-78126f6e77bb)




netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *chef-automate* processing.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 9fc0e992e29795abde8426dd5d5cb409a1ac4df9 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/chef-automate/deploys/647e168fa2813000073e72ba |
sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![C](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/C-16px.png 'C')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) Reliability Rating on New Code (is worse than A)  
[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 0.0% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

Fix issues before they fail your Quality Gate with [![SonarLint](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/sonarlint-16px.png 'SonarLint')](https://www.sonarqube.org/sonarlint/?referrer=pull-request) [SonarLint in your IDE](https://www.sonarqube.org/sonarlint/?referrer=pull-request).
sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![C](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/C-16px.png 'C')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) Reliability Rating on New Code (is worse than A)  
[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '0.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 0.0% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

Fix issues before they fail your Quality Gate with [![SonarLint](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/sonarlint-16px.png 'SonarLint')](https://www.sonarqube.org/sonarlint/?referrer=pull-request) [SonarLint in your IDE](https://www.sonarqube.org/sonarlint/?referrer=pull-request).
sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![C](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/C-16px.png 'C')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) Reliability Rating on New Code (is worse than A)  
[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![44.3%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/40-16px.png '44.3%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 44.3% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

Fix issues before they fail your Quality Gate with [![SonarLint](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/sonarlint-16px.png 'SonarLint')](https://www.sonarqube.org/sonarlint/?referrer=pull-request) [SonarLint in your IDE](https://www.sonarqube.org/sonarlint/?referrer=pull-request).
sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![2.6%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '2.6%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 2.6% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![33.5%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/25-16px.png '33.5%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 33.5% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![34.6%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/25-16px.png '34.6%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 34.6% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![59.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/50-16px.png '59.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 59.7% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![61.2%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '61.2%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 61.2% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![74.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '74.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 74.0% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![76.4%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '76.4%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 76.4% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.3%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.3%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.3% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![78.9%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '78.9%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 78.9% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![78.9%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '78.9%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 78.9% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![79.3%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '79.3%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 79.3% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL)

[![80.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '80.7%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list) [80.7% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL)

[![81.3%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '81.3%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list) [81.3% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL)

[![81.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '81.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list) [81.0% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![26.3%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/25-16px.png '26.3%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 26.3% Coverage on New Code (is less than 80%)  
[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![4.8%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/5-16px.png '4.8%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 4.79% Duplicated Lines (%) on New Code (is greater than 3%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![41.8%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/40-16px.png '41.8%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 41.8% Coverage on New Code (is less than 80%)  
[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![4.8%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/5-16px.png '4.8%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 4.79% Duplicated Lines (%) on New Code (is greater than 3%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![47.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/40-16px.png '47.0%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 47.0% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![48.2%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/40-16px.png '48.2%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 48.2% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL)

[![82.9%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '82.9%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list) [82.9% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL)

[![85.3%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '85.3%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list) [85.3% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL)

[![85.3%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '85.3%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list) [85.3% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [2 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL)

[![85.3%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '85.3%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list) [85.3% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list)


Sunanda-Boorla: Please check verify-private pipeline, applications-service is failing
sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL) [6 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&resolved=false&types=CODE_SMELL)

[![85.5%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/60-16px.png '85.5%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list) [85.5% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949&metric=new_duplicated_lines_density&view=list)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.8%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.8%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.8% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.8%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.8%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.8% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.7% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.7% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.7% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.7% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.7% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) [![22.7%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/0-16px.png '22.7%')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949) 22.7% Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=7949)



Patch:
diff --git a/components/automate-cli/cmd/chef-automate/automateConstants.go b/components/automate-cli/cmd/chef-automate/automateConstants.go
index aae7e8a86..3b293415c 100644
--- a/components/automate-cli/cmd/chef-automate/automateConstants.go
+++ b/components/automate-cli/cmd/chef-automate/automateConstants.go
@@ -11,11 +11,13 @@ const AUTOMATE_HA_WORKSPACE_DIR = "/hab/a2_deploy_workspace"
 const AUTOMATE_HA_WORKSPACE_A2HARB_FILE = "/hab/a2_deploy_workspace/a2ha.rb"
 const AUTOMATE_HA_WORKSPACE_CONFIG_FILE = "/hab/a2_deploy_workspace/config.toml"
 const AUTOMATE_HA_AUTOMATE_CONFIG_FILE = "/hab/a2_deploy_workspace/configs/automate.toml"
+const AUTOMATE_HA_AUTOMATE_NODE_CONFIG_DIR = "/hab/a2_deploy_workspace/node_configs/"
 const AUTOMATE_HA_INVALID_BASTION = "Invalid bastion, to run this command use automate bastion"
 const AIRGAP_HA_TRANS_DIR_PATH = "/hab/a2_deploy_workspace/terraform/transfer_files/"
 const AUTOMATE_HA_TERRAFORM_DIR = "/hab/a2_deploy_workspace/terraform/"
 const AUTOMATE_HA_FILE_PERMISSION_0755 = 0755
 const AUTOMATE_HA_FILE_PERMISSION_0644 = 0644
+const DATE_FORMAT = "%Y%m%d%H%M%S"
 
 const frontendAutotfvarsTemplate = `
 frontend_aib_dest_file = "/var/tmp/{{ .bundleName }}"
diff --git a/components/automate-cli/cmd/chef-automate/certRotate.go b/components/automate-cli/cmd/chef-automate/certRotate.go
index d8aedc14f..80193f02b 100644
--- a/components/automate-cli/cmd/chef-automate/certRotate.go
+++ b/components/automate-cli/cmd/chef-automate/certRotate.go
@@ -550,7 +550,7 @@ func (c *certRotateFlow) patchConfig(param *patchFnParameters) error {
 	// Defining set of commands which run on particular remoteservice nodes
 	var scriptCommands string
 	if param.remoteService == AUTOMATE || param.remoteService == CHEF_SERVER || param.remoteService == "frontend" {
-		scriptCommands = fmt.Sprintf(FRONTEND_COMMAND, PATCH, param.remoteService+param.timestamp, dateFormat)
+		scriptCommands = fmt.Sprintf(FRONTEND_COMMAND, PATCH, param.remoteService+param.timestamp, DATE_FORMAT)
 	} else if param.remoteService == POSTGRESQL || param.remoteService == OPENSEARCH {
 		scriptCommands = fmt.Sprintf(COPY_USER_CONFIG, param.remoteService+param.timestamp, param.remoteService)
 	}
diff --git a/components/automate-cli/cmd/chef-automate/cmdUtils.go b/components/automate-cli/cmd/chef-automate/cmdUtils.go
index f46c3293b..40c54afb4 100644
--- a/components/automate-cli/cmd/chef-automate/cmdUtils.go
+++ b/components/automate-cli/cmd/chef-automate/cmdUtils.go
@@ -18,6 +18,10 @@ type Cmd struct {
 	CmdInputs *CmdInputs
 }
 
+func NewCmd() *Cmd {
+	return &Cmd{CmdInputs: &CmdInputs{NodeType: false}}
+}
+
 type CmdInputs struct {
 	Cmd                      string
 	Args                     []string
@@ -43,6 +47,16 @@ type NodeTypeAndCmd struct {
 	Infra      *AutomateHAInfraDetails
 }
 
+func NewNodeTypeAndCmd() *NodeTypeAndCmd {
+	return &NodeTypeAndCmd{
+		Frontend:   NewCmd(),
+		Automate:   NewCmd(),
+		ChefServer: NewCmd(),
+		Opensearch: NewCmd(),
+		Postgresql: NewCmd(),
+	}
+}
+
 type CmdResult struct {
 	ScriptName  string
 	HostIP      string
@@ -131,6 +145,7 @@ func (c *remoteCmdExecutor) execute(nodeMap *NodeTypeAndCmd) (map[string][]*CmdR
 		if err != nil {
 			return cmdResult, err
 		}
+
 		output := c.executeCmdOnGivenNodes(nodeMap.Frontend.CmdInputs, nodeIps, remoteService, nodeMap.Frontend.CmdInputs.InputFilesPrefix, writer)
 		return output, nil
 	case nodeMap.Automate.CmdInputs.NodeType:
diff --git a/components/automate-cli/cmd/chef-automate/config.go b/components/automate-cli/cmd/chef-automate/config.go
index 84c308038..b92ba428f 100644
--- a/components/automate-cli/cmd/chef-automate/config.go
+++ b/components/automate-cli/cmd/chef-automate/config.go
@@ -40,7 +40,6 @@ var configCmdFlags = struct {
 }{}
 
 const (
-	dateFormat       = "%Y%m%d%H%M%S"
 	postgresql       = "postgresql"
 	opensearch_const = "opensearch"
 	PRODUCT_WARNING  = `Ignored 'products' from [deployment.v1.svc]`
@@ -360,7 +359,7 @@ func runPatchCommand(cmd *cobra.Command, args []string) error {
 		configFile := args[0]
 		configFileName := stringutils.GetFileName(configFile)
 		frontendPrefix := "frontend" + "_" + timestamp + "_"
-		frontendCmd := fmt.Sprintf(FRONTEND_COMMAND, PATCH, frontendPrefix+configFileName, dateFormat)
+		frontendCmd := fmt.Sprintf(FRONTEND_COMMAND, PATCH, frontendPrefix+configFileName, DATE_FORMAT)
 		frontend := &Cmd{
 			PreExec: prePatchCheckForFrontendNodes,
 			CmdInputs: &CmdInputs{
@@ -375,7 +374,7 @@ func runPatchCommand(cmd *cobra.Command, args []string) error {
 			},
 		}
 		automatePrefix := "automate" + "_" + timestamp + "_"
-		automateCmd := fmt.Sprintf(FRONTEND_COMMAND, PATCH, automatePrefix+configFileName, dateFormat)
+		automateCmd := fmt.Sprintf(FRONTEND_COMMAND, PATCH, automatePrefix+configFileName, DATE_FORMAT)
 		automate := &Cmd{
 			PreExec: prePatchCheckForFrontendNodes,
 			CmdInputs: &CmdInputs{
@@ -390,7 +389,7 @@ func runPatchCommand(cmd *cobra.Command, args []string) error {
 			},
 		}
 		chefserverPrefix := "chef_server" + "_" + timestamp + "_"
-		chefServerCmd := fmt.Sprintf(FRONTEND_COMMAND, PATCH, chefserverPrefix+configFileName, dateFormat)
+		chefServerCmd := fmt.Sprintf(FRONTEND_COMMAND, PATCH, chefserverPrefix+configFileName, DATE_FORMAT)
 		chefServer := &Cmd{
 			PreExec: prePatchCheckForFrontendNodes,
 			CmdInputs: &CmdInputs{
@@ -405,7 +404,7 @@ func runPatchCommand(cmd *cobra.Command, args []string) error {
 			},
 		}
 		postgresqlPrefix := "postgresql" + "_" + timestamp + "_"
-		postgresqlCmd := fmt.Sprintf(BACKEND_COMMAND, dateFormat, "postgresql", "%s", postgresqlPrefix+configFileName)
+		postgresqlCmd := fmt.Sprintf(BACKEND_COMMAND, DATE_FORMAT, "postgresql", "%s", postgresqlPrefix+configFileName)
 		postgresql := &Cmd{
 			PreExec: prePatchCheckForPostgresqlNodes,
 			CmdInputs: &CmdInputs{
@@ -420,7 +419,7 @@ func runPatchCommand(cmd *cobra.Command, args []string) error {
 			},
 		}
 		opensearchPrefix := "opensearch" + "_" + timestamp + "_"
-		opensearchCmd := fmt.Sprintf(BACKEND_COMMAND, dateFormat, "opensearch", "%s", opensearchPrefix+configFileName)
+		opensearchCmd := fmt.Sprintf(BACKEND_COMMAND, DATE_FORMAT, "opensearch", "%s", opensearchPrefix+configFileName)
 		opensearch := &Cmd{
 			PreExec: prePatchCheckForOpensearch,
 			CmdInputs: &CmdInputs{
@@ -650,7 +649,7 @@ type ResultConfigSet struct {
 func setConfigForFrontEndNodes(args []string, sshUtil SSHUtil, frontendIps []string, remoteService string, timestamp string, cliWriter *cli.Writer) error {
 	resultChan := make(chan ResultConfigSet, len(frontendIps))
 	configFile := remoteService + timestamp
-	scriptCommands := fmt.Sprintf(FRONTEND_COMMAND, SET, configFile, dateFormat)
+	scriptCommands := fmt.Sprintf(FRONTEND_COMMAND, SET, configFile, DATE_FORMAT)
 	originalSSHConfig := sshUtil.getSSHConfig()
 
 	for _, hostIP := range frontendIps {
@@ -787,7 +786,7 @@ func setConfigForOpensearch(args []string, remoteService string, sshUtil SSHUtil
 
 // setConfigForPostgresqlAndOpensearch set the configuration for postgresql and opensearch nodes in Automate HA
 func setConfigForPostgresqlAndOpensearch(remoteService string, timestamp string, sshUtil SSHUtil, hostIP string, tomlFilePath string, writer *cli.Writer) error {
-	scriptCommands := fmt.Sprintf(BACKEND_COMMAND, dateFormat, remoteService, "%s", remoteService+timestamp)
+	scriptCommands := fmt.Sprintf(BACKEND_COMMAND, DATE_FORMAT, remoteService, "%s", remoteService+timestamp)
 
 	sshUtil.getSSHConfig().hostIP = hostIP
 	printConnectionMessage(remoteService, sshUtil.getSSHConfig().hostIP, writer)
diff --git a/components/automate-cli/cmd/chef-automate/constants.go b/components/automate-cli/cmd/chef-automate/constants.go
index 36d95f2db..51c9b547c 100644
--- a/components/automate-cli/cmd/chef-automate/constants.go
+++ b/components/automate-cli/cmd/chef-automate/constants.go
@@ -25,4 +25,8 @@ const (
 	CHEF_SERVER_NAME    = "Chef Server"
 	OPENSEARCH_NAME     = "Opensearch"
 	POSTGRESQL_NAME     = "Postgresql"
+	AUTOMATE_TOML       = "automate.config.toml"
+	CHEF_SERVER_TOML    = "chef_server.config.toml"
+	POSTGRESQL_TOML     = "postgresql.config.toml"
+	OPENSEARCH_TOML     = "opensearch.config.toml"
 )
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_add_aws.go b/components/automate-cli/cmd/chef-automate/ha_node_add_aws.go
index b7ed44159..54de65368 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_add_aws.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_add_aws.go
@@ -47,10 +47,17 @@ func (ani *AddNodeAWSImpl) Execute(c *cobra.Command, args []string) error {
 	if err != nil {
 		return err
 	}
+
 	err = ani.modifyConfig()
 	if err != nil {
 		return err
 	}
+
+	err = ani.nodeUtils.saveConfigToBastion()
+	if err != nil {
+		return err
+	}
+
 	if !ani.flags.autoAccept {
 		res, err := ani.promptUserConfirmation()
 		if err != nil {
@@ -149,5 +156,13 @@ func (ani *AddNodeAWSImpl) runDeploy() error {
 	if err != nil {
 		return err
 	}
-	return ani.nodeUtils.executeAutomateClusterCtlCommandAsync("deploy", argsdeploy, upgradeHaHelpDoc)
+	err = ani.nodeUtils.executeAutomateClusterCtlCommandAsync("deploy", argsdeploy, upgradeHaHelpDoc)
+	syncErr := ani.nodeUtils.syncConfigToAllNodes()
+	if syncErr != nil {
+		if err != nil {
+			return errors.Wrap(err, syncErr.Error())
+		}
+		return syncErr
+	}
+	return err
 }
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_add_onprem.go b/components/automate-cli/cmd/chef-automate/ha_node_add_onprem.go
index 49e87314e..3fc8f518d 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_add_onprem.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_add_onprem.go
@@ -6,7 +6,7 @@ import (
 	"path/filepath"
 	"strings"
 
-	"errors"
+	"github.com/pkg/errors"
 
 	"github.com/chef/automate/components/automate-cli/pkg/status"
 	cli "github.com/chef/automate/components/automate-deployment/pkg/cli"
@@ -83,6 +83,12 @@ func (ani *AddNodeOnPremImpl) Execute(c *cobra.Command, args []string) error {
 	if err != nil {
 		return err
 	}
+
+	err = ani.nodeUtils.saveConfigToBastion()
+	if err != nil {
+		return err
+	}
+
 	if !ani.flags.autoAccept {
 		res, err := ani.promptUserConfirmation()
 		if err != nil {
@@ -196,7 +202,15 @@ func (ani *AddNodeOnPremImpl) runDeploy() error {
 		return err
 	}
 	argsdeploy := []string{"-y"}
-	return ani.nodeUtils.executeAutomateClusterCtlCommandAsync("deploy", argsdeploy, upgradeHaHelpDoc)
+	err = ani.nodeUtils.executeAutomateClusterCtlCommandAsync("deploy", argsdeploy, upgradeHaHelpDoc)
+	syncErr := ani.nodeUtils.syncConfigToAllNodes()
+	if syncErr != nil {
+		if err != nil {
+			return errors.Wrap(err, syncErr.Error())
+		}
+		return syncErr
+	}
+	return err
 }
 
 func (ani *AddNodeOnPremImpl) validateCmdArgs() *list.List {
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_delete_aws.go b/components/automate-cli/cmd/chef-automate/ha_node_delete_aws.go
index a4e62eb60..5dc04d253 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_delete_aws.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_delete_aws.go
@@ -80,6 +80,14 @@ func (dna *DeleteNodeAWSImpl) Execute(c *cobra.Command, args []string) error {
 	if err != nil {
 		return err
 	}
+
+	// TODO : Remove this after fixing the following ticket
+	// https://chefio.atlassian.net/browse/CHEF-3630
+	err = dna.nodeUtils.saveConfigToBastion()
+	if err != nil {
+		return err
+	}
+
 	if !dna.flags.autoAccept {
 		res, err := dna.promptUserConfirmation()
 		if err != nil {
@@ -215,7 +223,17 @@ func (dna *DeleteNodeAWSImpl) runDeploy() error {
 		return err
 	}
 
-	return dna.nodeUtils.executeAutomateClusterCtlCommandAsync("deploy", argsdeploy, upgradeHaHelpDoc)
+	err = dna.nodeUtils.executeAutomateClusterCtlCommandAsync("deploy", argsdeploy, upgradeHaHelpDoc)
+	// TODO : Remove this after fixing the following ticket
+	// https://chefio.atlassian.net/browse/CHEF-3630
+	syncErr := dna.nodeUtils.syncConfigToAllNodes()
+	if syncErr != nil {
+		if err != nil {
+			return errors.Wrap(err, syncErr.Error())
+		}
+		return syncErr
+	}
+	return err
 }
 
 func (dna *DeleteNodeAWSImpl) runRemoveNodeFromAws() error {
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_delete_onprem.go b/components/automate-cli/cmd/chef-automate/ha_node_delete_onprem.go
index 50edc7878..422fccb62 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_delete_onprem.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_delete_onprem.go
@@ -76,6 +76,13 @@ func (dni *DeleteNodeOnPremImpl) Execute(c *cobra.Command, args []string) error
 		}
 	}
 
+	// TODO : Remove this after fixing the following ticket
+	// https://chefio.atlassian.net/browse/CHEF-3630
+	err = dni.nodeUtils.saveConfigToBastion()
+	if err != nil {
+		return err
+	}
+
 	previousCount, err := dni.nodeUtils.calculateTotalInstanceCount()
 	if err != nil {
 		return err
@@ -239,7 +246,18 @@ func (dni *DeleteNodeOnPremImpl) runDeploy() error {
 		return err
 	}
 	argsdeploy := []string{"-y"}
-	return dni.nodeUtils.executeAutomateClusterCtlCommandAsync("deploy", argsdeploy, upgradeHaHelpDoc)
+	err = dni.nodeUtils.executeAutomateClusterCtlCommandAsync("deploy", argsdeploy, upgradeHaHelpDoc)
+
+	// TODO : Remove this after fixing the following ticket
+	// https://chefio.atlassian.net/browse/CHEF-3630
+	syncErr := dni.nodeUtils.syncConfigToAllNodes()
+	if syncErr != nil {
+		if err != nil {
+			return errors.Wrap(err, syncErr.Error())
+		}
+		return syncErr
+	}
+	return err
 }
 
 func (dni *DeleteNodeOnPremImpl) validateCmdArgs() *list.List {
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_operations_utils.go b/components/automate-cli/cmd/chef-automate/ha_node_operations_utils.go
index 08829604e..c5f368bd4 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_operations_utils.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_operations_utils.go
@@ -8,12 +8,15 @@ import (
 	"regexp"
 	"strconv"
 	"strings"
+	"time"
 
+	dc "github.com/chef/automate/api/config/deployment"
 	"github.com/chef/automate/components/automate-cli/pkg/status"
 	"github.com/chef/automate/components/automate-deployment/pkg/cli"
 	"github.com/chef/automate/lib/io/fileutils"
 	"github.com/chef/automate/lib/platform/command"
 	"github.com/chef/automate/lib/stringutils"
+	"github.com/chef/toml"
 	ptoml "github.com/pelletier/go-toml"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
@@ -40,100 +43,6 @@ type HAModifyAndDeploy interface {
 	runDeploy() error
 }
 
-type MockNodeUtilsImpl struct {
-	executeAutomateClusterCtlCommandAsyncfunc func(command string, args []string, helpDocs string) error
-	getHaInfraDetailsfunc                     func() (*AutomateHAInfraDetails, *SSHConfig, error)
-	writeHAConfigFilesFunc                    func(templateName string, data interface{}) error
-	taintTerraformFunc                        func(path string) error
-	isA2HARBFileExistFunc                     func() bool
-	getModeFromConfigFunc                     func(path string) (string, error)
-	checkIfFileExistFunc                      func(path string) bool
-	pullAndUpdateConfigFunc                   func(sshUtil *SSHUtil, exceptionIps []string) (*ExistingInfraConfigToml, error)
-	pullAndUpdateConfigAwsFunc                func(sshUtil *SSHUtil, exceptionIps []string) (*AwsConfigToml, error)
-	isManagedServicesOnFunc                   func() bool
-	getConfigPullerFunc                       func(sshUtil *SSHUtil) (PullConfigs, error)
-	getInfraConfigFunc                        func(sshUtil *SSHUtil) (*ExistingInfraConfigToml, error)
-	getAWSConfigFunc                          func(sshUtil *SSHUtil) (*AwsConfigToml, error)
-	getModeOfDeploymentFunc                   func() string
-	executeShellCommandFunc                   func() error
-	moveAWSAutoTfvarsFileFunc                 func(path string) error
-	modifyTfArchFileFunc                      func(path string) error
-	getAWSConfigIpFunc                        func() (*AWSConfigIp, error)
-	stopServicesOnNodeFunc                    func(ip, nodeType, deploymentType string, infra *AutomateHAInfraDetails) error
-	excludeOpenSearchNodeFunc                 func(ipToDelete string, infra *AutomateHAInfraDetails) error
-	checkExistingExcludedOSNodesFunc          func(automateIp string, infra *AutomateHAInfraDetails) (string, error)
-	calculateTotalInstanceCountFunc           func() (int, error)
-}
-
-func (mnu *MockNodeUtilsImpl) executeAutomateClusterCtlCommandAsync(command string, args []string, helpDocs string) error {
-	return mnu.executeAutomateClusterCtlCommandAsyncfunc(command, args, helpDocs)
-}
-func (mnu *MockNodeUtilsImpl) getAWSConfigIp() (*AWSConfigIp, error) {
-	return mnu.getAWSConfigIpFunc()
-}
-func (mnu *MockNodeUtilsImpl) getHaInfraDetails() (*AutomateHAInfraDetails, *SSHConfig, error) {
-	return mnu.getHaInfraDetailsfunc()
-}
-func (mnu *MockNodeUtilsImpl) writeHAConfigFiles(templateName string, data interface{}) error {
-	return mnu.writeHAConfigFilesFunc(templateName, data)
-}
-func (mnu *MockNodeUtilsImpl) taintTerraform(path string) error {
-	return mnu.taintTerraformFunc(path)
-}
-
-func (mnu *MockNodeUtilsImpl) isA2HARBFileExist() bool {
-	return mnu.isA2HARBFileExistFunc()
-}
-func (mnu *MockNodeUtilsImpl) getModeFromConfig(path string) (string, error) {
-	return mnu.getModeFromConfigFunc(path)
-}
-func (mnu *MockNodeUtilsImpl) checkIfFileExist(path string) bool {
-	return mnu.checkIfFileExistFunc(path)
-}
-func (mnu *MockNodeUtilsImpl) pullAndUpdateConfig(sshUtil *SSHUtil, exceptionIps []string) (*ExistingInfraConfigToml, error) {
-	return mnu.pullAndUpdateConfigFunc(sshUtil, exceptionIps)
-}
-func (mnu *MockNodeUtilsImpl) isManagedServicesOn() bool {
-	return mnu.isManagedServicesOnFunc()
-}
-func (mnu *MockNodeUtilsImpl) getConfigPuller(sshUtil *SSHUtil) (PullConfigs, error) {
-	return mnu.getConfigPullerFunc(sshUtil)
-}
-func (mnu *MockNodeUtilsImpl) getInfraConfig(sshUtil *SSHUtil) (*ExistingInfraConfigToml, error) {
-	return mnu.getInfraConfigFunc(sshUtil)
-}
-func (mnu *MockNodeUtilsImpl) getAWSConfig(sshUtil *SSHUtil) (*AwsConfigToml, error) {
-	return mnu.getAWSConfigFunc(sshUtil)
-}
-func (mnu *MockNodeUtilsImpl) getModeOfDeployment() string {
-	return mnu.getModeOfDeploymentFunc()
-}
-func (mnu *MockNodeUtilsImpl) executeShellCommand(command, path string) error {
-	return mnu.executeShellCommandFunc()
-}
-
-func (mnu *MockNodeUtilsImpl) moveAWSAutoTfvarsFile(path string) error {
-	return mnu.moveAWSAutoTfvarsFileFunc(path)
-}
-func (mnu *MockNodeUtilsImpl) modifyTfArchFile(path string) error {
-	return mnu.modifyTfArchFileFunc(path)
-}
-func (mnu *MockNodeUtilsImpl) pullAndUpdateConfigAws(sshUtil *SSHUtil, exceptionIps []string) (*AwsConfigToml, error) {
-	return mnu.pullAndUpdateConfigAwsFunc(sshUtil, exceptionIps)
-}
-func (mnu *MockNodeUtilsImpl) stopServicesOnNode(ip, nodeType, deploymentType string, infra *AutomateHAInfraDetails) error {
-	return mnu.stopServicesOnNodeFunc(ip, nodeType, deploymentType, infra)
-}
-func (mnu *MockNodeUtilsImpl) excludeOpenSearchNode(ipToDelete string, infra *AutomateHAInfraDetails) error {
-	return mnu.excludeOpenSearchNodeFunc(ipToDelete, infra)
-}
-func (mnu *MockNodeUtilsImpl) checkExistingExcludedOSNodes(automateIp string, infra *AutomateHAInfraDetails) (string, error) {
-	return mnu.checkExistingExcludedOSNodesFunc(automateIp, infra)
-}
-func (mnu *MockNodeUtilsImpl) calculateTotalInstanceCount() (int, error) {
-	return mnu.calculateTotalInstanceCountFunc()
-}
-
 type NodeOpUtils interface {
 	executeAutomateClusterCtlCommandAsync(command string, args []string, helpDocs string) error
 	getHaInfraDetails() (*AutomateHAInfraDetails, *SSHConfig, error)
@@ -157,6 +66,10 @@ type NodeOpUtils interface {
 	excludeOpenSearchNode(ipToDelete string, infra *AutomateHAInfraDetails) error
 	checkExistingExcludedOSNodes(automateIp string, infra *AutomateHAInfraDetails) (string, error)
 	calculateTotalInstanceCount() (int, error)
+	parseAndMoveConfigFileToWorkspaceDir(outFiles []string, outputDirectory string) error
+	executeCustomCmdOnEachNodeType(outputFiles []string, inputFiles []string, inputFilesPrefix string, service string, cmdString string, singleNode bool) error
+	saveConfigToBastion() error
+	syncConfigToAllNodes() error
 }
 
 type NodeUtilsImpl struct {
@@ -334,6 +247,54 @@ func (nu *NodeUtilsImpl) getHaInfraDetails() (*AutomateHAInfraDetails, *SSHConfi
 	return infra, sshconfig, nil
 }
 
+func (nu *NodeUtilsImpl) saveConfigToBastion() error {
+	nodeObjects := getNodeObjectsToFetchConfigFromAllNodeTypes()
+	return executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, true, AUTOMATE_HA_AUTOMATE_NODE_CONFIG_DIR, nu)
+}
+
+func (nu *NodeUtilsImpl) syncConfigToAllNodes() error {
+	nodeObjects := getNodeObjectsToPatchWorkspaceConfigToAllNodes()
+	return executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, false, "", nu)
+}
+
+// Execute custom command in one node of all the each node-type
+func executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects []*NodeObject, singleNode bool, outputDirectory string, nu NodeOpUtils) error {
+	for _, nodeObject := range nodeObjects {
+		outFiles := nodeObject.OutputFile
+		err := nu.executeCustomCmdOnEachNodeType(outFiles, nodeObject.InputFile, nodeObject.InputFilePrefix, nodeObject.NodeType, nodeObject.CmdString, singleNode)
+		if err != nil {
+			return err
+		}
+		if len(outFiles) > 0 {
+			if err = nu.parseAndMoveConfigFileToWorkspaceDir(outFiles, outputDirectory); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// Execute 'config show' command in specific service and fetch the output file to bastion
+func (nu *NodeUtilsImpl) executeCustomCmdOnEachNodeType(outputFiles []string, inputFiles []string, inputFilesPrefix string, service string, cmdString string, singleNode bool) error {
+
+	infra, _, err := nu.getHaInfraDetails()
+	if err != nil {
+		return err
+	}
+	nodeMap := createNodeMap(outputFiles, inputFiles, inputFilesPrefix, service, cmdString, singleNode, infra)
+
+	sshUtil := nu.cmdUtil.GetSshUtil()
+
+	sshUtil.setSSHConfig(&SSHConfig{
+		sshUser:    infra.Outputs.SSHUser.Value,
+		sshPort:    infra.Outputs.SSHPort.Value,
+		sshKeyFile: infra.Outputs.SSHKeyFile.Value,
+	})
+
+	_, err = nu.cmdUtil.ExecuteWithNodeMap(nodeMap)
+	return err
+}
+
 func (nu *NodeUtilsImpl) isManagedServicesOn() bool {
 	return isManagedServicesOn()
 }
@@ -703,3 +664,162 @@ func readConfigAWS(path string) (AwsConfigToml, error) {
 	}
 	return config, nil
 }
+
+type NodeObject struct {
+	CmdString       string
+	OutputFile      []string
+	InputFile       []string
+	InputFilePrefix string
+	NodeType        string
+}
+
+func NewNodeObjectWithOutputFile(cmdString string, outFile []string, inputFile []string, inputFilePrefix string, nodeType string) *NodeObject {
+	return &NodeObject{cmdString, outFile, inputFile, inputFilePrefix, nodeType}
+}
+
+func (nu *NodeUtilsImpl) parseAndMoveConfigFileToWorkspaceDir(outFiles []string, outputDirectory string) error {
+
+	err := removeOutputHeaderInConfigFile(outFiles[0])
+	if err != nil {
+		return errors.Wrap(err, "error on removing output header in fetched config")
+	}
+	if err = fileutils.Move(outFiles[0], outputDirectory+outFiles[0]); err != nil {
+		return err
+	}
+	return nil
+}
+
+func removeOutputHeaderInConfigFile(filePath string) error {
+	return fileutils.RemoveFirstLine(filePath)
+}
+
+func getNodeObjectsToFetchConfigFromAllNodeTypes() []*NodeObject {
+	nodeObjects := []*NodeObject{
+		NewNodeObjectWithOutputFile(fmt.Sprintf(GET_FRONTEND_CONFIG, AUTOMATE_TOML), []string{AUTOMATE_TOML}, nil, "", AUTOMATE),
+		NewNodeObjectWithOutputFile(fmt.Sprintf(GET_FRONTEND_CONFIG, CHEF_SERVER_TOML), []string{CHEF_SERVER_TOML}, nil, "", CHEF_SERVER),
+	}
+	if !isManagedServicesOn() {
+		backendNodeObjects := []*NodeObject{
+			NewNodeObjectWithOutputFile(fmt.Sprintf(GET_BACKEND_CONFIG, POSTGRESQL, " > "+POSTGRESQL_TOML), []string{POSTGRESQL_TOML}, nil, "", POSTGRESQL),
+			NewNodeObjectWithOutputFile(fmt.Sprintf(GET_BACKEND_CONFIG, OPENSEARCH, " > "+OPENSEARCH_TOML), []string{OPENSEARCH_TOML}, nil, "", OPENSEARCH),
+		}
+		nodeObjects = append(nodeObjects, backendNodeObjects...)
+	}
+	return nodeObjects
+}
+
+func getNodeObjectsToPatchWorkspaceConfigToAllNodes() []*NodeObject {
+	timestamp := time.Now().Format("20060102150405")
+	fmt.Println("====================================================================")
+	fmt.Println("sync Config to all frontend nodes")
+	frontendPrefix := "frontend" + "_" + timestamp + "_"
+	frontend := fmt.Sprintf(FRONTEND_COMMAND, PATCH, frontendPrefix+AUTOMATE_TOML, DATE_FORMAT)
+	chefserver := fmt.Sprintf(FRONTEND_COMMAND, PATCH, frontendPrefix+CHEF_SERVER_TOML, DATE_FORMAT)
+	nodeObjects := []*NodeObject{
+		NewNodeObjectWithOutputFile(frontend, nil, []string{AUTOMATE_HA_AUTOMATE_NODE_CONFIG_DIR + AUTOMATE_TOML}, frontendPrefix, AUTOMATE),
+		NewNodeObjectWithOutputFile(chefserver, nil, []string{AUTOMATE_HA_AUTOMATE_NODE_CONFIG_DIR + CHEF_SERVER_TOML}, frontendPrefix, CHEF_SERVER),
+	}
+	return nodeObjects
+}
+
+func createNodeMap(outputFiles []string, inputFiles []string, inputFilesPrefix string, service string, cmdString string, singleNode bool, infra *AutomateHAInfraDetails) *NodeTypeAndCmd {
+
+	nodeMap := NewNodeTypeAndCmd()
+	cmd := newNodeTypeCmd(nodeMap, cmdString, outputFiles, singleNode)
+	if service == POSTGRESQL {
+		cmd.CmdInputs.Args = inputFiles
+	} else if service == OPENSEARCH {
+		cmd.CmdInputs.Args = inputFiles
+	} else {
+		cmd.CmdInputs.Args = inputFiles
+		// Patch only incase of frontends node
+		if len(inputFiles) > 0 {
+			cmd.PreExec = prePatchForFrontendNodes
+			cmd.CmdInputs.InputFilesPrefix = inputFilesPrefix
+			cmd.CmdInputs.WaitTimeout = 300
+		}
+	}
+	switch service {
+	case AUTOMATE:
+		nodeMap.Automate = cmd
+	case CHEF_SERVER:
+		nodeMap.ChefServer = cmd
+	case POSTGRESQL:
+		nodeMap.Postgresql = cmd
+	case OPENSEARCH:
+		nodeMap.Opensearch = cmd
+	}
+
+	nodeMap.Infra = infra
+
+	return nodeMap
+}
+
+// Create *Cmd struct instance with 'cmdString' and 'outputFiles' params
+func newNodeTypeCmd(nodeMap *NodeTypeAndCmd, cmdString string, outputFiles []string, singleNode bool) *Cmd {
+	return &Cmd{
+		CmdInputs: &CmdInputs{
+			Cmd:                      cmdString,
+			Single:                   singleNode,
+			InputFiles:               []string{},
+			Outputfiles:              outputFiles,
+			NodeType:                 true,
+			HideSSHConnectionMessage: true,
+		},
+	}
+}
+
+// prePatchForFrontendNodes parse frontend config before patch and remove cert related keys-values
+func prePatchForFrontendNodes(inputs *CmdInputs, sshUtil SSHUtil, infra *AutomateHAInfraDetails, remoteService string, writer *cli.Writer) error {
+	srcPath, err := removeRestrictedKeysFromSrcFile(inputs.Args[0])
+	if err != nil {
+		return err
+	}
+
+	inputs.InputFiles = []string{srcPath}
+
+	return nil
+}
+
+// Remove TLS values used for frontend LB and product key in frontend nodes
+func removeRestrictedKeysFromSrcFile(srcString string) (string, error) {
+
+	tomlbyt, _ := fileutils.ReadFile(srcString) // nosemgrep
+	destString := string(tomlbyt)
+	var dest dc.AutomateConfig
+	if _, err := toml.Decode(destString, &dest); err != nil {
+		return "", err
+	}
+
+	// Ignoring cert values for "global.v1.frontend_tls"
+	if dest.Global != nil &&
+		dest.Global.V1 != nil &&
+		len(dest.Global.V1.FrontendTls) != 0 {
+		dest.Global.V1.FrontendTls = nil
+	}
+
+	// Ignoring cert values for "load_balancer.v1.sys.frontend_tls"
+	if dest.LoadBalancer != nil &&
+		dest.LoadBalancer.V1 != nil &&
+		dest.LoadBalancer.V1.Sys != nil &&
+		len(dest.LoadBalancer.V1.Sys.FrontendTls) != 0 {
+		dest.LoadBalancer.V1.Sys.FrontendTls = nil
+	}
+
+	// Ignoring product key
+	if dest.Deployment == nil ||
+		dest.Deployment.V1 == nil ||
+		dest.Deployment.V1.Svc == nil ||
+		dest.Deployment.V1.Svc.Products == nil {
+		return srcString, nil
+	} else {
+		// Following are the unsupported or restricted key to patch via bastion
+		dest.Deployment.V1.Svc.Products = nil
+
+		srcString, err := fileutils.CreateTomlFileFromConfig(dest, srcString)
+		if err != nil {
+			return "", err
+		}
+		return srcString, nil
+	}
+}
diff --git a/components/automate-cli/cmd/chef-automate/mock_ha_node_operations_utils.go b/components/automate-cli/cmd/chef-automate/mock_ha_node_operations_utils.go
new file mode 100644
index 000000000..019331156
--- /dev/null
+++ b/components/automate-cli/cmd/chef-automate/mock_ha_node_operations_utils.go
@@ -0,0 +1,120 @@
+package main
+
+type MockNodeUtilsImpl struct {
+	executeAutomateClusterCtlCommandAsyncfunc    func(command string, args []string, helpDocs string) error
+	getHaInfraDetailsfunc                        func() (*AutomateHAInfraDetails, *SSHConfig, error)
+	writeHAConfigFilesFunc                       func(templateName string, data interface{}) error
+	taintTerraformFunc                           func(path string) error
+	isA2HARBFileExistFunc                        func() bool
+	getModeFromConfigFunc                        func(path string) (string, error)
+	checkIfFileExistFunc                         func(path string) bool
+	pullAndUpdateConfigFunc                      func(sshUtil *SSHUtil, exceptionIps []string) (*ExistingInfraConfigToml, error)
+	pullAndUpdateConfigAwsFunc                   func(sshUtil *SSHUtil, exceptionIps []string) (*AwsConfigToml, error)
+	isManagedServicesOnFunc                      func() bool
+	getConfigPullerFunc                          func(sshUtil *SSHUtil) (PullConfigs, error)
+	getInfraConfigFunc                           func(sshUtil *SSHUtil) (*ExistingInfraConfigToml, error)
+	getAWSConfigFunc                             func(sshUtil *SSHUtil) (*AwsConfigToml, error)
+	getModeOfDeploymentFunc                      func() string
+	executeShellCommandFunc                      func() error
+	moveAWSAutoTfvarsFileFunc                    func(path string) error
+	modifyTfArchFileFunc                         func(path string) error
+	getAWSConfigIpFunc                           func() (*AWSConfigIp, error)
+	stopServicesOnNodeFunc                       func(ip, nodeType, deploymentType string, infra *AutomateHAInfraDetails) error
+	excludeOpenSearchNodeFunc                    func(ipToDelete string, infra *AutomateHAInfraDetails) error
+	checkExistingExcludedOSNodesFunc             func(automateIp string, infra *AutomateHAInfraDetails) (string, error)
+	calculateTotalInstanceCountFunc              func() (int, error)
+	parseAndMoveConfigFileToWorkspaceDirFunc     func(outputFiles []string, outputDirectory string) error
+	executeCmdInAllNodeTypesAndCaptureOutputFunc func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error
+	executeCustomCmdOnEachNodeTypeFunc           func(outputFiles []string, inputFiles []string, inputFilesPrefix string, service string, cmdString string, singleNode bool) error
+	saveConfigToBastionFunc                      func() error
+	syncConfigToAllNodesFunc                     func() error
+}
+
+func (mnu *MockNodeUtilsImpl) executeAutomateClusterCtlCommandAsync(command string, args []string, helpDocs string) error {
+	return mnu.executeAutomateClusterCtlCommandAsyncfunc(command, args, helpDocs)
+}
+func (mnu *MockNodeUtilsImpl) getAWSConfigIp() (*AWSConfigIp, error) {
+	return mnu.getAWSConfigIpFunc()
+}
+func (mnu *MockNodeUtilsImpl) getHaInfraDetails() (*AutomateHAInfraDetails, *SSHConfig, error) {
+	return mnu.getHaInfraDetailsfunc()
+}
+func (mnu *MockNodeUtilsImpl) writeHAConfigFiles(templateName string, data interface{}) error {
+	return mnu.writeHAConfigFilesFunc(templateName, data)
+}
+func (mnu *MockNodeUtilsImpl) taintTerraform(path string) error {
+	return mnu.taintTerraformFunc(path)
+}
+
+func (mnu *MockNodeUtilsImpl) isA2HARBFileExist() bool {
+	return mnu.isA2HARBFileExistFunc()
+}
+func (mnu *MockNodeUtilsImpl) getModeFromConfig(path string) (string, error) {
+	return mnu.getModeFromConfigFunc(path)
+}
+func (mnu *MockNodeUtilsImpl) checkIfFileExist(path string) bool {
+	return mnu.checkIfFileExistFunc(path)
+}
+func (mnu *MockNodeUtilsImpl) pullAndUpdateConfig(sshUtil *SSHUtil, exceptionIps []string) (*ExistingInfraConfigToml, error) {
+	return mnu.pullAndUpdateConfigFunc(sshUtil, exceptionIps)
+}
+func (mnu *MockNodeUtilsImpl) isManagedServicesOn() bool {
+	return mnu.isManagedServicesOnFunc()
+}
+func (mnu *MockNodeUtilsImpl) getConfigPuller(sshUtil *SSHUtil) (PullConfigs, error) {
+	return mnu.getConfigPullerFunc(sshUtil)
+}
+func (mnu *MockNodeUtilsImpl) getInfraConfig(sshUtil *SSHUtil) (*ExistingInfraConfigToml, error) {
+	return mnu.getInfraConfigFunc(sshUtil)
+}
+func (mnu *MockNodeUtilsImpl) getAWSConfig(sshUtil *SSHUtil) (*AwsConfigToml, error) {
+	return mnu.getAWSConfigFunc(sshUtil)
+}
+func (mnu *MockNodeUtilsImpl) getModeOfDeployment() string {
+	return mnu.getModeOfDeploymentFunc()
+}
+func (mnu *MockNodeUtilsImpl) executeShellCommand(command, path string) error {
+	return mnu.executeShellCommandFunc()
+}
+
+func (mnu *MockNodeUtilsImpl) moveAWSAutoTfvarsFile(path string) error {
+	return mnu.moveAWSAutoTfvarsFileFunc(path)
+}
+func (mnu *MockNodeUtilsImpl) modifyTfArchFile(path string) error {
+	return mnu.modifyTfArchFileFunc(path)
+}
+func (mnu *MockNodeUtilsImpl) pullAndUpdateConfigAws(sshUtil *SSHUtil, exceptionIps []string) (*AwsConfigToml, error) {
+	return mnu.pullAndUpdateConfigAwsFunc(sshUtil, exceptionIps)
+}
+func (mnu *MockNodeUtilsImpl) stopServicesOnNode(ip, nodeType, deploymentType string, infra *AutomateHAInfraDetails) error {
+	return mnu.stopServicesOnNodeFunc(ip, nodeType, deploymentType, infra)
+}
+func (mnu *MockNodeUtilsImpl) excludeOpenSearchNode(ipToDelete string, infra *AutomateHAInfraDetails) error {
+	return mnu.excludeOpenSearchNodeFunc(ipToDelete, infra)
+}
+func (mnu *MockNodeUtilsImpl) checkExistingExcludedOSNodes(automateIp string, infra *AutomateHAInfraDetails) (string, error) {
+	return mnu.checkExistingExcludedOSNodesFunc(automateIp, infra)
+}
+func (mnu *MockNodeUtilsImpl) calculateTotalInstanceCount() (int, error) {
+	return mnu.calculateTotalInstanceCountFunc()
+}
+
+func (mnu *MockNodeUtilsImpl) parseAndMoveConfigFileToWorkspaceDir(outputFiles []string, outputDirectory string) error {
+	return mnu.parseAndMoveConfigFileToWorkspaceDirFunc(outputFiles, outputDirectory)
+}
+
+func (mnu *MockNodeUtilsImpl) executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+	return mnu.executeCmdInAllNodeTypesAndCaptureOutputFunc(nodeObjects, singleNode, outputDirectory)
+}
+
+func (mnu *MockNodeUtilsImpl) executeCustomCmdOnEachNodeType(outputFiles []string, inputFiles []string, inputFilesPrefix string, service string, cmdString string, singleNode bool) error {
+	return mnu.executeCustomCmdOnEachNodeTypeFunc(outputFiles, inputFiles, inputFilesPrefix, service, cmdString, singleNode)
+}
+
+func (mnu *MockNodeUtilsImpl) saveConfigToBastion() error {
+	return mnu.saveConfigToBastionFunc()
+}
+
+func (mnu *MockNodeUtilsImpl) syncConfigToAllNodes() error {
+	return mnu.syncConfigToAllNodesFunc()
+}
diff --git a/lib/io/fileutils/fileutils.go b/lib/io/fileutils/fileutils.go
index 19093bd9e..40dd21763 100644
--- a/lib/io/fileutils/fileutils.go
+++ b/lib/io/fileutils/fileutils.go
@@ -1,15 +1,18 @@
 package fileutils
 
 import (
+	"bufio"
 	"io"
 	"io/ioutil"
 	"os"
 	"os/exec"
+	"path/filepath"
 	"strings"
 
 	"github.com/pkg/errors"
 
 	"github.com/chef/automate/lib/platform/sys"
+	"github.com/chef/toml"
 	"github.com/sirupsen/logrus"
 )
 
@@ -30,6 +33,8 @@ type FileUtils interface {
 	WriteFile(filepath string, data []byte, perm os.FileMode) error
 	CreateTempFile(content string, filename string) (string, error)
 	DeleteFile(fileName string) error
+	Move(sourceFile string, destinationFile string) error
+	RemoveFirstLine(filePath string) error
 }
 
 type FileSystemUtils struct{}
@@ -72,6 +77,13 @@ func (fsu *FileSystemUtils) DeleteFile(filePath string) error {
 	return DeleteFile(filePath)
 }
 
+func (fsu *FileSystemUtils) Move(sourceFile string, destinationFile string) error {
+	return Move(sourceFile, destinationFile)
+}
+func (fsu *FileSystemUtils) RemoveFirstLine(filePath string) error {
+	return RemoveFirstLine(filePath)
+}
+
 // LogCLose closes the given io.Closer, logging any error.
 func LogClose(c io.Closer, log logrus.FieldLogger, msg string) {
 	if err := c.Close(); err != nil {
@@ -175,3 +187,96 @@ func CreateTempFile(content string, filename string) (string, error) {
 func DeleteFile(filePath string) error {
 	return os.Remove(filePath)
 }
+
+// Moves file from current/source directory to destination directory.
+// Creates the directory, if not already exists
+//
+// Example usage:
+// err := fileutils.Move("file.txt", "/path/to/my/dir/", "");
+// Incase of retriving the old file name, leave renamedFileName as empty
+func Move(sourceFile string, destinationFile string) error {
+	destinationDir, fileName := filepath.Split(destinationFile)
+
+	if err := os.MkdirAll(destinationDir, os.ModePerm); err != nil {
+		return err
+	}
+	err := os.Rename(sourceFile, destinationFile)
+	if err != nil {
+		// Checks if the error is of type *os.LinkError
+		if linkErr, ok := err.(*os.LinkError); ok {
+			// Checks the underlying error code & Handles the "file exists" error
+			if linkErr.Err.Error() == "file exists" {
+				if err = os.Remove(destinationFile); err != nil {
+					return err
+				}
+				// Retrys the rename operation
+				if err = os.Rename(sourceFile, destinationDir+fileName); err != nil {
+					return err
+				}
+			}
+		}
+		return err
+	}
+	return nil
+}
+
+func RemoveFirstLine(filePath string) error {
+	// Open the file for reading
+	file, err := os.OpenFile(filePath, os.O_RDWR, 0644)
+	if err != nil {
+		return err
+	}
+	defer file.Close()
+
+	// Create a temporary file to write the updated content
+	tempFile, err := os.CreateTemp("", "temp")
+	if err != nil {
+		return err
+	}
+	defer tempFile.Close()
+
+	// Create a scanner to read the file line by line
+	scanner := bufio.NewScanner(file)
+
+	// Skip the first line
+	scanner.Scan()
+
+	// Write the remaining lines to the temporary file
+	for scanner.Scan() {
+		line := scanner.Text()
+		_, err := tempFile.WriteString(line + "\n")
+		if err != nil {
+			return err
+		}
+	}
+
+	// Close the files
+	file.Close()
+	tempFile.Close()
+
+	// Replace the original file with the temporary file
+	if err = os.Rename(tempFile.Name(), filePath); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// createTomlFileFromConfig created a toml file where path and struct interface is provided
+func CreateTomlFileFromConfig(config interface{}, tomlFile string) (string, error) {
+	f, err := os.Create(tomlFile)
+
+	if err != nil {
+		// failed to create/open the file
+		return "", errors.Wrap(err, "Failed to create/open the file, \n%v")
+	}
+	if err := toml.NewEncoder(f).Encode(config); err != nil {
+		// failed to encode
+		return "", errors.Wrap(err, "Failed to encode\n%v")
+	}
+	if err := f.Close(); err != nil {
+		return "", errors.Wrap(err, "Failed to close the file\n%v")
+	}
+
+	return tomlFile, nil
+}
diff --git a/lib/io/fileutils/mockFileUtils.go b/lib/io/fileutils/mockFileUtils.go
index 15e9642af..45e47355c 100644
--- a/lib/io/fileutils/mockFileUtils.go
+++ b/lib/io/fileutils/mockFileUtils.go
@@ -16,6 +16,8 @@ type MockFileSystemUtils struct {
 	WriteFileFunc              func(filepath string, data []byte, perm os.FileMode) error
 	CreateTempFileFunc         func(content string, filename string) (string, error)
 	DeleteTempFileFunc         func(tempFile string) error
+	MoveFunc                   func(sourceFile string, destinationFile string) error
+	RemoveFirstLineFunc        func(filePath string) error
 }
 
 func (fsu *MockFileSystemUtils) PathExists(path string) (bool, error) {
@@ -51,3 +53,9 @@ func (fsu *MockFileSystemUtils) CreateTempFile(content string, filename string)
 func (fsu *MockFileSystemUtils) DeleteFile(tempFile string) error {
 	return fsu.DeleteTempFileFunc(tempFile)
 }
+func (fsu *MockFileSystemUtils) Move(sourceFile string, destinationFile string) error {
+	return fsu.MoveFunc(sourceFile, destinationFile)
+}
+func (fsu *MockFileSystemUtils) RemoveFirstLine(filePath string) error {
+	return fsu.RemoveFirstLineFunc(filePath)
+}


Test patch:
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_add_aws_test.go b/components/automate-cli/cmd/chef-automate/ha_node_add_aws_test.go
index 69913b89c..093d505a3 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_add_aws_test.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_add_aws_test.go
@@ -185,6 +185,18 @@ func TestAddnodeDeployWithNewOSNodeInAws(t *testing.T) {
 			tfArchModified = true
 			return nil
 		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH_AWS, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
@@ -273,6 +285,18 @@ func TestAddnodeWithExecuteFuncGenConfigErr(t *testing.T) {
 			tfArchModified = true
 			return nil
 		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH_AWS, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
@@ -299,6 +323,203 @@ This will add the new nodes to your existing setup. It might take a while. Are y
 	assert.Error(t, err)
 	assert.Contains(t, err.Error(), "random")
 }
+
+func TestAddnodeWithSaveConfigToBasionErr(t *testing.T) {
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	flags := AddDeleteNodeHACmdFlags{opensearchCount: 1}
+	var filewritten, deployed, autoFileMoved, tfArchModified bool
+	nodeAdd := NewAddNodeAWS(w.CliWriter, flags, &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			deployed = false
+			return nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			filewritten = false
+			return nil
+		},
+		isA2HARBFileExistFunc: func() bool {
+			return true
+		},
+		taintTerraformFunc: func(path string) error {
+			return nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return AWS_MODE, nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		pullAndUpdateConfigAwsFunc: PullAwsConfFunc,
+		moveAWSAutoTfvarsFileFunc: func(path string) error {
+			autoFileMoved = false
+			return nil
+		},
+		modifyTfArchFileFunc: func(path string) error {
+			tfArchModified = false
+			return nil
+		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return errors.New("error removing header")
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
+	}, CONFIG_TOML_PATH_AWS, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+			return "", nil
+		},
+	})
+	err := nodeAdd.Execute(nil, nil)
+	assert.Error(t, err)
+	assert.ErrorContains(t, err, "error removing header")
+	assert.Equal(t, false, autoFileMoved)
+	assert.Equal(t, false, tfArchModified)
+	assert.Equal(t, false, filewritten)
+	assert.Equal(t, false, deployed)
+}
+
+func TestAddnodeWithSyncConfigToAllNodesErr(t *testing.T) {
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	flags := AddDeleteNodeHACmdFlags{automateCount: 1}
+	var filewritten, deployed, autoFileMoved, tfArchModified bool
+	nodeAdd := NewAddNodeAWS(w.CliWriter, flags, &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			deployed = true
+			return nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			filewritten = true
+			return nil
+		},
+		isA2HARBFileExistFunc: func() bool {
+			return true
+		},
+		taintTerraformFunc: func(path string) error {
+			return nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return AWS_MODE, nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return true
+		},
+		pullAndUpdateConfigAwsFunc: PullAwsConfFunc,
+		moveAWSAutoTfvarsFileFunc: func(path string) error {
+			autoFileMoved = true
+			return nil
+		},
+		modifyTfArchFileFunc: func(path string) error {
+			tfArchModified = true
+			return nil
+		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return errors.New("random")
+		},
+	}, CONFIG_TOML_PATH_AWS, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+			return "", nil
+		},
+	})
+
+	err := nodeAdd.Execute(nil, nil)
+	assert.Error(t, err)
+	assert.ErrorContains(t, err, "random")
+	assert.Equal(t, true, autoFileMoved)
+	assert.Equal(t, true, tfArchModified)
+	assert.Equal(t, true, filewritten)
+	assert.Equal(t, true, deployed)
+}
+
+func TestAddnodeWithSyncConfigToAllNodesErrAndDeployError(t *testing.T) {
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	flags := AddDeleteNodeHACmdFlags{automateCount: 1}
+	var filewritten, deployed, autoFileMoved, tfArchModified bool
+	nodeAdd := NewAddNodeAWS(w.CliWriter, flags, &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			deployed = true
+			if command == "deploy" {
+				deployed = false
+				return errors.New("Deployment failed")
+			}
+			return nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			filewritten = true
+			return nil
+		},
+		isA2HARBFileExistFunc: func() bool {
+			return true
+		},
+		taintTerraformFunc: func(path string) error {
+			return nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return AWS_MODE, nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return true
+		},
+		pullAndUpdateConfigAwsFunc: PullAwsConfFunc,
+		moveAWSAutoTfvarsFileFunc: func(path string) error {
+			autoFileMoved = true
+			return nil
+		},
+		modifyTfArchFileFunc: func(path string) error {
+			tfArchModified = true
+			return nil
+		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return errors.New("random")
+		},
+	}, CONFIG_TOML_PATH_AWS, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+			return "", nil
+		},
+	})
+
+	err := nodeAdd.Execute(nil, nil)
+	assert.Error(t, err)
+	assert.ErrorContains(t, err, "random")
+	assert.ErrorContains(t, err, "Deployment failed")
+	assert.Equal(t, true, autoFileMoved)
+	assert.Equal(t, true, tfArchModified)
+	assert.Equal(t, true, filewritten)
+	assert.Equal(t, false, deployed)
+}
+
 func TestAddnodeWithExecuteFunc(t *testing.T) {
 	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
 	flags := AddDeleteNodeHACmdFlags{opensearchCount: 1}
@@ -336,7 +557,26 @@ func TestAddnodeWithExecuteFunc(t *testing.T) {
 			tfArchModified = true
 			return nil
 		},
-	}, CONFIG_TOML_PATH_AWS, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		executeCustomCmdOnEachNodeTypeFunc: func(outputFiles, inputFiles []string, inputFilesPrefix, service, cmdString string, singleNode bool) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+	}, CONFIG_TOML_PATH_AWS, &fileutils.MockFileSystemUtils{
+		MoveFunc: func(sourceFile, destinationFile string) error {
+			return nil
+		},
+	}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
 		},
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_add_onprem_test.go b/components/automate-cli/cmd/chef-automate/ha_node_add_onprem_test.go
index a45e77fc6..eb944c62f 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_add_onprem_test.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_add_onprem_test.go
@@ -394,6 +394,15 @@ func TestAddnodeDeployWithNewOSNode(t *testing.T) {
 		isManagedServicesOnFunc: func() bool {
 			return false
 		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 		pullAndUpdateConfigFunc: PullConfFunc,
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
@@ -446,6 +455,12 @@ func TestAddnodeDeployWithNewOSNodeGenconfigError(t *testing.T) {
 		isManagedServicesOnFunc: func() bool {
 			return false
 		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
 		pullAndUpdateConfigFunc: PullConfFunc,
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
@@ -520,6 +535,18 @@ func TestAddnodeExecuteWithNewOSNodeNoCertByIP(t *testing.T) {
 			cfg.Opensearch.Config.CertsByIP = []CertByIP{}
 			return &cfg, nil
 		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
@@ -576,6 +603,18 @@ func TestAddnodeExecuteWithNewOSNode(t *testing.T) {
 			return false
 		},
 		pullAndUpdateConfigFunc: PullConfFunc,
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
@@ -597,3 +636,140 @@ This will add the new nodes to your existing setup. It might take a while. Are y
 	assert.Equal(t, true, filewritten)
 	assert.Equal(t, true, deployed)
 }
+
+func TestAddnodeExecuteSyncConfigToAllNodes(t *testing.T) {
+
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	mockNodeUtil := newMockNodeUtilsImplForAddOnprem()
+
+	t.Run("With sync config error", func(t *testing.T) {
+
+		mockNodeUtil.syncConfigToAllNodesFunc = func() error {
+			return errors.New("sync error")
+		}
+		nodeAdd := createNewAddNodeOnprem(mockNodeUtil, nil, w)
+
+		err := nodeAdd.runDeploy()
+		assert.Error(t, err, "sync error")
+	})
+	t.Run("With sync config error and deploy error", func(t *testing.T) {
+
+		mockNodeUtil.syncConfigToAllNodesFunc = func() error {
+			return errors.New("sync error")
+		}
+		mockNodeUtil.executeAutomateClusterCtlCommandAsyncfunc = func(command string, args []string, helpDocs string) error {
+			return errors.New("deploy error")
+		}
+		nodeAdd := createNewAddNodeOnprem(mockNodeUtil, nil, w)
+
+		err := nodeAdd.runDeploy()
+		assert.Error(t, err, "sync error")
+	})
+}
+
+func TestAddnodeExecuteSaveConfigFromAllNodeType(t *testing.T) {
+
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	mockNodeUtil := newMockNodeUtilsImplForAddOnprem()
+
+	t.Run("With save config error", func(t *testing.T) {
+
+		mockNodeUtil.saveConfigToBastionFunc = func() error {
+			return errors.New("error fetching config")
+		}
+		mockNodeUtil.pullAndUpdateConfigFunc = PullConfFunc
+		nodeAdd := createNewAddNodeOnprem(mockNodeUtil, nil, w)
+
+		err := nodeAdd.Execute(nil, nil)
+		assert.Error(t, err, "error fetching config")
+	})
+
+	t.Run("no error", func(t *testing.T) {
+
+		mockNodeUtil.saveConfigToBastionFunc = func() error {
+			return nil
+		}
+		mockNodeUtil.pullAndUpdateConfigFunc = PullConfFunc
+		nodeAdd := createNewAddNodeOnprem(mockNodeUtil, nil, w)
+
+		err := nodeAdd.Execute(nil, nil)
+		assert.NoError(t, err)
+	})
+}
+
+func newMockNodeUtilsImplForAddOnprem() *MockNodeUtilsImpl {
+	return &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			return nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			return nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return EXISTING_INFRA_MODE, nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		pullAndUpdateConfigAwsFunc: PullAwsConfFunc,
+		isA2HARBFileExistFunc: func() bool {
+			return true
+		},
+		taintTerraformFunc: func(path string) error {
+			return nil
+		},
+		getAWSConfigIpFunc: func() (*AWSConfigIp, error) {
+			return &AWSConfigIp{
+				configAutomateIpList:   []string{"192.0.0.1", "192.0.0.2", "192.0.0.3", "192.0.0.4"},
+				configChefServerIpList: []string{"192.0.1.1", "192.0.1.2", "192.0.1.3", "192.0.1.4"},
+				configOpensearchIpList: []string{"192.0.2.1", "192.0.2.2", "192.0.2.3", "192.0.2.4"},
+				configPostgresqlIpList: []string{"192.0.3.1", "192.0.3.2", "192.0.3.3", "192.0.3.4"},
+			}, nil
+		},
+		executeShellCommandFunc: func() error {
+			return nil
+		},
+		moveAWSAutoTfvarsFileFunc: func(path string) error {
+			return nil
+		},
+		modifyTfArchFileFunc: func(path string) error {
+			return nil
+		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
+		calculateTotalInstanceCountFunc: func() (int, error) {
+			return 0, nil
+		},
+	}
+}
+
+func createNewAddNodeOnprem(mockNodeUtilsImpl *MockNodeUtilsImpl, mockSSHUtilsImpl *MockSSHUtilsImpl, w *majorupgrade_utils.CustomWriter) HAModifyAndDeploy {
+
+	flags := AddDeleteNodeHACmdFlags{
+		opensearchIp: TEST_IP_1,
+	}
+	return NewAddNodeOnPrem(
+		w.CliWriter,
+		flags,
+		mockNodeUtilsImpl,
+		CONFIG_TOML_PATH,
+		&fileutils.MockFileSystemUtils{},
+		&MockSSHUtilsImpl{
+			connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+				return "", nil
+			},
+		})
+}
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_delete_aws_test.go b/components/automate-cli/cmd/chef-automate/ha_node_delete_aws_test.go
index a1553534e..619caccab 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_delete_aws_test.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_delete_aws_test.go
@@ -512,6 +512,15 @@ func TestDeletenodeDeployWithNewOSNodeInAws(t *testing.T) {
 				tfArchModified = true
 				return nil
 			},
+			executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+				return nil
+			},
+			parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+				return nil
+			},
+			syncConfigToAllNodesFunc: func() error {
+				return nil
+			},
 		},
 		CONFIG_TOML_PATH_AWS,
 		&fileutils.MockFileSystemUtils{},
@@ -629,6 +638,18 @@ func TestDeletenodeAWSExecuteWithError(t *testing.T) {
 			calculateTotalInstanceCountFunc: func() (int, error) {
 				return 0, nil
 			},
+			executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+				return nil
+			},
+			parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+				return nil
+			},
+			saveConfigToBastionFunc: func() error {
+				return nil
+			},
+			syncConfigToAllNodesFunc: func() error {
+				return nil
+			},
 		},
 		CONFIG_TOML_PATH_AWS,
 		&fileutils.MockFileSystemUtils{},
@@ -702,6 +723,18 @@ func TestDeletenodeAWSExecuteNoError(t *testing.T) {
 			count = count - 1
 			return count, nil
 		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 	}
 	flagsArr := []AddDeleteNodeHACmdFlags{
 		{
@@ -741,3 +774,124 @@ func TestDeletenodeAWSExecuteNoError(t *testing.T) {
 	}
 
 }
+
+func TestDeletenodeDeploy(t *testing.T) {
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	mockNodeUtil := newMockNodeUtilsImplForDeleteAWS()
+
+	t.Run("With save config error", func(t *testing.T) {
+
+		mockNodeUtil.saveConfigToBastionFunc = func() error {
+			return errors.New("error removing header from output file")
+		}
+		nodeDelete := createNewDeleteNodeAWS(mockNodeUtil, nil, w)
+
+		err := nodeDelete.Execute(nil, nil)
+		assert.Error(t, err, "error removing header from output file")
+	})
+
+	t.Run("With sync config error", func(t *testing.T) {
+
+		mockNodeUtil.syncConfigToAllNodesFunc = func() error {
+			return errors.New("sync error")
+		}
+		nodeDelete := createNewDeleteNodeAWS(mockNodeUtil, nil, w)
+
+		err := nodeDelete.runDeploy()
+		assert.Error(t, err, "sync error")
+	})
+	t.Run("With sync config error and deploy error", func(t *testing.T) {
+
+		mockNodeUtil.syncConfigToAllNodesFunc = func() error {
+			return errors.New("sync error")
+		}
+		mockNodeUtil.executeAutomateClusterCtlCommandAsyncfunc = func(command string, args []string, helpDocs string) error {
+			if command == "deploy" {
+				return errors.New("deploy error")
+			}
+			return nil
+		}
+		nodeDelete := createNewDeleteNodeAWS(mockNodeUtil, nil, w)
+
+		err := nodeDelete.runDeploy()
+		assert.Error(t, err, "sync error")
+		assert.Error(t, err, "deploy error")
+	})
+}
+
+func newMockNodeUtilsImplForDeleteAWS() *MockNodeUtilsImpl {
+	return &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			return nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			return nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return EXISTING_INFRA_MODE, nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		pullAndUpdateConfigAwsFunc: PullAwsConfFunc,
+		isA2HARBFileExistFunc: func() bool {
+			return true
+		},
+		taintTerraformFunc: func(path string) error {
+			return nil
+		},
+		getAWSConfigIpFunc: func() (*AWSConfigIp, error) {
+			return &AWSConfigIp{
+				configAutomateIpList:   []string{"192.0.0.1", "192.0.0.2", "192.0.0.3", "192.0.0.4"},
+				configChefServerIpList: []string{"192.0.1.1", "192.0.1.2", "192.0.1.3", "192.0.1.4"},
+				configOpensearchIpList: []string{"192.0.2.1", "192.0.2.2", "192.0.2.3", "192.0.2.4"},
+				configPostgresqlIpList: []string{"192.0.3.1", "192.0.3.2", "192.0.3.3", "192.0.3.4"},
+			}, nil
+		},
+		executeShellCommandFunc: func() error {
+			return nil
+		},
+		moveAWSAutoTfvarsFileFunc: func(path string) error {
+			return nil
+		},
+		modifyTfArchFileFunc: func(path string) error {
+			return nil
+		},
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
+		calculateTotalInstanceCountFunc: func() (int, error) {
+			return 0, nil
+		},
+	}
+}
+
+func createNewDeleteNodeAWS(mockNodeUtilsImpl *MockNodeUtilsImpl, mockSSHUtilsImpl *MockSSHUtilsImpl, w *majorupgrade_utils.CustomWriter) HAModifyAndDeploy {
+
+	flags := AddDeleteNodeHACmdFlags{
+		automateIp: "192.0.0.1",
+	}
+	return NewDeleteNodeAWS(
+		w.CliWriter,
+		flags,
+		mockNodeUtilsImpl,
+		CONFIG_TOML_PATH_AWS,
+		&fileutils.MockFileSystemUtils{},
+		&MockSSHUtilsImpl{
+			connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+				return "", nil
+			},
+		})
+}
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_delete_onprem_test.go b/components/automate-cli/cmd/chef-automate/ha_node_delete_onprem_test.go
index 4c78dcc15..8e4bb98a5 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_delete_onprem_test.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_delete_onprem_test.go
@@ -345,6 +345,131 @@ func TestDeleteNodeDeployWithNewOSNode(t *testing.T) {
 			return false
 		},
 		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
+	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+			return "", nil
+		},
+	})
+	err := nodedelete.validate()
+	assert.NoError(t, err)
+	err = nodedelete.modifyConfig()
+	assert.NoError(t, err)
+	assert.Equal(t, flags.opensearchIp, nodedelete.(*DeleteNodeOnPremImpl).ipToDelete)
+	res, err := nodedelete.promptUserConfirmation()
+	assert.Equal(t, true, res)
+	assert.NoError(t, err)
+	assert.Contains(t, w.Output(), `Existing nodes:
+================================================
+Automate => 192.0.2.0, 192.0.2.1
+Chef-Server => 192.0.2.2
+OpenSearch => 192.0.2.3, 192.0.2.4, 192.0.2.5, 192.0.2.6
+Postgresql => 192.0.2.7, 192.0.2.8, 192.0.2.9
+
+Node to be deleted:
+================================================
+Opensearch => 192.0.2.3
+Removal of node for Postgresql or OpenSearch is at your own risk and may result to data loss. Consult your database administrator before trying to delete Postgresql or OpenSearch node.
+This will delete the above node from your existing setup. It might take a while. Are you sure you want to continue? (y/n)`)
+	err = nodedelete.runDeploy()
+	assert.NoError(t, err)
+	assert.Equal(t, true, filewritten)
+	assert.Equal(t, true, deployed)
+}
+
+func TestDeleteNodeDeployWithSaveConfigToBastionError(t *testing.T) {
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	flags := AddDeleteNodeHACmdFlags{
+		opensearchIp: "192.0.2.3",
+	}
+	nodedelete := NewDeleteNodeOnPrem(w.CliWriter, flags, &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return EXISTING_INFRA_MODE, nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			return nil
+		},
+		executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			return nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return errors.New("error on removing output header in fetched config")
+		},
+		isA2HARBFileExistFunc: func() bool {
+			return true
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
+	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+			return "", nil
+		},
+	})
+	err := nodedelete.Execute(nil, nil)
+	assert.Error(t, err, "error on removing output header in fetched config")
+}
+
+func TestDeleteNodeDeployWithError(t *testing.T) {
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	flags := AddDeleteNodeHACmdFlags{
+		opensearchIp: "192.0.2.3",
+	}
+	var filewritten, deployed bool
+	nodedelete := NewDeleteNodeOnPrem(w.CliWriter, flags, &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return EXISTING_INFRA_MODE, nil
+		}, executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			deployed = false
+			return errors.New("Invalid or empty command")
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			filewritten = true
+			return nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
@@ -371,11 +496,143 @@ Opensearch => 192.0.2.3
 Removal of node for Postgresql or OpenSearch is at your own risk and may result to data loss. Consult your database administrator before trying to delete Postgresql or OpenSearch node.
 This will delete the above node from your existing setup. It might take a while. Are you sure you want to continue? (y/n)`)
 	err = nodedelete.runDeploy()
+	assert.Error(t, err, "Invalid or empty command")
+	assert.Equal(t, true, filewritten)
+	assert.Equal(t, false, deployed)
+}
+
+func TestDeleteNodeDeployWithErrorSync(t *testing.T) {
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	flags := AddDeleteNodeHACmdFlags{
+		opensearchIp: "192.0.2.3",
+	}
+	var filewritten, deployed bool
+	nodedelete := NewDeleteNodeOnPrem(w.CliWriter, flags, &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return EXISTING_INFRA_MODE, nil
+		}, executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			deployed = true
+			return nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			filewritten = true
+			return nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return errors.New("sync failed")
+		},
+	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+			return "", nil
+		},
+	},
+	)
+	err := nodedelete.validate()
+	assert.NoError(t, err)
+	err = nodedelete.modifyConfig()
 	assert.NoError(t, err)
+	assert.Equal(t, flags.opensearchIp, nodedelete.(*DeleteNodeOnPremImpl).ipToDelete)
+	res, err := nodedelete.promptUserConfirmation()
+	assert.Equal(t, true, res)
+	assert.NoError(t, err)
+	assert.Contains(t, w.Output(), `Existing nodes:
+================================================
+Automate => 192.0.2.0, 192.0.2.1
+Chef-Server => 192.0.2.2
+OpenSearch => 192.0.2.3, 192.0.2.4, 192.0.2.5, 192.0.2.6
+Postgresql => 192.0.2.7, 192.0.2.8, 192.0.2.9
+
+Node to be deleted:
+================================================
+Opensearch => 192.0.2.3
+Removal of node for Postgresql or OpenSearch is at your own risk and may result to data loss. Consult your database administrator before trying to delete Postgresql or OpenSearch node.
+This will delete the above node from your existing setup. It might take a while. Are you sure you want to continue? (y/n)`)
+	err = nodedelete.runDeploy()
+	assert.Error(t, err, "sync failed")
 	assert.Equal(t, true, filewritten)
 	assert.Equal(t, true, deployed)
 }
 
+func TestDeleteNodeDeployWithErrorSyncAndDeployError(t *testing.T) {
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	flags := AddDeleteNodeHACmdFlags{
+		opensearchIp: "192.0.2.3",
+	}
+	var filewritten, deployed bool
+	nodedelete := NewDeleteNodeOnPrem(w.CliWriter, flags, &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return EXISTING_INFRA_MODE, nil
+		}, executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			deployed = false
+			return errors.New("Invalid or empty command")
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			filewritten = true
+			return nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return errors.New("Invalid or empty command")
+		},
+	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+			return "", nil
+		},
+	},
+	)
+	err := nodedelete.validate()
+	assert.NoError(t, err)
+	err = nodedelete.modifyConfig()
+	assert.NoError(t, err)
+	assert.Equal(t, flags.opensearchIp, nodedelete.(*DeleteNodeOnPremImpl).ipToDelete)
+	res, err := nodedelete.promptUserConfirmation()
+	assert.Equal(t, true, res)
+	assert.NoError(t, err)
+	assert.Contains(t, w.Output(), `Existing nodes:
+================================================
+Automate => 192.0.2.0, 192.0.2.1
+Chef-Server => 192.0.2.2
+OpenSearch => 192.0.2.3, 192.0.2.4, 192.0.2.5, 192.0.2.6
+Postgresql => 192.0.2.7, 192.0.2.8, 192.0.2.9
+
+Node to be deleted:
+================================================
+Opensearch => 192.0.2.3
+Removal of node for Postgresql or OpenSearch is at your own risk and may result to data loss. Consult your database administrator before trying to delete Postgresql or OpenSearch node.
+This will delete the above node from your existing setup. It might take a while. Are you sure you want to continue? (y/n)`)
+	err = nodedelete.runDeploy()
+	assert.Error(t, err, "Invalid or empty command")
+	assert.Equal(t, true, filewritten)
+	assert.Equal(t, false, deployed)
+}
+
 func TestDeleteNodeDeployWithNewOSMinCountError(t *testing.T) {
 	w := majorupgrade_utils.NewCustomWriter()
 	flags := AddDeleteNodeHACmdFlags{
@@ -398,6 +655,13 @@ func TestDeleteNodeDeployWithNewOSMinCountError(t *testing.T) {
 			return false
 		},
 		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
@@ -431,6 +695,13 @@ func TestDeleteNodeDeployWithNewOSNodeError(t *testing.T) {
 			return false
 		},
 		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
@@ -513,6 +784,19 @@ func TestRemovenodeExecuteWithNewOSNodeNoCertsByIP(t *testing.T) {
 			cfg.Opensearch.Config.CertsByIP = []CertByIP{}
 			return &cfg, nil
 		},
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
@@ -578,6 +862,97 @@ func TestRemovenodeExecuteWithNewOSNode(t *testing.T) {
 			return count, nil
 		},
 		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
+	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
+		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+			return "", nil
+		},
+	})
+	err := nodeAdd.Execute(nil, nil)
+	assert.NoError(t, err)
+	assert.Contains(t, w.Output(), `Existing nodes:
+================================================
+Automate => 192.0.2.0, 192.0.2.1
+Chef-Server => 192.0.2.2
+OpenSearch => 192.0.2.3, 192.0.2.4, 192.0.2.5, 192.0.2.6
+Postgresql => 192.0.2.7, 192.0.2.8, 192.0.2.9
+
+Node to be deleted:
+================================================
+Opensearch => 192.0.2.6
+Removal of node for Postgresql or OpenSearch is at your own risk and may result to data loss. Consult your database administrator before trying to delete Postgresql or OpenSearch node.
+This will delete the above node from your existing setup. It might take a while. Are you sure you want to continue? (y/n)`)
+	assert.Equal(t, true, filewritten)
+	assert.Equal(t, true, deployed)
+}
+
+func TestRemovenodeExecuteWithProvisionError(t *testing.T) {
+	count := 10
+	w := majorupgrade_utils.NewCustomWriterWithInputs("y")
+	flags := AddDeleteNodeHACmdFlags{
+		opensearchIp: "192.0.2.6",
+	}
+	var filewritten, deployed bool
+	nodeAdd := NewDeleteNodeOnPrem(w.CliWriter, flags, &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			return nil, &SSHConfig{}, nil
+		},
+		executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			deployed = true
+			return nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			filewritten = true
+			return nil
+		},
+		isA2HARBFileExistFunc: func() bool {
+			return true
+		},
+		checkIfFileExistFunc: func(path string) bool {
+			return checkIfFileExist(path)
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return EXISTING_INFRA_MODE, nil
+		},
+		taintTerraformFunc: func(path string) error {
+			return nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		stopServicesOnNodeFunc: func(ip, nodeType, deploymentType string, infra *AutomateHAInfraDetails) error {
+			return nil
+		},
+		calculateTotalInstanceCountFunc: func() (int, error) {
+			count = count - 1
+			return count, nil
+		},
+		pullAndUpdateConfigFunc: PullConfFunc,
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
 	}, CONFIG_TOML_PATH, &fileutils.MockFileSystemUtils{}, &MockSSHUtilsImpl{
 		connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
 			return "", nil
diff --git a/components/automate-cli/cmd/chef-automate/ha_node_operations_utils_test.go b/components/automate-cli/cmd/chef-automate/ha_node_operations_utils_test.go
index 2c1981531..1783b8c87 100644
--- a/components/automate-cli/cmd/chef-automate/ha_node_operations_utils_test.go
+++ b/components/automate-cli/cmd/chef-automate/ha_node_operations_utils_test.go
@@ -227,6 +227,66 @@ func TestMoveAWSAutoTfvarsDestroyFolderNotExist(t *testing.T) {
 
 }
 
+func TestSaveConfigToBastion(t *testing.T) {
+	mockUtil := &MockNodeUtilsImpl{
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			infra := &AutomateHAInfraDetails{}
+			infra.Outputs.AutomatePrivateIps.Value = []string{TEST_IP_1}
+			return infra, &SSHConfig{}, nil
+		},
+		executeAutomateClusterCtlCommandAsyncfunc: func(command string, args []string, helpDocs string) error {
+			return nil
+		},
+		writeHAConfigFilesFunc: func(templateName string, data interface{}) error {
+			return nil
+		},
+		isA2HARBFileExistFunc: func() bool {
+			return true
+		},
+		checkIfFileExistFunc: func(path string) bool {
+			return checkIfFileExist(path)
+		},
+		getModeFromConfigFunc: func(path string) (string, error) {
+			return EXISTING_INFRA_MODE, nil
+		},
+		taintTerraformFunc: func(path string) error {
+			return nil
+		},
+		isManagedServicesOnFunc: func() bool {
+			return false
+		},
+		stopServicesOnNodeFunc: func(ip, nodeType, deploymentType string, infra *AutomateHAInfraDetails) error {
+			return nil
+		},
+		pullAndUpdateConfigFunc: func(sshUtil *SSHUtil, exceptionIps []string) (*ExistingInfraConfigToml, error) {
+			cfg, err := readConfig(CONFIG_TOML_PATH + "/config.toml")
+			if err != nil {
+				return nil, err
+			}
+			cfg.Automate.Config.CertsByIP = []CertByIP{}
+			cfg.ChefServer.Config.CertsByIP = []CertByIP{}
+			cfg.Postgresql.Config.CertsByIP = []CertByIP{}
+			cfg.Opensearch.Config.CertsByIP = []CertByIP{}
+			return &cfg, nil
+		},
+
+		executeCmdInAllNodeTypesAndCaptureOutputFunc: func(nodeObjects []*NodeObject, singleNode bool, outputDirectory string) error {
+			return nil
+		},
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return nil
+		},
+		saveConfigToBastionFunc: func() error {
+			return nil
+		},
+		syncConfigToAllNodesFunc: func() error {
+			return nil
+		},
+	}
+	err := mockUtil.saveConfigToBastion()
+	assert.NoError(t, err)
+}
+
 func TestModifyTfArchFile(t *testing.T) {
 	nodeUtil := NewNodeUtils(NewRemoteCmdExecutorWithoutNodeMap(NewSSHUtil(&SSHConfig{}), MockWriter.CliWriter), command.NewMockExecutor(t), MockWriter.CliWriter)
 	dir := t.TempDir()
@@ -550,3 +610,393 @@ func TestGetIPsFromOSClusterResponseNotFound(t *testing.T) {
 	out := getIPsFromOSClusterResponse(input)
 	assert.Equal(t, "", out)
 }
+
+func TestSyncConfigToAllNodes(t *testing.T) {
+	nodeUtil := NewNodeUtils(&MockRemoteCmdExecutor{
+		ExecuteFunc: func() (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+		ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+		GetSshUtilFunc: func() SSHUtil {
+			return &MockSSHUtilsImpl{
+				connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+					return "", nil
+				},
+				copyFileToRemoteFunc: func(srcFilePath string, destFileName string, removeFile bool) error {
+					return nil
+				},
+			}
+		},
+	}, command.NewMockExecutor(t), MockWriter.CliWriter)
+
+	t.Run("save config in bastion", func(t *testing.T) {
+		err := nodeUtil.saveConfigToBastion()
+		assert.Error(t, err, "Automate Ha infra confile file not exist")
+	})
+	t.Run("sync config in all nodes", func(t *testing.T) {
+		err := nodeUtil.syncConfigToAllNodes()
+		assert.Error(t, err, "Automate Ha infra confile file not exist")
+	})
+}
+
+func TestexecuteCmdInAllNodeTypesAndCaptureOutput(t *testing.T) {
+	t.Run("save config in bastion", func(t *testing.T) {
+
+		mnu := &MockNodeUtilsImpl{
+			parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+				return nil
+			},
+			getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+				return nil, nil, nil
+			},
+			executeCustomCmdOnEachNodeTypeFunc: func(outputFiles, inputFiles []string, inputFilesPrefix, service, cmdString string, singleNode bool) error {
+				return nil
+			},
+		}
+		nodeObjects := getNodeObjectsToFetchConfigFromAllNodeTypes()
+		singleNode := true
+		outputDirectory := ""
+
+		err := executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, singleNode, outputDirectory, mnu)
+		assert.NoError(t, err)
+	})
+
+	t.Run("save config in bastion with error in parsing", func(t *testing.T) {
+
+		mnu := &MockNodeUtilsImpl{
+			parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+				return errors.New("error parsing output file")
+			},
+			getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+				return nil, nil, nil
+			},
+			executeCustomCmdOnEachNodeTypeFunc: func(outputFiles, inputFiles []string, inputFilesPrefix, service, cmdString string, singleNode bool) error {
+				return nil
+			},
+		}
+		nodeObjects := getNodeObjectsToFetchConfigFromAllNodeTypes()
+		singleNode := true
+		outputDirectory := ""
+
+		err := executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, singleNode, outputDirectory, mnu)
+		assert.Error(t, err, "error parsing output file")
+	})
+
+	t.Run("Get node object with to patch command in all nodes", func(t *testing.T) {
+		mnu := NewNodeUtils(&MockRemoteCmdExecutor{
+			ExecuteFunc: func() (map[string][]*CmdResult, error) {
+				return nil, nil
+			},
+			ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+				return nil, nil
+			},
+			GetSshUtilFunc: func() SSHUtil {
+				return &MockSSHUtilsImpl{
+					connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+						return "", nil
+					},
+					copyFileToRemoteFunc: func(srcFilePath string, destFileName string, removeFile bool) error {
+						return nil
+					},
+				}
+			},
+		}, command.NewMockExecutor(t), MockWriter.CliWriter)
+
+		nodeObjects := getNodeObjectsToPatchWorkspaceConfigToAllNodes()
+		singleNode := true
+		outputDirectory := ""
+		err := executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, singleNode, outputDirectory, mnu)
+		assert.Error(t, err, "No ips found")
+	})
+
+	t.Run("Get node object with to patch command for PG node", func(t *testing.T) {
+		mnu := NewNodeUtils(&MockRemoteCmdExecutor{
+			ExecuteFunc: func() (map[string][]*CmdResult, error) {
+				return nil, nil
+			},
+			ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+				return nil, nil
+			},
+			GetSshUtilFunc: func() SSHUtil {
+				return &MockSSHUtilsImpl{
+					connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+						return "", nil
+					},
+					copyFileToRemoteFunc: func(srcFilePath string, destFileName string, removeFile bool) error {
+						return nil
+					},
+				}
+			},
+		}, command.NewMockExecutor(t), MockWriter.CliWriter)
+
+		nodeObjects := []*NodeObject{
+			NewNodeObjectWithOutputFile("", nil, nil, "", POSTGRESQL),
+		}
+		singleNode := true
+		outputDirectory := ""
+		err := executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, singleNode, outputDirectory, mnu)
+		assert.Error(t, err, "No ips found")
+	})
+
+	t.Run("Get node object with to patch command for OS node", func(t *testing.T) {
+		mnu := NewNodeUtils(&MockRemoteCmdExecutor{
+			ExecuteFunc: func() (map[string][]*CmdResult, error) {
+				return nil, nil
+			},
+			ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+				return nil, nil
+			},
+			GetSshUtilFunc: func() SSHUtil {
+				return &MockSSHUtilsImpl{
+					connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+						return "", nil
+					},
+					copyFileToRemoteFunc: func(srcFilePath string, destFileName string, removeFile bool) error {
+						return nil
+					},
+				}
+			},
+		}, command.NewMockExecutor(t), MockWriter.CliWriter)
+
+		nodeObjects := []*NodeObject{
+			NewNodeObjectWithOutputFile("", nil, nil, "", OPENSEARCH),
+		}
+		singleNode := true
+		outputDirectory := ""
+		err := executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, singleNode, outputDirectory, mnu)
+		assert.Error(t, err, "No ips found")
+	})
+
+	t.Run("Get node object for fetch command in all nodes", func(t *testing.T) {
+		mnu := NewNodeUtils(&MockRemoteCmdExecutor{
+			ExecuteFunc: func() (map[string][]*CmdResult, error) {
+				return nil, nil
+			},
+			ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+				return nil, nil
+			},
+			GetSshUtilFunc: func() SSHUtil {
+				return &MockSSHUtilsImpl{
+					connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+						return "", nil
+					},
+					copyFileToRemoteFunc: func(srcFilePath string, destFileName string, removeFile bool) error {
+						return nil
+					},
+				}
+			},
+		}, command.NewMockExecutor(t), MockWriter.CliWriter)
+
+		nodeObjects := getNodeObjectsToFetchConfigFromAllNodeTypes()
+		singleNode := true
+		outputDirectory := ""
+		err := executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, singleNode, outputDirectory, mnu)
+		assert.Error(t, err, "No ips found")
+	})
+}
+
+func TestexecuteCmdInAllNodeTypesAndCaptureOutputToSaveConfigInBastionBeforeNodeModify(t *testing.T) {
+
+	t.Run("save config in bastion", func(t *testing.T) {
+
+		mnu := &MockNodeUtilsImpl{
+			parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+				return nil
+			},
+			getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+				return nil, nil, nil
+			},
+			executeCustomCmdOnEachNodeTypeFunc: func(outputFiles, inputFiles []string, inputFilesPrefix, service, cmdString string, singleNode bool) error {
+				return nil
+			},
+		}
+		nodeObjects := getNodeObjectsToFetchConfigFromAllNodeTypes()
+		singleNode := true
+		outputDirectory := ""
+
+		err := executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, singleNode, outputDirectory, mnu)
+		assert.NoError(t, err)
+	})
+
+	t.Run("save config in bastion with error in parsing", func(t *testing.T) {
+
+		mnu := &MockNodeUtilsImpl{
+			parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+				return errors.New("error parsing output file")
+			},
+			getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+				return nil, nil, nil
+			},
+			executeCustomCmdOnEachNodeTypeFunc: func(outputFiles, inputFiles []string, inputFilesPrefix, service, cmdString string, singleNode bool) error {
+				return nil
+			},
+		}
+		nodeObjects := getNodeObjectsToFetchConfigFromAllNodeTypes()
+		singleNode := true
+		outputDirectory := ""
+
+		err := executeCmdInAllNodeTypesAndCaptureOutput(nodeObjects, singleNode, outputDirectory, mnu)
+		assert.Error(t, err, "error parsing output file")
+	})
+}
+
+func TestCreateNodeMap(t *testing.T) {
+	mnu := &MockNodeUtilsImpl{
+		parseAndMoveConfigFileToWorkspaceDirFunc: func(outputFiles []string, outputDirectory string) error {
+			return errors.New("error parsing output file")
+		},
+		getHaInfraDetailsfunc: func() (*AutomateHAInfraDetails, *SSHConfig, error) {
+			infra := &AutomateHAInfraDetails{}
+			infra.Outputs.AutomatePrivateIps.Value = []string{TEST_IP_1}
+			return infra, &SSHConfig{}, nil
+		},
+		executeCustomCmdOnEachNodeTypeFunc: func(outputFiles, inputFiles []string, inputFilesPrefix, service, cmdString string, singleNode bool) error {
+			return nil
+		},
+	}
+
+	infra, _, err := mnu.getHaInfraDetails()
+	assert.NoError(t, err)
+
+	outputFiles := []string{"outputFiles.toml"}
+	inputFiles := []string{"inputFiles.toml"}
+	inputFilesPrefix := "/tmp/"
+
+	cmdString := "sudo chef-automate config patch"
+	singleNode := true
+
+	t.Run(AUTOMATE, func(t *testing.T) {
+		service := AUTOMATE
+		nodeMap := createNodeMap(outputFiles, inputFiles, inputFilesPrefix, service, cmdString, singleNode, infra)
+		assert.NotNil(t, nodeMap, "automate")
+	})
+	t.Run(CHEF_SERVER, func(t *testing.T) {
+		service := CHEF_SERVER
+		nodeMap := createNodeMap(outputFiles, inputFiles, inputFilesPrefix, service, cmdString, singleNode, infra)
+		assert.NotNil(t, nodeMap, "automate")
+	})
+	t.Run(POSTGRESQL, func(t *testing.T) {
+		service := POSTGRESQL
+		nodeMap := createNodeMap(outputFiles, inputFiles, inputFilesPrefix, service, cmdString, singleNode, infra)
+		assert.NotNil(t, nodeMap, "automate")
+	})
+	t.Run(OPENSEARCH, func(t *testing.T) {
+		service := OPENSEARCH
+		nodeMap := createNodeMap(outputFiles, inputFiles, inputFilesPrefix, service, cmdString, singleNode, infra)
+		assert.NotNil(t, nodeMap, "automate")
+	})
+}
+
+func TestPrePatchForFrontendNodes(t *testing.T) {
+
+	tomlFileContent := `
+	[deployment]
+  [deployment.v1]
+    [deployment.v1.svc]
+      channel = "current"
+      upgrade_strategy = "none"
+      deployment_type = "local"
+      products = ["automate", "chef-server"]
+			[[global.v1.frontend_tls]]
+      cert=""
+			[[load_balancer.v1.sys.frontend_tls]]
+			cert = ""`
+
+	filePath, err := fileutils.CreateTempFile(tomlFileContent, AUTOMATE_TOML)
+	assert.NoError(t, err)
+	defer fileutils.DeleteFile(filePath)
+
+	t.Run("with empty toml", func(t *testing.T) {
+		cmpInput := &CmdInputs{
+			InputFiles: []string{AUTOMATE_TOML},
+			Args:       []string{""},
+		}
+		err := prePatchForFrontendNodes(cmpInput, NewSSHUtil(&SSHConfig{}), nil, "", nil)
+		assert.NoError(t, err)
+	})
+	t.Run("with toml file content", func(t *testing.T) {
+		cmpInput := &CmdInputs{
+			InputFiles: []string{AUTOMATE_TOML},
+			Args:       []string{filePath},
+		}
+		err := prePatchForFrontendNodes(cmpInput, NewSSHUtil(&SSHConfig{}), nil, "", nil)
+		assert.NoError(t, err)
+	})
+	t.Run("with invalid toml file content", func(t *testing.T) {
+		tomlFileContent := `
+	[deploy`
+		filePath, err := fileutils.CreateTempFile(tomlFileContent, AUTOMATE_TOML)
+		assert.NoError(t, err)
+		cmpInput := &CmdInputs{
+			InputFiles: []string{AUTOMATE_TOML},
+			Args:       []string{filePath},
+		}
+		err = prePatchForFrontendNodes(cmpInput, NewSSHUtil(&SSHConfig{}), nil, "", nil)
+		assert.Error(t, err, "expected '.' or ']'")
+	})
+}
+
+func TestParseAndMoveConfigFileToWorkspaceDir(t *testing.T) {
+	mnu := NewNodeUtils(&MockRemoteCmdExecutor{
+		ExecuteFunc: func() (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+		ExecuteWithNodeMapFunc: func(nodeMap *NodeTypeAndCmd) (map[string][]*CmdResult, error) {
+			return nil, nil
+		},
+		GetSshUtilFunc: func() SSHUtil {
+			return &MockSSHUtilsImpl{
+				connectAndExecuteCommandOnRemoteFunc: func(remoteCommands string, spinner bool) (string, error) {
+					return "", nil
+				},
+				copyFileToRemoteFunc: func(srcFilePath string, destFileName string, removeFile bool) error {
+					return nil
+				},
+			}
+		},
+	}, command.NewMockExecutor(t), MockWriter.CliWriter)
+
+	tomlFileContent := `Output of IP a.b.c.d:
+[deployment]
+  [deployment.v1]
+    [deployment.v1.svc]
+      channel = "current"
+      upgrade_strategy = "none"
+      deployment_type = "local"
+      products = ["automate", "chef-server"]
+			[[global.v1.frontend_tls]]
+      cert=""
+			[[load_balancer.v1.sys.frontend_tls]]
+			cert = ""
+`
+	finalTomlFileContent := `[deployment]
+  [deployment.v1]
+    [deployment.v1.svc]
+      channel = "current"
+      upgrade_strategy = "none"
+      deployment_type = "local"
+      products = ["automate", "chef-server"]
+			[[global.v1.frontend_tls]]
+      cert=""
+			[[load_balancer.v1.sys.frontend_tls]]
+			cert = ""
+`
+
+	filePath, err := fileutils.CreateTempFile(tomlFileContent, AUTOMATE_TOML)
+	assert.NoError(t, err)
+	defer fileutils.DeleteFile(filePath)
+
+	t.Run("No error", func(t *testing.T) {
+		err = mnu.parseAndMoveConfigFileToWorkspaceDir([]string{filePath}, "")
+		assert.NoError(t, err)
+		contentByte, err := fileutils.ReadFile(filePath)
+		assert.NoError(t, err)
+		assert.Equal(t, finalTomlFileContent, string(contentByte))
+	})
+	t.Run("error on removing output header", func(t *testing.T) {
+		err = mnu.parseAndMoveConfigFileToWorkspaceDir([]string{AUTOMATE_TOML}, "")
+		assert.Error(t, err, "error on removing output header in fetched config")
+	})
+}
diff --git a/lib/io/fileutils/fileutils_test.go b/lib/io/fileutils/fileutils_test.go
index e350b3920..964a7ac8b 100644
--- a/lib/io/fileutils/fileutils_test.go
+++ b/lib/io/fileutils/fileutils_test.go
@@ -1,9 +1,11 @@
 package fileutils_test
 
 import (
+	"io/fs"
 	"io/ioutil"
 	"os"
 	"path"
+	"path/filepath"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -82,3 +84,120 @@ func TestDeleteTempFile(t *testing.T) {
 		return
 	}
 }
+
+func TestMove(t *testing.T) {
+	content := "abc"
+	filename := "file-name"
+	destinationDir := createTempDir(t)
+	defer os.RemoveAll(destinationDir)
+
+	t.Run("Move a file to new directory", func(t *testing.T) {
+		srcFile, err := fileutils.CreateTempFile(content, filename)
+		assert.Contains(t, srcFile, "file-name")
+		require.NoError(t, err)
+		defer fileutils.DeleteFile(srcFile)
+
+		err = fileutils.Move(srcFile, destinationDir+filename)
+		defer fileutils.DeleteFile(destinationDir + filename)
+		require.NoError(t, err)
+		fileExists, err := fileutils.PathExists(destinationDir + filename)
+		require.NoError(t, err)
+		assert.True(t, fileExists)
+	})
+
+	t.Run("Move a file to a directory and overwrite the existing file", func(t *testing.T) {
+		srcFile, err := fileutils.CreateTempFile(content, filename)
+		assert.Contains(t, srcFile, "file-name")
+		require.NoError(t, err)
+		defer fileutils.DeleteFile(srcFile)
+
+		existingFile := filepath.Join(destinationDir, "existing.txt")
+		err = fileutils.WriteFile(existingFile, []byte("Existing File"), 0644)
+		require.NoError(t, err)
+		err = fileutils.Move(srcFile, existingFile)
+		require.NoError(t, err)
+	})
+
+	t.Run("Invalid destinationfile", func(t *testing.T) {
+		srcFile, err := fileutils.CreateTempFile(content, filename)
+		assert.Contains(t, srcFile, "file-name")
+		require.NoError(t, err)
+		defer fileutils.DeleteFile(srcFile)
+
+		invalidSourceFile := "/path/to/invalid/source.txt"
+		err = fileutils.Move(invalidSourceFile, destinationDir+filename)
+		linkErr, _ := err.(*os.LinkError)
+		value := linkErr.Err.Error()
+		require.Contains(t, value, "no such file or directory", "No such file or Directory")
+	})
+}
+
+func createTempDir(t *testing.T) string {
+	dir, err := ioutil.TempDir("", "destination_*")
+	if err != nil {
+		t.Fatalf("Failed to create temporary directory: %v", err)
+	}
+	return dir
+}
+
+func TestRemoveFirstLine(t *testing.T) {
+	content := "HeaderToBeRemoved\nabc"
+	filename := "file-name"
+
+	t.Run("Remove first line", func(t *testing.T) {
+		res, err := fileutils.CreateTempFile(content, filename)
+		assert.Contains(t, res, "file-name")
+		require.NoError(t, err)
+		err = fileutils.RemoveFirstLine(res)
+		require.NoError(t, err)
+		fileContent, err := fileutils.ReadFile(res)
+		require.NoError(t, err)
+		assert.EqualValues(t, string(fileContent), "abc\n")
+	})
+
+	t.Run("Open file error", func(t *testing.T) {
+		err := fileutils.RemoveFirstLine(filename)
+		require.Error(t, err.(*fs.PathError), "No such file or directory")
+	})
+}
+
+func TestCreateTomlFileFromConfig(t *testing.T) {
+	tomlFilePath := "file-name"
+
+	user := struct {
+		Name string
+		Age  int
+	}{
+		Name: "John Doe",
+		Age:  30,
+	}
+
+	expectedContent := `Name = "John Doe"
+Age = 30
+`
+	defer os.Remove(tomlFilePath)
+
+	t.Run("Create toml file", func(t *testing.T) {
+		tomlFile, err := fileutils.CreateTomlFileFromConfig(user, tomlFilePath)
+		require.NoError(t, err)
+		fileByte, err := fileutils.ReadFile(tomlFile)
+		require.NoError(t, err)
+		assert.Contains(t, string(fileByte), expectedContent)
+		// err = fileutils.DeleteTempFile(tomlFile)
+		require.NoError(t, err)
+	})
+
+	invalidFile := "/path/to/invalid/file.toml"
+
+	t.Run("Open file error", func(t *testing.T) {
+		_, err := fileutils.CreateTomlFileFromConfig(user, invalidFile)
+		// fmt.Print(err.(*fs.PathError))
+		require.Error(t, err, "Failed to create/open the file")
+	})
+
+	t.Run("Error encoding the config", func(t *testing.T) {
+		var invalidConfig int
+		_, err := fileutils.CreateTomlFileFromConfig(invalidConfig, tomlFilePath)
+		require.Error(t, err, "Failed to encode")
+	})
+}