Files
cloudpods/cmd/climc/shell/misc/feature.go

193 lines
4.8 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package misc
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/sets"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules/yunionconf"
)
type GlobalSettingsValue struct {
SetupKeys []string `json:"setupKeys"`
SetupKeysVersion string `json:"setupKeysVersion"`
SetupOneStackInitialized bool `json:"setupOneStackInitialized"`
ProductVersion string `json:"productVersion"`
UserDefinedKeys map[string]bool `json:"userDefinedKeys"`
}
func NewGlobalSettingsValue(setupKeys []string, setupOneStack bool) *GlobalSettingsValue {
settings := &GlobalSettingsValue{
SetupOneStackInitialized: setupOneStack,
UserDefinedKeys: make(map[string]bool),
}
for _, key := range setupKeys {
settings.Switch(key, true)
}
return settings
}
func (g *GlobalSettingsValue) Switch(featureKey string, on bool) {
if g.UserDefinedKeys == nil {
g.UserDefinedKeys = map[string]bool{}
}
g.UserDefinedKeys[featureKey] = on
ss := sets.NewString(g.SetupKeys...)
if on {
ss.Insert(featureKey)
} else {
ss.Delete(featureKey)
}
g.SetupKeys = ss.List()
}
func init() {
var storageFeatures = []string{
"s3", "xsky", "ceph",
}
var features = []string{
"onestack",
"baremetal",
"lb",
"aliyun",
"aws",
"azure",
"ctyun",
"google",
"huawei",
"qcloud",
"ucloud",
"ecloud",
"jdcloud",
"vmware",
"openstack",
"dstack",
"zstack",
"apsara",
"cloudpods",
"hcso",
"nutanix",
"bill",
"auth",
"onecloud",
"proxmox",
"public",
"private",
"storage",
"default",
"k8s",
"monitor",
"bingocloud",
"ksyun",
"baidu",
"cucloud",
"qingcloud",
"volcengine",
"oraclecloud",
}
features = append(features, storageFeatures...)
const (
GlobalSettings = "global-settings"
SystemScope = "system"
YunionAgent = "yunionagent"
)
type FeatureCfgOpts struct {
Switch string `help:"Config feature on or off" choices:"on|off"`
}
featureR := func(name string) {
R(&FeatureCfgOpts{}, fmt.Sprintf("feature-config-%s", name), fmt.Sprintf("Set feature %s on or off", name), func(s *mcclient.ClientSession, args *FeatureCfgOpts) error {
enable := true
if args.Switch == "off" {
enable = false
}
items, err := yunionconf.Parameters.List(s, jsonutils.Marshal(map[string]string{
"name": GlobalSettings,
"scope": "system"}))
if err != nil {
return errors.Wrapf(err, "get %s from yunionconf", GlobalSettings)
}
if len(items.Data) == 0 {
// create it if enabled
if enable {
value := []string{name}
if utils.IsInStringArray(name, storageFeatures) {
value = append(value, "storage")
}
input := map[string]interface{}{
"name": GlobalSettings,
"service_id": YunionAgent,
"value": NewGlobalSettingsValue(value, true),
}
params := jsonutils.Marshal(input)
if _, err := yunionconf.Parameters.Create(s, params); err != nil {
return errors.Errorf("create %s for feature %q", GlobalSettings, name)
}
return nil
} else {
return errors.Errorf("not found %s", GlobalSettings)
}
}
if len(items.Data) != 1 {
return errors.Errorf("found %d %q from yunionconf", len(items.Data), GlobalSettings)
}
// update it
ss := items.Data[0]
value, err := ss.Get("value")
if err != nil {
return errors.Wrap(err, "get value")
}
curConf := new(GlobalSettingsValue)
if err := value.Unmarshal(curConf); err != nil {
return errors.Wrapf(err, "unmarshal to GlobalSettingsValue: %s", value)
}
if !enable {
curConf.Switch(name, false)
} else {
curConf.Switch(name, true)
if utils.IsInStringArray(name, storageFeatures) {
curConf.Switch("storage", true)
}
}
id, err := ss.GetString("id")
if err != nil {
return errors.Errorf("get id from %s", ss)
}
ss.(*jsonutils.JSONDict).Set("value", jsonutils.Marshal(curConf))
obj, err := yunionconf.Parameters.Update(s, id, ss)
if err != nil {
return errors.Wrapf(err, "update %s(%s)", GlobalSettings, id)
}
printObject(obj)
return nil
})
}
for _, name := range features {
featureR(name)
}
}