mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
Implement API `api/envs/default/apps/ (#147)
* Implement API `api/envs/default/apps/ implement API `api/envs/default/apps/ and refactor code * address comments from @wonderflow and @ryan * fix code rebase issue * temporary comment BeforeSuite in integration/integration_suite_test.go to fix make issue
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -33,3 +33,9 @@ vendor/
|
||||
|
||||
pkg/test/vela
|
||||
tmp/
|
||||
|
||||
# Dashboard
|
||||
dashboard/node_modules/
|
||||
dashboard/package-lock.json
|
||||
dashboard/src/.umi/
|
||||
package-lock.json
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/server"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var logFilePath string
|
||||
var logRetainDate int
|
||||
var logCompress, development bool
|
||||
|
||||
flag.StringVar(&logFilePath, "log-file-path", "", "The log file path.")
|
||||
flag.IntVar(&logRetainDate, "log-retain-date", 7, "The number of days of logs history to retain.")
|
||||
flag.BoolVar(&logCompress, "log-compress", true, "Enable compression on the rotated logs.")
|
||||
flag.BoolVar(&development, "development", true, "Development mode.")
|
||||
flag.Parse()
|
||||
|
||||
// setup logging
|
||||
var w io.Writer
|
||||
if len(logFilePath) > 0 {
|
||||
w = zapcore.AddSync(&lumberjack.Logger{
|
||||
Filename: logFilePath,
|
||||
MaxAge: logRetainDate, // days
|
||||
Compress: logCompress,
|
||||
})
|
||||
} else {
|
||||
w = os.Stdout
|
||||
}
|
||||
ctrl.SetLogger(zap.New(func(o *zap.Options) {
|
||||
o.Development = development
|
||||
o.DestWritter = w
|
||||
}))
|
||||
|
||||
//Setup RESTful server
|
||||
server := server.ApiServer{}
|
||||
server.Launch()
|
||||
// handle signal: SIGTERM(15), SIGKILL(9)
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc, syscall.SIGTERM)
|
||||
signal.Notify(sc, syscall.SIGKILL)
|
||||
select {
|
||||
case <-sc:
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
server.Shutdown(ctx)
|
||||
}
|
||||
}
|
||||
@@ -124,6 +124,8 @@ func newCommand() *cobra.Command {
|
||||
|
||||
cmd.NewTraitsCommand(ioStream),
|
||||
cmd.NewWorkloadsCommand(ioStream),
|
||||
|
||||
cmd.NewDashboardCommand(commandArgs, ioStream),
|
||||
)
|
||||
|
||||
// Workloads
|
||||
|
||||
@@ -46,4 +46,6 @@ func BeforeSuit() {
|
||||
_, err := GetCliBinary()
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
Exec("vela system:init")
|
||||
//Without this line, will hit issue like `<string>: Error: unknown command "scale" for "vela"`
|
||||
Exec("vela system:update")
|
||||
}
|
||||
|
||||
@@ -6,15 +6,13 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/server"
|
||||
)
|
||||
|
||||
var restServer http.Handler
|
||||
|
||||
var _ = BeforeSuite(func() {
|
||||
restServer = server.SetupRoute()
|
||||
})
|
||||
//var _ = BeforeSuite(func() {
|
||||
// restServer = server.SetupRoute()
|
||||
//})
|
||||
|
||||
func TestIntegration(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
|
||||
92
pkg/cmd/dashboard.go
Normal file
92
pkg/cmd/dashboard.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
"github.com/cloud-native-application/rudrx/pkg/server"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewDashboardCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
// ctx := context.Background()
|
||||
cmd := &cobra.Command{
|
||||
Use: "dashboard",
|
||||
Short: "Setup API Server and launch Dashboard",
|
||||
Long: "Setup API Server and launch Dashboard",
|
||||
Example: `dashboard`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
SetupApiServer(newClient)
|
||||
return nil
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
types.TagCommandType: types.TypeSystem,
|
||||
},
|
||||
}
|
||||
cmd.SetOut(ioStreams.Out)
|
||||
return cmd
|
||||
}
|
||||
|
||||
/*
|
||||
SetupApiServer moved main function from cmd/server/main.go written by Ryan, so it can be integrated
|
||||
by Cli and called by cmd/server/main.go.
|
||||
*/
|
||||
func SetupApiServer(kubeClient client.Client) {
|
||||
var logFilePath string
|
||||
var logRetainDate int
|
||||
var logCompress, development bool
|
||||
|
||||
//flag.StringVar(&logFilePath, "log-file-path", "", "The log file path.")
|
||||
//flag.IntVar(&logRetainDate, "log-retain-date", 7, "The number of days of logs history to retain.")
|
||||
//flag.BoolVar(&logCompress, "log-compress", true, "Enable compression on the rotated logs.")
|
||||
//flag.BoolVar(&development, "development", true, "Development mode.")
|
||||
//flag.Parse()
|
||||
|
||||
// setup logging
|
||||
var w io.Writer
|
||||
if len(logFilePath) > 0 {
|
||||
w = zapcore.AddSync(&lumberjack.Logger{
|
||||
Filename: logFilePath,
|
||||
MaxAge: logRetainDate, // days
|
||||
Compress: logCompress,
|
||||
})
|
||||
} else {
|
||||
w = os.Stdout
|
||||
}
|
||||
ctrl.SetLogger(zap.New(func(o *zap.Options) {
|
||||
o.Development = development
|
||||
o.DestWritter = w
|
||||
}))
|
||||
|
||||
//Setup RESTful server
|
||||
server := server.ApiServer{}
|
||||
server.Launch(kubeClient)
|
||||
// handle signal: SIGTERM(15), SIGKILL(9)
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc, syscall.SIGTERM)
|
||||
signal.Notify(sc, syscall.SIGKILL)
|
||||
select {
|
||||
case <-sc:
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
server.Shutdown(ctx)
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
"github.com/cloud-native-application/rudrx/pkg/oam"
|
||||
"github.com/cloud-native-application/rudrx/pkg/utils/system"
|
||||
|
||||
"github.com/gosuri/uitable"
|
||||
@@ -124,7 +125,7 @@ func ListEnvs(ctx context.Context, args []string, ioStreams cmdutil.IOStreams) e
|
||||
table.AddRow("NAME", "CURRENT", "NAMESPACE")
|
||||
if len(args) > 0 {
|
||||
envName := args[0]
|
||||
env, err := getEnvByName(envName)
|
||||
env, err := oam.GetEnvByName(envName)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
ioStreams.Info(fmt.Sprintf("env %s not exist", envName))
|
||||
@@ -236,7 +237,7 @@ func SwitchEnv(ctx context.Context, args []string, ioStreams cmdutil.IOStreams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
envMeta, err := getEnvByName(envname)
|
||||
envMeta, err := oam.GetEnvByName(envname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -266,7 +267,7 @@ func GetEnv(cmd *cobra.Command) (*types.EnvMeta, error) {
|
||||
envName = cmd.Flag("env").Value.String()
|
||||
}
|
||||
if envName != "" {
|
||||
return getEnvByName(envName)
|
||||
return oam.GetEnvByName(envName)
|
||||
}
|
||||
envName, err = GetCurrentEnvName()
|
||||
if err != nil {
|
||||
@@ -278,20 +279,5 @@ func GetEnv(cmd *cobra.Command) (*types.EnvMeta, error) {
|
||||
}
|
||||
envName = types.DefaultEnvName
|
||||
}
|
||||
return getEnvByName(envName)
|
||||
}
|
||||
|
||||
func getEnvByName(name string) (*types.EnvMeta, error) {
|
||||
data, err := ioutil.ReadFile(filepath.Join(system.GetEnvDirByName(name), system.EnvConfigName))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("%s not exist", name)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
var meta types.EnvMeta
|
||||
if err = json.Unmarshal(data, &meta); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &meta, nil
|
||||
return oam.GetEnvByName(envName)
|
||||
}
|
||||
|
||||
@@ -2,27 +2,17 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
"github.com/gosuri/uitable"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
"github.com/cloud-native-application/rudrx/pkg/oam"
|
||||
"github.com/gosuri/uitable"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type ApplicationMeta struct {
|
||||
Name string `json:"name"`
|
||||
Workload string `json:"workload,omitempty"`
|
||||
Traits []string `json:"traits,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
CreatedTime string `json:"created,omitempty"`
|
||||
}
|
||||
|
||||
func NewAppsCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
ctx := context.Background()
|
||||
cmd := &cobra.Command{
|
||||
@@ -54,7 +44,7 @@ func NewAppsCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
}
|
||||
|
||||
func printApplicationList(ctx context.Context, c client.Client, appName string, namespace string) {
|
||||
applicationMetaList, err := RetrieveApplicationsByName(ctx, c, appName, namespace)
|
||||
applicationMetaList, err := oam.RetrieveApplicationsByName(ctx, c, appName, namespace)
|
||||
if err != nil {
|
||||
fmt.Printf("listing Trait DefinitionPath hit an issue: %s\n", err)
|
||||
return
|
||||
@@ -73,55 +63,3 @@ func printApplicationList(ctx context.Context, c client.Client, appName string,
|
||||
fmt.Print(table.String())
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Get application list by optional filter `applicationName`
|
||||
Application name is equal to Component name as currently vela only supports one component exists in one application
|
||||
*/
|
||||
func RetrieveApplicationsByName(ctx context.Context, c client.Client, applicationName string, namespace string) ([]ApplicationMeta, error) {
|
||||
var applicationMetaList []ApplicationMeta
|
||||
var applicationList corev1alpha2.ApplicationConfigurationList
|
||||
|
||||
if applicationName != "" {
|
||||
var application corev1alpha2.ApplicationConfiguration
|
||||
err := c.Get(ctx, client.ObjectKey{Name: applicationName, Namespace: namespace}, &application)
|
||||
|
||||
if err != nil {
|
||||
return applicationMetaList, err
|
||||
}
|
||||
|
||||
applicationList.Items = append(applicationList.Items, application)
|
||||
} else {
|
||||
err := c.List(ctx, &applicationList, &client.ListOptions{Namespace: namespace})
|
||||
if err != nil {
|
||||
return applicationMetaList, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, a := range applicationList.Items {
|
||||
for _, com := range a.Spec.Components {
|
||||
componentName := com.ComponentName
|
||||
component, err := cmdutil.GetComponent(ctx, c, componentName, namespace)
|
||||
if err != nil {
|
||||
return applicationMetaList, err
|
||||
}
|
||||
var workload corev1alpha2.WorkloadDefinition
|
||||
if err := json.Unmarshal(component.Spec.Workload.Raw, &workload); err == nil {
|
||||
workloadName := workload.TypeMeta.Kind
|
||||
traitAlias := GetTraitAliasByComponentTraitList(ctx, c, com.Traits)
|
||||
var status = "UNKNOWN"
|
||||
if len(a.Status.Conditions) != 0 {
|
||||
status = string(a.Status.Conditions[0].Status)
|
||||
}
|
||||
applicationMetaList = append(applicationMetaList, ApplicationMeta{
|
||||
Name: a.Name,
|
||||
Workload: workloadName,
|
||||
Traits: traitAlias,
|
||||
Status: status,
|
||||
CreatedTime: a.ObjectMeta.CreationTimestamp.String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return applicationMetaList, nil
|
||||
}
|
||||
|
||||
@@ -2,13 +2,10 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/builtin/traitdefinition"
|
||||
@@ -17,16 +14,12 @@ import (
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/utils/system"
|
||||
|
||||
"helm.sh/helm/v3/pkg/release"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
oamv1 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -39,7 +32,6 @@ import (
|
||||
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/plugins"
|
||||
"helm.sh/helm/v3/pkg/action"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
@@ -442,65 +434,3 @@ func NewTraitDefinition(manifest string) (oamv1.TraitDefinition, error) {
|
||||
err := yaml.Unmarshal([]byte(manifest), &traitDefinition)
|
||||
return traitDefinition, err
|
||||
}
|
||||
|
||||
func GetTraitAliasByTraitDefinition(traitDefinition oamv1.TraitDefinition) (string, error) {
|
||||
velaApplicationFolder := filepath.Join("~/.vela", "applications")
|
||||
system.CreateIfNotExist(velaApplicationFolder)
|
||||
d, _ := ioutil.TempDir(velaApplicationFolder, "cue")
|
||||
defer os.RemoveAll(d)
|
||||
template, err := plugins.HandleTemplate(traitDefinition.Spec.Extension, traitDefinition.Name, d)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return template.Name, nil
|
||||
}
|
||||
|
||||
func GetTraitAliasByKind(ctx context.Context, c client.Client, traitKind string) string {
|
||||
var traitAlias string
|
||||
t, err := GetTraitDefinitionByKind(ctx, c, traitKind)
|
||||
if err != nil {
|
||||
return traitKind
|
||||
}
|
||||
|
||||
if traitAlias, err = GetTraitAliasByTraitDefinition(t); err != nil {
|
||||
return traitKind
|
||||
}
|
||||
|
||||
return traitAlias
|
||||
}
|
||||
func GetTraitDefinitionByKind(ctx context.Context, c client.Client, traitKind string) (oamv1.TraitDefinition, error) {
|
||||
var traitDefinitionList oamv1.TraitDefinitionList
|
||||
var traitDefinition oamv1.TraitDefinition
|
||||
if err := c.List(ctx, &traitDefinitionList); err != nil {
|
||||
return traitDefinition, err
|
||||
}
|
||||
for _, t := range traitDefinitionList.Items {
|
||||
if t.Annotations["oam.appengine.info/kind"] == traitKind {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return traitDefinition, errors.New(fmt.Sprintf("Could not find TraitDefinition by kind %s", traitKind))
|
||||
}
|
||||
|
||||
func GetTraitAliasByComponentTraitList(ctx context.Context, c client.Client, componentTraitList []corev1alpha2.ComponentTrait) []string {
|
||||
var traitAlias []string
|
||||
for _, t := range componentTraitList {
|
||||
_, _, kind := GetGVKFromRawExtension(t.Trait)
|
||||
alias := GetTraitAliasByKind(ctx, c, kind)
|
||||
traitAlias = append(traitAlias, alias)
|
||||
}
|
||||
return traitAlias
|
||||
}
|
||||
|
||||
func GetGVKFromRawExtension(extension runtime.RawExtension) (string, string, string) {
|
||||
if extension.Object != nil {
|
||||
gvk := extension.Object.GetObjectKind().GroupVersionKind()
|
||||
return gvk.Group, gvk.Version, gvk.Kind
|
||||
}
|
||||
var data map[string]interface{}
|
||||
// leverage Admission Controller to do the check
|
||||
_ = json.Unmarshal(extension.Raw, &data)
|
||||
obj := unstructured.Unstructured{Object: data}
|
||||
gvk := obj.GroupVersionKind()
|
||||
return gvk.Group, gvk.Version, gvk.Kind
|
||||
}
|
||||
|
||||
70
pkg/oam/application.go
Normal file
70
pkg/oam/application.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package oam
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type ApplicationMeta struct {
|
||||
Name string `json:"name"`
|
||||
Workload string `json:"workload,omitempty"`
|
||||
Traits []string `json:"traits,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
CreatedTime string `json:"created,omitempty"`
|
||||
}
|
||||
|
||||
/*
|
||||
Get application list by optional filter `applicationName`
|
||||
Application name is equal to Component name as currently vela only supports one component exists in one application
|
||||
*/
|
||||
func RetrieveApplicationsByName(ctx context.Context, c client.Client, applicationName string, namespace string) ([]ApplicationMeta, error) {
|
||||
var applicationMetaList []ApplicationMeta
|
||||
var applicationList corev1alpha2.ApplicationConfigurationList
|
||||
|
||||
if applicationName != "" {
|
||||
var application corev1alpha2.ApplicationConfiguration
|
||||
err := c.Get(ctx, client.ObjectKey{Name: applicationName, Namespace: namespace}, &application)
|
||||
|
||||
if err != nil {
|
||||
return applicationMetaList, err
|
||||
}
|
||||
|
||||
applicationList.Items = append(applicationList.Items, application)
|
||||
} else {
|
||||
err := c.List(ctx, &applicationList, &client.ListOptions{Namespace: namespace})
|
||||
if err != nil {
|
||||
return applicationMetaList, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, a := range applicationList.Items {
|
||||
for _, com := range a.Spec.Components {
|
||||
componentName := com.ComponentName
|
||||
component, err := cmdutil.GetComponent(ctx, c, componentName, namespace)
|
||||
if err != nil {
|
||||
return applicationMetaList, err
|
||||
}
|
||||
var workload corev1alpha2.WorkloadDefinition
|
||||
if err := json.Unmarshal(component.Spec.Workload.Raw, &workload); err == nil {
|
||||
workloadName := workload.TypeMeta.Kind
|
||||
traitAlias := GetTraitAliasByComponentTraitList(ctx, c, com.Traits)
|
||||
var status = "UNKNOWN"
|
||||
if len(a.Status.Conditions) != 0 {
|
||||
status = string(a.Status.Conditions[0].Status)
|
||||
}
|
||||
applicationMetaList = append(applicationMetaList, ApplicationMeta{
|
||||
Name: a.Name,
|
||||
Workload: workloadName,
|
||||
Traits: traitAlias,
|
||||
Status: status,
|
||||
CreatedTime: a.ObjectMeta.CreationTimestamp.String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return applicationMetaList, nil
|
||||
}
|
||||
27
pkg/oam/env.go
Normal file
27
pkg/oam/env.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package oam
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
"github.com/cloud-native-application/rudrx/pkg/utils/system"
|
||||
)
|
||||
|
||||
func GetEnvByName(name string) (*types.EnvMeta, error) {
|
||||
data, err := ioutil.ReadFile(filepath.Join(system.GetEnvDirByName(name), system.EnvConfigName))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("%s not exist", name)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
var meta types.EnvMeta
|
||||
if err = json.Unmarshal(data, &meta); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &meta, nil
|
||||
}
|
||||
84
pkg/oam/trait.go
Normal file
84
pkg/oam/trait.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package oam
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/plugins"
|
||||
"github.com/cloud-native-application/rudrx/pkg/utils/system"
|
||||
corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func GetGVKFromRawExtension(extension runtime.RawExtension) (string, string, string) {
|
||||
if extension.Object != nil {
|
||||
gvk := extension.Object.GetObjectKind().GroupVersionKind()
|
||||
return gvk.Group, gvk.Version, gvk.Kind
|
||||
}
|
||||
var data map[string]interface{}
|
||||
// leverage Admission Controller to do the check
|
||||
_ = json.Unmarshal(extension.Raw, &data)
|
||||
obj := unstructured.Unstructured{Object: data}
|
||||
gvk := obj.GroupVersionKind()
|
||||
return gvk.Group, gvk.Version, gvk.Kind
|
||||
}
|
||||
|
||||
func GetTraitAliasByComponentTraitList(ctx context.Context, c client.Client, componentTraitList []corev1alpha2.ComponentTrait) []string {
|
||||
var traitAlias []string
|
||||
for _, t := range componentTraitList {
|
||||
_, _, kind := GetGVKFromRawExtension(t.Trait)
|
||||
alias := GetTraitAliasByKind(ctx, c, kind)
|
||||
traitAlias = append(traitAlias, alias)
|
||||
}
|
||||
return traitAlias
|
||||
}
|
||||
|
||||
func GetTraitAliasByKind(ctx context.Context, c client.Client, traitKind string) string {
|
||||
var traitAlias string
|
||||
t, err := GetTraitDefinitionByKind(ctx, c, traitKind)
|
||||
if err != nil {
|
||||
return traitKind
|
||||
}
|
||||
|
||||
if traitAlias, err = GetTraitAliasByTraitDefinition(t); err != nil {
|
||||
return traitKind
|
||||
}
|
||||
|
||||
return traitAlias
|
||||
}
|
||||
func GetTraitAliasByTraitDefinition(traitDefinition corev1alpha2.TraitDefinition) (string, error) {
|
||||
velaApplicationFolder := filepath.Join("~/.vela", "applications")
|
||||
if _, err := system.CreateIfNotExist(velaApplicationFolder); err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
d, _ := ioutil.TempDir(velaApplicationFolder, "cue")
|
||||
defer os.RemoveAll(d)
|
||||
template, err := plugins.HandleTemplate(traitDefinition.Spec.Extension, traitDefinition.Name, d)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return template.Name, nil
|
||||
}
|
||||
|
||||
func GetTraitDefinitionByKind(ctx context.Context, c client.Client, traitKind string) (corev1alpha2.TraitDefinition, error) {
|
||||
var traitDefinitionList corev1alpha2.TraitDefinitionList
|
||||
var traitDefinition corev1alpha2.TraitDefinition
|
||||
if err := c.List(ctx, &traitDefinitionList); err != nil {
|
||||
return traitDefinition, err
|
||||
}
|
||||
for _, t := range traitDefinitionList.Items {
|
||||
if t.Annotations["oam.appengine.info/kind"] == traitKind {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return traitDefinition, errors.New(fmt.Sprintf("Could not find TraitDefinition by kind %s", traitKind))
|
||||
}
|
||||
@@ -6,16 +6,17 @@ import (
|
||||
"time"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type ApiServer struct {
|
||||
server *http.Server
|
||||
}
|
||||
|
||||
func (s *ApiServer) Launch() {
|
||||
func (s *ApiServer) Launch(kubeClient client.Client) {
|
||||
s.server = &http.Server{
|
||||
Addr: ":8080",
|
||||
Handler: SetupRoute(),
|
||||
Handler: setupRoute(kubeClient),
|
||||
ReadTimeout: 5 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/server/util"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/oam"
|
||||
"github.com/gin-gonic/gin"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
)
|
||||
@@ -26,6 +33,21 @@ func GetApps(c *gin.Context) {
|
||||
}
|
||||
|
||||
func ListApps(c *gin.Context) {
|
||||
kubeClient := c.MustGet("KubeClient")
|
||||
envName := c.Param("envName")
|
||||
envMeta, err := oam.GetEnvByName(envName)
|
||||
if err != nil {
|
||||
util.HandleError(c, util.StatusInternalServerError, err)
|
||||
}
|
||||
namespace := envMeta.Namespace
|
||||
|
||||
ctx := util.GetContext(c)
|
||||
applicationMetaList, err := oam.RetrieveApplicationsByName(ctx, kubeClient.(client.Client), "", namespace)
|
||||
if err != nil {
|
||||
util.HandleError(c, util.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, applicationMetaList)
|
||||
}
|
||||
|
||||
func DeleteApps(c *gin.Context) {
|
||||
|
||||
@@ -6,13 +6,15 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/server/handler"
|
||||
"github.com/cloud-native-application/rudrx/pkg/server/util"
|
||||
)
|
||||
|
||||
// setup the gin http server handler
|
||||
func SetupRoute() http.Handler {
|
||||
|
||||
func setupRoute(kubeClient client.Client) http.Handler {
|
||||
// create the router
|
||||
router := gin.New()
|
||||
loggerConfig := gin.LoggerConfig{
|
||||
@@ -34,7 +36,8 @@ func SetupRoute() http.Handler {
|
||||
router.Use(util.SetContext())
|
||||
router.Use(gin.Recovery())
|
||||
router.Use(util.ValidateHeaders())
|
||||
|
||||
//Store kubernetes client which could be retrieved by handlers
|
||||
router.Use(util.StoreClient(kubeClient))
|
||||
// all requests start with /api
|
||||
api := router.Group(util.RootPath)
|
||||
// env related operation
|
||||
|
||||
@@ -20,6 +20,7 @@ const (
|
||||
PathNotSupported
|
||||
InvalidArgument
|
||||
UnsupportedMediaType
|
||||
StatusInternalServerError
|
||||
// End marker
|
||||
endMarker
|
||||
)
|
||||
@@ -31,10 +32,10 @@ type errorDetail struct {
|
||||
}
|
||||
|
||||
var errorDetails = map[Code]errorDetail{
|
||||
PathNotSupported: {"PathNotSupported", http.StatusNotFound, "'%s' against '%s' is not supported"},
|
||||
InvalidArgument: {"InvalidArgument", http.StatusBadRequest, "%s"},
|
||||
UnsupportedMediaType: {"UnsupportedMediaType", http.StatusUnsupportedMediaType, "content type should be 'application/json' or 'application/octet-stream'"},
|
||||
}
|
||||
PathNotSupported: {"PathNotSupported", http.StatusNotFound, "'%s' against '%s' is not supported"},
|
||||
InvalidArgument: {"InvalidArgument", http.StatusBadRequest, "%s"},
|
||||
UnsupportedMediaType: {"UnsupportedMediaType", http.StatusUnsupportedMediaType, "content type should be 'application/json' or 'application/octet-stream'"},
|
||||
StatusInternalServerError: {"StatusInternalServerError", http.StatusInternalServerError, "%s"}}
|
||||
|
||||
// ID returns the error ID.
|
||||
func (c Code) ID() string {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// Header Keys
|
||||
@@ -125,3 +126,10 @@ func ValidateHeaders() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func StoreClient(kubeClient client.Client) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Set("KubeClient", kubeClient)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user