Repository: chef/automate (go)

Issue:
Run History shows the local time but with a UTC label
## Describe the bug
When viewing Client Runs the time is listed inaccurately on the page header, the Run Duration field, and the Run History tab.  It shows the local time but with a UTC label.

## To Reproduce
View the client run times listed for a server and compare them with the times in the chef-client.log on the server or the times listed in the Chef Manage interface.

## Expected behavior
The time should display as ~either the local time, the local time with a timezone label, or in~ UTC time with a UTC label.

## Screenshots
![image](https://user-images.githubusercontent.com/44782158/67299366-314d0d00-f4b2-11e9-8c74-d51c080d08a3.png)
![image](https://user-images.githubusercontent.com/44782158/67299013-b97ee280-f4b1-11e9-9f6d-fa2e8c62d4ca.png)

## Versions (please complete the following information):
- OS: CentOS 7
- Chrome
- Automate Build 20191001203421

## Additional context
I believe this started in Automate Build 20191007115919.

Pull request:
Update Timestamps to use UTC
### :nut_and_bolt: Description: What code changed, and why?

Problem: Time across the site (not just run history drawer) is showing in local time instead of UTC as desired.

For times converted in our HTML, I've added a `.utc()` to our datetime pipe, which uses moment.js.  this will return UTC instead of local time.

For times requested where the conversion is done in component.ts files, i've added `.utc()` to the moment conversion.

<!-- /!\ Please ensure that you are NOT disclosing any customer information without their consent /!\ -->

### :chains: Related Resources
https://github.com/chef/automate/issues/1678
https://github.com/chef/automate/issues/1679
https://github.com/chef/automate/issues/1705
fixes #1938 

### :+1: Definition of Done
Time is being displayed in UTC where labeled as such
- liscense lockoutcomponents
- node scan results and scan history
- compliance run results and drawer

### :athletic_shoe: How to Build and Test the Change
1. build components/automate-ui-devproxy && start_all_services

License Lockout modal
1. chef-automate dev psql chef_license_control_service -- -c "UPDATE licenses SET active=NULL" to remove the current license
2. Navigate to https://a2-dev.test/
3. Fill out the trial license form and submit
4. Observe the trial expiration modal

Node Details
1. Navigate to https://a2-dev.test/infrastructure/client-runs
2. Click on any of your nodes available in the list
3. View the Failure or Success Tag Timestamp in Bold Blue or Pink Div
4. View the Run Duration Time Stamp on Node Home
5. Click View Error Log to see Timestamp in Modal
6. Click on Run History button in top right to view sidebar -> view updated timestamp.

Node Credentials
1. Navigate to https://a2-dev.test/settings/node-credentials
2. Add a Credential
3. view timestamp in Last Modified column

Node Integrations
1. Navigate to https://a2-dev.test/settings/node-integrations
2. Create an Integration (follow instructions here - GCP was easiest)
3. View timestamp in date created column

API Tokens
1. Navigate to https://a2-dev.test/settings/tokens
2. Create a token
3. View timestamp in Created Date column

### :white_check_mark: Checklist

- [ ] Tests added/updated?
- [ ] Docs added/updated?

### :camera: Screenshots, if applicable

Patch:
diff --git a/components/automate-chef-io/content/docs/default-policies.md b/components/automate-chef-io/content/docs/default-policies.md
index 282781a15..3c75f3e02 100644
--- a/components/automate-chef-io/content/docs/default-policies.md
+++ b/components/automate-chef-io/content/docs/default-policies.md
@@ -43,6 +43,7 @@ the specific endpoints they protect.
 
 > Corresponds to "Client Runs" tab or `/nodes`
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 ConfigMgmt | GetNodes | /cfgmgmt/nodes | GET | cfgmgmt:nodes | read
@@ -61,6 +62,7 @@ JobScheduler | GetStatusJobScheduler | /retention/nodes/status | GET | cfgmgmt:s
 JobScheduler | ConfigureNodesMissingScheduler | /retention/nodes/missing-nodes/config | POST | cfgmgmt:scheduler:missing-node | configure
 JobScheduler | ConfigureDeleteNodesScheduler | /retention/nodes/delete-nodes/config | POST | cfgmgmt:scheduler:delete-node | configure
 JobScheduler | ConfigureMissingNodesForDeletionScheduler | /retention/nodes/missing-nodes-deletion/config | POST | cfgmgmt:scheduler:missing-nodes-deletion | configure
+{{% /responsive-table %}}
 
 ## Compliance
 
@@ -83,6 +85,7 @@ JobScheduler | ConfigureMissingNodesForDeletionScheduler | /retention/nodes/miss
 > Corresponds to "Compliance" tab (`/compliance/reporting/overview`), "Scan Jobs" tab
 (`/compliance/scanner/jobs`) & "Profiles" tab (`/profiles`)
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 ProfilesService | Read | /compliance/profiles/read/{owner}/{name}/version/{version} | GET | compliance:profiles:storage:{owner}:{name}:{version} | read
@@ -109,6 +112,7 @@ JobsService | Update | /compliance/scanner/jobs/id/{id} | PUT | compliance:scann
 JobsService | Delete | /compliance/scanner/jobs/id/{id} | DELETE | compliance:scanner:jobs:{id} | delete
 JobsService | List | /compliance/scanner/jobs/search | POST | compliance:scanner:jobs | search
 JobsService | Rerun | /compliance/scanner/jobs/rerun/id/{id} | GET | compliance:scanner:jobs:{id} | rerun
+{{% /responsive-table %}}
 
 ## Event Feed
 
@@ -137,12 +141,14 @@ JobsService | Rerun | /compliance/scanner/jobs/rerun/id/{id} | GET | compliance:
 
 > Corresponds to "Event Feed" tab (`/event-feed`)
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 EventFeed | GetEventFeed | /eventfeed | GET | events | read
 EventFeed | GetEventTypeCounts | /event_type_counts | GET | events:types | count
 EventFeed | GetEventTaskCounts | /event_task_counts | GET | events:tasks | count
 EventFeed | GetEventStringBuckets | /eventstrings | GET | events:strings | read
+{{% /responsive-table %}}
 
 ## Applications (BETA)
 
@@ -171,6 +177,7 @@ EventFeed | GetEventStringBuckets | /eventstrings | GET | events:strings | read
 
 > Corresponds to "Application tab (`/applications`)
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 Applications | GetServiceGroups | /beta/applications/service-groups | GET | service_groups | list
@@ -182,6 +189,7 @@ JobScheduler | GetDisconnectedServicesConfig          | /beta/retention/service_
 JobScheduler | UpdateDisconnectedServicesConfig       | /beta/retention/service_groups/disconnected_services/config        | POST | service_groups:scheduler:disconnected_services        | configure
 JobScheduler | GetDeleteDisconnectedServicesConfig    | /beta/retention/service_groups/delete_disconnected_services/config | GET  | service_groups:scheduler:delete_disconnected_services | read
 JobScheduler | UpdateDeleteDisconnectedServicesConfig | /beta/retention/service_groups/delete_disconnected_services/config | POST | service_groups:scheduler:delete_disconnected_services | configure
+{{% /responsive-table %}}
 
 ## Telemetry
 
@@ -203,9 +211,11 @@ JobScheduler | UpdateDeleteDisconnectedServicesConfig | /beta/retention/service_
 
 > Corresponds to Telemetry (`/telemetry`)
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 Telemetry | GetTelemetryConfiguration | /config | GET | telemetry:config | read
+{{% /responsive-table %}}
 
 ## Secrets
 
@@ -234,6 +244,7 @@ Telemetry | GetTelemetryConfiguration | /config | GET | telemetry:config | read
 
 > Corresponds to the "Credentials" tab or `/compliance/credentials`
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 SecretsService | Create | /secrets | POST | secrets | create
@@ -241,6 +252,7 @@ SecretsService | Read | /secrets/id/{id} | GET | secrets:{id} | read
 SecretsService | Update | /secrets/id/{id} | PATCH | secrets:{id} | update
 SecretsService | Delete | /secrets/id/{id} | DELETE | secrets:{id} | delete
 SecretsService | List | /secrets/search | POST | secrets | search
+{{% /responsive-table %}}
 
 ## Nodes
 
@@ -269,6 +281,7 @@ SecretsService | List | /secrets/search | POST | secrets | search
 
 > Corresponds to `/compliance/scanner/nodes`
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 NodesService | Create | /nodes | POST | nodes | create
@@ -277,6 +290,7 @@ NodesService | Update | /nodes/id/{id} | PUT | nodes:{id} | update
 NodesService | Delete | /nodes/id/{id} | DELETE | nodes:{id} | delete
 NodesService | List | /nodes/search | POST | nodes | list
 NodesService | Rerun | /nodes/rerun/id/{id} | GET | nodes:{id} | rerun
+{{% /responsive-table %}}
 
 ## Node Manager
 
@@ -303,6 +317,7 @@ NodesService | Rerun | /nodes/rerun/id/{id} | GET | nodes:{id} | rerun
 
 ### Node Manager Page
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 NodeManagerService | Create | /nodemanagers | POST | nodemanagers | create
@@ -312,6 +327,7 @@ NodeManagerService | Delete | /nodemanagers/id/{id} | DELETE | nodemanagers:{id}
 NodeManagerService | List | /nodemanagers/search | POST | nodemanagers | list
 NodeManagerService | SearchCloudProviderFields | /nodemanagers/id/{node_manager_id}/search-fields | POST | nodemanagers:{node_manager_id}:fields | search
 NodeManagerService | SearchCloudProviderNodes | /nodemanagers/id/{node_manager_id}/search-nodes | POST | nodemanagers:{node_manager_id}:nodes | search
+{{% /responsive-table %}}
 
 ## Ingest
 
@@ -337,6 +353,7 @@ NodeManagerService | SearchCloudProviderNodes | /nodemanagers/id/{node_manager_i
 
 > Corresponds to `/ingest/events`
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 ChefIngester | ProcessChefRun | /ingest/events/chef/run | POST | ingest:nodes:{entity_uuid}:runs | create
@@ -345,6 +362,7 @@ ChefIngester | ProcessNodeDelete | /ingest/events/chef/nodedelete | POST | inges
 ChefIngester | GetVersion | /ingest/version | GET | service_info:version | read
  |  |  |  |  |
 LegacyDataCollector | ProcessLegacyEvent | /events/data-collector | POST | ingest:unified_events | create
+{{% /responsive-table %}}
 
 ## Profile
 
@@ -376,10 +394,12 @@ LegacyDataCollector | ProcessLegacyEvent | /events/data-collector | POST | inges
 
 ### Profile Pages
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 UsersMgmt | GetUserByUsername | /auth/users/{username} | GET | auth:users:{username} | read
 UsersMgmt | UpdateSelf | /users/{username} | PUT | users:{username} | update
+{{% /responsive-table %}}
 
 ## Administrative
 
@@ -408,6 +428,7 @@ UsersMgmt | UpdateSelf | /users/{username} | PUT | users:{username} | update
 
 > Corresponds to the "Admin" (`/auth`) and "Notifications" tab (`/notifications`)
 
+{{% responsive-table %}}
 Service | Method | HTTP Endpoint | HTTP Method | Resource | Action
 ---|---|---|---|---|---
 TokensMgmt | GetTokens | /auth/tokens | GET | auth:api_tokens | read
@@ -448,3 +469,4 @@ Authorization | DeletePolicy | /auth/policies/{id} | DELETE | auth:policies:{id}
 Authorization | IntrospectAll | /auth/introspect | GET | auth_introspection:introspect_all | read
 Authorization | IntrospectSome | /auth/introspect_some | POST | auth_introspection:introspect_some | read
 Authorization | Introspect | /auth/introspect | POST | auth_introspection:introspect | read
+{{% /responsive-table %}}
diff --git a/components/automate-chef-io/data/docs/api_chef_automate/cfgmgmt/cfgmgmt.swagger.json b/components/automate-chef-io/data/docs/api_chef_automate/cfgmgmt/cfgmgmt.swagger.json
index 269dd8609..09b4123c3 100644
--- a/components/automate-chef-io/data/docs/api_chef_automate/cfgmgmt/cfgmgmt.swagger.json
+++ b/components/automate-chef-io/data/docs/api_chef_automate/cfgmgmt/cfgmgmt.swagger.json
@@ -735,6 +735,12 @@
         },
         "expanded_run_list": {
           "$ref": "#/definitions/chef.automate.api.cfgmgmt.response.ExpandedRunList"
+        },
+        "projects": {
+          "type": "array",
+          "items": {
+            "type": "string"
+          }
         }
       }
     },
diff --git a/components/automate-deployment/PORT_ALLOCATION.md b/components/automate-deployment/PORT_ALLOCATION.md
index 4f25f9f75..5d16d5a9d 100644
--- a/components/automate-deployment/PORT_ALLOCATION.md
+++ b/components/automate-deployment/PORT_ALLOCATION.md
@@ -6,79 +6,6 @@ Where possible we try to choose ports in the following range:
 
     10113-10162
 
-When adding a service, choose a port from those marked UNUSED in the
-list below.  Add the name of the service it will use used for. If
-appropriate, also add it to the list of ports to be checked in
+When adding a service, choose a port using the dev command:
 
-pkg/preflight/checks.go
-
-## Port Assignments
-
-```
-|  Port | Service/Use                  |
-|-------+------------------------------|
-|    80 | automate-load-balancer       |
-|   443 | automate-load-balancer       |
-|  2000 | automate-gateway             |
-|  2001 | automate-gateway             |
-|  5432 | automate-postgresql          |
-|  2192 | ingest-service               |
-|  9631 | hab-sup                      |
-|  9638 | hab-sup                      |
-| 10100 | pg-sidecar-service           |
-| 10113 | authn-service                |
-| 10114 | UNUSED (prev. authn-service) |
-| 10115 | session-service              |
-| 10116 | automate-dex                 |
-| 10117 | automate-dex                 |
-| 10118 | UNUSED                       |
-| 10119 | config-mgmt-service          |
-| 10120 | nodemanager-service          |
-| 10121 | compliance-service           |
-| 10122 | ingest-service               |
-| 10123 | es-sidecar-service           |
-| 10124 | license-control-service      |
-| 10125 | notifications-service        |
-| 10126 | UNUSED                       |
-| 10127 | local-user-service           |
-| 10128 | teams-service                |
-| 10129 | data-lifecycle-service       |
-| 10130 | authz-service                |
-| 10131 | secrets-service              |
-| 10132 | event-service                |
-| 10133 | applications-service         |
-| 10134 | UNUSED                       |
-| 10135 | UNUSED                       |
-| 10136 | UNUSED                       |
-| 10137 | UNUSED                       |
-| 10138 | UNUSED                       |
-| 10139 | UNUSED                       |
-| 10140 | NATS Server (event-service)  |
-| 10141 | automate-elasticsearch       |
-| 10142 | automate-elasticsearch       |
-| 10143 | backup-gateway               |
-| 10144 | automate-es-gateway          |
-| 10145 | automate-pg-gateway          |
-| 10146 | automate-pg-gateway          |
-| 10147 | UNUSED                       |
-| 10148 | UNUSED                       |
-| 10149 | UNUSED                       |
-| 10150 | UNUSED                       |
-| 10151 | UNUSED                       |
-| 10152 | UNUSED                       |
-| 10153 | UNUSED                       |
-| 10154 | UNUSED                       |
-| 10155 | UNUSED                       |
-| 10156 | UNUSED                       |
-| 10157 | UNUSED                       |
-| 10158 | UNUSED                       |
-| 10159 | UNUSED                       |
-| 10160 | automate-deployment          |
-| 10161 | automate-ui                  |
-| 10162 | authn-service                |
-| 10200 | automate-cs-nginx            |
-| 10201 | automate-cs-bookshelf        |
-| 10202 | automate-cs-oc-bifrost       |
-| 10203 | automate-cs-oc-erchef        |
-| 10204 | automate-cs-nginx            |
-```
+    chef-automate dev ports free
diff --git a/components/automate-deployment/pkg/client/deployer.go b/components/automate-deployment/pkg/client/deployer.go
index 2a5c02871..47be0011e 100644
--- a/components/automate-deployment/pkg/client/deployer.go
+++ b/components/automate-deployment/pkg/client/deployer.go
@@ -530,6 +530,7 @@ func (d *deployer) preflight(skipSharedPortCheck bool) {
 	preflightCheckOpts := preflight.DeployPreflightCheckOptions{
 		SkipSharedPortCheck: skipSharedPortCheck,
 		Airgap:              d.airgap,
+		AutomateConfig:      d.mergedCfg,
 	}
 
 	d.writer.Title("Beginning pre-flight checks")
diff --git a/components/automate-deployment/pkg/preflight/checks.go b/components/automate-deployment/pkg/preflight/checks.go
index f3fa76ca7..d5210b3ea 100644
--- a/components/automate-deployment/pkg/preflight/checks.go
+++ b/components/automate-deployment/pkg/preflight/checks.go
@@ -5,8 +5,13 @@ import (
 	"fmt"
 	"os"
 	"os/user"
+	"reflect"
 	"strings"
 
+	dc "github.com/chef/automate/api/config/deployment"
+	"github.com/chef/automate/components/automate-deployment/pkg/deployment"
+	"github.com/chef/automate/components/automate-deployment/pkg/habpkg"
+	"github.com/chef/automate/components/automate-grpc/protoc-gen-a2-config/api/a2conf"
 	"github.com/chef/automate/lib/proc"
 
 	"github.com/pkg/errors"
@@ -364,168 +369,69 @@ func ConnectivityCheck(urls []string) Check {
 	}
 }
 
-type PortToCheck struct {
-	Description string
-	Port        int
-	Shared      bool
+var a1MigratePorts = []uint16{80, 443, 2133, 2134, 5432}
+
+func skippablePort(port uint16) bool {
+	for _, p := range a1MigratePorts {
+		if p == port {
+			return true
+		}
+	}
+	return false
 }
 
-var defaultRequiredPorts = []PortToCheck{
-	{
-		Description: "automate-gateway HTTP",
-		Port:        2000,
-	},
-	{
-		Description: "automate-gateway GRPC",
-		Port:        2001,
-	},
-	{
-		Description: "ingest-service",
-		Port:        2192,
-	},
-	{
-		Description: "hab-sup HTTP",
-		Port:        9631,
-	},
-	{
-		Description: "hab-sup gossip",
-		Port:        9638,
-	},
-	{
-		Description: "pg-sidecar-service",
-		Port:        10100,
-	},
-	{
-		Description: "authn-service",
-		Port:        10113,
-	},
-	{
-		Description: "UNUSED",
-		Port:        10114,
-	},
-	{
-		Description: "session-service",
-		Port:        10115,
-	},
-	{
-		Description: "dex",
-		Port:        10116,
-	},
-	{
-		Description: "dex",
-		Port:        10117,
-	},
-	{
-		Description: "UNUSED",
-		Port:        10118,
-	},
-	{
-		Description: "config-mgmt-service",
-		Port:        10119,
-	},
-	{
-		Description: "nodemanager-service",
-		Port:        10120,
-	},
-	{
-		Description: "compliance-service",
-		Port:        10121,
-	},
-	{
-		Description: "ingest-service",
-		Port:        10122,
-	},
-	{
-		Description: "es-sidecar-service",
-		Port:        10123,
-	},
-	{
-		Description: "license-control-service",
-		Port:        10124,
-	},
-	{
-		Description: "notifications-service",
-		Port:        10125,
-	},
-	{
-		Description: "local-user-service",
-		Port:        10127,
-	},
-	{
-		Description: "teams-service",
-		Port:        10128,
-	},
-	{
-		Description: "secrets-service",
-		Port:        10131,
-	},
-	{
-		Description: "applications-service",
-		Port:        10133,
-	},
-	// TODO @afiune Uncomment once this is not a feature flag
-	//{
-	//Description: "event-service NATS",
-	//Port:        10140,
-	//},
-	// @afiune Why is the event-service not here?
-	// TODO: Add it to the checks!
-	{
-		Description: "elasticsearch",
-		Port:        10141,
-	},
-	{
-		Description: "elasticsearch",
-		Port:        10142,
-	},
-	{
-		Description: "UNUSED",
-		Port:        10159,
-	},
-	{
-		Description: "deployment-service",
-		Port:        10160,
-	},
-	{
-		Description: "automate-ui",
-		Port:        10161,
-	},
-	{
-		Description: "authn-service",
-		Port:        10162,
-	},
-	{
-		Description: "automate-load-balancer",
-		Port:        80,
-		Shared:      true,
-	},
-	{
-		Description: "automate-load-balancer",
-		Port:        443,
-		Shared:      true,
-	},
-	{
-		Description: "compliance-service",
-		Port:        2133,
-		Shared:      true,
-	},
-	{
-		Description: "compliance-service",
-		Port:        2134,
-		Shared:      true,
-	},
-	{
-		Description: "postgresql",
-		Port:        5432,
-		Shared:      true,
-	},
+func requiredPortsForConfig(skipShared bool, config *dc.AutomateConfig) ([]int, error) {
+	if config == nil {
+		config = dc.DefaultAutomateConfig()
+	}
+
+	servicesToCheck, err := deployment.ExpectedServiceIDsForConfig(config.GetDeployment())
+	if err != nil {
+		return nil, err
+	}
+	servicesToCheck = append(servicesToCheck, habpkg.New("chef", "deployment-service"))
+
+	portsToCheck := make([]int, 0, len(servicesToCheck)+8)
+	// Append habitat ports, currently hard coded nearly everywhere.
+	portsToCheck = append(portsToCheck, 9631, 9638)
+	acValue := reflect.ValueOf(*config)
+	for i := 0; i < acValue.NumField(); i++ {
+		if v, ok := acValue.Field(i).Interface().(a2conf.A2ServiceConfig); ok {
+			if hasServiceByName(servicesToCheck, v.ServiceName()) {
+				ports := v.ListPorts()
+				for _, p := range ports {
+					portVal, err := v.GetPort(p.Name)
+					if err != nil {
+						return nil, err
+					}
+					if portVal != 0 && !(skipShared && skippablePort(portVal)) {
+						portsToCheck = append(portsToCheck, int(portVal))
+					}
+				}
+			}
+		}
+	}
+	return portsToCheck, nil
 }
 
-func DefaultPortCheck(skipShared bool) Check {
-	return PortCheck(defaultRequiredPorts, skipShared)
+func hasServiceByName(c []habpkg.HabPkg, name string) bool {
+	for _, s := range c {
+		if s.Name() == name {
+			return true
+		}
+	}
+	return false
 }
 
-func PortCheck(portsToCheck []PortToCheck, skipShared bool) Check {
+func DefaultPortCheck(skipShared bool, config *dc.AutomateConfig) (Check, error) {
+	portsToCheck, err := requiredPortsForConfig(skipShared, config)
+	if err != nil {
+		return noopCheck, err
+	}
+	return PortCheck(portsToCheck), nil
+}
+
+func PortCheck(portsToCheck []int) Check {
 	return Check{
 		Name: "ports_free",
 		TestFunc: func(t TestProbe) error {
@@ -553,13 +459,9 @@ func PortCheck(portsToCheck []PortToCheck, skipShared bool) Check {
 
 			failed := false
 			for _, p := range portsToCheck {
-				if skipShared && p.Shared {
-					logrus.Debugf("skipping shared port check %s(%d)", p.Description, p.Port)
-					continue
-				}
-				if usedPorts[p.Port] {
+				if usedPorts[p] {
 					failed = true
-					t.ReportFailure(fmt.Sprintf("required port %d in use", p.Port))
+					t.ReportFailure(fmt.Sprintf("required port %d in use", p))
 				}
 			}
 
diff --git a/components/automate-deployment/pkg/preflight/preflight.go b/components/automate-deployment/pkg/preflight/preflight.go
index 4008584d5..77568a64b 100644
--- a/components/automate-deployment/pkg/preflight/preflight.go
+++ b/components/automate-deployment/pkg/preflight/preflight.go
@@ -2,6 +2,9 @@ package preflight
 
 import (
 	"github.com/pkg/errors"
+
+	"github.com/chef/automate/api/config/deployment"
+	dc "github.com/chef/automate/api/config/deployment"
 )
 
 type Check struct {
@@ -18,12 +21,14 @@ type DeployPreflightCheckOptions struct {
 	SkipSharedPortCheck bool
 	SkipA2DeployedCheck bool
 	Airgap              bool
+	AutomateConfig      *dc.AutomateConfig
 }
 
 type DeployPreflightChecker struct {
 	skipSharedPorts     bool
 	skipA2DeployedCheck bool
 	airgap              bool
+	automateConfig      *deployment.AutomateConfig
 }
 
 func NewDeployPreflightChecker(opts DeployPreflightCheckOptions) *DeployPreflightChecker {
@@ -31,11 +36,15 @@ func NewDeployPreflightChecker(opts DeployPreflightCheckOptions) *DeployPrefligh
 		skipSharedPorts:     opts.SkipSharedPortCheck,
 		skipA2DeployedCheck: opts.SkipA2DeployedCheck,
 		airgap:              opts.Airgap,
+		automateConfig:      opts.AutomateConfig,
 	}
 }
 
 func (c *DeployPreflightChecker) Run(probe TestProbe) error {
-	portCheck := DefaultPortCheck(c.skipSharedPorts)
+	portCheck, err := DefaultPortCheck(c.skipSharedPorts, c.automateConfig)
+	if err != nil {
+		return errors.Wrap(err, "failed to configure preflight checks")
+	}
 	isA2DeployedCheck := IsA2DeployedCheck(&portCheck)
 	chefAutomateInBinCheck := CLIInBin()
 	connectivityCheck := DefaultConnectivityCheck()
diff --git a/components/automate-ui/src/app/entities/license/license.model.ts b/components/automate-ui/src/app/entities/license/license.model.ts
index 0523d49c8..c0397dadb 100644
--- a/components/automate-ui/src/app/entities/license/license.model.ts
+++ b/components/automate-ui/src/app/entities/license/license.model.ts
@@ -53,5 +53,5 @@ export interface RequestLicenseResponse {
 }
 
 export function parsedExpirationDate(license: LicenseStatus): string {
-  return moment(license.licensed_period.end).format(DateTime.RFC2822);
+  return moment.utc(license.licensed_period.end).format(DateTime.RFC2822);
 }
diff --git a/components/automate-ui/src/app/page-components/json-tree/vendor/json-tree.js b/components/automate-ui/src/app/page-components/json-tree/vendor/json-tree.js
index 7e7291260..1f0ab81ed 100644
--- a/components/automate-ui/src/app/page-components/json-tree/vendor/json-tree.js
+++ b/components/automate-ui/src/app/page-components/json-tree/vendor/json-tree.js
@@ -372,6 +372,7 @@ var jsonTree = (function() {
               },
               childNodesUl,
               labelEl,
+              moreContentEl,
               childNodes = [];
   
           self.label = label;
diff --git a/components/automate-ui/src/app/page-components/run-history/run-history.component.ts b/components/automate-ui/src/app/page-components/run-history/run-history.component.ts
index 9f4cba9b1..dcb110fbb 100644
--- a/components/automate-ui/src/app/page-components/run-history/run-history.component.ts
+++ b/components/automate-ui/src/app/page-components/run-history/run-history.component.ts
@@ -102,20 +102,20 @@ export class RunHistoryComponent implements OnInit, OnDestroy {
 
   // returning US date format
   renderDate(datestamp) {
-    return moment(datestamp).format('MM/DD/YY');
+    return moment.utc(datestamp).format('MM/DD/YY');
   }
 
   renderTime(datestamp) {
-    return moment(datestamp).format('HH:mm:ss');
+    return moment.utc(datestamp).format('HH:mm:ss');
   }
 
   getDuration(start_time, end_time) {
-    return moment.duration(moment(end_time).diff(moment(start_time))).humanize();
+    return moment.duration(moment.utc(end_time).diff(moment.utc(start_time))).humanize();
   }
 
   onDownloadRunsReport() {
     const format = 'csv'; // or 'json'
-    const filename = `${moment().format('YYYY-M-D')}.${format}`;
+    const filename = `${moment.utc().format('YYYY-M-D')}.${format}`;
 
     const onComplete = () => console.warn('completed downloading report');
     const onError = _e => console.error('error downloading report');
@@ -176,7 +176,7 @@ export class RunHistoryComponent implements OnInit, OnDestroy {
   }
 
   private formatDate(dateString: string): string {
-    return moment(dateString).format('YYYY-MM-DD');
+    return moment.utc(dateString).format('YYYY-MM-DD');
   }
 
   updatePageNumber(pageNumber) {
diff --git a/components/automate-ui/src/app/pages/+compliance/+credentials/components/credentials-list-row.ts b/components/automate-ui/src/app/pages/+compliance/+credentials/components/credentials-list-row.ts
index 3dd0e7b22..8220128cc 100644
--- a/components/automate-ui/src/app/pages/+compliance/+credentials/components/credentials-list-row.ts
+++ b/components/automate-ui/src/app/pages/+compliance/+credentials/components/credentials-list-row.ts
@@ -22,7 +22,7 @@ export class CredentialsListRowComponent {
   }
 
   getLastModified(lastModifiedDate): string {
-    return moment(lastModifiedDate).format(DateTime.RFC2822);
+    return moment.utc(lastModifiedDate).format(DateTime.RFC2822);
   }
 
   public startCredentialDelete(): void {
diff --git a/components/automate-ui/src/app/pages/+compliance/+reporting/+reporting-overview/overview-trend/overview-trend.component.ts b/components/automate-ui/src/app/pages/+compliance/+reporting/+reporting-overview/overview-trend/overview-trend.component.ts
index 30904592d..2acb06573 100644
--- a/components/automate-ui/src/app/pages/+compliance/+reporting/+reporting-overview/overview-trend/overview-trend.component.ts
+++ b/components/automate-ui/src/app/pages/+compliance/+reporting/+reporting-overview/overview-trend/overview-trend.component.ts
@@ -155,8 +155,8 @@ export class OverviewTrendComponent implements OnChanges, OnDestroy  {
       .attr('y', this.vbHeight - 3)
       .text(() => {
         return [
-          moment(this.domainX[0]).format(DateTime.CHEF_DATE_TIME),
-          moment(this.domainX[1]).format(DateTime.CHEF_DATE_TIME)
+          moment.utc(this.domainX[0]).format(DateTime.CHEF_DATE_TIME),
+          moment.utc(this.domainX[1]).format(DateTime.CHEF_DATE_TIME)
         ].join(' - ');
       });
 
diff --git a/components/automate-ui/src/app/pipes/datetime.pipe.ts b/components/automate-ui/src/app/pipes/datetime.pipe.ts
index 456312ae2..cd6ccc788 100644
--- a/components/automate-ui/src/app/pipes/datetime.pipe.ts
+++ b/components/automate-ui/src/app/pipes/datetime.pipe.ts
@@ -12,7 +12,7 @@ import * as moment from 'moment';
 export class DatetimePipe implements PipeTransform {
 
   public transform(value: moment.Moment | string, formatStr: string): string {
-    const datetime = moment.isMoment(value) ? value : moment(value);
+    const datetime = moment.isMoment(value) ? value : moment.utc(value);
     return datetime.format(formatStr);
   }
 


Test patch:
diff --git a/components/automate-deployment/pkg/preflight/preflight_test.go b/components/automate-deployment/pkg/preflight/preflight_test.go
index 01acce52e..941d5197f 100644
--- a/components/automate-deployment/pkg/preflight/preflight_test.go
+++ b/components/automate-deployment/pkg/preflight/preflight_test.go
@@ -674,21 +674,8 @@ func TestConnectivityCheck(t *testing.T) {
 	})
 }
 
-func TestNetstatCheckNoSkipShared(t *testing.T) {
-	portsToCheck := []preflight.PortToCheck{
-		{
-			Description: "https",
-			Port:        443,
-			Shared:      true,
-		},
-		{
-			Description: "something",
-			Port:        10141,
-			Shared:      false,
-		},
-	}
-	check := preflight.PortCheck(portsToCheck, false)
-
+func TestNetstatCheck(t *testing.T) {
+	check := preflight.PortCheck([]int{10141})
 	t.Run("succeeds when ports are not used", func(t *testing.T) {
 		ipv4Txt := strings.TrimSpace(`
 sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
@@ -706,149 +693,7 @@ sl  local_address                         remote_address
 		probe.AssertSuccess()
 	})
 
-	t.Run("fails when shared port is used", func(t *testing.T) {
-		t.Run("when it's in ipv4", func(t *testing.T) {
-			ipv4Txt := strings.TrimSpace(`
-				sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				1: 00000000:01BB 00000000:0000 0A 00000000:00000000 00:00000000 00000000    42        0 9064307 1 0000000000000000 99 0 0 10 0
-				2: 7501A8C0:BB08 7501A8C0:2790 01 00000000:00000000 00:00000000 00000000    42        0 10309977 1 0000000000000000 20 3 31 10 -1`)
-			ipv6Txt := strings.TrimSpace(`
-				sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				0: 00000000000000000000000001000000:0277 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12089 1 0000000000000000 99 0 0 10 0
-				1: 00000000000000000000000000000000:0BB8 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000   988        0 15314 1 0000000000000000 99 0 0 10 0`)
-			probe := NewMockTestProbe(t)
-			probe.WithFileContents("/proc/net/tcp", []byte(ipv4Txt))
-			probe.WithFileContents("/proc/net/tcp6", []byte(ipv6Txt))
-			err := check.TestFunc(probe)
-			require.NoError(t, err)
-			// We don't report success for each port because that's the way it was when this code was bash
-			probe.AssertFailure()
-		})
-
-		t.Run("when it's ipv6", func(t *testing.T) {
-			ipv4Txt := strings.TrimSpace(`
-				sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				1: 00000000:2797 00000000:0000 0A 00000000:00000000 00:00000000 00000000    42        0 9064307 1 0000000000000000 99 0 0 10 0
-				2: 7501A8C0:BB08 7501A8C0:2790 01 00000000:00000000 00:00000000 00000000    42        0 10309977 1 0000000000000000 20 3 31 10 -1`)
-			ipv6Txt := strings.TrimSpace(`
-				sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				0: 00000000000000000000000001000000:01BB 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12089 1 0000000000000000 99 0 0 10 0
-				1: 00000000000000000000000000000000:0BB8 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000   988        0 15314 1 0000000000000000 99 0 0 10 0`)
-			probe := NewMockTestProbe(t)
-			probe.WithFileContents("/proc/net/tcp", []byte(ipv4Txt))
-			probe.WithFileContents("/proc/net/tcp6", []byte(ipv6Txt))
-			err := check.TestFunc(probe)
-			require.NoError(t, err)
-			probe.AssertFailure()
-		})
-	})
-
-	t.Run("fails when non shared port is used", func(t *testing.T) {
-		t.Run("when it's in ipv4", func(t *testing.T) {
-			ipv4Txt := strings.TrimSpace(`
-				sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				1: 00000000:279D 00000000:0000 0A 00000000:00000000 00:00000000 00000000    42        0 9064307 1 0000000000000000 99 0 0 10 0
-				2: 7501A8C0:BB08 7501A8C0:2790 01 00000000:00000000 00:00000000 00000000    42        0 10309977 1 0000000000000000 20 3 31 10 -1`)
-			ipv6Txt := strings.TrimSpace(`
-				sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				0: 00000000000000000000000001000000:0277 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12089 1 0000000000000000 99 0 0 10 0
-				1: 00000000000000000000000000000000:0BB8 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000   988        0 15314 1 0000000000000000 99 0 0 10 0`)
-			probe := NewMockTestProbe(t)
-			probe.WithFileContents("/proc/net/tcp", []byte(ipv4Txt))
-			probe.WithFileContents("/proc/net/tcp6", []byte(ipv6Txt))
-			err := check.TestFunc(probe)
-			require.NoError(t, err)
-			probe.AssertFailure()
-		})
-
-		t.Run("when it's ipv6", func(t *testing.T) {
-			ipv4Txt := strings.TrimSpace(`
-				sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				1: 00000000:2797 00000000:0000 0A 00000000:00000000 00:00000000 00000000    42        0 9064307 1 0000000000000000 99 0 0 10 0
-				2: 7501A8C0:BB08 7501A8C0:2790 01 00000000:00000000 00:00000000 00000000    42        0 10309977 1 0000000000000000 20 3 31 10 -1`)
-			ipv6Txt := strings.TrimSpace(`
-				sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				0: 00000000000000000000000001000000:279D 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12089 1 0000000000000000 99 0 0 10 0
-				1: 00000000000000000000000000000000:0BB8 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000   988        0 15314 1 0000000000000000 99 0 0 10 0`)
-			probe := NewMockTestProbe(t)
-			probe.WithFileContents("/proc/net/tcp", []byte(ipv4Txt))
-			probe.WithFileContents("/proc/net/tcp6", []byte(ipv6Txt))
-			err := check.TestFunc(probe)
-			require.NoError(t, err)
-			probe.AssertFailure()
-		})
-	})
-}
-
-func TestNetstatCheckSkipShared(t *testing.T) {
-	portsToCheck := []preflight.PortToCheck{
-		{
-			Description: "https",
-			Port:        443,
-			Shared:      true,
-		},
-		{
-			Description: "something",
-			Port:        10141,
-			Shared:      false,
-		},
-	}
-	check := preflight.PortCheck(portsToCheck, true)
-
-	t.Run("succeeds when ports are not used", func(t *testing.T) {
-		ipv4Txt := strings.TrimSpace(`
-sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-1: 00000000:2797 00000000:0000 0A 00000000:00000000 00:00000000 00000000    42        0 9064307 1 0000000000000000 99 0 0 10 0
-2: 7501A8C0:BB08 7501A8C0:2790 01 00000000:00000000 00:00000000 00000000    42        0 10309977 1 0000000000000000 20 3 31 10 -1`)
-		ipv6Txt := strings.TrimSpace(`
-sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-0: 00000000000000000000000001000000:0277 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12089 1 0000000000000000 99 0 0 10 0
-1: 00000000000000000000000000000000:0BB8 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000   988        0 15314 1 0000000000000000 99 0 0 10 0`)
-		probe := NewMockTestProbe(t)
-		probe.WithFileContents("/proc/net/tcp", []byte(ipv4Txt))
-		probe.WithFileContents("/proc/net/tcp6", []byte(ipv6Txt))
-		err := check.TestFunc(probe)
-		require.NoError(t, err)
-		probe.AssertSuccess()
-	})
-
-	t.Run("succeeds when shared port is used", func(t *testing.T) {
-		t.Run("when it's in ipv4", func(t *testing.T) {
-			ipv4Txt := strings.TrimSpace(`
-				sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				1: 00000000:01BB 00000000:0000 0A 00000000:00000000 00:00000000 00000000    42        0 9064307 1 0000000000000000 99 0 0 10 0
-				2: 7501A8C0:BB08 7501A8C0:2790 01 00000000:00000000 00:00000000 00000000    42        0 10309977 1 0000000000000000 20 3 31 10 -1`)
-			ipv6Txt := strings.TrimSpace(`
-				sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				0: 00000000000000000000000001000000:0277 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12089 1 0000000000000000 99 0 0 10 0
-				1: 00000000000000000000000000000000:0BB8 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000   988        0 15314 1 0000000000000000 99 0 0 10 0`)
-			probe := NewMockTestProbe(t)
-			probe.WithFileContents("/proc/net/tcp", []byte(ipv4Txt))
-			probe.WithFileContents("/proc/net/tcp6", []byte(ipv6Txt))
-			err := check.TestFunc(probe)
-			require.NoError(t, err)
-			probe.AssertSuccess()
-		})
-
-		t.Run("when it's ipv6", func(t *testing.T) {
-			ipv4Txt := strings.TrimSpace(`
-				sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				1: 00000000:2797 00000000:0000 0A 00000000:00000000 00:00000000 00000000    42        0 9064307 1 0000000000000000 99 0 0 10 0
-				2: 7501A8C0:BB08 7501A8C0:2790 01 00000000:00000000 00:00000000 00000000    42        0 10309977 1 0000000000000000 20 3 31 10 -1`)
-			ipv6Txt := strings.TrimSpace(`
-				sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
-				0: 00000000000000000000000001000000:01BB 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12089 1 0000000000000000 99 0 0 10 0
-				1: 00000000000000000000000000000000:0BB8 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000   988        0 15314 1 0000000000000000 99 0 0 10 0`)
-			probe := NewMockTestProbe(t)
-			probe.WithFileContents("/proc/net/tcp", []byte(ipv4Txt))
-			probe.WithFileContents("/proc/net/tcp6", []byte(ipv6Txt))
-			err := check.TestFunc(probe)
-			require.NoError(t, err)
-			probe.AssertSuccess()
-		})
-	})
-
-	t.Run("fails when non shared port is used", func(t *testing.T) {
+	t.Run("fails port is used", func(t *testing.T) {
 		t.Run("when it's in ipv4", func(t *testing.T) {
 			ipv4Txt := strings.TrimSpace(`
 				sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode