Skip to content

Commit d65f068

Browse files
committed
Refactor registry package
1 parent 6032e22 commit d65f068

3 files changed

Lines changed: 158 additions & 115 deletions

File tree

cmd/up.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func (cmd *UpCmd) Run(cobraCmd *cobra.Command, args []string) {
156156
// Build image if necessary
157157
mustRedeploy := cmd.buildImages()
158158

159-
// Check if we find a running release pod
159+
// Check if the chart directory has changed
160160
hash, err := hash.Directory("chart")
161161
if err != nil {
162162
log.Fatalf("Error hashing chart directory: %v", err)
@@ -165,6 +165,7 @@ func (cmd *UpCmd) Run(cobraCmd *cobra.Command, args []string) {
165165
// Load config
166166
config := configutil.GetConfig(false)
167167

168+
// Check if we find a running release pod
168169
pod, err := getRunningDevSpacePod(cmd.helm, cmd.kubectl)
169170
if err != nil || mustRedeploy || cmd.flags.deploy || config.DevSpace.ChartHash == nil || *config.DevSpace.ChartHash != hash {
170171
cmd.deployChart()

pkg/devspace/registry/create.go

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package registry
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
"time"
8+
9+
"k8s.io/client-go/kubernetes"
10+
11+
"github.com/covexo/devspace/pkg/devspace/clients/helm"
12+
"github.com/covexo/devspace/pkg/devspace/config/configutil"
13+
"github.com/covexo/devspace/pkg/devspace/config/v1"
14+
"github.com/covexo/yamlq"
15+
"github.com/foomo/htpasswd"
16+
k8sv1 "k8s.io/api/core/v1"
17+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18+
)
19+
20+
func createRegistry(kubectl *kubernetes.Clientset, helm *helm.HelmClientWrapper, internalRegistry *v1.InternalRegistry, registryConfig *v1.RegistryConfig) error {
21+
registryReleaseName := *internalRegistry.Release.Name
22+
registryReleaseNamespace := *internalRegistry.Release.Namespace
23+
registryReleaseValues := internalRegistry.Release.Values
24+
25+
// Create registry namespace & ignore errors
26+
kubectl.CoreV1().Namespaces().Create(&k8sv1.Namespace{
27+
ObjectMeta: metav1.ObjectMeta{
28+
Name: registryReleaseNamespace,
29+
},
30+
})
31+
32+
// Deploy the registry
33+
_, err := helm.InstallChartByName(registryReleaseName, registryReleaseNamespace, "stable/docker-registry", "", registryReleaseValues)
34+
if err != nil {
35+
return fmt.Errorf("Unable to initialize docker registry: %s", err.Error())
36+
}
37+
38+
// Create/Update secret if necessary
39+
if registryConfig != nil && registryConfig.Auth != nil {
40+
// Update registry secret
41+
err = createOrUpdateRegistrySecret(kubectl, internalRegistry, registryConfig)
42+
if err != nil {
43+
return err
44+
}
45+
}
46+
47+
// Get the registry url
48+
serviceHostname, err := getRegistryURL(kubectl, registryReleaseNamespace, registryReleaseName+"-docker-registry")
49+
if err != nil {
50+
return err
51+
}
52+
53+
// Check if an ingress is configured
54+
ingressHostname := ""
55+
if registryReleaseValues != nil {
56+
registryValues := yamlq.NewQuery(*registryReleaseValues)
57+
isIngressEnabled, _ := registryValues.Bool("ingress", "enabled")
58+
59+
if isIngressEnabled {
60+
firstIngressHostname, _ := registryValues.String("ingress", "hosts", "0")
61+
62+
if len(firstIngressHostname) > 0 {
63+
ingressHostname = firstIngressHostname
64+
}
65+
}
66+
}
67+
68+
// Update config values
69+
if len(ingressHostname) == 0 {
70+
registryConfig.URL = configutil.String(serviceHostname)
71+
registryConfig.Insecure = configutil.Bool(true)
72+
} else {
73+
registryConfig.URL = configutil.String(ingressHostname)
74+
registryConfig.Insecure = configutil.Bool(false)
75+
}
76+
77+
return nil
78+
}
79+
80+
func createOrUpdateRegistrySecret(kubectl *kubernetes.Clientset, internalRegistry *v1.InternalRegistry, registryConfig *v1.RegistryConfig) error {
81+
registryReleaseName := *internalRegistry.Release.Name
82+
registryReleaseNamespace := *internalRegistry.Release.Namespace
83+
84+
registryAuth := registryConfig.Auth
85+
htpasswdSecretName := registryReleaseName + "-docker-registry-secret"
86+
htpasswdSecret, err := kubectl.Core().Secrets(registryReleaseNamespace).Get(htpasswdSecretName, metav1.GetOptions{})
87+
if err != nil {
88+
return fmt.Errorf("Unable to retrieve secret for docker registry: %s", err.Error())
89+
}
90+
91+
if htpasswdSecret == nil || htpasswdSecret.Data == nil {
92+
htpasswdSecret = &k8sv1.Secret{
93+
ObjectMeta: metav1.ObjectMeta{
94+
Name: htpasswdSecretName,
95+
},
96+
Data: map[string][]byte{},
97+
}
98+
}
99+
100+
oldHtpasswdData := htpasswdSecret.Data["htpasswd"]
101+
newHtpasswdData := htpasswd.HashedPasswords{}
102+
103+
if len(oldHtpasswdData) != 0 {
104+
oldHtpasswdDataBytes := []byte(oldHtpasswdData)
105+
newHtpasswdData, _ = htpasswd.ParseHtpasswd(oldHtpasswdDataBytes)
106+
}
107+
108+
err = newHtpasswdData.SetPassword(*registryAuth.Username, *registryAuth.Password, htpasswd.HashBCrypt)
109+
if err != nil {
110+
return fmt.Errorf("Unable to set password in htpasswd: %s", err.Error())
111+
}
112+
113+
newHtpasswdDataBytes := newHtpasswdData.Bytes()
114+
htpasswdSecret.Data["htpasswd"] = newHtpasswdDataBytes
115+
116+
_, err = kubectl.Core().Secrets(registryReleaseNamespace).Get(htpasswdSecretName, metav1.GetOptions{})
117+
if err != nil {
118+
_, err = kubectl.Core().Secrets(registryReleaseNamespace).Create(htpasswdSecret)
119+
} else {
120+
_, err = kubectl.Core().Secrets(registryReleaseNamespace).Update(htpasswdSecret)
121+
}
122+
123+
if err != nil {
124+
return fmt.Errorf("Unable to update htpasswd secret: %s", err.Error())
125+
}
126+
127+
return nil
128+
}
129+
130+
func getRegistryURL(kubectl *kubernetes.Clientset, registryReleaseNamespace, registryServiceName string) (string, error) {
131+
maxServiceWaiting := 60 * time.Second
132+
serviceWaitingInterval := 3 * time.Second
133+
134+
for true {
135+
registryService, err := kubectl.Core().Services(registryReleaseNamespace).Get(registryServiceName, metav1.GetOptions{})
136+
if err != nil {
137+
return "", err
138+
}
139+
140+
if len(registryService.Spec.ClusterIP) > 0 {
141+
return registryService.Spec.ClusterIP + ":" + strconv.Itoa(registryPort), nil
142+
}
143+
144+
time.Sleep(serviceWaitingInterval)
145+
maxServiceWaiting = maxServiceWaiting - serviceWaitingInterval
146+
147+
if maxServiceWaiting <= 0 {
148+
return "", errors.New("Timeout waiting for registry service to start")
149+
}
150+
}
151+
152+
return "", nil
153+
}

pkg/devspace/registry/registry.go

Lines changed: 3 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,15 @@ import (
66
"encoding/hex"
77
"errors"
88
"fmt"
9-
"strconv"
109
"time"
1110

1211
"github.com/covexo/devspace/pkg/devspace/config/v1"
1312

1413
"github.com/covexo/devspace/pkg/util/log"
15-
"github.com/foomo/htpasswd"
1614
"k8s.io/client-go/kubernetes"
1715

1816
"github.com/covexo/devspace/pkg/devspace/clients/helm"
1917
"github.com/covexo/devspace/pkg/devspace/config/configutil"
20-
"github.com/covexo/yamlq"
2118

2219
k8sv1 "k8s.io/api/core/v1"
2320
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -85,121 +82,13 @@ func InitInternalRegistry(kubectl *kubernetes.Clientset, helm *helm.HelmClientWr
8582
registryReleaseName := *internalRegistry.Release.Name
8683
registryReleaseDeploymentName := registryReleaseName + "-docker-registry"
8784
registryReleaseNamespace := *internalRegistry.Release.Namespace
88-
registryReleaseValues := internalRegistry.Release.Values
8985

9086
// Check if registry already exists
9187
registryDeployment, err := kubectl.ExtensionsV1beta1().Deployments(registryReleaseNamespace).Get(registryReleaseDeploymentName, metav1.GetOptions{})
9288
if err != nil {
93-
// Check if registry namespace exists
94-
_, err := kubectl.CoreV1().Namespaces().Get(registryReleaseNamespace, metav1.GetOptions{})
89+
err = createRegistry(kubectl, helm, internalRegistry, registryConfig)
9590
if err != nil {
96-
// Create registry namespace
97-
_, err = kubectl.CoreV1().Namespaces().Create(&k8sv1.Namespace{
98-
ObjectMeta: metav1.ObjectMeta{
99-
Name: registryReleaseNamespace,
100-
},
101-
})
102-
103-
if err != nil {
104-
return err
105-
}
106-
}
107-
108-
_, err = helm.InstallChartByName(registryReleaseName, registryReleaseNamespace, "stable/docker-registry", "", registryReleaseValues)
109-
if err != nil {
110-
return fmt.Errorf("Unable to initialize docker registry: %s", err.Error())
111-
}
112-
113-
if registryConfig != nil && registryConfig.Auth != nil {
114-
registryAuth := registryConfig.Auth
115-
htpasswdSecretName := registryReleaseName + "-docker-registry-secret"
116-
htpasswdSecret, err := kubectl.Core().Secrets(registryReleaseNamespace).Get(htpasswdSecretName, metav1.GetOptions{})
117-
if err != nil {
118-
return fmt.Errorf("Unable to retrieve secret for docker registry: %s", err.Error())
119-
}
120-
121-
if htpasswdSecret == nil || htpasswdSecret.Data == nil {
122-
htpasswdSecret = &k8sv1.Secret{
123-
ObjectMeta: metav1.ObjectMeta{
124-
Name: htpasswdSecretName,
125-
},
126-
Data: map[string][]byte{},
127-
}
128-
}
129-
130-
oldHtpasswdData := htpasswdSecret.Data["htpasswd"]
131-
newHtpasswdData := htpasswd.HashedPasswords{}
132-
133-
if len(oldHtpasswdData) != 0 {
134-
oldHtpasswdDataBytes := []byte(oldHtpasswdData)
135-
newHtpasswdData, _ = htpasswd.ParseHtpasswd(oldHtpasswdDataBytes)
136-
}
137-
138-
err = newHtpasswdData.SetPassword(*registryAuth.Username, *registryAuth.Password, htpasswd.HashBCrypt)
139-
if err != nil {
140-
return fmt.Errorf("Unable to set password in htpasswd: %s", err.Error())
141-
}
142-
143-
newHtpasswdDataBytes := newHtpasswdData.Bytes()
144-
145-
htpasswdSecret.Data["htpasswd"] = newHtpasswdDataBytes
146-
147-
_, err = kubectl.Core().Secrets(registryReleaseNamespace).Get(htpasswdSecretName, metav1.GetOptions{})
148-
if err != nil {
149-
_, err = kubectl.Core().Secrets(registryReleaseNamespace).Create(htpasswdSecret)
150-
} else {
151-
_, err = kubectl.Core().Secrets(registryReleaseNamespace).Update(htpasswdSecret)
152-
}
153-
}
154-
155-
if err != nil {
156-
return fmt.Errorf("Unable to update htpasswd secret: %s", err.Error())
157-
}
158-
159-
registryServiceName := registryReleaseName + "-docker-registry"
160-
serviceHostname := ""
161-
maxServiceWaiting := 60 * time.Second
162-
serviceWaitingInterval := 3 * time.Second
163-
164-
for true {
165-
registryService, err := kubectl.Core().Services(registryReleaseNamespace).Get(registryServiceName, metav1.GetOptions{})
166-
if err != nil {
167-
return err
168-
}
169-
170-
if len(registryService.Spec.ClusterIP) > 0 {
171-
serviceHostname = registryService.Spec.ClusterIP + ":" + strconv.Itoa(registryPort)
172-
break
173-
}
174-
175-
time.Sleep(serviceWaitingInterval)
176-
maxServiceWaiting = maxServiceWaiting - serviceWaitingInterval
177-
178-
if maxServiceWaiting <= 0 {
179-
return errors.New("Timeout waiting for registry service to start")
180-
}
181-
}
182-
183-
ingressHostname := ""
184-
if registryReleaseValues != nil {
185-
registryValues := yamlq.NewQuery(*registryReleaseValues)
186-
isIngressEnabled, _ := registryValues.Bool("ingress", "enabled")
187-
188-
if isIngressEnabled {
189-
firstIngressHostname, _ := registryValues.String("ingress", "hosts", "0")
190-
191-
if len(firstIngressHostname) > 0 {
192-
ingressHostname = firstIngressHostname
193-
}
194-
}
195-
}
196-
197-
if len(ingressHostname) == 0 {
198-
registryConfig.URL = configutil.String(serviceHostname)
199-
registryConfig.Insecure = configutil.Bool(true)
200-
} else {
201-
registryConfig.URL = configutil.String(ingressHostname)
202-
registryConfig.Insecure = configutil.Bool(false)
91+
return err
20392
}
20493
}
20594

@@ -238,7 +127,7 @@ func waitForRegistry(registryNamespace, registryReleaseDeploymentName string, cl
238127
return errors.New("Internal registry start waiting time timed out")
239128
}
240129

241-
//GetImageURL returns the image (optional with tag)
130+
// GetImageURL returns the image (optional with tag)
242131
func GetImageURL(imageConfig *v1.ImageConfig, includingLatestTag bool) string {
243132
registryConfig, registryConfErr := GetRegistryConfig(imageConfig)
244133

0 commit comments

Comments
 (0)