Repository: replicatedhq/kots
Pull request #258 (2020-01-12 21:47:30)

refactor to move kotsadm DeployOptions and UpgradeOptions types into subpackage


Patch:
diff --git a/cmd/kots/cli/admin-console-upgrade.go b/cmd/kots/cli/admin-console-upgrade.go
index 94950e3fa..cb805ba05 100644
--- a/cmd/kots/cli/admin-console-upgrade.go
+++ b/cmd/kots/cli/admin-console-upgrade.go
@@ -2,7 +2,9 @@ package cli
 
 import (
 	"github.com/pkg/errors"
+
 	"github.com/replicatedhq/kots/pkg/kotsadm"
+	kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"github.com/replicatedhq/kots/pkg/logger"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
@@ -21,7 +23,7 @@ func AdminConsoleUpgradeCmd() *cobra.Command {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			v := viper.GetViper()
 
-			upgradeOptions := kotsadm.UpgradeOptions{
+			upgradeOptions := kotsadmtypes.UpgradeOptions{
 				Namespace:  v.GetString("namespace"),
 				Kubeconfig: v.GetString("kubeconfig"),
 			}
diff --git a/cmd/kots/cli/install.go b/cmd/kots/cli/install.go
index cbe622896..d8cb62b2d 100644
--- a/cmd/kots/cli/install.go
+++ b/cmd/kots/cli/install.go
@@ -15,6 +15,7 @@ import (
 	"github.com/replicatedhq/kots/pkg/docker/registry"
 	"github.com/replicatedhq/kots/pkg/k8sutil"
 	"github.com/replicatedhq/kots/pkg/kotsadm"
+	kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"github.com/replicatedhq/kots/pkg/logger"
 	"github.com/replicatedhq/kots/pkg/pull"
 	"github.com/replicatedhq/kots/pkg/upload"
@@ -113,7 +114,7 @@ func InstallCmd() *cobra.Command {
 					return errors.Wrap(err, "failed to pull app metadata")
 				}
 
-				deployOptions := kotsadm.DeployOptions{
+				deployOptions := kotsadmtypes.DeployOptions{
 					Namespace:           namespace,
 					Kubeconfig:          v.GetString("kubeconfig"),
 					Context:             v.GetString("context"),
diff --git a/pkg/k8sutil/config.go b/pkg/k8sutil/config.go
index 2f106c828..5e518f5a8 100644
--- a/pkg/k8sutil/config.go
+++ b/pkg/k8sutil/config.go
@@ -2,14 +2,13 @@ package k8sutil
 
 import (
 	"github.com/pkg/errors"
+	kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types"
 	authorizationv1 "k8s.io/api/authorization/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	"k8s.io/client-go/kubernetes"
-
-	"github.com/replicatedhq/kots/pkg/kotsadm"
 )
 
-func GetCurrentRules(deployOptions kotsadm.DeployOptions, clientset *kubernetes.Clientset) ([]rbacv1.PolicyRule, error) {
+func GetCurrentRules(deployOptions kotsadmtypes.DeployOptions, clientset *kubernetes.Clientset) ([]rbacv1.PolicyRule, error) {
 	sar := &authorizationv1.SelfSubjectRulesReview{
 		Spec: authorizationv1.SelfSubjectRulesReviewSpec{
 			Namespace: deployOptions.Namespace,
diff --git a/pkg/kotsadm/api.go b/pkg/kotsadm/api.go
index e0612cf2f..ff01b19a0 100644
--- a/pkg/kotsadm/api.go
+++ b/pkg/kotsadm/api.go
@@ -5,6 +5,7 @@ import (
 	"time"
 
 	"github.com/pkg/errors"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	corev1 "k8s.io/api/core/v1"
 	kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -15,7 +16,7 @@ import (
 
 var timeoutWaitingForAPI = time.Duration(time.Minute * 2)
 
-func getApiYAML(deployOptions DeployOptions) (map[string][]byte, error) {
+func getApiYAML(deployOptions types.DeployOptions) (map[string][]byte, error) {
 	docs := map[string][]byte{}
 	s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)
 
@@ -52,7 +53,7 @@ func getApiYAML(deployOptions DeployOptions) (map[string][]byte, error) {
 	return docs, nil
 }
 
-func waitForAPI(deployOptions *DeployOptions, clientset *kubernetes.Clientset) error {
+func waitForAPI(deployOptions *types.DeployOptions, clientset *kubernetes.Clientset) error {
 	start := time.Now()
 
 	for {
@@ -77,7 +78,7 @@ func waitForAPI(deployOptions *DeployOptions, clientset *kubernetes.Clientset) e
 	}
 }
 
-func ensureAPI(deployOptions *DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureAPI(deployOptions *types.DeployOptions, clientset *kubernetes.Clientset) error {
 	if err := ensureApiRBAC(deployOptions.Namespace, clientset); err != nil {
 		return errors.Wrap(err, "failed to ensure api rbac")
 	}
@@ -160,7 +161,7 @@ func ensureApiServiceAccount(namespace string, clientset *kubernetes.Clientset)
 	return nil
 }
 
-func ensureAPIDeployment(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureAPIDeployment(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.AppsV1().Deployments(deployOptions.Namespace).Get("kotsadm-api", metav1.GetOptions{})
 	if err != nil {
 		if !kuberneteserrors.IsNotFound(err) {
diff --git a/pkg/kotsadm/api_objects.go b/pkg/kotsadm/api_objects.go
index 5e650ff5b..8a013812d 100644
--- a/pkg/kotsadm/api_objects.go
+++ b/pkg/kotsadm/api_objects.go
@@ -3,13 +3,13 @@ package kotsadm
 import (
 	"fmt"
 
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
+	"github.com/replicatedhq/kots/pkg/util"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
-
-	"github.com/replicatedhq/kots/pkg/util"
 )
 
 func apiRole(namespace string) *rbacv1.Role {
@@ -94,7 +94,7 @@ func apiServiceAccount(namespace string) *corev1.ServiceAccount {
 	return serviceAccount
 }
 
-func apiDeployment(deployOptions DeployOptions) *appsv1.Deployment {
+func apiDeployment(deployOptions types.DeployOptions) *appsv1.Deployment {
 	var securityContext corev1.PodSecurityContext
 	if !deployOptions.IsOpenShift {
 		securityContext = corev1.PodSecurityContext{
diff --git a/pkg/kotsadm/application_metadata.go b/pkg/kotsadm/application_metadata.go
index 0f2c62041..70d5cc580 100644
--- a/pkg/kotsadm/application_metadata.go
+++ b/pkg/kotsadm/application_metadata.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 
 	"github.com/pkg/errors"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/serializer/json"
@@ -24,7 +25,7 @@ func getApplicationMetadataYAML(data []byte, namespace string) (map[string][]byt
 	return docs, nil
 }
 
-func ensureApplicationMetadata(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureApplicationMetadata(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.CoreV1().ConfigMaps(deployOptions.Namespace).Get("kotsadm-application-metadata", metav1.GetOptions{})
 	if err != nil {
 		if !kuberneteserrors.IsNotFound(err) {
diff --git a/pkg/kotsadm/kotsadm.go b/pkg/kotsadm/kotsadm.go
index b0cf85e32..2f340baa2 100644
--- a/pkg/kotsadm/kotsadm.go
+++ b/pkg/kotsadm/kotsadm.go
@@ -3,6 +3,7 @@ package kotsadm
 import (
 	"github.com/google/uuid"
 	"github.com/pkg/errors"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"github.com/replicatedhq/kots/pkg/logger"
 	corev1 "k8s.io/api/core/v1"
 	kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
@@ -11,35 +12,8 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client/config"
 )
 
-type DeployOptions struct {
-	Namespace              string
-	Kubeconfig             string
-	Context                string
-	IncludeShip            bool
-	IncludeGitHub          bool
-	SharedPassword         string
-	SharedPasswordBcrypt   string
-	S3AccessKey            string
-	S3SecretKey            string
-	JWT                    string
-	PostgresPassword       string
-	APIEncryptionKey       string
-	AutoCreateClusterToken string
-	ServiceType            string
-	NodePort               int32
-	Hostname               string
-	ApplicationMetadata    []byte
-	LimitRange             *corev1.LimitRange
-	IsOpenShift            bool // true if the application is being deployed to an OpenShift cluster
-}
-
-type UpgradeOptions struct {
-	Namespace  string
-	Kubeconfig string
-}
-
 // YAML will return a map containing the YAML needed to run the admin console
-func YAML(deployOptions DeployOptions) (map[string][]byte, error) {
+func YAML(deployOptions types.DeployOptions) (map[string][]byte, error) {
 	docs := map[string][]byte{}
 
 	if deployOptions.ApplicationMetadata != nil {
@@ -115,7 +89,7 @@ func YAML(deployOptions DeployOptions) (map[string][]byte, error) {
 	return docs, nil
 }
 
-func Upgrade(upgradeOptions UpgradeOptions) error {
+func Upgrade(upgradeOptions types.UpgradeOptions) error {
 	cfg, err := config.GetConfig()
 	if err != nil {
 		return errors.Wrap(err, "failed to get cluster config")
@@ -147,7 +121,7 @@ func Upgrade(upgradeOptions UpgradeOptions) error {
 	return nil
 }
 
-func Deploy(deployOptions DeployOptions) error {
+func Deploy(deployOptions types.DeployOptions) error {
 	cfg, err := config.GetConfig()
 	if err != nil {
 		return errors.Wrap(err, "failed to get cluster config")
@@ -200,7 +174,7 @@ func Deploy(deployOptions DeployOptions) error {
 	return nil
 }
 
-func ensureKotsadm(deployOptions DeployOptions, clientset *kubernetes.Clientset, log *logger.Logger) error {
+func ensureKotsadm(deployOptions types.DeployOptions, clientset *kubernetes.Clientset, log *logger.Logger) error {
 	if err := ensureMinio(deployOptions, clientset); err != nil {
 		return errors.Wrap(err, "failed to ensure minio")
 	}
@@ -238,8 +212,8 @@ func ensureKotsadm(deployOptions DeployOptions, clientset *kubernetes.Clientset,
 	return nil
 }
 
-func readDeployOptionsFromCluster(namespace string, kubeconfig string, clientset *kubernetes.Clientset) (*DeployOptions, error) {
-	deployOptions := DeployOptions{
+func readDeployOptionsFromCluster(namespace string, kubeconfig string, clientset *kubernetes.Clientset) (*types.DeployOptions, error) {
+	deployOptions := types.DeployOptions{
 		Namespace:     namespace,
 		Kubeconfig:    kubeconfig,
 		IncludeShip:   false,
diff --git a/pkg/kotsadm/minio.go b/pkg/kotsadm/minio.go
index 681e22beb..95507ecae 100644
--- a/pkg/kotsadm/minio.go
+++ b/pkg/kotsadm/minio.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 
 	"github.com/pkg/errors"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/serializer/json"
@@ -11,7 +12,7 @@ import (
 	"k8s.io/client-go/kubernetes/scheme"
 )
 
-func getMinioYAML(deployOptions DeployOptions) (map[string][]byte, error) {
+func getMinioYAML(deployOptions types.DeployOptions) (map[string][]byte, error) {
 	docs := map[string][]byte{}
 	s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)
 
@@ -30,7 +31,7 @@ func getMinioYAML(deployOptions DeployOptions) (map[string][]byte, error) {
 	return docs, nil
 }
 
-func ensureMinio(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureMinio(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	if err := ensureS3Secret(deployOptions.Namespace, clientset); err != nil {
 		return errors.Wrap(err, "failed to ensure minio secret")
 	}
@@ -46,7 +47,7 @@ func ensureMinio(deployOptions DeployOptions, clientset *kubernetes.Clientset) e
 	return nil
 }
 
-func ensureMinioStatefulset(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureMinioStatefulset(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.AppsV1().StatefulSets(deployOptions.Namespace).Get("kotsadm-minio", metav1.GetOptions{})
 	if err != nil {
 		if !kuberneteserrors.IsNotFound(err) {
diff --git a/pkg/kotsadm/minio_objects.go b/pkg/kotsadm/minio_objects.go
index 9a91d5da6..20ae249e6 100644
--- a/pkg/kotsadm/minio_objects.go
+++ b/pkg/kotsadm/minio_objects.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"os"
 
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"github.com/replicatedhq/kots/pkg/util"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
@@ -12,7 +13,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/intstr"
 )
 
-func minioStatefulset(deployOptions DeployOptions) *appsv1.StatefulSet {
+func minioStatefulset(deployOptions types.DeployOptions) *appsv1.StatefulSet {
 	size := resource.MustParse("4Gi")
 
 	if deployOptions.LimitRange != nil {
diff --git a/pkg/kotsadm/operator.go b/pkg/kotsadm/operator.go
index c6275f2d4..a33c2b7bf 100644
--- a/pkg/kotsadm/operator.go
+++ b/pkg/kotsadm/operator.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/pkg/errors"
 	"github.com/replicatedhq/kots/pkg/k8sutil"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	rbacv1 "k8s.io/api/rbac/v1"
 	kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -21,7 +22,7 @@ const (
 	Namespace = "namespace"
 )
 
-func getOperatorYAML(deployOptions DeployOptions) (map[string][]byte, error) {
+func getOperatorYAML(deployOptions types.DeployOptions) (map[string][]byte, error) {
 	docs := map[string][]byte{}
 	s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)
 
@@ -52,7 +53,7 @@ func getOperatorYAML(deployOptions DeployOptions) (map[string][]byte, error) {
 	return docs, nil
 }
 
-func ensureOperator(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureOperator(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	rules, err := k8sutil.GetCurrentRules(deployOptions, clientset)
 	if err != nil {
 		return errors.Wrap(err, "failed to get current rules")
@@ -178,7 +179,7 @@ func ensureOperatorServiceAccount(namespace string, clientset *kubernetes.Client
 	return nil
 }
 
-func ensureOperatorDeployment(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureOperatorDeployment(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.AppsV1().Deployments(deployOptions.Namespace).Get("kotsadm-operator", metav1.GetOptions{})
 	if err != nil {
 		if !kuberneteserrors.IsNotFound(err) {
diff --git a/pkg/kotsadm/operator_objects.go b/pkg/kotsadm/operator_objects.go
index 22f7bf565..ac70de5f6 100644
--- a/pkg/kotsadm/operator_objects.go
+++ b/pkg/kotsadm/operator_objects.go
@@ -3,12 +3,12 @@ package kotsadm
 import (
 	"fmt"
 
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
+	"github.com/replicatedhq/kots/pkg/util"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	"github.com/replicatedhq/kots/pkg/util"
 )
 
 func operatorClusterRole(namespace string) *rbacv1.ClusterRole {
@@ -124,7 +124,7 @@ func operatorServiceAccount(namespace string) *corev1.ServiceAccount {
 	return serviceAccount
 }
 
-func operatorDeployment(deployOptions DeployOptions) *appsv1.Deployment {
+func operatorDeployment(deployOptions types.DeployOptions) *appsv1.Deployment {
 	var securityContext corev1.PodSecurityContext
 	if !deployOptions.IsOpenShift {
 		securityContext = corev1.PodSecurityContext{
diff --git a/pkg/kotsadm/postgres.go b/pkg/kotsadm/postgres.go
index 02a7de3bd..e7f956423 100644
--- a/pkg/kotsadm/postgres.go
+++ b/pkg/kotsadm/postgres.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/google/uuid"
 	"github.com/pkg/errors"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/serializer/json"
@@ -12,7 +13,7 @@ import (
 	"k8s.io/client-go/kubernetes/scheme"
 )
 
-func getPostgresYAML(deployOptions DeployOptions) (map[string][]byte, error) {
+func getPostgresYAML(deployOptions types.DeployOptions) (map[string][]byte, error) {
 	docs := map[string][]byte{}
 	s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)
 
@@ -34,7 +35,7 @@ func getPostgresYAML(deployOptions DeployOptions) (map[string][]byte, error) {
 	return docs, nil
 }
 
-func ensurePostgres(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensurePostgres(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	if err := ensurePostgresSecret(deployOptions, clientset); err != nil {
 		return errors.Wrap(err, "failed to ensure postgres secret")
 	}
@@ -50,7 +51,7 @@ func ensurePostgres(deployOptions DeployOptions, clientset *kubernetes.Clientset
 	return nil
 }
 
-func ensurePostgresStatefulset(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensurePostgresStatefulset(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.AppsV1().StatefulSets(deployOptions.Namespace).Get("kotsadm-postgres", metav1.GetOptions{})
 	if err != nil {
 		if !kuberneteserrors.IsNotFound(err) {
diff --git a/pkg/kotsadm/postgres_objects.go b/pkg/kotsadm/postgres_objects.go
index e959c0048..e5682b89f 100644
--- a/pkg/kotsadm/postgres_objects.go
+++ b/pkg/kotsadm/postgres_objects.go
@@ -3,16 +3,16 @@ package kotsadm
 import (
 	"os"
 
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
+	"github.com/replicatedhq/kots/pkg/util"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
-
-	"github.com/replicatedhq/kots/pkg/util"
 )
 
-func postgresStatefulset(deployOptions DeployOptions) *appsv1.StatefulSet {
+func postgresStatefulset(deployOptions types.DeployOptions) *appsv1.StatefulSet {
 	size := resource.MustParse("1Gi")
 
 	if deployOptions.LimitRange != nil {
diff --git a/pkg/kotsadm/schemahero.go b/pkg/kotsadm/schemahero.go
index c0f020946..7e3fd5519 100644
--- a/pkg/kotsadm/schemahero.go
+++ b/pkg/kotsadm/schemahero.go
@@ -5,6 +5,7 @@ import (
 	"time"
 
 	"github.com/pkg/errors"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"github.com/replicatedhq/kots/pkg/logger"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -13,7 +14,7 @@ import (
 	"k8s.io/client-go/kubernetes/scheme"
 )
 
-func getMigrationsYAML(deployOptions DeployOptions) (map[string][]byte, error) {
+func getMigrationsYAML(deployOptions types.DeployOptions) (map[string][]byte, error) {
 	docs := map[string][]byte{}
 	s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)
 
@@ -26,7 +27,7 @@ func getMigrationsYAML(deployOptions DeployOptions) (map[string][]byte, error) {
 	return docs, nil
 }
 
-func runSchemaHeroMigrations(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func runSchemaHeroMigrations(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	// we don't deploy the operator because that would require too high of
 	// a priv. so we just deploy database migrations here, at deployment time
 
@@ -70,7 +71,7 @@ func waitForHealthyPostgres(namespace string, clientset *kubernetes.Clientset) (
 	}
 }
 
-func createSchemaHeroPod(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func createSchemaHeroPod(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.CoreV1().Pods(deployOptions.Namespace).Create(migrationsPod(deployOptions))
 	if err != nil {
 		return errors.Wrap(err, "failed to create pod")
diff --git a/pkg/kotsadm/schemahero_objects.go b/pkg/kotsadm/schemahero_objects.go
index f3811752e..151d9a1d8 100644
--- a/pkg/kotsadm/schemahero_objects.go
+++ b/pkg/kotsadm/schemahero_objects.go
@@ -4,13 +4,13 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
+	"github.com/replicatedhq/kots/pkg/util"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	"github.com/replicatedhq/kots/pkg/util"
 )
 
-func migrationsPod(deployOptions DeployOptions) *corev1.Pod {
+func migrationsPod(deployOptions types.DeployOptions) *corev1.Pod {
 	name := fmt.Sprintf("kotsadm-migrations-%d", time.Now().Unix())
 
 	var securityContext corev1.PodSecurityContext
diff --git a/pkg/kotsadm/secrets.go b/pkg/kotsadm/secrets.go
index 8f3b1a79a..3b1563f3b 100644
--- a/pkg/kotsadm/secrets.go
+++ b/pkg/kotsadm/secrets.go
@@ -8,6 +8,7 @@ import (
 	"github.com/manifoldco/promptui"
 	"github.com/pkg/errors"
 	"github.com/replicatedhq/kots/pkg/crypto"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"golang.org/x/crypto/bcrypt"
 	corev1 "k8s.io/api/core/v1"
 	kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
@@ -17,7 +18,7 @@ import (
 	"k8s.io/client-go/kubernetes/scheme"
 )
 
-func getSecretsYAML(deployOptions *DeployOptions) (map[string][]byte, error) {
+func getSecretsYAML(deployOptions *types.DeployOptions) (map[string][]byte, error) {
 	docs := map[string][]byte{}
 	s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)
 
@@ -74,7 +75,7 @@ func getSecretsYAML(deployOptions *DeployOptions) (map[string][]byte, error) {
 	return docs, nil
 }
 
-func ensureSecrets(deployOptions *DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureSecrets(deployOptions *types.DeployOptions, clientset *kubernetes.Clientset) error {
 	if err := ensureJWTSessionSecret(deployOptions.Namespace, clientset); err != nil {
 		return errors.Wrap(err, "failed to ensure jwt session secret")
 	}
@@ -171,7 +172,7 @@ func getPostgresSecret(namespace string, clientset *kubernetes.Clientset) (*core
 	return pgSecret, nil
 }
 
-func ensurePostgresSecret(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensurePostgresSecret(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	existingPgSecret, err := getPostgresSecret(deployOptions.Namespace, clientset)
 	if err != nil {
 		return errors.Wrap(err, "failed to check for existing postgres secret")
@@ -200,7 +201,7 @@ func getSharedPasswordSecret(namespace string, clientset *kubernetes.Clientset)
 	return sharedPasswordSecret, nil
 }
 
-func ensureSharedPasswordSecret(deployOptions *DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureSharedPasswordSecret(deployOptions *types.DeployOptions, clientset *kubernetes.Clientset) error {
 	if deployOptions.SharedPassword == "" {
 		sharedPassword, err := promptForSharedPassword()
 		if err != nil {
@@ -266,7 +267,7 @@ func promptForSharedPassword() (string, error) {
 
 }
 
-func ensureAPIEncryptionSecret(deployOptions *DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureAPIEncryptionSecret(deployOptions *types.DeployOptions, clientset *kubernetes.Clientset) error {
 	secret, err := getAPIEncryptionSecret(deployOptions.Namespace, clientset)
 	if err != nil {
 		return errors.Wrap(err, "failed to check for existing postgres secret")
diff --git a/pkg/kotsadm/types/deployoptions.go b/pkg/kotsadm/types/deployoptions.go
new file mode 100644
index 000000000..83fd7a14c
--- /dev/null
+++ b/pkg/kotsadm/types/deployoptions.go
@@ -0,0 +1,27 @@
+package types
+
+import (
+	"k8s.io/api/core/v1"
+)
+
+type DeployOptions struct {
+	Namespace              string
+	Kubeconfig             string
+	Context                string
+	IncludeShip            bool
+	IncludeGitHub          bool
+	SharedPassword         string
+	SharedPasswordBcrypt   string
+	S3AccessKey            string
+	S3SecretKey            string
+	JWT                    string
+	PostgresPassword       string
+	APIEncryptionKey       string
+	AutoCreateClusterToken string
+	ServiceType            string
+	NodePort               int32
+	Hostname               string
+	ApplicationMetadata    []byte
+	LimitRange             *v1.LimitRange
+	IsOpenShift            bool // true if the application is being deployed to an OpenShift cluster
+}
diff --git a/pkg/kotsadm/types/upgradeoptions.go b/pkg/kotsadm/types/upgradeoptions.go
new file mode 100644
index 000000000..873b3b000
--- /dev/null
+++ b/pkg/kotsadm/types/upgradeoptions.go
@@ -0,0 +1,6 @@
+package types
+
+type UpgradeOptions struct {
+	Namespace  string
+	Kubeconfig string
+}
diff --git a/pkg/kotsadm/web.go b/pkg/kotsadm/web.go
index 988ac8eb3..d378ec8e5 100644
--- a/pkg/kotsadm/web.go
+++ b/pkg/kotsadm/web.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/manifoldco/promptui"
 	"github.com/pkg/errors"
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/serializer/json"
@@ -20,7 +21,7 @@ var (
 	executableMode = int32(511) // hex 777
 )
 
-func getWebYAML(deployOptions DeployOptions) (map[string][]byte, error) {
+func getWebYAML(deployOptions types.DeployOptions) (map[string][]byte, error) {
 	docs := map[string][]byte{}
 	s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)
 
@@ -45,7 +46,7 @@ func getWebYAML(deployOptions DeployOptions) (map[string][]byte, error) {
 	return docs, nil
 }
 
-func ensureWeb(deployOptions *DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureWeb(deployOptions *types.DeployOptions, clientset *kubernetes.Clientset) error {
 	if deployOptions.Hostname == "" {
 		hostname, err := promptForHostname()
 		if err != nil {
@@ -79,7 +80,7 @@ func ensureWeb(deployOptions *DeployOptions, clientset *kubernetes.Clientset) er
 	return nil
 }
 
-func ensureWebConfig(deployOptions *DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureWebConfig(deployOptions *types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.CoreV1().ConfigMaps(deployOptions.Namespace).Get("kotsadm-web-scripts", metav1.GetOptions{})
 	if err != nil {
 		if !kuberneteserrors.IsNotFound(err) {
@@ -95,7 +96,7 @@ func ensureWebConfig(deployOptions *DeployOptions, clientset *kubernetes.Clients
 	return nil
 }
 
-func ensureWebDeployment(deployOptions DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureWebDeployment(deployOptions types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.AppsV1().Deployments(deployOptions.Namespace).Get("kotsadm-web", metav1.GetOptions{})
 	if err != nil {
 		if !kuberneteserrors.IsNotFound(err) {
@@ -111,7 +112,7 @@ func ensureWebDeployment(deployOptions DeployOptions, clientset *kubernetes.Clie
 	return nil
 }
 
-func ensureWebService(deployOptions *DeployOptions, clientset *kubernetes.Clientset) error {
+func ensureWebService(deployOptions *types.DeployOptions, clientset *kubernetes.Clientset) error {
 	_, err := clientset.CoreV1().Services(deployOptions.Namespace).Get("kotsadm-web", metav1.GetOptions{})
 	if err != nil {
 		if !kuberneteserrors.IsNotFound(err) {
@@ -127,7 +128,7 @@ func ensureWebService(deployOptions *DeployOptions, clientset *kubernetes.Client
 	return nil
 }
 
-func promptForWebServiceType(deployOptions *DeployOptions) (string, error) {
+func promptForWebServiceType(deployOptions *types.DeployOptions) (string, error) {
 	prompt := promptui.Select{
 		Label: "Web/UI Service Type:",
 		Items: []string{"ClusterIP", "NodePort", "LoadBalancer"},
diff --git a/pkg/kotsadm/web_objects.go b/pkg/kotsadm/web_objects.go
index d096545d0..a8f202ecf 100644
--- a/pkg/kotsadm/web_objects.go
+++ b/pkg/kotsadm/web_objects.go
@@ -3,15 +3,15 @@ package kotsadm
 import (
 	"fmt"
 
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
+	"github.com/replicatedhq/kots/pkg/util"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
-
-	"github.com/replicatedhq/kots/pkg/util"
 )
 
-func webConfig(deployOptions DeployOptions) *corev1.ConfigMap {
+func webConfig(deployOptions types.DeployOptions) *corev1.ConfigMap {
 	configMap := &corev1.ConfigMap{
 		TypeMeta: metav1.TypeMeta{
 			APIVersion: "v1",
@@ -43,7 +43,7 @@ nginx -g "daemon off;"`, deployOptions.Hostname, deployOptions.Hostname,
 	return configMap
 }
 
-func webDeployment(deployOptions DeployOptions) *appsv1.Deployment {
+func webDeployment(deployOptions types.DeployOptions) *appsv1.Deployment {
 	var securityContext corev1.PodSecurityContext
 	if !deployOptions.IsOpenShift {
 		securityContext = corev1.PodSecurityContext{
@@ -133,7 +133,7 @@ func webDeployment(deployOptions DeployOptions) *appsv1.Deployment {
 	return deployment
 }
 
-func webService(deployOptions DeployOptions) *corev1.Service {
+func webService(deployOptions types.DeployOptions) *corev1.Service {
 	port := corev1.ServicePort{
 		Name:       "http",
 		Port:       3000,
diff --git a/pkg/upstream/admin-console.go b/pkg/upstream/admin-console.go
index d0c19a078..b40a858e5 100644
--- a/pkg/upstream/admin-console.go
+++ b/pkg/upstream/admin-console.go
@@ -9,6 +9,7 @@ import (
 	"github.com/manifoldco/promptui"
 	"github.com/pkg/errors"
 	"github.com/replicatedhq/kots/pkg/kotsadm"
+	kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"github.com/replicatedhq/kots/pkg/upstream/types"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
@@ -104,7 +105,7 @@ func loadUpstreamSettingsFromDeployment(settings *UpstreamSettings, deployment *
 func generateNewAdminConsoleFiles(settings *UpstreamSettings) ([]types.UpstreamFile, error) {
 	upstreamFiles := []types.UpstreamFile{}
 
-	deployOptions := kotsadm.DeployOptions{
+	deployOptions := kotsadmtypes.DeployOptions{
 		Namespace:              "default",
 		SharedPassword:         settings.SharedPassword,
 		SharedPasswordBcrypt:   settings.SharedPasswordBcrypt,


Test patch:
diff --git a/pkg/kotsadm/postgres_test.go b/pkg/kotsadm/postgres_test.go
index e97fd29ee..10bedef8c 100644
--- a/pkg/kotsadm/postgres_test.go
+++ b/pkg/kotsadm/postgres_test.go
@@ -3,6 +3,7 @@ package kotsadm
 import (
 	"testing"
 
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	appsv1 "k8s.io/api/apps/v1"
@@ -32,7 +33,7 @@ func Test_getPostgresYAML(t *testing.T) {
 		t.Run(test.name, func(t *testing.T) {
 			req := require.New(t)
 
-			manifests, err := getPostgresYAML(DeployOptions{
+			manifests, err := getPostgresYAML(types.DeployOptions{
 				Namespace:        test.namespace,
 				PostgresPassword: test.password,
 			})
diff --git a/pkg/kotsadm/schemahero_test.go b/pkg/kotsadm/schemahero_test.go
index 9ebd9103a..12067d58d 100644
--- a/pkg/kotsadm/schemahero_test.go
+++ b/pkg/kotsadm/schemahero_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/replicatedhq/kots/pkg/kotsadm/types"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	corev1 "k8s.io/api/core/v1"
@@ -30,7 +31,7 @@ func Test_getMigrationsYAML(t *testing.T) {
 		t.Run(test.name, func(t *testing.T) {
 			req := require.New(t)
 
-			deployOptions := DeployOptions{
+			deployOptions := types.DeployOptions{
 				Namespace:        test.namespace,
 				PostgresPassword: fmt.Sprintf("%d", time.Now().Unix()),
 			}