11package adminconsole
22
33import (
4+ "bytes"
45 "context"
56 "encoding/base64"
67 "fmt"
@@ -9,13 +10,27 @@ import (
910 "github.com/pkg/errors"
1011 "github.com/replicatedhq/embedded-cluster/pkg/addons/registry"
1112 "github.com/replicatedhq/embedded-cluster/pkg/helm"
13+ "github.com/replicatedhq/embedded-cluster/pkg/kubeutils"
1214 "github.com/replicatedhq/embedded-cluster/pkg/spinner"
1315 "golang.org/x/crypto/bcrypt"
1416 corev1 "k8s.io/api/core/v1"
1517 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18+ "k8s.io/apimachinery/pkg/runtime"
19+ jsonserializer "k8s.io/apimachinery/pkg/runtime/serializer/json"
1620 "sigs.k8s.io/controller-runtime/pkg/client"
1721)
1822
23+ var (
24+ serializer runtime.Serializer
25+ )
26+
27+ func init () {
28+ scheme := kubeutils .Scheme
29+ serializer = jsonserializer .NewSerializerWithOptions (jsonserializer .DefaultMetaFactory , scheme , scheme , jsonserializer.SerializerOptions {
30+ Yaml : true ,
31+ })
32+ }
33+
1934func (a * AdminConsole ) Install (ctx context.Context , kcli client.Client , hcli helm.Client , overrides []string , writer * spinner.MessageWriter ) error {
2035 // some resources are not part of the helm chart and need to be created before the chart is installed
2136 // TODO: move this to the helm chart
@@ -28,40 +43,49 @@ func (a *AdminConsole) Install(ctx context.Context, kcli client.Client, hcli hel
2843 return errors .Wrap (err , "generate helm values" )
2944 }
3045
31- _ , err = hcli . Install ( ctx , helm.InstallOptions {
46+ opts := helm.InstallOptions {
3247 ReleaseName : releaseName ,
3348 ChartPath : a .ChartLocation (),
3449 ChartVersion : Metadata .Version ,
3550 Values : values ,
3651 Namespace : namespace ,
3752 Labels : getBackupLabels (),
38- })
39- if err != nil {
40- return errors .Wrap (err , "helm install" )
4153 }
4254
43- // install the application
44-
45- if a .KotsInstaller != nil {
46- err := a .KotsInstaller (writer )
55+ if a .DryRun {
56+ manifests , err := hcli .Render (ctx , opts )
4757 if err != nil {
48- return err
58+ return errors .Wrap (err , "dry run render" )
59+ }
60+ a .dryRunManifests = append (a .dryRunManifests , manifests ... )
61+ } else {
62+ _ , err = hcli .Install (ctx , opts )
63+ if err != nil {
64+ return errors .Wrap (err , "helm install" )
65+ }
66+
67+ // install the application
68+ if a .KotsInstaller != nil {
69+ err := a .KotsInstaller (writer )
70+ if err != nil {
71+ return err
72+ }
4973 }
5074 }
5175
5276 return nil
5377}
5478
5579func (a * AdminConsole ) createPreRequisites (ctx context.Context , kcli client.Client ) error {
56- if err := createNamespace (ctx , kcli , namespace ); err != nil {
80+ if err := a . createNamespace (ctx , kcli , namespace ); err != nil {
5781 return errors .Wrap (err , "create namespace" )
5882 }
5983
60- if err := createPasswordSecret (ctx , kcli , namespace , a .Password ); err != nil {
84+ if err := a . createPasswordSecret (ctx , kcli , namespace , a .Password ); err != nil {
6185 return errors .Wrap (err , "create kots password secret" )
6286 }
6387
64- if err := createCAConfigmap (ctx , kcli , namespace , a .PrivateCAs ); err != nil {
88+ if err := a . createCAConfigmap (ctx , kcli , namespace , a .PrivateCAs ); err != nil {
6589 return errors .Wrap (err , "create kots CA configmap" )
6690 }
6791
@@ -70,90 +94,115 @@ func (a *AdminConsole) createPreRequisites(ctx context.Context, kcli client.Clie
7094 if err != nil {
7195 return errors .Wrap (err , "get registry cluster IP" )
7296 }
73- if err := createRegistrySecret (ctx , kcli , namespace , registryIP ); err != nil {
97+ if err := a . createRegistrySecret (ctx , kcli , namespace , registryIP ); err != nil {
7498 return errors .Wrap (err , "create registry secret" )
7599 }
76100 }
77101
78102 return nil
79103}
80104
81- func createNamespace (ctx context.Context , kcli client.Client , namespace string ) error {
82- ns := corev1.Namespace {
83- ObjectMeta : metav1.ObjectMeta {
84- Name : namespace ,
85- },
86- }
87- if err := kcli .Create (ctx , & ns ); client .IgnoreAlreadyExists (err ) != nil {
88- return err
89- }
90- return nil
91- }
92-
93- func createPasswordSecret (ctx context.Context , kcli client.Client , namespace string , password string ) error {
94- passwordBcrypt , err := bcrypt .GenerateFromPassword ([]byte (password ), 10 )
105+ func (a * AdminConsole ) createCAConfigmap (ctx context.Context , cli client.Client , namespace string , privateCAs []string ) error {
106+ cas , err := privateCAsToMap (privateCAs )
95107 if err != nil {
96- return errors .Wrap (err , "generate bcrypt from password " )
108+ return errors .Wrap (err , "create private cas map " )
97109 }
98110
99- kotsPasswordSecret := corev1.Secret {
111+ kotsCAConfigmap := corev1.ConfigMap {
100112 TypeMeta : metav1.TypeMeta {
101- Kind : "Secret " ,
113+ Kind : "ConfigMap " ,
102114 APIVersion : "v1" ,
103115 },
104116 ObjectMeta : metav1.ObjectMeta {
105- Name : "kotsadm-password " ,
117+ Name : "kotsadm-private-cas " ,
106118 Namespace : namespace ,
107119 Labels : map [string ]string {
108120 "kots.io/kotsadm" : "true" ,
109121 "replicated.com/disaster-recovery" : "infra" ,
110122 "replicated.com/disaster-recovery-chart" : "admin-console" ,
111123 },
112124 },
113- Data : map [string ][]byte {
114- "passwordBcrypt" : []byte (passwordBcrypt ),
115- },
125+ Data : cas ,
116126 }
117127
118- err = kcli .Create (ctx , & kotsPasswordSecret )
119- if err != nil {
120- return errors .Wrap (err , "create kotsadm-password secret" )
128+ if a .DryRun {
129+ b := bytes .NewBuffer (nil )
130+ if err := serializer .Encode (& kotsCAConfigmap , b ); err != nil {
131+ return errors .Wrap (err , "serialize CA configmap" )
132+ }
133+ a .dryRunManifests = append (a .dryRunManifests , b .Bytes ())
134+ } else {
135+ if err := cli .Create (ctx , & kotsCAConfigmap ); client .IgnoreAlreadyExists (err ) != nil {
136+ return errors .Wrap (err , "create kotsadm-private-cas configmap" )
137+ }
121138 }
122139
123140 return nil
124141}
125142
126- func createCAConfigmap (ctx context.Context , cli client.Client , namespace string , privateCAs []string ) error {
127- cas , err := privateCAsToMap (privateCAs )
143+ func (a * AdminConsole ) createNamespace (ctx context.Context , kcli client.Client , namespace string ) error {
144+ ns := corev1.Namespace {
145+ ObjectMeta : metav1.ObjectMeta {
146+ Name : namespace ,
147+ },
148+ }
149+
150+ if a .DryRun {
151+ b := bytes .NewBuffer (nil )
152+ if err := serializer .Encode (& ns , b ); err != nil {
153+ return errors .Wrap (err , "serialize namespace" )
154+ }
155+ a .dryRunManifests = append (a .dryRunManifests , b .Bytes ())
156+ } else {
157+ if err := kcli .Create (ctx , & ns ); client .IgnoreAlreadyExists (err ) != nil {
158+ return err
159+ }
160+ }
161+ return nil
162+ }
163+
164+ func (a * AdminConsole ) createPasswordSecret (ctx context.Context , kcli client.Client , namespace string , password string ) error {
165+ passwordBcrypt , err := bcrypt .GenerateFromPassword ([]byte (password ), 10 )
128166 if err != nil {
129- return errors .Wrap (err , "create private cas map " )
167+ return errors .Wrap (err , "generate bcrypt from password " )
130168 }
131169
132- kotsCAConfigmap := corev1.ConfigMap {
170+ kotsPasswordSecret := corev1.Secret {
133171 TypeMeta : metav1.TypeMeta {
134- Kind : "ConfigMap " ,
172+ Kind : "Secret " ,
135173 APIVersion : "v1" ,
136174 },
137175 ObjectMeta : metav1.ObjectMeta {
138- Name : "kotsadm-private-cas " ,
176+ Name : "kotsadm-password " ,
139177 Namespace : namespace ,
140178 Labels : map [string ]string {
141179 "kots.io/kotsadm" : "true" ,
142180 "replicated.com/disaster-recovery" : "infra" ,
143181 "replicated.com/disaster-recovery-chart" : "admin-console" ,
144182 },
145183 },
146- Data : cas ,
184+ Data : map [string ][]byte {
185+ "passwordBcrypt" : []byte (passwordBcrypt ),
186+ },
147187 }
148188
149- if err := cli .Create (ctx , & kotsCAConfigmap ); client .IgnoreAlreadyExists (err ) != nil {
150- return errors .Wrap (err , "create kotsadm-private-cas configmap" )
189+ if a .DryRun {
190+ b := bytes .NewBuffer (nil )
191+ if err := serializer .Encode (& kotsPasswordSecret , b ); err != nil {
192+ return errors .Wrap (err , "serialize password secret" )
193+ }
194+ a .dryRunManifests = append (a .dryRunManifests , b .Bytes ())
195+ } else {
196+ err = kcli .Create (ctx , & kotsPasswordSecret )
197+ if err != nil {
198+ return errors .Wrap (err , "create kotsadm-password secret" )
199+ }
151200 }
152201
153202 return nil
154203}
155204
156- func createRegistrySecret (ctx context.Context , kcli client.Client , namespace string , registryIP string ) error {
205+ func ( a * AdminConsole ) createRegistrySecret (ctx context.Context , kcli client.Client , namespace string , registryIP string ) error {
157206 authString := base64 .StdEncoding .EncodeToString ([]byte (fmt .Sprintf ("embedded-cluster:%s" , registry .GetRegistryPassword ())))
158207 authConfig := fmt .Sprintf (`{"auths":{"%s:5000":{"username": "embedded-cluster", "password": "%s", "auth": "%s"}}}` , registryIP , registry .GetRegistryPassword (), authString )
159208
@@ -177,16 +226,30 @@ func createRegistrySecret(ctx context.Context, kcli client.Client, namespace str
177226 Type : "kubernetes.io/dockerconfigjson" ,
178227 }
179228
180- err := kcli .Create (ctx , & registryCreds )
181- if err != nil {
182- return errors .Wrap (err , "create registry-auth secret" )
229+ if a .DryRun {
230+ b := bytes .NewBuffer (nil )
231+ if err := serializer .Encode (& registryCreds , b ); err != nil {
232+ return errors .Wrap (err , "serialize registry secret" )
233+ }
234+ a .dryRunManifests = append (a .dryRunManifests , b .Bytes ())
235+ } else {
236+ err := kcli .Create (ctx , & registryCreds )
237+ if err != nil {
238+ return errors .Wrap (err , "create registry-auth secret" )
239+ }
183240 }
184241
185242 return nil
186243}
187244
188245func privateCAsToMap (privateCAs []string ) (map [string ]string , error ) {
189246 cas := map [string ]string {}
247+
248+ // Handle nil privateCAs
249+ if privateCAs == nil {
250+ return cas , nil
251+ }
252+
190253 for i , path := range privateCAs {
191254 data , err := os .ReadFile (path )
192255 if err != nil {
0 commit comments