mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
add production certificate issuer and fix route trait
This commit is contained in:
145
CONTRIBUTING.md
145
CONTRIBUTING.md
@@ -5,12 +5,10 @@ contributing to `kubevela` or build a PoC (Proof of Concept).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Golang version 1.12+
|
||||
2. Kubernetes version v1.15+ with `~/.kube/config` configured.
|
||||
3. OAM Kubernetes Runtime installed.
|
||||
4. Kustomize version 3.8+
|
||||
5. ginkgo 1.14.0+ (just for [E2E test](https://github.com/oam-dev/kubevela/blob/master/DEVELOPMENT.md#e2e-test))
|
||||
6. golangci-lint 1.31.0+, it will install automatically if you run `make`, you can [install it manually](https://golangci-lint.run/usage/install/#local-installation) if the installation is too slow.
|
||||
1. Golang version 1.13+
|
||||
2. Kubernetes version v1.16+ with `~/.kube/config` configured.
|
||||
3. ginkgo 1.14.0+ (just for [E2E test](https://github.com/oam-dev/kubevela/blob/master/DEVELOPMENT.md#e2e-test))
|
||||
4. golangci-lint 1.31.0+, it will install automatically if you run `make`, you can [install it manually](https://golangci-lint.run/usage/install/#local-installation) if the installation is too slow.
|
||||
|
||||
## Build
|
||||
* Clone this project
|
||||
@@ -19,96 +17,89 @@ contributing to `kubevela` or build a PoC (Proof of Concept).
|
||||
git clone git@github.com:oam-dev/kubevela.git
|
||||
```
|
||||
|
||||
* Install Template CRD into your cluster
|
||||
* Build Vela CLI
|
||||
|
||||
```shell script
|
||||
make install
|
||||
make
|
||||
```
|
||||
|
||||
* Install template object
|
||||
* Configure vela to PATH
|
||||
|
||||
after build, make will create `vela` binary to `bin/`, Set this path to PATH.
|
||||
|
||||
```shell script
|
||||
kubectl apply -f config/samples/
|
||||
export PATH=$PATH:/your/path/to/project/kubevela/bin
|
||||
```
|
||||
|
||||
## Develop & Debug
|
||||
If you change Template CRD, remember to rerun `make install`.
|
||||
|
||||
Use the following command to develop and debug.
|
||||
* Install Vela Core
|
||||
|
||||
```shell script
|
||||
$ cd cmd/vela
|
||||
$ go run main.go COMMAND [FLAG]
|
||||
vela install
|
||||
```
|
||||
|
||||
## Use
|
||||
|
||||
* Create ENV
|
||||
|
||||
```shell script
|
||||
vela env init myenv --namespace myenv --email my@email.com --domain kubevela.io
|
||||
```
|
||||
|
||||
* Create Component
|
||||
|
||||
For example, use the following command to create and run an application.
|
||||
|
||||
```shell script
|
||||
$ go run main.go run containerized app2057 nginx:1.9.4
|
||||
Creating AppConfig app2057
|
||||
$ vela comp run mycomp -t webservice --image crccheck/hello-world --port 8000
|
||||
Creating AppConfig appcomp
|
||||
SUCCEED
|
||||
|
||||
$ kubectl get oam
|
||||
NAME WORKLOAD-KIND
|
||||
component.core.oam.dev/app2057 ContainerizedWorkload
|
||||
|
||||
NAME AGE
|
||||
containerizedworkload.core.oam.dev/poc 53m
|
||||
|
||||
NAME AGE
|
||||
applicationconfiguration.core.oam.dev/app2057 69s
|
||||
|
||||
NAME DEFINITION-NAME
|
||||
traitdefinition.core.oam.dev/simplerollouttraits.extend.oam.dev simplerollouttraits.extend.oam.dev
|
||||
|
||||
NAME DEFINITION-NAME
|
||||
workloaddefinition.core.oam.dev/containerizedworkloads.core.oam.dev containerizedworkloads.core.oam.dev
|
||||
workloaddefinition.core.oam.dev/deployments.apps deployments.apps
|
||||
workloaddefinition.core.oam.dev/statefulsets.apps statefulsets.apps
|
||||
```
|
||||
|
||||
## E2E test
|
||||
```
|
||||
$ make e2e-test
|
||||
Running Suite: Trait Suite
|
||||
==========================
|
||||
Random Seed: 1596559178
|
||||
Will run 5 of 5 specs
|
||||
* Add Trait
|
||||
|
||||
Trait env init
|
||||
should print env initiation successful message
|
||||
kubevela/e2e/commonContext.go:14
|
||||
Create env succeed, current env is default
|
||||
•
|
||||
------------------------------
|
||||
Trait env set
|
||||
should show env set message
|
||||
kubevela/e2e/commonContext.go:40
|
||||
Set env succeed, current env is default
|
||||
•
|
||||
------------------------------
|
||||
Trait run
|
||||
should print successful creation information
|
||||
kubevela/e2e/commonContext.go:76
|
||||
Creating AppConfig app-trait-basic
|
||||
SUCCEED
|
||||
•
|
||||
------------------------------
|
||||
Trait kubevela attach trait
|
||||
should print successful attached information
|
||||
kubevela/e2e/trait/trait_test.go:24
|
||||
Applying trait for app
|
||||
```shell script
|
||||
$ vela route mycomp
|
||||
Adding route for app abc
|
||||
Succeeded!
|
||||
•
|
||||
------------------------------
|
||||
Trait delete
|
||||
should print successful deletion information
|
||||
kubevela/e2e/commonContext.go:85
|
||||
Deleting AppConfig "app-trait-basic"
|
||||
DELETE SUCCEED
|
||||
•
|
||||
Ran 5 of 5 Specs in 9.717 seconds
|
||||
SUCCESS! -- 5 Passed | 0 Failed | 0 Pending | 0 Skipped
|
||||
PASS
|
||||
```
|
||||
|
||||
* Check Status
|
||||
|
||||
```
|
||||
$ vela comp status abc
|
||||
Showing status of Component abc deployed in Environment t2
|
||||
Component Status:
|
||||
Name: abc Containerized(type) UNKNOWN APIVersion standard.oam.dev/v1alpha1 Kind Containerized workload is unknown for HealthScope
|
||||
Traits
|
||||
└─Trait/route
|
||||
|
||||
Last Deployment:
|
||||
Created at: 2020-09-18 18:47:09 +0800 CST
|
||||
Updated at: 2020-09-18T18:47:16+08:00
|
||||
```
|
||||
|
||||
* Delete App
|
||||
|
||||
```shell script
|
||||
$ vela app ls
|
||||
abc
|
||||
|
||||
$ vela app delete abc
|
||||
Deleting Application "abc"
|
||||
delete apps succeed abc from t2
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
### Unit test
|
||||
|
||||
```shell script
|
||||
make test
|
||||
```
|
||||
|
||||
### E2E test
|
||||
```
|
||||
make e2e-test
|
||||
```
|
||||
|
||||
## Make a pull request
|
||||
|
||||
64
README.md
64
README.md
@@ -29,38 +29,54 @@ This command will install vela core controller into your K8s cluster, along with
|
||||
|
||||
## Demos
|
||||
|
||||
#### Check workloads
|
||||
|
||||
```
|
||||
$ vela workloads
|
||||
NAME DEFINITION
|
||||
backend containerizeds.standard.oam.dev
|
||||
task jobs
|
||||
webservice containerizeds.standard.oam.dev
|
||||
```
|
||||
|
||||
#### workload run
|
||||
* Create ENV
|
||||
|
||||
```shell script
|
||||
$ vela comp run -t webservice app123 -p 80 --image nginx:1.9.4
|
||||
Creating AppConfig app123
|
||||
vela env init myenv --namespace myenv --email my@email.com --domain kubevela.io
|
||||
```
|
||||
|
||||
* Create Component
|
||||
|
||||
For example, use the following command to create and run an application.
|
||||
|
||||
```shell script
|
||||
$ vela comp run mycomp -t webservice --image crccheck/hello-world --port 8000
|
||||
Creating AppConfig appcomp
|
||||
SUCCEED
|
||||
|
||||
$ vela comp status app123
|
||||
|
||||
$ vela comp ls
|
||||
NAME APP WORKLOAD TRAITS STATUS CREATED-TIME
|
||||
app123 app123 deployment Deployed 2020-08-27 10:56:41 +0800 CST
|
||||
```
|
||||
|
||||
#### app
|
||||
* Add Trait
|
||||
|
||||
```shell script
|
||||
$ vela route mycomp
|
||||
Adding route for app abc
|
||||
Succeeded!
|
||||
```
|
||||
|
||||
* Check Status
|
||||
|
||||
```
|
||||
$ vela comp status abc
|
||||
Showing status of Component abc deployed in Environment t2
|
||||
Component Status:
|
||||
Name: abc Containerized(type) UNKNOWN APIVersion standard.oam.dev/v1alpha1 Kind Containerized workload is unknown for HealthScope
|
||||
Traits
|
||||
└─Trait/route
|
||||
|
||||
Last Deployment:
|
||||
Created at: 2020-09-18 18:47:09 +0800 CST
|
||||
Updated at: 2020-09-18T18:47:16+08:00
|
||||
```
|
||||
|
||||
* Delete App
|
||||
|
||||
```shell script
|
||||
$ vela app ls
|
||||
app123
|
||||
abc
|
||||
|
||||
$ vela app delete app123
|
||||
Deleting AppConfig "app123"
|
||||
DELETE SUCCEED
|
||||
$ vela app delete abc
|
||||
Deleting Application "abc"
|
||||
delete apps succeed abc from t2
|
||||
```
|
||||
|
||||
#### Auto-Completion
|
||||
|
||||
@@ -27,8 +27,13 @@ const (
|
||||
|
||||
type EnvMeta struct {
|
||||
Name string `json:"name"`
|
||||
Current string `json:"current,omitempty"`
|
||||
Namespace string `json:"namespace"`
|
||||
Email string `json:"email,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
|
||||
// Below are not arguments, should be auto-generated
|
||||
Issuer string `json:"issuer"`
|
||||
Current string `json:"current,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
37
charts/vela-core/templates/routetrait.yaml
Normal file
37
charts/vela-core/templates/routetrait.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: routes.standard.oam.dev
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
|
||||
definition.oam.dev/kind: Route
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- core.oam.dev/v1alpha2.ContainerizedWorkload
|
||||
- standard.oam.dev/v1alpha1.Containerized
|
||||
- deployments.apps
|
||||
workloadRefPath: spec.workloadRef
|
||||
definitionRef:
|
||||
name: routes.standard.oam.dev
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Route"
|
||||
spec: {
|
||||
host: route.domain
|
||||
path: route.path
|
||||
tls: {
|
||||
issuerName: route.issuer
|
||||
}
|
||||
backend: {
|
||||
port: route.port
|
||||
}
|
||||
}
|
||||
}
|
||||
route: {
|
||||
domain: *"" | string
|
||||
path: *"" | string
|
||||
port: *443 | int
|
||||
issuer: *"" | string
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core"
|
||||
"github.com/gosuri/uitable"
|
||||
certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
|
||||
"github.com/spf13/cobra"
|
||||
k8sruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
@@ -34,7 +35,7 @@ var chartTGZSource string
|
||||
|
||||
func init() {
|
||||
_ = clientgoscheme.AddToScheme(scheme)
|
||||
|
||||
_ = certmanager.AddToScheme(scheme)
|
||||
_ = core.AddToScheme(scheme)
|
||||
// +kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
||||
19
config/samples/issuer.yaml
Normal file
19
config/samples/issuer.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
apiVersion: cert-manager.io/v1alpha2
|
||||
kind: Issuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
# You must replace this email address with your own.
|
||||
# Let's Encrypt will use this to contact you about expiring
|
||||
# certificates, and issues related to your account.
|
||||
email: wonderflow@icloud.com
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
privateKeySecretRef:
|
||||
# Secret resource that will be used to store the account's private key.
|
||||
name: example-issuer-account-key
|
||||
# Add a single challenge solver, HTTP01 using nginx
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
@@ -21,13 +21,17 @@ spec:
|
||||
spec: {
|
||||
host: route.domain
|
||||
path: route.path
|
||||
tls: {
|
||||
issuerName: route.issuer
|
||||
}
|
||||
backend: {
|
||||
port: route.port
|
||||
}
|
||||
}
|
||||
}
|
||||
route: {
|
||||
domain: string
|
||||
domain: *"" | string
|
||||
path: *"" | string
|
||||
port: *443 | int
|
||||
issuer: *"" | string
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ var (
|
||||
cli := fmt.Sprintf("vela env init %s --namespace %s", envName, envName)
|
||||
output, err := Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
expectedOutput := fmt.Sprintf("Create env succeed, current env is %s", envName)
|
||||
expectedOutput := fmt.Sprintf("ENV %s CREATED,", envName)
|
||||
gomega.Expect(output).To(gomega.ContainSubstring(expectedOutput))
|
||||
})
|
||||
})
|
||||
@@ -214,7 +214,7 @@ var (
|
||||
err = json.Unmarshal(result, &r)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
gomega.Expect(http.StatusOK).Should(gomega.Equal(r.Code))
|
||||
gomega.Expect(r.Data.(string)).To(gomega.ContainSubstring("Create env succeed"))
|
||||
gomega.Expect(r.Data.(string)).To(gomega.ContainSubstring("CREATED"))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ func EvalToObject(capName string, data map[string]interface{}) (*unstructured.Un
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (app *Application) GetComponentTraits(componentName string) ([]v1alpha2.ComponentTrait, error) {
|
||||
func (app *Application) GetComponentTraits(componentName string, env *types.EnvMeta) ([]v1alpha2.ComponentTrait, error) {
|
||||
var traits []v1alpha2.ComponentTrait
|
||||
rawTraits, err := app.GetTraits(componentName)
|
||||
if err != nil {
|
||||
@@ -338,6 +338,14 @@ func (app *Application) GetComponentTraits(componentName string) ([]v1alpha2.Com
|
||||
return traits, nil
|
||||
}
|
||||
|
||||
func (app *Application) VelaCoreInjection(obj *unstructured.Unstructured, env *types.EnvMeta, traitType string) {
|
||||
switch traitType {
|
||||
case "route":
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func FormatDefaultHealthScopeName(appName string) string {
|
||||
return appName + "-default-health"
|
||||
}
|
||||
@@ -387,7 +395,7 @@ func (app *Application) OAM(env *types.EnvMeta) ([]v1alpha2.Component, v1alpha2.
|
||||
}})
|
||||
|
||||
//TODO(wonderflow): handle component data input/output here
|
||||
compTraits, err := app.GetComponentTraits(name)
|
||||
compTraits, err := app.GetComponentTraits(name, env)
|
||||
if err != nil {
|
||||
return nil, v1alpha2.ApplicationConfiguration{}, nil, err
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func NewEnvInitCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
|
||||
DisableFlagsInUseLine: true,
|
||||
Short: "Create environments",
|
||||
Long: "Create environment and set the currently using environment",
|
||||
Example: `vela env init test --namespace test`,
|
||||
Example: `vela env init test --namespace test --email my@email.com`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
|
||||
if err != nil {
|
||||
@@ -71,6 +71,8 @@ func NewEnvInitCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
|
||||
}
|
||||
cmd.SetOut(ioStreams.Out)
|
||||
cmd.Flags().StringVar(&envArgs.Namespace, "namespace", "default", "specify K8s namespace for env")
|
||||
cmd.Flags().StringVar(&envArgs.Email, "email", "", "specify email for production TLS Certificate notification")
|
||||
cmd.Flags().StringVar(&envArgs.Domain, "domain", "", "specify domain your applications")
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -94,7 +96,6 @@ func NewEnvDeleteCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
}
|
||||
|
||||
func NewEnvSetCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
ctx := context.Background()
|
||||
cmd := &cobra.Command{
|
||||
Use: "set",
|
||||
Aliases: []string{"sw"},
|
||||
@@ -103,7 +104,7 @@ func NewEnvSetCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
Long: "Set an environment as the current using one",
|
||||
Example: `vela env set test`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return SetEnv(ctx, args, ioStreams)
|
||||
return SetEnv(args, ioStreams)
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
types.TagCommandType: types.TypeStart,
|
||||
@@ -149,8 +150,8 @@ func CreateOrUpdateEnv(ctx context.Context, c client.Client, envArgs *types.EnvM
|
||||
return fmt.Errorf("you must specify env name for vela env init command")
|
||||
}
|
||||
envName := args[0]
|
||||
namespace := envArgs.Namespace
|
||||
msg, err := oam.CreateOrUpdateEnv(ctx, c, envName, namespace)
|
||||
envArgs.Name = envName
|
||||
msg, err := oam.CreateOrUpdateEnv(ctx, c, envName, envArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -158,7 +159,7 @@ func CreateOrUpdateEnv(ctx context.Context, c client.Client, envArgs *types.EnvM
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetEnv(ctx context.Context, args []string, ioStreams cmdutil.IOStreams) error {
|
||||
func SetEnv(args []string, ioStreams cmdutil.IOStreams) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("you must specify env name for vela env command")
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func TestENV(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
|
||||
// set as default env
|
||||
err = SetEnv(ctx, []string{"default"}, ioStream)
|
||||
err = SetEnv([]string{"default"}, ioStream)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// check env set success
|
||||
@@ -93,10 +93,10 @@ func TestENV(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// can not set as a non-exist env
|
||||
err = SetEnv(ctx, []string{"env1"}, ioStream)
|
||||
err = SetEnv([]string{"env1"}, ioStream)
|
||||
assert.Error(t, err)
|
||||
|
||||
// set success
|
||||
err = SetEnv(ctx, []string{"default"}, ioStream)
|
||||
err = SetEnv([]string{"default"}, ioStream)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func AddTraitCommands(parentCmd *cobra.Command, c types.Args, ioStreams cmdutil.
|
||||
Long: "Attach " + name + " trait to an app",
|
||||
Example: "vela " + name + " frontend",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
o := &commandOptions{IOStreams: ioStreams}
|
||||
o := &commandOptions{IOStreams: ioStreams, traitType: name}
|
||||
o.Template = tmp
|
||||
newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
|
||||
if err != nil {
|
||||
@@ -103,7 +103,9 @@ func (o *commandOptions) AddOrUpdateTrait(cmd *cobra.Command, args []string) err
|
||||
if err = o.Prepare(cmd, args); err != nil {
|
||||
return err
|
||||
}
|
||||
if o.app, err = oam.AddOrUpdateTrait(o.Env.Name, o.appName, o.workloadName, cmd.Flags(), o.Template); err != nil {
|
||||
flags := cmd.Flags()
|
||||
|
||||
if o.app, err = oam.AddOrUpdateTrait(o.Env, o.appName, o.workloadName, flags, o.Template); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -138,6 +140,7 @@ func (o *commandOptions) Run(ctx context.Context, cmd *cobra.Command) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.Info(msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ func (r *Reconciler) createService(ctx context.Context, mLog logr.Logger, worklo
|
||||
},
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
},
|
||||
}
|
||||
// assign selector
|
||||
|
||||
@@ -9,6 +9,9 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/jetstack/cert-manager/pkg/apis/acme/v1alpha2"
|
||||
certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
|
||||
v1 "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -36,15 +39,40 @@ func GetEnvByName(name string) (*types.EnvMeta, error) {
|
||||
//Create or update env.
|
||||
//If it does not exist, create it and set to the new env.
|
||||
//If it exists, update it and set to the new env.
|
||||
func CreateOrUpdateEnv(ctx context.Context, c client.Client, envName string, namespace string) (string, error) {
|
||||
func CreateOrUpdateEnv(ctx context.Context, c client.Client, envName string, envArgs *types.EnvMeta) (string, error) {
|
||||
var message = ""
|
||||
var envArgs = types.EnvMeta{
|
||||
Name: envName,
|
||||
Namespace: namespace,
|
||||
}
|
||||
// Create Namespace
|
||||
if err := c.Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: envArgs.Namespace}}); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return message, err
|
||||
}
|
||||
|
||||
// Create Issuer For SSL
|
||||
if envArgs.Email != "" {
|
||||
issuerName := "oam-env-" + envArgs.Name
|
||||
if err := c.Create(ctx, &certmanager.Issuer{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: issuerName, Namespace: envArgs.Namespace},
|
||||
Spec: certmanager.IssuerSpec{
|
||||
IssuerConfig: certmanager.IssuerConfig{
|
||||
ACME: &v1alpha2.ACMEIssuer{
|
||||
Email: envArgs.Email,
|
||||
Server: "https://acme-v02.api.letsencrypt.org/directory",
|
||||
PrivateKey: v1.SecretKeySelector{
|
||||
LocalObjectReference: v1.LocalObjectReference{Name: "oam-env-" + envArgs.Name + ".key"},
|
||||
},
|
||||
Solvers: []v1alpha2.ACMEChallengeSolver{{
|
||||
HTTP01: &v1alpha2.ACMEChallengeSolverHTTP01{
|
||||
Ingress: &v1alpha2.ACMEChallengeSolverHTTP01Ingress{Class: GetStringPointer("nginx")},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return message, err
|
||||
}
|
||||
envArgs.Issuer = issuerName
|
||||
}
|
||||
|
||||
data, err := json.Marshal(envArgs)
|
||||
if err != nil {
|
||||
return message, err
|
||||
@@ -67,42 +95,22 @@ func CreateOrUpdateEnv(ctx context.Context, c client.Client, envName string, nam
|
||||
if err = ioutil.WriteFile(curEnvPath, []byte(envName), 0644); err != nil {
|
||||
return message, err
|
||||
}
|
||||
message = fmt.Sprintf("Create env succeed, current env is " + envName + " namespace is " + envArgs.Namespace + ", use --namespace=<namespace> to specify namespace with env init")
|
||||
message = fmt.Sprintf("ENV %s CREATED, Namespace: %s, Email: %s.", envName, envArgs.Namespace, envArgs.Email)
|
||||
return message, nil
|
||||
}
|
||||
|
||||
//Create env. If env already exists, return error
|
||||
func CreateEnv(ctx context.Context, c client.Client, envName string, namespace string) (string, error) {
|
||||
var message = ""
|
||||
var envArgs = types.EnvMeta{
|
||||
Name: envName,
|
||||
Namespace: namespace,
|
||||
}
|
||||
data, err := json.Marshal(envArgs)
|
||||
if err != nil {
|
||||
return message, err
|
||||
}
|
||||
_, err = GetEnvByName(envName)
|
||||
func GetStringPointer(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
// CreateEnv will only create. If env already exists, return error
|
||||
func CreateEnv(ctx context.Context, c client.Client, envName string, envArgs *types.EnvMeta) (string, error) {
|
||||
_, err := GetEnvByName(envName)
|
||||
if err == nil {
|
||||
message = fmt.Sprintf("Env %s already exist", envName)
|
||||
message := fmt.Sprintf("Env %s already exist", envName)
|
||||
return message, errors.New(message)
|
||||
}
|
||||
if err := c.Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: envArgs.Namespace}}); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return message, err
|
||||
}
|
||||
envdir, err := system.GetEnvDir()
|
||||
if err != nil {
|
||||
return message, err
|
||||
}
|
||||
subEnvDir := filepath.Join(envdir, envName)
|
||||
if _, err := system.CreateIfNotExist(subEnvDir); err != nil {
|
||||
return "", nil
|
||||
}
|
||||
if err = ioutil.WriteFile(filepath.Join(subEnvDir, system.EnvConfigName), data, 0644); err != nil {
|
||||
return message, err
|
||||
}
|
||||
message = "Create env succeed"
|
||||
return message, err
|
||||
return CreateOrUpdateEnv(ctx, c, envName, envArgs)
|
||||
}
|
||||
|
||||
//Update Env, if env does not exist, return error
|
||||
|
||||
@@ -148,12 +148,47 @@ func SimplifyCapabilityStruct(capabilityList []types.Capability) []apis.TraitMet
|
||||
return traitList
|
||||
}
|
||||
|
||||
func ValidateAndMutateForCore(traitType, workloadName string, flags *pflag.FlagSet, env *types.EnvMeta) error {
|
||||
switch traitType {
|
||||
case "route":
|
||||
domain, _ := flags.GetString("domain")
|
||||
if domain == "" {
|
||||
if env.Domain == "" {
|
||||
return fmt.Errorf("--domain is required if not set in env")
|
||||
}
|
||||
if strings.HasPrefix(env.Domain, "https://") {
|
||||
env.Domain = strings.TrimPrefix(env.Domain, "https://")
|
||||
}
|
||||
if strings.HasPrefix(env.Domain, "http://") {
|
||||
env.Domain = strings.TrimPrefix(env.Domain, "http://")
|
||||
}
|
||||
if err := flags.Set("domain", workloadName+"."+env.Domain); err != nil {
|
||||
return fmt.Errorf("set flag for vela-core trait('route') err %v, please make sure your template is right", err)
|
||||
}
|
||||
}
|
||||
issuer, _ := flags.GetString("issuer")
|
||||
if issuer == "" {
|
||||
if env.Issuer == "" {
|
||||
return fmt.Errorf("--issuer is required, you can also set email in env and let it generate automatically")
|
||||
}
|
||||
if err := flags.Set("issuer", env.Issuer); err != nil {
|
||||
return fmt.Errorf("set flag for vela-core trait('route') err %v, please make sure your template is right", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//AddOrUpdateTrait attach trait to workload
|
||||
func AddOrUpdateTrait(envName string, appName string, workloadName string, flagSet *pflag.FlagSet, template types.Capability) (*application.Application, error) {
|
||||
func AddOrUpdateTrait(env *types.EnvMeta, appName string, workloadName string, flagSet *pflag.FlagSet, template types.Capability) (*application.Application, error) {
|
||||
err := ValidateAndMutateForCore(template.Name, workloadName, flagSet, env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if appName == "" {
|
||||
appName = workloadName
|
||||
}
|
||||
app, err := application.Load(envName, appName)
|
||||
app, err := application.Load(env.Name, appName)
|
||||
if err != nil {
|
||||
return app, err
|
||||
}
|
||||
@@ -181,7 +216,7 @@ func AddOrUpdateTrait(envName string, appName string, workloadName string, flagS
|
||||
if err = app.SetTrait(workloadName, traitAlias, traitData); err != nil {
|
||||
return app, err
|
||||
}
|
||||
return app, app.Save(envName)
|
||||
return app, app.Save(env.Name)
|
||||
}
|
||||
|
||||
func AttachTrait(c *gin.Context, body apis.TraitBody) (string, error) {
|
||||
@@ -204,12 +239,13 @@ func AttachTrait(c *gin.Context, body apis.TraitBody) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
appObj, err = AddOrUpdateTrait(body.EnvName, body.AppGroup, body.WorkloadName, fs, template)
|
||||
// Run step
|
||||
env, err := GetEnvByName(body.EnvName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Run step
|
||||
env, err := GetEnvByName(body.EnvName)
|
||||
|
||||
appObj, err = AddOrUpdateTrait(env, body.AppGroup, body.WorkloadName, fs, template)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
type Environment struct {
|
||||
EnvName string `json:"envName" binding:"required,min=1,max=32"`
|
||||
Namespace string `json:"namespace" binding:"required,min=1,max=32"`
|
||||
Email string `json:"email"`
|
||||
Domain string `json:"domain"`
|
||||
Current string `json:"current,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
@@ -23,9 +24,16 @@ func CreateEnv(c *gin.Context) {
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
|
||||
ctx := util.GetContext(c)
|
||||
kubeClient := c.MustGet("KubeClient")
|
||||
message, err := oam.CreateEnv(ctx, kubeClient.(client.Client), name, namespace)
|
||||
message, err := oam.CreateEnv(ctx, kubeClient.(client.Client), name, &types.EnvMeta{
|
||||
Name: name,
|
||||
Current: environment.Current,
|
||||
Namespace: namespace,
|
||||
Email: environment.Email,
|
||||
Domain: environment.Domain,
|
||||
})
|
||||
util.AssembleResponse(c, message, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,17 @@
|
||||
spec: {
|
||||
host: route.domain
|
||||
path: route.path
|
||||
tls: {
|
||||
issuerName: route.issuer
|
||||
}
|
||||
backend: {
|
||||
port: route.port
|
||||
}
|
||||
}
|
||||
}
|
||||
route: {
|
||||
domain: string
|
||||
domain: *"" | string
|
||||
path: *"" | string
|
||||
port: *443 | int
|
||||
issuer: *"" | string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user