support vela cap:remove

This commit is contained in:
天元
2020-08-12 17:08:14 +08:00
parent 714727d9a1
commit 1baa6a09d1
15 changed files with 288 additions and 144 deletions
+13 -12
View File
@@ -28,17 +28,18 @@ import (
)
type Source struct {
RepoName string `json:"repoName"`
RepoName string `json:"repoName"`
ChartName string `json:"chartName,omitempty"`
}
// Capability defines the content of a capability
type Capability struct {
Name string `json:"name"`
Type DefinitionType `json:"type"`
CueTemplate string `json:"template,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
DefinitionPath string `json:"definition"`
CrdName string `json:"crdName,omitempty"`
Name string `json:"name"`
Type CapType `json:"type"`
CueTemplate string `json:"template,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
DefinitionPath string `json:"definition"`
CrdName string `json:"crdName,omitempty"`
//trait only
AppliesTo []string `json:"appliesTo,omitempty"`
@@ -56,15 +57,15 @@ type Chart struct {
}
type Installation struct {
Helm []Chart `json:"helm"`
Helm Chart `json:"helm"`
}
type DefinitionType string
type CapType string
const (
TypeWorkload DefinitionType = "workload"
TypeTrait DefinitionType = "trait"
TypeScope DefinitionType = "scope"
TypeWorkload CapType = "workload"
TypeTrait CapType = "trait"
TypeScope CapType = "scope"
)
type Parameter struct {
+1
View File
@@ -156,6 +156,7 @@ func PrintHelpByTag(cmd *cobra.Command, all []*cobra.Command, tag string) {
}
}
cmd.Println(table.String())
cmd.Println(" <use 'vela refresh' to sync from cluster or install by `vela cap` >")
cmd.Println()
}
+4 -3
View File
@@ -15,9 +15,10 @@ spec:
extension:
install:
helm:
- repo: stable
name: nginx-ingress
version: 1.41.2
repo: stable
name: nginx-ingress
url: https://kubernetes-charts.storage.googleapis.com/
version: 1.41.2
template: |
#Template: {
apiVersion: "networking.k8s.io/v1beta1"
+2 -1
View File
@@ -6,6 +6,7 @@ require (
cuelang.org/go v0.2.2
github.com/crossplane/crossplane-runtime v0.8.0
github.com/crossplane/oam-kubernetes-runtime v0.0.8
github.com/gertd/go-pluralize v0.1.7
github.com/ghodss/yaml v1.0.0
github.com/gin-gonic/gin v1.6.3
github.com/google/go-github/v32 v32.1.0
@@ -17,8 +18,8 @@ require (
github.com/spf13/cobra v1.0.0
github.com/stretchr/testify v1.6.1
go.uber.org/zap v1.10.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gotest.tools v2.2.0+incompatible
helm.sh/helm/v3 v3.2.4
k8s.io/api v0.18.6
+117 -23
View File
@@ -5,9 +5,14 @@ import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"github.com/ghodss/yaml"
@@ -33,6 +38,7 @@ func CapabilityCommandGroup(parentCmd *cobra.Command, c types.Args, ioStream cmd
NewCapListCommand(ioStream),
NewCapCenterSyncCommand(ioStream),
NewCapAddCommand(c, ioStream),
NewCapRemoveCommand(c, ioStream),
)
}
@@ -70,7 +76,13 @@ func NewCapCenterConfigCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
if err = plugins.StoreRepos(repos); err != nil {
return err
}
ioStreams.Info(fmt.Sprintf("Successfully configured capability center: %s, please use 'vela cap:center:sync %s' to sync capabilities", args[0], args[0]))
ioStreams.Info(fmt.Sprintf("Successfully configured capability center: %s, start to sync from remote", args[0]))
client, err := plugins.NewCenterClient(context.Background(), config.Name, config.Address, config.Token)
err = client.SyncCapabilityFromCenter()
if err != nil {
return err
}
ioStreams.Info("sync finished")
return nil
},
Annotations: map[string]string{
@@ -112,6 +124,38 @@ func NewCapAddCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
return cmd
}
func NewCapRemoveCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "cap:remove <name>",
Short: "Remove capability from cluster",
Long: "Remove capability from cluster",
Example: `vela cap:remove route`,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("you must specify <name> for capability you want to remove")
}
newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
if err != nil {
return err
}
name := args[0]
if strings.Contains(name, "/") {
l := strings.Split(name, "/")
if len(l) > 2 {
return fmt.Errorf("invalid format '%s', you can't contain more than one / in name", name)
}
name = l[1]
}
return RemoveCapability(newClient, name, ioStreams)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeOthers,
},
}
cmd.PersistentFlags().StringP("token", "t", "", "Github Repo token")
return cmd
}
func NewCapCenterSyncCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "cap:center:sync [centerName]",
@@ -151,6 +195,7 @@ func NewCapCenterSyncCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
return err
}
}
ioStreams.Info("sync finished")
return nil
},
Annotations: map[string]string{
@@ -176,7 +221,7 @@ func NewCapListCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
return err
}
table := uitable.New()
table.AddRow("NAME", "TYPE", "DEFINITION", "STATUS", "APPLIES-TO")
table.AddRow("NAME", "CENTER", "TYPE", "DEFINITION", "STATUS", "APPLIES-TO")
if repoName != "" {
if err = ListCenterCapabilities(table, filepath.Join(dir, repoName), ioStreams); err != nil {
return err
@@ -188,7 +233,6 @@ func NewCapListCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
if err != nil {
return err
}
for _, dd := range dirs {
if !dd.IsDir() {
continue
@@ -207,6 +251,53 @@ func NewCapListCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
return cmd
}
func RemoveCapability(client client.Client, capabilityName string, ioStreams cmdutil.IOStreams) error {
// TODO(wonderflow): make sure no apps is using this capability
caps, err := plugins.LoadAllInstalledCapability()
if err != nil {
return err
}
for _, w := range caps {
if w.Name == capabilityName {
return UninstallCap(client, w, ioStreams)
}
}
return errors.New(capabilityName + " not exist")
}
func UninstallCap(client client.Client, cap types.Capability, ioStreams cmdutil.IOStreams) error {
// 1. Remove WorkloadDefinition or TraitDefinition
ctx := context.Background()
var obj runtime.Object
switch cap.Type {
case types.TypeTrait:
obj = &v1alpha2.TraitDefinition{ObjectMeta: v1.ObjectMeta{Name: cap.CrdName, Namespace: types.DefaultOAMNS}}
case types.TypeWorkload:
obj = &v1alpha2.WorkloadDefinition{ObjectMeta: v1.ObjectMeta{Name: cap.CrdName, Namespace: types.DefaultOAMNS}}
}
if err := client.Delete(ctx, obj); err != nil {
return err
}
if cap.Install != nil && cap.Install.Helm.Name != "" {
// 2. Remove Helm chart if there is
if err := HelmUninstall(ioStreams, cap.Install.Helm.Name, cap.Name); err != nil {
return err
}
}
// 3. Remove local capability file
capdir, _ := system.GetCapabilityDir()
switch cap.Type {
case types.TypeTrait:
return os.Remove(filepath.Join(capdir, "traits", cap.Name))
case types.TypeWorkload:
return os.Remove(filepath.Join(capdir, "workloads", cap.Name))
}
ioStreams.Infof("%s removed successfully", cap.Name)
return nil
}
func InstallCapability(client client.Client, centerName, capabilityName string, ioStreams cmdutil.IOStreams) error {
dir, _ := system.GetCapCenterDir()
repoDir := filepath.Join(dir, centerName)
@@ -218,7 +309,6 @@ func InstallCapability(client client.Client, centerName, capabilityName string,
defDir, _ := system.GetCapabilityDir()
switch tp.Type {
case types.TypeWorkload:
defDir = filepath.Join(defDir, "workloads")
var wd v1alpha2.WorkloadDefinition
workloadData, err := ioutil.ReadFile(filepath.Join(repoDir, tp.CrdName+".yaml"))
if err != nil {
@@ -230,6 +320,7 @@ func InstallCapability(client client.Client, centerName, capabilityName string,
wd.Namespace = types.DefaultOAMNS
ioStreams.Info("Installing workload capability " + wd.Name)
if tp.Install != nil {
tp.Source.ChartName = tp.Install.Helm.Name
if err = InstallHelmChart(ioStreams, tp.Install.Helm); err != nil {
return err
}
@@ -238,7 +329,6 @@ func InstallCapability(client client.Client, centerName, capabilityName string,
return err
}
case types.TypeTrait:
defDir = filepath.Join(defDir, "traits")
var td v1alpha2.TraitDefinition
traitdata, err := ioutil.ReadFile(filepath.Join(repoDir, tp.CrdName+".yaml"))
if err != nil {
@@ -250,6 +340,7 @@ func InstallCapability(client client.Client, centerName, capabilityName string,
td.Namespace = types.DefaultOAMNS
ioStreams.Info("Installing trait capability " + td.Name)
if tp.Install != nil {
tp.Source.ChartName = tp.Install.Helm.Name
if err = InstallHelmChart(ioStreams, tp.Install.Helm); err != nil {
return err
}
@@ -268,19 +359,14 @@ func InstallCapability(client client.Client, centerName, capabilityName string,
return nil
}
func InstallHelmChart(ioStreams cmdutil.IOStreams, charts []types.Chart) error {
for _, c := range charts {
if err := HelmInstall(ioStreams, c.Repo, c.URl, c.Name, c.Version, c.Name); err != nil {
return err
}
}
return nil
func InstallHelmChart(ioStreams cmdutil.IOStreams, c types.Chart) error {
return HelmInstall(ioStreams, c.Repo, c.URl, c.Name, c.Version, c.Name)
}
func GetSyncedCapabilities(repoName, addonName string) (types.Capability, error) {
dir, _ := system.GetCapCenterDir()
repoDir := filepath.Join(dir, repoName)
templates, err := plugins.LoadCapabilityFromLocal(repoDir)
templates, err := plugins.LoadCapabilityFromSyncedCenter(repoDir)
if err != nil {
return types.Capability{}, err
}
@@ -293,7 +379,7 @@ func GetSyncedCapabilities(repoName, addonName string) (types.Capability, error)
}
func ListCenterCapabilities(table *uitable.Table, repoDir string, ioStreams cmdutil.IOStreams) error {
templates, err := plugins.LoadCapabilityFromLocal(repoDir)
templates, err := plugins.LoadCapabilityFromSyncedCenter(repoDir)
if err != nil {
return err
}
@@ -301,23 +387,31 @@ func ListCenterCapabilities(table *uitable.Table, repoDir string, ioStreams cmdu
return nil
}
baseDir := filepath.Base(repoDir)
workloads := GatherWorkloads(templates)
for _, p := range templates {
status := CheckInstallStatus(baseDir, p)
table.AddRow(baseDir+"/"+p.Name, p.Type, p.Type, status, p.AppliesTo)
convertedApplyTo := ConvertApplyTo(p.AppliesTo, workloads)
table.AddRow(p.Name, baseDir, p.Type, p.CrdName, status, convertedApplyTo)
}
return nil
}
func GatherWorkloads(templates []types.Capability) []types.Capability {
workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
if err != nil {
workloads = make([]types.Capability, 0)
}
for _, t := range templates {
if t.Type == types.TypeWorkload {
workloads = append(workloads, t)
}
}
return workloads
}
func CheckInstallStatus(repoName string, tmp types.Capability) string {
var status = "uninstalled"
dir, _ := system.GetCapabilityDir()
switch tmp.Type {
case types.TypeTrait:
dir = filepath.Join(dir, "traits")
case types.TypeWorkload:
dir = filepath.Join(dir, "workloads")
}
installed, _ := plugins.LoadTempFromLocal(dir)
installed, _ := plugins.LoadInstalledCapabilityWithType(tmp.Type)
for _, i := range installed {
if i.Source != nil && i.Source.RepoName == repoName && i.Name == tmp.Name && i.CrdName == tmp.CrdName {
return "installed"
+4 -9
View File
@@ -2,7 +2,6 @@ package cmd
import (
"context"
"path/filepath"
"github.com/cloud-native-application/rudrx/api/types"
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
@@ -43,10 +42,8 @@ func RefreshDefinitions(ctx context.Context, c client.Client, ioStreams cmdutil.
if err != nil {
return err
}
workloadDir := filepath.Join(dir, "workloads")
system.StatAndCreate(workloadDir)
ioStreams.Infof("get %d workload definitions from cluster, syncing to %s...", len(templates), workloadDir)
successNum := plugins.SinkTemp2Local(templates, workloadDir)
ioStreams.Infof("get %d workload definitions from cluster, syncing...", len(templates))
successNum := plugins.SinkTemp2Local(templates, dir)
ioStreams.Infof("%d workload definitions successfully synced\n", successNum)
ioStreams.Info("syncing trait definitions from cluster...")
@@ -54,10 +51,8 @@ func RefreshDefinitions(ctx context.Context, c client.Client, ioStreams cmdutil.
if err != nil {
return err
}
traitDir := filepath.Join(dir, "traits")
system.StatAndCreate(traitDir)
ioStreams.Infof("get %d trait definitions from cluster, syncing to %s...", len(templates), traitDir)
successNum = plugins.SinkTemp2Local(templates, traitDir)
ioStreams.Infof("get %d trait definitions from cluster, syncing...", len(templates))
successNum = plugins.SinkTemp2Local(templates, dir)
ioStreams.Infof("%d trait definitions successfully synced\n", successNum)
return nil
}
+30 -2
View File
@@ -220,9 +220,24 @@ func HelmInstall(ioStreams cmdutil.IOStreams, repoName, repoUrl, chartName, vers
return nil
}
func HelmUninstall(ioStreams cmdutil.IOStreams, chartName, releaseName string) error {
if !IsHelmReleaseRunning(releaseName, chartName, ioStreams) {
return nil
}
uninstall, err := NewHelmUninstall()
if err != nil {
return err
}
_, err = uninstall.Run(releaseName)
if err != nil {
return err
}
ioStreams.Infof("Successfully removed %s with release name %s\n", chartName, releaseName)
return nil
}
func NewHelmInstall(version, releaseName string, ioStreams cmdutil.IOStreams) (*action.Install, error) {
actionConfig := new(action.Configuration)
if err := actionConfig.Init(
kube.GetConfig(cmdutil.GetKubeConfig(), "", types.DefaultOAMNS),
types.DefaultOAMNS,
@@ -233,12 +248,25 @@ func NewHelmInstall(version, releaseName string, ioStreams cmdutil.IOStreams) (*
}
client := action.NewInstall(actionConfig)
client.Namespace = types.DefaultOAMNS
client.ReleaseName = releaseName
client.Version = version
return client, nil
}
func NewHelmUninstall() (*action.Uninstall, error) {
actionConfig := new(action.Configuration)
if err := actionConfig.Init(
kube.GetConfig(cmdutil.GetKubeConfig(), "", types.DefaultOAMNS),
types.DefaultOAMNS,
os.Getenv("HELM_DRIVER"),
debug,
); err != nil {
return nil, err
}
return action.NewUninstall(actionConfig), nil
}
func debug(format string, v ...interface{}) {
if settings.Debug {
format = fmt.Sprintf("[debug] %s\n", format)
+2 -7
View File
@@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"fmt"
"path/filepath"
"strconv"
"strings"
@@ -13,8 +12,6 @@ import (
"cuelang.org/go/cue"
"github.com/cloud-native-application/rudrx/pkg/utils/system"
"k8s.io/apimachinery/pkg/runtime"
"github.com/cloud-native-application/rudrx/pkg/plugins"
@@ -45,8 +42,7 @@ func NewCommandOptions(ioStreams cmdutil.IOStreams) *commandOptions {
}
func AddTraitCommands(parentCmd *cobra.Command, c types.Args, ioStreams cmdutil.IOStreams) error {
dir, _ := system.GetCapabilityDir()
templates, err := plugins.LoadTempFromLocal(filepath.Join(dir, "traits"))
templates, err := plugins.LoadInstalledCapabilityWithType(types.TypeTrait)
if err != nil {
return err
}
@@ -172,8 +168,7 @@ func (o *commandOptions) Complete(cmd *cobra.Command, args []string, ctx context
}
func AddTraitDetachCommands(parentCmd *cobra.Command, c types.Args, ioStreams cmdutil.IOStreams) error {
dir, _ := system.GetCapabilityDir()
templates, err := plugins.LoadTempFromLocal(filepath.Join(dir, "traits"))
templates, err := plugins.LoadInstalledCapabilityWithType(types.TypeTrait)
if err != nil {
return err
}
+18 -7
View File
@@ -1,15 +1,14 @@
package cmd
import (
"path/filepath"
"strings"
"github.com/cloud-native-application/rudrx/api/types"
"github.com/cloud-native-application/rudrx/pkg/plugins"
"github.com/cloud-native-application/rudrx/pkg/utils/system"
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
plur "github.com/gertd/go-pluralize"
"github.com/gosuri/uitable"
"github.com/spf13/cobra"
)
@@ -23,12 +22,11 @@ func NewTraitsCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
Long: "List traits",
Example: `vela traits`,
RunE: func(cmd *cobra.Command, args []string) error {
dir, _ := system.GetCapabilityDir()
templates, err := plugins.LoadTempFromLocal(filepath.Join(dir, "traits"))
templates, err := plugins.LoadInstalledCapabilityWithType(types.TypeTrait)
if err != nil {
return err
}
workloads, err := plugins.LoadTempFromLocal(filepath.Join(dir, "workloads"))
workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
if err != nil {
return err
}
@@ -83,9 +81,22 @@ func ConvertApplyTo(applyTo []string, workloads []types.Capability) []string {
return converted
}
func check(crdname string, workloads []types.Capability) (string, bool) {
func parse(applyTo string) string {
l := strings.Split(applyTo, "/")
if len(l) != 2 {
return applyTo
}
apigroup, versionKind := l[0], l[1]
l = strings.Split(versionKind, ".")
if len(l) != 2 {
return applyTo
}
return plur.NewClient().Plural(strings.ToLower(l[1])) + "." + apigroup
}
func check(applyto string, workloads []types.Capability) (string, bool) {
for _, v := range workloads {
if crdname == v.CrdName {
if parse(applyto) == v.CrdName {
return v.Name, true
}
}
+12 -5
View File
@@ -15,13 +15,15 @@ import (
func Test_printTraitList(t *testing.T) {
traits := []types.Capability{
{
Name: "route",
CrdName: "routes.oam.dev",
AppliesTo: []string{"deployments.apps", "clonsets.alibaba"},
Name: "route",
CrdName: "routes.oam.dev",
// This format is currently OAM spec standard
AppliesTo: []string{"apps/v1.Deployment", "alibaba/v1.Clonset"},
},
{
Name: "scaler",
CrdName: "scaler.oam.dev",
Name: "scaler",
CrdName: "scaler.oam.dev",
// This format is also reasonable, it's align with oam definition name, so we also support here
AppliesTo: []string{"deployments.apps"},
},
}
@@ -86,3 +88,8 @@ func Test_printTraitList(t *testing.T) {
assert.Equal(t, c.ExpectedString, b.String(), cname)
}
}
func TestParse(t *testing.T) {
assert.Equal(t, "containerizedworkloads.core.oam.dev", parse("core.oam.dev/v1alpha2.ContainerizedWorkload"))
assert.Equal(t, "containerizedworkloads.core.oam.dev", parse("containerizedworkloads.core.oam.dev"))
}
+1 -2
View File
@@ -48,8 +48,7 @@ func newRunOptions(ioStreams cmdutil.IOStreams) *runOptions {
}
func AddWorkloadCommands(parentCmd *cobra.Command, c types.Args, ioStreams cmdutil.IOStreams) error {
dir, _ := system.GetCapabilityDir()
templates, err := plugins.LoadTempFromLocal(filepath.Join(dir, "workloads"))
templates, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
if err != nil {
return err
}
+1 -5
View File
@@ -1,12 +1,9 @@
package cmd
import (
"path/filepath"
"github.com/cloud-native-application/rudrx/api/types"
"github.com/cloud-native-application/rudrx/pkg/plugins"
"github.com/cloud-native-application/rudrx/pkg/utils/system"
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
"github.com/gosuri/uitable"
@@ -21,8 +18,7 @@ func NewWorkloadsCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
Long: "List workloads",
Example: `vela workloads`,
RunE: func(cmd *cobra.Command, args []string) error {
dir, _ := system.GetCapabilityDir()
workloads, err := plugins.LoadTempFromLocal(filepath.Join(dir, "workloads"))
workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
if err != nil {
return err
}
+1 -1
View File
@@ -71,7 +71,7 @@ func GetTraitsFromCluster(ctx context.Context, namespace string, c client.Client
return templates, nil
}
func HandleDefinition(name, syncDir, crdName string, extention *runtime.RawExtension, tp types.DefinitionType, applyTo []string) (types.Capability, error) {
func HandleDefinition(name, syncDir, crdName string, extention *runtime.RawExtension, tp types.CapType, applyTo []string) (types.Capability, error) {
var tmp types.Capability
tmp, err := HandleTemplate(extention, name, syncDir)
if err != nil {
+79 -57
View File
@@ -10,73 +10,34 @@ import (
"strings"
"github.com/cloud-native-application/rudrx/api/types"
"github.com/cloud-native-application/rudrx/pkg/utils/system"
)
func GetDefFromLocal(dir string, defType types.DefinitionType) ([]types.Capability, error) {
temps, err := LoadTempFromLocal(dir)
func LoadAllInstalledCapability() ([]types.Capability, error) {
workloads, err := LoadInstalledCapabilityWithType(types.TypeWorkload)
if err != nil {
return nil, err
}
var defs []types.Capability
for _, t := range temps {
if t.Type != defType {
continue
}
defs = append(defs, t)
}
return defs, nil
}
func SinkTemp2Local(templates []types.Capability, dir string) int {
success := 0
for _, tmp := range templates {
data, err := json.Marshal(tmp)
if err != nil {
fmt.Printf("sync %s err: %v\n", tmp.Name, err)
continue
}
err = ioutil.WriteFile(filepath.Join(dir, tmp.Name), data, 0644)
if err != nil {
fmt.Printf("sync %s err: %v\n", tmp.Name, err)
continue
}
success++
}
return success
}
func LoadCapabilityFromLocal(dir string) ([]types.Capability, error) {
var tmps []types.Capability
files, err := ioutil.ReadDir(dir)
traits, err := LoadInstalledCapabilityWithType(types.TypeTrait)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
for _, f := range files {
if f.IsDir() {
continue
}
if strings.HasSuffix(f.Name(), ".cue") {
continue
}
data, err := ioutil.ReadFile(filepath.Join(dir, f.Name()))
if err != nil {
fmt.Printf("read file %s err %v\n", f.Name(), err)
continue
}
tmp, err := ParseAndSyncCapability(data, filepath.Join(dir, ".tmp"))
if err != nil {
fmt.Printf("get definition of %s err %v\n", f.Name(), err)
continue
}
tmps = append(tmps, tmp)
}
return tmps, nil
workloads = append(workloads, traits...)
return workloads, nil
}
func LoadTempFromLocal(dir string) ([]types.Capability, error) {
func LoadInstalledCapabilityWithType(capT types.CapType) ([]types.Capability, error) {
dir, _ := system.GetCapabilityDir()
return loadInstalledCapabilityWithType(dir, capT)
}
// leave dir as argument for test convenience
func loadInstalledCapabilityWithType(dir string, capT types.CapType) ([]types.Capability, error) {
dir = GetSubDir(dir, capT)
return loadInstalledCapability(dir)
}
func loadInstalledCapability(dir string) ([]types.Capability, error) {
var tmps []types.Capability
files, err := ioutil.ReadDir(dir)
if err != nil {
@@ -108,3 +69,64 @@ func LoadTempFromLocal(dir string) ([]types.Capability, error) {
}
return tmps, nil
}
func GetSubDir(dir string, capT types.CapType) string {
switch capT {
case types.TypeWorkload:
return filepath.Join(dir, "workloads")
case types.TypeTrait:
return filepath.Join(dir, "traits")
}
return dir
}
func SinkTemp2Local(templates []types.Capability, dir string) int {
success := 0
for _, tmp := range templates {
subDir := GetSubDir(dir, tmp.Type)
system.StatAndCreate(subDir)
data, err := json.Marshal(tmp)
if err != nil {
fmt.Printf("sync %s err: %v\n", tmp.Name, err)
continue
}
err = ioutil.WriteFile(filepath.Join(subDir, tmp.Name), data, 0644)
if err != nil {
fmt.Printf("sync %s err: %v\n", tmp.Name, err)
continue
}
success++
}
return success
}
func LoadCapabilityFromSyncedCenter(dir string) ([]types.Capability, error) {
var tmps []types.Capability
files, err := ioutil.ReadDir(dir)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
for _, f := range files {
if f.IsDir() {
continue
}
if strings.HasSuffix(f.Name(), ".cue") {
continue
}
data, err := ioutil.ReadFile(filepath.Join(dir, f.Name()))
if err != nil {
fmt.Printf("read file %s err %v\n", f.Name(), err)
continue
}
tmp, err := ParseAndSyncCapability(data, filepath.Join(dir, ".tmp"))
if err != nil {
fmt.Printf("get definition of %s err %v\n", f.Name(), err)
continue
}
tmps = append(tmps, tmp)
}
return tmps, nil
}
+3 -10
View File
@@ -47,7 +47,7 @@ func TestLocalSink(t *testing.T) {
cases := map[string]struct {
dir string
tmps []types.Capability
Type types.DefinitionType
Type types.CapType
expDef []types.Capability
err error
}{
@@ -91,21 +91,14 @@ func TestLocalSink(t *testing.T) {
}
}
func testInDir(t *testing.T, casename, dir string, tmps, defexp []types.Capability, Type types.DefinitionType, err1 error) {
func testInDir(t *testing.T, casename, dir string, tmps, defexp []types.Capability, Type types.CapType, err1 error) {
err := os.MkdirAll(dir, 0755)
assert.NoError(t, err, casename)
defer os.RemoveAll(dir)
number := SinkTemp2Local(tmps, dir)
assert.Equal(t, len(tmps), number)
gottmps, err := LoadTempFromLocal(dir)
if err1 != nil {
assert.Equal(t, err1, err)
} else {
assert.NoError(t, err, casename)
}
assert.Equal(t, tmps, gottmps, casename)
if Type != "" {
gotDef, err := GetDefFromLocal(dir, Type)
gotDef, err := loadInstalledCapabilityWithType(dir, Type)
assert.NoError(t, err, casename)
assert.Equal(t, defexp, gotDef, casename)
}