Skip to content

Commit 2c1d311

Browse files
authored
Add domain option for add/edit service command (kuberlogic#199)
* Add domain option for add/edit service command
1 parent 0961391 commit 2c1d311

12 files changed

+80
-42
lines changed

modules/dynamic-apiserver/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ generate: generate-server generate-client
8383

8484
.PHONY: docker-build
8585
docker-build: export LDFLAGS="-X github.com/kuberlogic/kuberlogic/modules/dynamic-apiserver/cmd.ver=$(VERSION)"
86-
docker-build:
86+
docker-build:
8787
CGO_ENABLED=0 \
8888
GOOS=linux \
8989
GOARCH=amd64 \

modules/dynamic-apiserver/openapi.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,6 @@ definitions:
450450
$ref: "#/definitions/Advanced"
451451

452452
domain:
453-
readOnly: true
454453
type: string
455454

456455
status:

modules/dynamic-apiserver/pkg/cli/service_add_operation.go

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cli
22

33
import (
44
"fmt"
5+
56
client2 "github.com/go-openapi/runtime/client"
67
"github.com/kuberlogic/kuberlogic/modules/dynamic-apiserver/pkg/generated/client"
78
"github.com/spf13/viper"
@@ -26,6 +27,7 @@ func makeServiceAddCmd(apiClientFunc func() (*client.ServiceAPI, error)) *cobra.
2627
_ = cmd.PersistentFlags().Int64("replicas", 1, "how many replicas need for service")
2728
_ = cmd.PersistentFlags().String("version", "", "what the version of service")
2829
_ = cmd.PersistentFlags().String("backup_schedule", "", "backup schedule in cron format")
30+
_ = cmd.PersistentFlags().String("domain", "", "on which domain service will be available")
2931
_ = cmd.PersistentFlags().Bool("tls_enabled", false, "")
3032
_ = cmd.PersistentFlags().Bool(subscriptionIdFlag, false, "")
3133

@@ -90,6 +92,12 @@ func runServiceAdd(apiClientFunc func() (*client.ServiceAPI, error)) func(cmd *c
9092
svc.TLSEnabled = *value
9193
}
9294

95+
if value, err := getString(cmd, "domain"); err != nil {
96+
return err
97+
} else if value != nil {
98+
svc.Domain = *value
99+
}
100+
93101
if value, err := getString(cmd, subscriptionIdFlag); err != nil {
94102
return err
95103
} else if value != nil {

modules/dynamic-apiserver/pkg/cli/service_edit_operation.go

+11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cli
22

33
import (
44
"fmt"
5+
56
client2 "github.com/go-openapi/runtime/client"
67
"github.com/kuberlogic/kuberlogic/modules/dynamic-apiserver/pkg/generated/client"
78
"github.com/pkg/errors"
@@ -27,6 +28,7 @@ func makeServiceEditCmd(apiClientFunc func() (*client.ServiceAPI, error)) *cobra
2728
_ = cmd.PersistentFlags().String("version", "", "what the version of service")
2829
_ = cmd.PersistentFlags().String("backup_schedule", "", "backup schedule in cron format")
2930
_ = cmd.PersistentFlags().Bool("tls_enabled", false, "")
31+
_ = cmd.PersistentFlags().String("domain", "", "on which domain service will be available")
3032

3133
// limits
3234
_ = cmd.PersistentFlags().String("limits.cpu", "", "cpu limits")
@@ -88,6 +90,12 @@ func runServiceEdit(apiClientFunc func() (*client.ServiceAPI, error)) func(cmd *
8890
svc.TLSEnabled = *value
8991
}
9092

93+
if value, err := getString(cmd, "domain"); err != nil {
94+
return err
95+
} else if value != nil {
96+
svc.Domain = *value
97+
}
98+
9199
if value, err := getString(cmd, "limits.cpu"); err != nil {
92100
return err
93101
} else if value != nil {
@@ -130,6 +138,9 @@ func runServiceEdit(apiClientFunc func() (*client.ServiceAPI, error)) func(cmd *
130138

131139
// set required fields
132140
svc.Type = getResponse.GetPayload().Type
141+
if svc.Domain == "" {
142+
svc.Domain = getResponse.GetPayload().Domain
143+
}
133144

134145
// make request and then print result
135146
response, err := apiClient.Service.ServiceEdit(editParams, client2.APIKeyAuth(

modules/dynamic-apiserver/pkg/generated/models/service.go

-14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/dynamic-apiserver/pkg/generated/restapi/embedded_spec.go

+2-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/dynamic-apiserver/pkg/util/util.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package util
66

77
import (
88
"encoding/json"
9+
"fmt"
10+
911
"github.com/go-openapi/strfmt"
1012
"github.com/kuberlogic/kuberlogic/modules/dynamic-apiserver/pkg/config"
1113
"github.com/kuberlogic/kuberlogic/modules/dynamic-apiserver/pkg/generated/models"
@@ -37,7 +39,11 @@ func ServiceToKuberlogic(svc *models.Service, cfg *config.Config) (*kuberlogicco
3739
c.Spec.Version = svc.Version
3840
}
3941

40-
c.Spec.Domain = cfg.Domain
42+
c.Spec.Domain = fmt.Sprintf("%s.%s", *svc.ID, cfg.Domain)
43+
if svc.Domain != "" {
44+
c.Spec.Domain = svc.Domain
45+
}
46+
4147
if svc.BackupSchedule != "" {
4248
c.Spec.BackupSchedule = svc.BackupSchedule
4349
}

modules/dynamic-operator/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -211,5 +211,5 @@ patch-webhook-endpoint:
211211
.PHONY: generate-local-webhook-certs
212212
generate-local-webhook-certs:
213213
mkdir -p /tmp/k8s-webhook-server/serving-certs/; \
214-
kubectl get secret webhook-server-cert -o=jsonpath="{.data['tls\.key']}" | base64 -d > /tmp/k8s-webhook-server/serving-certs/tls.key
215-
kubectl get secret webhook-server-cert -o=jsonpath="{.data['tls\.crt']}" | base64 -d > /tmp/k8s-webhook-server/serving-certs/tls.crt
214+
kubectl get secret --namespace=kuberlogic webhook-server-cert -o=jsonpath="{.data['tls\.key']}" | base64 -d > /tmp/k8s-webhook-server/serving-certs/tls.key
215+
kubectl get secret --namespace=kuberlogic webhook-server-cert -o=jsonpath="{.data['tls\.crt']}" | base64 -d > /tmp/k8s-webhook-server/serving-certs/tls.crt

modules/dynamic-operator/api/v1alpha1/kuberlogicservice_types.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
package v1alpha1
66

77
import (
8+
"time"
9+
810
v1 "k8s.io/api/core/v1"
911
v11 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1012
"k8s.io/apimachinery/pkg/api/meta"
1113
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12-
"time"
1314
)
1415

1516
const (
@@ -111,11 +112,7 @@ func (in *KuberLogicService) TLSEnabled() bool {
111112
}
112113

113114
func (in *KuberLogicService) GetHost() string {
114-
var host string
115-
if in.Spec.Domain != "" {
116-
host = in.GetName() + "." + in.Spec.Domain
117-
}
118-
return host
115+
return in.Spec.Domain
119116
}
120117

121118
func (in *KuberLogicService) SetAccessEndpoint() {

modules/dynamic-operator/api/v1alpha1/kuberlogicservice_webhook.go

+30
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,32 @@
55
package v1alpha1
66

77
import (
8+
"context"
89
"encoding/json"
10+
"fmt"
11+
912
"github.com/kuberlogic/kuberlogic/modules/dynamic-operator/plugin/commons"
1013
"github.com/pkg/errors"
1114
"github.com/robfig/cron"
1215
v1 "k8s.io/api/core/v1"
1316
"k8s.io/apimachinery/pkg/runtime"
1417
ctrl "sigs.k8s.io/controller-runtime"
18+
"sigs.k8s.io/controller-runtime/pkg/client"
1519
"sigs.k8s.io/controller-runtime/pkg/webhook"
1620
)
1721

1822
var log = ctrl.Log.WithName("kuberlogicservice-webhook")
1923

2024
var pluginInstances map[string]commons.PluginService
25+
var k8sClient client.Client
2126

2227
var (
2328
errInvalidBackupSchedule = errors.New("invalid backupSchedule format")
2429
errVolDownsizeForbidden = errors.New("volume downsize forbidden")
2530
)
2631

2732
func (r *KuberLogicService) SetupWebhookWithManager(mgr ctrl.Manager, plugins map[string]commons.PluginService) error {
33+
k8sClient = mgr.GetClient()
2834
pluginInstances = plugins
2935
return ctrl.NewWebhookManagedBy(mgr).
3036
For(r).
@@ -134,6 +140,10 @@ func (r *KuberLogicService) ValidateCreate() error {
134140
if err = plugin.ValidateCreate(*req).Error(); err != nil {
135141
return err
136142
}
143+
144+
if err = validateDomain(r.Spec.Domain); err != nil {
145+
return err
146+
}
137147
return nil
138148
}
139149

@@ -169,6 +179,13 @@ func (r *KuberLogicService) ValidateUpdate(old runtime.Object) error {
169179
if err = plugin.ValidateUpdate(*req).Error(); err != nil {
170180
return err
171181
}
182+
183+
if r.Spec.Domain != oldSpec.Spec.Domain {
184+
if err = validateDomain(r.Spec.Domain); err != nil {
185+
return err
186+
}
187+
}
188+
172189
return nil
173190
}
174191

@@ -221,3 +238,16 @@ func validateScheduleFormat(schedule string) error {
221238
_, err := cron.ParseStandard(schedule)
222239
return err
223240
}
241+
242+
func validateDomain(domain string) error {
243+
klsList := &KuberLogicServiceList{}
244+
if err := k8sClient.List(context.TODO(), klsList); err != nil {
245+
return err
246+
}
247+
for _, item := range klsList.Items {
248+
if item.Spec.Domain == domain {
249+
return errors.New(fmt.Sprintf("Domain %s conflicts with tenant: %s", domain, item.Name))
250+
}
251+
}
252+
return nil
253+
}

modules/dynamic-operator/api/v1alpha1/kuberlogicservice_webhook_test.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
package v1alpha1
66

77
import (
8+
"time"
9+
810
. "github.com/onsi/ginkgo"
911
. "github.com/onsi/gomega"
1012
v1 "k8s.io/api/core/v1"
@@ -13,7 +15,6 @@ import (
1315
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1416
"k8s.io/apimachinery/pkg/types"
1517
"sigs.k8s.io/controller-runtime/pkg/client"
16-
"time"
1718
)
1819

1920
var _ = Describe("KuberlogicService controller", func() {
@@ -48,6 +49,7 @@ var _ = Describe("KuberlogicService controller", func() {
4849
Type: "docker-compose",
4950
Replicas: defaultReplicas,
5051
Limits: defaultLimits,
52+
Domain: "kls.com",
5153
},
5254
}
5355

@@ -59,20 +61,21 @@ var _ = Describe("KuberlogicService controller", func() {
5961
Spec: KuberLogicServiceSpec{
6062
Type: "docker-compose",
6163
Replicas: defaultReplicas,
64+
Domain: "default-resources.com",
6265
},
6366
}
6467

6568
It("Should create KuberLogicService resource", func() {
6669
By("By creating a new KuberLogicService")
6770

68-
Expect(k8sClient.Create(ctx, kls)).Should(Succeed())
71+
Expect(testK8sClient.Create(ctx, kls)).Should(Succeed())
6972

7073
By("By checking a new KuberLogicService")
7174
lookupKlsKey := types.NamespacedName{Name: klsName, Namespace: klsNamespace}
7275
createdKls := &KuberLogicService{}
7376

7477
Eventually(func() error {
75-
return k8sClient.Get(ctx, lookupKlsKey, createdKls)
78+
return testK8sClient.Get(ctx, lookupKlsKey, createdKls)
7679
}, timeout, interval).Should(Not(HaveOccurred()))
7780

7881
log.Info("resources", "res", createdKls.Spec.Limits)
@@ -82,30 +85,30 @@ var _ = Describe("KuberlogicService controller", func() {
8285

8386
By("By creating a new KuberLogicService with default limits")
8487

85-
Expect(k8sClient.Create(ctx, defaultResourceKls)).Should(Succeed())
88+
Expect(testK8sClient.Create(ctx, defaultResourceKls)).Should(Succeed())
8689

8790
By("By checking default plugin resources")
8891
Eventually(func() error {
89-
return k8sClient.Get(ctx, client.ObjectKeyFromObject(defaultResourceKls), createdKls)
92+
return testK8sClient.Get(ctx, client.ObjectKeyFromObject(defaultResourceKls), createdKls)
9093
}, timeout, interval).Should(Not(HaveOccurred()))
9194

9295
log.Info("resources", "res", createdKls.Spec.Limits)
9396
Expect(createdKls.Spec.Limits["storage"]).Should(Equal(resource.MustParse("1Gi")))
9497

9598
By("Volume downsize is not supported")
9699
defaultResourceKls.Spec.Limits["storage"] = resource.MustParse("1Mi")
97-
Expect(k8sClient.Update(ctx, defaultResourceKls).Error()).Should(ContainSubstring("volume downsize forbidden"))
100+
Expect(testK8sClient.Update(ctx, defaultResourceKls).Error()).Should(ContainSubstring("volume downsize forbidden"))
98101
})
99102
It("Should remove KuberLogicService resource", func() {
100103
By("Removing KuberLogicService resource")
101104

102105
for _, item := range []*KuberLogicService{kls, defaultResourceKls} {
103-
Expect(k8sClient.Delete(ctx, item)).Should(Succeed())
106+
Expect(testK8sClient.Delete(ctx, item)).Should(Succeed())
104107

105108
By("By checking a new KuberLogicService")
106109
removedKls := &KuberLogicService{}
107110
Eventually(func() bool {
108-
return errors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(item), removedKls))
111+
return errors.IsNotFound(testK8sClient.Get(ctx, client.ObjectKeyFromObject(item), removedKls))
109112
}, timeout, interval).Should(BeTrue())
110113
}
111114
})

modules/dynamic-operator/api/v1alpha1/webhook_suite_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import (
3838
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
3939

4040
var (
41-
k8sClient client.Client
41+
testK8sClient client.Client
4242
testEnv *envtest.Environment
4343
ctx context.Context
4444
cancel context.CancelFunc
@@ -81,9 +81,9 @@ var _ = BeforeSuite(func() {
8181
Expect(err).NotTo(HaveOccurred())
8282
Expect(cfg).NotTo(BeNil())
8383

84-
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
84+
testK8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
8585
Expect(err).NotTo(HaveOccurred())
86-
Expect(k8sClient).NotTo(BeNil())
86+
Expect(testK8sClient).NotTo(BeNil())
8787
} else {
8888

8989
By("bootstrapping test environment")
@@ -99,9 +99,9 @@ var _ = BeforeSuite(func() {
9999
Expect(err).NotTo(HaveOccurred())
100100
Expect(cfg).NotTo(BeNil())
101101

102-
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
102+
testK8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
103103
Expect(err).NotTo(HaveOccurred())
104-
Expect(k8sClient).NotTo(BeNil())
104+
Expect(testK8sClient).NotTo(BeNil())
105105

106106
logger := hclog.New(&hclog.LoggerOptions{
107107
Name: "plugin",

0 commit comments

Comments
 (0)