chore: remove unused configs code

This commit is contained in:
liugq 2024-12-02 12:14:36 +08:00
parent f87f3c6599
commit 655725f6ad
12 changed files with 10 additions and 785 deletions

View File

@ -12,7 +12,7 @@
# must in major config file
path.configs: "config"
configs:
managed: true
managed: false
auto_reload: true
manager:
local_configs_repo_path: ./config_repo/

View File

@ -8,7 +8,7 @@ import (
"bytes"
"fmt"
log "github.com/cihub/seelog"
"infini.sh/console/plugin/managed/common"
"infini.sh/framework/modules/configs/common"
"infini.sh/framework/core/elastic"
"infini.sh/framework/core/global"
"infini.sh/framework/core/kv"

View File

@ -7,7 +7,7 @@ package common
import (
log "github.com/cihub/seelog"
"infini.sh/console/modules/agent/model"
"infini.sh/console/plugin/managed/common"
"infini.sh/framework/modules/configs/common"
"infini.sh/framework/core/env"
)

View File

@ -1,261 +0,0 @@
/* Copyright © INFINI LTD. All rights reserved.
* Web: https://infinilabs.com
* Email: hello#infini.ltd */
package client
import (
"context"
"fmt"
log "github.com/cihub/seelog"
"infini.sh/console/plugin/managed/common"
"infini.sh/console/plugin/managed/config"
"infini.sh/framework/core/api"
"infini.sh/framework/core/errors"
"infini.sh/framework/core/global"
"infini.sh/framework/core/keystore"
"infini.sh/framework/core/kv"
"infini.sh/framework/core/model"
"infini.sh/framework/core/task"
"infini.sh/framework/core/util"
"net/http"
"net/url"
"os"
"path/filepath"
"sync"
"time"
)
const bucketName = "instance_registered"
const configRegisterEnvKey = "CONFIG_MANAGED_SUCCESS"
func ConnectToManager() error {
if !global.Env().SystemConfig.Configs.Managed {
return nil
}
if exists, err := kv.ExistsKey(bucketName, []byte(global.Env().SystemConfig.NodeConfig.ID)); exists && err == nil {
//already registered skip further process
log.Info("already registered to config manager")
global.Register(configRegisterEnvKey, true)
return nil
}
log.Info("register new instance to config manager")
//register to config manager
if global.Env().SystemConfig.Configs.Servers == nil || len(global.Env().SystemConfig.Configs.Servers) == 0 {
return errors.Errorf("no config manager was found")
}
info := model.GetInstanceInfo()
req := util.Request{Method: util.Verb_POST}
req.ContentType = "application/json"
req.Path = common.REGISTER_API
req.Body = util.MustToJSONBytes(info)
server, res, err := submitRequestToManager(&req)
if err == nil && server != "" {
if res.StatusCode == 200 || util.ContainStr(string(res.Body), "exists") {
log.Infof("success register to config manager: %v", string(server))
err := kv.AddValue(bucketName, []byte(global.Env().SystemConfig.NodeConfig.ID), []byte(util.GetLowPrecisionCurrentTime().String()))
if err != nil {
panic(err)
}
global.Register(configRegisterEnvKey, true)
}
} else {
log.Error("failed to register to config manager,", err, ",", server)
}
return err
}
func submitRequestToManager(req *util.Request) (string, *util.Result, error) {
var err error
var res *util.Result
for _, server := range global.Env().SystemConfig.Configs.Servers {
req.Url, err = url.JoinPath(server, req.Path)
if err != nil {
continue
}
res, err = util.ExecuteRequestWithCatchFlag(mTLSClient, req, true)
if err != nil {
continue
}
return server, res, nil
}
return "", nil, err
}
var clientInitLock = sync.Once{}
var mTLSClient *http.Client
func ListenConfigChanges() error {
clientInitLock.Do(func() {
if global.Env().SystemConfig.Configs.Managed {
//init client
cfg := global.Env().GetClientConfigByEndpoint("configs", "")
if cfg != nil {
hClient, err := api.NewHTTPClient(cfg)
if err != nil {
panic(err)
}
mTLSClient = hClient
}
//init config sync listening
req := common.ConfigSyncRequest{}
req.Client = model.GetInstanceInfo()
var syncFunc = func() {
if global.Env().IsDebug {
log.Trace("fetch configs from manger")
}
cfgs := config.GetConfigs(false, false)
req.Configs = cfgs
req.Hash = util.MD5digestString(util.MustToJSONBytes(cfgs))
//fetch configs from manager
request := util.Request{Method: util.Verb_POST}
request.ContentType = "application/json"
request.Path = common.SYNC_API
request.Body = util.MustToJSONBytes(req)
if global.Env().IsDebug {
log.Debug("config sync request: ", string(util.MustToJSONBytes(req)))
}
_, res, err := submitRequestToManager(&request)
if err != nil {
log.Error("failed to submit request to config manager,", err)
return
}
if res != nil {
obj := common.ConfigSyncResponse{}
err := util.FromJSONBytes(res.Body, &obj)
if err != nil {
panic(err)
}
if global.Env().IsDebug {
log.Debug("config sync response: ", string(res.Body))
}
if obj.Changed {
//update secrets //TODO client send salt to manager first, manager encrypt secrets with salt and send back
if obj.Secrets != nil {
for k, v := range obj.Secrets.Keystore {
if v.Type == "plaintext" {
err := saveKeystore(k, v.Value)
if err != nil {
log.Error("error on save keystore:", k, ",", err)
}
}
}
//TODO maybe we have other secrets
}
for _, v := range obj.Configs.DeletedConfigs {
if v.Managed {
err := config.DeleteConfig(v.Name)
if err != nil {
panic(err)
}
} else {
log.Error("config [", v.Name, "] is not managed by config manager, skip deleting")
}
}
for _, v := range obj.Configs.CreatedConfigs {
err := config.SaveConfig(v.Name, v)
if err != nil {
panic(err)
}
}
for _, v := range obj.Configs.UpdatedConfigs {
err := config.SaveConfig(v.Name, v)
if err != nil {
panic(err)
}
}
var keyValuePairs = []util.KeyValue{}
//checking backup files, remove old configs, only keep max num of files
filepath.Walk(global.Env().SystemConfig.PathConfig.Config, func(file string, f os.FileInfo, err error) error {
//only allow to delete backup files
if !util.SuffixStr(file, ".bak") {
return nil
}
keyValuePairs = append(keyValuePairs, util.KeyValue{Key: file, Value: f.ModTime().Unix()})
return nil
})
if len(keyValuePairs) > 0 {
keyValuePairs = util.SortKeyValueArray(keyValuePairs, true)
if len(keyValuePairs) > global.Env().SystemConfig.Configs.MaxBackupFiles {
tobeDeleted := keyValuePairs[global.Env().SystemConfig.Configs.MaxBackupFiles:]
for _, v := range tobeDeleted {
log.Debug("delete config file: ", v.Key)
err := util.FileDelete(v.Key)
if err != nil {
panic(err)
}
}
}
}
}
}
}
syncFunc()
if !global.Env().SystemConfig.Configs.ScheduledTask {
log.Debug("register background task for checking configs changes")
global.RegisterBackgroundCallback(&global.BackgroundTask{
Tag: "checking configs changes",
Interval: util.GetDurationOrDefault(global.Env().SystemConfig.Configs.Interval, time.Duration(30)*time.Second),
Func: syncFunc,
})
} else {
log.Debug("register schedule task for checking configs changes")
task.RegisterScheduleTask(task.ScheduleTask{
Description: fmt.Sprintf("sync configs from manager"),
Type: "interval",
Interval: global.Env().SystemConfig.Configs.Interval,
Task: func(ctx context.Context) {
syncFunc()
},
})
}
}
})
return nil
}
func saveKeystore(k string, v string) error {
log.Debug("save keystore:", k)
ks, err := keystore.GetWriteableKeystore()
if err != nil {
return err
}
err = ks.Store(k, util.UnsafeStringToBytes(v))
if err != nil {
return err
}
err = ks.Save()
return err
}

View File

@ -1,43 +0,0 @@
/* Copyright © INFINI LTD. All rights reserved.
* Web: https://infinilabs.com
* Email: hello#infini.ltd */
package common
import (
"crypto/x509"
"encoding/pem"
log "github.com/cihub/seelog"
"infini.sh/framework/core/global"
"infini.sh/framework/core/util"
"os"
"path"
)
func GetOrInitDefaultCaCerts()(string, string, error){
dataDir := global.Env().GetDataDir()
caFile := path.Join(dataDir, "certs/ca.crt")
caKey := path.Join(dataDir, "certs/ca.key")
if !(util.FileExists(caFile) && util.FileExists(caKey) ) {
err := os.MkdirAll(path.Join(dataDir, "certs"), 0775)
if err != nil {
return "", "", err
}
log.Info("auto generating cert files")
_, rootKey, rootCertPEM := util.GetRootCert()
caKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rootKey),
})
_, err = util.FilePutContentWithByte(caKey, caKeyPEM)
if err != nil {
return "", "", err
}
_, err = util.FilePutContentWithByte(caFile, rootCertPEM)
if err != nil {
return "", "", err
}
}
return caFile, caKey, nil
}

View File

@ -1,89 +0,0 @@
/* Copyright © INFINI LTD. All rights reserved.
* Web: https://infinilabs.com
* Email: hello#infini.ltd */
package common
import "infini.sh/framework/core/model"
const REGISTER_API = "/instance/_register"
const SYNC_API = "/configs/_sync"
const GET_INSTALL_SCRIPT_API = "/instance/_get_install_script"
type ConfigFile struct {
Name string `json:"name,omitempty"`
Location string `json:"location,omitempty"`
Content string `json:"content,omitempty"`
Updated int64 `json:"updated,omitempty"`
Version int64 `json:"version,omitempty"`
Size int64 `json:"size,omitempty"`
Readonly bool `json:"readonly,omitempty"`
Managed bool `json:"managed"`
Hash string `json:"hash,omitempty"`
}
type ConfigList struct {
Main ConfigFile `json:"main,omitempty"`
Configs map[string]ConfigFile `json:"configs,omitempty"`
}
type ConfigDeleteRequest struct {
Configs []string `json:"configs"`
}
type ConfigUpdateRequest struct {
Configs map[string]string `json:"configs"`
}
type ConfigSyncRequest struct {
ForceSync bool `json:"force_sync"` //ignore hash check in server
Hash string `json:"hash"`
Client model.Instance `json:"client"`
Configs ConfigList `json:"configs"`
}
type ConfigSyncResponse struct {
Changed bool `json:"changed"`
Configs struct {
CreatedConfigs map[string]ConfigFile `json:"created,omitempty"`
DeletedConfigs map[string]ConfigFile `json:"deleted,omitempty"`
UpdatedConfigs map[string]ConfigFile `json:"updated,omitempty"`
} `json:"configs,omitempty"`
Secrets *Secrets `json:"secrets,omitempty"`
}
type ResourceGroup struct {
Name string `json:"name"`
List []string `json:"list"`
}
type ConfigGroup struct {
Files []string `config:"files"`
}
type InstanceGroup struct {
ConfigGroups []string `config:"configs"`
Instances []string `config:"instances"`
Secrets []string `config:"secrets"`
}
type Secrets struct {
Keystore map[string]KeystoreValue `json:"keystore,omitempty"`
}
type KeystoreValue struct {
Type string `json:"type"`
Value string `json:"value"`
}
type ConfigRepo struct {
ConfigGroups map[string]ConfigGroup `config:"configs"`
InstanceGroups map[string]InstanceGroup `config:"instances"`
SecretGroups map[string]Secrets `config:"secrets"`
}
type InstanceSettings struct {
ConfigFiles []string `config:"configs"`
Secrets []string `config:"secrets"`
}

View File

@ -1,339 +0,0 @@
/* ©INFINI, All Rights Reserved.
* mail: contact#infini.ltd */
package config
import (
"fmt"
log "github.com/cihub/seelog"
"infini.sh/console/core"
"infini.sh/console/plugin/managed/common"
"infini.sh/framework/core/api"
httprouter "infini.sh/framework/core/api/router"
"infini.sh/framework/core/env"
"infini.sh/framework/core/errors"
"infini.sh/framework/core/global"
"infini.sh/framework/core/util"
"infini.sh/framework/core/util/file"
"net/http"
"os"
"path"
"path/filepath"
"regexp"
"strings"
"time"
)
func init() {
api.HandleAPIMethod(api.GET, "/config/", h.listConfigAction)
api.HandleAPIMethod(api.PUT, "/config/", h.saveConfigAction)
api.HandleAPIMethod(api.DELETE, "/config/", h.deleteConfigAction)
api.HandleAPIMethod(api.POST, "/config/_reload", h.reloadConfigAction)
api.HandleAPIMethod(api.GET, "/config/runtime", h.getConfigAction)
api.HandleAPIMethod(api.GET, "/environments", h.getEnvAction)
}
var h = DefaultHandler{}
type DefaultHandler struct {
core.Handler
}
func (handler DefaultHandler) getEnvAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
handler.WriteJSONHeader(w)
handler.WriteJSON(w, os.Environ(), 200)
}
func (handler DefaultHandler) getConfigAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
json := env.GetConfigAsJSON()
handler.WriteJSONHeader(w)
handler.Write(w, []byte(json))
}
func validateFile(cfgDir, name string) error {
cfgDir, _ = filepath.Abs(cfgDir)
name, _ = filepath.Abs(name)
//filter out the hidden files and go files
if strings.HasPrefix(filepath.Base(name), ".") || strings.HasSuffix(filepath.Base(name), ".go") {
return errors.Errorf("invalid config filename")
}
//filetype checking
ext := filepath.Ext(name)
if len(global.Env().SystemConfig.Configs.ValidConfigsExtensions) > 0 && !util.ContainsAnyInArray(ext, global.Env().SystemConfig.Configs.ValidConfigsExtensions) {
return errors.Errorf("invalid config file: %s, only support: %v", name, global.Env().SystemConfig.Configs.ValidConfigsExtensions)
}
//permission checking
if !util.IsFileWithinFolder(name, cfgDir) {
return errors.Errorf("invalid config file: %s, outside of path: %v", name, cfgDir)
}
return nil
}
func DeleteConfig(name string) error {
cfgDir, err := filepath.Abs(global.Env().GetConfigDir())
if err != nil {
return err
}
fileToDelete := path.Join(cfgDir, name)
log.Info("delete config file: ", fileToDelete)
//file checking
if err := validateFile(cfgDir, fileToDelete); err != nil {
return err
}
if util.FileExists(fileToDelete) {
if global.Env().SystemConfig.Configs.SoftDelete {
err := util.Rename(fileToDelete, fmt.Sprintf("%v.%v.bak", fileToDelete, time.Now().UnixMilli()))
if err != nil {
return err
}
} else {
err := util.FileDelete(fileToDelete)
if err != nil {
return err
}
}
} else {
return errors.Errorf("file not exists: %s", fileToDelete)
}
return nil
}
func SaveConfig(name string, cfg common.ConfigFile) error {
//update version
if cfg.Managed {
cfg.Content = updateConfigVersion(cfg.Content, cfg.Version)
cfg.Content = updateConfigManaged(cfg.Content, true)
}
return SaveConfigStr(name, cfg.Content)
}
func SaveConfigStr(name, content string) error {
cfgDir, err := filepath.Abs(global.Env().GetConfigDir())
if err != nil {
return err
}
fileToSave := path.Join(cfgDir, name)
log.Info("write config file: ", fileToSave)
log.Trace("file content: ", content)
if err := validateFile(cfgDir, fileToSave); err != nil {
return err
}
if util.FileExists(fileToSave) {
if global.Env().SystemConfig.Configs.SoftDelete {
err := util.Rename(fileToSave, fmt.Sprintf("%v.%v.bak", fileToSave, time.Now().UnixMilli()))
if err != nil {
return err
}
}
}
_, err = util.FilePutContent(fileToSave, content)
if err != nil {
return err
}
return nil
}
func (handler DefaultHandler) deleteConfigAction(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
reqBody := common.ConfigDeleteRequest{}
err := handler.DecodeJSON(req, &reqBody)
if err != nil {
panic(err)
}
for _, name := range reqBody.Configs {
err := DeleteConfig(name)
if err != nil {
panic(err)
}
}
handler.WriteAckOKJSON(w)
}
var versionRegexp = regexp.MustCompile(`#MANAGED_CONFIG_VERSION:\s*(?P<version>\d+)`)
var managedRegexp = regexp.MustCompile(`#MANAGED:\s*(?P<managed>\w+)`)
func parseConfigVersion(input string) int64 {
matches := versionRegexp.FindStringSubmatch(util.TrimSpaces(input))
if len(matches) > 0 {
ver := versionRegexp.SubexpIndex("version")
if ver >= 0 {
str := (matches[ver])
v, err := util.ToInt64(util.TrimSpaces(str))
if err != nil {
log.Error(err)
}
return v
}
}
return -1
}
func parseConfigManaged(input string, defaultManaged bool) bool {
matches := managedRegexp.FindStringSubmatch(util.TrimSpaces(input))
if len(matches) > 0 {
v := managedRegexp.SubexpIndex("managed")
if v >= 0 {
str := util.TrimSpaces(strings.ToLower(matches[v]))
if str == "true" {
return true
} else if str == "false" {
return false
}
}
}
return defaultManaged
}
func updateConfigManaged(input string, managed bool) string {
if managedRegexp.MatchString(input) {
return managedRegexp.ReplaceAllString(input, fmt.Sprintf("#MANAGED: %v", managed))
} else {
return fmt.Sprintf("%v\n#MANAGED: %v", input, managed)
}
}
func updateConfigVersion(input string, newVersion int64) string {
if versionRegexp.MatchString(input) {
return versionRegexp.ReplaceAllString(input, fmt.Sprintf("#MANAGED_CONFIG_VERSION: %d", newVersion))
} else {
return fmt.Sprintf("%v\n#MANAGED_CONFIG_VERSION: %d", input, newVersion)
}
}
func (handler DefaultHandler) listConfigAction(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
configs := GetConfigs(true, false)
handler.WriteJSON(w, configs, 200)
}
func GetConfigs(returnContent, managedOnly bool) common.ConfigList {
cfgDir, err := filepath.Abs(global.Env().GetConfigDir())
if err != nil {
panic(err)
}
configs := common.ConfigList{}
configs.Configs = make(map[string]common.ConfigFile)
mainConfig, _ := filepath.Abs(global.Env().GetConfigFile())
info, err := file.Stat(mainConfig)
if err != nil {
panic(err)
}
c, err := util.FileGetContent(mainConfig)
if err != nil {
panic(err)
}
configs.Main = common.ConfigFile{
Name: util.TrimLeftStr(filepath.Base(mainConfig), cfgDir),
Location: mainConfig,
Readonly: true,
Managed: false,
Updated: info.ModTime().Unix(),
Size: info.Size(),
}
if returnContent {
configs.Main.Content = string(c)
}
//get files within folder
filepath.Walk(cfgDir, func(file string, f os.FileInfo, err error) error {
cfg, err := GetConfigFromFile(cfgDir, file)
if cfg != nil {
if !cfg.Managed && managedOnly {
return nil
}
if !returnContent {
cfg.Content = ""
}
configs.Configs[cfg.Name] = *cfg
}
return nil
})
return configs
}
func GetConfigFromFile(cfgDir, filename string) (*common.ConfigFile, error) {
//file checking
if err := validateFile(cfgDir, filename); err != nil {
return nil, err
}
c, err := util.FileGetContent(filename)
if err != nil {
return nil, err
}
f, err := file.Stat(filename)
if err != nil {
return nil, err
}
content := string(c)
cfg := common.ConfigFile{
Name: util.TrimLeftStr(filepath.Base(filename), cfgDir),
Location: filename,
Version: parseConfigVersion(content),
Updated: f.ModTime().Unix(),
Size: f.Size(),
}
cfg.Content = content
cfg.Managed = parseConfigManaged(content, cfg.Version > 0 || global.Env().SystemConfig.Configs.ConfigFileManagedByDefault)
return &cfg, nil
}
func (handler DefaultHandler) saveConfigAction(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
reqBody := common.ConfigUpdateRequest{}
err := handler.DecodeJSON(req, &reqBody)
if err != nil {
panic(err)
}
for name, content := range reqBody.Configs {
err := SaveConfigStr(name, content)
if err != nil {
panic(err)
}
}
handler.WriteAckOKJSON(w)
}
func (handler DefaultHandler) reloadConfigAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
log.Infof("refresh config")
err := global.Env().RefreshConfig()
if err != nil {
panic(err)
}
handler.WriteAckOKJSON(w)
}

View File

@ -1,43 +0,0 @@
/* Copyright © INFINI LTD. All rights reserved.
* Web: https://infinilabs.com
* Email: hello#infini.ltd */
package config
import (
"fmt"
"github.com/magiconair/properties/assert"
"testing"
)
func TestUpdateVersion(t *testing.T) {
input := `PEFFIX DON"T CHANGE,,, #MANAGED_CONFIG_VERSION: 1234, keep this as well`
output := updateConfigVersion(input, 1235)
fmt.Println(output)
assert.Equal(t, output, `PEFFIX DON"T CHANGE,,, #MANAGED_CONFIG_VERSION: 1235, keep this as well`)
input = `PEFFIX DON"T CHANGE, this is my config`
output = updateConfigVersion(input, 1235)
fmt.Println("new config:")
fmt.Println(output)
assert.Equal(t, output, "PEFFIX DON\"T CHANGE, this is my config\n#MANAGED_CONFIG_VERSION: 1235")
}
func TestVersion(t *testing.T) {
ver:=parseConfigVersion("#MANAGED_CONFIG_VERSION: 1234")
assert.Equal(t, ver, int64(1234))
ver=parseConfigVersion("#MANAGED_CONFIG_VERSION:1234")
assert.Equal(t, ver, int64(1234))
ver=parseConfigVersion("#MANAGED_CONFIG_VERSION:1234 ")
assert.Equal(t, ver, int64(1234))
ver=parseConfigVersion("##MANAGED_CONFIG_VERSION: 1234")
assert.Equal(t, ver, int64(1234))
ver=parseConfigVersion("what's the version, i think is 1234")
assert.Equal(t, ver, int64(-1))
}

View File

@ -6,8 +6,8 @@ package server
import (
log "github.com/cihub/seelog"
"infini.sh/console/plugin/managed/common"
"infini.sh/console/plugin/managed/config"
"infini.sh/framework/modules/configs/common"
"infini.sh/framework/modules/configs/config"
httprouter "infini.sh/framework/core/api/router"
config3 "infini.sh/framework/core/config"
"infini.sh/framework/core/global"

View File

@ -14,7 +14,7 @@ import (
log "github.com/cihub/seelog"
"infini.sh/console/core/security/enum"
"infini.sh/console/plugin/managed/common"
"infini.sh/framework/modules/configs/common"
"infini.sh/framework/core/api"
httprouter "infini.sh/framework/core/api/router"
elastic2 "infini.sh/framework/core/elastic"
@ -33,7 +33,7 @@ func init() {
api.HandleAPIMethod(api.POST, common.REGISTER_API, handler.registerInstance) //client register self to config servers
//for public usage, get install script
api.HandleAPIMethod(api.GET, common.GET_INSTALL_SCRIPT_API, handler.getInstallScript)
api.HandleAPIMethod(api.GET, GET_INSTALL_SCRIPT_API, handler.getInstallScript)
api.HandleAPIMethod(api.POST, "/instance/_generate_install_script", handler.RequireLogin(handler.generateInstallCommand))

View File

@ -9,7 +9,7 @@ import (
"fmt"
log "github.com/cihub/seelog"
"infini.sh/console/core"
"infini.sh/console/plugin/managed/common"
"infini.sh/framework/modules/configs/common"
"infini.sh/framework/core/api"
"infini.sh/framework/core/errors"
"infini.sh/framework/core/global"

View File

@ -10,7 +10,6 @@ import (
"github.com/valyala/fasttemplate"
"infini.sh/console/core/security"
"infini.sh/console/modules/agent/common"
common2 "infini.sh/console/plugin/managed/common"
httprouter "infini.sh/framework/core/api/router"
"infini.sh/framework/core/global"
"infini.sh/framework/core/util"
@ -29,6 +28,7 @@ type Token struct {
}
const ExpiredIn = time.Millisecond * 1000 * 60 * 60
const GET_INSTALL_SCRIPT_API = "/instance/_get_install_script"
var expiredTokenCache = util.NewCacheWithExpireOnAdd(ExpiredIn, 100)
@ -63,7 +63,7 @@ func (h *APIHandler) generateInstallCommand(w http.ResponseWriter, req *http.Req
consoleEndpoint = getDefaultEndpoint(req)
}
endpoint, err := url.JoinPath(consoleEndpoint, common2.GET_INSTALL_SCRIPT_API)
endpoint, err := url.JoinPath(consoleEndpoint, GET_INSTALL_SCRIPT_API)
if err != nil {
panic(err)
}