diff --git a/.gitignore b/.gitignore index 6888ae906..6ba063f29 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ logs/* .build/ .vscode/ .CHANGELOG +vendor/ diff --git a/Makefile b/Makefile index bb7f28f8a..202db37d1 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,32 @@ -.PHONY: build debug test tar +.PHONY: build debug install test upload lint # go env GOPROXY := "https://goproxy.cn,direct" GOOS := $(if $(GOOS),$(GOOS),$(shell go env GOOS)) GOARCH := $(if $(GOARCH),$(GOARCH),$(shell go env GOARCH)) CGO_LDFLAGS := "-static" +CGO_CFLAGS := "-D_LARGEFILE64_SOURCE" CC := musl-gcc GOENV := GO111MODULE=on GOENV += GOPROXY=$(GOPROXY) GOENV += CC=$(CC) -GOENV += CGO_ENABLED=1 CGO_LDFLAGS=$(CGO_LDFLAGS) +GOENV += CGO_ENABLED=1 CGO_LDFLAGS=$(CGO_LDFLAGS) CGO_CFLAGS=$(CGO_CFLAGS) GOENV += GOOS=$(GOOS) GOARCH=$(GOARCH) - +GOLANGCILINT_VERSION ?= v1.50.0 +GOBIN := $(shell go env GOPATH)/bin +GOBIN_GOLANGCILINT := $(shell which $(GOBIN)/golangci-lint) # go GO := go # output OUTPUT := bin/curveadm +SERVER_OUTPUT := bin/pigeon # build flags LDFLAGS := -s -w LDFLAGS += -extldflags "-static -fpic" +LDFLAGS += -X github.com/opencurve/curveadm/cli/cli.CommitId=$(shell git rev-parse --short HEAD) BUILD_FLAGS := -a BUILD_FLAGS += -trimpath @@ -48,18 +53,28 @@ TEST_FLAGS += -run $(CASE) # packages PACKAGES := $(PWD)/cmd/curveadm/main.go +SERVER_PACKAGES := $(PWD)/cmd/service/main.go # tar VERSION := "unknown" build: $(GOENV) $(GO) build -o $(OUTPUT) $(BUILD_FLAGS) $(PACKAGES) + $(GO) build -o $(SERVER_OUTPUT) $(SERVER_PACKAGES) debug: $(GOENV) $(GO) build -o $(OUTPUT) $(DEBUG_FLAGS) $(PACKAGES) +install: + cp bin/curveadm ~/.curveadm/bin + test: $(GO_TEST) $(TEST_FLAGS) ./... upload: @NOSCMD=$(NOSCMD) bash build/package/upload.sh $(VERSION) + +lint: + go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCILINT_VERSION) + $(GOBIN_GOLANGCILINT) run -v + diff --git a/cli/cli/cli.go b/cli/cli/cli.go index 703ca62e7..48139b4a8 100644 --- a/cli/cli/cli.go +++ b/cli/cli/cli.go @@ -52,7 +52,6 @@ type CurveAdm struct { pluginDir string logDir string tempDir string - dbpath string logpath string config *configure.CurveAdmConfig @@ -70,6 +69,7 @@ type CurveAdm struct { clusterName string // current cluster name clusterTopologyData string // cluster topology clusterPoolData string // cluster pool + monitor storage.Monitor } /* @@ -142,9 +142,9 @@ func (curveadm *CurveAdm) init() error { // (4) Init error code errno.Init(logpath) - // (5) New storage: create table in sqlite - dbpath := fmt.Sprintf("%s/curveadm.db", curveadm.dataDir) - s, err := storage.NewStorage(dbpath) + // (5) New storage: create table in sqlite/rqlite + dbUrl := config.GetDBUrl() + s, err := storage.NewStorage(dbUrl) if err != nil { log.Error("Init SQLite database failed", log.Field("Error", err)) @@ -174,7 +174,13 @@ func (curveadm *CurveAdm) init() error { log.Field("ClusterName", cluster.Name)) } - curveadm.dbpath = dbpath + // (8) Get monitor configure + monitor, err := s.GetMonitor(cluster.Id) + if err != nil { + log.Error("Get monitor failed", log.Field("Error", err)) + return errno.ERR_GET_MONITOR_FAILED.E(err) + } + curveadm.logpath = logpath curveadm.config = config curveadm.in = os.Stdin @@ -188,6 +194,7 @@ func (curveadm *CurveAdm) init() error { curveadm.clusterName = cluster.Name curveadm.clusterTopologyData = cluster.Topology curveadm.clusterPoolData = cluster.Pool + curveadm.monitor = monitor return nil } @@ -253,11 +260,11 @@ func (curveadm *CurveAdm) DataDir() string { return curveadm.d func (curveadm *CurveAdm) PluginDir() string { return curveadm.pluginDir } func (curveadm *CurveAdm) LogDir() string { return curveadm.logDir } func (curveadm *CurveAdm) TempDir() string { return curveadm.tempDir } -func (curveadm *CurveAdm) DBPath() string { return curveadm.dbpath } func (curveadm *CurveAdm) LogPath() string { return curveadm.logpath } func (curveadm *CurveAdm) Config() *configure.CurveAdmConfig { return curveadm.config } func (curveadm *CurveAdm) SudoAlias() string { return curveadm.config.GetSudoAlias() } func (curveadm *CurveAdm) SSHTimeout() int { return curveadm.config.GetSSHTimeout() } +func (curveadm *CurveAdm) Engine() string { return curveadm.config.GetEngine() } func (curveadm *CurveAdm) In() io.Reader { return curveadm.in } func (curveadm *CurveAdm) Out() io.Writer { return curveadm.out } func (curveadm *CurveAdm) Err() io.Writer { return curveadm.err } @@ -269,6 +276,7 @@ func (curveadm *CurveAdm) ClusterUUId() string { return curveadm.c func (curveadm *CurveAdm) ClusterName() string { return curveadm.clusterName } func (curveadm *CurveAdm) ClusterTopologyData() string { return curveadm.clusterTopologyData } func (curveadm *CurveAdm) ClusterPoolData() string { return curveadm.clusterPoolData } +func (curveadm *CurveAdm) Monitor() storage.Monitor { return curveadm.monitor } func (curveadm *CurveAdm) GetHost(host string) (*hosts.HostConfig, error) { if len(curveadm.Hosts()) == 0 { @@ -377,6 +385,7 @@ func (curveadm *CurveAdm) ExecOptions() module.ExecOptions { ExecInLocal: false, ExecSudoAlias: curveadm.config.GetSudoAlias(), ExecTimeoutSec: curveadm.config.GetTimeout(), + ExecWithEngine: curveadm.config.GetEngine(), } } diff --git a/cli/cli/version.go b/cli/cli/version.go index 6a40bda51..45ef11049 100644 --- a/cli/cli/version.go +++ b/cli/cli/version.go @@ -25,5 +25,7 @@ package cli var ( - Version = "0.2.0" + Version = "0.3.0" + + CommitId = "unknown" ) diff --git a/cli/command/client/map.go b/cli/command/client/map.go index c2b0ed9a6..37876769a 100644 --- a/cli/command/client/map.go +++ b/cli/command/client/map.go @@ -23,10 +23,10 @@ package client import ( - "github.com/dustin/go-humanize" "strconv" "strings" + "github.com/dustin/go-humanize" "github.com/fatih/color" "github.com/opencurve/curveadm/cli/cli" comm "github.com/opencurve/curveadm/internal/common" @@ -41,9 +41,10 @@ import ( const ( MAP_EXAMPLE = `Examples: - $ curveadm map user:/volume --host machine1 --create # Map volume which created by automatic - $ curveadm map user:/volume --host machine1 --size=10GB --create # Map volume which size is 10GB and created by automatic - $ curveadm map user:/volume --host machine1 -c /path/to/client.yaml # Map volume with specified configure file` + $ curveadm map user:/volume --host machine1 --create # Map volume which created by automatic + $ curveadm map user:/volume --host machine1 --size=10GiB --create # Map volume which size is 10GiB and created by automatic + $ curveadm map user:/volume --host machine1 --create --poolset ssd # Map volume created by automatic in poolset 'ssd' + $ curveadm map user:/volume --host machine1 -c /path/to/client.yaml # Map volume with specified configure file` ) var ( @@ -64,6 +65,7 @@ type mapOptions struct { create bool filename string noExclusive bool + poolset string } func ParseImage(image string) (user, name string, err error) { @@ -159,6 +161,7 @@ func NewMapCommand(curveadm *cli.CurveAdm) *cobra.Command { flags.BoolVar(&options.noExclusive, "no-exclusive", false, "Map volume non exclusive") flags.StringVar(&options.size, "size", "10GiB", "Specify volume size") flags.StringVarP(&options.filename, "conf", "c", "client.yaml", "Specify client configuration file") + flags.StringVar(&options.poolset, "poolset", "default", "Specify the poolset name") return cmd } @@ -181,6 +184,7 @@ func genMapPlaybook(curveadm *cli.CurveAdm, Size: size, Create: options.create, NoExclusive: options.noExclusive, + Poolset: options.poolset, }, comm.KEY_CLIENT_HOST: options.host, // for checker comm.KEY_CHECK_KERNEL_MODULE_NAME: comm.KERNERL_MODULE_NBD, diff --git a/cli/command/client/status.go b/cli/command/client/status.go index d9a66b571..b0029c0ef 100644 --- a/cli/command/client/status.go +++ b/cli/command/client/status.go @@ -36,6 +36,7 @@ import ( var ( GET_STATUS_PLAYBOOK_STEPS = []int{ + playbook.INIT_CLIENT_STATUS, playbook.GET_CLIENT_STATUS, } ) @@ -57,6 +58,9 @@ func NewStatusCommand(curveadm *cli.CurveAdm) *cobra.Command { DisableFlagsInUseLine: true, } + flags := cmd.Flags() + flags.BoolVarP(&options.verbose, "verbose", "v", false, "Verbose output for status") + return cmd } @@ -74,8 +78,13 @@ func genStatusPlaybook(curveadm *cli.CurveAdm, pb.AddStep(&playbook.PlaybookStep{ Type: step, Configs: config, + Options: map[string]interface{}{ + comm.KEY_CLIENT_STATUS_VERBOSE: options.verbose, + }, ExecOptions: playbook.ExecOptions{ - SilentSubBar: true, + SilentSubBar: true, + SilentMainBar: step == playbook.INIT_CLIENT_STATUS, + SkipError: true, }, }) } @@ -113,11 +122,9 @@ func runStatus(curveadm *cli.CurveAdm, options statusOptions) error { } // 3) run playground - if err = pb.Run(); err != nil { - return err - } + err = pb.Run() // 4) display service status displayStatus(curveadm, clients, options) - return nil + return err } diff --git a/cli/command/cluster/add.go b/cli/command/cluster/add.go index 2beaa7d61..40d413a59 100644 --- a/cli/command/cluster/add.go +++ b/cli/command/cluster/add.go @@ -25,6 +25,7 @@ package cluster import ( + "github.com/google/uuid" "github.com/opencurve/curveadm/cli/cli" comm "github.com/opencurve/curveadm/internal/common" "github.com/opencurve/curveadm/internal/configure/topology" @@ -161,7 +162,8 @@ func runAdd(curveadm *cli.CurveAdm, options addOptions) error { } // 4) insert cluster (with topology) into database - err = storage.InsertCluster(name, options.descriotion, data) + uuid := uuid.NewString() + err = storage.InsertCluster(name, uuid, options.descriotion, data) if err != nil { return errno.ERR_INSERT_CLUSTER_FAILED.E(err) } diff --git a/cli/command/cluster/cmd.go b/cli/command/cluster/cmd.go index f388d9631..6759e23c0 100644 --- a/cli/command/cluster/cmd.go +++ b/cli/command/cluster/cmd.go @@ -43,9 +43,9 @@ func NewClusterCommand(curveadm *cli.CurveAdm) *cobra.Command { NewCheckoutCommand(curveadm), NewListCommand(curveadm), NewRemoveCommand(curveadm), - // TODO(P1): enable export and import + // TODO(P1): enable export //NewExportCommand(curveadm), - //NewImportCommand(curveadm), + NewImportCommand(curveadm), ) return cmd } diff --git a/cli/command/cluster/import.go b/cli/command/cluster/import.go index d5b20654a..e4f8de0eb 100644 --- a/cli/command/cluster/import.go +++ b/cli/command/cluster/import.go @@ -24,16 +24,11 @@ package cluster import ( "fmt" - "io" - "os" - "regexp" - "strconv" - "strings" - "github.com/opencurve/curveadm/pkg/log/zaplog" "github.com/opencurve/curveadm/cli/cli" "github.com/opencurve/curveadm/internal/storage" "github.com/opencurve/curveadm/internal/utils" + "github.com/opencurve/curveadm/pkg/log/zaplog" "github.com/spf13/cobra" ) @@ -43,7 +38,7 @@ const ( var ( importExample = `Examples: - $ curveadm cluster import my-cluster # Import a cluster named 'my-cluster' + $ curveadm cluster import my-cluster # Import cluster 'my-cluster' with curveadm.db $ curveadm cluster import my-cluster -f /path/to/dbfile # Import cluster 'my-cluster' with specified database file` ) @@ -73,100 +68,40 @@ func NewImportCommand(curveadm *cli.CurveAdm) *cobra.Command { return cmd } -func readItem(file *os.File) (int, string, error) { - // key: --- $ID $LENGTH - buffer := []byte{} - bytes := make([]byte, 1) - for { - _, err := file.Read(bytes) - if err == io.EOF { - if len(buffer) == 0 { - return 0, "", io.EOF - } else { - return 0, "", fmt.Errorf("invalid curveadm database, line: %s", string(buffer)) - } - } else if err != nil { - return 0, "", err - } else if bytes[0] == '\n' { - break - } - buffer = append(buffer, bytes[0]) - } - - key := string(buffer) - pattern := regexp.MustCompile("^--- ([0-9]+) ([0-9]+)$") - mu := pattern.FindStringSubmatch(key) - if len(mu) == 0 { - return 0, "", fmt.Errorf("invalid curveadm database, line: %s", key) - } - - id, _ := strconv.Atoi(mu[1]) - nbytes, _ := strconv.Atoi(mu[2]) - if nbytes > MAX_VALUE_BYETS { - return 0, "", fmt.Errorf("too big value int curveadm database") - } - - // value - bytes = make([]byte, nbytes) - nread, err := file.Read(bytes) - if err == io.EOF || nread != nbytes { - return 0, "", fmt.Errorf("value broken in database") - } else if err != nil { - return 0, "", err +func readDB(filepath, name string) (*storage.Cluster, []storage.Service, error) { + dbUrl := fmt.Sprintf("sqlite://%s", filepath) + s, err := storage.NewStorage(dbUrl) + if err != nil { + return nil, nil, err } - return id, string(bytes[:nbytes-1]), nil -} - -func readDatabase(filename string) (storage.Cluster, []storage.Service, error) { - cluster := storage.Cluster{} - services := []storage.Service{} - file, err := os.Open(filename) + clusters, err := s.GetClusters(name) if err != nil { - return cluster, services, err + return nil, nil, err + } else if len(clusters) == 0 { + return nil, nil, fmt.Errorf("cluster '%s' not found", name) + } else if len(clusters) > 1 { + return nil, nil, fmt.Errorf("cluster '%s' is duplicate", name) } - defer file.Close() - - for { - id, value, err := readItem(file) - if err == io.EOF { - break - } else if err != nil { - return cluster, services, err - } - switch id { - case CLUSTER_DESCRIPTION: - cluster.Description = value - break - case CLUSTER_TOPOLOGY: - cluster.Topology = value - break - case SERVICE: - items := strings.Split(value, " ") - if len(items) != 2 { - return cluster, services, fmt.Errorf("invalid service, line: %s", value) - } - service := storage.Service{ - Id: items[0], - ContainerId: items[1], - } - services = append(services, service) - } + cluster := clusters[0] + services, err := s.GetServices(cluster.Id) + if err != nil { + return nil, nil, err } - - return cluster, services, nil + return &cluster, services, nil } -func importCluster(storage *storage.Storage, name, dbfile string) error { +func importCluster(storage *storage.Storage, dbfile, name string) error { // read database file - cluster, services, err := readDatabase(dbfile) + cluster, services, err := readDB(dbfile, name) if err != nil { return err } // insert cluster - if storage.InsertCluster(name, cluster.Description, cluster.Topology); err != nil { + err = storage.InsertCluster(name, cluster.UUId, cluster.Description, cluster.Topology) + if err != nil { return err } @@ -177,7 +112,8 @@ func importCluster(storage *storage.Storage, name, dbfile string) error { } clusterId := clusters[0].Id for _, service := range services { - if err := storage.InsertService(clusterId, service.Id, service.ContainerId); err != nil { + err := storage.InsertService(clusterId, service.Id, service.ContainerId) + if err != nil { return err } } @@ -191,10 +127,9 @@ func runImport(curveadm *cli.CurveAdm, options importOptions) error { if err != nil { zaplog.Error("GetClusters", zaplog.Field("error", err)) return err - } else if len(clusters) != 0 { + } else if len(clusters) != 0 { // TODO: let user enter a new cluster name return fmt.Errorf("cluster %s already exist", name) - } else if err := importCluster(storage, name, options.dbfile); err != nil { - storage.DeleteCluster(name) + } else if err := importCluster(storage, options.dbfile, name); err != nil { return err } diff --git a/cli/command/cmd.go b/cli/command/cmd.go index 0c19d9548..91faca5bd 100644 --- a/cli/command/cmd.go +++ b/cli/command/cmd.go @@ -32,6 +32,7 @@ import ( "github.com/opencurve/curveadm/cli/command/cluster" "github.com/opencurve/curveadm/cli/command/config" "github.com/opencurve/curveadm/cli/command/hosts" + "github.com/opencurve/curveadm/cli/command/monitor" "github.com/opencurve/curveadm/cli/command/pfs" "github.com/opencurve/curveadm/cli/command/playground" "github.com/opencurve/curveadm/cli/command/target" @@ -42,13 +43,13 @@ import ( ) var curveadmExample = `Examples: - $ curveadm playground --kind curvebs # Run a CurveBS playground quickly - $ curveadm cluster add c1 # Add a cluster named 'c1' - $ curveadm deploy # Deploy current cluster - $ curveadm stop # Stop current cluster service - $ curveadm clean # Clean current cluster - $ curveadm enter 6ff561598c6f # Enter specified service container - $ curveadm -u # Upgrade curveadm itself to the latest version` + $ curveadm playground run --kind curvebs # Run a CurveBS playground quickly + $ curveadm cluster add c1 # Add a cluster named 'c1' + $ curveadm deploy # Deploy current cluster + $ curveadm stop # Stop current cluster service + $ curveadm clean # Clean current cluster + $ curveadm enter 6ff561598c6f # Enter specified service container + $ curveadm -u # Upgrade curveadm itself to the latest version` type rootOptions struct { debug bool @@ -64,6 +65,7 @@ func addSubCommands(cmd *cobra.Command, curveadm *cli.CurveAdm) { playground.NewPlaygroundCommand(curveadm), // curveadm playground ... target.NewTargetCommand(curveadm), // curveadm target ... pfs.NewPFSCommand(curveadm), // curveadm pfs ... + monitor.NewMonitorCommand(curveadm), // curveadm monitor ... NewAuditCommand(curveadm), // curveadm audit NewCleanCommand(curveadm), // curveadm clean @@ -93,7 +95,7 @@ func addSubCommands(cmd *cobra.Command, curveadm *cli.CurveAdm) { } func setupRootCommand(cmd *cobra.Command, curveadm *cli.CurveAdm) { - cmd.SetVersionTemplate("CurveAdm v{{.Version}}\n") + cmd.SetVersionTemplate("{{.Version}}\n") cliutil.SetFlagErrorFunc(cmd) cliutil.SetHelpTemplate(cmd) cliutil.SetUsageTemplate(cmd) @@ -106,7 +108,7 @@ func NewCurveAdmCommand(curveadm *cli.CurveAdm) *cobra.Command { cmd := &cobra.Command{ Use: "curveadm [OPTIONS] COMMAND [ARGS...]", Short: "Deploy and manage CurveBS/CurveFS cluster", - Version: cli.Version, + Version: fmt.Sprintf("CurveAdm v%s, build %s", cli.Version, cli.CommitId), Example: curveadmExample, RunE: func(cmd *cobra.Command, args []string) error { if options.debug { diff --git a/cli/command/deploy.go b/cli/command/deploy.go index fda7c1d71..a193d88f3 100644 --- a/cli/command/deploy.go +++ b/cli/command/deploy.go @@ -29,6 +29,7 @@ import ( "github.com/fatih/color" "github.com/opencurve/curveadm/cli/cli" comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/configure" "github.com/opencurve/curveadm/internal/configure/topology" "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/internal/playbook" @@ -43,6 +44,7 @@ const ( CREATE_CONTAINER = playbook.CREATE_CONTAINER SYNC_CONFIG = playbook.SYNC_CONFIG START_ETCD = playbook.START_ETCD + ENABLE_ETCD_AUTH = playbook.ENABLE_ETCD_AUTH START_MDS = playbook.START_MDS CREATE_PHYSICAL_POOL = playbook.CREATE_PHYSICAL_POOL START_CHUNKSERVER = playbook.START_CHUNKSERVER @@ -65,6 +67,7 @@ var ( CREATE_CONTAINER, SYNC_CONFIG, START_ETCD, + ENABLE_ETCD_AUTH, START_MDS, CREATE_PHYSICAL_POOL, START_CHUNKSERVER, @@ -79,6 +82,7 @@ var ( CREATE_CONTAINER, SYNC_CONFIG, START_ETCD, + ENABLE_ETCD_AUTH, START_MDS, CREATE_LOGICAL_POOL, START_METASERVER, @@ -86,6 +90,7 @@ var ( DEPLOY_FILTER_ROLE = map[int]string{ START_ETCD: ROLE_ETCD, + ENABLE_ETCD_AUTH: ROLE_ETCD, START_MDS: ROLE_MDS, START_CHUNKSERVER: ROLE_CHUNKSERVER, START_SNAPSHOTCLONE: ROLE_SNAPSHOTCLONE, @@ -99,6 +104,7 @@ var ( CREATE_PHYSICAL_POOL: 1, CREATE_LOGICAL_POOL: 1, BALANCE_LEADER: 1, + ENABLE_ETCD_AUTH: 1, } CAN_SKIP_ROLES = []string{ @@ -107,8 +113,10 @@ var ( ) type deployOptions struct { - skip []string - insecure bool + skip []string + insecure bool + poolset string + poolsetDiskType string } func checkDeployOptions(options deployOptions) error { @@ -141,6 +149,8 @@ func NewDeployCommand(curveadm *cli.CurveAdm) *cobra.Command { flags := cmd.Flags() flags.StringSliceVar(&options.skip, "skip", []string{}, "Specify skipped service roles") flags.BoolVarP(&options.insecure, "insecure", "k", false, "Deploy without precheck") + flags.StringVar(&options.poolset, "poolset", "default", "Specify the poolset name") + flags.StringVar(&options.poolsetDiskType, "poolset-disktype", "ssd", "Specify the disk type of physical pool") return cmd } @@ -157,11 +167,12 @@ func skipServiceRole(deployConfigs []*topology.DeployConfig, options deployOptio return dcs } -func skipDeploySteps(deploySteps []int, options deployOptions) []int { +func skipDeploySteps(dcs []*topology.DeployConfig, deploySteps []int, options deployOptions) []int { steps := []int{} skipped := utils.Slice2Map(options.skip) for _, step := range deploySteps { - if step == START_SNAPSHOTCLONE && skipped[ROLE_SNAPSHOTCLONE] { + if (step == START_SNAPSHOTCLONE && skipped[ROLE_SNAPSHOTCLONE]) || + (step == ENABLE_ETCD_AUTH && len(dcs) > 0 && !dcs[0].GetEtcdAuthEnable()) { continue } steps = append(steps, step) @@ -200,15 +211,27 @@ func precheckBeforeDeploy(curveadm *cli.CurveAdm, return nil } +func calcNumOfChunkserver(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig) int { + services := curveadm.FilterDeployConfigByRole(dcs, topology.ROLE_CHUNKSERVER) + return len(services) +} + func genDeployPlaybook(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig, options deployOptions) (*playbook.Playbook, error) { + var steps []int kind := dcs[0].GetKind() - steps := CURVEFS_DEPLOY_STEPS if kind == topology.KIND_CURVEBS { steps = CURVEBS_DEPLOY_STEPS + } else { + steps = CURVEFS_DEPLOY_STEPS + } + steps = skipDeploySteps(dcs, steps, options) + poolset := configure.Poolset{ + Name: options.poolset, + Type: options.poolsetDiskType, } - steps = skipDeploySteps(steps, options) + diskType := options.poolsetDiskType pb := playbook.NewPlaybook(curveadm) for _, step := range steps { @@ -228,8 +251,13 @@ func genDeployPlaybook(curveadm *cli.CurveAdm, options := map[string]interface{}{} if step == CREATE_PHYSICAL_POOL { options[comm.KEY_CREATE_POOL_TYPE] = comm.POOL_TYPE_PHYSICAL + options[comm.KEY_POOLSET] = poolset + options[comm.KEY_NUMBER_OF_CHUNKSERVER] = calcNumOfChunkserver(curveadm, dcs) } else if step == CREATE_LOGICAL_POOL { options[comm.KEY_CREATE_POOL_TYPE] = comm.POOL_TYPE_LOGICAL + options[comm.POOLSET] = poolset + options[comm.POOLSET_DISK_TYPE] = diskType + options[comm.KEY_NUMBER_OF_CHUNKSERVER] = calcNumOfChunkserver(curveadm, dcs) } pb.AddStep(&playbook.PlaybookStep{ diff --git a/cli/command/exec.go b/cli/command/exec.go index 7b62c037a..b08bdc30c 100644 --- a/cli/command/exec.go +++ b/cli/command/exec.go @@ -20,8 +20,6 @@ * Author: Jingli Chen (Wine93) */ -// __SIGN_BY_WINE93__ - package command import ( @@ -60,6 +58,11 @@ func NewExecCommand(curveadm *cli.CurveAdm) *cobra.Command { return cmd } +// exec: +// 1. parse cluster topology +// 2. filter service +// 3. get container id +// 4. exec cmd in remote container func runExec(curveadm *cli.CurveAdm, options execOptions) error { // 1) parse cluster topology dcs, err := curveadm.ParseTopology() diff --git a/cli/command/format.go b/cli/command/format.go index d88c397ec..d948e4fdc 100644 --- a/cli/command/format.go +++ b/cli/command/format.go @@ -60,6 +60,7 @@ type formatOptions struct { filename string showStatus bool stopFormat bool + concurrent uint } func NewFormatCommand(curveadm *cli.CurveAdm) *cobra.Command { @@ -80,6 +81,7 @@ func NewFormatCommand(curveadm *cli.CurveAdm) *cobra.Command { flags.StringVarP(&options.filename, "formatting", "f", "format.yaml", "Specify the configure file for formatting chunkfile pool") flags.BoolVar(&options.showStatus, "status", false, "Show formatting status") flags.BoolVar(&options.stopFormat, "stop", false, "Stop formatting progress") + flags.UintVarP(&options.concurrent, "concurrent", "c", 10, "Specify the number of concurrent for formatting") return cmd } @@ -108,6 +110,7 @@ func genFormatPlaybook(curveadm *cli.CurveAdm, Type: step, Configs: fcs, ExecOptions: playbook.ExecOptions{ + Concurrency: options.concurrent, SilentSubBar: options.showStatus, }, }) diff --git a/cli/command/migrate.go b/cli/command/migrate.go index 2a1b1ddf5..310b29cee 100644 --- a/cli/command/migrate.go +++ b/cli/command/migrate.go @@ -103,7 +103,9 @@ var ( ) type migrateOptions struct { - filename string + filename string + poolset string + poolsetDiskType string } func NewMigrateCommand(curveadm *cli.CurveAdm) *cobra.Command { @@ -120,6 +122,10 @@ func NewMigrateCommand(curveadm *cli.CurveAdm) *cobra.Command { DisableFlagsInUseLine: true, } + flags := cmd.Flags() + flags.StringVar(&options.poolset, "poolset", "default", "Specify the poolset") + flags.StringVar(&options.poolsetDiskType, "poolset-disktype", "ssd", "Specify the disk type of physical pool") + return cmd } @@ -152,7 +158,7 @@ func checkMigrateTopology(curveadm *cli.CurveAdm, data string) error { dcs2add[0].GetRole() != dcs2del[0].GetRole() { return errno.ERR_REQUIRE_SAME_ROLE_SERVICES_FOR_MIGRATING } - if len(dcs2del) != dcs2del[0].GetReplicas() { + if len(dcs2del) != dcs2del[0].GetInstances() { return errno.ERR_REQUIRE_WHOLE_HOST_SERVICES_FOR_MIGRATING } @@ -178,13 +184,15 @@ func getMigrates(curveadm *cli.CurveAdm, data string) []*configure.MigrateServer } func genMigratePlaybook(curveadm *cli.CurveAdm, - dcs []*topology.DeployConfig, data string) (*playbook.Playbook, error) { + dcs []*topology.DeployConfig, options migrateOptions, data string) (*playbook.Playbook, error) { diffs, _ := diffTopology(curveadm, data) dcs2add := diffs[topology.DIFF_ADD] dcs2del := diffs[topology.DIFF_DELETE] migrates := getMigrates(curveadm, data) role := migrates[0].From.GetRole() steps := MIGRATE_ROLE_STEPS[role] + poolset := options.poolset + poolsetDiskType := options.poolsetDiskType pb := playbook.NewPlaybook(curveadm) for _, step := range steps { @@ -210,10 +218,14 @@ func genMigratePlaybook(curveadm *cli.CurveAdm, case playbook.CREATE_PHYSICAL_POOL: options[comm.KEY_CREATE_POOL_TYPE] = comm.POOL_TYPE_PHYSICAL options[comm.KEY_MIGRATE_SERVERS] = migrates + options[comm.POOLSET] = poolset + options[comm.POOLSET_DISK_TYPE] = poolsetDiskType case playbook.CREATE_LOGICAL_POOL: options[comm.KEY_CREATE_POOL_TYPE] = comm.POOL_TYPE_LOGICAL options[comm.KEY_MIGRATE_SERVERS] = migrates options[comm.KEY_NEW_TOPOLOGY_DATA] = data + options[comm.POOLSET] = poolset + options[comm.POOLSET_DISK_TYPE] = poolsetDiskType case playbook.UPDATE_TOPOLOGY: options[comm.KEY_NEW_TOPOLOGY_DATA] = data } @@ -270,7 +282,7 @@ func runMigrate(curveadm *cli.CurveAdm, options migrateOptions) error { } // 6) generate migrate playbook - pb, err := genMigratePlaybook(curveadm, dcs, data) + pb, err := genMigratePlaybook(curveadm, dcs, options, data) if err != nil { return err } diff --git a/cli/command/monitor/clean.go b/cli/command/monitor/clean.go new file mode 100644 index 000000000..97bdbe4a8 --- /dev/null +++ b/cli/command/monitor/clean.go @@ -0,0 +1,133 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-27 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/opencurve/curveadm/cli/cli" + comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/playbook" + tui "github.com/opencurve/curveadm/internal/tui/common" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +const ( + CLEAN_EXAMPLE = `Examples: + $ curveadm monitor clean # Clean everything for monitor + $ curveadm monitor clean --only='data' # Clean data for monitor + $ curveadm monitor clean --role=grafana --only=container # Clean container for grafana service` +) + +var ( + CLEAN_PLAYBOOK_STEPS = []int{ + playbook.CLEAN_MONITOR, + } + + CLEAN_ITEMS = []string{ + comm.CLEAN_ITEM_DATA, + comm.CLEAN_ITEM_CONTAINER, + } +) + +type cleanOptions struct { + id string + role string + host string + only []string +} + +func NewCleanCommand(curveadm *cli.CurveAdm) *cobra.Command { + var options cleanOptions + + cmd := &cobra.Command{ + Use: "clean [OPTIONS]", + Short: "Clean monitor's environment", + Args: cliutil.NoArgs, + Example: CLEAN_EXAMPLE, + RunE: func(cmd *cobra.Command, args []string) error { + return runClean(curveadm, options) + }, + DisableFlagsInUseLine: true, + } + + flags := cmd.Flags() + flags.StringVar(&options.id, "id", "*", "Specify monitor service id") + flags.StringVar(&options.role, "role", "*", "Specify monitor service role") + flags.StringVar(&options.host, "host", "*", "Specify monitor service host") + flags.StringSliceVarP(&options.only, "only", "o", CLEAN_ITEMS, "Specify clean item") + return cmd +} + +func genCleanPlaybook(curveadm *cli.CurveAdm, + mcs []*configure.MonitorConfig, + options cleanOptions) (*playbook.Playbook, error) { + mcs = configure.FilterMonitorConfig(curveadm, mcs, configure.FilterMonitorOption{ + Id: options.id, + Role: options.role, + Host: options.host, + }) + if len(mcs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } + steps := CLEAN_PLAYBOOK_STEPS + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + Options: map[string]interface{}{ + comm.KEY_CLEAN_ITEMS: options.only, + }, + }) + } + return pb, nil +} + +func runClean(curveadm *cli.CurveAdm, options cleanOptions) error { + // 1) parse monitor config + mcs, err := parseMonitorConfig(curveadm) + if err != nil { + return err + } + + // 2) generate clean playbook + pb, err := genCleanPlaybook(curveadm, mcs, options) + if err != nil { + return err + } + + // 3) confirm by user + if pass := tui.ConfirmYes(tui.PromptCleanService(options.role, options.host, options.only)); !pass { + curveadm.WriteOut(tui.PromptCancelOpetation("clean monitor service")) + return errno.ERR_CANCEL_OPERATION + } + + // 4) run playground + err = pb.Run() + if err != nil { + return err + } + return nil +} diff --git a/cli/command/monitor/cmd.go b/cli/command/monitor/cmd.go new file mode 100644 index 000000000..d1b6e1988 --- /dev/null +++ b/cli/command/monitor/cmd.go @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-17 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/opencurve/curveadm/cli/cli" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +func NewMonitorCommand(curveadm *cli.CurveAdm) *cobra.Command { + cmd := &cobra.Command{ + Use: "monitor", + Short: "Manage monitor", + Args: cliutil.NoArgs, + RunE: cliutil.ShowHelp(curveadm.Err()), + } + + cmd.AddCommand( + NewDeployCommand(curveadm), + NewStartCommand(curveadm), + NewStopCommand(curveadm), + NewStatusCommand(curveadm), + NewCleanCommand(curveadm), + NewRestartCommand(curveadm), + NewReloadCommand(curveadm), + ) + return cmd +} diff --git a/cli/command/monitor/deploy.go b/cli/command/monitor/deploy.go new file mode 100644 index 000000000..83ce33dc3 --- /dev/null +++ b/cli/command/monitor/deploy.go @@ -0,0 +1,175 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-17 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/fatih/color" + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/configure/topology" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/playbook" + "github.com/opencurve/curveadm/internal/storage" + "github.com/opencurve/curveadm/internal/tasks" + "github.com/opencurve/curveadm/internal/utils" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +const ( + DEPLOY_EXAMPLE = `Examples: + $ curveadm monitor deploy -c monitor.yaml # deploy monitor for current cluster` +) + +var ( + MONITOR_DEPLOY_STEPS = []int{ + playbook.PULL_MONITOR_IMAGE, + playbook.CREATE_MONITOR_CONTAINER, + playbook.SYNC_MONITOR_CONFIG, + playbook.CLEAN_CONFIG_CONTAINER, + playbook.START_MONITOR_SERVICE, + } +) + +type deployOptions struct { + filename string +} + +/* + * Deploy Steps: + * 1) pull images(curvebs, node_exporter, prometheus, grafana) + * 2) create container + * 3) sync config + * 4) start container + * 4.1) start node_exporter container + * 4.2) start prometheus container + * 4.3) start grafana container + */ +func NewDeployCommand(curveadm *cli.CurveAdm) *cobra.Command { + var options deployOptions + + cmd := &cobra.Command{ + Use: "deploy [OPTIONS]", + Short: "Deploy monitor for current cluster", + Args: cliutil.NoArgs, + Example: DEPLOY_EXAMPLE, + RunE: func(cmd *cobra.Command, args []string) error { + return runDeploy(curveadm, options) + }, + DisableFlagsInUseLine: true, + } + + flags := cmd.Flags() + flags.StringVarP(&options.filename, "conf", "c", "monitor.yaml", "Specify monitor configuration file") + return cmd +} + +func genDeployPlaybook(curveadm *cli.CurveAdm, + mcs []*configure.MonitorConfig) (*playbook.Playbook, error) { + steps := MONITOR_DEPLOY_STEPS + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + if step == playbook.CLEAN_CONFIG_CONTAINER { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + ExecOptions: tasks.ExecOptions{ + SilentMainBar: true, + SilentSubBar: true, + }, + }) + continue + } + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + }) + } + return pb, nil +} + +func parseTopology(curveadm *cli.CurveAdm) ([]string, []string, []*topology.DeployConfig, error) { + dcs, err := curveadm.ParseTopology() + if err != nil || len(dcs) == 0 { + return nil, nil, nil, err + } + hosts := []string{} + hostIps := []string{} + thostMap := make(map[string]bool) + thostIpMap := make(map[string]bool) + for _, dc := range dcs { + thostMap[dc.GetHost()] = true + thostIpMap[dc.GetListenIp()] = true + } + for key := range thostMap { + hosts = append(hosts, key) + } + for key := range thostIpMap { + hostIps = append(hostIps, key) + } + return hosts, hostIps, dcs, nil +} + +func runDeploy(curveadm *cli.CurveAdm, options deployOptions) error { + // 1) parse cluster topology and get services' hosts + hosts, hostIps, dcs, err := parseTopology(curveadm) + if err != nil { + return err + } + + // 2) parse monitor configure + mcs, err := configure.ParseMonitorConfig(curveadm, options.filename, "", hosts, hostIps, dcs) + if err != nil { + return err + } + + // 3) save monitor data + data, err := utils.ReadFile(options.filename) + if err != nil { + return errno.ERR_READ_MONITOR_FILE_FAILED.E(err) + } + err = curveadm.Storage().ReplaceMonitor(storage.Monitor{ + ClusterId: curveadm.ClusterId(), + Monitor: data, + }) + if err != nil { + return errno.ERR_REPLACE_MONITOR_FAILED.E(err) + } + + // 4) generate deploy playbook + pb, err := genDeployPlaybook(curveadm, mcs) + if err != nil { + return err + } + + // 5) run playground + err = pb.Run() + if err != nil { + return err + } + + // 6) print success prompt + curveadm.WriteOutln("") + curveadm.WriteOutln(color.GreenString("Deploy monitor success ^_^")) + return nil +} diff --git a/cli/command/monitor/reload.go b/cli/command/monitor/reload.go new file mode 100644 index 000000000..7483fda7c --- /dev/null +++ b/cli/command/monitor/reload.go @@ -0,0 +1,126 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-28 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/playbook" + "github.com/opencurve/curveadm/internal/tasks" + tui "github.com/opencurve/curveadm/internal/tui/common" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +var ( + MONITOR_RELOAD_STEPS = []int{ + playbook.CREATE_MONITOR_CONTAINER, + playbook.SYNC_MONITOR_CONFIG, + playbook.CLEAN_CONFIG_CONTAINER, + playbook.RESTART_MONITOR_SERVICE, + } +) + +type reloadOptions struct { + id string + role string + host string +} + +func NewReloadCommand(curveadm *cli.CurveAdm) *cobra.Command { + var options reloadOptions + cmd := &cobra.Command{ + Use: "reload [OPTIONS]", + Short: "Reload monitor service", + Args: cliutil.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return runReload(curveadm, options) + }, + DisableFlagsInUseLine: true, + } + + flags := cmd.Flags() + flags.StringVar(&options.id, "id", "*", "Specify monitor service id") + flags.StringVar(&options.role, "role", "*", "Specify monitor service role") + flags.StringVar(&options.host, "host", "*", "Specify monitor service host") + + return cmd +} + +func genReloadPlaybook(curveadm *cli.CurveAdm, + mcs []*configure.MonitorConfig, + options reloadOptions) (*playbook.Playbook, error) { + mcs = configure.FilterMonitorConfig(curveadm, mcs, configure.FilterMonitorOption{ + Id: options.id, + Role: options.role, + Host: options.host, + }) + if len(mcs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } + + steps := MONITOR_RELOAD_STEPS + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + if step == playbook.CREATE_MONITOR_CONTAINER || step == playbook.CLEAN_CONFIG_CONTAINER { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + ExecOptions: tasks.ExecOptions{ + SilentMainBar: true, + SilentSubBar: true, + }, + }) + continue + } + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + }) + } + return pb, nil +} + +func runReload(curveadm *cli.CurveAdm, options reloadOptions) error { + // 1) parse monitor configure + mcs, err := parseMonitorConfig(curveadm) + if err != nil { + return err + } + + // 2) generate reload playbook + pb, err := genReloadPlaybook(curveadm, mcs, options) + if err != nil { + return err + } + + // 3) confirm by user + if pass := tui.ConfirmYes(tui.PromptReloadService(options.id, options.role, options.host)); !pass { + curveadm.WriteOut(tui.PromptCancelOpetation("reload monitor service")) + return errno.ERR_CANCEL_OPERATION + } + + // 4) run playground + return pb.Run() +} diff --git a/cli/command/monitor/restart.go b/cli/command/monitor/restart.go new file mode 100644 index 000000000..ad5df1dd7 --- /dev/null +++ b/cli/command/monitor/restart.go @@ -0,0 +1,111 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-28 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/playbook" + tui "github.com/opencurve/curveadm/internal/tui/common" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +var ( + MONITOR_RESTART_STEPS = []int{ + playbook.RESTART_MONITOR_SERVICE, + } +) + +type restartOptions struct { + id string + role string + host string +} + +func NewRestartCommand(curveadm *cli.CurveAdm) *cobra.Command { + var options restartOptions + cmd := &cobra.Command{ + Use: "restart [OPTIONS]", + Short: "Restart monitor service", + Args: cliutil.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return runRestart(curveadm, options) + }, + DisableFlagsInUseLine: true, + } + + flags := cmd.Flags() + flags.StringVar(&options.id, "id", "*", "Specify monitor service id") + flags.StringVar(&options.role, "role", "*", "Specify monitor service role") + flags.StringVar(&options.host, "host", "*", "Specify monitor service host") + + return cmd +} + +func genRestartPlaybook(curveadm *cli.CurveAdm, + mcs []*configure.MonitorConfig, + options restartOptions) (*playbook.Playbook, error) { + mcs = configure.FilterMonitorConfig(curveadm, mcs, configure.FilterMonitorOption{ + Id: options.id, + Role: options.role, + Host: options.host, + }) + if len(mcs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } + + steps := MONITOR_RESTART_STEPS + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + }) + } + return pb, nil +} + +func runRestart(curveadm *cli.CurveAdm, options restartOptions) error { + // 1) parse monitor configure + mcs, err := parseMonitorConfig(curveadm) + if err != nil { + return err + } + + // 2) generate restart playbook + pb, err := genRestartPlaybook(curveadm, mcs, options) + if err != nil { + return err + } + + // 3) confirm by user + if pass := tui.ConfirmYes(tui.PromptRestartService(options.id, options.role, options.host)); !pass { + curveadm.WriteOut(tui.PromptCancelOpetation("restart monitor service")) + return errno.ERR_CANCEL_OPERATION + } + + // 4) run playground + return pb.Run() +} diff --git a/cli/command/monitor/start.go b/cli/command/monitor/start.go new file mode 100644 index 000000000..7209f75a1 --- /dev/null +++ b/cli/command/monitor/start.go @@ -0,0 +1,111 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-26 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/playbook" + tui "github.com/opencurve/curveadm/internal/tui/common" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +var ( + MONITOR_START_STEPS = []int{ + playbook.START_MONITOR_SERVICE, + } +) + +type startOptions struct { + id string + role string + host string +} + +func NewStartCommand(curveadm *cli.CurveAdm) *cobra.Command { + var options startOptions + cmd := &cobra.Command{ + Use: "start [OPTIONS]", + Short: "Start monitor service", + Args: cliutil.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return runStart(curveadm, options) + }, + DisableFlagsInUseLine: true, + } + + flags := cmd.Flags() + flags.StringVar(&options.id, "id", "*", "Specify monitor service id") + flags.StringVar(&options.role, "role", "*", "Specify monitor service role") + flags.StringVar(&options.host, "host", "*", "Specify monitor service host") + + return cmd +} + +func genStartPlaybook(curveadm *cli.CurveAdm, + mcs []*configure.MonitorConfig, + options startOptions) (*playbook.Playbook, error) { + mcs = configure.FilterMonitorConfig(curveadm, mcs, configure.FilterMonitorOption{ + Id: options.id, + Role: options.role, + Host: options.host, + }) + if len(mcs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } + + steps := MONITOR_START_STEPS + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + }) + } + return pb, nil +} + +func runStart(curveadm *cli.CurveAdm, options startOptions) error { + // 1) parse monitor configure + mcs, err := parseMonitorConfig(curveadm) + if err != nil { + return err + } + + // 2) generate start playbook + pb, err := genStartPlaybook(curveadm, mcs, options) + if err != nil { + return err + } + + // 3) confirm by user + if pass := tui.ConfirmYes(tui.PromptStartService(options.id, options.role, options.host)); !pass { + curveadm.WriteOut(tui.PromptCancelOpetation("start monitor service")) + return errno.ERR_CANCEL_OPERATION + } + + // 4) run playground + return pb.Run() +} diff --git a/cli/command/monitor/status.go b/cli/command/monitor/status.go new file mode 100644 index 000000000..478caf86e --- /dev/null +++ b/cli/command/monitor/status.go @@ -0,0 +1,150 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-26 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/opencurve/curveadm/cli/cli" + comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/playbook" + "github.com/opencurve/curveadm/internal/task/task/monitor" + tui "github.com/opencurve/curveadm/internal/tui/service" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +var ( + GET_MONITOR_STATUS_PLAYBOOK_STEPS = []int{ + playbook.INIT_MONITOR_STATUS, + playbook.GET_MONITOR_STATUS, + } +) + +type statusOptions struct { + id string + role string + host string + verbose bool +} + +func NewStatusCommand(curveadm *cli.CurveAdm) *cobra.Command { + var options statusOptions + cmd := &cobra.Command{ + Use: "status [OPTIONS]", + Short: "Display monitor services status", + Args: cliutil.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return runStatus(curveadm, options) + }, + DisableFlagsInUseLine: true, + } + + flags := cmd.Flags() + flags.StringVar(&options.id, "id", "*", "Specify monitor service id") + flags.StringVar(&options.role, "role", "*", "Specify monitor service role") + flags.StringVar(&options.host, "host", "*", "Specify monitor service host") + flags.BoolVarP(&options.verbose, "verbose", "v", false, "Verbose output for status") + return cmd +} + +func parseMonitorConfig(curveadm *cli.CurveAdm) ([]*configure.MonitorConfig, error) { + if curveadm.ClusterId() == -1 { + return nil, errno.ERR_NO_CLUSTER_SPECIFIED + } + hosts, hostIps, dcs, err := parseTopology(curveadm) + if err != nil { + return nil, err + } + + monitor := curveadm.Monitor() + return configure.ParseMonitorConfig(curveadm, "", monitor.Monitor, hosts, hostIps, dcs) +} + +func genStatusPlaybook(curveadm *cli.CurveAdm, + mcs []*configure.MonitorConfig, + options statusOptions) (*playbook.Playbook, error) { + mcs = configure.FilterMonitorConfig(curveadm, mcs, configure.FilterMonitorOption{ + Id: options.id, + Role: options.role, + Host: options.host, + }) + if len(mcs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } + + steps := GET_MONITOR_STATUS_PLAYBOOK_STEPS + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + ExecOptions: playbook.ExecOptions{ + SilentSubBar: true, + SilentMainBar: step == playbook.INIT_MONITOR_STATUS, + SkipError: true, + }, + }) + } + return pb, nil +} + +func displayStatus(curveadm *cli.CurveAdm, dcs []*configure.MonitorConfig, options statusOptions) { + statuses := []monitor.MonitorStatus{} + value := curveadm.MemStorage().Get(comm.KEY_MONITOR_STATUS) + if value != nil { + m := value.(map[string]monitor.MonitorStatus) + for _, status := range m { + statuses = append(statuses, status) + } + } + + output := tui.FormatMonitorStatus(statuses, options.verbose) + curveadm.WriteOutln("") + curveadm.WriteOutln("cluster name : %s", curveadm.ClusterName()) + curveadm.WriteOutln("cluster kind : %s", dcs[0].GetKind()) + curveadm.WriteOutln("") + curveadm.WriteOut("%s", output) +} + +func runStatus(curveadm *cli.CurveAdm, options statusOptions) error { + // 1) parse monitor config + mcs, err := parseMonitorConfig(curveadm) + if err != nil { + return err + } + + // 2) generate get status playbook + pb, err := genStatusPlaybook(curveadm, mcs, options) + if err != nil { + return err + } + + // 3) run playground + err = pb.Run() + + // 4) display service status + displayStatus(curveadm, mcs, options) + return err + +} diff --git a/cli/command/monitor/stop.go b/cli/command/monitor/stop.go new file mode 100644 index 000000000..4d8020a4c --- /dev/null +++ b/cli/command/monitor/stop.go @@ -0,0 +1,112 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-27 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/playbook" + tui "github.com/opencurve/curveadm/internal/tui/common" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +var ( + MONITOR_STOP_STEPS = []int{ + playbook.STOP_MONITOR_SERVICE, + } +) + +type stopOptions struct { + id string + role string + host string +} + +func NewStopCommand(curveadm *cli.CurveAdm) *cobra.Command { + var options stopOptions + cmd := &cobra.Command{ + Use: "stop [OPTIONS]", + Short: "Stop monitor service", + Args: cliutil.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return runStop(curveadm, options) + }, + DisableFlagsInUseLine: true, + } + + flags := cmd.Flags() + flags.StringVar(&options.id, "id", "*", "Specify service id") + flags.StringVar(&options.role, "role", "*", "Specify service role") + flags.StringVar(&options.host, "host", "*", "Specify service host") + + return cmd +} + +func genStopPlaybook(curveadm *cli.CurveAdm, + mcs []*configure.MonitorConfig, + options stopOptions) (*playbook.Playbook, error) { + mcs = configure.FilterMonitorConfig(curveadm, mcs, configure.FilterMonitorOption{ + Id: options.id, + Role: options.role, + Host: options.host, + }) + if len(mcs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } + + steps := MONITOR_STOP_STEPS + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: mcs, + }) + } + return pb, nil +} + +func runStop(curveadm *cli.CurveAdm, options stopOptions) error { + // 1) parse monitor config + mcs, err := parseMonitorConfig(curveadm) + if err != nil { + return err + } + + // 2) generate stop playbook + pb, err := genStopPlaybook(curveadm, mcs, options) + if err != nil { + return err + } + + // 3) confirm by user + pass := tui.ConfirmYes(tui.PromptStopService(options.id, options.role, options.host)) + if !pass { + curveadm.WriteOut(tui.PromptCancelOpetation("stop monitor service")) + return errno.ERR_CANCEL_OPERATION + } + + // 4) run playground + return pb.Run() +} diff --git a/cli/command/playground/run.go b/cli/command/playground/run.go index 599440488..0611f690f 100644 --- a/cli/command/playground/run.go +++ b/cli/command/playground/run.go @@ -112,7 +112,7 @@ func NewRunCommand(curveadm *cli.CurveAdm) *cobra.Command { flags := cmd.Flags() flags.StringVarP(&options.kind, "kind", "k", "curvefs", "Specify the type of playground (curvebs/curvefs)") flags.StringVar(&options.mountPoint, "mountpoint", "p", "Specify the mountpoint for CurveFS playground") - flags.StringVarP(&options.containerImage, "container_image", "i", "harbor.cloud.netease.com/curve/curvebs:playground", "Specify the playground container image") + flags.StringVarP(&options.containerImage, "container_image", "i", "opencurvedocker/curvebs:playground", "Specify the playground container image") return cmd } diff --git a/cli/command/scale_out.go b/cli/command/scale_out.go index e2d272afe..5e703b056 100644 --- a/cli/command/scale_out.go +++ b/cli/command/scale_out.go @@ -23,9 +23,12 @@ package command import ( + "time" + "github.com/fatih/color" "github.com/opencurve/curveadm/cli/cli" comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/configure" "github.com/opencurve/curveadm/internal/configure/topology" "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/internal/playbook" @@ -33,7 +36,6 @@ import ( cliutil "github.com/opencurve/curveadm/internal/utils" utils "github.com/opencurve/curveadm/internal/utils" "github.com/spf13/cobra" - "time" ) var ( @@ -113,8 +115,10 @@ var ( ) type scaleOutOptions struct { - insecure bool - filename string + insecure bool + filename string + poolset string + poolsetDiskType string } func NewScaleOutCommand(curveadm *cli.CurveAdm) *cobra.Command { @@ -134,6 +138,8 @@ func NewScaleOutCommand(curveadm *cli.CurveAdm) *cobra.Command { flags := cmd.Flags() flags.BoolVarP(&options.insecure, "insecure", "k", false, "Scale out cluster without precheck") + flags.StringVar(&options.poolset, "poolset", "default", "Specify the poolset name") + flags.StringVar(&options.poolsetDiskType, "poolset-disktype", "ssd", "Specify the disk type of physical pool") return cmd } @@ -305,11 +311,14 @@ func precheckBeforeScaleOut(curveadm *cli.CurveAdm, options scaleOutOptions, dat } func genScaleOutPlaybook(curveadm *cli.CurveAdm, - dcs []*topology.DeployConfig, data string) (*playbook.Playbook, error) { + dcs []*topology.DeployConfig, + data string, + options scaleOutOptions) (*playbook.Playbook, error) { diffs, _ := diffTopology(curveadm, data) dcs2scaleOut := diffs[topology.DIFF_ADD] role := dcs2scaleOut[0].GetRole() steps := SCALE_OUT_ROLE_STEPS[role] + poolset := configure.Poolset{Name: options.poolset, Type: options.poolsetDiskType} pb := playbook.NewPlaybook(curveadm) for _, step := range steps { @@ -330,10 +339,16 @@ func genScaleOutPlaybook(curveadm *cli.CurveAdm, options[comm.KEY_CREATE_POOL_TYPE] = comm.POOL_TYPE_PHYSICAL options[comm.KEY_SCALE_OUT_CLUSTER] = dcs2scaleOut options[comm.KEY_NEW_TOPOLOGY_DATA] = data + options[comm.KEY_NUMBER_OF_CHUNKSERVER] = calcNumOfChunkserver(curveadm, dcs) + + calcNumOfChunkserver(curveadm, dcs2scaleOut) + options[comm.KEY_POOLSET] = poolset case CREATE_LOGICAL_POOL: options[comm.KEY_CREATE_POOL_TYPE] = comm.POOL_TYPE_LOGICAL options[comm.KEY_SCALE_OUT_CLUSTER] = dcs2scaleOut options[comm.KEY_NEW_TOPOLOGY_DATA] = data + options[comm.KEY_NUMBER_OF_CHUNKSERVER] = calcNumOfChunkserver(curveadm, dcs) + + calcNumOfChunkserver(curveadm, dcs2scaleOut) + options[comm.KEY_POOLSET] = poolset case playbook.UPDATE_TOPOLOGY: options[comm.KEY_NEW_TOPOLOGY_DATA] = data } @@ -396,7 +411,7 @@ func runScaleOut(curveadm *cli.CurveAdm, options scaleOutOptions) error { } // 7) generate scale-out playbook - pb, err := genScaleOutPlaybook(curveadm, dcs, data) + pb, err := genScaleOutPlaybook(curveadm, dcs, data, options) if err != nil { return err } diff --git a/cli/command/status.go b/cli/command/status.go index 5bc2ea1cf..820a12569 100644 --- a/cli/command/status.go +++ b/cli/command/status.go @@ -48,11 +48,11 @@ var ( ) type statusOptions struct { - id string - role string - host string - verbose bool - showReplicas bool + id string + role string + host string + verbose bool + showInstances bool } func NewStatusCommand(curveadm *cli.CurveAdm) *cobra.Command { @@ -73,7 +73,7 @@ func NewStatusCommand(curveadm *cli.CurveAdm) *cobra.Command { flags.StringVar(&options.role, "role", "*", "Specify service role") flags.StringVar(&options.host, "host", "*", "Specify service host") flags.BoolVarP(&options.verbose, "verbose", "v", false, "Verbose output for status") - flags.BoolVarP(&options.showReplicas, "show-replicas", "s", false, "Display service replicas") + flags.BoolVarP(&options.showInstances, "show-instances", "s", false, "Display service num") return cmd } @@ -113,7 +113,7 @@ func displayStatus(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig, options } } - output := tui.FormatStatus(statuses, options.verbose, options.showReplicas) + output := tui.FormatStatus(statuses, options.verbose, options.showInstances) curveadm.WriteOutln("") curveadm.WriteOutln("cluster name : %s", curveadm.ClusterName()) curveadm.WriteOutln("cluster kind : %s", dcs[0].GetKind()) diff --git a/cmd/service/main.go b/cmd/service/main.go new file mode 100644 index 000000000..9db6bc713 --- /dev/null +++ b/cmd/service/main.go @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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 main + +import ( + "github.com/opencurve/curveadm/http" + "github.com/opencurve/pigeon" +) + +func main() { + admServer := http.NewServer() + pigeon.Serve(admServer) +} diff --git a/configs/bs/cluster/monitor.yaml b/configs/bs/cluster/monitor.yaml new file mode 100644 index 000000000..0c330c89c --- /dev/null +++ b/configs/bs/cluster/monitor.yaml @@ -0,0 +1,20 @@ +host: server-host + +node_exporter: + container_image: prom/node-exporter:latest + listen_port: 9100 + +prometheus: + container_image: prom/prometheus:latest + data_dir: /tmp/monitor/prometheus + listen_port: 9090 + retention.time: 7d + retention.size: 256GB + +grafana: + container_image: grafana/grafana:latest + data_dir: /tmp/monitor/grafana + listen_port: 3000 + username: admin + password: curve + \ No newline at end of file diff --git a/configs/bs/cluster/scale-out.yaml b/configs/bs/cluster/scale-out.yaml index 8469a5153..bd8d6ec65 100644 --- a/configs/bs/cluster/scale-out.yaml +++ b/configs/bs/cluster/scale-out.yaml @@ -1,10 +1,10 @@ chunkserver_services: deploy: - host: ${machine1} - replica: 20 # 请注意这里的replica不代表存储池的副本数,而是节点上同类进程的数量,比如这里指的是chunkserver进程的数量,也就是配置的磁盘数,相关问题可以参考:https://github.com/opencurve/curveadm/issues/146 + instances: 20 # 请注意这里的replica不代表存储池的副本数,而是节点上同类进程的数量,比如这里指的是chunkserver进程的数量,也就是配置的磁盘数,相关问题可以参考:https://github.com/opencurve/curveadm/issues/146 config: - host: ${machine2} - replica: 20 + instances: 20 - host: ${machine3} - replica: 20 + instances: 20 diff --git a/configs/bs/cluster/topology.yaml b/configs/bs/cluster/topology.yaml index f26db217c..e644839c9 100644 --- a/configs/bs/cluster/topology.yaml +++ b/configs/bs/cluster/topology.yaml @@ -1,6 +1,6 @@ kind: curvebs global: - container_image: opencurvedocker/curvebs:v1.2 + container_image: opencurvedocker/curvebs:v1.2.6 log_dir: ${home}/logs/${service_role}${service_replicas_sequence} data_dir: ${home}/data/${service_role}${service_replicas_sequence} s3.nos_address: <> @@ -36,16 +36,16 @@ mds_services: chunkserver_services: config: listen.ip: ${service_host} - listen.port: 82${format_replicas_sequence} # 8200,8201,8202 - data_dir: /data/chunkserver${service_replicas_sequence} # /data/chunkserver0, /data/chunksever1 + listen.port: 82${format_instances_sequence} # 8200,8201,8202 + data_dir: /data/chunkserver${service_instances_sequence} # /data/chunkserver0, /data/chunksever1 copysets: 100 deploy: - host: ${machine1} - replicas: 3 # 请注意这里的replica不代表存储池的副本数,而是节点上同类进程的数量,比如这里指的是chunkserver进程的数量,也就是配置的磁盘数,相关问题可以参考:https://github.com/opencurve/curveadm/issues/146 + instances: 3 - host: ${machine2} - replicas: 3 + instances: 3 - host: ${machine3} - replicas: 3 + instances: 3 snapshotclone_services: config: diff --git a/configs/bs/stand-alone/topology.yaml b/configs/bs/stand-alone/topology.yaml index d3a854d82..544bf64d5 100644 --- a/configs/bs/stand-alone/topology.yaml +++ b/configs/bs/stand-alone/topology.yaml @@ -1,6 +1,6 @@ kind: curvebs global: - container_image: opencurvedocker/curvebs:v1.2 + container_image: opencurvedocker/curvebs:v1.2.7-rc1_0ff8409 log_dir: ${home}/logs/${service_role}${service_host_sequence} data_dir: ${home}/data/${service_role}${service_host_sequence} s3.nos_address: <> diff --git a/configs/fs/cluster/client.yaml b/configs/fs/cluster/client.yaml index cbe164c85..08e1bb887 100644 --- a/configs/fs/cluster/client.yaml +++ b/configs/fs/cluster/client.yaml @@ -1,5 +1,5 @@ kind: curvefs -container_image: opencurvedocker/curvefs:latest +container_image: quay.io/opencurve/curve/curvefs:v2.7.0-rc1_d8a1137 mdsOpt.rpcRetryOpt.addrs: 10.0.1.1:6700,10.0.1.2:6700,10.0.1.3:6700 log_dir: /home/curve/curvefs/logs/client diff --git a/configs/fs/cluster/topology.yaml b/configs/fs/cluster/topology.yaml index 5f795e6d8..b4ed43484 100644 --- a/configs/fs/cluster/topology.yaml +++ b/configs/fs/cluster/topology.yaml @@ -3,7 +3,7 @@ global: report_usage: true data_dir: ${home}/curvefs/data/${service_role} log_dir: ${home}/curvefs/logs/${service_role} - container_image: opencurvedocker/curvefs:latest + container_image: quay.io/opencurve/curve/curvefs:v2.7.0-rc1_d8a1137 variable: home: /tmp machine1: server-host1 @@ -38,7 +38,7 @@ metaserver_services: global.enable_external_server: true metaserver.loglevel: 0 # whether commit filesystem caches of raft wal to disk. - # it should be true iff you wants data NEVER lost, + # it should be true if you wants data NEVER lost, # of course, it will leads some performance skew. braft.raft_sync: false deploy: diff --git a/configs/fs/stand-alone/client.yaml b/configs/fs/stand-alone/client.yaml index cbe164c85..08e1bb887 100644 --- a/configs/fs/stand-alone/client.yaml +++ b/configs/fs/stand-alone/client.yaml @@ -1,5 +1,5 @@ kind: curvefs -container_image: opencurvedocker/curvefs:latest +container_image: quay.io/opencurve/curve/curvefs:v2.7.0-rc1_d8a1137 mdsOpt.rpcRetryOpt.addrs: 10.0.1.1:6700,10.0.1.2:6700,10.0.1.3:6700 log_dir: /home/curve/curvefs/logs/client diff --git a/configs/fs/stand-alone/topology.yaml b/configs/fs/stand-alone/topology.yaml index 6a21b5ed0..3394604ab 100644 --- a/configs/fs/stand-alone/topology.yaml +++ b/configs/fs/stand-alone/topology.yaml @@ -3,7 +3,7 @@ global: report_usage: true data_dir: ${home}/curvefs/data/${service_role}${service_host_sequence} log_dir: ${home}/curvefs/logs/${service_role}${service_host_sequence} - container_image: opencurvedocker/curvefs:latest + container_image: quay.io/opencurve/curve/curvefs:v2.7.0-rc1_d8a1137 variable: home: /tmp target: server-host diff --git a/go.mod b/go.mod index 301fc078e..ad6de144b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/opencurve/curveadm go 1.18 require ( - github.com/docker/cli v20.10.21+incompatible + github.com/docker/cli v23.0.3+incompatible github.com/dustin/go-humanize v1.0.0 github.com/fatih/color v1.13.0 github.com/go-resty/resty/v2 v2.7.0 @@ -12,88 +12,123 @@ require ( github.com/jpillora/longestcommon v0.0.0-20161227235612-adb9d91ee629 github.com/kpango/glg v1.6.14 github.com/mattn/go-sqlite3 v1.14.16 + github.com/mcuadros/go-defaults v1.2.0 github.com/melbahja/goph v1.3.0 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/moby/term v0.0.0-20221205130635-1aeaba878587 + github.com/opencurve/pigeon v0.0.0-20230512031044-d5a430bb02a4 github.com/pingcap/log v1.1.0 github.com/sergi/go-diff v1.2.0 - github.com/spf13/cobra v1.6.1 - github.com/spf13/viper v1.14.0 - github.com/stretchr/testify v1.8.1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/viper v1.15.0 + github.com/stretchr/testify v1.8.2 github.com/vbauerster/mpb/v7 v7.5.3 go.uber.org/zap v1.24.0 - golang.org/x/crypto v0.3.0 + golang.org/x/crypto v0.8.0 ) require ( - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/Microsoft/hcsshim v0.9.5 // indirect + github.com/Wine93/grace v0.0.0-20221021033009-7d0348013a3c // indirect + github.com/bytedance/sonic v1.8.7 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect + github.com/facebookgo/grace v0.0.0-20180706040059-75cf19382434 // indirect + github.com/facebookgo/httpdown v0.0.0-20180706035922-5979d39b15c2 // indirect + github.com/facebookgo/stats v0.0.0-20151006221625-1b76add642e4 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.9.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.12.0 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/google/pprof v0.0.0-20230406165453-00490a63f317 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/imroc/req/v3 v3.33.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/leodido/go-urn v1.2.3 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/onsi/ginkgo/v2 v2.9.2 // indirect + github.com/quic-go/qpack v0.4.0 // indirect + github.com/quic-go/qtls-go1-19 v0.3.2 // indirect + github.com/quic-go/qtls-go1-20 v0.2.2 // indirect + github.com/quic-go/quic-go v0.33.0 // indirect + github.com/sevlyar/go-daemon v0.1.6 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect +) + +require ( + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/containerd/continuity v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.21+incompatible // indirect + github.com/docker/docker v23.0.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/fvbommel/sortorder v1.0.2 // indirect - github.com/goccy/go-json v0.10.0 // indirect + github.com/fvbommel/sortorder v1.1.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kpango/fastime v1.1.6 // indirect github.com/kr/fs v0.1.0 // indirect - github.com/magiconair/properties v1.8.6 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moby/sys/mount v0.3.3 // indirect - github.com/moby/sys/mountinfo v0.6.2 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc2 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect + github.com/pelletier/go-toml/v2 v2.0.7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/sftp v1.13.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/rivo/uniseg v0.4.3 // indirect + github.com/rqlite/gorqlite v0.0.0-20230310040812-ec5e524a562e github.com/sirupsen/logrus v1.9.0 // indirect - github.com/spf13/afero v1.9.3 // indirect + github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.4.1 // indirect + github.com/subosito/gotenv v1.4.2 // indirect github.com/theupdateframework/notary v0.7.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.3.0 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/term v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect - golang.org/x/tools v0.4.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/term v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/tools v0.8.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index f5bdadec9..ce71e43db 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -37,51 +36,12 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.9.5 h1:AbV+VPfTrIVffukazHcpxmz/sRiE6YaMDzHWR9BXZHo= -github.com/Microsoft/hcsshim v0.9.5/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= @@ -92,302 +52,102 @@ github.com/Wine93/goph v0.0.0-20220907033045-3b286d827fb3/go.mod h1:vy08GGf/z8wG github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc= github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.21+incompatible h1:qVkgyYUnOLQ98LtXBrwd/duVqPT2X4SHndOuGsfwyhU= -github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/cli v23.0.3+incompatible h1:Zcse1DuDqBdgI7OQDV8Go7b83xLgfhW1eza4HfEdxpY= +github.com/docker/cli v23.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.21+incompatible h1:UTLdBmHk3bEY+w8qeO5KttOhy6OmXWsl/FEet9Uswog= -github.com/docker/docker v20.10.21+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/docker v23.0.3+incompatible h1:9GhVsShNWz1hO//9BNg/dpMnZW25KydO4wtVxWAIbho= +github.com/docker/docker v23.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= -github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= +github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.3.0 h1:pgwjLi/dvffoP9aabwkT3AKpXQM93QARkjFhDDqC1UE= github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= -github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-module/carbon/v2 v2.1.9 h1:OWkhYzTTPe+jPOUEL2JkvGwf6bKNQJoh4LVT1LUay80= github.com/golang-module/carbon/v2 v2.1.9/go.mod h1:NF5unWf838+pyRY0o+qZdIwBMkFf7w0hmLIguLiEpzU= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -398,7 +158,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -414,8 +173,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI= @@ -430,11 +189,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -449,39 +205,17 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -489,48 +223,26 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE= github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc= github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jpillora/longestcommon v0.0.0-20161227235612-adb9d91ee629 h1:1dSBUfGlorLAua2CRx0zFN7kQsTpE2DQSmr7rrTNgY8= github.com/jpillora/longestcommon v0.0.0-20161227235612-adb9d91ee629/go.mod h1:mb5nS4uRANwOJSZj8rlCWAfAcGi72GGMIXx+xGOjA7M= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kpango/fastime v1.1.6 h1:lAw1Tiwnlbsx1xZs6W9eM7/8niwabknewbmLkh/yTVo= github.com/kpango/fastime v1.1.6/go.mod h1:tTNDbIo5qL6D7g5vh2YbkyUbOVP2kD/we3rSjN22PMY= github.com/kpango/glg v1.6.14 h1:Ss3ZvTQ23blUCDYizSAijiFTZsgGeYr/lanUGgQ10rY= @@ -539,148 +251,71 @@ github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= -github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= -github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= -github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= -github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= +github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pingcap/errors v0.11.0 h1:DCJQB8jrHbQ1VVlMFIrbj2ApScNNotVmkSNplu2yUt4= github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pingcap/log v1.1.0 h1:ELiPxACz7vdo1qAvvaWJg1NrYFoY6gqAh/+Uo6aXdD8= github.com/pingcap/log v1.1.0/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -690,217 +325,121 @@ github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go= github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rqlite/gorqlite v0.0.0-20230310040812-ec5e524a562e h1:updBXFrJFAJO/3b/mctukZQEIVUq09iwV/wireIlZFA= +github.com/rqlite/gorqlite v0.0.0-20230310040812-ec5e524a562e/go.mod h1:xF/KoXmrRyahPfo5L7Szb5cAAUl53dMWBh9cMruGEZg= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= -github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= -github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= +github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= -github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vbauerster/mpb/v7 v7.5.3 h1:BkGfmb6nMrrBQDFECR/Q7RkKCw7ylMetCb4079CGs4w= github.com/vbauerster/mpb/v7 v7.5.3/go.mod h1:i+h4QY6lmLvBNK2ah1fSreiw3ajskRlBp9AhY/PnuOE= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -934,31 +473,23 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -973,22 +504,15 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -998,8 +522,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1010,51 +532,30 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1063,53 +564,33 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1118,34 +599,25 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1169,17 +641,14 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1187,14 +656,12 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1221,13 +688,11 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1236,7 +701,6 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1247,31 +711,24 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1281,12 +738,9 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1299,52 +753,36 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1 h1:7QBf+IK2gx70Ap/hDsOmam3GE0v9HicjfEdAxE62UoM= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1354,43 +792,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= -k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= -k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/http/core/core.go b/http/core/core.go new file mode 100644 index 000000000..d10f503ea --- /dev/null +++ b/http/core/core.go @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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 core + +import ( + "fmt" + "strconv" + + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/pigeon" +) + +func Exit(r *pigeon.Request, err error) bool { + var status int + if err == nil { + status = 200 + r.SendJSON(pigeon.JSON{ + "errorCode": "0", + "errorMsg": "success", + }) + } else { + code := err.(*errno.ErrorCode) + if code.IsHttpErr() { + status = code.HttpCode() + } else { + status = 503 + } + r.SendJSON(pigeon.JSON{ + "errorCode": strconv.Itoa(code.GetCode()), + "errorMsg": fmt.Sprintf("desc: %s; clue: %s", code.GetDescription(), code.GetClue()), + }) + } + return r.Exit(status) +} + +func Default(r *pigeon.Request) bool { + r.Logger().Warn("unupport request uri", pigeon.Field("uri", r.Uri)) + return Exit(r, errno.ERR_UNSUPPORT_REQUEST_URI) +} + +func ExitSuccessWithData(r *pigeon.Request, data interface{}) bool { + r.SendJSON(pigeon.JSON{ + "data": data, + "errorCode": "0", + "errorMsg": "success", + }) + return r.Exit(200) +} + +func ExitFailWithData(r *pigeon.Request, data interface{}, message string) bool { + r.SendJSON(pigeon.JSON{ + "errorCode": "503", + "errorMsg": message, + "data": data, + }) + return r.Exit(503) +} diff --git a/http/manager/bind.go b/http/manager/bind.go new file mode 100644 index 000000000..0dece3d83 --- /dev/null +++ b/http/manager/bind.go @@ -0,0 +1,81 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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 manager + +import ( + "github.com/opencurve/pigeon" + "mime/multipart" + "net/http" +) + +var METHOD_REQUEST map[string]Request + +type ( + HandlerFunc func(r *pigeon.Request, ctx *Context) bool + + Context struct { + Data interface{} + } + + Request struct { + httpMethod string + method string + vType interface{} + handler HandlerFunc + } +) + +func init() { + METHOD_REQUEST = map[string]Request{} + for _, request := range requests { + METHOD_REQUEST[request.method] = request + } +} + +type DeployClusterCmdRequest struct { + Command string `json:"command" binding:"required"` +} + +type DeployClusterUploadRequest struct { + FilePath string `json:"filepath" form:"filepath" binding:"required"` + File *multipart.FileHeader `form:"file" binding:"required"` +} + +type DeployClusterDownloadRequest struct { + FilePath string `json:"filepath" form:"filepath" binding:"required"` +} + +var requests = []Request{ + { + http.MethodPost, + "cluster.deploy.cmd", + DeployClusterCmdRequest{}, + DeployClusterCmd, + }, + { + http.MethodPost, + "cluster.deploy.upload", + DeployClusterUploadRequest{}, + DeployClusterUpload, + }, + { + http.MethodGet, + "cluster.deploy.download", + DeployClusterDownloadRequest{}, + DeployClusterDownload, + }, +} diff --git a/http/manager/entrypoint.go b/http/manager/entrypoint.go new file mode 100644 index 000000000..bd81da5cb --- /dev/null +++ b/http/manager/entrypoint.go @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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 manager + +import ( + "reflect" + + "github.com/mcuadros/go-defaults" + "github.com/opencurve/curveadm/http/core" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/pigeon" +) + +func Entrypoint(r *pigeon.Request) bool { + if r.Method != pigeon.HTTP_METHOD_GET && + r.Method != pigeon.HTTP_METHOD_POST { + return core.Exit(r, errno.ERR_UNSUPPORT_HTTP_METHOD) + } + + request, ok := METHOD_REQUEST[r.Args["method"]] + if !ok { + return core.Exit(r, errno.ERR_UNSUPPORT_METHOD_ARGUMENT) + } else if request.httpMethod != r.Method { + return core.Exit(r, errno.ERR_HTTP_METHOD_MISMATCHED) + } + + vType := reflect.TypeOf(request.vType) + data := reflect.New(vType).Interface() + if err := r.BindBody(data); err != nil { + r.Logger().Error("bad request form param", + pigeon.Field("error", err)) + return core.Exit(r, errno.ERR_BAD_REQUEST_FORM_PARAM) + } + defaults.SetDefaults(data) + return request.handler(r, &Context{data}) +} diff --git a/http/manager/manager.go b/http/manager/manager.go new file mode 100644 index 000000000..06e53cfe8 --- /dev/null +++ b/http/manager/manager.go @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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 manager + +import ( + "github.com/opencurve/curveadm/http/core" + "github.com/opencurve/curveadm/internal/utils" + "github.com/opencurve/pigeon" + "io" + "os/exec" +) + +func DeployClusterCmd(r *pigeon.Request, ctx *Context) bool { + data := ctx.Data.(*DeployClusterCmdRequest) + r.Logger().Info("DeployClusterCmd", pigeon.Field("command", data.Command)) + cmd := exec.Command("/bin/bash", "-c", data.Command) + out, err := cmd.CombinedOutput() + if err != nil { + r.Logger().Warn("DeployClusterCmd failed when execute command", + pigeon.Field("error", err)) + return core.ExitFailWithData(r, string(out), string(out)) + } + r.Logger().Info("DeployClusterCmd", pigeon.Field("result", out)) + return core.ExitSuccessWithData(r, string(out)) +} + +func DeployClusterUpload(r *pigeon.Request, ctx *Context) bool { + data := ctx.Data.(*DeployClusterUploadRequest) + r.Logger().Info("DeployClusterUpload", pigeon.Field("file", data.FilePath)) + mf, err := data.File.Open() + if err != nil { + r.Logger().Warn("DeployClusterUpload failed when open file", + pigeon.Field("error", err)) + return core.ExitFailWithData(r, err.Error(), err.Error()) + } + defer mf.Close() + content, err := io.ReadAll(mf) + if err != nil { + r.Logger().Warn("DeployClusterUpload failed when read file", + pigeon.Field("error", err)) + return core.ExitFailWithData(r, err.Error(), err.Error()) + } + err = utils.WriteFile(data.FilePath, string(content), 0644) + if err != nil { + r.Logger().Warn("DeployClusterUpload failed when write file", + pigeon.Field("error", err)) + return core.ExitFailWithData(r, err.Error(), err.Error()) + } + return core.Exit(r, err) +} + +func DeployClusterDownload(r *pigeon.Request, ctx *Context) bool { + data := ctx.Data.(*DeployClusterDownloadRequest) + r.Logger().Info("DeployClusterDownload", pigeon.Field("file", data.FilePath)) + return r.SendFile(data.FilePath) +} diff --git a/http/server.go b/http/server.go new file mode 100644 index 000000000..82fface6e --- /dev/null +++ b/http/server.go @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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 http + +import ( + "github.com/opencurve/curveadm/http/core" + "github.com/opencurve/curveadm/http/manager" + "github.com/opencurve/pigeon" +) + +func NewServer() *pigeon.HTTPServer { + server := pigeon.NewHTTPServer("curveadm") + server.Route("/", manager.Entrypoint) + server.DefaultRoute(core.Default) + return server +} diff --git a/internal/build/debug.go b/internal/build/debug.go index 48559377e..a12c83e21 100644 --- a/internal/build/debug.go +++ b/internal/build/debug.go @@ -38,7 +38,8 @@ const ( DEBUG_TOOL = "DEBUG_TOOL" DEBUG_CLUSTER = "DEBUG_CLUSTER" DEBUG_CREATE_POOL = "DEBUG_CREATE_POOL" - DEBUG_CLIENT_CONFIGURE = "DEBUG_CLIENT_CONFIGURE" + DEBUG_CLIENT_CONFIGURE = "DEBUG_CLIENT_CONFIGURE" + DEBUG_MONITOR_CONFIGURE = "DEBUG_MONITOR_CONFIGURE" ) type Field struct { diff --git a/internal/common/common.go b/internal/common/common.go index c897f0cd7..8e67c6485 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -41,10 +41,14 @@ var ( // task options const ( // common - KEY_ALL_DEPLOY_CONFIGS = "ALL_DEPLOY_CONFIGS" - KEY_CREATE_POOL_TYPE = "POOL_TYPE" - POOL_TYPE_LOGICAL = "logicalpool" - POOL_TYPE_PHYSICAL = "physicalpool" + KEY_ALL_DEPLOY_CONFIGS = "ALL_DEPLOY_CONFIGS" + KEY_POOLSET = "KEY_POOLSET" + KEY_CREATE_POOL_TYPE = "POOL_TYPE" + POOL_TYPE_LOGICAL = "logicalpool" + POOL_TYPE_PHYSICAL = "physicalpool" + POOLSET = "poolset" + POOLSET_DISK_TYPE = "poolset-disktype" + KEY_NUMBER_OF_CHUNKSERVER = "NUMBER_OF_CHUNKSERVER" // format KEY_ALL_FORMAT_STATUS = "ALL_FORMAT_STATUS" @@ -75,14 +79,16 @@ const ( CLEANED_CONTAINER_ID = "-" // client - KEY_CLIENT_HOST = "CLIENT_HOST" - KEY_CLIENT_KIND = "CLIENT_KIND" - KEY_ALL_CLIENT_STATUS = "ALL_CLIENT_STATUS" - KEY_MAP_OPTIONS = "MAP_OPTIONS" - KEY_MOUNT_OPTIONS = "MOUNT_OPTIONS" - CLIENT_STATUS_LOSED = "Losed" - KERNERL_MODULE_NBD = "nbd" - KERNERL_MODULE_FUSE = "fuse" + KEY_CLIENT_HOST = "CLIENT_HOST" + KEY_CLIENT_KIND = "CLIENT_KIND" + KEY_ALL_CLIENT_STATUS = "ALL_CLIENT_STATUS" + KEY_CLIENT_STATUS_VERBOSE = "CLIENT_STATUS_VERBOSE" + KEY_MAP_OPTIONS = "MAP_OPTIONS" + KEY_MOUNT_OPTIONS = "MOUNT_OPTIONS" + CLIENT_STATUS_LOSED = "Losed" + CLIENT_STATUS_UNKNOWN = "Unknown" + KERNERL_MODULE_NBD = "nbd" + KERNERL_MODULE_FUSE = "fuse" // polarfs KEY_POLARFS_HOST = "POLARFS_HOST" @@ -104,6 +110,12 @@ const ( // playground KEY_ALL_PLAYGROUNDS_STATUS = "ALL_PLAYGROUNDS_STATUS" PLAYGROUDN_STATUS_LOSED = "Losed" + + // monitor + KEY_MONITOR_HOST = "MONITOR_HOST" + KEY_SERVICE_HOSTS = "SERVICE_HOSTS" + KEY_MONITOR_STATUS = "MONITOR_STATUS" + CLEANED_MONITOR_CONF = "-" ) // others diff --git a/internal/configure/client.go b/internal/configure/client.go index 607cb7638..7d0de47ac 100644 --- a/internal/configure/client.go +++ b/internal/configure/client.go @@ -144,19 +144,36 @@ func ParseClientCfg(data string) (*ClientConfig, error) { } func ParseClientConfig(filename string) (*ClientConfig, error) { + // 1. read file content + data, err := utils.ReadFile(filename) + if err != nil { + return nil, errno.ERR_PARSE_CLIENT_CONFIGURE_FAILED.E(err) + } + + // 2. new parser parser := viper.NewWithOptions(viper.KeyDelimiter("::")) parser.SetConfigFile(filename) parser.SetConfigType("yaml") - if err := parser.ReadInConfig(); err != nil { + err = parser.ReadInConfig() + if err != nil { return nil, errno.ERR_PARSE_CLIENT_CONFIGURE_FAILED.E(err) } - config := map[string]interface{}{} - if err := parser.Unmarshal(&config); err != nil { + // 3. parse + m := map[string]interface{}{} + err = parser.Unmarshal(&m) + if err != nil { return nil, errno.ERR_PARSE_CLIENT_CONFIGURE_FAILED.E(err) } - build.DEBUG(build.DEBUG_CLIENT_CONFIGURE, config) - return NewClientConfig(config) + + // 4. new config + cfg, err := NewClientConfig(m) + if err != nil { + return nil, err + } + + cfg.data = data + return cfg, nil } func (cc *ClientConfig) getString(key string) string { @@ -186,6 +203,7 @@ func (cc *ClientConfig) GetS3BucketName() string { return cc.getStri func (cc *ClientConfig) GetContainerPid() string { return cc.getString(KEY_CONTAINER_PID) } func (cc *ClientConfig) GetEnvironments() string { return cc.getString(KEY_ENVIRONMENT) } func (cc *ClientConfig) GetCoreLocateDir() string { return DEFAULT_CORE_LOCATE_DIR } +func (cc *ClientConfig) GetData() string { return cc.data } func (cc *ClientConfig) GetServiceConfig() map[string]string { return cc.serviceConfig } func (cc *ClientConfig) GetVariables() *variable.Variables { return cc.variables } func (cc *ClientConfig) GetContainerImage() string { diff --git a/internal/configure/curveadm/curveadm.go b/internal/configure/curveadm/curveadm.go index 4f1b850ba..749a746dd 100644 --- a/internal/configure/curveadm/curveadm.go +++ b/internal/configure/curveadm/curveadm.go @@ -25,6 +25,10 @@ package curveadm import ( + "fmt" + "os" + "regexp" + "github.com/opencurve/curveadm/internal/build" "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/internal/utils" @@ -40,14 +44,25 @@ import ( * [ssh_connections] * retries = 3 * timeout = 10 + * + * [database] + * url = "sqlite:///home/curve/.curveadm/data/curveadm.db" */ const ( KEY_LOG_LEVEL = "log_level" KEY_SUDO_ALIAS = "sudo_alias" + KEY_ENGINE = "engine" KEY_TIMEOUT = "timeout" KEY_AUTO_UPGRADE = "auto_upgrade" KEY_SSH_RETRIES = "retries" KEY_SSH_TIMEOUT = "timeout" + KEY_DB_URL = "url" + + // rqlite://127.0.0.1:4000 + // sqlite:///home/curve/.curveadm/data/curveadm.db + REGEX_DB_URL = "^(sqlite|rqlite)://(.+)$" + DB_SQLITE = "sqlite" + DB_RQLITE = "rqlite" WITHOUT_SUDO = " " ) @@ -56,30 +71,24 @@ type ( CurveAdmConfig struct { LogLevel string SudoAlias string + Engine string Timeout int AutoUpgrade bool SSHRetries int SSHTimeout int + DBUrl string } CurveAdm struct { Defaults map[string]interface{} `mapstructure:"defaults"` SSHConnections map[string]interface{} `mapstructure:"ssh_connections"` + DataBase map[string]interface{} `mapstructure:"database"` } ) var ( GlobalCurveAdmConfig *CurveAdmConfig - defaultCurveAdmConfig = &CurveAdmConfig{ - LogLevel: "error", - SudoAlias: "sudo", - Timeout: 180, - AutoUpgrade: true, - SSHRetries: 3, - SSHTimeout: 10, - } - SUPPORT_LOG_LEVEL = map[string]bool{ "debug": true, "info": true, @@ -92,6 +101,21 @@ func ReplaceGlobals(cfg *CurveAdmConfig) { GlobalCurveAdmConfig = cfg } +func newDefault() *CurveAdmConfig { + home, _ := os.UserHomeDir() + cfg := &CurveAdmConfig{ + LogLevel: "error", + SudoAlias: "sudo", + Engine: "docker", + Timeout: 180, + AutoUpgrade: true, + SSHRetries: 3, + SSHTimeout: 10, + DBUrl: fmt.Sprintf("sqlite://%s/.curveadm/data/curveadm.db", home), + } + return cfg +} + // TODO(P2): using ItemSet to check value type func requirePositiveInt(k string, v interface{}) (int, error) { num, ok := utils.Str2Int(v.(string)) @@ -133,6 +157,10 @@ func parseDefaultsSection(cfg *CurveAdmConfig, defaults map[string]interface{}) case KEY_SUDO_ALIAS: cfg.SudoAlias = v.(string) + // container engine + case KEY_ENGINE: + cfg.Engine = v.(string) + // timeout case KEY_TIMEOUT: num, err := requirePositiveInt(KEY_TIMEOUT, v) @@ -141,6 +169,7 @@ func parseDefaultsSection(cfg *CurveAdmConfig, defaults map[string]interface{}) } cfg.Timeout = num + // auto upgrade case KEY_AUTO_UPGRADE: yes, err := requirePositiveBool(KEY_AUTO_UPGRADE, v) if err != nil { @@ -189,8 +218,39 @@ func parseConnectionSection(cfg *CurveAdmConfig, connection map[string]interface return nil } +func parseDatabaseSection(cfg *CurveAdmConfig, database map[string]interface{}) error { + if database == nil { + return nil + } + + for k, v := range database { + switch k { + // database url + case KEY_DB_URL: + dbUrl := v.(string) + pattern := regexp.MustCompile(REGEX_DB_URL) + mu := pattern.FindStringSubmatch(dbUrl) + if len(mu) == 0 { + return errno.ERR_UNSUPPORT_CURVEADM_DATABASE_URL.F("url: %s", dbUrl) + } + cfg.DBUrl = dbUrl + + default: + return errno.ERR_UNSUPPORT_CURVEADM_CONFIGURE_ITEM. + F("%s: %s", k, v) + } + } + + return nil +} + +type sectionParser struct { + parser func(*CurveAdmConfig, map[string]interface{}) error + section map[string]interface{} +} + func ParseCurveAdmConfig(filename string) (*CurveAdmConfig, error) { - cfg := defaultCurveAdmConfig + cfg := newDefault() if !utils.PathExist(filename) { build.DEBUG(build.DEBUG_CURVEADM_CONFIGURE, cfg) return cfg, nil @@ -211,13 +271,16 @@ func ParseCurveAdmConfig(filename string) (*CurveAdmConfig, error) { return nil, errno.ERR_PARSE_CURVRADM_CONFIGURE_FAILED.E(err) } - err = parseDefaultsSection(cfg, global.Defaults) - if err != nil { - return nil, err + items := []sectionParser{ + {parseDefaultsSection, global.Defaults}, + {parseConnectionSection, global.SSHConnections}, + {parseDatabaseSection, global.DataBase}, } - err = parseConnectionSection(cfg, global.SSHConnections) - if err != nil { - return nil, err + for _, item := range items { + err := item.parser(cfg, item.section) + if err != nil { + return nil, err + } } build.DEBUG(build.DEBUG_CURVEADM_CONFIGURE, cfg) @@ -229,9 +292,23 @@ func (cfg *CurveAdmConfig) GetTimeout() int { return cfg.Timeout } func (cfg *CurveAdmConfig) GetAutoUpgrade() bool { return cfg.AutoUpgrade } func (cfg *CurveAdmConfig) GetSSHRetries() int { return cfg.SSHRetries } func (cfg *CurveAdmConfig) GetSSHTimeout() int { return cfg.SSHTimeout } +func (cfg *CurveAdmConfig) GetEngine() string { return cfg.Engine } func (cfg *CurveAdmConfig) GetSudoAlias() string { if len(cfg.SudoAlias) == 0 { return WITHOUT_SUDO } return cfg.SudoAlias } + +func (cfg *CurveAdmConfig) GetDBUrl() string { + return cfg.DBUrl +} + +func (cfg *CurveAdmConfig) GetDBPath() string { + pattern := regexp.MustCompile(REGEX_DB_URL) + mu := pattern.FindStringSubmatch(cfg.DBUrl) + if len(mu) == 0 || mu[1] != DB_SQLITE { + return "" + } + return mu[2] +} diff --git a/internal/configure/format.go b/internal/configure/format.go index fa9f0581f..bf53d71e2 100644 --- a/internal/configure/format.go +++ b/internal/configure/format.go @@ -32,6 +32,12 @@ import ( const ( DEFAULT_CONTAINER_IMAGE = "opencurvedocker/curvebs:v1.2" + DEFAULT_BLOCK_SIZE = 4096 + DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024 +) + +var ( + VALID_BLOCK_SIZE = [2]int{512, 4096} ) /* @@ -51,12 +57,16 @@ type ( Device string MountPoint string FormtPercent int + BlockSize int + ChunkSize int } Format struct { ContainerImage string `mapstructure:"container_image"` Hosts []string `mapstructure:"host"` Disks []string `mapstructure:"disk"` + BlockSize int `mapstructure:"block_size"` + ChunkSize int `mapstructure:"chunk_size"` } ) @@ -93,6 +103,16 @@ func newFormatConfig(containerImage, host, disk string) (*FormatConfig, error) { }, nil } +func isValidBlockSize(blocksize int) bool { + for _, bs := range VALID_BLOCK_SIZE { + if bs == blocksize { + return true + } + } + + return false +} + func ParseFormat(filename string) ([]*FormatConfig, error) { if !utils.PathExist(filename) { return nil, errno.ERR_FORMAT_CONFIGURE_FILE_NOT_EXIST. @@ -107,7 +127,10 @@ func ParseFormat(filename string) ([]*FormatConfig, error) { return nil, errno.ERR_PARSE_FORMAT_CONFIGURE_FAILED.E(err) } - format := &Format{} + format := &Format{ + BlockSize: DEFAULT_BLOCK_SIZE, + ChunkSize: DEFAULT_CHUNK_SIZE, + } err = parser.Unmarshal(format) if err != nil { return nil, errno.ERR_PARSE_FORMAT_CONFIGURE_FAILED.E(err) @@ -118,6 +141,10 @@ func ParseFormat(filename string) ([]*FormatConfig, error) { containerImage = format.ContainerImage } + if !isValidBlockSize(format.BlockSize) { + return nil, errno.ERR_INVALID_BLOCK_SIZE.F("block_size: %d", format.BlockSize) + } + fcs := []*FormatConfig{} for _, host := range format.Hosts { for _, disk := range format.Disks { @@ -125,6 +152,8 @@ func ParseFormat(filename string) ([]*FormatConfig, error) { if err != nil { return nil, err } + fc.BlockSize = format.BlockSize + fc.ChunkSize = format.ChunkSize fcs = append(fcs, fc) } } @@ -137,3 +166,5 @@ func (fc *FormatConfig) GetHost() string { return fc.Host } func (fc *FormatConfig) GetDevice() string { return fc.Device } func (fc *FormatConfig) GetMountPoint() string { return fc.MountPoint } func (fc *FormatConfig) GetFormatPercent() int { return fc.FormtPercent } +func (fc *FormatConfig) GetBlockSize() int { return fc.BlockSize } +func (fc *FormatConfig) GetChunkSize() int { return fc.ChunkSize } diff --git a/internal/configure/hosts/hc_get.go b/internal/configure/hosts/hc_get.go index 876538410..219aeff57 100644 --- a/internal/configure/hosts/hc_get.go +++ b/internal/configure/hosts/hc_get.go @@ -70,14 +70,28 @@ func (hc *HostConfig) getBool(i *comm.Item) bool { func (hc *HostConfig) GetHost() string { return hc.getString(CONFIG_HOST) } func (hc *HostConfig) GetHostname() string { return hc.getString(CONFIG_HOSTNAME) } func (hc *HostConfig) GetSSHHostname() string { return hc.getString(CONFIG_SSH_HOSTNAME) } -func (hc *HostConfig) GetUser() string { return hc.getString(CONFIG_USER) } func (hc *HostConfig) GetSSHPort() int { return hc.getInt(CONFIG_SSH_PORT) } func (hc *HostConfig) GetPrivateKeyFile() string { return hc.getString(CONFIG_PRIVATE_CONFIG_FILE) } func (hc *HostConfig) GetForwardAgent() bool { return hc.getBool(CONFIG_FORWARD_AGENT) } func (hc *HostConfig) GetBecomeUser() string { return hc.getString(CONFIG_BECOME_USER) } func (hc *HostConfig) GetLabels() []string { return hc.labels } func (hc *HostConfig) GetEnvs() []string { return hc.envs } + +func (hc *HostConfig) GetUser() string { + user := hc.getString(CONFIG_USER) + if user == "${user}" { + return utils.GetCurrentUser() + } + return user +} + +func (hc *HostConfig) GetProtocol() string { return hc.getString(CONFIG_PROTOCOL) } func (hc *HostConfig) GetSSHConfig() *module.SSHConfig { + + if hc.GetProtocol() != SSH_PROTOCOL { + return nil + } + hostname := hc.GetSSHHostname() if len(hostname) == 0 { hostname = hc.GetHostname() @@ -95,3 +109,17 @@ func (hc *HostConfig) GetSSHConfig() *module.SSHConfig { ConnectRetries: curveadm.GlobalCurveAdmConfig.GetSSHRetries(), } } + +func (hc *HostConfig) GetHttpConfig() *module.HttpConfig { + + if hc.GetProtocol() != HTTP_PROTOCOL { + return nil + } + + return &module.HttpConfig{ + Host: hc.GetHostname(), + Port: (uint)(hc.GetHTTPPort()), + } +} + +func (hc *HostConfig) GetHTTPPort() int { return hc.getInt(CONFIG_HTTP_PORT) } diff --git a/internal/configure/hosts/hc_item.go b/internal/configure/hosts/hc_item.go index 6900cbd63..a7fb50cc8 100644 --- a/internal/configure/hosts/hc_item.go +++ b/internal/configure/hosts/hc_item.go @@ -32,7 +32,10 @@ import ( ) const ( - DEFAULT_SSH_PORT = 22 + DEFAULT_SSH_PORT = 22 + DEFAULT_HTTP_PORT = 8000 + SSH_PROTOCOL = "ssh" + HTTP_PROTOCOL = "http" ) var ( @@ -97,4 +100,18 @@ var ( false, nil, ) + + CONFIG_PROTOCOL = itemset.Insert( + "protocol", + comm.REQUIRE_STRING, + false, + SSH_PROTOCOL, + ) + + CONFIG_HTTP_PORT = itemset.Insert( + "http_port", + comm.REQUIRE_POSITIVE_INTEGER, + false, + DEFAULT_HTTP_PORT, + ) ) diff --git a/internal/configure/monitor.go b/internal/configure/monitor.go new file mode 100644 index 000000000..6d7f34a94 --- /dev/null +++ b/internal/configure/monitor.go @@ -0,0 +1,359 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-17 +* Author: wanghai (SeanHai) + */ + +package configure + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/configure/hosts" + "github.com/opencurve/curveadm/internal/configure/topology" + "github.com/opencurve/curveadm/internal/errno" + "github.com/spf13/viper" +) + +const ( + ROLE_NODE_EXPORTER = "node_exporter" + ROLE_PROMETHEUS = "prometheus" + ROLE_GRAFANA = "grafana" + ROLE_MONITOR_CONF = "monitor_conf" + + KEY_HOST = "host" + KEY_LISTEN_PORT = "listen_port" + KEY_RETENTION_TIME = "retention.time" + KEY_RETENTION_SIZE = "retention.size" + KEY_PROMETHEUS_TARGET = "target" + KEY_GRAFANA_USER = "username" + KEY_GRAFANA_PASSWORD = "password" + + KEY_NODE_IPS = "node_ips" + KRY_NODE_LISTEN_PORT = "node_listen_port" + KEY_PROMETHEUS_IP = "prometheus_listen_ip" + KEY_PROMETHEUS_PORT = "prometheus_listen_port" +) + +type monitor struct { + Host string `mapstructure:"host"` + NodeExporter map[string]interface{} `mapstructure:"node_exporter"` + Prometheus map[string]interface{} `mapstructure:"prometheus"` + Grafana map[string]interface{} `mapstructure:"grafana"` +} + +type MonitorConfig struct { + kind string + id string // role_host + role string + host string + config map[string]interface{} + ctx *topology.Context +} + +type serviceTarget struct { + Targets []string `json:"targets"` + Labels map[string]string `json:"labels"` +} + +type FilterMonitorOption struct { + Id string + Role string + Host string +} + +func (m *MonitorConfig) getString(data *map[string]interface{}, key string) string { + v := (*data)[strings.ToLower(key)] + if v == nil { + return "" + } + return v.(string) +} + +func (m *MonitorConfig) getStrings(data *map[string]interface{}, key string) []string { + v := (*data)[strings.ToLower(key)] + if v == nil { + return []string{} + } + return v.([]string) +} + +func (m *MonitorConfig) getInt(data *map[string]interface{}, key string) int { + v := (*data)[strings.ToLower(key)] + if v == nil { + return -1 + } + return v.(int) +} + +func (m *MonitorConfig) GetKind() string { + return m.kind +} + +func (m *MonitorConfig) GetId() string { + return m.id +} + +func (m *MonitorConfig) GetRole() string { + return m.role +} + +func (m *MonitorConfig) GetHost() string { + return m.host +} + +func (m *MonitorConfig) GetNodeIps() []string { + return m.getStrings(&m.config, KEY_NODE_IPS) +} + +func (m *MonitorConfig) GetNodeListenPort() int { + return m.getInt(&m.config, KRY_NODE_LISTEN_PORT) +} + +func (m *MonitorConfig) GetPrometheusListenPort() int { + return m.getInt(&m.config, KEY_PROMETHEUS_PORT) +} + +func (m *MonitorConfig) GetImage() string { + return m.getString(&m.config, KEY_CONTAINER_IMAGE) +} + +func (m *MonitorConfig) GetListenPort() int { + return m.getInt(&m.config, KEY_LISTEN_PORT) +} + +func (m *MonitorConfig) GetDataDir() string { + return m.getString(&m.config, KEY_DATA_DIR) +} + +func (m *MonitorConfig) GetLogDir() string { + return m.getString(&m.config, KEY_LOG_DIR) +} + +func (m *MonitorConfig) GetPrometheusRetentionTime() string { + return m.getString(&m.config, KEY_RETENTION_TIME) +} + +func (m *MonitorConfig) GetPrometheusRetentionSize() string { + return m.getString(&m.config, KEY_RETENTION_SIZE) +} + +func (m *MonitorConfig) GetPrometheusTarget() string { + return m.getString(&m.config, KEY_PROMETHEUS_TARGET) +} + +func (m *MonitorConfig) GetPrometheusIp() string { + return m.getString(&m.config, KEY_PROMETHEUS_IP) +} + +func (m *MonitorConfig) GetGrafanaUser() string { + return m.getString(&m.config, KEY_GRAFANA_USER) +} + +func (m *MonitorConfig) GetGrafanaPassword() string { + return m.getString(&m.config, KEY_GRAFANA_PASSWORD) +} + +func getHost(c *monitor, role string) string { + h := c.Host + switch role { + case ROLE_NODE_EXPORTER: + if _, ok := c.NodeExporter[KEY_HOST]; ok { + return c.NodeExporter[KEY_HOST].(string) + } + c.NodeExporter[KEY_HOST] = h + case ROLE_PROMETHEUS: + if _, ok := c.Prometheus[KEY_HOST]; ok { + return c.Prometheus[KEY_HOST].(string) + } + c.Prometheus[KEY_HOST] = h + case ROLE_GRAFANA: + if _, ok := c.Grafana[KEY_HOST]; ok { + return c.Grafana[KEY_HOST].(string) + } + c.Grafana[KEY_HOST] = h + } + return h +} + +func parsePrometheusTarget(dcs []*topology.DeployConfig) (string, error) { + targets := []serviceTarget{} + tMap := make(map[string]serviceTarget) + for _, dc := range dcs { + role := dc.GetRole() + ip := dc.GetListenIp() + var item string + switch role { + case topology.ROLE_ETCD: + item = fmt.Sprintf("%s:%d", ip, dc.GetListenClientPort()) + case topology.ROLE_MDS, + topology.ROLE_CHUNKSERVER, + topology.ROLE_METASERVER: + item = fmt.Sprintf("%s:%d", ip, dc.GetListenPort()) + case topology.ROLE_SNAPSHOTCLONE: + item = fmt.Sprintf("%s:%d", ip, dc.GetListenDummyPort()) + } + if _, ok := tMap[role]; ok { + t := tMap[role] + t.Targets = append(t.Targets, item) + tMap[role] = t + } else { + tMap[role] = serviceTarget{ + Labels: map[string]string{"job": role}, + Targets: []string{item}, + } + } + } + for _, v := range tMap { + targets = append(targets, v) + } + target, err := json.Marshal(targets) + if err != nil { + return "", errno.ERR_PARSE_PROMETHEUS_TARGET_FAILED.E(err) + } + return string(target), nil +} + +func ParseMonitorConfig(curveadm *cli.CurveAdm, filename string, data string, hs []string, + hostIps []string, dcs []*topology.DeployConfig) ( + []*MonitorConfig, error) { + parser := viper.NewWithOptions(viper.KeyDelimiter("::")) + parser.SetConfigType("yaml") + if len(data) != 0 && data != common.CLEANED_MONITOR_CONF { + if err := parser.ReadConfig(bytes.NewBuffer([]byte(data))); err != nil { + return nil, errno.ERR_PARSE_MONITOR_CONFIGURE_FAILED.E(err) + } + } else if len(filename) != 0 { + parser.SetConfigFile(filename) + if err := parser.ReadInConfig(); err != nil { + return nil, errno.ERR_PARSE_MONITOR_CONFIGURE_FAILED.E(err) + } + } else { + return nil, errno.ERR_PARSE_MONITOR_CONFIGURE_FAILED + } + + config := monitor{} + if err := parser.Unmarshal(&config); err != nil { + return nil, errno.ERR_PARSE_MONITOR_CONFIGURE_FAILED.E(err) + } + + // get host -> hostname(ip) + ctx := topology.NewContext() + hcs, err := hosts.ParseHosts(curveadm.Hosts()) + if err != nil { + return nil, err + } + for _, hc := range hcs { + ctx.Add(hc.GetHost(), hc.GetHostname()) + } + + mkind := dcs[0].GetKind() + mconfImage := dcs[0].GetContainerImage() + roles := []string{} + switch { + case config.NodeExporter != nil: + roles = append(roles, ROLE_NODE_EXPORTER) + fallthrough + case config.Prometheus != nil: + roles = append(roles, ROLE_PROMETHEUS) + fallthrough + case config.Grafana != nil: + roles = append(roles, ROLE_GRAFANA) + } + ret := []*MonitorConfig{} + for _, role := range roles { + host := getHost(&config, role) + switch role { + case ROLE_PROMETHEUS: + target, err := parsePrometheusTarget(dcs) + if err != nil { + return nil, err + } + if config.NodeExporter != nil { + config.Prometheus[KEY_NODE_IPS] = hostIps + config.Prometheus[KRY_NODE_LISTEN_PORT] = config.NodeExporter[KEY_LISTEN_PORT] + } + config.Prometheus[KEY_PROMETHEUS_TARGET] = target + ret = append(ret, &MonitorConfig{ + kind: mkind, + id: fmt.Sprintf("%s_%s", role, host), + role: role, + host: host, + config: config.Prometheus, + ctx: ctx, + }) + case ROLE_GRAFANA: + if config.Prometheus != nil { + config.Grafana[KEY_PROMETHEUS_PORT] = config.Prometheus[KEY_LISTEN_PORT] + config.Grafana[KEY_PROMETHEUS_IP] = ctx.Lookup(config.Prometheus[KEY_HOST].(string)) + } + ret = append(ret, &MonitorConfig{ + kind: mkind, + id: fmt.Sprintf("%s_%s", role, host), + role: role, + host: host, + config: config.Grafana, + ctx: ctx, + }, &MonitorConfig{ + kind: mkind, + id: fmt.Sprintf("%s_%s", ROLE_MONITOR_CONF, host), + role: ROLE_MONITOR_CONF, + host: host, + config: map[string]interface{}{ + KEY_CONTAINER_IMAGE: mconfImage, + }, + ctx: ctx, + }) + case ROLE_NODE_EXPORTER: + for _, h := range hs { + ret = append(ret, &MonitorConfig{ + kind: mkind, + id: fmt.Sprintf("%s_%s", role, h), + role: role, + host: h, + config: config.NodeExporter, + ctx: ctx, + }) + } + } + } + return ret, nil +} + +func FilterMonitorConfig(curveadm *cli.CurveAdm, mcs []*MonitorConfig, + options FilterMonitorOption) []*MonitorConfig { + ret := []*MonitorConfig{} + for _, mc := range mcs { + mcId := mc.GetId() + role := mc.GetRole() + host := mc.GetHost() + serviceId := curveadm.GetServiceId(mcId) + if (options.Id == "*" || options.Id == serviceId) && + (options.Role == "*" || options.Role == role) && + (options.Host == "*" || options.Host == host) { + ret = append(ret, mc) + } + } + return ret +} diff --git a/internal/configure/pool.go b/internal/configure/pool.go index 128204edb..b38274ba8 100644 --- a/internal/configure/pool.go +++ b/internal/configure/pool.go @@ -47,6 +47,11 @@ type ( To *topology.DeployConfig } + Poolset struct { + Name string `json:"name"` + Type string `json:"type"` + } + LogicalPool struct { Name string `json:"name"` Replicas int `json:"replicasnum"` @@ -66,10 +71,12 @@ type ( Zone string `json:"zone"` PhysicalPool string `json:"physicalpool,omitempty"` // curvebs Pool string `json:"pool,omitempty"` // curvefs + Poolset string `json:"poolset,omitempty"` // curvebs } CurveClusterTopo struct { Servers []Server `json:"servers"` + Poolsets []Poolset `json:"poolsets"` // curvebs LogicalPools []LogicalPool `json:"logicalpools,omitempty"` // curvebs Pools []LogicalPool `json:"pools,omitempty"` // curvefs NPools int `json:"npools"` @@ -86,15 +93,19 @@ type ( * externalport: 16701 * zone: zone1 * physicalpool: pool1 + * poolset: ssd_poolset1 * ... * logicalpools: * - name: pool1 * physicalpool: pool1 - * replicasnum: 3 + * replicassum: 3 * copysetnum: 100 * zonenum: 3 * type: 0 * scatterwidth: 0 + * poolsets: + * - name: ssd_poolset1 + * type: ssd * ... * * @@ -110,7 +121,7 @@ type ( * ... * pools: * - name: pool1 - * replicasnum: 3 + * replicasum: 3 * copysetnum: 100 * zonenum: 3 */ @@ -128,7 +139,7 @@ func SortDeployConfigs(dcs []*topology.DeployConfig) { dc1, dc2 := dcs[i], dcs[j] if dc1.GetRole() == dc2.GetRole() { if dc1.GetHostSequence() == dc2.GetHostSequence() { - return dc1.GetReplicasSequence() < dc2.GetReplicasSequence() + return dc1.GetInstancesSequence() < dc2.GetInstancesSequence() } return dc1.GetHostSequence() < dc2.GetHostSequence() } @@ -137,10 +148,10 @@ func SortDeployConfigs(dcs []*topology.DeployConfig) { } func formatName(dc *topology.DeployConfig) string { - return fmt.Sprintf("%s_%s_%d", dc.GetHost(), dc.GetName(), dc.GetReplicasSequence()) + return fmt.Sprintf("%s_%s_%d", dc.GetHost(), dc.GetName(), dc.GetInstancesSequence()) } -func createLogicalPool(dcs []*topology.DeployConfig, logicalPool string) (LogicalPool, []Server) { +func createLogicalPool(dcs []*topology.DeployConfig, logicalPool, poolset string) (LogicalPool, []Server) { var zone string copysets := 0 servers := []Server{} @@ -157,14 +168,14 @@ func createLogicalPool(dcs []*topology.DeployConfig, logicalPool string) (Logica zone = nextZone() } - // NOTE: if we deploy chunkservers with replica feature - // and the value of replica greater than 1, we should + // NOTE: if we deploy chunkservers with instance feature + // and the value of instance greater than 1, we should // set internal port and external port to 0 for let MDS // attribute them as services on the same machine. // see issue: https://github.com/opencurve/curve/issues/1441 internalPort := dc.GetListenPort() externalPort := dc.GetListenExternalPort() - if dc.GetReplicas() > 1 { + if dc.GetInstances() > 1 { internalPort = 0 externalPort = 0 } @@ -179,6 +190,7 @@ func createLogicalPool(dcs []*topology.DeployConfig, logicalPool string) (Logica } if kind == KIND_CURVEBS { server.PhysicalPool = physicalPool + server.Poolset = poolset } else { server.Pool = logicalPool } @@ -209,24 +221,37 @@ func createLogicalPool(dcs []*topology.DeployConfig, logicalPool string) (Logica return lpool, servers } -func generateClusterPool(dcs []*topology.DeployConfig, poolName string) CurveClusterTopo { - lpool, servers := createLogicalPool(dcs, poolName) +func generateClusterPool(dcs []*topology.DeployConfig, poolName string, poolset Poolset) CurveClusterTopo { + lpool, servers := createLogicalPool(dcs, poolName, poolset.Name) topo := CurveClusterTopo{Servers: servers, NPools: 1} if dcs[0].GetKind() == KIND_CURVEBS { topo.LogicalPools = []LogicalPool{lpool} + topo.Poolsets = []Poolset{poolset} } else { topo.Pools = []LogicalPool{lpool} } return topo } -func ScaleOutClusterPool(old *CurveClusterTopo, dcs []*topology.DeployConfig) { +func ScaleOutClusterPool(old *CurveClusterTopo, dcs []*topology.DeployConfig, poolset Poolset) { npools := old.NPools - topo := generateClusterPool(dcs, fmt.Sprintf("pool%d", npools+1)) + topo := generateClusterPool(dcs, fmt.Sprintf("pool%d", npools+1), poolset) if dcs[0].GetKind() == KIND_CURVEBS { + // logical pools for _, pool := range topo.LogicalPools { old.LogicalPools = append(old.LogicalPools, pool) } + + // poolsets + m := map[string]bool{} + for _, poolset := range old.Poolsets { + m[poolset.Name] = true + } + for _, poolset := range topo.Poolsets { + if !m[poolset.Name] { + old.Poolsets = append(old.Poolsets, poolset) + } + } } else { for _, pool := range topo.Pools { old.Pools = append(old.Pools, pool) @@ -261,7 +286,7 @@ func MigrateClusterServer(old *CurveClusterTopo, migrates []*MigrateServer) { } } -func GenerateDefaultClusterPool(dcs []*topology.DeployConfig) (topo CurveClusterTopo, err error) { - topo = generateClusterPool(dcs, "pool1") +func GenerateDefaultClusterPool(dcs []*topology.DeployConfig, poolset Poolset) (topo CurveClusterTopo, err error) { + topo = generateClusterPool(dcs, "pool1", poolset) return } diff --git a/internal/configure/topology/dc.go b/internal/configure/topology/dc.go index a39112ff0..b57ed770f 100644 --- a/internal/configure/topology/dc.go +++ b/internal/configure/topology/dc.go @@ -48,16 +48,16 @@ const ( type ( DeployConfig struct { - kind string // KIND_CURVEFS / KIND_CUVREBS - id string // role_host_[name/hostSequence]_replicasSequence - parentId string // role_host_[name/hostSequence]_0 - role string // etcd/mds/metaserevr/chunkserver - host string - hostname string - name string - replicas int - hostSequence int // start with 0 - replicasSequence int // start with 0 + kind string // KIND_CURVEFS / KIND_CUVREBS + id string // role_host_[name/hostSequence]_instancesSequence + parentId string // role_host_[name/hostSequence]_0 + role string // etcd/mds/metaserevr/chunkserver + host string + hostname string + name string + instances int + hostSequence int // start with 0 + instancesSequence int // start with 0 config map[string]interface{} serviceConfig map[string]string @@ -73,8 +73,8 @@ type ( ) // etcd_hostname_0_0 -func formatId(role, host, name string, replicasSequence int) string { - return fmt.Sprintf("%s_%s_%s_%d", role, host, name, replicasSequence) +func formatId(role, host, name string, instancesSequence int) string { + return fmt.Sprintf("%s_%s_%s_%d", role, host, name, instancesSequence) } func formatName(name string, hostSequence int) string { @@ -104,8 +104,8 @@ func newVariables(m map[string]interface{}) (*variable.Variables, error) { return vars, nil } -func NewDeployConfig(ctx *Context, kind, role, host, name string, replicas int, - hostSequence, replicasSequence int, config map[string]interface{}) (*DeployConfig, error) { +func NewDeployConfig(ctx *Context, kind, role, host, name string, instances int, + hostSequence, instancesSequence int, config map[string]interface{}) (*DeployConfig, error) { // variable section v := config[CONFIG_VARIABLE.key] if !utils.IsStringAnyMap(v) && v != nil { @@ -137,19 +137,19 @@ func NewDeployConfig(ctx *Context, kind, role, host, name string, replicas int, name = formatName(name, hostSequence) return &DeployConfig{ - kind: kind, - id: formatId(role, host, name, replicasSequence), - parentId: formatId(role, host, name, 0), - role: role, - host: host, - name: name, - replicas: replicas, - hostSequence: hostSequence, - replicasSequence: replicasSequence, - config: config, - serviceConfig: map[string]string{}, - variables: vars, - ctx: ctx, + kind: kind, + id: formatId(role, host, name, instancesSequence), + parentId: formatId(role, host, name, 0), + role: role, + host: host, + name: name, + instances: instances, + hostSequence: hostSequence, + instancesSequence: instancesSequence, + config: config, + serviceConfig: map[string]string{}, + variables: vars, + ctx: ctx, }, nil } diff --git a/internal/configure/topology/dc_get.go b/internal/configure/topology/dc_get.go index 85e9b6b3f..ee8e7c2b1 100644 --- a/internal/configure/topology/dc_get.go +++ b/internal/configure/topology/dc_get.go @@ -34,25 +34,28 @@ import ( const ( // service project layout - LAYOUT_CURVEFS_ROOT_DIR = "/curvefs" - LAYOUT_CURVEBS_ROOT_DIR = "/curvebs" - LAYOUT_PLAYGROUND_ROOT_DIR = "playground" - LAYOUT_CONF_SRC_DIR = "/conf" - LAYOUT_SERVICE_BIN_DIR = "/sbin" - LAYOUT_SERVICE_CONF_DIR = "/conf" - LAYOUT_SERVICE_LOG_DIR = "/logs" - LAYOUT_SERVICE_DATA_DIR = "/data" - LAYOUT_TOOLS_DIR = "/tools" - LAYOUT_CURVEBS_CHUNKFILE_POOL_DIR = "chunkfilepool" - LAYOUT_CURVEBS_COPYSETS_DIR = "copysets" - LAYOUT_CURVEBS_RECYCLER_DIR = "recycler" - LAYOUT_CURVEBS_TOOLS_CONFIG_SYSTEM_PATH = "/etc/curve/tools.conf" - LAYOUT_CURVEFS_TOOLS_CONFIG_SYSTEM_PATH = "/etc/curvefs/tools.conf" - LAYOUT_CORE_SYSTEM_DIR = "/core" + LAYOUT_CURVEFS_ROOT_DIR = "/curvefs" + LAYOUT_CURVEBS_ROOT_DIR = "/curvebs" + LAYOUT_PLAYGROUND_ROOT_DIR = "playground" + LAYOUT_CONF_SRC_DIR = "/conf" + LAYOUT_SERVICE_BIN_DIR = "/sbin" + LAYOUT_SERVICE_CONF_DIR = "/conf" + LAYOUT_SERVICE_LOG_DIR = "/logs" + LAYOUT_SERVICE_DATA_DIR = "/data" + LAYOUT_TOOLS_DIR = "/tools" + LAYOUT_TOOLS_V2_DIR = "/tools-v2" + LAYOUT_CURVEBS_CHUNKFILE_POOL_DIR = "chunkfilepool" + LAYOUT_CURVEBS_COPYSETS_DIR = "copysets" + LAYOUT_CURVEBS_RECYCLER_DIR = "recycler" + LAYOUT_CURVEBS_TOOLS_CONFIG_SYSTEM_PATH = "/etc/curve/tools.conf" + LAYOUT_CURVEFS_TOOLS_CONFIG_SYSTEM_PATH = "/etc/curvefs/tools.conf" + LAYOUT_CURVE_TOOLS_V2_CONFIG_SYSTEM_PATH = "/etc/curve/curve.yaml" + LAYOUT_CORE_SYSTEM_DIR = "/core" BINARY_CURVEBS_TOOL = "curvebs-tool" BINARY_CURVEBS_FORMAT = "curve_format" BINARY_CURVEFS_TOOL = "curvefs_tool" + BINARY_CURVE_TOOL_V2 = "curve" METAFILE_CHUNKFILE_POOL = "chunkfilepool.meta" METAFILE_CHUNKSERVER_ID = "chunkserver.dat" ) @@ -114,9 +117,9 @@ func (dc *DeployConfig) GetRole() string { return dc.role } func (dc *DeployConfig) GetHost() string { return dc.host } func (dc *DeployConfig) GetHostname() string { return dc.hostname } func (dc *DeployConfig) GetName() string { return dc.name } -func (dc *DeployConfig) GetReplicas() int { return dc.replicas } +func (dc *DeployConfig) GetInstances() int { return dc.instances } func (dc *DeployConfig) GetHostSequence() int { return dc.hostSequence } -func (dc *DeployConfig) GetReplicasSequence() int { return dc.replicasSequence } +func (dc *DeployConfig) GetInstancesSequence() int { return dc.instancesSequence } func (dc *DeployConfig) GetServiceConfig() map[string]string { return dc.serviceConfig } func (dc *DeployConfig) GetVariables() *variable.Variables { return dc.variables } @@ -140,6 +143,9 @@ func (dc *DeployConfig) GetS3Address() string { return dc.getString(CONFI func (dc *DeployConfig) GetS3BucketName() string { return dc.getString(CONFIG_S3_BUCKET_NAME) } func (dc *DeployConfig) GetEnableRDMA() bool { return dc.getBool(CONFIG_ENABLE_RDMA) } func (dc *DeployConfig) GetEnableRenameAt2() bool { return dc.getBool(CONFIG_ENABLE_RENAMEAT2) } +func (dc *DeployConfig) GetEtcdAuthEnable() bool { return dc.getBool(CONFIG_ETCD_AUTH_ENABLE) } +func (dc *DeployConfig) GetEtcdAuthUsername() string { return dc.getString(CONFIG_ETCD_AUTH_USERNAME) } +func (dc *DeployConfig) GetEtcdAuthPassword() string { return dc.getString(CONFIG_ETCD_AUTH_PASSWORD) } func (dc *DeployConfig) GetEnableChunkfilePool() bool { return dc.getBool(CONFIG_ENABLE_CHUNKFILE_POOL) } @@ -221,6 +227,11 @@ type ( ToolsConfSystemPath string // /etc/curve/tools.conf ToolsBinaryPath string // /curvebs/tools/sbin/curvebs-tool + // tools-v2 + ToolsV2ConfSrcPath string // /curvebs/conf/curve.yaml + ToolsV2ConfSystemPath string // /etc/curve/curve.yaml + ToolsV2BinaryPath string // /curvebs/tools-v2/sbin/curve + // format FormatBinaryPath string // /curvebs/tools/sbin/curve_format ChunkfilePoolRootDir string // /curvebs/chunkserver/data @@ -260,6 +271,12 @@ func (dc *DeployConfig) GetProjectLayout() Layout { LAYOUT_CURVEBS_TOOLS_CONFIG_SYSTEM_PATH, LAYOUT_CURVEFS_TOOLS_CONFIG_SYSTEM_PATH) + // tools-v2 + toolsV2RootDir := root + LAYOUT_TOOLS_V2_DIR + toolsV2BinDir := toolsV2RootDir + LAYOUT_SERVICE_BIN_DIR + toolsV2BinaryName := BINARY_CURVE_TOOL_V2 + toolsV2ConfSystemPath := LAYOUT_CURVE_TOOLS_V2_CONFIG_SYSTEM_PATH + // format chunkserverDataDir := fmt.Sprintf("%s/%s%s", root, ROLE_CHUNKSERVER, LAYOUT_SERVICE_DATA_DIR) @@ -290,6 +307,11 @@ func (dc *DeployConfig) GetProjectLayout() Layout { ToolsConfSystemPath: toolsConfSystemPath, ToolsBinaryPath: fmt.Sprintf("%s/%s", toolsBinDir, toolsBinaryName), + // toolsv2 + ToolsV2ConfSrcPath: fmt.Sprintf("%s/curve.yaml", confSrcDir), + ToolsV2ConfSystemPath: toolsV2ConfSystemPath, + ToolsV2BinaryPath: fmt.Sprintf("%s/%s", toolsV2BinDir, toolsV2BinaryName), + // format FormatBinaryPath: fmt.Sprintf("%s/%s", toolsBinDir, BINARY_CURVEBS_FORMAT), ChunkfilePoolRootDir: chunkserverDataDir, diff --git a/internal/configure/topology/dc_item.go b/internal/configure/topology/dc_item.go index d24856d14..24f23e972 100644 --- a/internal/configure/topology/dc_item.go +++ b/internal/configure/topology/dc_item.go @@ -283,6 +283,27 @@ var ( true, nil, ) + + CONFIG_ETCD_AUTH_ENABLE = itemset.insert( + "etcd.auth.enable", + REQUIRE_BOOL, + false, + false, + ) + + CONFIG_ETCD_AUTH_USERNAME = itemset.insert( + "etcd.auth.username", + REQUIRE_STRING, + false, + nil, + ) + + CONFIG_ETCD_AUTH_PASSWORD = itemset.insert( + "etcd.auth.password", + REQUIRE_STRING, + false, + nil, + ) ) func (i *item) Key() string { diff --git a/internal/configure/topology/topology.go b/internal/configure/topology/topology.go index 1f20fc01b..f3dc9da7a 100644 --- a/internal/configure/topology/topology.go +++ b/internal/configure/topology/topology.go @@ -32,18 +32,14 @@ import ( "github.com/spf13/viper" ) -var ( - CURVEBS_ROLES = []string{ROLE_ETCD, ROLE_MDS, ROLE_CHUNKSERVER, ROLE_SNAPSHOTCLONE} - CURVEFS_ROLES = []string{ROLE_ETCD, ROLE_MDS, ROLE_METASERVER} -) - type ( Deploy struct { - Host string `mapstructure:"host"` - Name string `mapstructure:"name"` - Replica int `mapstructure:"replica"` // old version - Replicas int `mapstructure:"replicas"` - Config map[string]interface{} `mapstructure:"config"` + Host string `mapstructure:"host"` + Name string `mapstructure:"name"` + Replica int `mapstructure:"replica"` // old version + Replicas int `mapstructure:"replicas"` // old version + Instances int `mapstructure:"instances"` + Config map[string]interface{} `mapstructure:"config"` } Service struct { @@ -64,6 +60,20 @@ type ( } ) +var ( + CURVEBS_ROLES = []string{ + ROLE_ETCD, + ROLE_MDS, + ROLE_CHUNKSERVER, + ROLE_SNAPSHOTCLONE, + } + CURVEFS_ROLES = []string{ + ROLE_ETCD, + ROLE_MDS, + ROLE_METASERVER, + } +) + func merge(parent, child map[string]interface{}, deep int) { for k, v := range parent { if child[k] == nil { @@ -140,23 +150,28 @@ func ParseTopology(data string, ctx *Context) ([]*DeployConfig, error) { merge(servicesConfig, deployConfig, 1) // create deploy config - replicas := 1 + instances := 1 if deploy.Replicas < 0 { - return nil, errno.ERR_REPLICAS_REQUIRES_POSITIVE_INTEGER. + return nil, errno.ERR_INSTANCES_REQUIRES_POSITIVE_INTEGER. F("replicas: %d", deploy.Replicas) } else if deploy.Replica < 0 { - return nil, errno.ERR_REPLICAS_REQUIRES_POSITIVE_INTEGER. + return nil, errno.ERR_INSTANCES_REQUIRES_POSITIVE_INTEGER. F("replica: %d", deploy.Replica) + } else if deploy.Instances < 0 { + return nil, errno.ERR_INSTANCES_REQUIRES_POSITIVE_INTEGER. + F("Instance: %d", deploy.Instances) + } else if deploy.Instances > 0 { + instances = deploy.Instances } else if deploy.Replicas > 0 { - replicas = deploy.Replicas + instances = deploy.Replicas } else if deploy.Replica > 0 { - replicas = deploy.Replica + instances = deploy.Replica } - for replicasSequence := 0; replicasSequence < replicas; replicasSequence++ { + for instancesSequence := 0; instancesSequence < instances; instancesSequence++ { dc, err := NewDeployConfig(ctx, kind, - role, deploy.Host, deploy.Name, replicas, - hostSequence, replicasSequence, utils.DeepCopy(deployConfig)) + role, deploy.Host, deploy.Name, instances, + hostSequence, instancesSequence, utils.DeepCopy(deployConfig)) if err != nil { return nil, err // already is error code } diff --git a/internal/configure/topology/variables.go b/internal/configure/topology/variables.go index 1ed01f270..02cb4bb65 100644 --- a/internal/configure/topology/variables.go +++ b/internal/configure/topology/variables.go @@ -59,8 +59,8 @@ type Var struct { * ${service_role} "mds" * ${service_host} "10.0.0.1" * ${service_host_sequence} "1" - * ${service_replicas_sequence} "1" - * ${format_replicas_sequence} "01" + * ${service_instances_sequence} "1" + * ${format_instances_sequence} "01" * ${service_addr} "10.0.0.1" * ${service_port} "6666" * ${service_client_port} "2379" (etcd) @@ -94,8 +94,10 @@ var ( {name: "service_host_sequence"}, {name: "service_replica_sequence"}, {name: "service_replicas_sequence"}, + {name: "service_instances_sequence"}, {name: "format_replica_sequence"}, {name: "format_replicas_sequence"}, + {name: "format_instances_sequence"}, {name: "service_addr", lookup: true}, {name: "service_port"}, {name: "service_client_port", role: []string{ROLE_ETCD}}, @@ -174,10 +176,10 @@ func joinEtcdPeer(dcs []*DeployConfig) string { } hostSequence := dc.GetHostSequence() - replicaSquence := dc.GetReplicasSequence() + instanceSquence := dc.GetInstancesSequence() peerHost := dc.GetListenIp() peerPort := dc.GetListenPort() - peer := fmt.Sprintf("etcd%d%d=http://%s:%d", hostSequence, replicaSquence, peerHost, peerPort) + peer := fmt.Sprintf("etcd%d%d=http://%s:%d", hostSequence, instanceSquence, peerHost, peerPort) peers = append(peers, peer) } return strings.Join(peers, ",") @@ -245,13 +247,17 @@ func getValue(name string, dcs []*DeployConfig, idx int) string { case "service_host_sequence": return strconv.Itoa(dc.GetHostSequence()) case "service_replica_sequence": - return strconv.Itoa(dc.GetReplicasSequence()) + return strconv.Itoa(dc.GetInstancesSequence()) case "service_replicas_sequence": - return strconv.Itoa(dc.GetReplicasSequence()) + return strconv.Itoa(dc.GetInstancesSequence()) + case "service_instances_sequence": + return strconv.Itoa(dc.GetInstancesSequence()) case "format_replica_sequence": - return fmt.Sprintf("%02d", dc.GetReplicasSequence()) + return fmt.Sprintf("%02d", dc.GetInstancesSequence()) case "format_replicas_sequence": - return fmt.Sprintf("%02d", dc.GetReplicasSequence()) + return fmt.Sprintf("%02d", dc.GetInstancesSequence()) + case "format_instances_sequence": + return fmt.Sprintf("%02d", dc.GetInstancesSequence()) case "service_addr": return utils.Atoa(dc.get(CONFIG_LISTEN_IP)) case "service_port": diff --git a/internal/errno/errno.go b/internal/errno/errno.go index b6a281f71..e96daf3c3 100644 --- a/internal/errno/errno.go +++ b/internal/errno/errno.go @@ -107,6 +107,15 @@ func (e *ErrorCode) F(format string, a ...interface{}) *ErrorCode { return e } +func (e *ErrorCode) FD(format string, s ...interface{}) *ErrorCode { + newEC := &ErrorCode{ + code: e.code, + description: e.description, + } + newEC.description = fmt.Sprintf(newEC.description+" "+format, s...) + return newEC +} + func (e *ErrorCode) Error() string { if e.code == CODE_CANCEL_OPERATION { return "" @@ -114,6 +123,14 @@ func (e *ErrorCode) Error() string { return tui.PromptErrorCode(e.code, e.description, e.clue, gLogpath) } +func (e *ErrorCode) IsHttpErr() bool { + return e.code/10000 == 70 +} + +func (e *ErrorCode) HttpCode() int { + return e.code % 1000 +} + /* * 0xx: init curveadm * @@ -126,6 +143,7 @@ func (e *ErrorCode) Error() string { * * 113: clients table * * 114: plauground table * * 115: audit table + * * 116: any table * * 2xx: command options * 20*: hosts @@ -215,6 +233,7 @@ var ( ERR_GET_CLIENT_BY_ID_FAILED = EC(113002, "execute SQL failed which get client by id") ERR_GET_ALL_CLIENTS_FAILED = EC(113003, "execute SQL failed which get all clients") ERR_DELETE_CLIENT_FAILED = EC(113004, "execute SQL failed which delete client") + ERR_SET_CLIENT_AUX_INFO_FAILED = EC(113005, "execute SQL failed which set client aux info") // 114: database/SQL (execute SQL statement: playground table) ERR_INSERT_PLAYGROUND_FAILED = EC(114000, "execute SQL failed which insert playground") ERR_GET_ALL_PLAYGROUND_FAILED = EC(114001, "execute SQL failed which get all playgrounds") @@ -222,6 +241,14 @@ var ( ERR_DELETE_PLAYGROUND_FAILED = EC(114003, "execute SQL failed which delete playground") // 115: database/SQL (execute SQL statement: audit table) ERR_GET_AUDIT_LOGS_FAILE = EC(115000, "execute SQL failed which get audit logs") + // 116: database/SQL (execute SQL statement: any table) + ERR_INSERT_CLIENT_CONFIG_FAILED = EC(116000, "execute SQL failed which insert client config") + ERR_SELECT_CLIENT_CONFIG_FAILED = EC(116001, "execute SQL failed which select client config") + ERR_DELETE_CLIENT_CONFIG_FAILED = EC(116002, "execute SQL failed which delete client config") + // 117: database/SQL (execute SQL statement: monitor table) + ERR_GET_MONITOR_FAILED = EC(117000, "execute SQL failed while get monitor") + ERR_REPLACE_MONITOR_FAILED = EC(117001, "execute SQL failed while replace monitor") + ERR_UPDATE_MONITOR_FAILED = EC(117002, "execute SQL failed while update monitor") // 200: command options (hosts) @@ -233,6 +260,8 @@ var ( ERR_UNSUPPORT_SKIPPED_CHECK_ITEM = EC(210004, "unsupport skipped check item") ERR_UNSUPPORT_CLEAN_ITEM = EC(210005, "unsupport clean item") ERR_NO_SERVICES_MATCHED = EC(210006, "no services matched") + // TODO: please check pool set disk type + ERR_INVALID_DISK_TYPE = EC(210007, "poolset disk type must be lowercase and can only be one of ssd, hdd and nvme") // 220: commad options (client common) ERR_UNSUPPORT_CLIENT_KIND = EC(220000, "unsupport client kind") @@ -274,6 +303,7 @@ var ( // 311: configure (curveadm.cfg: invalid configure value) ERR_UNSUPPORT_CURVEADM_LOG_LEVEL = EC(311000, "unsupport curveadm log level") ERR_UNSUPPORT_CURVEADM_CONFIGURE_ITEM = EC(311001, "unsupport curveadm configure item") + ERR_UNSUPPORT_CURVEADM_DATABASE_URL = EC(311002, "unsupport curveadm database url") // 320: configure (hosts.yaml: parse failed) ERR_HOSTS_FILE_NOT_FOUND = EC(320000, "hosts file not found") @@ -291,6 +321,13 @@ var ( ERR_DUPLICATE_HOST = EC(321007, "host is duplicate") ERR_HOSTNAME_REQUIRES_VALID_IP_ADDRESS = EC(321008, "hostname requires valid IP address") + // 322: configure (monitor.yaml: parse failed) + ERR_PARSE_MONITOR_CONFIGURE_FAILED = EC(322000, "parse monitor configure failed") + ERR_READ_MONITOR_FILE_FAILED = EC(322001, "read monitor file failed") + ERR_PARSE_PROMETHEUS_TARGET_FAILED = EC(322002, "parse prometheus targets failed") + ERR_PARSE_CURVE_MANAGER_CONF_FAILED = EC(322003, "parse curve-manager configure failed") + ERR_UPDATE_CURVE_MANAGER_CONF_FAILED = EC(322004, "update curve-manager configure failed") + // 330: configure (topology.yaml: parse failed) ERR_TOPOLOGY_FILE_NOT_FOUND = EC(330000, "topology file not found") ERR_READ_TOPOLOGY_FILE_FAILED = EC(330001, "read topology file failed") @@ -302,11 +339,11 @@ var ( ERR_RENDERING_VARIABLE_FAILED = EC(330007, "rendering variable failed") ERR_CREATE_HASH_FOR_TOPOLOGY_FAILED = EC(330008, "create hash for topology failed") // 331: configure (topology.yaml: invalid configure value) - ERR_UNSUPPORT_CLUSTER_KIND = EC(331000, "unsupport cluster kind") - ERR_NO_SERVICES_IN_TOPOLOGY = EC(331001, "no services in topology") - ERR_REPLICAS_REQUIRES_POSITIVE_INTEGER = EC(331002, "replicas requires a positive integer") - ERR_INVALID_VARIABLE_SECTION = EC(331003, "invalid variable section") - ERR_DUPLICATE_SERVICE_ID = EC(331004, "service id is duplicate") + ERR_UNSUPPORT_CLUSTER_KIND = EC(331000, "unsupport cluster kind") + ERR_NO_SERVICES_IN_TOPOLOGY = EC(331001, "no services in topology") + ERR_INSTANCES_REQUIRES_POSITIVE_INTEGER = EC(331002, "instances requires a positive integer") + ERR_INVALID_VARIABLE_SECTION = EC(331003, "invalid variable section") + ERR_DUPLICATE_SERVICE_ID = EC(331004, "service id is duplicate") // 332: configure (topology.yaml: update topology) ERR_DELETE_SERVICE_WHILE_COMMIT_TOPOLOGY_IS_DENIED = EC(332000, "delete service while commit topology is denied") ERR_ADD_SERVICE_WHILE_COMMIT_TOPOLOGY_IS_DENIED = EC(332001, "add service while commit topology is denied") @@ -330,6 +367,7 @@ var ( ERR_MOUNT_POINT_REQUIRE_ABSOLUTE_PATH = EC(341002, "mount point must be an absolute path") ERR_FORMAT_PERCENT_REQUIRES_INTERGET = EC(341003, "format percentage requires an integer") ERR_FORMAT_PERCENT_MUST_BE_BETWEEN_1_AND_100 = EC(341004, "format percentage must be between 1 and 100") + ERR_INVALID_BLOCK_SIZE = EC(341005, "invalid block size, support 512,4096") // 350: configure (client.yaml: parse failed) ERR_PARSE_CLIENT_CONFIGURE_FAILED = EC(350000, "parse client configure failed") @@ -367,6 +405,7 @@ var ( ERR_INVALID_DEVICE_USAGE = EC(410020, "invalid device usage") ERR_ENCRYPT_FILE_FAILED = EC(410021, "encrypt file failed") ERR_CLIENT_ID_NOT_FOUND = EC(410022, "client id not found") + ERR_ENABLE_ETCD_AUTH_FAILED = EC(410023, "enable etcd auth failed") // 420: common (curvebs client) ERR_VOLUME_ALREADY_MAPPED = EC(420000, "volume already mapped") @@ -416,13 +455,14 @@ var ( ERR_METASERVER_REQUIRES_3_HOSTS = EC(503009, "metaserver requires at least 3 hosts to distrubute zones") // 510: checker (ssh) - ERR_SSH_CONNECT_FAILED = EC(510000, "SSH connect failed") + ERR_SSH_CONNECT_FAILED = EC(510000, "SSH connect failed") + ERR_HTTP_CONNECT_FAILED = EC(510001, "HTTP connect failed") // 520: checker (permission) - ERR_USER_NOT_FOUND = EC(520000, "user not found") - ERR_HOSTNAME_NOT_RESOLVED = EC(520001, "hostname not resolved") - ERR_CREATE_DIRECOTRY_PERMISSION_DENIED = EC(520002, "create direcotry permission denied") - ERR_EXECUTE_DOCKER_COMMAND_PERMISSION_DENIED = EC(520003, "execute docker command permission denied") + ERR_USER_NOT_FOUND = EC(520000, "user not found") + ERR_HOSTNAME_NOT_RESOLVED = EC(520001, "hostname not resolved") + ERR_CREATE_DIRECOTRY_PERMISSION_DENIED = EC(520002, "create direcotry permission denied") + ERR_EXECUTE_CONTAINER_ENGINE_COMMAND_PERMISSION_DENIED = EC(520003, "execute docker/podman command permission denied") // 530: checker (kernel) ERR_UNRECOGNIZED_KERNEL_VERSION = EC(530000, "unrecognized kernel version") @@ -449,9 +489,9 @@ var ( ERR_INVALID_CURVEFS_CLIENT_S3_BUCKET_NAME = EC(570003, "invalid curvefs client S3 bucket name") // 590: checker (others) - ERR_DOCKER_NOT_INSTALLED = EC(590000, "docker not installed") - ERR_DOCKER_DAEMON_IS_NOT_RUNNING = EC(590001, "docker daemon is not running") - ERR_NO_SPACE_LEFT_ON_DEVICE = EC(590002, "no space left on device") + ERR_CONTAINER_ENGINE_NOT_INSTALLED = EC(590000, "container engine docker/podman not installed") + ERR_DOCKER_DAEMON_IS_NOT_RUNNING = EC(590001, "docker daemon is not running") + ERR_NO_SPACE_LEFT_ON_DEVICE = EC(590002, "no space left on device") // 600: exeute task (common) ERR_EXECUTE_COMMAND_TIMED_OUT = EC(600000, "execute command timed out") @@ -493,28 +533,38 @@ var ( ERR_INSTALL_OR_REMOVE_DEBIAN_PACKAGE_FAILED = EC(620024, "install or remove debian package failed (dpkg)") ERR_INSTALL_OR_REMOVE_RPM_PACKAGE_FAILED = EC(620025, "install or remove rpm package failed (rpm)") ERR_SECURE_COPY_FILE_TO_REMOTE_FAILED = EC(620026, "secure copy file to remote failed (scp)") + ERR_GET_BLOCK_DEVICE_UUID_FAILED = EC(620027, "get block device uuid failed (blkid)") + ERR_RESERVE_FILESYSTEM_BLOCKS_FAILED = EC(620028, "reserve filesystem blocks (tune2fs)") ERR_RUN_SCRIPT_FAILED = EC(620998, "run script failed (bash script.sh)") ERR_RUN_A_BASH_COMMAND_FAILED = EC(620999, "run a bash command failed (bash -c)") - // 630: execute task (docker command) - ERR_GET_DOCKER_INFO_FAILED = EC(630000, "get docker info failed (docker info)") - ERR_PULL_IMAGE_FAILED = EC(630001, "pull image failed (docker pull IMAGE)") - ERR_CREATE_CONTAINER_FAILED = EC(630002, "create container failed (docker create IMAGE)") - ERR_START_CONTAINER_FAILED = EC(630003, "start container failed (docker start CONTAINER)") - ERR_STOP_CONTAINER_FAILED = EC(630004, "stop container failed (docker stop CONTAINER)") - ERR_RESTART_CONTAINER_FAILED = EC(630005, "restart container failed (docker restart CONTAINER)") - ERR_WAIT_CONTAINER_STOP_FAILED = EC(630006, "wait container stop failed (docker wait CONTAINER)") - ERR_REMOVE_CONTAINER_FAILED = EC(630007, "remove container failed (docker rm CONTAINER)") - ERR_LIST_CONTAINERS_FAILED = EC(630008, "list containers failed (docker ps)") - ERR_RUN_COMMAND_IN_CONTAINER_FAILED = EC(630009, "run a command in container failed (docker exec CONTAINER COMMAND)") - ERR_COPY_FROM_CONTAINER_FAILED = EC(630010, "copy file from container failed (docker cp CONTAINER:SRC_PATH DEST_PATH)") - ERR_COPY_INTO_CONTAINER_FAILED = EC(630011, "copy file into container failed (docker cp SRC_PATH CONTAINER:DEST_PATH)") - ERR_INSPECT_CONTAINER_FAILED = EC(630012, "get container low-level information failed (docker inspect ID)") - ERR_GET_CONTAINER_LOGS_FAILED = EC(630013, "get container logs failed (docker logs ID)") + // 630: execute task (docker/podman command) + ERR_GET_CONTAINER_ENGINE_INFO_FAILED = EC(630000, "get container engine info failed") + ERR_PULL_IMAGE_FAILED = EC(630001, "pull image failed") + ERR_CREATE_CONTAINER_FAILED = EC(630002, "create container failed") + ERR_START_CONTAINER_FAILED = EC(630003, "start container failed") + ERR_STOP_CONTAINER_FAILED = EC(630004, "stop container failed") + ERR_RESTART_CONTAINER_FAILED = EC(630005, "restart container failed") + ERR_WAIT_CONTAINER_STOP_FAILED = EC(630006, "wait container stop failed") + ERR_REMOVE_CONTAINER_FAILED = EC(630007, "remove container failed") + ERR_LIST_CONTAINERS_FAILED = EC(630008, "list containers failed") + ERR_RUN_COMMAND_IN_CONTAINER_FAILED = EC(630009, "run a command in container failed") + ERR_COPY_FROM_CONTAINER_FAILED = EC(630010, "copy file from container failed") + ERR_COPY_INTO_CONTAINER_FAILED = EC(630011, "copy file into container failed") + ERR_INSPECT_CONTAINER_FAILED = EC(630012, "get container low-level information failed") + ERR_GET_CONTAINER_LOGS_FAILED = EC(630013, "get container logs failed") + ERR_UPDATE_CONTAINER_FAILED = EC(630014, "update container failed") // 690: execuetr task (others) ERR_START_CRONTAB_IN_CONTAINER_FAILED = EC(690000, "start crontab in container failed") + // 70: http service + ERR_UNSUPPORT_REQUEST_URI = EC(701400, "unsupport request uri") + ERR_UNSUPPORT_METHOD_ARGUMENT = EC(702400, "unsupport method argument") + ERR_HTTP_METHOD_MISMATCHED = EC(703400, "http method mismatch") + ERR_BAD_REQUEST_FORM_PARAM = EC(704400, "bad request form param") + ERR_UNSUPPORT_HTTP_METHOD = EC(705405, "unsupport http method") + // 900: others ERR_CANCEL_OPERATION = EC(CODE_CANCEL_OPERATION, "cancel operation") // 999 diff --git a/internal/playbook/configs.go b/internal/playbook/configs.go index f0a83403c..911f76708 100644 --- a/internal/playbook/configs.go +++ b/internal/playbook/configs.go @@ -36,6 +36,7 @@ const ( TYPE_CONFIG_DEPLOY TYPE_CONFIG_CLIENT TYPE_CONFIG_PLAYGROUND + TYPE_CONFIG_MONITOR TYPE_CONFIG_ANY TYPE_CONFIG_NULL ) @@ -48,6 +49,7 @@ type SmartConfig struct { dcs []*topology.DeployConfig ccs []*configure.ClientConfig pgcs []*configure.PlaygroundConfig + mcs []*configure.MonitorConfig anys []interface{} } @@ -94,6 +96,13 @@ func (c *SmartConfig) GetPGC(index int) *configure.PlaygroundConfig { return c.pgcs[index] } +func (c *SmartConfig) GetMC(index int) *configure.MonitorConfig { + if index < 0 || index >= c.len || c.ctype != TYPE_CONFIG_MONITOR { + return nil + } + return c.mcs[index] +} + func (c *SmartConfig) GetAny(index int) interface{} { if index < 0 || index >= c.len || c.ctype != TYPE_CONFIG_ANY { return nil @@ -110,6 +119,7 @@ func NewSmartConfig(configs interface{}) (*SmartConfig, error) { dcs: []*topology.DeployConfig{}, ccs: []*configure.ClientConfig{}, pgcs: []*configure.PlaygroundConfig{}, + mcs: []*configure.MonitorConfig{}, anys: []interface{}{}, } build.DEBUG(build.DEBUG_SMART_CONFIGS, @@ -138,6 +148,10 @@ func NewSmartConfig(configs interface{}) (*SmartConfig, error) { c.ctype = TYPE_CONFIG_PLAYGROUND c.pgcs = configs.([]*configure.PlaygroundConfig) c.len = len(c.pgcs) + case []*configure.MonitorConfig: + c.ctype = TYPE_CONFIG_MONITOR + c.mcs = configs.([]*configure.MonitorConfig) + c.len = len(c.mcs) case []interface{}: c.ctype = TYPE_CONFIG_ANY c.anys = configs.([]interface{}) @@ -164,6 +178,10 @@ func NewSmartConfig(configs interface{}) (*SmartConfig, error) { c.ctype = TYPE_CONFIG_PLAYGROUND c.pgcs = append(c.pgcs, configs.(*configure.PlaygroundConfig)) c.len = 1 + case *configure.MonitorConfig: + c.ctype = TYPE_CONFIG_MONITOR + c.mcs = append(c.mcs, configs.(*configure.MonitorConfig)) + c.len = 1 case nil: c.ctype = TYPE_CONFIG_NULL c.len = 1 diff --git a/internal/playbook/factory.go b/internal/playbook/factory.go index fbccaa87f..f62a7b3e5 100644 --- a/internal/playbook/factory.go +++ b/internal/playbook/factory.go @@ -31,6 +31,7 @@ import ( "github.com/opencurve/curveadm/internal/task/task/checker" comm "github.com/opencurve/curveadm/internal/task/task/common" "github.com/opencurve/curveadm/internal/task/task/fs" + "github.com/opencurve/curveadm/internal/task/task/monitor" pg "github.com/opencurve/curveadm/internal/task/task/playground" "github.com/opencurve/curveadm/internal/tasks" ) @@ -58,6 +59,7 @@ const ( SYNC_CONFIG START_SERVICE START_ETCD + ENABLE_ETCD_AUTH START_MDS START_CHUNKSERVER START_SNAPSHOTCLONE @@ -77,17 +79,33 @@ const ( COLLECT_CLIENT BACKUP_ETCD_DATA CHECK_MDS_ADDRESS + INIT_CLIENT_STATUS GET_CLIENT_STATUS INSTALL_CLIENT UNINSTALL_CLIENT // bs + FORMAT_CHUNKFILE_POOL + GET_FORMAT_STATUS + STOP_FORMAT BALANCE_LEADER START_NEBD_SERVICE CREATE_VOLUME MAP_IMAGE UNMAP_IMAGE + // monitor + PULL_MONITOR_IMAGE + CREATE_MONITOR_CONTAINER + SYNC_MONITOR_CONFIG + CLEAN_CONFIG_CONTAINER + START_MONITOR_SERVICE + RESTART_MONITOR_SERVICE + STOP_MONITOR_SERVICE + INIT_MONITOR_STATUS + GET_MONITOR_STATUS + CLEAN_MONITOR + // bs/target START_TARGET_DAEMON STOP_TARGET_DAEMON @@ -99,8 +117,6 @@ const ( CHECK_CLIENT_S3 MOUNT_FILESYSTEM UMOUNT_FILESYSTEM - FORMAT_CHUNKFILE_POOL - GET_FORMAT_STATUS // polarfs DETECT_OS_RELEASE @@ -114,9 +130,6 @@ const ( REMOVE_PLAYGROUND GET_PLAYGROUND_STATUS - // STOP_FORMAT type stop formatting - STOP_FORMAT - // unknown UNKNOWN ) @@ -197,6 +210,8 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) { START_SNAPSHOTCLONE, START_METASERVER: t, err = comm.NewStartServiceTask(curveadm, config.GetDC(i)) + case ENABLE_ETCD_AUTH: + t, err = comm.NewEnableEtcdAuthTask(curveadm, config.GetDC(i)) case STOP_SERVICE: t, err = comm.NewStopServiceTask(curveadm, config.GetDC(i)) case RESTART_SERVICE: @@ -224,6 +239,8 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) { t, err = comm.NewCollectClientTask(curveadm, config.GetAny(i)) case BACKUP_ETCD_DATA: t, err = comm.NewBackupEtcdDataTask(curveadm, config.GetDC(i)) + case INIT_CLIENT_STATUS: + t, err = comm.NewInitClientStatusTask(curveadm, config.GetAny(i)) case GET_CLIENT_STATUS: t, err = comm.NewGetClientStatusTask(curveadm, config.GetAny(i)) case INSTALL_CLIENT: @@ -283,6 +300,27 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) { t, err = pg.NewRemovePlaygroundTask(curveadm, config.GetAny(i)) case GET_PLAYGROUND_STATUS: t, err = pg.NewGetPlaygroundStatusTask(curveadm, config.GetAny(i)) + // monitor + case PULL_MONITOR_IMAGE: + t, err = monitor.NewPullImageTask(curveadm, config.GetMC(i)) + case CREATE_MONITOR_CONTAINER: + t, err = monitor.NewCreateContainerTask(curveadm, config.GetMC(i)) + case SYNC_MONITOR_CONFIG: + t, err = monitor.NewSyncConfigTask(curveadm, config.GetMC(i)) + case CLEAN_CONFIG_CONTAINER: + t, err = monitor.NewCleanConfigContainerTask(curveadm, config.GetMC(i)) + case START_MONITOR_SERVICE: + t, err = monitor.NewStartServiceTask(curveadm, config.GetMC(i)) + case RESTART_MONITOR_SERVICE: + t, err = monitor.NewRestartServiceTask(curveadm, config.GetMC(i)) + case STOP_MONITOR_SERVICE: + t, err = monitor.NewStopServiceTask(curveadm, config.GetMC(i)) + case INIT_MONITOR_STATUS: + t, err = monitor.NewInitMonitorStatusTask(curveadm, config.GetMC(i)) + case GET_MONITOR_STATUS: + t, err = monitor.NewGetMonitorStatusTask(curveadm, config.GetMC(i)) + case CLEAN_MONITOR: + t, err = monitor.NewCleanMonitorTask(curveadm, config.GetMC(i)) default: return nil, errno.ERR_UNKNOWN_TASK_TYPE. diff --git a/internal/playbook/tasks/tasks.go b/internal/playbook/tasks/tasks.go index 589a2dc4e..da01cd2a7 100644 --- a/internal/playbook/tasks/tasks.go +++ b/internal/playbook/tasks/tasks.go @@ -122,7 +122,7 @@ func (ts *Tasks) displayStatus() func(static decor.Statistics) string { } } -func (ts *Tasks) displayReplica(t *task.Task) func(static decor.Statistics) string { +func (ts *Tasks) displayInstance(t *task.Task) func(static decor.Statistics) string { total := ts.CountPtid(t.Ptid()) return func(static decor.Statistics) string { nsucc, nskip, _ := ts.monitor.sum(static.ID) @@ -150,7 +150,7 @@ func (ts *Tasks) addSubBar(t *task.Task) { mpb.PrependDecorators( decor.Name(" + "), decor.Name(t.Subname()+" "), - decor.Any(ts.displayReplica(t), decor.WCSyncWidthR), + decor.Any(ts.displayInstance(t), decor.WCSyncWidthR), decor.Name(" "), decor.OnComplete(decor.Spinner([]string{}), ""), decor.Any(ts.displayStatus()), diff --git a/internal/task/scripts/nginx.go b/internal/storage/driver/driver.go similarity index 57% rename from internal/task/scripts/nginx.go rename to internal/storage/driver/driver.go index d7cfcb762..004b3d478 100644 --- a/internal/task/scripts/nginx.go +++ b/internal/storage/driver/driver.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 NetEase Inc. + * Copyright (c) 2023 NetEase Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -11,31 +11,30 @@ * 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. + * limitations under the Licensele(). */ /* * Project: CurveAdm - * Created Date: 2022-08-09 + * Created Date: 2023-05-24 * Author: Jingli Chen (Wine93) */ -package scripts +package driver -var START_NGINX = ` -g_listen="$1" - -cat << __EOF__ > /etc/nginx/nginx.conf -daemon off; -events { - worker_connections 768; +type IQueryResult interface { + Next() bool + Scan(dest ...any) error + Close() error } -http { - server { - $g_listen - } + +type IWriteResult interface { + LastInsertId() (int64, error) } -__EOF__ -nginx -` +type IDataBaseDriver interface { + Open(dbUrl string) error + Close() error + Query(query string, args ...any) (IQueryResult, error) + Write(query string, args ...any) (IWriteResult, error) +} diff --git a/internal/storage/driver/rqlite.go b/internal/storage/driver/rqlite.go new file mode 100644 index 000000000..426bb2481 --- /dev/null +++ b/internal/storage/driver/rqlite.go @@ -0,0 +1,88 @@ +package driver + +import ( + "strings" + "sync" + + "github.com/rqlite/gorqlite" + rqlite "github.com/rqlite/gorqlite" +) + +type RQLiteDB struct { + conn *rqlite.Connection + sync.Mutex +} + +type QueryResult struct { + result rqlite.QueryResult +} + +type WriteResult struct { + result rqlite.WriteResult +} + +var ( + _ IDataBaseDriver = (*RQLiteDB)(nil) + _ IQueryResult = (*QueryResult)(nil) + _ IWriteResult = (*WriteResult)(nil) +) + +func NewRQLiteDB() *RQLiteDB { + return &RQLiteDB{} +} + +func (db *RQLiteDB) Open(url string) error { + connURL := "http://" + strings.TrimPrefix(url, "rqlite://") + conn, err := gorqlite.Open(connURL) + if err != nil { + return err + } + db.conn = conn + return nil +} + +func (db *RQLiteDB) Close() error { + return nil +} + +func (result *QueryResult) Next() bool { + return result.result.Next() +} + +func (result *QueryResult) Scan(dest ...any) error { + return result.result.Scan(dest...) +} + +func (result *QueryResult) Close() error { + return nil +} + +func (db *RQLiteDB) Query(query string, args ...any) (IQueryResult, error) { + db.Lock() + defer db.Unlock() + + result, err := db.conn.QueryOneParameterized( + rqlite.ParameterizedStatement{ + Query: query, + Arguments: append([]interface{}{}, args...), + }, + ) + return &QueryResult{result: result}, err +} + +func (result *WriteResult) LastInsertId() (int64, error) { + return result.result.LastInsertID, nil +} + +func (db *RQLiteDB) Write(query string, args ...any) (IWriteResult, error) { + db.Lock() + defer db.Unlock() + + result, err := db.conn.WriteOneParameterized( + rqlite.ParameterizedStatement{ + Query: query, + Arguments: append([]interface{}{}, args...), + }, + ) + return &WriteResult{result: result}, err +} diff --git a/internal/storage/driver/sqlite.go b/internal/storage/driver/sqlite.go new file mode 100644 index 000000000..ab1378046 --- /dev/null +++ b/internal/storage/driver/sqlite.go @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 NetEase Inc. + * + * 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 Licensele(). + */ + +/* + * Project: CurveAdm + * Created Date: 2023-05-24 + * Author: Jingli Chen (Wine93) + */ + +package driver + +import ( + "database/sql" + "strings" + "sync" + + _ "github.com/mattn/go-sqlite3" +) + +type SQLiteDB struct { + db *sql.DB + sync.Mutex +} + +type Rows struct { + rows *sql.Rows +} + +type Result struct { + result sql.Result +} + +var ( + _ IDataBaseDriver = (*SQLiteDB)(nil) + _ IQueryResult = (*Rows)(nil) + _ IWriteResult = (*Result)(nil) +) + +func NewSQLiteDB() *SQLiteDB { + return &SQLiteDB{} +} + +func (db *SQLiteDB) Open(url string) error { + var err error + dataSourceName := strings.TrimPrefix(url, "sqlite://") + db.db, err = sql.Open("sqlite3", dataSourceName) + return err +} + +func (db *SQLiteDB) Close() error { + return db.db.Close() +} + +func (result *Rows) Next() bool { + return result.rows.Next() +} + +func (result *Rows) Scan(dest ...any) error { + return result.rows.Scan(dest...) +} + +func (result *Rows) Close() error { + return result.rows.Close() +} + +func (db *SQLiteDB) Query(query string, args ...any) (IQueryResult, error) { + db.Lock() + defer db.Unlock() + + rows, err := db.db.Query(query, args...) + if err != nil { + return nil, err + } + return &Rows{rows: rows}, nil +} + +func (result *Result) LastInsertId() (int64, error) { + return result.result.LastInsertId() +} + +func (db *SQLiteDB) Write(query string, args ...any) (IWriteResult, error) { + db.Lock() + defer db.Unlock() + + stmt, err := db.db.Prepare(query) + if err != nil { + return nil, err + } + + result, err := stmt.Exec(args...) + return &Result{result: result}, err +} diff --git a/internal/storage/sql.go b/internal/storage/sql.go index 9a0c191fc..0ce916aa1 100644 --- a/internal/storage/sql.go +++ b/internal/storage/sql.go @@ -37,9 +37,18 @@ package storage +import "time" + +// version +type Version struct { + Id int + Version string + LastConfirm string +} + var ( - // tables (hosts/clusters/containers(service)/clients/playrgound/audit) - CREATE_VERSION_TABLE = ` + // table: version + CreateVersionTable = ` CREATE TABLE IF NOT EXISTS version ( id INTEGER PRIMARY KEY AUTOINCREMENT, version TEXT NOT NULL, @@ -47,7 +56,26 @@ var ( ) ` - CREATE_HOSTS_TABLE = ` + // insert version + InsertVersion = `INSERT INTO version(version, lastconfirm) VALUES(?, "")` + + // set version + SetVersion = `UPDATE version SET version = ?, lastconfirm = ? WHERE id = ?` + + // select version + SelectVersion = `SELECT * FROM version` +) + +// hosts +type Hosts struct { + Id int + Data string + LastModifiedTime time.Time +} + +var ( + // table: hosts + CreateHostsTable = ` CREATE TABLE IF NOT EXISTS hosts ( id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT NOT NULL, @@ -55,7 +83,31 @@ var ( ) ` - CREATE_CLUSTERS_TABLE = ` + // insert hosts + InsertHosts = `INSERT INTO hosts(data, lastmodified_time) VALUES(?, datetime('now','localtime'))` + + // set hosts + SetHosts = `UPDATE hosts SET data = ?, lastmodified_time = datetime('now','localtime') WHERE id = ?` + + // select hosts + SelectHosts = `SELECT * FROM hosts` +) + +// cluster +type Cluster struct { + Id int + UUId string + Name string + Description string + CreateTime time.Time + Topology string + Pool string + Current bool +} + +var ( + // table: clusters + CreateClustersTable = ` CREATE TABLE IF NOT EXISTS clusters ( id INTEGER PRIMARY KEY AUTOINCREMENT, uuid TEXT NOT NULL, @@ -68,8 +120,48 @@ var ( ) ` + // insert cluster + InsertCluster = ` + INSERT INTO clusters(uuid, name, description, topology, pool, create_time) + VALUES(?, ?, ?, ?, "", datetime('now','localtime')) + ` + + // delete cluster + DeleteCluster = `DELETE from clusters WHERE name = ?` + + // select cluster + SelectCluster = `SELECT * FROM clusters WHERE name LIKE ?` + + // get current cluster + GetCurrentCluster = `SELECT * FROM clusters WHERE current = 1` + + // checkout cluster + CheckoutCluster = ` + UPDATE clusters + SET current = CASE name + WHEN ? THEN 1 + ELSE 0 + END + ` + + // set cluster topology + SetClusterTopology = `UPDATE clusters SET topology = ? WHERE id = ?` + + // set cluster pool + SetClusterPool = `UPDATE clusters SET topology = ?, pool = ? WHERE id = ?` +) + +// service +type Service struct { + Id string + ClusterId int + ContainerId string +} + +var ( + // table: containers // id: clusterId_role_host_(sequence/name) - CREATE_CONTAINERS_TABLE = ` + CreateContainersTable = ` CREATE TABLE IF NOT EXISTS containers ( id TEXT PRIMARY KEY, cluster_id INTEGER NOT NULL, @@ -77,7 +169,31 @@ var ( ) ` - CREATE_CLIENTS_TABLE = ` + // insert service + InsertService = `INSERT INTO containers(id, cluster_id, container_id) VALUES(?, ?, ?)` + + // select service + SelectService = `SELECT * FROM containers WHERE id = ?` + + // select services in cluster + SelectServicesInCluster = `SELECT * FROM containers WHERE cluster_id = ?` + + // set service container id + SetContainerId = `UPDATE containers SET container_id = ? WHERE id = ?` +) + +// client +type Client struct { + Id string + Kind string + Host string + ContainerId string + AuxInfo string +} + +var ( + // table: clients + CreateClientsTable = ` CREATE TABLE IF NOT EXISTS clients ( id TEXT PRIMARY KEY, kind TEXT NOT NULL, @@ -86,117 +202,167 @@ var ( aux_info TEXT NOT NULL ) ` + // insert client + InsertClient = `INSERT INTO clients(id, kind, host, container_id, aux_info) VALUES(?, ?, ?, ?, ?)` + + // set client aux info + SetClientAuxInfo = `UPDATE clients SET aux_info = ? WHERE id = ?` + + // select clients + SelectClients = `SELECT * FROM clients` + + // select client by id + SelectClientById = `SELECT * FROM clients WHERE id = ?` + + // delete client + DeleteClient = `DELETE from clients WHERE id = ?` +) - CREATE_PLAYGROUND_TABLE = ` - CREATE TABLE IF NOT EXISTS playgrounds ( +// playground +type Playground struct { + Id int + Name string + CreateTime time.Time + MountPoint string + Status string +} + +var ( + // table: playground + CreatePlaygroundTable = ` + CREATE TABLE IF NOT EXISTS playgrounds ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, create_time DATE NOT NULL, mount_point TEXT NOT NULL, - status TEXT NOT NULL + status TEXT NOT NULL ) - ` - - CREATE_AUDIT_TABLE = ` - CREATE TABLE IF NOT EXISTS audit ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - execute_time DATE NOT NULL, - work_directory TEXT NOT NULL, - command TEXT NOT NULL, - status INTEGER DEFAULT 0, - error_code INTEGET DEFAULT 0 - ) - ` - - CHECK_POOl_COLUMN = ` - SELECT COUNT(*) AS total - FROM pragma_table_info('clusters') - WHERE name='pool' ` - RENAME_CLUSTERS_TABLE = `ALTER TABLE clusters RENAME TO clusters_old` - - INSERT_CLUSTERS_FROM_OLD_TABLE = ` - INSERT INTO clusters(id, uuid, name, description, topology, pool, create_time, current) - SELECT id, uuid, name, description, topology, "", create_time, current - FROM clusters_old + // insert playground + InsertPlayground = ` + INSERT INTO playgrounds(name, create_time, mount_point, status) + VALUES(?, datetime('now','localtime'), ?, ?) ` - DROP_OLD_CLUSTERS_TABLE = `DROP TABLE clusters_old` - - // version - INSERT_VERSION = `INSERT INTO version(version, lastconfirm) VALUES(?, "")` - - SET_VERSION = `UPDATE version SET version = ?, lastconfirm = ? WHERE id = ?` + // set playground status + SetPlaygroundStatus = `UPDATE playgrounds SET status = ? WHERE name = ?` - SELECT_VERSION = `SELECT * FROM version` + // select playground + SelectPlayground = `SELECT * FROM playgrounds WHERE name LIKE ?` - // hosts - INSERT_HOSTS = `INSERT INTO hosts(data, lastmodified_time) VALUES(?, datetime('now','localtime'))` + // select playground by id + SelectPlaygroundById = `SELECT * FROM playgrounds WHERE id = ?` - SET_HOSTS = `UPDATE hosts SET data = ?, lastmodified_time = datetime('now','localtime') WHERE id = ?` - - SELECT_HOSTS = `SELECT * FROM hosts` - - // cluster - INSERT_CLUSTER = `INSERT INTO clusters(uuid, name, description, topology, pool, create_time) - VALUES(hex(randomblob(16)), ?, ?, ?, "", datetime('now','localtime'))` - - DELETE_CLUSTER = `DELETE from clusters WHERE name = ?` - - SELECT_CLUSTER = `SELECT * FROM clusters WHERE name LIKE ?` + // delete playground + DeletePlayground = `DELETE from playgrounds WHERE name = ?` +) - GET_CURRENT_CLUSTER = `SELECT * FROM clusters WHERE current = 1` +// audit log +type AuditLog struct { + Id int + ExecuteTime time.Time + WorkDirectory string + Command string + Status int + ErrorCode int +} - CHECKOUT_CLUSTER = ` - UPDATE clusters - SET current = CASE name - WHEN ? THEN 1 - ELSE 0 - END +var ( + // table: audit + CreateAuditTable = ` + CREATE TABLE IF NOT EXISTS audit ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + execute_time DATE NOT NULL, + work_directory TEXT NOT NULL, + command TEXT NOT NULL, + status INTEGER DEFAULT 0, + error_code INTEGET DEFAULT 0 + ) ` - SET_CLUSTER_TOPOLOGY = `UPDATE clusters SET topology = ? WHERE id = ?` + // insert audit log + InsertAuditLog = ` + INSERT INTO audit(execute_time, work_directory, command, status) + VALUES(?, ?, ?, ?) + ` - SET_CLUSTER_POOL = `UPDATE clusters SET topology = ?, pool = ? WHERE id = ?` + // set audit log status + SetAuditLogStatus = `UPDATE audit SET status = ?, error_code = ? WHERE id = ?` - // service - INSERT_SERVICE = `INSERT INTO containers(id, cluster_id, container_id) VALUES(?, ?, ?)` + // select audit log + SelectAuditLog = `SELECT * FROM audit` - SELECT_SERVICE = `SELECT * FROM containers WHERE id = ?` + // select audit log by id + SelectAuditLogById = `SELECT * FROM audit WHERE id = ?` +) - SELECT_SERVICE_IN_CLUSTER = `SELECT * FROM containers WHERE cluster_id = ?` +// any: we can store anything +type Any struct { + Id string + Data string +} - SET_CONTAINER_ID = `UPDATE containers SET container_id = ? WHERE id = ?` +var ( + // table: any + CreateAnyTable = ` + CREATE TABLE IF NOT EXISTS any ( + id TEXT PRIMARY KEY, + data TEXT NOT NULL + ) + ` - // client - INSERT_CLIENT = `INSERT INTO clients(id, kind, host, container_id, aux_info) VALUES(?, ?, ?, ?, ?)` + // insert item + InsertAnyItem = `INSERT INTO any(id, data) VALUES(?, ?)` - SELECT_CLIENTS = `SELECT * FROM clients` + // set item + SetAnyItem = `UPDATE any SET data = ? WHERE id = ?` - SELECT_CLIENT_BY_ID = `SELECT * FROM clients WHERE id = ?` + // select item by id + SelectAnyItem = `SELECT * FROM any WHERE id = ?` - DELETE_CLIENT = `DELETE from clients WHERE id = ?` + // delete item + DeleteAnyItem = `DELETE from any WHERE id = ?` +) - // playground - INSERT_PLAYGROUND = `INSERT INTO playgrounds(name, create_time, mount_point, status) - VALUES(?, datetime('now','localtime'), ?, ?)` +var ( + // check pool column + CheckPoolColumn = ` + SELECT COUNT(*) AS total + FROM pragma_table_info('clusters') + WHERE name='pool' + ` - SET_PLAYGROUND_STATUS = `UPDATE playgrounds SET status = ? WHERE name = ?` + // rename clusters table + RenameClustersTable = `ALTER TABLE clusters RENAME TO clusters_old` - SELECT_PLAYGROUND = `SELECT * FROM playgrounds WHERE name LIKE ?` + // insert clusters from old table + InsertClustersFromOldTable = ` + INSERT INTO clusters(id, uuid, name, description, topology, pool, create_time, current) + SELECT id, uuid, name, description, topology, "", create_time, current + FROM clusters_old + ` - SELECT_PLAYGROUND_BY_ID = `SELECT * FROM playgrounds WHERE id = ?` + // statement: drom old clusters table + DropOldClustersTable = `DROP TABLE clusters_old` +) - DELETE_PLAYGROUND = `DELETE from playgrounds WHERE name = ?` +var ( + // monitor + CreateMonitorTable = ` + CREATE TABLE IF NOT EXISTS monitors ( + cluster_id INTEGER PRIMARY KEY, + monitor TEXT NOT NULL + ) + ` + // monitor + InsertMonitor = `INSERT INTO monitors(cluster_id, monitor) VALUES(?, ?)` - // audit - INSERT_AUDIT_LOG = `INSERT INTO audit(execute_time, work_directory, command, status) - VALUES(?, ?, ?, ?)` + UpdateMonitor = `UPDATE monitors SET monitor = ? WHERE cluster_id = ?` - SET_AUDIT_LOG_STATUS = `UPDATE audit SET status = ?, error_code = ? WHERE id = ?` + SelectMonitor = `SELECT monitor FROM monitors WHERE cluster_id = ?` - SELECT_AUDIT_LOG = `SELECT * FROM audit` + DeleteMonitor = `DELETE FROM monitors WHERE cluster_id = ?` - SELECT_AUDIT_LOG_BY_ID = `SELECT * FROM audit WHERE id = ?` + ReplaceMonitor = `REPLACE INTO monitors (cluster_id, monitor) VALUES(?, ?)` ) diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 3d4a9c440..bd1f69a13 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -23,162 +23,79 @@ package storage import ( - "database/sql" "fmt" - "sync" + "regexp" "time" _ "github.com/mattn/go-sqlite3" + "github.com/opencurve/curveadm/internal/storage/driver" ) -type Version struct { - Id int - Version string - LastConfirm string -} - -type Hosts struct { - Id int - Data string - LastmodifiedTime time.Time -} - -type Cluster struct { - Id int - UUId string - Name string - Description string - CreateTime time.Time - Topology string - Pool string - Current bool -} - -type Service struct { - Id string - ClusterId int - ContainerId string -} - -type Client struct { - Id string - Kind string - Host string - ContainerId string - AuxInfo string -} +var ( + ErrInvalidDBUrl = fmt.Errorf("invalid database url") +) -type Playground struct { - Id int - Name string - CreateTime time.Time - MountPoint string - Status string -} +// rqlite://127.0.0.1:4000 +// sqlite:///home/curve/.curveadm/data/curveadm.db +const ( + REGEX_DB_URL = "^(sqlite|rqlite)://(.+)$" +) -type AuditLog struct { - Id int - ExecuteTime time.Time - WorkDirectory string - Command string - Status int - ErrorCode int +type Monitor struct { + ClusterId int + Monitor string } type Storage struct { - db *sql.DB - mutex *sync.Mutex + db driver.IDataBaseDriver } -func NewStorage(dbfile string) (*Storage, error) { - db, err := sql.Open("sqlite3", dbfile) - if err != nil { - return nil, err +func NewStorage(dbURL string) (*Storage, error) { + pattern := regexp.MustCompile(REGEX_DB_URL) + mu := pattern.FindStringSubmatch(dbURL) + if len(mu) == 0 { + return nil, ErrInvalidDBUrl } - s := &Storage{db: db, mutex: &sync.Mutex{}} - if err = s.init(); err != nil { - return nil, err + storage := &Storage{} + if mu[1] == "sqlite" { + storage.db = driver.NewSQLiteDB() + } else { + storage.db = driver.NewRQLiteDB() } - return s, nil -} - -func (s *Storage) init() error { - if err := s.execSQL(CREATE_VERSION_TABLE); err != nil { - return err - } else if err := s.execSQL(CREATE_HOSTS_TABLE); err != nil { - return err - } else if err := s.execSQL(CREATE_HOSTS_TABLE); err != nil { - return err - } else if err := s.execSQL(CREATE_CLUSTERS_TABLE); err != nil { - return err - } else if err := s.execSQL(CREATE_CONTAINERS_TABLE); err != nil { - return err - } else if err := s.execSQL(CREATE_CLIENTS_TABLE); err != nil { - return err - } else if err := s.execSQL(CREATE_PLAYGROUND_TABLE); err != nil { - return err - } else if err := s.execSQL(CREATE_AUDIT_TABLE); err != nil { - return err - } else if err := s.compatible(); err != nil { - return err + err := storage.db.Open(dbURL) + if err == nil { + err = storage.init() } - - return nil + return storage, err } -func (s *Storage) compatible() error { - tx, err := s.db.Begin() - if err != nil { - return err +func (s *Storage) init() error { + sqls := []string{ + CreateVersionTable, + CreateHostsTable, + CreateClustersTable, + CreateContainersTable, + CreateClientsTable, + CreatePlaygroundTable, + CreateAuditTable, + CreateMonitorTable, + CreateAnyTable, } - err = func() error { - rows, err := tx.Query(CHECK_POOl_COLUMN) + for _, sql := range sqls { + _, err := s.db.Write(sql) if err != nil { return err } - - if rows.Next() { - count := 0 - err = rows.Scan(&count) - rows.Close() - if err != nil { - return err - } - if count != 0 { - return nil - } - } - - alterSQL := fmt.Sprintf("%s;%s;%s;%s", - RENAME_CLUSTERS_TABLE, - CREATE_CLUSTERS_TABLE, - INSERT_CLUSTERS_FROM_OLD_TABLE, - DROP_OLD_CLUSTERS_TABLE, - ) - _, err = tx.Exec(alterSQL) - return err - }() - - if err != nil { - tx.Rollback() - return err } - return tx.Commit() + return nil } -func (s *Storage) execSQL(query string, args ...interface{}) error { - s.mutex.Lock() - defer s.mutex.Unlock() - stmt, err := s.db.Prepare(query) - if err != nil { - return err - } - - _, err = stmt.Exec(args...) +func (s *Storage) write(query string, args ...any) error { + _, err := s.db.Write(query, args...) return err } @@ -192,24 +109,22 @@ func (s *Storage) SetVersion(version, lastConfirm string) error { if err != nil { return err } else if len(versions) == 0 { - return s.execSQL(INSERT_VERSION, version) + return s.write(InsertVersion, version) } - return s.execSQL(SET_VERSION, version, lastConfirm, versions[0].Id) + return s.write(SetVersion, version, lastConfirm, versions[0].Id) } func (s *Storage) GetVersions() ([]Version, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - rows, err := s.db.Query(SELECT_VERSION) + result, err := s.db.Query(SelectVersion) if err != nil { return nil, err } + defer result.Close() - defer rows.Close() var versions []Version var version Version - for rows.Next() { - err = rows.Scan(&version.Id, &version.Version, &version.LastConfirm) + for result.Next() { + err = result.Scan(&version.Id, &version.Version, &version.LastConfirm) versions = append(versions, version) break } @@ -222,24 +137,22 @@ func (s *Storage) SetHosts(data string) error { if err != nil { return err } else if len(hostses) == 0 { - return s.execSQL(INSERT_HOSTS, data) + return s.write(InsertHosts, data) } - return s.execSQL(SET_HOSTS, data, hostses[0].Id) + return s.write(SetHosts, data, hostses[0].Id) } func (s *Storage) GetHostses() ([]Hosts, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - rows, err := s.db.Query(SELECT_HOSTS) + result, err := s.db.Query(SelectHosts) if err != nil { return nil, err } + defer result.Close() - defer rows.Close() var hostses []Hosts var hosts Hosts - for rows.Next() { - err = rows.Scan(&hosts.Id, &hosts.Data, &hosts.LastmodifiedTime) + for result.Next() { + err = result.Scan(&hosts.Id, &hosts.Data, &hosts.LastModifiedTime) hostses = append(hostses, hosts) break } @@ -247,28 +160,34 @@ func (s *Storage) GetHostses() ([]Hosts, error) { } // cluster -func (s *Storage) InsertCluster(name, description, topology string) error { - return s.execSQL(INSERT_CLUSTER, name, description, topology) +func (s *Storage) InsertCluster(name, uuid, description, topology string) error { + return s.write(InsertCluster, uuid, name, description, topology) } func (s *Storage) DeleteCluster(name string) error { - return s.execSQL(DELETE_CLUSTER, name) + return s.write(DeleteCluster, name) } func (s *Storage) getClusters(query string, args ...interface{}) ([]Cluster, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - rows, err := s.db.Query(query, args...) + result, err := s.db.Query(query, args...) if err != nil { return nil, err } + defer result.Close() - defer rows.Close() clusters := []Cluster{} - for rows.Next() { + for result.Next() { cluster := Cluster{} - err = rows.Scan(&cluster.Id, &cluster.UUId, &cluster.Name, &cluster.Description, - &cluster.Topology, &cluster.Pool, &cluster.CreateTime, &cluster.Current) + err = result.Scan( + &cluster.Id, + &cluster.UUId, + &cluster.Name, + &cluster.Description, + &cluster.Topology, + &cluster.Pool, + &cluster.CreateTime, + &cluster.Current, + ) if err != nil { return nil, err } @@ -279,16 +198,16 @@ func (s *Storage) getClusters(query string, args ...interface{}) ([]Cluster, err } func (s *Storage) GetClusters(name string) ([]Cluster, error) { - return s.getClusters(SELECT_CLUSTER, name) + return s.getClusters(SelectCluster, name) } func (s *Storage) CheckoutCluster(name string) error { - return s.execSQL(CHECKOUT_CLUSTER, name) + return s.write(CheckoutCluster, name) } func (s *Storage) GetCurrentCluster() (Cluster, error) { cluster := Cluster{Id: -1, Name: ""} - clusters, err := s.getClusters(GET_CURRENT_CLUSTER) + clusters, err := s.getClusters(GetCurrentCluster) if err != nil { return cluster, err } else if len(clusters) == 1 { @@ -299,31 +218,29 @@ func (s *Storage) GetCurrentCluster() (Cluster, error) { } func (s *Storage) SetClusterTopology(id int, topology string) error { - return s.execSQL(SET_CLUSTER_TOPOLOGY, topology, id) + return s.write(SetClusterTopology, topology, id) } func (s *Storage) SetClusterPool(id int, topology, pool string) error { - return s.execSQL(SET_CLUSTER_POOL, topology, pool, id) + return s.write(SetClusterPool, topology, pool, id) } // service func (s *Storage) InsertService(clusterId int, serviceId, containerId string) error { - return s.execSQL(INSERT_SERVICE, serviceId, clusterId, containerId) + return s.write(InsertService, serviceId, clusterId, containerId) } func (s *Storage) getServices(query string, args ...interface{}) ([]Service, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - rows, err := s.db.Query(query, args...) + result, err := s.db.Query(query, args...) if err != nil { return nil, err } + defer result.Close() - defer rows.Close() services := []Service{} var service Service - for rows.Next() { - err = rows.Scan(&service.Id, &service.ClusterId, &service.ContainerId) + for result.Next() { + err = result.Scan(&service.Id, &service.ClusterId, &service.ContainerId) if err != nil { return nil, err } @@ -334,11 +251,11 @@ func (s *Storage) getServices(query string, args ...interface{}) ([]Service, err } func (s *Storage) GetServices(clusterId int) ([]Service, error) { - return s.getServices(SELECT_SERVICE_IN_CLUSTER, clusterId) + return s.getServices(SelectServicesInCluster, clusterId) } func (s *Storage) GetContainerId(serviceId string) (string, error) { - services, err := s.getServices(SELECT_SERVICE, serviceId) + services, err := s.getServices(SelectService, serviceId) if err != nil || len(services) == 0 { return "", err } @@ -347,27 +264,29 @@ func (s *Storage) GetContainerId(serviceId string) (string, error) { } func (s *Storage) SetContainId(serviceId, containerId string) error { - return s.execSQL(SET_CONTAINER_ID, containerId, serviceId) + return s.write(SetContainerId, containerId, serviceId) } // client func (s *Storage) InsertClient(id, kind, host, containerId, auxInfo string) error { - return s.execSQL(INSERT_CLIENT, id, kind, host, containerId, auxInfo) + return s.write(InsertClient, id, kind, host, containerId, auxInfo) +} + +func (s *Storage) SetClientAuxInfo(id, auxInfo string) error { + return s.write(SetClientAuxInfo, id, auxInfo) } func (s *Storage) getClients(query string, args ...interface{}) ([]Client, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - rows, err := s.db.Query(query, args...) + result, err := s.db.Query(query, args...) if err != nil { return nil, err } + defer result.Close() - defer rows.Close() clients := []Client{} var client Client - for rows.Next() { - err = rows.Scan(&client.Id, &client.Kind, &client.Host, &client.ContainerId, &client.AuxInfo) + for result.Next() { + err = result.Scan(&client.Id, &client.Kind, &client.Host, &client.ContainerId, &client.AuxInfo) if err != nil { return nil, err } @@ -378,7 +297,7 @@ func (s *Storage) getClients(query string, args ...interface{}) ([]Client, error } func (s *Storage) GetClientContainerId(id string) (string, error) { - clients, err := s.getClients(SELECT_CLIENT_BY_ID, id) + clients, err := s.getClients(SelectClientById, id) if err != nil || len(clients) == 0 { return "", err } @@ -387,44 +306,42 @@ func (s *Storage) GetClientContainerId(id string) (string, error) { } func (s *Storage) GetClient(id string) ([]Client, error) { - return s.getClients(SELECT_CLIENT_BY_ID, id) + return s.getClients(SelectClientById, id) } func (s *Storage) GetClients() ([]Client, error) { - return s.getClients(SELECT_CLIENTS) + return s.getClients(SelectClients) } func (s *Storage) DeleteClient(id string) error { - return s.execSQL(DELETE_CLIENT, id) + return s.write(DeleteClient, id) } // playground func (s *Storage) InsertPlayground(name, mountPoint string) error { // FIXME: remove status - return s.execSQL(INSERT_PLAYGROUND, name, mountPoint, "") + return s.write(InsertPlayground, name, mountPoint, "") } func (s *Storage) SetPlaygroundStatus(name, status string) error { - return s.execSQL(SET_PLAYGROUND_STATUS, status, name) + return s.write(SetPlaygroundStatus, status, name) } func (s *Storage) DeletePlayground(name string) error { - return s.execSQL(DELETE_PLAYGROUND, name) + return s.write(DeletePlayground, name) } func (s *Storage) getPlaygrounds(query string, args ...interface{}) ([]Playground, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - rows, err := s.db.Query(query, args...) + result, err := s.db.Query(query, args...) if err != nil { return nil, err } + defer result.Close() - defer rows.Close() playgrounds := []Playground{} var playground Playground - for rows.Next() { - err = rows.Scan( + for result.Next() { + err = result.Scan( &playground.Id, &playground.Name, &playground.CreateTime, @@ -440,47 +357,38 @@ func (s *Storage) getPlaygrounds(query string, args ...interface{}) ([]Playgroun } func (s *Storage) GetPlaygrounds(name string) ([]Playground, error) { - return s.getPlaygrounds(SELECT_PLAYGROUND, name) + return s.getPlaygrounds(SelectPlayground, name) } func (s *Storage) GetPlaygroundById(id string) ([]Playground, error) { - return s.getPlaygrounds(SELECT_PLAYGROUND_BY_ID, id) + return s.getPlaygrounds(SelectPlaygroundById, id) } // audit func (s *Storage) InsertAuditLog(time time.Time, workDir, command string, status int) (int64, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - stmt, err := s.db.Prepare(INSERT_AUDIT_LOG) - if err != nil { - return -1, err - } - - result, err := stmt.Exec(time, workDir, command, status) + result, err := s.db.Write(InsertAuditLog, time, workDir, command, status) if err != nil { - return -1, err + return 0, err } return result.LastInsertId() } func (s *Storage) SetAuditLogStatus(id int64, status, errorCode int) error { - return s.execSQL(SET_AUDIT_LOG_STATUS, status, errorCode, id) + return s.write(SetAuditLogStatus, status, errorCode, id) } func (s *Storage) getAuditLogs(query string, args ...interface{}) ([]AuditLog, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - rows, err := s.db.Query(query, args...) + result, err := s.db.Query(query, args...) if err != nil { return nil, err } + defer result.Close() - defer rows.Close() auditLogs := []AuditLog{} var auditLog AuditLog - for rows.Next() { - err = rows.Scan(&auditLog.Id, + for result.Next() { + err = result.Scan(&auditLog.Id, &auditLog.ExecuteTime, &auditLog.WorkDirectory, &auditLog.Command, @@ -496,9 +404,84 @@ func (s *Storage) getAuditLogs(query string, args ...interface{}) ([]AuditLog, e } func (s *Storage) GetAuditLogs() ([]AuditLog, error) { - return s.getAuditLogs(SELECT_AUDIT_LOG) + return s.getAuditLogs(SelectAuditLog) } func (s *Storage) GetAuditLog(id int64) ([]AuditLog, error) { - return s.getAuditLogs(SELECT_AUDIT_LOG_BY_ID, id) + return s.getAuditLogs(SelectAuditLogById, id) +} + +// any item prefix +const ( + PREFIX_CLIENT_CONFIG = 0x01 +) + +func (s *Storage) realId(prefix int, id string) string { + return fmt.Sprintf("%d:%s", prefix, id) +} + +func (s *Storage) InsertClientConfig(id, data string) error { + id = s.realId(PREFIX_CLIENT_CONFIG, id) + return s.write(InsertAnyItem, id, data) +} + +func (s *Storage) GetClientConfig(id string) ([]Any, error) { + id = s.realId(PREFIX_CLIENT_CONFIG, id) + result, err := s.db.Query(SelectAnyItem, id) + if err != nil { + return nil, err + } + defer result.Close() + + items := []Any{} + var item Any + for result.Next() { + err = result.Scan(&item.Id, &item.Data) + if err != nil { + return nil, err + } + items = append(items, item) + } + + return items, nil +} + +func (s *Storage) DeleteClientConfig(id string) error { + id = s.realId(PREFIX_CLIENT_CONFIG, id) + return s.write(DeleteAnyItem, id) +} + +func (s *Storage) GetMonitor(clusterId int) (Monitor, error) { + monitor := Monitor{ + ClusterId: clusterId, + } + rows, err := s.db.Query(SelectMonitor, clusterId) + if err != nil { + return monitor, err + } + + defer rows.Close() + for rows.Next() { + err = rows.Scan(&monitor.Monitor) + if err != nil { + return monitor, err + } + } + return monitor, nil +} + +func (s *Storage) InsertMonitor(m Monitor) error { + return s.write(InsertMonitor, m.ClusterId, m.Monitor) +} + +func (s *Storage) UpdateMonitor(m Monitor) error { + return s.write(UpdateMonitor, m.Monitor, m.ClusterId) +} + +func (s *Storage) DeleteMonitor(clusterId int) error { + return s.write(DeleteMonitor, clusterId) +} + +func (s *Storage) ReplaceMonitor(m Monitor) error { + return s.write(ReplaceMonitor, m.ClusterId, m.Monitor) } diff --git a/internal/task/context/context.go b/internal/task/context/context.go index bbc758373..693e170f6 100644 --- a/internal/task/context/context.go +++ b/internal/task/context/context.go @@ -29,27 +29,27 @@ import ( ) type Context struct { - sshClient *module.SSHClient - module *module.Module - register *Register + remoteClient module.RemoteClient + module *module.Module + register *Register } -func NewContext(sshClient *module.SSHClient) (*Context, error) { +func NewContext(remoteClient module.RemoteClient) (*Context, error) { return &Context{ - sshClient: sshClient, - module: module.NewModule(sshClient), - register: NewRegister(), + remoteClient: remoteClient, + module: module.NewModule(remoteClient), + register: NewRegister(), }, nil } func (ctx *Context) Close() { - if ctx.sshClient != nil { - ctx.sshClient.Client().Close() + if ctx.remoteClient != nil { + ctx.remoteClient.Close() } } -func (ctx *Context) SSHClient() *module.SSHClient { - return ctx.sshClient +func (ctx *Context) RemoteClient() module.RemoteClient { + return ctx.remoteClient } func (ctx *Context) Module() *module.Module { diff --git a/internal/task/scripts/collect.go b/internal/task/scripts/collect.go deleted file mode 100644 index 0e2ee5114..000000000 --- a/internal/task/scripts/collect.go +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2021 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2021-11-26 - * Author: Jingli Chen (Wine93) - */ - -package scripts - -/* - * Usage: collect PREFIX CONTAINER_ID DEST_DIR - * Example: collect /usr/local/curvefs/etcd 8d9b0c0bdec5 /tmp/dest_dir - */ -var COLLECT = ` -############################ GLOBAL VARIABLES -g_prefix="$1" -g_container_id="$2" -g_dest_dir="$3" -g_log_dir="$g_prefix/logs" -g_conf_dir="$g_prefix/conf" - -############################ FUNCTIONS -function docker_cmd() { - sudo docker exec $g_container_id /bin/bash -c "$1" -} - -function docker_cp() { - sudo docker cp $g_container_id:$1 $2 -} - -function copy_logs() { - sudo docker logs $g_container_id > $g_dest_dir/logs/stdout - sudo docker logs $g_container_id 2> $g_dest_dir/logs/stderr - for file in $(docker_cmd "ls $g_log_dir | tail -n 5") - do - docker_cp $g_log_dir/$file $g_dest_dir/logs - done -} - -function copy_config() { - docker_cp $g_conf_dir $g_dest_dir -} - -function main() { - mkdir -p $g_dest_dir/{logs,conf} - copy_logs - copy_config -} - -############################ MAIN() -main "$@" -` diff --git a/internal/task/scripts/create_volume.go b/internal/task/scripts/create_volume.go deleted file mode 100644 index 765054ccc..000000000 --- a/internal/task/scripts/create_volume.go +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2022 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2022-07-31 - * Author: Jingli Chen (Wine93) - */ - -package scripts - -/* - * Usage: create_volume USER VOLUME SIZE - * Example: create_volume curve test 10 - */ -var CREATE_VOLUME = ` -#!/usr/bin/env bash - -g_user=$1 -g_volume=$2 -g_size=$3 - -output=$(curve_ops_tool create -userName=$g_user -fileName=$g_volume -fileLength=$g_size) -if [ $? -ne 0 ]; then - if [ "$output" = "CreateFile fail with errCode: 101" ]; then - echo "EXIST" - else - echo "FAILED" - fi -else - echo "SUCCESS" -fi -` diff --git a/internal/task/scripts/createfs.go b/internal/task/scripts/createfs.go deleted file mode 100644 index 211d35249..000000000 --- a/internal/task/scripts/createfs.go +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2022 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2022-01-04 - * Author: chengyi01 - */ - -package scripts - -/* - * Usage: create fs before mount fs - * Example: createfs /test - */ -var CREATEFS = ` -g_curvefs_tool="curvefs_tool" -g_curvefs_tool_operator="create-fs" -g_rpc_timeout_ms="-rpcTimeoutMs=10000" -g_fsname="-fsName=" -g_fstype="-fsType=" -g_entrypoint="/entrypoint.sh" - -function createfs() { - g_fsname=$g_fsname$1 - g_fstype=$g_fstype$2 - - $g_curvefs_tool $g_curvefs_tool_operator $g_fsname $g_fstype $g_rpc_timeout_ms -} - -createfs "$@" - -ret=$? -if [ $ret -eq 0 ]; then - $g_entrypoint "$@" - ret=$? - exit $ret -else - echo "CREATEFS FAILED" - exit 1 -fi -` diff --git a/internal/task/scripts/enable_etcd_auth.go b/internal/task/scripts/enable_etcd_auth.go new file mode 100644 index 000000000..a18ff157c --- /dev/null +++ b/internal/task/scripts/enable_etcd_auth.go @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. +*/ + +/* +* Project: Curveadm +* Created Date: 2023-08-02 +* Author: wanghai (SeanHai) +*/ + +package scripts + +var ENABLE_ETCD_AUTH = ` +#!/usr/bin/env bash + +if [ $# -ne 3 ]; then + echo "Usage: $0 endpoints username password" + exit 1 +fi + +endpoints=$1 +username=$2 +password=$3 +root_user=root + +# create root user +etcdctl --endpoints=${endpoints} user add ${root_user}:${password} && \ +etcdctl --endpoints=${endpoints} user grant-role ${root_user} root || exit 1 + +# create user if not root +if [ "${username}" != "${root_user}" ]; then + etcdctl --endpoints=${endpoints} user add ${username}:${password} && \ + etcdctl --endpoints=${endpoints} user grant-role ${username} root || exit 1 +fi + +# enable auth +etcdctl --endpoints=${endpoints} auth enable --user=${root_user}:${password} || exit 1 +` diff --git a/internal/task/scripts/format.go b/internal/task/scripts/format.go deleted file mode 100644 index 826fcf137..000000000 --- a/internal/task/scripts/format.go +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2021 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2021-12-27 - * Author: Jingli Chen (Wine93) - */ - -package scripts - -var FORMAT = ` -binary=$1 -percent=$2 -chunkfile_size=$3 -chunkfile_pool_dir=$4 -chunkfile_pool_meta_path=$5 - -mkdir -p $chunkfile_pool_dir -$binary \ - -allocatePercent=$percent \ - -fileSize=$chunkfile_size \ - -filePoolDir=$chunkfile_pool_dir \ - -filePoolMetaPath=$chunkfile_pool_meta_path \ - -fileSystemPath=$chunkfile_pool_dir -` diff --git a/internal/task/scripts/map.go b/internal/task/scripts/map.go deleted file mode 100644 index f6cedea15..000000000 --- a/internal/task/scripts/map.go +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2021 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2022-01-10 - * Author: Jingli Chen (Wine93) - */ - -package scripts - -/* - * Usage: map USER VOLUME CREATE SIZE - * Example: map curve test true 10 - */ -var MAP = ` -#!/usr/bin/env bash - -g_user=$1 -g_volume=$2 -g_options=$3 -g_stderr=/tmp/__curveadm_map__ - -mkdir -p /curvebs/nebd/data/lock -touch /etc/curve/curvetab -curve-nbd map --nbds_max=16 ${g_options} cbd:pool/${g_volume}_${g_user}_ > ${g_stderr} 2>&1 -if [ $? -ne 0 ]; then - cat ${g_stderr} - exit 1 -else - echo "SUCCESS" -fi -` diff --git a/internal/task/scripts/monitor.go b/internal/task/scripts/monitor.go new file mode 100644 index 000000000..cf6f25302 --- /dev/null +++ b/internal/task/scripts/monitor.go @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-23 +* Author: wanghai (SeanHai) + */ + +package scripts + +var PROMETHEUS_YML = ` +global: + scrape_interval: 3s + evaluation_interval: 15s + +scrape_configs: + - job_name: 'prometheus' + static_configs: + - targets: ['localhost:%d'] + + - job_name: 'curve_metrics' + file_sd_configs: + - files: ['target.json'] + + - job_name: 'node' + static_configs: + - targets: %s +` + +var GRAFANA_DATA_SOURCE = ` +datasources: +- name: 'Prometheus' + type: 'prometheus' + access: 'proxy' + org_id: 1 + url: 'http://%s:%d' + is_default: true + version: 1 + editable: true +` \ No newline at end of file diff --git a/internal/task/scripts/recycle.go b/internal/task/scripts/recycle.go deleted file mode 100644 index 3dfe5c2b2..000000000 --- a/internal/task/scripts/recycle.go +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2021 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2022-01-13 - * Author: Jingli Chen (Wine93) - */ - -package scripts - -/* - * Usage: recycle SOURCE DESTINATION SIZE - * Example: recycle '/data/chunkserver0/copysets /data/chunkserver0/recycler' /data/chunkserver0/chunkfilepool 16781312 - */ -var RECYCLE = ` -g_source=$1 -g_dest=$2 -g_size=$3 -chunkid=$(ls -vr ${g_dest} | head -n 1) -chunkid=${chunkid%.clean} -for file in $(find $g_source -type f -size ${g_size}c -printf '%p\n'); do - chunkid=$((chunkid+1)) - mv $file $g_dest/$chunkid -done -` diff --git a/internal/task/scripts/script.go b/internal/task/scripts/script.go index 1cd4c6e1c..51bcc9813 100644 --- a/internal/task/scripts/script.go +++ b/internal/task/scripts/script.go @@ -22,6 +22,10 @@ package scripts +import ( + _ "embed" +) + const ( STATUS_OK = "CURVEADM_OK" STATUS_FAIL = "CURVEADM_FAIL" @@ -29,15 +33,32 @@ const ( ) var ( - SCRIPT_WAIT string = WAIT - SCRIPT_COLLECT string = COLLECT - SCRIPT_REPORT string = REPORT - SCRIPT_FORMAT string = FORMAT - SCRIPT_MAP string = MAP - SCRIPT_TARGET string = TARGET - SCRIPT_RECYCLE string = RECYCLE - SCRIPT_CREATEFS string = CREATEFS - SCRIPT_CREATE_VOLUME string = CREATE_VOLUME - SCRIPT_WAIT_CHUNKSERVERS string = WAIT_CHUNKSERVERS - SCRIPT_START_NGINX string = START_NGINX + // Common + + //go:embed shell/wait.sh + WAIT string + //go:embed shell/report.sh + REPORT string + + // CurveBS + + //go:embed shell/format.sh + FORMAT string + //go:embed shell/wait_chunkserver.sh + WAIT_CHUNKSERVERS string + //go:embed shell/start_nginx.sh + START_NGINX string + //go:embed shell/create_volume.sh + CREATE_VOLUME string + //go:embed shell/map.sh + MAP string + //go:embed shell/target.sh + TARGET string + //go:embed shell/recycle.sh + RECYCLE string + + // CurveFS + + //go:embed shell/create_fs.sh + CREATE_FS string ) diff --git a/internal/task/scripts/shell/create_fs.sh b/internal/task/scripts/shell/create_fs.sh new file mode 100644 index 000000000..718ea9724 --- /dev/null +++ b/internal/task/scripts/shell/create_fs.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Usage: create_fs USER VOLUME SIZE +# Example: create_fs curve test 10 +# Created Date: 2022-01-04 +# Author: chengyi01 + + +g_curvefs_tool="curvefs_tool" +g_curvefs_tool_operator="create-fs" +g_rpc_timeout_ms="-rpcTimeoutMs=10000" +g_fsname="-fsName=" +g_fstype="-fsType=" +g_entrypoint="/entrypoint.sh" + +function createfs() { + g_fsname=$g_fsname$1 + g_fstype=$g_fstype$2 + + $g_curvefs_tool $g_curvefs_tool_operator "$g_fsname" "$g_fstype" $g_rpc_timeout_ms +} + +createfs "$@" + +ret=$? +if [ $ret -eq 0 ]; then + $g_entrypoint "$@" + ret=$? + exit $ret +else + echo "CREATEFS FAILED" + exit 1 +fi diff --git a/internal/task/scripts/shell/create_volume.sh b/internal/task/scripts/shell/create_volume.sh new file mode 100644 index 000000000..847dd6eae --- /dev/null +++ b/internal/task/scripts/shell/create_volume.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# Usage: create_volume USER VOLUME SIZE +# Example: create_volume curve test 10 +# Created Date: 2022-07-31 +# Author: Jingli Chen (Wine93) + + +g_user=$1 +g_volume=$2 +g_size=$3 +g_poolset=$4 +g_create_opts=( + "-userName=$g_user" + "-fileName=$g_volume" + -fileLength="$g_size" +) +if [ -n "$g_poolset" ]; then + g_create_opts+=("-poolset=$g_poolset") +fi + +output=$(curve_ops_tool create "${g_create_opts[@]}") +if [ "$?" -ne 0 ]; then + if [ "$output" = "CreateFile fail with errCode: kFileExists" ]; then + echo "EXIST" + else + echo "FAILED" + fi +else + echo "SUCCESS" +fi diff --git a/internal/task/scripts/shell/format.sh b/internal/task/scripts/shell/format.sh new file mode 100644 index 000000000..c58cece09 --- /dev/null +++ b/internal/task/scripts/shell/format.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Created Date: 2021-12-27 +# Author: Jingli Chen (Wine93) + + +binary=$1 +percent=$2 +chunkfile_size=$3 +chunkfile_pool_dir=$4 +chunkfile_pool_meta_path=$5 +chunkfile_block_size=$6 + +mkdir -p $chunkfile_pool_dir +$binary \ + -allocatePercent=$percent \ + -fileSize=$chunkfile_size \ + -filePoolDir=$chunkfile_pool_dir \ + -filePoolMetaPath=$chunkfile_pool_meta_path \ + -fileSystemPath=$chunkfile_pool_dir \ + -blockSize=$chunkfile_block_size \ + -undefok blockSize diff --git a/internal/task/scripts/shell/map.sh b/internal/task/scripts/shell/map.sh new file mode 100644 index 000000000..3a23b5133 --- /dev/null +++ b/internal/task/scripts/shell/map.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Usage: map USER VOLUME CREATE SIZE +# Example: map curve test true 10 +# Created Date: 2022-01-10 +# Author: Jingli Chen (Wine93) + + +g_user=$1 +g_volume=$2 +g_options=$3 +g_stderr=/tmp/__curveadm_map__ + +mkdir -p /curvebs/nebd/data/lock +touch /etc/curve/curvetab +curve-nbd map --nbds_max=16 ${g_options} cbd:pool/${g_volume}_${g_user}_ > ${g_stderr} 2>&1 +if [ $? -ne 0 ]; then + cat ${g_stderr} + exit 1 +else + echo "SUCCESS" +fi diff --git a/internal/task/scripts/shell/recycle.sh b/internal/task/scripts/shell/recycle.sh new file mode 100644 index 000000000..c4e7bba8c --- /dev/null +++ b/internal/task/scripts/shell/recycle.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# Usage: recycle SOURCE DESTINATION SIZE +# Example: recycle '/data/chunkserver0/copysets /data/chunkserver0/recycler' /data/chunkserver0/chunkfilepool 16781312 +# Created Date: 2022-01-13 +# Author: Jingli Chen (Wine93) + + +g_source=$1 +g_dest=$2 +g_size=$3 +chunkid=$(ls -vr ${g_dest} | head -n 1) +chunkid=${chunkid%.clean} +for file in $(find $g_source -type f -size ${g_size}c -printf '%p\n'); do + chunkid=$((chunkid+1)) + mv $file $g_dest/$chunkid +done diff --git a/internal/task/scripts/report.go b/internal/task/scripts/shell/report.sh similarity index 52% rename from internal/task/scripts/report.go rename to internal/task/scripts/shell/report.sh index f6a8f179c..a7fedeaa9 100644 --- a/internal/task/scripts/report.go +++ b/internal/task/scripts/shell/report.sh @@ -1,32 +1,11 @@ -/* - * Copyright (c) 2021 NetEase Inc. - * - * 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. - */ +#!/usr/bin/env bash -/* - * Project: CurveAdm - * Created Date: 2021-12-06 - * Author: Jingli Chen (Wine93) - */ +# Usage: report KIND UUID ROLE +# Example: report curvebs abcdef01234567890 metaserver +# Created Date: 2021-12-06 +# Author: Jingli Chen (Wine93) -package scripts -/* - * Usage: report KIND UUID ROLE - * Example: report curvebs abcdef01234567890 metaserver - */ -var REPORT = ` function rematch() { local s=$1 regex=$2 if [[ $s =~ $regex ]]; then @@ -41,7 +20,7 @@ function fs_usage() { BYTES["GB"] = BYTES["MB"] * 1024 BYTES["TB"] = BYTES["GB"] * 1024 } - { + { if ($0 ~ /all cluster/) { printf ("%0.f", $8 * BYTES[$9]) } @@ -64,4 +43,3 @@ curl -XPOST http://curveadm.aspirer.wang:19302/ \ -d "uuid=$g_uuid" \ -d "role=$g_role" \ -d "usage=$g_usage" -` diff --git a/internal/task/scripts/shell/start_nginx.sh b/internal/task/scripts/shell/start_nginx.sh new file mode 100644 index 000000000..a0888f9fa --- /dev/null +++ b/internal/task/scripts/shell/start_nginx.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Created Date: 2022-08-09 +# Author: Jingli Chen (Wine93) + + +g_listen="$1" + +cat << __EOF__ > /etc/nginx/nginx.conf +daemon off; +events { + worker_connections 768; +} +http { + server { + $g_listen + } +} +__EOF__ + +nginx diff --git a/internal/task/scripts/target.go b/internal/task/scripts/shell/target.sh similarity index 64% rename from internal/task/scripts/target.go rename to internal/task/scripts/shell/target.sh index 5767f8540..82d564a86 100644 --- a/internal/task/scripts/target.go +++ b/internal/task/scripts/shell/target.sh @@ -1,35 +1,11 @@ -/* - * Copyright (c) 2021 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2022-02-08 - * Author: Jingli Chen (Wine93) - */ - -package scripts +#!/usr/bin/env bash -/* - * Usage: target USER VOLUME CREATE SIZE - * Example: target curve test true 10 - * See Also: https://linux.die.net/man/8/tgtadm - */ +# Usage: target USER VOLUME CREATE SIZE +# Example: target curve test true 10 +# See Also: https://linux.die.net/man/8/tgtadm +# Created Date: 2022-02-08 +# Author: Jingli Chen (Wine93) -var TARGET = ` -#!/usr/bin/env bash g_user=$1 g_volume=$2 @@ -103,4 +79,3 @@ if [ $? -ne 0 ]; then echo "tgtadm target bind failed" exit 1 fi -` diff --git a/internal/task/scripts/shell/wait.sh b/internal/task/scripts/shell/wait.sh new file mode 100644 index 000000000..41c1c5fbb --- /dev/null +++ b/internal/task/scripts/shell/wait.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Usage: wait ADDR... +# Example: wait 10.0.10.1:2379 10.0.10.2:2379 +# Created Date: 2021-11-25 +# Author: Jingli Chen (Wine93) + + +[[ -z $(which curl) ]] && apt-get install -y curl +wait=0 +while ((wait<20)) +do + for addr in "$@" + do + curl --connect-timeout 3 --max-time 10 $addr -Iso /dev/null + if [ $? == 0 ]; then + exit 0 + fi + done + sleep 0.5s + wait=$(expr $wait + 1) +done +echo "wait timeout" +exit 1 diff --git a/internal/task/scripts/shell/wait_chunkserver.sh b/internal/task/scripts/shell/wait_chunkserver.sh new file mode 100644 index 000000000..303783d72 --- /dev/null +++ b/internal/task/scripts/shell/wait_chunkserver.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Usage: wait_chunkserver 3 +# Created Date: 2022-03-09 +# Author: aspirer + + +g_total="$1" + +wait=0 +while ((wait<60)) +do + online=$(curve_ops_tool chunkserver-status | sed -nr 's/.*online = ([0-9]+).*/\1/p') + if [[ $online -eq $g_total ]]; then + exit 0 + fi + + sleep 0.5s + wait=$((wait+1)) +done + +echo "wait all chunkserver online timeout, total=$g_total, online=$online" +exit 1 diff --git a/internal/task/scripts/wait.go b/internal/task/scripts/wait.go deleted file mode 100644 index 838ee2c46..000000000 --- a/internal/task/scripts/wait.go +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2021 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2021-11-25 - * Author: Jingli Chen (Wine93) - */ - -package scripts - -/* - * Usage: wait ADDR... - * Example: wait 10.0.10.1:2379 10.0.10.2:2379 - */ -var WAIT = ` -[[ -z $(which curl) ]] && apt-get install -y curl -wait=0 -while ((wait<20)) -do - for addr in "$@" - do - curl --connect-timeout 3 --max-time 10 $addr -Iso /dev/null - if [ $? == 0 ]; then - exit 0 - fi - done - sleep 0.5s - wait=$(expr $wait + 1) -done -echo "wait timeout" -exit 1 -` diff --git a/internal/task/scripts/wait_chunkservers.go b/internal/task/scripts/wait_chunkservers.go deleted file mode 100644 index 15109190b..000000000 --- a/internal/task/scripts/wait_chunkservers.go +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2022 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2022-03-09 - * Author: aspirer - */ - -package scripts - -/* - * Usage: no args, just run it in bash - */ -// FIXME(P0): wait not works, return -12 -var WAIT_CHUNKSERVERS = ` -wait=0 -while ((wait<60)) -do - status=$(curve_ops_tool chunkserver-status |grep "offline") - total=$(echo ${status} | grep -c "total num = 0") - offline=$(echo ${status} | grep -c "offline = 0") - if [ ${total} -eq 0 ] && [ ${offline} -eq 1 ]; then - echo "CURVEADM_SUCCESS" - exit 0 - fi - sleep 0.5s - wait=$(expr ${wait} + 1) -done -echo "CURVEADM_TIMEOUT" -exit 1 -` diff --git a/internal/task/step/container.go b/internal/task/step/container.go index 52da2b6e0..0ddd41a1f 100644 --- a/internal/task/step/container.go +++ b/internal/task/step/container.go @@ -31,7 +31,7 @@ import ( ) type ( - DockerInfo struct { + EngineInfo struct { Success *bool Out *string module.ExecOptions @@ -61,7 +61,9 @@ type ( Mount string Name string Network string + User string Pid string + Publish string Privileged bool Remove bool // automatically remove the container when it exits Restart string @@ -154,16 +156,16 @@ type ( } ) -func (s *DockerInfo) Execute(ctx *context.Context) error { +func (s *EngineInfo) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().DockerInfo() out, err := cli.Execute(s.ExecOptions) - return PostHandle(s.Success, s.Out, out, err, errno.ERR_GET_DOCKER_INFO_FAILED) + return PostHandle(s.Success, s.Out, out, err, errno.ERR_GET_CONTAINER_ENGINE_INFO_FAILED.FD("(%s info)", s.ExecWithEngine)) } func (s *PullImage) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().PullImage(s.Image) out, err := cli.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_PULL_IMAGE_FAILED) + return PostHandle(nil, s.Out, out, err, errno.ERR_PULL_IMAGE_FAILED.FD("(%s pull IMAGE)", s.ExecWithEngine)) } func (s *CreateContainer) Execute(ctx *context.Context) error { @@ -203,6 +205,12 @@ func (s *CreateContainer) Execute(ctx *context.Context) error { if len(s.Pid) > 0 { cli.AddOption("--pid %s", s.Pid) } + if len(s.Publish) > 0 { + cli.AddOption("--publish %s", s.Publish) + } + if len(s.User) > 0 { + cli.AddOption("--user %s", s.User) + } if s.Privileged { cli.AddOption("--privileged") } @@ -223,13 +231,13 @@ func (s *CreateContainer) Execute(ctx *context.Context) error { } out, err := cli.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_CREATE_CONTAINER_FAILED) + return PostHandle(nil, s.Out, out, err, errno.ERR_CREATE_CONTAINER_FAILED.FD("(%s create IMAGE)", s.ExecWithEngine)) } func (s *StartContainer) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().StartContainer(*s.ContainerId) out, err := cli.Execute(s.ExecOptions) - return PostHandle(s.Success, s.Out, out, err, errno.ERR_START_CONTAINER_FAILED) + return PostHandle(s.Success, s.Out, out, err, errno.ERR_START_CONTAINER_FAILED.FD("(%s start CONTAINER)", s.ExecWithEngine)) } func (s *StopContainer) Execute(ctx *context.Context) error { @@ -239,25 +247,25 @@ func (s *StopContainer) Execute(ctx *context.Context) error { } out, err := cli.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_STOP_CONTAINER_FAILED) + return PostHandle(nil, s.Out, out, err, errno.ERR_STOP_CONTAINER_FAILED.FD("(%s stop CONTAINER)", s.ExecWithEngine)) } func (s *RestartContainer) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().RestartContainer(s.ContainerId) out, err := cli.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_RESTART_CONTAINER_FAILED) + return PostHandle(nil, s.Out, out, err, errno.ERR_RESTART_CONTAINER_FAILED.FD("(%s restart CONTAINER)", s.ExecWithEngine)) } func (s *WaitContainer) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().WaitContainer(s.ContainerId) out, err := cli.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_WAIT_CONTAINER_STOP_FAILED) + return PostHandle(nil, s.Out, out, err, errno.ERR_WAIT_CONTAINER_STOP_FAILED.FD("(%s wait CONTAINER)", s.ExecWithEngine)) } func (s *RemoveContainer) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().RemoveContainer(s.ContainerId) out, err := cli.Execute(s.ExecOptions) - return PostHandle(s.Success, s.Out, out, err, errno.ERR_REMOVE_CONTAINER_FAILED) + return PostHandle(s.Success, s.Out, out, err, errno.ERR_REMOVE_CONTAINER_FAILED.FD("(%s rm CONTAINER)", s.ExecWithEngine)) } func (s *ListContainers) Execute(ctx *context.Context) error { @@ -276,25 +284,25 @@ func (s *ListContainers) Execute(ctx *context.Context) error { } out, err := cli.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_LIST_CONTAINERS_FAILED) + return PostHandle(nil, s.Out, out, err, errno.ERR_LIST_CONTAINERS_FAILED.FD("(%s ps)", s.ExecWithEngine)) } func (s *ContainerExec) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().ContainerExec(*s.ContainerId, s.Command) out, err := cli.Execute(s.ExecOptions) - return PostHandle(s.Success, s.Out, out, err, errno.ERR_RUN_COMMAND_IN_CONTAINER_FAILED) + return PostHandle(s.Success, s.Out, out, err, errno.ERR_RUN_COMMAND_IN_CONTAINER_FAILED.FD("(%s exec CONTAINER COMMAND)", s.ExecWithEngine)) } func (s *CopyFromContainer) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().CopyFromContainer(s.ContainerId, s.ContainerSrcPath, s.HostDestPath) out, err := cli.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_COPY_FROM_CONTAINER_FAILED) + return PostHandle(nil, s.Out, out, err, errno.ERR_COPY_FROM_CONTAINER_FAILED.FD("(%s cp CONTAINER:SRC_PATH DEST_PATH)", s.ExecWithEngine)) } func (s *CopyIntoContainer) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().CopyIntoContainer(s.HostSrcPath, s.ContainerId, s.ContainerDestPath) out, err := cli.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_COPY_INTO_CONTAINER_FAILED) + return PostHandle(nil, s.Out, out, err, errno.ERR_COPY_INTO_CONTAINER_FAILED.FD("(%s cp SRC_PATH CONTAINER:DEST_PATH)", s.ExecWithEngine)) } func (s *InspectContainer) Execute(ctx *context.Context) error { @@ -304,11 +312,11 @@ func (s *InspectContainer) Execute(ctx *context.Context) error { } out, err := cli.Execute(s.ExecOptions) - return PostHandle(s.Success, s.Out, out, err, errno.ERR_INSPECT_CONTAINER_FAILED) + return PostHandle(s.Success, s.Out, out, err, errno.ERR_INSPECT_CONTAINER_FAILED.FD("(%s inspect ID)", s.ExecWithEngine)) } func (s *ContainerLogs) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().ContainerLogs(s.ContainerId) out, err := cli.Execute(s.ExecOptions) - return PostHandle(s.Success, s.Out, out, err, errno.ERR_GET_CONTAINER_LOGS_FAILED) + return PostHandle(s.Success, s.Out, out, err, errno.ERR_GET_CONTAINER_LOGS_FAILED.FD("(%s logs ID)", s.ExecWithEngine)) } diff --git a/internal/task/step/file.go b/internal/task/step/file.go index 597578308..cfd4fc575 100644 --- a/internal/task/step/file.go +++ b/internal/task/step/file.go @@ -28,6 +28,7 @@ import ( "bufio" "fmt" "os" + "path" "regexp" "strings" @@ -79,11 +80,37 @@ type ( module.ExecOptions } + TrySyncFile struct { + ContainerSrcId *string + ContainerSrcPath string + ContainerDestId *string + ContainerDestPath string + KVFieldSplit string + Mutate func(string, string, string) (string, error) + module.ExecOptions + } + + SyncFileDirectly struct { + ContainerSrcId *string + ContainerSrcPath string + ContainerDestId *string + ContainerDestPath string + IsDir bool + module.ExecOptions + } + DownloadFile struct { RemotePath string LocalPath string module.ExecOptions } + + CreateAndUploadDir struct { + HostDirName string + ContainerDestId *string + ContainerDestPath string + module.ExecOptions + } ) func (s *ReadFile) Execute(ctx *context.Context) error { @@ -97,7 +124,7 @@ func (s *ReadFile) Execute(ctx *context.Context) error { dockerCli := ctx.Module().DockerCli().CopyFromContainer(s.ContainerId, s.ContainerSrcPath, remotePath) _, err := dockerCli.Execute(s.ExecOptions) if err != nil { - return errno.ERR_COPY_FROM_CONTAINER_FAILED.E(err) + return errno.ERR_COPY_FROM_CONTAINER_FAILED.FD("(%s cp CONTAINER:SRC_PATH DEST_PATH)", s.ExecWithEngine).E(err) } } @@ -162,7 +189,7 @@ func (s *InstallFile) Execute(ctx *context.Context) error { cli := ctx.Module().DockerCli().CopyIntoContainer(remotePath, *s.ContainerId, s.ContainerDestPath) _, err = cli.Execute(s.ExecOptions) if err != nil { - return errno.ERR_COPY_INTO_CONTAINER_FAILED.E(err) + return errno.ERR_COPY_INTO_CONTAINER_FAILED.FD(" (%scp SRC_PATH CONTAINER:DEST_PATH)", s.ExecWithEngine).E(err) } } return nil @@ -241,6 +268,79 @@ func (s *SyncFile) Execute(ctx *context.Context) error { return nil } +func (s *SyncFileDirectly) Execute(ctx *context.Context) error { + hostPath := utils.RandFilename(TEMP_DIR) + defer os.RemoveAll(hostPath) + steps := []task.Step{} + steps = append(steps, &CopyFromContainer{ + ContainerId: *s.ContainerSrcId, + ContainerSrcPath: s.ContainerSrcPath, + HostDestPath: hostPath, + ExecOptions: s.ExecOptions, + }) + if s.IsDir { + hostPath = fmt.Sprintf("%s/.", hostPath) + } + steps = append(steps, &CopyIntoContainer{ + HostSrcPath: hostPath, + ContainerId: *s.ContainerDestId, + ContainerDestPath: s.ContainerDestPath, + ExecOptions: s.ExecOptions, + }) + + for _, step := range steps { + err := step.Execute(ctx) + if err != nil { + return err + } + } + return nil +} + func (s *DownloadFile) Execute(ctx *context.Context) error { return ctx.Module().File().Download(s.RemotePath, s.LocalPath) } + +func (s *TrySyncFile) Execute(ctx *context.Context) error { + var input string + step := &ReadFile{ + ContainerId: *s.ContainerSrcId, + ContainerSrcPath: s.ContainerSrcPath, + Content: &input, + ExecOptions: s.ExecOptions, + } + if err := step.Execute(ctx); err != nil { + // no this file + return nil + } + sync := SyncFile{ + ContainerSrcId: s.ContainerSrcId, + ContainerSrcPath: s.ContainerSrcPath, + ContainerDestId: s.ContainerDestId, + ContainerDestPath: s.ContainerDestPath, + KVFieldSplit: s.KVFieldSplit, + Mutate: s.Mutate, + ExecOptions: s.ExecOptions, + } + return sync.Execute(ctx) +} + +func (s *CreateAndUploadDir) Execute(ctx *context.Context) error { + randPath := utils.RandFilename(TEMP_DIR) + hostPath := path.Join(randPath, s.HostDirName) + cmd := ctx.Module().Shell().Mkdir(randPath, hostPath) + _, err := cmd.Execute(s.ExecOptions) + if err != nil { + return errno.ERR_RENAME_FILE_OR_DIRECTORY_FAILED.E(err) + } + step := &CopyIntoContainer{ + HostSrcPath: hostPath, + ContainerId: *s.ContainerDestId, + ContainerDestPath: s.ContainerDestPath, + ExecOptions: s.ExecOptions, + } + err = step.Execute(ctx) + cmd = ctx.Module().Shell().Rmdir(hostPath, randPath) + cmd.Execute(s.ExecOptions) + return err +} diff --git a/internal/task/step/shell.go b/internal/task/step/shell.go index e002e1cac..88a08668d 100644 --- a/internal/task/step/shell.go +++ b/internal/task/step/shell.go @@ -114,6 +114,14 @@ type ( module.ExecOptions } + Tune2FS struct { + Device string + ReservedBlocksPercentage string + Success *bool + Out *string + module.ExecOptions + } + Fuser struct { Names []string Out *string @@ -137,6 +145,15 @@ type ( module.ExecOptions } + BlockId struct { + Device string + Format string + MatchTag string + Success *bool + Out *string + module.ExecOptions + } + // network SocketStatistics struct { Filter string @@ -376,6 +393,16 @@ func (s *UmountFilesystem) Execute(ctx *context.Context) error { return nil } +func (s *Tune2FS) Execute(ctx *context.Context) error { + cmd := ctx.Module().Shell().Tune2FS(s.Device) + if len(s.ReservedBlocksPercentage) > 0 { + cmd.AddOption("-m %s", s.ReservedBlocksPercentage) + } + + out, err := cmd.Execute(s.ExecOptions) + return PostHandle(s.Success, s.Out, out, err, errno.ERR_RESERVE_FILESYSTEM_BLOCKS_FAILED) +} + func (s *Fuser) Execute(ctx *context.Context) error { cmd := ctx.Module().Shell().Fuser(s.Names...) out, err := cmd.Execute(s.ExecOptions) @@ -405,6 +432,19 @@ func (s *ListBlockDevice) Execute(ctx *context.Context) error { return PostHandle(s.Success, s.Out, out, err, errno.ERR_LIST_BLOCK_DEVICES_FAILED) } +func (s *BlockId) Execute(ctx *context.Context) error { + cmd := ctx.Module().Shell().BlkId(s.Device) + if len(s.Format) > 0 { + cmd.AddOption("-o %s", s.Format) + } + if len(s.MatchTag) > 0 { + cmd.AddOption("-s %s", s.MatchTag) + } + + out, err := cmd.Execute(s.ExecOptions) + return PostHandle(s.Success, s.Out, out, err, errno.ERR_GET_BLOCK_DEVICE_UUID_FAILED) +} + // network func (s *SocketStatistics) Execute(ctx *context.Context) error { cmd := ctx.Module().Shell().SocketStatistics(s.Filter) @@ -567,18 +607,20 @@ func (s *Scp) Execute(ctx *context.Context) error { return errno.ERR_WRITE_FILE_FAILED.E(err) } - config := ctx.SSHClient().Config() - cmd := ctx.Module().Shell().Scp(localPath, config.User, config.Host, s.RemotePath) - cmd.AddOption("-P %d", config.Port) - if !config.ForwardAgent { - cmd.AddOption("-i %s", config.PrivateKeyPath) - } + //config := ctx.SSHClient().Config() + //cmd := ctx.Module().Shell().Scp(localPath, config.User, config.Host, s.RemotePath) + //cmd.AddOption("-P %d", config.Port) + //if !config.ForwardAgent { + // cmd.AddOption("-i %s", config.PrivateKeyPath) + //} + + err = ctx.Module().File().Upload(localPath, s.RemotePath) options := s.ExecOptions options.ExecWithSudo = false options.ExecInLocal = true - out, err := cmd.Execute(options) - return PostHandle(nil, nil, out, err, errno.ERR_SECURE_COPY_FILE_TO_REMOTE_FAILED) + //out, err := cmd.Execute(options) + return PostHandle(nil, nil, "", err, errno.ERR_SECURE_COPY_FILE_TO_REMOTE_FAILED) } func (s *Command) Execute(ctx *context.Context) error { diff --git a/internal/task/task/bs/add_target.go b/internal/task/task/bs/add_target.go index a5f3beee5..83a721dd3 100644 --- a/internal/task/task/bs/add_target.go +++ b/internal/task/task/bs/add_target.go @@ -34,12 +34,12 @@ import ( ) type TargetOption struct { - Host string - User string - Volume string - Create bool - Size int - Tid string + Host string + User string + Volume string + Create bool + Size int + Tid string Blocksize uint64 } @@ -52,7 +52,7 @@ func NewAddTargetTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task } subname := fmt.Sprintf("host=%s volume=%s", options.Host, volume) - t := task.NewTask("Add Target", subname, hc.GetSSHConfig()) + t := task.NewTask("Add Target", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var output string @@ -65,7 +65,6 @@ func NewAddTargetTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.ID}} {{.Status}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", DEFAULT_TGTD_CONTAINER_NAME), Out: &output, ExecOptions: curveadm.ExecOptions(), diff --git a/internal/task/task/bs/balance_leader.go b/internal/task/task/bs/balance_leader.go index 2c29f75a7..565688233 100644 --- a/internal/task/task/bs/balance_leader.go +++ b/internal/task/task/bs/balance_leader.go @@ -48,7 +48,7 @@ func NewBalanceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Ta subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Balance Leader", subname, hc.GetSSHConfig()) + t := task.NewTask("Balance Leader", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step t.AddStep(&step.ContainerExec{ diff --git a/internal/task/task/bs/create_volume.go b/internal/task/task/bs/create_volume.go index 41607ba96..44e34e43b 100644 --- a/internal/task/task/bs/create_volume.go +++ b/internal/task/task/bs/create_volume.go @@ -23,6 +23,7 @@ package bs import ( + "encoding/json" "fmt" "strings" @@ -43,6 +44,15 @@ rootUserPassword=root_password ` ) +func checkCreateOption(create bool) step.LambdaType { + return func(ctx *context.Context) error { + if !create { + return task.ERR_SKIP_TASK + } + return nil + } +} + func checkVolumeStatus(out *string) step.LambdaType { return func(ctx *context.Context) error { if len(*out) == 0 { @@ -66,6 +76,28 @@ func checkCreateStatus(out *string) step.LambdaType { } } +func setClientAuxInfo(curveadm *cli.CurveAdm, options MapOptions) step.LambdaType { + return func(ctx *context.Context) error { + volumeId := curveadm.GetVolumeId(options.Host, options.User, options.Volume) + + auxInfo := &AuxInfo{ + User: options.User, + Volume: options.Volume, + Poolset: options.Poolset, + } + bytes, err := json.Marshal(auxInfo) + if err != nil { + return errno.ERR_ENCODE_VOLUME_INFO_TO_JSON_FAILED.E(err) + } + + err = curveadm.Storage().SetClientAuxInfo(volumeId, string(bytes)) + if err != nil { + return errno.ERR_SET_CLIENT_AUX_INFO_FAILED.E(err) + } + return nil + } +} + func NewCreateVolumeTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task.Task, error) { options := curveadm.MemStorage().Get(comm.KEY_MAP_OPTIONS).(MapOptions) hc, err := curveadm.GetHost(options.Host) @@ -74,7 +106,7 @@ func NewCreateVolumeTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*t } subname := fmt.Sprintf("hostname=%s image=%s", hc.GetHostname(), cc.GetContainerImage()) - t := task.NewTask("Create Volume", subname, hc.GetSSHConfig()) + t := task.NewTask("Create Volume", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var out string @@ -83,11 +115,13 @@ func NewCreateVolumeTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*t toolsConf := fmt.Sprintf(FORMAT_TOOLS_CONF, cc.GetClusterMDSAddr()) script := scripts.CREATE_VOLUME scriptPath := "/curvebs/nebd/sbin/create.sh" - command := fmt.Sprintf("/bin/bash %s %s %s %d", scriptPath, options.User, options.Volume, options.Size) + command := fmt.Sprintf("/bin/bash %s %s %s %d %s", scriptPath, options.User, options.Volume, options.Size, options.Poolset) + t.AddStep(&step.Lambda{ + Lambda: checkCreateOption(options.Create), + }) t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.Status}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", containerName), Out: &out, ExecOptions: curveadm.ExecOptions(), @@ -116,6 +150,9 @@ func NewCreateVolumeTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*t t.AddStep(&step.Lambda{ Lambda: checkCreateStatus(&out), }) + t.AddStep(&step.Lambda{ + Lambda: setClientAuxInfo(curveadm, options), + }) return t, nil } diff --git a/internal/task/task/bs/delete_target.go b/internal/task/task/bs/delete_target.go index e5e58cb61..9b86a1736 100644 --- a/internal/task/task/bs/delete_target.go +++ b/internal/task/task/bs/delete_target.go @@ -58,7 +58,7 @@ func NewDeleteTargetTask(curveadm *cli.CurveAdm, cc *client.ClientConfig) (*task } subname := fmt.Sprintf("hostname=%s tid=%s", hc.GetHostname(), options.Tid) - t := task.NewTask("Delete Target", subname, hc.GetSSHConfig()) + t := task.NewTask("Delete Target", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var output string @@ -67,7 +67,6 @@ func NewDeleteTargetTask(curveadm *cli.CurveAdm, cc *client.ClientConfig) (*task t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.ID}} {{.Status}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", DEFAULT_TGTD_CONTAINER_NAME), Out: &output, ExecOptions: curveadm.ExecOptions(), diff --git a/internal/task/task/bs/detect_release.go b/internal/task/task/bs/detect_release.go index b1cb0a23a..e61ce8da3 100644 --- a/internal/task/task/bs/detect_release.go +++ b/internal/task/task/bs/detect_release.go @@ -75,7 +75,7 @@ func NewDetectOSReleaseTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, var success bool var out string subname := fmt.Sprintf("host=%s", host) - t := task.NewTask("Detect OS Release", subname, hc.GetSSHConfig()) + t := task.NewTask("Detect OS Release", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task t.AddStep(&step.Cat{ diff --git a/internal/task/task/bs/format.go b/internal/task/task/bs/format.go index c630bd5bd..cf7a2b71b 100644 --- a/internal/task/task/bs/format.go +++ b/internal/task/task/bs/format.go @@ -64,9 +64,9 @@ type ( } ) -func skipFormat(containerId *string) step.LambdaType { +func skipFormat(output *string, name string) step.LambdaType { return func(ctx *context.Context) error { - if len(*containerId) > 0 { + if *output == name { return task.ERR_SKIP_TASK } return nil @@ -116,10 +116,10 @@ func (s *step2EditFSTab) execute(ctx *context.Context) error { NoClobber: true, ExecOptions: curveadm.ExecOptions(), }) - steps = append(steps, &step.ListBlockDevice{ // uuid for device - Device: []string{s.device}, - Format: "UUID", - NoHeadings: true, + steps = append(steps, &step.BlockId{ // uuid for device + Device: s.device, + Format: "value", + MatchTag: "UUID", Success: &success, Out: &s.uuid, ExecOptions: curveadm.ExecOptions(), @@ -178,37 +178,40 @@ func NewFormatChunkfilePoolTask(curveadm *cli.CurveAdm, fc *configure.FormatConf device := fc.GetDevice() mountPoint := fc.GetMountPoint() usagePercent := fc.GetFormatPercent() + blockSize := fc.GetBlockSize() + chunkSize := fc.GetChunkSize() subname := fmt.Sprintf("host=%s device=%s mountPoint=%s usage=%d%%", fc.GetHost(), device, mountPoint, usagePercent) - t := task.NewTask("Start Format Chunkfile Pool", subname, hc.GetSSHConfig()) + t := task.NewTask("Start Format Chunkfile Pool", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task - var oldContainerId, containerId, oldUUID string + var output, containerId, oldUUID string + var success bool containerName := device2ContainerName(device) layout := topology.GetCurveBSProjectLayout() chunkfilePoolRootDir := layout.ChunkfilePoolRootDir - formatScript := scripts.SCRIPT_FORMAT + formatScript := scripts.FORMAT formatScriptPath := fmt.Sprintf("%s/format.sh", layout.ToolsBinDir) - formatCommand := fmt.Sprintf("%s %s %d %d %s %s", formatScriptPath, layout.FormatBinaryPath, - usagePercent, DEFAULT_CHUNKFILE_SIZE, layout.ChunkfilePoolDir, layout.ChunkfilePoolMetaPath) + formatCommand := fmt.Sprintf("%s %s %d %d %s %s %d", formatScriptPath, layout.FormatBinaryPath, + usagePercent, chunkSize, layout.ChunkfilePoolDir, layout.ChunkfilePoolMetaPath, blockSize) // 1: skip if formating container exist t.AddStep(&step.ListContainers{ ShowAll: true, - Format: "'{{.ID}}'", - Quiet: true, + Format: "'{{.Names}}'", Filter: fmt.Sprintf("name=%s", containerName), - Out: &oldContainerId, + Out: &output, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: skipFormat(&oldContainerId), + Lambda: skipFormat(&output, containerName), }) - // 2: mkfs, mount device, edit fstab - t.AddStep(&step.ListBlockDevice{ - Device: []string{device}, - Format: "UUID", - NoHeadings: true, + // 2: mkfs, mount device, edit fstab, tune2fs + t.AddStep(&step.BlockId{ + Device: device, + Format: "value", + MatchTag: "UUID", + Success: &success, Out: &oldUUID, ExecOptions: curveadm.ExecOptions(), }) @@ -238,6 +241,11 @@ func NewFormatChunkfilePoolTask(curveadm *cli.CurveAdm, fc *configure.FormatConf mountPoint: mountPoint, curveadm: curveadm, }) + t.AddStep(&step.Tune2FS{ // tune2fs -m 0 DEVICE + Device: device, + ReservedBlocksPercentage: "0", + ExecOptions: curveadm.ExecOptions(), + }) // 3: run container to format chunkfile pool t.AddStep(&step.PullImage{ Image: fc.GetContainerImage(), diff --git a/internal/task/task/bs/format_status.go b/internal/task/task/bs/format_status.go index 121dd80b9..396f5d6e3 100644 --- a/internal/task/task/bs/format_status.go +++ b/internal/task/task/bs/format_status.go @@ -26,10 +26,10 @@ import ( "fmt" "strings" - comm "github.com/opencurve/curveadm/internal/common" - "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/cli/cli" + comm "github.com/opencurve/curveadm/internal/common" "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/internal/task/context" "github.com/opencurve/curveadm/internal/task/step" "github.com/opencurve/curveadm/internal/task/task" @@ -122,7 +122,7 @@ func NewGetFormatStatusTask(curveadm *cli.CurveAdm, fc *configure.FormatConfig) // new task device := fc.GetDevice() subname := fmt.Sprintf("host=%s device=%s", fc.GetHost(), fc.GetDevice()) - t := task.NewTask("Get Format Status", subname, hc.GetSSHConfig()) + t := task.NewTask("Get Format Status", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var deviceUsage, containerStatus string diff --git a/internal/task/task/bs/format_stop.go b/internal/task/task/bs/format_stop.go index 424b1ec2a..25fdffc0d 100644 --- a/internal/task/task/bs/format_stop.go +++ b/internal/task/task/bs/format_stop.go @@ -79,16 +79,16 @@ func NewStopFormatTask(curveadm *cli.CurveAdm, fc *configure.FormatConfig) (*tas containerName := device2ContainerName(device) subname := fmt.Sprintf("host=%s device=%s mountPoint=%s containerName=%s", fc.GetHost(), device, mountPoint, containerName) - t := task.NewTask("Stop Format Chunkfile Pool", subname, hc.GetSSHConfig()) + t := task.NewTask("Stop Format Chunkfile Pool", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) var oldContainerId string var oldUUID string // 1: list block device and edit fstab delete record - t.AddStep(&step.ListBlockDevice{ - Device: []string{device}, - Format: "UUID", - NoHeadings: true, + t.AddStep(&step.BlockId{ + Device: device, + Format: "value", + MatchTag: "UUID", Out: &oldUUID, ExecOptions: curveadm.ExecOptions(), }) @@ -105,7 +105,6 @@ func NewStopFormatTask(curveadm *cli.CurveAdm, fc *configure.FormatConfig) (*tas t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.ID}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", containerName), Out: &oldContainerId, ExecOptions: curveadm.ExecOptions(), diff --git a/internal/task/task/bs/install_polarfs.go b/internal/task/task/bs/install_polarfs.go index 9b7976d36..a43cbe0b9 100644 --- a/internal/task/task/bs/install_polarfs.go +++ b/internal/task/task/bs/install_polarfs.go @@ -104,7 +104,7 @@ func NewInstallPolarFSTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) ( // new task release := getRelease(curveadm) subname := fmt.Sprintf("host=%s release=%s", host, release) - t := task.NewTask("Install PolarFS", subname, hc.GetSSHConfig()) + t := task.NewTask("Install PolarFS", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var input, output string diff --git a/internal/task/task/bs/list_targets.go b/internal/task/task/bs/list_targets.go index ccdd618ad..7ce2412dc 100644 --- a/internal/task/task/bs/list_targets.go +++ b/internal/task/task/bs/list_targets.go @@ -72,13 +72,14 @@ func addTarget(memStorage *utils.SafeMap, id string, target *Target) { /* Output Example: Target 3: iqn.2022-02.com.opencurve:curve.wine93/test03 - ... - LUN information: - LUN: 0 - ... - LUN: 1 - ... - Backing store path: cbd:pool//test03_wine93_ + + ... + LUN information: + LUN: 0 + ... + LUN: 1 + ... + Backing store path: cbd:pool//test03_wine93_ */ func (s *step2FormatTarget) Execute(ctx *context.Context) error { output := *s.output @@ -91,7 +92,7 @@ func (s *step2FormatTarget) Execute(ctx *context.Context) error { mu := titlePattern.FindStringSubmatch(line) if len(mu) > 0 { target = &Target{ - Host: s.host, + Host: s.host, Tid: mu[1], Name: mu[2], Store: "-", @@ -118,7 +119,7 @@ func NewListTargetsTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, erro } subname := fmt.Sprintf("host=%s", hc.GetHostname()) - t := task.NewTask("List Targets", subname, hc.GetSSHConfig()) + t := task.NewTask("List Targets", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var output string @@ -127,7 +128,6 @@ func NewListTargetsTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, erro t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.ID}} {{.Status}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", DEFAULT_TGTD_CONTAINER_NAME), Out: &output, ExecOptions: curveadm.ExecOptions(), diff --git a/internal/task/task/bs/map.go b/internal/task/task/bs/map.go index 2a925ebf3..68eb0f6af 100644 --- a/internal/task/task/bs/map.go +++ b/internal/task/task/bs/map.go @@ -36,6 +36,12 @@ import ( "github.com/opencurve/curveadm/internal/task/task" ) +const ( + TOOLS_V2_CONFIG_DELIMITER = ": " + TOOLS_V2_CONFIG_SRC_PATH = "/curvebs/conf/curve.yaml" + TOOLS_V2_CONFIG_DEST_PATH = "/etc/curve/curve.yaml" +) + type ( MapOptions struct { Host string @@ -44,6 +50,7 @@ type ( Create bool Size int NoExclusive bool + Poolset string } ) @@ -72,7 +79,7 @@ func NewMapTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task.Task, } subname := fmt.Sprintf("hostname=%s volume=%s:%s", hc.GetHostname(), options.User, options.Volume) - t := task.NewTask("Map Volume", subname, hc.GetSSHConfig()) + t := task.NewTask("Map Volume", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var out string @@ -87,7 +94,6 @@ func NewMapTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task.Task, t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.Status}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", containerName), Out: &out, ExecOptions: curveadm.ExecOptions(), @@ -115,6 +121,15 @@ func NewMapTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task.Task, ContainerDestPath: scriptPath, ExecOptions: curveadm.ExecOptions(), }) + t.AddStep(&step.TrySyncFile{ // sync tools-v2 config + ContainerSrcId: &containerId, + ContainerSrcPath: TOOLS_V2_CONFIG_SRC_PATH, + ContainerDestId: &containerId, + ContainerDestPath: TOOLS_V2_CONFIG_DEST_PATH, + KVFieldSplit: TOOLS_V2_CONFIG_DELIMITER, + Mutate: newMutate(cc, TOOLS_V2_CONFIG_DELIMITER), + ExecOptions: curveadm.ExecOptions(), + }) t.AddStep(&step.ContainerExec{ ContainerId: &containerId, Command: command, diff --git a/internal/task/task/bs/start_nebd.go b/internal/task/task/bs/start_nebd.go index aaee80172..e2a2eef5c 100644 --- a/internal/task/task/bs/start_nebd.go +++ b/internal/task/task/bs/start_nebd.go @@ -51,9 +51,10 @@ type ( } AuxInfo struct { - User string `json:"user"` - Volume string `json:"volume,"` - Config string `json:"config,omitempty"` // TODO(P1) + User string `json:"user"` + Volume string `json:"volume"` + Poolset string `json:"poolset"` + Config string `json:"config,omitempty"` // TODO(P1) } ) @@ -65,9 +66,9 @@ func volume2ContainerName(user, volume string) string { return fmt.Sprintf("curvebs-volume-%s", utils.MD5Sum(formatImage(user, volume))) } -func checkVolumeExist(volume string, containerId *string) step.LambdaType { +func checkVolumeExist(volume, containerName string, out *string) step.LambdaType { return func(ctx *context.Context) error { - if len(*containerId) > 0 { + if len(*out) > 0 && *out == containerName { return errno.ERR_VOLUME_ALREADY_MAPPED. F("volume: %s", volume) } @@ -122,8 +123,9 @@ func (s *step2InsertClient) Execute(ctx *context.Context) error { volumeId := curveadm.GetVolumeId(options.Host, options.User, options.Volume) auxInfo := &AuxInfo{ - User: options.User, - Volume: options.Volume, + User: options.User, + Volume: options.Volume, + Poolset: options.Poolset, } bytes, err := json.Marshal(auxInfo) if err != nil { @@ -135,6 +137,12 @@ func (s *step2InsertClient) Execute(ctx *context.Context) error { if err != nil { return errno.ERR_INSERT_CLIENT_FAILED.E(err) } + + err = curveadm.Storage().InsertClientConfig(volumeId, config.GetData()) + if err != nil { + return errno.ERR_INSERT_CLIENT_CONFIG_FAILED.E(err) + } + return nil } @@ -146,7 +154,7 @@ func NewStartNEBDServiceTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) } subname := fmt.Sprintf("hostname=%s image=%s", hc.GetHostname(), cc.GetContainerImage()) - t := task.NewTask("Start NEBD Service", subname, hc.GetSSHConfig()) + t := task.NewTask("Start NEBD Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var containerId, out string @@ -156,24 +164,23 @@ func NewStartNEBDServiceTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) hostname := containerName host2addr := fmt.Sprintf("%s:%s", hostname, hc.GetHostname()) - t.AddStep(&step.DockerInfo{ + t.AddStep(&step.EngineInfo{ Success: &success, Out: &out, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checker.CheckDockerInfo(options.Host, &success, &out), + Lambda: checker.CheckEngineInfo(options.Host, curveadm.ExecOptions().ExecWithEngine, &success, &out), }) t.AddStep(&step.ListContainers{ ShowAll: true, - Format: "'{{.ID}}'", - Quiet: true, + Format: "'{{.Names}}'", Filter: fmt.Sprintf("name=%s", containerName), - Out: &containerId, + Out: &out, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checkVolumeExist(volume, &containerId), + Lambda: checkVolumeExist(volume, containerName, &out), }) t.AddStep(&step.CreateDirectory{ Paths: []string{cc.GetLogDir(), cc.GetDataDir()}, diff --git a/internal/task/task/bs/start_tgtd.go b/internal/task/task/bs/start_tgtd.go index 0aa917149..cca7005dd 100644 --- a/internal/task/task/bs/start_tgtd.go +++ b/internal/task/task/bs/start_tgtd.go @@ -66,7 +66,7 @@ func NewStartTargetDaemonTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig // new task subname := fmt.Sprintf("host=%s image=%s", options.Host, cc.GetContainerImage()) - t := task.NewTask("Start Target Daemon", subname, hc.GetSSHConfig()) + t := task.NewTask("Start Target Daemon", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var status, containerId, out string @@ -77,7 +77,6 @@ func NewStartTargetDaemonTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.Status}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", DEFAULT_TGTD_CONTAINER_NAME), Out: &status, ExecOptions: curveadm.ExecOptions(), diff --git a/internal/task/task/bs/stop_tgtd.go b/internal/task/task/bs/stop_tgtd.go index 1531bd71a..c65130cf9 100644 --- a/internal/task/task/bs/stop_tgtd.go +++ b/internal/task/task/bs/stop_tgtd.go @@ -50,14 +50,13 @@ func NewStopTargetDaemonTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, // new task subname := fmt.Sprintf("host=%s", options.Host) - t := task.NewTask("Stop Target Daemon", subname, hc.GetSSHConfig()) + t := task.NewTask("Stop Target Daemon", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var containerId string t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.ID}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", DEFAULT_TGTD_CONTAINER_NAME), Out: &containerId, ExecOptions: curveadm.ExecOptions(), diff --git a/internal/task/task/bs/uninstall_polarfs.go b/internal/task/task/bs/uninstall_polarfs.go index c228403ca..c89d98547 100644 --- a/internal/task/task/bs/uninstall_polarfs.go +++ b/internal/task/task/bs/uninstall_polarfs.go @@ -77,7 +77,7 @@ func NewUninstallPolarFSTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, // new task release := getRelease(curveadm) subname := fmt.Sprintf("host=%s release=%s", host, release) - t := task.NewTask("Uninstall PolarFS", subname, hc.GetSSHConfig()) + t := task.NewTask("Uninstall PolarFS", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task t.AddStep(&step.RemoveFile{ diff --git a/internal/task/task/bs/unmap.go b/internal/task/task/bs/unmap.go index 9e1740f4a..b04fea22e 100644 --- a/internal/task/task/bs/unmap.go +++ b/internal/task/task/bs/unmap.go @@ -26,13 +26,13 @@ import ( "fmt" "strings" - tui "github.com/opencurve/curveadm/internal/tui/common" "github.com/opencurve/curveadm/cli/cli" comm "github.com/opencurve/curveadm/internal/common" "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/internal/task/context" "github.com/opencurve/curveadm/internal/task/step" "github.com/opencurve/curveadm/internal/task/task" + tui "github.com/opencurve/curveadm/internal/tui/common" "github.com/opencurve/curveadm/pkg/module" ) @@ -121,6 +121,12 @@ func (s *step2DeleteClient) Execute(ctx *context.Context) error { if err != nil { return errno.ERR_DELETE_CLIENT_FAILED.E(err) } + + err = s.curveadm.Storage().DeleteClientConfig(s.volumeId) + if err != nil { + return errno.ERR_DELETE_CLIENT_CONFIG_FAILED.E(err) + } + return nil } @@ -138,7 +144,7 @@ func NewUnmapTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { subname := fmt.Sprintf("hostname=%s volume=%s:%s containerId=%s", hc.GetHostname(), options.User, options.Volume, tui.TrimContainerId(containerId)) - t := task.NewTask("Unmap Volume", subname, hc.GetSSHConfig()) + t := task.NewTask("Unmap Volume", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var output string @@ -148,7 +154,6 @@ func NewUnmapTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.ID}} {{.Status}}'", - Quiet: true, Filter: fmt.Sprintf("id=%s", containerId), Out: &output, ExecOptions: curveadm.ExecOptions(), diff --git a/internal/task/task/checker/common.go b/internal/task/task/checker/common.go index e9830da80..06ed34eba 100644 --- a/internal/task/task/checker/common.go +++ b/internal/task/task/checker/common.go @@ -126,7 +126,7 @@ func getServiceListenAddresses(dc *topology.DeployConfig) []Address { if dc.GetEnableExternalServer() { address = append(address, Address{ Role: ROLE_CHUNKSERVER, - IP: dc.GetListenIp(), + IP: dc.GetListenExternalIp(), Port: dc.GetListenExternalPort(), }) } diff --git a/internal/task/task/checker/date.go b/internal/task/task/checker/date.go index 41a4900aa..95777db2a 100644 --- a/internal/task/task/checker/date.go +++ b/internal/task/task/checker/date.go @@ -87,7 +87,7 @@ func NewGetHostDate(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Ta } subname := fmt.Sprintf("host=%s start=%d", dc.GetHost(), time.Now().Unix()) - t := task.NewTask("Get Host Date ", subname, hc.GetSSHConfig()) + t := task.NewTask("Get Host Date ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) var start int64 var out string @@ -132,7 +132,7 @@ func checkDate(curveadm *cli.CurveAdm) step.LambdaType { } func NewCheckDate(curveadm *cli.CurveAdm, c interface{}) (*task.Task, error) { - t := task.NewTask("Check Host Date ", "", nil) + t := task.NewTask("Check Host Date ", "", nil, nil) t.AddStep(&step.Lambda{ Lambda: checkDate(curveadm), }) diff --git a/internal/task/task/checker/kernel.go b/internal/task/task/checker/kernel.go index 075c8404d..58522f1fc 100644 --- a/internal/task/task/checker/kernel.go +++ b/internal/task/task/checker/kernel.go @@ -42,7 +42,7 @@ import ( const ( CHUNKSERVER_LEAST_KERNEL_VERSION = "3.15.0" - REGEX_KERNEL_VAERSION = "^(\\d+\\.\\d+\\.\\d+)(-.+)?$" + REGEX_KERNEL_VAERSION = "^(\\d+\\.\\d+\\.\\d+)(?:[-_].+)?$" ) func calcKernelVersion(version string) int { @@ -106,7 +106,7 @@ func NewCheckKernelVersionTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig // new task subname := fmt.Sprintf("host=%s role=%s require=(>=%s)", dc.GetHost(), dc.GetRole(), CHUNKSERVER_LEAST_KERNEL_VERSION) - t := task.NewTask("Check Kernel Version ", subname, hc.GetSSHConfig()) + t := task.NewTask("Check Kernel Version ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string @@ -132,7 +132,7 @@ func NewCheckKernelModuleTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig // new task name := curveadm.MemStorage().Get(comm.KEY_CHECK_KERNEL_MODULE_NAME).(string) subname := fmt.Sprintf("host=%s module=%s", host, name) - t := task.NewTask("Check Kernel Module", subname, hc.GetSSHConfig()) + t := task.NewTask("Check Kernel Module", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string diff --git a/internal/task/task/checker/kernel_test.go b/internal/task/task/checker/kernel_test.go index 4f7d3b497..2669e1666 100644 --- a/internal/task/task/checker/kernel_test.go +++ b/internal/task/task/checker/kernel_test.go @@ -39,6 +39,7 @@ func TestCheckKernelVersion(t *testing.T) { }{ {"5.12.0", nil}, {"4.9.65-netease", nil}, + {"4.18.0_80.7.1.el8_0_bch_v1.0", nil}, {"4.19.0-16-amd64", nil}, {"3.15.0", nil}, {"3.15.0.0.", errno.ERR_UNRECOGNIZED_KERNEL_VERSION}, diff --git a/internal/task/task/checker/network.go b/internal/task/task/checker/network.go index 0edcf9142..4c96e1d1a 100644 --- a/internal/task/task/checker/network.go +++ b/internal/task/task/checker/network.go @@ -43,6 +43,7 @@ const ( FORMAT_FILTER_SPORT = "( sport = :%d )" HTTP_SERVER_CONTAINER_NAME = "curveadm-precheck-nginx" + CHECK_PORT_CONTAINER_NAME = "curveadm-precheck-port" ) // TASK: check port in use @@ -53,9 +54,14 @@ func checkPortInUse(success *bool, out *string, host string, port int) step.Lamb } if len(*out) > 0 { + if *out == "RTNETLINK answers: Invalid argument" { + return nil + } + return errno.ERR_PORT_ALREADY_IN_USE. F("host=%s, port=%d", host, port) } + return nil } } @@ -65,12 +71,60 @@ func joinPorts(dc *topology.DeployConfig, addresses []Address) string { for _, address := range addresses { ports = append(ports, strconv.Itoa(address.Port)) } - if dc.GetReplicas() > 1 { // replicas service + if dc.GetInstances() > 1 { // instances service ports = append(ports, "...") } return strings.Join(ports, ",") } +func getCheckPortContainerName(curveadm *cli.CurveAdm, dc *topology.DeployConfig) string { + return fmt.Sprintf("%s-%s-%s", + CHECK_PORT_CONTAINER_NAME, + dc.GetRole(), + curveadm.GetServiceId(dc.GetId())) +} + +type step2CheckPortStatus struct { + containerId *string + success *bool + dc *topology.DeployConfig + curveadm *cli.CurveAdm + port int +} + +// execute the "ss" command within a temporary container +func (s *step2CheckPortStatus) Execute(ctx *context.Context) error { + filter := fmt.Sprintf(FORMAT_FILTER_SPORT, s.port) + cli := ctx.Module().Shell().SocketStatistics(filter) + cli.AddOption("--no-header") + cli.AddOption("--listening") + command, err := cli.String() + if err != nil { + return err + } + + var out string + steps := []task.Step{} + steps = append(steps, &step.ContainerExec{ + ContainerId: s.containerId, + Command: command, + Success: s.success, + Out: &out, + ExecOptions: s.curveadm.ExecOptions(), + }) + steps = append(steps, &step.Lambda{ + Lambda: checkPortInUse(s.success, &out, s.dc.GetHost(), s.port), + }) + + for _, step := range steps { + err := step.Execute(ctx) + if err != nil { + return err + } + } + return nil +} + func NewCheckPortInUseTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { hc, err := curveadm.GetHost(dc.GetHost()) if err != nil { @@ -80,21 +134,37 @@ func NewCheckPortInUseTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* addresses := getServiceListenAddresses(dc) subname := fmt.Sprintf("host=%s role=%s ports={%s}", dc.GetHost(), dc.GetRole(), joinPorts(dc, addresses)) - t := task.NewTask("Check Port In Use ", subname, hc.GetSSHConfig()) + t := task.NewTask("Check Port In Use ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) - var out string + var containerId, out string var success bool + t.AddStep(&step.PullImage{ + Image: dc.GetContainerImage(), + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.CreateContainer{ + Image: dc.GetContainerImage(), + Command: "-c 'sleep infinity'", // keep the container running + Entrypoint: "/bin/bash", + Name: getCheckPortContainerName(curveadm, dc), + Remove: true, + Out: &containerId, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.StartContainer{ + ContainerId: &containerId, + Success: &success, + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + for _, address := range addresses { - t.AddStep(&step.SocketStatistics{ - Filter: fmt.Sprintf(FORMAT_FILTER_SPORT, address.Port), - Listening: true, - NoHeader: true, - Success: &success, - Out: &out, - ExecOptions: curveadm.ExecOptions(), - }) - t.AddStep(&step.Lambda{ - Lambda: checkPortInUse(&success, &out, dc.GetHost(), address.Port), + t.AddStep(&step2CheckPortStatus{ + containerId: &containerId, + success: &success, + dc: dc, + curveadm: curveadm, + port: address.Port, }) } @@ -133,7 +203,7 @@ func NewCheckDestinationReachableTask(curveadm *cli.CurveAdm, dc *topology.Deplo addresses := unique(getServiceConnectAddress(dc, dcs)) subname := fmt.Sprintf("host=%s role=%s ping={%s}", dc.GetHost(), dc.GetRole(), tui.TrimAddress(strings.Join(addresses, ","))) - t := task.NewTask("Check Destination Reachable ", subname, hc.GetSSHConfig()) + t := task.NewTask("Check Destination Reachable ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) var out string var success bool @@ -164,7 +234,7 @@ func getNginxListens(dc *topology.DeployConfig) string { return strings.Join(listens, " ") } -func getContainerName(curveadm *cli.CurveAdm, dc *topology.DeployConfig) string { +func getHTTPServerContainerName(curveadm *cli.CurveAdm, dc *topology.DeployConfig) string { return fmt.Sprintf("%s-%s-%s", HTTP_SERVER_CONTAINER_NAME, dc.GetRole(), @@ -188,7 +258,7 @@ func NewStartHTTPServerTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( addresses := getServiceListenAddresses(dc) subname := fmt.Sprintf("host=%s role=%s ports={%s}", dc.GetHost(), dc.GetRole(), joinPorts(dc, addresses)) - t := task.NewTask("Start Mock HTTP Server ", subname, hc.GetSSHConfig()) + t := task.NewTask("Start Mock HTTP Server ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var containerId, out string @@ -204,7 +274,7 @@ func NewStartHTTPServerTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( Image: dc.GetContainerImage(), Command: command, Entrypoint: "/bin/bash", - Name: getContainerName(curveadm, dc), + Name: getHTTPServerContainerName(curveadm, dc), Remove: true, Out: &containerId, ExecOptions: curveadm.ExecOptions(), @@ -259,7 +329,7 @@ func NewCheckNetworkFirewallTask(curveadm *cli.CurveAdm, dc *topology.DeployConf // add task subname := fmt.Sprintf("host=%s role=%s", dc.GetHost(), dc.GetRole()) - t := task.NewTask("Check Network Firewall ", subname, hc.GetSSHConfig()) + t := task.NewTask("Check Network Firewall ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string @@ -283,7 +353,7 @@ func NewCheckNetworkFirewallTask(curveadm *cli.CurveAdm, dc *topology.DeployConf return t, nil } -// TASK: stop http server +// TASK: stop container type step2StopContainer struct { containerId *string dc *topology.DeployConfig @@ -325,14 +395,26 @@ func NewCleanEnvironmentTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) // new task subname := fmt.Sprintf("host=%s role=%s", dc.GetHost(), dc.GetRole()) - t := task.NewTask("Clean Precheck Environment", subname, hc.GetSSHConfig()) + t := task.NewTask("Clean Precheck Environment", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string t.AddStep(&step.ListContainers{ ShowAll: true, Format: `"{{.ID}}"`, - Filter: fmt.Sprintf("name=%s", getContainerName(curveadm, dc)), + Filter: fmt.Sprintf("name=%s", getCheckPortContainerName(curveadm, dc)), + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step2StopContainer{ + containerId: &out, + dc: dc, + curveadm: curveadm, + }) + t.AddStep(&step.ListContainers{ + ShowAll: true, + Format: `"{{.ID}}"`, + Filter: fmt.Sprintf("name=%s", getHTTPServerContainerName(curveadm, dc)), Out: &out, ExecOptions: curveadm.ExecOptions(), }) diff --git a/internal/task/task/checker/permission.go b/internal/task/task/checker/permission.go index dbe4e0565..a4a116875 100644 --- a/internal/task/task/checker/permission.go +++ b/internal/task/task/checker/permission.go @@ -87,7 +87,7 @@ func checkCreateDirectory(dc *topology.DeployConfig, path string, success *bool, } } -func CheckDockerInfo(host string, success *bool, out *string) step.LambdaType { +func CheckEngineInfo(host, engine string, success *bool, out *string) step.LambdaType { return func(ctx *context.Context) error { if *success { return nil @@ -95,13 +95,13 @@ func CheckDockerInfo(host string, success *bool, out *string) step.LambdaType { *out = strings.ToLower(*out) if strings.Contains(*out, SIGNATURE_COMMAND_NOT_FOUND) { - return errno.ERR_DOCKER_NOT_INSTALLED. + return errno.ERR_CONTAINER_ENGINE_NOT_INSTALLED. F("host=%s\n%s", host, *out) } else if strings.Contains(*out, SIGNATURE_PERMISSION_DENIED) { - return errno.ERR_EXECUTE_DOCKER_COMMAND_PERMISSION_DENIED. + return errno.ERR_EXECUTE_CONTAINER_ENGINE_COMMAND_PERMISSION_DENIED. F("host=%s\n%s", host, *out) } else if strings.Contains(*out, SIGNATURE_PERMISSION_WITH_PASSWORD) { - return errno.ERR_EXECUTE_DOCKER_COMMAND_PERMISSION_DENIED. + return errno.ERR_EXECUTE_CONTAINER_ENGINE_COMMAND_PERMISSION_DENIED. F("host=%s (need password)", host) } else if strings.Contains(*out, SIGNATURE_DOCKER_DEAMON_IS_NOT_RUNNING) { return errno.ERR_DOCKER_DAEMON_IS_NOT_RUNNING. @@ -119,7 +119,7 @@ func NewCheckPermissionTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( // new task subname := fmt.Sprintf("host=%s role=%s", dc.GetHost(), dc.GetRole()) - t := task.NewTask("Check Permission ", subname, hc.GetSSHConfig()) + t := task.NewTask("Check Permission ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out, hostname string @@ -145,7 +145,7 @@ func NewCheckPermissionTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( t.AddStep(&step.Ping{ Destination: &hostname, Count: 1, - Timeout: 1, + Timeout: 1, Success: &success, ExecOptions: curveadm.ExecOptions(), }) @@ -164,14 +164,14 @@ func NewCheckPermissionTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( Lambda: checkCreateDirectory(dc, dir.Path, &success, &out), }) } - // (4) check docker command {exist, permission, running} - t.AddStep(&step.DockerInfo{ + // (4) check docker/podman engine command {exist, permission, running} + t.AddStep(&step.EngineInfo{ Success: &success, Out: &out, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: CheckDockerInfo(dc.GetHost(), &success, &out), + Lambda: CheckEngineInfo(dc.GetHost(), curveadm.ExecOptions().ExecWithEngine, &success, &out), }) return t, nil diff --git a/internal/task/task/checker/service.go b/internal/task/task/checker/service.go index f762f1942..cb19f443a 100644 --- a/internal/task/task/checker/service.go +++ b/internal/task/task/checker/service.go @@ -138,7 +138,7 @@ func NewCheckChunkfilePoolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig } subname := fmt.Sprintf("host=%s role=%s", dc.GetHost(), dc.GetRole()) - t := task.NewTask("Check Chunkfile Pool ", subname, hc.GetSSHConfig()) + t := task.NewTask("Check Chunkfile Pool ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) t.AddStep(&step2CheckChunkfilePool{ dc: dc, @@ -150,7 +150,7 @@ func NewCheckChunkfilePoolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig func NewCheckS3Task(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { subname := fmt.Sprintf("host=%s role=%s", dc.GetHost(), dc.GetRole()) - t := task.NewTask("Check S3", subname, nil) + t := task.NewTask("Check S3", subname, nil, nil) t.AddStep(&step2CheckS3{ s3AccessKey: dc.GetS3AccessKey(), @@ -171,13 +171,13 @@ func NewCheckMdsAddressTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) address := cc.GetClusterMDSAddr() subname := fmt.Sprintf("host=%s address=%s", host, address) - t := task.NewTask("Check MDS Address", subname, hc.GetSSHConfig()) + t := task.NewTask("Check MDS Address", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) return t, nil } func NewClientS3ConfigureTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task.Task, error) { - t := task.NewTask("Check S3 Configure ", "", nil) + t := task.NewTask("Check S3 Configure ", "", nil, nil) t.AddStep(&step2CheckClientS3Configure{ config: cc, diff --git a/internal/task/task/checker/ssh.go b/internal/task/task/checker/ssh.go index 9d0e893bd..c3ea3b2d9 100644 --- a/internal/task/task/checker/ssh.go +++ b/internal/task/task/checker/ssh.go @@ -73,7 +73,7 @@ func NewCheckSSHConnectTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( // new task method := utils.Choose(hc.GetForwardAgent(), "forwardAgent", "privateKey") subname := fmt.Sprintf("host=%s method=%s", dc.GetHost(), method) - t := task.NewTask("Check SSH Connect ", subname, hc.GetSSHConfig()) + t := task.NewTask("Check SSH Connect ", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task t.AddStep(&step.Lambda{ diff --git a/internal/task/task/checker/topology.go b/internal/task/task/checker/topology.go index 9b6c5185e..d28b030ca 100644 --- a/internal/task/task/checker/topology.go +++ b/internal/task/task/checker/topology.go @@ -263,7 +263,7 @@ func NewCheckTopologyTask(curveadm *cli.CurveAdm, null interface{}) (*task.Task, // new task dcs := curveadm.MemStorage().Get(comm.KEY_ALL_DEPLOY_CONFIGS).([]*topology.DeployConfig) subname := fmt.Sprintf("cluster=%s kind=%s", curveadm.ClusterName(), dcs[0].GetKind()) - t := task.NewTask("Check Topology ", subname, nil) + t := task.NewTask("Check Topology ", subname, nil, nil) // add step to task for _, dc := range dcs { diff --git a/internal/task/task/common/backup_etcd.go b/internal/task/task/common/backup_etcd.go index e9aaeb3b7..ba218df44 100644 --- a/internal/task/task/common/backup_etcd.go +++ b/internal/task/task/common/backup_etcd.go @@ -57,7 +57,7 @@ func NewBackupEtcdDataTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Backup Etcd Data", subname, hc.GetSSHConfig()) + t := task.NewTask("Backup Etcd Data", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) t.AddStep(&step.ContainerExec{ ContainerId: &containerId, diff --git a/internal/task/task/common/clean_service.go b/internal/task/task/common/clean_service.go index 47d031112..83f27e598 100644 --- a/internal/task/task/common/clean_service.go +++ b/internal/task/task/common/clean_service.go @@ -61,12 +61,11 @@ type ( execOptions module.ExecOptions } - step2CleanContainer struct { - config *topology.DeployConfig - serviceId string - containerId string - storage *storage.Storage - execOptions module.ExecOptions + Step2CleanContainer struct { + ServiceId string + ContainerId string + Storage *storage.Storage + ExecOptions module.ExecOptions } ) @@ -94,22 +93,22 @@ func (s *step2RecycleChunk) Execute(ctx *context.Context) error { return nil } -func (s *step2CleanContainer) Execute(ctx *context.Context) error { - containerId := s.containerId +func (s *Step2CleanContainer) Execute(ctx *context.Context) error { + containerId := s.ContainerId if len(containerId) == 0 { // container not created return nil } else if containerId == comm.CLEANED_CONTAINER_ID { // container has removed return nil } - cli := ctx.Module().DockerCli().RemoveContainer(s.containerId) - out, err := cli.Execute(s.execOptions) + cli := ctx.Module().DockerCli().RemoveContainer(s.ContainerId) + out, err := cli.Execute(s.ExecOptions) // container has removed if err != nil && !strings.Contains(out, SIGNATURE_CONTAINER_REMOVED) { return err } - return s.storage.SetContainId(s.serviceId, comm.CLEANED_CONTAINER_ID) + return s.Storage.SetContainId(s.ServiceId, comm.CLEANED_CONTAINER_ID) } func getCleanFiles(clean map[string]bool, dc *topology.DeployConfig, recycle bool) []string { @@ -150,21 +149,20 @@ func NewCleanServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*ta recycle := curveadm.MemStorage().Get(comm.KEY_CLEAN_BY_RECYCLE).(bool) subname := fmt.Sprintf("host=%s role=%s containerId=%s clean=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId), strings.Join(only, ",")) - t := task.NewTask("Clean Service", subname, hc.GetSSHConfig()) + t := task.NewTask("Clean Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task clean := utils.Slice2Map(only) files := getCleanFiles(clean, dc, recycle) // directorys which need cleaned - recyleScript := scripts.SCRIPT_RECYCLE + recyleScript := scripts.RECYCLE recyleScriptPath := utils.RandFilename(TEMP_DIR) if dc.GetKind() == topology.KIND_CURVEBS { - t.AddStep(&step.Scp{ - Content: &recyleScript, - RemotePath: recyleScriptPath, - Mode: 0777, - ExecOptions: curveadm.ExecOptions(), - }) + t.AddStep((&step.InstallFile{ + Content: &recyleScript, + HostDestPath: recyleScriptPath, + ExecOptions: curveadm.ExecOptions(), + })) t.AddStep(&step2RecycleChunk{ dc: dc, clean: clean, @@ -177,12 +175,11 @@ func NewCleanServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*ta ExecOptions: curveadm.ExecOptions(), }) if clean[comm.CLEAN_ITEM_CONTAINER] == true { - t.AddStep(&step2CleanContainer{ - config: dc, - serviceId: serviceId, - containerId: containerId, - storage: curveadm.Storage(), - execOptions: curveadm.ExecOptions(), + t.AddStep(&Step2CleanContainer{ + ServiceId: serviceId, + ContainerId: containerId, + Storage: curveadm.Storage(), + ExecOptions: curveadm.ExecOptions(), }) } diff --git a/internal/task/task/common/client_status.go b/internal/task/task/common/client_status.go index 4d4d9a581..4ed1d2ce7 100644 --- a/internal/task/task/common/client_status.go +++ b/internal/task/task/common/client_status.go @@ -27,6 +27,7 @@ import ( "github.com/opencurve/curveadm/cli/cli" comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/internal/storage" "github.com/opencurve/curveadm/internal/task/context" "github.com/opencurve/curveadm/internal/task/step" @@ -35,12 +36,21 @@ import ( "github.com/opencurve/curveadm/internal/utils" ) +const ( + MISSING_CLIENT_CONFIG = "-" +) + type ( + step2InitClientStatus struct { + client storage.Client + cfgPath *string + memStorage *utils.SafeMap + } + step2FormatClientStatus struct { - client storage.Client - containerId string - status *string - memStorage *utils.SafeMap + client storage.Client + status *string + memStorage *utils.SafeMap } ClientStatus struct { @@ -50,9 +60,32 @@ type ( ContainerId string Status string AuxInfo string + CfgPath string } ) +func dumpCfg(curveadm *cli.CurveAdm, id string, cfgPath *string) step.LambdaType { + return func(ctx *context.Context) error { + *cfgPath = MISSING_CLIENT_CONFIG + cfgs, err := curveadm.Storage().GetClientConfig(id) + if err != nil { + return errno.ERR_SELECT_CLIENT_CONFIG_FAILED.E(err) + } else if len(cfgs) == 0 { + return nil + } + + data := cfgs[0].Data + path := utils.RandFilename("/tmp") + err = utils.WriteFile(path, data, 0644) + if err != nil { + return errno.ERR_WRITE_FILE_FAILED.E(err) + } + + *cfgPath = path + return nil + } +} + // TODO(P0): init client status func setClientStatus(memStorage *utils.SafeMap, id string, status ClientStatus) { memStorage.TX(func(kv *utils.SafeMap) error { @@ -67,25 +100,60 @@ func setClientStatus(memStorage *utils.SafeMap, id string, status ClientStatus) }) } -func (s *step2FormatClientStatus) Execute(ctx *context.Context) error { - status := *s.status - if len(status) == 0 { // container losed - status = comm.CLIENT_STATUS_LOSED - } - +func (s *step2InitClientStatus) Execute(ctx *context.Context) error { client := s.client id := client.Id setClientStatus(s.memStorage, id, ClientStatus{ Id: client.Id, Host: client.Host, Kind: client.Kind, - ContainerId: s.containerId, - Status: status, + ContainerId: client.ContainerId, + Status: comm.CLIENT_STATUS_UNKNOWN, AuxInfo: client.AuxInfo, + CfgPath: *s.cfgPath, }) return nil } +func (s *step2FormatClientStatus) Execute(ctx *context.Context) error { + status := *s.status + if len(status) == 0 { // container losed + status = comm.CLIENT_STATUS_LOSED + } + + id := s.client.Id + s.memStorage.TX(func(kv *utils.SafeMap) error { + v := kv.Get(comm.KEY_ALL_CLIENT_STATUS) + m := v.(map[string]ClientStatus) + + // update the status + s := m[id] + s.Status = status + m[id] = s + kv.Set(comm.KEY_ALL_CLIENT_STATUS, m) + return nil + }) + return nil +} + +func NewInitClientStatusTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { + client := v.(storage.Client) + + t := task.NewTask("Init Client Status", "", nil, nil) + + var cfgPath string + t.AddStep(&step.Lambda{ + Lambda: dumpCfg(curveadm, client.Id, &cfgPath), + }) + t.AddStep(&step2InitClientStatus{ + client: client, + cfgPath: &cfgPath, + memStorage: curveadm.MemStorage(), + }) + + return t, nil +} + func NewGetClientStatusTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { client := v.(storage.Client) hc, err := curveadm.GetHost(client.Host) @@ -96,7 +164,7 @@ func NewGetClientStatusTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, containerId := client.ContainerId subname := fmt.Sprintf("host=%s kind=%s containerId=%s", hc.GetHost(), client.Kind, tui.TrimContainerId(containerId)) - t := task.NewTask("Get Client Status", subname, hc.GetSSHConfig()) + t := task.NewTask("Get Client Status", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step var status string @@ -108,10 +176,9 @@ func NewGetClientStatusTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step2FormatClientStatus{ - client: client, - containerId: containerId, - status: &status, - memStorage: curveadm.MemStorage(), + client: client, + status: &status, + memStorage: curveadm.MemStorage(), }) return t, nil diff --git a/internal/task/task/common/collect_client.go b/internal/task/task/common/collect_client.go index f9085cf20..1d8363d77 100644 --- a/internal/task/task/common/collect_client.go +++ b/internal/task/task/common/collect_client.go @@ -47,7 +47,7 @@ func NewCollectClientTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, er containerId := client.ContainerId subname := fmt.Sprintf("host=%s kind=%s containerId=%s", hc.GetHost(), client.Kind, tui.TrimContainerId(containerId)) - t := task.NewTask("Collect Client", subname, hc.GetSSHConfig()) + t := task.NewTask("Collect Client", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string diff --git a/internal/task/task/common/collect_curveadm.go b/internal/task/task/common/collect_curveadm.go index 1cd3cb337..36a3b88d2 100644 --- a/internal/task/task/common/collect_curveadm.go +++ b/internal/task/task/common/collect_curveadm.go @@ -40,9 +40,10 @@ func NewCollectCurveAdmTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( kind := dc.GetKind() subname := fmt.Sprintf("cluster=%s kind=%s", curveadm.ClusterName(), kind) - t := task.NewTask("Collect CurveAdm", subname, nil) + t := task.NewTask("Collect CurveAdm", subname, nil, nil) // add step to task + dbPath := curveadm.Config().GetDBPath() secret := curveadm.MemStorage().Get(comm.KEY_SECRET).(string) urlFormat := curveadm.MemStorage().Get(comm.KEY_SUPPORT_UPLOAD_URL_FORMAT).(string) baseDir := TEMP_DIR @@ -59,11 +60,13 @@ func NewCollectCurveAdmTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( Paths: []string{localPath /*, hostLogDir, hostConfDir*/}, ExecOptions: options, }) - t.AddStep(&step.CopyFile{ - Source: curveadm.DBPath(), - Dest: localPath, - ExecOptions: options, - }) + if len(dbPath) > 0 { // only copy local database (like sqlite) + t.AddStep(&step.CopyFile{ + Source: dbPath, + Dest: localPath, + ExecOptions: options, + }) + } t.AddStep(&step.Tar{ File: localPath, Archive: localTarballPath, diff --git a/internal/task/task/common/collect_service.go b/internal/task/task/common/collect_service.go index 19698aa13..f5581dc1f 100644 --- a/internal/task/task/common/collect_service.go +++ b/internal/task/task/common/collect_service.go @@ -24,6 +24,8 @@ package common import ( "fmt" + "path" + "github.com/opencurve/curveadm/cli/cli" comm "github.com/opencurve/curveadm/internal/common" "github.com/opencurve/curveadm/internal/configure/topology" @@ -32,7 +34,6 @@ import ( "github.com/opencurve/curveadm/internal/task/task" tui "github.com/opencurve/curveadm/internal/tui/common" "github.com/opencurve/curveadm/internal/utils" - "path" ) const ( @@ -92,19 +93,18 @@ func NewCollectServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* // new task subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Collect Service", subname, hc.GetSSHConfig()) + t := task.NewTask("Collect Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string - //var files []string secret := curveadm.MemStorage().Get(comm.KEY_SECRET).(string) urlFormat := curveadm.MemStorage().Get(comm.KEY_SUPPORT_UPLOAD_URL_FORMAT).(string) baseDir := TEMP_DIR vname := utils.NewVariantName(fmt.Sprintf("%s_%s", serviceId, utils.RandString(5))) remoteSaveDir := fmt.Sprintf("%s/%s", baseDir, vname.Name) // /tmp/7b510fb63730_ox1fe remoteTarbllPath := path.Join(baseDir, vname.CompressName) // /tmp/7b510fb63730_ox1fe.tar.gz - localTarballPath := path.Join(baseDir, vname.CompressName) // /tmp/7b510fb63730_ox1fe.tar.gz - localEncryptdTarballPath := path.Join(baseDir, vname.EncryptCompressName) // // /tmp/7b510fb63730_ox1fe-encrypted.tar.gz + localTarballPath := path.Join(baseDir, vname.LocalCompressName) // /tmp/7b510fb63730_ox1fe.local.tar.gz + localEncryptdTarballPath := path.Join(baseDir, vname.EncryptCompressName) // /tmp/7b510fb63730_ox1fe-encrypted.tar.gz httpSavePath := path.Join("/", encodeSecret(secret), "service", dc.GetRole()) layout := dc.GetProjectLayout() containerLogDir := layout.ServiceLogDir // /curvebs/etcd/logs @@ -113,7 +113,7 @@ func NewCollectServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* localOptions.ExecInLocal = true t.AddStep(&step.CreateDirectory{ - Paths: []string{remoteSaveDir /*, hostLogDir, hostConfDir*/}, + Paths: []string{remoteSaveDir}, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step2CopyFilesFromContainer{ // copy logs directory diff --git a/internal/task/task/common/create_container.go b/internal/task/task/common/create_container.go index 0f7bf6f81..aacbf1089 100644 --- a/internal/task/task/common/create_container.go +++ b/internal/task/task/common/create_container.go @@ -44,22 +44,22 @@ const ( POLICY_NEVER_RESTART = "no" ) -type step2GetService struct { - serviceId string - containerId *string - storage *storage.Storage +type Step2GetService struct { + ServiceId string + ContainerId *string + Storage *storage.Storage } -type step2InsertService struct { - clusterId int - serviceId string - containerId *string - oldContainerId *string - storage *storage.Storage +type Step2InsertService struct { + ClusterId int + ServiceId string + ContainerId *string + OldContainerId *string + Storage *storage.Storage } -func (s *step2GetService) Execute(ctx *context.Context) error { - containerId, err := s.storage.GetContainerId(s.serviceId) +func (s *Step2GetService) Execute(ctx *context.Context) error { + containerId, err := s.Storage.GetContainerId(s.ServiceId) if err != nil { return errno.ERR_GET_SERVICE_CONTAINER_ID_FAILED.E(err) @@ -69,28 +69,28 @@ func (s *step2GetService) Execute(ctx *context.Context) error { return task.ERR_SKIP_TASK } - *s.containerId = containerId + *s.ContainerId = containerId return nil } -func (s *step2InsertService) E(e error, ec *errno.ErrorCode) error { +func (s *Step2InsertService) E(e error, ec *errno.ErrorCode) error { if e == nil { return nil } return ec.E(e) } -func (s *step2InsertService) Execute(ctx *context.Context) error { +func (s *Step2InsertService) Execute(ctx *context.Context) error { var err error - serviceId := s.serviceId - clusterId := s.clusterId - oldContainerId := *s.oldContainerId - containerId := *s.containerId + serviceId := s.ServiceId + clusterId := s.ClusterId + oldContainerId := *s.OldContainerId + containerId := *s.ContainerId if oldContainerId == comm.CLEANED_CONTAINER_ID { // container cleaned - err = s.storage.SetContainId(serviceId, containerId) + err = s.Storage.SetContainId(serviceId, containerId) err = s.E(err, errno.ERR_SET_SERVICE_CONTAINER_ID_FAILED) } else { - err = s.storage.InsertService(clusterId, serviceId, containerId) + err = s.Storage.InsertService(clusterId, serviceId, containerId) err = s.E(err, errno.ERR_INSERT_SERVICE_CONTAINER_ID_FAILED) } @@ -198,7 +198,7 @@ func getRestartPolicy(dc *topology.DeployConfig) string { return POLICY_NEVER_RESTART } -func trimContainerId(containerId *string) step.LambdaType { +func TrimContainerId(containerId *string) step.LambdaType { return func(ctx *context.Context) error { items := strings.Split(*containerId, "\n") *containerId = items[len(items)-1] @@ -214,7 +214,7 @@ func NewCreateContainerTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( // new task subname := fmt.Sprintf("host=%s role=%s", dc.GetHost(), dc.GetRole()) - t := task.NewTask("Create Container", subname, hc.GetSSHConfig()) + t := task.NewTask("Create Container", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var oldContainerId, containerId string @@ -227,10 +227,10 @@ func NewCreateContainerTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( options := curveadm.ExecOptions() options.ExecWithSudo = false - t.AddStep(&step2GetService{ // if service exist, break task - serviceId: serviceId, - containerId: &oldContainerId, - storage: curveadm.Storage(), + t.AddStep(&Step2GetService{ // if service exist, break task + ServiceId: serviceId, + ContainerId: &oldContainerId, + Storage: curveadm.Storage(), }) t.AddStep(&step.CreateDirectory{ Paths: []string{dc.GetLogDir(), dc.GetDataDir()}, @@ -252,14 +252,14 @@ func NewCreateContainerTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ( ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: trimContainerId(&containerId), + Lambda: TrimContainerId(&containerId), }) - t.AddStep(&step2InsertService{ - clusterId: clusterId, - serviceId: serviceId, - containerId: &containerId, - oldContainerId: &oldContainerId, - storage: curveadm.Storage(), + t.AddStep(&Step2InsertService{ + ClusterId: clusterId, + ServiceId: serviceId, + ContainerId: &containerId, + OldContainerId: &oldContainerId, + Storage: curveadm.Storage(), }) return t, nil diff --git a/internal/task/task/common/create_pool.go b/internal/task/task/common/create_pool.go index 02c017a01..aac7f8fc5 100644 --- a/internal/task/task/common/create_pool.go +++ b/internal/task/task/common/create_pool.go @@ -48,7 +48,15 @@ type step2SetClusterPool struct { storage *storage.Storage } +func getPoolset(curveadm *cli.CurveAdm, kind string) configure.Poolset { + if kind == configure.KIND_CURVEFS { + return configure.Poolset{} + } + return curveadm.MemStorage().Get(comm.KEY_POOLSET).(configure.Poolset) +} + func getClusterPool(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (configure.CurveClusterTopo, error) { + poolset := getPoolset(curveadm, dc.GetKind()) oldPool := configure.CurveClusterTopo{} dcs, err := curveadm.ParseTopology() if err != nil { @@ -58,7 +66,7 @@ func getClusterPool(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (configur // 1) generate a new default pool data := curveadm.ClusterPoolData() if len(data) == 0 { - return configure.GenerateDefaultClusterPool(dcs) + return configure.GenerateDefaultClusterPool(dcs, poolset) } // 2) OR change old pool and return it @@ -66,7 +74,7 @@ func getClusterPool(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (configur if err != nil { return oldPool, err } - pool, err := configure.GenerateDefaultClusterPool(dcs) + pool, err := configure.GenerateDefaultClusterPool(dcs, poolset) if err != nil { return pool, err } @@ -98,7 +106,8 @@ func prepare(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (clusterPoolJson // 2. scale out cluster or migrate servers if curveadm.MemStorage().Get(comm.KEY_SCALE_OUT_CLUSTER) != nil { // scale out cluster dcs := curveadm.MemStorage().Get(comm.KEY_SCALE_OUT_CLUSTER).([]*topology.DeployConfig) - configure.ScaleOutClusterPool(&clusterPool, dcs) + poolset := getPoolset(curveadm, dc.GetKind()) + configure.ScaleOutClusterPool(&clusterPool, dcs, poolset) } else if curveadm.MemStorage().Get(comm.KEY_MIGRATE_SERVERS) != nil { // migrate servers migrates := curveadm.MemStorage().Get(comm.KEY_MIGRATE_SERVERS).([]*configure.MigrateServer) configure.MigrateClusterServer(&clusterPool, migrates) @@ -187,11 +196,11 @@ func NewCreateTopologyTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* // new task pooltype := curveadm.MemStorage().Get(comm.KEY_CREATE_POOL_TYPE).(string) - name := utils.Choose(pooltype == comm.POOL_TYPE_LOGICAL, "Create Logical Pool", - "Create Physical Pool") + name := utils.Choose(pooltype == comm.POOL_TYPE_LOGICAL, + "Create Logical Pool", "Create Physical Pool") subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask(name, subname, hc.GetSSHConfig()) + t := task.NewTask(name, subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var success bool @@ -199,7 +208,7 @@ func NewCreateTopologyTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* host, role := dc.GetHost(), dc.GetRole() layout := dc.GetProjectLayout() poolJSONPath := fmt.Sprintf("%s/topology.json", layout.ToolsConfDir) - waitScript := scripts.SCRIPT_WAIT + waitScript := scripts.WAIT waitScriptPath := fmt.Sprintf("%s/wait.sh", layout.ToolsBinDir) clusterPoolJson, clusterMDSAddrs, err := prepare(curveadm, dc) if err != nil { @@ -216,7 +225,7 @@ func NewCreateTopologyTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checkContainerExist(host, role, containerId, &out), + Lambda: CheckContainerExist(host, role, containerId, &out), }) t.AddStep(&step.InstallFile{ // install curvebs/curvefs topology ContainerId: &containerId, @@ -242,8 +251,9 @@ func NewCreateTopologyTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* }) if dc.GetKind() == topology.KIND_CURVEBS && pooltype == comm.POOL_TYPE_LOGICAL { - waitChunkserversScript := scripts.SCRIPT_WAIT_CHUNKSERVERS + waitChunkserversScript := scripts.WAIT_CHUNKSERVERS waitChunkserversScriptPath := fmt.Sprintf("%s/wait_chunkservers.sh", layout.ToolsBinDir) + nchunkserver := curveadm.MemStorage().Get(comm.KEY_NUMBER_OF_CHUNKSERVER).(int) t.AddStep(&step.InstallFile{ // install wait_chunkservers script ContainerId: &containerId, ContainerDestPath: waitChunkserversScriptPath, @@ -252,7 +262,7 @@ func NewCreateTopologyTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* }) t.AddStep(&step.ContainerExec{ // wait all chunkservers online before create logical pool ContainerId: &containerId, - Command: fmt.Sprintf("bash %s", waitChunkserversScriptPath), + Command: fmt.Sprintf("bash %s %d", waitChunkserversScriptPath, nchunkserver), Success: &success, Out: &out, ExecOptions: curveadm.ExecOptions(), diff --git a/internal/task/task/common/etcd_auth_enable.go b/internal/task/task/common/etcd_auth_enable.go new file mode 100644 index 000000000..79280feac --- /dev/null +++ b/internal/task/task/common/etcd_auth_enable.go @@ -0,0 +1,106 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-08-02 +* Author: wanghai (SeanHai) + */ + +package common + +import ( + "fmt" + + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure/topology" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/task/context" + "github.com/opencurve/curveadm/internal/task/scripts" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" + tui "github.com/opencurve/curveadm/internal/tui/common" +) + +func checkEnableEtcdAuthStatus(success *bool, out *string) step.LambdaType { + return func(ctx *context.Context) error { + if !*success { + return errno.ERR_ENABLE_ETCD_AUTH_FAILED.S(*out) + } + return nil + } +} + +func NewEnableEtcdAuthTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(dc.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if curveadm.IsSkip(dc) { + return nil, nil + } else if err != nil { + return nil, err + } + hc, err := curveadm.GetHost(dc.GetHost()) + if err != nil { + return nil, err + } + + var success bool + var out string + host, role := dc.GetHost(), dc.GetRole() + // new task + subname := fmt.Sprintf("host=%s role=%s containerId=%s", + dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) + t := task.NewTask("Enable Etcd Auth", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + + script := scripts.ENABLE_ETCD_AUTH + layout := dc.GetProjectLayout() + scriptPath := fmt.Sprintf("%s/enable_auth.sh", layout.ServiceBinDir) + + etcdEndPoints, err := dc.GetVariables().Get("cluster_etcd_addr") + if err != nil { + return nil, err + } + + t.AddStep(&step.ListContainers{ + ShowAll: true, + Format: `"{{.ID}}"`, + Filter: fmt.Sprintf("id=%s", containerId), + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: CheckContainerExist(host, role, containerId, &out), + }) + t.AddStep(&step.InstallFile{ // install /curvebs(fs)/etcd/sbin/enable_auth.sh + ContainerId: &containerId, + ContainerDestPath: scriptPath, + Content: &script, + ExecOptions: curveadm.ExecOptions(), + }) + command := fmt.Sprintf("/bin/bash %s %s %s %s", scriptPath, etcdEndPoints, dc.GetEtcdAuthUsername(), + dc.GetEtcdAuthPassword()) + t.AddStep(&step.ContainerExec{ + ContainerId: &containerId, + Success: &success, + Out: &out, + Command: command, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: checkEnableEtcdAuthStatus(&success, &out), + }) + return t, nil +} diff --git a/internal/task/task/common/init_support.go b/internal/task/task/common/init_support.go index c322cc4a2..baa4d5f44 100644 --- a/internal/task/task/common/init_support.go +++ b/internal/task/task/common/init_support.go @@ -37,7 +37,7 @@ func NewInitSupportTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*tas kind := dc.GetKind() subname := fmt.Sprintf("cluster=%s kind=%s", curveadm.ClusterName(), kind) - t := task.NewTask("Init Support", subname, nil) + t := task.NewTask("Init Support", subname, nil, nil) /* * 0d7a7103521da69c6331a96355142c3b diff --git a/internal/task/task/common/install_client.go b/internal/task/task/common/install_client.go index dcb691b12..baadda58d 100644 --- a/internal/task/task/common/install_client.go +++ b/internal/task/task/common/install_client.go @@ -142,7 +142,7 @@ func NewInstallClientTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (* release := getRelease(curveadm) subname := fmt.Sprintf("host=%s release=%s", host, release) name := utils.Choose(kind == KIND_CURVEBS, "CurveBS", "CurveFS") - t := task.NewTask(fmt.Sprintf("Install %s Client", name), subname, hc.GetSSHConfig()) + t := task.NewTask(fmt.Sprintf("Install %s Client", name), subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var input, output string diff --git a/internal/task/task/common/pull_image.go b/internal/task/task/common/pull_image.go index ee40f930d..855b815c9 100644 --- a/internal/task/task/common/pull_image.go +++ b/internal/task/task/common/pull_image.go @@ -41,7 +41,7 @@ func NewPullImageTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task. // new task subname := fmt.Sprintf("host=%s image=%s", dc.GetHost(), dc.GetContainerImage()) - t := task.NewTask("Pull Image", subname, hc.GetSSHConfig()) + t := task.NewTask("Pull Image", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task t.AddStep(&step.PullImage{ diff --git a/internal/task/task/common/restart_service.go b/internal/task/task/common/restart_service.go index 4774df576..2bec6e6e2 100644 --- a/internal/task/task/common/restart_service.go +++ b/internal/task/task/common/restart_service.go @@ -48,7 +48,7 @@ func checkContainerStatus(host, role, containerId string, status *string) step.L } } -func waitContainerStart(seconds int) step.LambdaType { +func WaitContainerStart(seconds int) step.LambdaType { return func(ctx *context.Context) error { time.Sleep(time.Duration(seconds)) return nil @@ -71,7 +71,7 @@ func NewRestartServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* // new task subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Restart Service", subname, hc.GetSSHConfig()) + t := task.NewTask("Restart Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string @@ -85,14 +85,14 @@ func NewRestartServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checkContainerExist(host, role, containerId, &out), + Lambda: CheckContainerExist(host, role, containerId, &out), }) t.AddStep(&step.RestartContainer{ ContainerId: containerId, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: waitContainerStart(3), + Lambda: WaitContainerStart(3), }) t.AddStep(&step.ContainerExec{ ContainerId: &containerId, @@ -101,12 +101,12 @@ func NewRestartServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (* Out: &out, ExecOptions: curveadm.ExecOptions(), }) - t.AddStep(&step2CheckPostStart{ - host: dc.GetHost(), - containerId: containerId, - success: &success, - out: &out, - execOptions: curveadm.ExecOptions(), + t.AddStep(&Step2CheckPostStart{ + Host: dc.GetHost(), + ContainerId: containerId, + Success: &success, + Out: &out, + ExecOptions: curveadm.ExecOptions(), }) return t, nil diff --git a/internal/task/task/common/service_status.go b/internal/task/task/common/service_status.go index 94c582101..3be7dc94f 100644 --- a/internal/task/task/common/service_status.go +++ b/internal/task/task/common/service_status.go @@ -55,12 +55,11 @@ type ( memStorage *utils.SafeMap } - step2GetListenPorts struct { - dc *topology.DeployConfig - containerId string - status *string - ports *string - execOptions module.ExecOptions + Step2GetListenPorts struct { + ContainerId string + Status *string + Ports *string + ExecOptions module.ExecOptions } step2GetLeader struct { @@ -86,7 +85,7 @@ type ( ParentId string Role string Host string - Replica string + Instances string ContainerId string Ports string IsLeader bool @@ -118,7 +117,7 @@ func (s *step2InitStatus) Execute(ctx *context.Context) error { ParentId: dc.GetParentId(), Role: dc.GetRole(), Host: dc.GetHost(), - Replica: fmt.Sprintf("1/%d", dc.GetReplicas()), + Instances: fmt.Sprintf("1/%d", dc.GetInstances()), ContainerId: tui.TrimContainerId(s.containerId), Status: comm.SERVICE_STATUS_UNKNOWN, LogDir: dc.GetLogDir(), @@ -128,7 +127,7 @@ func (s *step2InitStatus) Execute(ctx *context.Context) error { return nil } -func (s *step2GetListenPorts) extractPort(line string) string { +func (s *Step2GetListenPorts) extractPort(line string) string { // e.g: tcp LISTEN 0 128 10.246.159.123:2379 *:* users:(("etcd",pid=7,fd=5)) regex, err := regexp.Compile("^.*:([0-9]+).*users.*$") if err == nil { @@ -140,8 +139,8 @@ func (s *step2GetListenPorts) extractPort(line string) string { return "" } -func (s *step2GetListenPorts) Execute(ctx *context.Context) error { - if !strings.HasPrefix(*s.status, "Up") { +func (s *Step2GetListenPorts) Execute(ctx *context.Context) error { + if !strings.HasPrefix(*s.Status, "Up") { return nil } @@ -155,8 +154,8 @@ func (s *step2GetListenPorts) Execute(ctx *context.Context) error { return nil } - cmd := ctx.Module().DockerCli().ContainerExec(s.containerId, command) - out, err := cmd.Execute(s.execOptions) + cmd := ctx.Module().DockerCli().ContainerExec(s.ContainerId, command) + out, err := cmd.Execute(s.ExecOptions) if err != nil { return nil } @@ -170,7 +169,7 @@ func (s *step2GetListenPorts) Execute(ctx *context.Context) error { ports = append(ports, port) } } - *s.ports = strings.Join(ports, ",") + *s.Ports = strings.Join(ports, ",") return nil } @@ -207,7 +206,7 @@ func (s *step2FormatServiceStatus) Execute(ctx *context.Context) error { ParentId: dc.GetParentId(), Role: dc.GetRole(), Host: dc.GetHost(), - Replica: fmt.Sprintf("1/%d", dc.GetReplicas()), + Instances: fmt.Sprintf("1/%d", dc.GetInstances()), ContainerId: tui.TrimContainerId(s.containerId), Ports: *s.ports, IsLeader: *s.isLeader, @@ -230,7 +229,7 @@ func NewInitServiceStatusTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Init Service Status", subname, nil) + t := task.NewTask("Init Service Status", subname, nil, nil) t.AddStep(&step2InitStatus{ dc: dc, @@ -242,7 +241,7 @@ func NewInitServiceStatusTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) return t, nil } -func trimContainerStatus(status *string) step.LambdaType { +func TrimContainerStatus(status *string) step.LambdaType { return func(ctx *context.Context) error { items := strings.Split(*status, "\n") *status = items[len(items)-1] @@ -266,7 +265,7 @@ func NewGetServiceStatusTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) // new task subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Get Service Status", subname, hc.GetSSHConfig()) + t := task.NewTask("Get Service Status", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var status string @@ -280,14 +279,13 @@ func NewGetServiceStatusTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: trimContainerStatus(&status), + Lambda: TrimContainerStatus(&status), }) - t.AddStep(&step2GetListenPorts{ - dc: dc, - containerId: containerId, - status: &status, - ports: &ports, - execOptions: curveadm.ExecOptions(), + t.AddStep(&Step2GetListenPorts{ + ContainerId: containerId, + Status: &status, + Ports: &ports, + ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step2GetLeader{ dc: dc, diff --git a/internal/task/task/common/start_service.go b/internal/task/task/common/start_service.go index 5ac190ce5..f421d3572 100644 --- a/internal/task/task/common/start_service.go +++ b/internal/task/task/common/start_service.go @@ -41,34 +41,34 @@ const ( CMD_ADD_CONTABLE = "bash -c '[[ ! -z $(which crontab) ]] && crontab %s'" ) -type step2CheckPostStart struct { - host string - role string - containerId string - success *bool - out *string - execOptions module.ExecOptions +type Step2CheckPostStart struct { + Host string + Role string + ContainerId string + Success *bool + Out *string + ExecOptions module.ExecOptions } -func (s *step2CheckPostStart) Execute(ctx *context.Context) error { - if *s.success { +func (s *Step2CheckPostStart) Execute(ctx *context.Context) error { + if *s.Success { return nil } var status string step := &step.InspectContainer{ - ContainerId: s.containerId, + ContainerId: s.ContainerId, Format: "'{{.State.Status}}'", Out: &status, - ExecOptions: s.execOptions, + ExecOptions: s.ExecOptions, } err := step.Execute(ctx) if err != nil { - return errno.ERR_START_CRONTAB_IN_CONTAINER_FAILED.S(*s.out) + return errno.ERR_START_CRONTAB_IN_CONTAINER_FAILED.S(*s.Out) } else if status != "running" { return errno.ERR_CONTAINER_IS_ABNORMAL. F("host=%s role=%s containerId=%s", - s.host, s.role, tui.TrimContainerId(s.containerId)) + s.Host, s.Role, tui.TrimContainerId(s.ContainerId)) } return nil } @@ -89,7 +89,7 @@ func NewStartServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*ta // new task subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Start Service", subname, hc.GetSSHConfig()) + t := task.NewTask("Start Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string @@ -103,14 +103,14 @@ func NewStartServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*ta ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checkContainerExist(host, role, containerId, &out), + Lambda: CheckContainerExist(host, role, containerId, &out), }) t.AddStep(&step.StartContainer{ ContainerId: &containerId, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: waitContainerStart(3), + Lambda: WaitContainerStart(3), }) t.AddStep(&step.ContainerExec{ ContainerId: &containerId, @@ -119,13 +119,13 @@ func NewStartServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*ta Out: &out, ExecOptions: curveadm.ExecOptions(), }) - t.AddStep(&step2CheckPostStart{ - host: dc.GetHost(), - role: dc.GetRole(), - containerId: containerId, - success: &success, - out: &out, - execOptions: curveadm.ExecOptions(), + t.AddStep(&Step2CheckPostStart{ + Host: dc.GetHost(), + Role: dc.GetRole(), + ContainerId: containerId, + Success: &success, + Out: &out, + ExecOptions: curveadm.ExecOptions(), }) return t, nil diff --git a/internal/task/task/common/stop_service.go b/internal/task/task/common/stop_service.go index 68e8d41e6..8aee65529 100644 --- a/internal/task/task/common/stop_service.go +++ b/internal/task/task/common/stop_service.go @@ -37,7 +37,7 @@ import ( tui "github.com/opencurve/curveadm/internal/tui/common" ) -func checkContainerExist(host, role, containerId string, out *string) step.LambdaType { +func CheckContainerExist(host, role, containerId string, out *string) step.LambdaType { return func(ctx *context.Context) error { if len(*out) == 0 { return errno.ERR_CONTAINER_ALREADT_REMOVED. @@ -73,7 +73,7 @@ func NewStopServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*tas // new task subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Stop Service", subname, hc.GetSSHConfig()) + t := task.NewTask("Stop Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string @@ -89,7 +89,7 @@ func NewStopServiceTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*tas ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checkContainerExist(host, role, containerId, &out), + Lambda: CheckContainerExist(host, role, containerId, &out), }) t.AddStep(&step.StopContainer{ ContainerId: containerId, diff --git a/internal/task/task/common/sync_binary.go b/internal/task/task/common/sync_binary.go deleted file mode 100644 index a4276768c..000000000 --- a/internal/task/task/common/sync_binary.go +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2021 NetEase Inc. - * - * 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. - */ - -/* - * Project: CurveAdm - * Created Date: 2021-11-25 - * Author: Hailang Mo (wavemomo) - */ - -package common - -/* -import ( - "fmt" - "path" - "path/filepath" - - "github.com/opencurve/curveadm/internal/task" - "github.com/opencurve/curveadm/cli/cli" - "github.com/opencurve/curveadm/internal/configure" - "github.com/opencurve/curveadm/internal/task/context" -) - -const KEY_BINARY_PATH = "BINARY_PATH" - -type step2SyncBinary struct { - containerID string - remoteContainerBinary string - localBinary string -} - -func (s *step2SyncBinary) Execute(ctx *context.Context) error { - remoteHostBinaryPath := fmt.Sprintf("/tmp/%s", path.Base(s.localBinary)) - if err := ctx.Module().Scp(s.localBinary, remoteHostBinaryPath); err != nil { - return err - } - - _, err := ctx.Module().SshShell("sudo docker cp %s %s:%s", remoteHostBinaryPath, s.containerID, - s.remoteContainerBinary) - return err - -} - -func (s *step2SyncBinary) Rollback(ctx *context.Context) {} - -func NewSyncBinaryTask(curveadm *cli.CurveAdm, dc *configure.DeployConfig) (*task.Task, error) { - serviceId := configure.GetServiceId(curveadm.ClusterId(), dc.GetId()) - containerId, err := curveadm.Storage().GetContainerId(serviceId) - if err != nil { - return nil, err - } else if containerId == "" { - return nil, fmt.Errorf("service(id=%s) not found", serviceId) - } - - binaryPath := curveadm.MemStorage().Get(KEY_BINARY_PATH).(string) - absPath, err := filepath.Abs(binaryPath) - if err != nil { - return nil, err - } - subname := fmt.Sprintf("host=%s role=%s binary=%s", dc.GetHost(), dc.GetRole(), absPath) - t := task.NewTask("Sync Binary", subname, dc) - remotePath := fmt.Sprintf("/usr/local/curvefs/%s/sbin/%s", dc.GetRole(), path.Base(binaryPath)) - t.AddStep(&step2SyncBinary{ - containerID: containerId, - localBinary: binaryPath, - remoteContainerBinary: remotePath, - }) - return t, nil -} -*/ diff --git a/internal/task/task/common/sync_config.go b/internal/task/task/common/sync_config.go index 2090f5f84..8373e7c7b 100644 --- a/internal/task/task/common/sync_config.go +++ b/internal/task/task/common/sync_config.go @@ -37,13 +37,14 @@ import ( ) const ( - DEFAULT_CONFIG_DELIMITER = "=" - ETCD_CONFIG_DELIMITER = ": " + DEFAULT_CONFIG_DELIMITER = "=" + ETCD_CONFIG_DELIMITER = ": " + TOOLS_V2_CONFIG_DELIMITER = ": " CURVE_CRONTAB_FILE = "/tmp/curve_crontab" ) -func newMutate(dc *topology.DeployConfig, delimiter string, forceRender bool) step.Mutate { +func NewMutate(dc *topology.DeployConfig, delimiter string, forceRender bool) step.Mutate { serviceConfig := dc.GetServiceConfig() return func(in, key, value string) (out string, err error) { if len(key) == 0 { @@ -102,13 +103,13 @@ func NewSyncConfigTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task // new task subname := fmt.Sprintf("host=%s role=%s containerId=%s", dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) - t := task.NewTask("Sync Config", subname, hc.GetSSHConfig()) + t := task.NewTask("Sync Config", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var out string layout := dc.GetProjectLayout() role := dc.GetRole() - reportScript := scripts.SCRIPT_REPORT + reportScript := scripts.REPORT reportScriptPath := fmt.Sprintf("%s/report.sh", layout.ToolsBinDir) crontab := newCrontab(curveadm.ClusterUUId(), dc, reportScriptPath) delimiter := DEFAULT_CONFIG_DELIMITER @@ -124,7 +125,7 @@ func NewSyncConfigTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checkContainerExist(dc.GetHost(), dc.GetRole(), containerId, &out), + Lambda: CheckContainerExist(dc.GetHost(), dc.GetRole(), containerId, &out), }) for _, conf := range layout.ServiceConfFiles { t.AddStep(&step.SyncFile{ // sync service config @@ -133,7 +134,7 @@ func NewSyncConfigTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task ContainerDestId: &containerId, ContainerDestPath: conf.Path, KVFieldSplit: delimiter, - Mutate: newMutate(dc, delimiter, conf.Name == "nginx.conf"), + Mutate: NewMutate(dc, delimiter, conf.Name == "nginx.conf"), ExecOptions: curveadm.ExecOptions(), }) } @@ -143,7 +144,16 @@ func NewSyncConfigTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task ContainerDestId: &containerId, ContainerDestPath: layout.ToolsConfSystemPath, KVFieldSplit: DEFAULT_CONFIG_DELIMITER, - Mutate: newMutate(dc, DEFAULT_CONFIG_DELIMITER, false), + Mutate: NewMutate(dc, DEFAULT_CONFIG_DELIMITER, false), + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.TrySyncFile{ // sync tools-v2 config + ContainerSrcId: &containerId, + ContainerSrcPath: layout.ToolsV2ConfSrcPath, + ContainerDestId: &containerId, + ContainerDestPath: layout.ToolsV2ConfSystemPath, + KVFieldSplit: TOOLS_V2_CONFIG_DELIMITER, + Mutate: NewMutate(dc, TOOLS_V2_CONFIG_DELIMITER, false), ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.InstallFile{ // install report script diff --git a/internal/task/task/common/uninstall_client.go b/internal/task/task/common/uninstall_client.go index ce939832d..f02f7ed0d 100644 --- a/internal/task/task/common/uninstall_client.go +++ b/internal/task/task/common/uninstall_client.go @@ -81,7 +81,7 @@ func NewUninstallClientTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, kind := curveadm.MemStorage().Get(comm.KEY_CLIENT_KIND).(string) subname := fmt.Sprintf("host=%s release=%s kind=%s", host, release, kind) name := utils.Choose(kind == KIND_CURVEBS, "CurveBS", "CurveFS") - t := task.NewTask(fmt.Sprintf("Uninstall %s Client", name), subname, hc.GetSSHConfig()) + t := task.NewTask(fmt.Sprintf("Uninstall %s Client", name), subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task t.AddPostStep(&step2UninstallPackage{ diff --git a/internal/task/task/common/update_topology.go b/internal/task/task/common/update_topology.go index b89bb8a43..f693a047f 100644 --- a/internal/task/task/common/update_topology.go +++ b/internal/task/task/common/update_topology.go @@ -27,10 +27,10 @@ package common import ( "github.com/opencurve/curveadm/cli/cli" comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/internal/task/context" "github.com/opencurve/curveadm/internal/task/step" "github.com/opencurve/curveadm/internal/task/task" - "github.com/opencurve/curveadm/internal/errno" ) func updateTopology(curveadm *cli.CurveAdm) step.LambdaType { @@ -45,7 +45,7 @@ func updateTopology(curveadm *cli.CurveAdm) step.LambdaType { } func NewUpdateTopologyTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { - t := task.NewTask("Update Topology", "", nil) + t := task.NewTask("Update Topology", "", nil, nil) // add step to task t.AddStep(&step.Lambda{ diff --git a/internal/task/task/fs/mount.go b/internal/task/task/fs/mount.go index 0d3ac588b..29be1c665 100644 --- a/internal/task/task/fs/mount.go +++ b/internal/task/task/fs/mount.go @@ -44,7 +44,8 @@ import ( const ( FORMAT_MOUNT_OPTION = "type=bind,source=%s,target=%s,bind-propagation=rshared" - CLIENT_CONFIG_DELIMITER = "=" + CLIENT_CONFIG_DELIMITER = "=" + TOOLS_V2_CONFIG_DELIMITER = ": " KEY_CURVEBS_CLUSTER = "curvebs.cluster" @@ -216,12 +217,12 @@ func mountPoint2ContainerName(mountPoint string) string { return fmt.Sprintf("curvefs-filesystem-%s", utils.MD5Sum(mountPoint)) } -func checkMountStatus(mountPoint string, out *string) step.LambdaType { +func checkMountStatus(mountPoint, name string, out *string) step.LambdaType { return func(ctx *context.Context) error { - if len(*out) == 0 { - return nil + if *out == name { + return errno.ERR_FS_PATH_ALREADY_MOUNTED.F("mountPath: %s", mountPoint) } - return errno.ERR_FS_PATH_ALREADY_MOUNTED.F("mountPath: %s", mountPoint) + return nil } } @@ -256,6 +257,12 @@ func (s *step2InsertClient) Execute(ctx *context.Context) error { if err != nil { return errno.ERR_INSERT_CLIENT_FAILED.E(err) } + + err = curveadm.Storage().InsertClientConfig(fsId, config.GetData()) + if err != nil { + return errno.ERR_INSERT_CLIENT_CONFIG_FAILED.E(err) + } + return nil } @@ -282,7 +289,7 @@ func NewMountFSTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task.T mountFSName := options.MountFSName mountFSType := options.MountFSType subname := fmt.Sprintf("mountFSName=%s mountFSType=%s mountPoint=%s", mountFSName, mountFSType, mountPoint) - t := task.NewTask("Mount FileSystem", subname, hc.GetSSHConfig()) + t := task.NewTask("Mount FileSystem", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var containerId, out string @@ -291,27 +298,26 @@ func NewMountFSTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task.T prefix := configure.GetFSClientPrefix() containerMountPath := configure.GetFSClientMountPath(mountPoint) containerName := mountPoint2ContainerName(mountPoint) - createfsScript := scripts.SCRIPT_CREATEFS + createfsScript := scripts.CREATE_FS createfsScriptPath := "/client.sh" - t.AddStep(&step.DockerInfo{ + t.AddStep(&step.EngineInfo{ Success: &success, Out: &out, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checker.CheckDockerInfo(options.Host, &success, &out), + Lambda: checker.CheckEngineInfo(options.Host, curveadm.ExecOptions().ExecWithEngine, &success, &out), }) t.AddStep(&step.ListContainers{ ShowAll: true, - Format: "'{{.Status}}'", - Quiet: true, + Format: "'{{.Names}}'", Filter: fmt.Sprintf("name=%s", containerName), Out: &out, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Lambda{ - Lambda: checkMountStatus(mountPoint, &out), + Lambda: checkMountStatus(mountPoint, containerName, &out), }) t.AddStep(&step.PullImage{ Image: cc.GetContainerImage(), @@ -372,6 +378,15 @@ func NewMountFSTask(curveadm *cli.CurveAdm, cc *configure.ClientConfig) (*task.T Mutate: newToolsMutate(cc, CLIENT_CONFIG_DELIMITER), ExecOptions: curveadm.ExecOptions(), }) + t.AddStep(&step.TrySyncFile{ // sync tools-v2 config + ContainerSrcId: &containerId, + ContainerSrcPath: fmt.Sprintf("%s/conf/curve.yaml", root), + ContainerDestId: &containerId, + ContainerDestPath: topology.GetCurveFSProjectLayout().ToolsV2ConfSystemPath, + KVFieldSplit: TOOLS_V2_CONFIG_DELIMITER, + Mutate: newToolsMutate(cc, TOOLS_V2_CONFIG_DELIMITER), + ExecOptions: curveadm.ExecOptions(), + }) t.AddStep(&step.InstallFile{ // install client.sh shell ContainerId: &containerId, ContainerDestPath: createfsScriptPath, diff --git a/internal/task/task/fs/umount.go b/internal/task/task/fs/umount.go index 6c14c93af..aaecd6407 100644 --- a/internal/task/task/fs/umount.go +++ b/internal/task/task/fs/umount.go @@ -83,6 +83,12 @@ func (s *step2DeleteClient) Execute(ctx *context.Context) error { if err != nil { return errno.ERR_DELETE_CLIENT_FAILED.E(err) } + + err = s.curveadm.Storage().DeleteClientConfig(s.fsId) + if err != nil { + return errno.ERR_DELETE_CLIENT_CONFIG_FAILED.E(err) + } + return nil } @@ -117,10 +123,6 @@ func (s *step2RemoveContainer) Execute(ctx *context.Context) error { func NewUmountFSTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) { options := curveadm.MemStorage().Get(comm.KEY_MOUNT_OPTIONS).(MountOptions) fsId := curveadm.GetFilesystemId(options.Host, options.MountPoint) - containerId, err := curveadm.Storage().GetClientContainerId(fsId) - if err != nil { - return nil, errno.ERR_GET_CLIENT_CONTAINER_ID_FAILED.E(err) - } hc, err := curveadm.GetHost(options.Host) if err != nil { return nil, err @@ -129,15 +131,16 @@ func NewUmountFSTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, error) // new task mountPoint := options.MountPoint subname := fmt.Sprintf("host=%s mountPoint=%s", options.Host, mountPoint) - t := task.NewTask("Umount FileSystem", subname, hc.GetSSHConfig()) + t := task.NewTask("Umount FileSystem", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) // add step to task var status string + containerId := mountPoint2ContainerName(mountPoint) + t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.Status}}'", - Quiet: true, - Filter: fmt.Sprintf("id=%s", containerId), + Filter: fmt.Sprintf("name=%s", containerId), Out: &status, ExecOptions: curveadm.ExecOptions(), }) diff --git a/internal/task/task/monitor/clean_container.go b/internal/task/task/monitor/clean_container.go new file mode 100644 index 000000000..feee92a10 --- /dev/null +++ b/internal/task/task/monitor/clean_container.go @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-26 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/task" + "github.com/opencurve/curveadm/internal/task/task/common" +) + +func NewCleanConfigContainerTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + role := cfg.GetRole() + if role != ROLE_MONITOR_CONF { + return nil, nil + } + host := cfg.GetHost() + hc, err := curveadm.GetHost(host) + if err != nil { + return nil, err + } + serviceId := curveadm.GetServiceId(cfg.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if err != nil { + return nil, err + } + t := task.NewTask("Clean Config Container", "", hc.GetSSHConfig(), hc.GetHttpConfig()) + t.AddStep(&common.Step2CleanContainer{ + ServiceId: serviceId, + ContainerId: containerId, + Storage: curveadm.Storage(), + ExecOptions: curveadm.ExecOptions(), + }) + return t, nil +} diff --git a/internal/task/task/monitor/clean_service.go b/internal/task/task/monitor/clean_service.go new file mode 100644 index 000000000..316ee6f81 --- /dev/null +++ b/internal/task/task/monitor/clean_service.go @@ -0,0 +1,94 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-27 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "fmt" + "strings" + + "github.com/opencurve/curveadm/cli/cli" + comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" + "github.com/opencurve/curveadm/internal/task/task/common" + tui "github.com/opencurve/curveadm/internal/tui/common" + "github.com/opencurve/curveadm/internal/utils" +) + +var ( + ROLE_NODE_EXPORTER = configure.ROLE_NODE_EXPORTER + ROLE_PROMETHEUS = configure.ROLE_PROMETHEUS + ROLE_GRAFANA = configure.ROLE_GRAFANA + ROLE_MONITOR_CONF = configure.ROLE_MONITOR_CONF +) + +func getCleanFiles(clean map[string]bool, mc *configure.MonitorConfig) []string { + files := []string{} + for item := range clean { + switch item { + case comm.CLEAN_ITEM_DATA: + files = append(files, mc.GetDataDir()) + } + } + return files +} + +func NewCleanMonitorTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(cfg.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if err != nil { + return nil, err + } + if cfg.GetRole() == ROLE_MONITOR_CONF && + (len(containerId) == 0 || containerId == comm.CLEANED_CONTAINER_ID) { + return nil, nil + } + hc, err := curveadm.GetHost(cfg.GetHost()) + if err != nil { + return nil, err + } + + // new task + only := curveadm.MemStorage().Get(comm.KEY_CLEAN_ITEMS).([]string) + subname := fmt.Sprintf("host=%s role=%s containerId=%s clean=%s", + cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId), strings.Join(only, ",")) + t := task.NewTask("Clean Monitor", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + + // add step to task + clean := utils.Slice2Map(only) + files := getCleanFiles(clean, cfg) // directorys which need cleaned + t.AddStep(&step.RemoveFile{ + Files: files, + ExecOptions: curveadm.ExecOptions(), + }) + if clean[comm.CLEAN_ITEM_CONTAINER] == true { + t.AddStep(&common.Step2CleanContainer{ + ServiceId: serviceId, + ContainerId: containerId, + Storage: curveadm.Storage(), + ExecOptions: curveadm.ExecOptions(), + }) + } + return t, nil +} diff --git a/internal/task/task/monitor/create_container.go b/internal/task/task/monitor/create_container.go new file mode 100644 index 000000000..ccf6382d8 --- /dev/null +++ b/internal/task/task/monitor/create_container.go @@ -0,0 +1,173 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-19 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "fmt" + "strings" + + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" + "github.com/opencurve/curveadm/internal/task/task/common" +) + +func getArguments(cfg *configure.MonitorConfig) string { + role := cfg.GetRole() + var argsMap map[string]interface{} + switch role { + case ROLE_NODE_EXPORTER: + argsMap = map[string]interface{}{ + "path.rootfs": "/host", + "collector.cpu.info": nil, + "web.listen-address": fmt.Sprintf(":%d", cfg.GetListenPort()), + } + case ROLE_PROMETHEUS: + argsMap = map[string]interface{}{ + "config.file": "/etc/prometheus/prometheus.yml", + "storage.tsdb.path": "/prometheus", + "storage.tsdb.retention.time": cfg.GetPrometheusRetentionTime(), + "storage.tsdb.retention.size": cfg.GetPrometheusRetentionSize(), + "web.console.libraries": "/usr/share/prometheus/console_libraries", + "web.console.templates": "/usr/share/prometheus/consoles", + "web.listen-address": fmt.Sprintf(":%d", cfg.GetListenPort()), + } + } + args := []string{} + for k, v := range argsMap { + var item string + if v != nil { + item = fmt.Sprintf("--%s=%v", k, v) + } else { + item = fmt.Sprintf("--%s", k) + } + args = append(args, item) + } + return strings.Join(args, " ") +} + +func getMountVolumes(cfg *configure.MonitorConfig) []step.Volume { + role := cfg.GetRole() + volumes := []step.Volume{} + switch role { + case ROLE_NODE_EXPORTER: + volumes = append(volumes, step.Volume{ + HostPath: "/", + ContainerPath: "/host:ro,rslave", + }, + step.Volume{ + HostPath: "/run/udev/data", + ContainerPath: "/run/udev/data", + }, + step.Volume{ + HostPath: "/run/dbus/system_bus_socket", + ContainerPath: "/var/run/dbus/system_bus_socket:ro", + }) + case ROLE_PROMETHEUS: + volumes = append(volumes, step.Volume{ + HostPath: cfg.GetDataDir(), + ContainerPath: "/prometheus", + }) + case ROLE_GRAFANA: + volumes = append(volumes, step.Volume{ + HostPath: cfg.GetDataDir(), + ContainerPath: "/var/lib/grafana", + }) + } + return volumes +} + +func getEnvironments(cfg *configure.MonitorConfig) []string { + role := cfg.GetRole() + if role == ROLE_GRAFANA { + return []string{ + "GF_INSTALL_PLUGINS=grafana-piechart-panel", + fmt.Sprintf("GF_SECURITY_ADMIN_USER=%s", cfg.GetGrafanaUser()), + fmt.Sprintf("GF_SECURITY_ADMIN_PASSWORD=%s", cfg.GetGrafanaPassword()), + fmt.Sprintf("GF_SERVER_HTTP_PORT=%d", cfg.GetListenPort()), + } + } + return []string{} +} + +func NewCreateContainerTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + host := cfg.GetHost() + hc, err := curveadm.GetHost(host) + if err != nil { + return nil, err + } + + // new task + subname := fmt.Sprintf("host=%s role=%s", host, cfg.GetRole()) + t := task.NewTask("Create Container", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + + // add step to task + var oldContainerId, containerId string + clusterId := curveadm.ClusterId() + mcId := cfg.GetId() + serviceId := curveadm.GetServiceId(mcId) + kind := cfg.GetKind() + role := cfg.GetRole() + hostname := fmt.Sprintf("%s-%s-%s", kind, role, serviceId) + options := curveadm.ExecOptions() + options.ExecWithSudo = false + + t.AddStep(&common.Step2GetService{ // if service exist, break task + ServiceId: serviceId, + ContainerId: &oldContainerId, + Storage: curveadm.Storage(), + }) + t.AddStep(&step.CreateDirectory{ + Paths: []string{cfg.GetDataDir()}, + ExecOptions: options, + }) + t.AddStep(&step.CreateContainer{ + Image: cfg.GetImage(), + Command: getArguments(cfg), + AddHost: []string{fmt.Sprintf("%s:127.0.0.1", hostname)}, + Envs: getEnvironments(cfg), + Hostname: hostname, + Init: true, + Name: hostname, + Privileged: true, + User: "0:0", + Pid: "host", + Restart: common.POLICY_NEVER_RESTART, + Ulimits: []string{"core=-1"}, + Volumes: getMountVolumes(cfg), + Out: &containerId, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: common.TrimContainerId(&containerId), + }) + t.AddStep(&common.Step2InsertService{ + ClusterId: clusterId, + ServiceId: serviceId, + ContainerId: &containerId, + OldContainerId: &oldContainerId, + Storage: curveadm.Storage(), + }) + return t, nil +} diff --git a/internal/task/task/monitor/pull_image.go b/internal/task/task/monitor/pull_image.go new file mode 100644 index 000000000..ebe87ae86 --- /dev/null +++ b/internal/task/task/monitor/pull_image.go @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-19 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "fmt" + + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" +) + +func NewPullImageTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + image := cfg.GetImage() + host := cfg.GetHost() + hc, err := curveadm.GetHost(host) + if err != nil { + return nil, err + } + + // new task + subname := fmt.Sprintf("host=%s image=%s", host, image) + t := task.NewTask("Pull Image", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + // add step to task + t.AddStep(&step.PullImage{ + Image: image, + ExecOptions: curveadm.ExecOptions(), + }) + return t, nil +} diff --git a/internal/task/task/monitor/restart_service.go b/internal/task/task/monitor/restart_service.go new file mode 100644 index 000000000..726056ba2 --- /dev/null +++ b/internal/task/task/monitor/restart_service.go @@ -0,0 +1,84 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-28 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "fmt" + + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" + "github.com/opencurve/curveadm/internal/task/task/common" + tui "github.com/opencurve/curveadm/internal/tui/common" +) + +func NewRestartServiceTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(cfg.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if IsSkip(cfg, []string{ROLE_MONITOR_CONF}) { + return nil, nil + } else if err != nil { + return nil, err + } + hc, err := curveadm.GetHost(cfg.GetHost()) + if err != nil { + return nil, err + } + + // new task + subname := fmt.Sprintf("host=%s role=%s containerId=%s", + cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) + t := task.NewTask("Restart Monitor Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + + // add step to task + var out string + var success bool + host, role := cfg.GetHost(), cfg.GetRole() + t.AddStep(&step.ListContainers{ + ShowAll: true, + Format: `"{{.ID}}"`, + Filter: fmt.Sprintf("id=%s", containerId), + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: common.CheckContainerExist(host, role, containerId, &out), + }) + t.AddStep(&step.RestartContainer{ + ContainerId: containerId, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: common.WaitContainerStart(3), + }) + t.AddStep(&common.Step2CheckPostStart{ + Host: host, + ContainerId: containerId, + Success: &success, + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + + return t, nil +} diff --git a/internal/task/task/monitor/start_service.go b/internal/task/task/monitor/start_service.go new file mode 100644 index 000000000..71c55faa8 --- /dev/null +++ b/internal/task/task/monitor/start_service.go @@ -0,0 +1,95 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-24 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "fmt" + + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" + "github.com/opencurve/curveadm/internal/task/task/common" + tui "github.com/opencurve/curveadm/internal/tui/common" +) + +func IsSkip(mc *configure.MonitorConfig, roles []string) bool { + role := mc.GetRole() + for _, r := range roles { + if role == r { + return true + } + } + return false +} + +func NewStartServiceTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(cfg.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if IsSkip(cfg, []string{ROLE_MONITOR_CONF}) { + return nil, nil + } else if err != nil { + return nil, err + } + hc, err := curveadm.GetHost(cfg.GetHost()) + if err != nil { + return nil, err + } + + // new task + subname := fmt.Sprintf("host=%s role=%s containerId=%s", + cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) + t := task.NewTask("Start Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + + // add step to task + var out string + var success bool + role, host := cfg.GetRole(), cfg.GetHost() + t.AddStep(&step.ListContainers{ + ShowAll: true, + Format: `"{{.ID}}"`, + Filter: fmt.Sprintf("id=%s", containerId), + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: common.CheckContainerExist(host, role, containerId, &out), + }) + t.AddStep(&step.StartContainer{ + ContainerId: &containerId, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: common.WaitContainerStart(3), + }) + t.AddStep(&common.Step2CheckPostStart{ + Host: cfg.GetHost(), + Role: cfg.GetRole(), + ContainerId: containerId, + Success: &success, + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + + return t, nil +} diff --git a/internal/task/task/monitor/status_service.go b/internal/task/task/monitor/status_service.go new file mode 100644 index 000000000..6908a8710 --- /dev/null +++ b/internal/task/task/monitor/status_service.go @@ -0,0 +1,181 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-27 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "fmt" + "strconv" + + "github.com/opencurve/curveadm/cli/cli" + comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/context" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" + "github.com/opencurve/curveadm/internal/task/task/common" + tui "github.com/opencurve/curveadm/internal/tui/common" + "github.com/opencurve/curveadm/internal/utils" +) + +type step2InitMonitorStatus struct { + mc *configure.MonitorConfig + serviceId string + containerId string + memStorage *utils.SafeMap +} + +type step2FormatMonitorStatus struct { + mc *configure.MonitorConfig + serviceId string + containerId string + ports *string + status *string + memStorage *utils.SafeMap +} + +type MonitorStatus struct { + Id string + Role string + Host string + ContainerId string + Ports string + Status string + DataDir string + Config *configure.MonitorConfig +} + +func setMonitorStatus(memStorage *utils.SafeMap, id string, status MonitorStatus) { + memStorage.TX(func(kv *utils.SafeMap) error { + m := map[string]MonitorStatus{} + v := kv.Get(comm.KEY_MONITOR_STATUS) + if v != nil { + m = v.(map[string]MonitorStatus) + } + m[id] = status + kv.Set(comm.KEY_MONITOR_STATUS, m) + return nil + }) +} + +func (s *step2InitMonitorStatus) Execute(ctx *context.Context) error { + mc := s.mc + id := s.serviceId + setMonitorStatus(s.memStorage, id, MonitorStatus{ + Id: id, + Role: mc.GetRole(), + Host: mc.GetHost(), + ContainerId: tui.TrimContainerId(s.containerId), + Status: comm.SERVICE_STATUS_UNKNOWN, + DataDir: mc.GetDataDir(), + Config: mc, + }) + return nil +} + +func (s *step2FormatMonitorStatus) Execute(ctx *context.Context) error { + status := *s.status + if s.containerId == comm.CLEANED_CONTAINER_ID { // container cleaned + status = comm.SERVICE_STATUS_CLEANED + } else if len(status) == 0 { // container losed + status = comm.SERVICE_STATUS_LOSED + } + + mc := s.mc + id := s.serviceId + setMonitorStatus(s.memStorage, id, MonitorStatus{ + Id: id, + Role: mc.GetRole(), + Host: mc.GetHost(), + ContainerId: tui.TrimContainerId(s.containerId), + Ports: *s.ports, + Status: status, + DataDir: mc.GetDataDir(), + Config: mc, + }) + return nil +} + +func NewInitMonitorStatusTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(cfg.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if IsSkip(cfg, []string{ROLE_MONITOR_CONF}) { + return nil, nil + } else if err != nil { + return nil, err + } + + subname := fmt.Sprintf("host=%s role=%s containerId=%s", + cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) + t := task.NewTask("Init Monitor Status", subname, nil, nil) + + t.AddStep(&step2InitMonitorStatus{ + mc: cfg, + serviceId: serviceId, + containerId: containerId, + memStorage: curveadm.MemStorage(), + }) + + return t, nil +} + +func NewGetMonitorStatusTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(cfg.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if IsSkip(cfg, []string{ROLE_MONITOR_CONF}) { + return nil, nil + } else if err != nil { + return nil, err + } + hc, err := curveadm.GetHost(cfg.GetHost()) + if err != nil { + return nil, err + } + + // new task + subname := fmt.Sprintf("host=%s role=%s containerId=%s", + cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) + t := task.NewTask("Get Monitor Status", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + + // add step to task + var status string + ports := strconv.Itoa(cfg.GetListenPort()) + t.AddStep(&step.ListContainers{ + ShowAll: true, + Format: `"{{.Status}}"`, + Filter: fmt.Sprintf("id=%s", containerId), + Out: &status, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: common.TrimContainerStatus(&status), + }) + t.AddStep(&step2FormatMonitorStatus{ + mc: cfg, + serviceId: serviceId, + containerId: containerId, + ports: &ports, + status: &status, + memStorage: curveadm.MemStorage(), + }) + return t, nil +} diff --git a/internal/task/task/monitor/stop_service.go b/internal/task/task/monitor/stop_service.go new file mode 100644 index 000000000..221cb3e52 --- /dev/null +++ b/internal/task/task/monitor/stop_service.go @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-27 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "fmt" + + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" + "github.com/opencurve/curveadm/internal/task/task/common" + tui "github.com/opencurve/curveadm/internal/tui/common" +) + +func NewStopServiceTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(cfg.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if IsSkip(cfg, []string{ROLE_MONITOR_CONF}) { + return nil, nil + } else if err != nil { + return nil, err + } + hc, err := curveadm.GetHost(cfg.GetHost()) + if err != nil { + return nil, err + } + + // new task + subname := fmt.Sprintf("host=%s role=%s containerId=%s", + cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) + t := task.NewTask("Stop Service", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + + // add step to task + var out string + role, host := cfg.GetRole(), cfg.GetHost() + t.AddStep(&step.ListContainers{ + ShowAll: true, + Format: `"{{.ID}}"`, + Filter: fmt.Sprintf("id=%s", containerId), + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: common.CheckContainerExist(host, role, containerId, &out), + }) + t.AddStep(&step.StopContainer{ + ContainerId: containerId, + ExecOptions: curveadm.ExecOptions(), + }) + return t, nil +} diff --git a/internal/task/task/monitor/sync_config.go b/internal/task/task/monitor/sync_config.go new file mode 100644 index 000000000..5ed9824cb --- /dev/null +++ b/internal/task/task/monitor/sync_config.go @@ -0,0 +1,141 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ + +/* +* Project: Curveadm +* Created Date: 2023-04-21 +* Author: wanghai (SeanHai) + */ + +package monitor + +import ( + "fmt" + "path" + "strings" + + "github.com/opencurve/curveadm/cli/cli" + "github.com/opencurve/curveadm/internal/configure" + "github.com/opencurve/curveadm/internal/task/scripts" + "github.com/opencurve/curveadm/internal/task/step" + "github.com/opencurve/curveadm/internal/task/task" + "github.com/opencurve/curveadm/internal/task/task/common" + tui "github.com/opencurve/curveadm/internal/tui/common" +) + +const ( + TOOL_SYS_PATH = "/usr/bin/curve_ops_tool" + MONITOR_CONF_PATH = "monitor" + PROMETHEUS_CONTAINER_PATH = "/etc/prometheus" + GRAFANA_CONTAINER_PATH = "/etc/grafana/grafana.ini" + DASHBOARD_CONTAINER_PATH = "/etc/grafana/provisioning/dashboards" + GRAFANA_DATA_SOURCE_PATH = "/etc/grafana/provisioning/datasources/all.yml" + CURVE_MANAGER_CONF_PATH = "/curve-manager/conf/pigeon.yaml" +) + +func getNodeExporterAddrs(hosts []string, port int) string { + endpoint := []string{} + for _, item := range hosts { + endpoint = append(endpoint, fmt.Sprintf("'%s:%d'", item, port)) + } + return fmt.Sprintf("[%s]", strings.Join(endpoint, ",")) +} + +func NewSyncConfigTask(curveadm *cli.CurveAdm, cfg *configure.MonitorConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(cfg.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if IsSkip(cfg, []string{ROLE_MONITOR_CONF, ROLE_NODE_EXPORTER}) { + return nil, nil + } else if err != nil { + return nil, err + } + + role, host := cfg.GetRole(), cfg.GetHost() + hc, err := curveadm.GetHost(host) + if err != nil { + return nil, err + } + + // new task + subname := fmt.Sprintf("host=%s role=%s containerId=%s", + cfg.GetHost(), cfg.GetRole(), tui.TrimContainerId(containerId)) + t := task.NewTask("Sync Config", subname, hc.GetSSHConfig(), hc.GetHttpConfig()) + // add step to task + var out string + t.AddStep(&step.ListContainers{ // gurantee container exist + ShowAll: true, + Format: `"{{.ID}}"`, + Filter: fmt.Sprintf("id=%s", containerId), + Out: &out, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: common.CheckContainerExist(cfg.GetHost(), cfg.GetRole(), containerId, &out), + }) + if role == ROLE_PROMETHEUS { + t.AddStep(&step.CreateAndUploadDir{ // prepare prometheus conf upath + HostDirName: "prometheus", + ContainerDestId: &containerId, + ContainerDestPath: "/etc", + ExecOptions: curveadm.ExecOptions(), + }) + content := fmt.Sprintf(scripts.PROMETHEUS_YML, cfg.GetListenPort(), + getNodeExporterAddrs(cfg.GetNodeIps(), cfg.GetNodeListenPort())) + t.AddStep(&step.InstallFile{ // install prometheus.yml file + ContainerId: &containerId, + ContainerDestPath: path.Join(PROMETHEUS_CONTAINER_PATH, "prometheus.yml"), + Content: &content, + ExecOptions: curveadm.ExecOptions(), + }) + target := cfg.GetPrometheusTarget() + t.AddStep(&step.InstallFile{ // install target.json file + ContainerId: &containerId, + ContainerDestPath: path.Join(PROMETHEUS_CONTAINER_PATH, "target.json"), + Content: &target, + ExecOptions: curveadm.ExecOptions(), + }) + } else if role == ROLE_GRAFANA { + serviceId = curveadm.GetServiceId(fmt.Sprintf("%s_%s", ROLE_MONITOR_CONF, cfg.GetHost())) + confContainerId, err := curveadm.GetContainerId(serviceId) + if err != nil { + return nil, err + } + t.AddStep(&step.SyncFileDirectly{ // sync grafana.ini file + ContainerSrcId: &confContainerId, + ContainerSrcPath: path.Join("/", cfg.GetKind(), MONITOR_CONF_PATH, "grafana/grafana.ini"), + ContainerDestId: &containerId, + ContainerDestPath: GRAFANA_CONTAINER_PATH, + IsDir: false, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.SyncFileDirectly{ // sync dashboard dir + ContainerSrcId: &confContainerId, + ContainerSrcPath: path.Join("/", cfg.GetKind(), MONITOR_CONF_PATH, "grafana/provisioning/dashboards"), + ContainerDestId: &containerId, + ContainerDestPath: DASHBOARD_CONTAINER_PATH, + IsDir: true, + ExecOptions: curveadm.ExecOptions(), + }) + content := fmt.Sprintf(scripts.GRAFANA_DATA_SOURCE, cfg.GetPrometheusIp(), cfg.GetPrometheusListenPort()) + t.AddStep(&step.InstallFile{ // install grafana datasource file + ContainerId: &containerId, + ContainerDestPath: GRAFANA_DATA_SOURCE_PATH, + Content: &content, + ExecOptions: curveadm.ExecOptions(), + }) + } + return t, nil +} diff --git a/internal/task/task/playground/create.go b/internal/task/task/playground/create.go index 68b0823b6..05e534d57 100644 --- a/internal/task/task/playground/create.go +++ b/internal/task/task/playground/create.go @@ -100,7 +100,7 @@ func NewCreatePlaygroundTask(curveadm *cli.CurveAdm, cfg *configure.PlaygroundCo // new task subname := fmt.Sprintf("kind=%s name=%s image=%s", kind, name, containerImage) - t := task.NewTask("Create Playground", subname, nil) + t := task.NewTask("Create Playground", subname, nil, nil) var containerId string // add step to task diff --git a/internal/task/task/playground/init.go b/internal/task/task/playground/init.go index 1b59f4f9c..9360fd532 100644 --- a/internal/task/task/playground/init.go +++ b/internal/task/task/playground/init.go @@ -29,6 +29,7 @@ import ( "strings" "github.com/opencurve/curveadm/cli/cli" + comm "github.com/opencurve/curveadm/internal/common" "github.com/opencurve/curveadm/internal/configure" "github.com/opencurve/curveadm/internal/configure/topology" "github.com/opencurve/curveadm/internal/errno" @@ -91,8 +92,8 @@ func checkContainerExist(name string, out *string) step.LambdaType { } } -func prepare(dcs []*topology.DeployConfig) (string, error) { - pool, err := configure.GenerateDefaultClusterPool(dcs) +func prepare(dcs []*topology.DeployConfig, poolset configure.Poolset) (string, error) { + pool, err := configure.GenerateDefaultClusterPool(dcs, poolset) if err != nil { return "", err } @@ -105,13 +106,14 @@ func NewInitPlaygroundTask(curveadm *cli.CurveAdm, cfg *configure.PlaygroundConf kind := cfg.GetKind() name := cfg.GetName() subname := fmt.Sprintf("kind=%s name=%s", kind, name) - t := task.NewTask("Init Playground", subname, nil) + t := task.NewTask("Init Playground", subname, nil, nil) // add step to task var containerId string layout := topology.GetCurveBSProjectLayout() poolJSONPath := path.Join(layout.ToolsConfDir, "topology.json") - clusterPoolJson, err := prepare(cfg.GetDeployConfigs()) + poolset := curveadm.MemStorage().Get(comm.KEY_POOLSET).(configure.Poolset) + clusterPoolJson, err := prepare(cfg.GetDeployConfigs(), poolset) if err != nil { return nil, err } diff --git a/internal/task/task/playground/list.go b/internal/task/task/playground/list.go index efb382323..1ce567985 100644 --- a/internal/task/task/playground/list.go +++ b/internal/task/task/playground/list.go @@ -83,14 +83,13 @@ func NewGetPlaygroundStatusTask(curveadm *cli.CurveAdm, v interface{}) (*task.Ta // new task playground := v.(storage.Playground) subname := fmt.Sprintf("id=%d name=%s", playground.Id, playground.Name) - t := task.NewTask("Get Playground Status", subname, nil) + t := task.NewTask("Get Playground Status", subname, nil, nil) // add step to task var status string t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.Status}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", playground.Name), Out: &status, ExecOptions: execOptions(curveadm), diff --git a/internal/task/task/playground/remove.go b/internal/task/task/playground/remove.go index 53aad3484..4d92a8424 100644 --- a/internal/task/task/playground/remove.go +++ b/internal/task/task/playground/remove.go @@ -95,14 +95,13 @@ func NewRemovePlaygroundTask(curveadm *cli.CurveAdm, v interface{}) (*task.Task, // new task playground := v.(storage.Playground) subname := fmt.Sprintf("name=%s", playground.Name) - t := task.NewTask("Remove Playground", subname, nil) + t := task.NewTask("Remove Playground", subname, nil, nil) // add step to task var containerId string t.AddStep(&step.ListContainers{ ShowAll: true, Format: "'{{.ID}}'", - Quiet: true, Filter: fmt.Sprintf("name=%s", playground.Name), Out: &containerId, ExecOptions: execOptions(curveadm), diff --git a/internal/task/task/playground/start.go b/internal/task/task/playground/start.go index 535fc4915..bbbc2ba83 100644 --- a/internal/task/task/playground/start.go +++ b/internal/task/task/playground/start.go @@ -43,7 +43,7 @@ func wait(seconds int) step.LambdaType { func NewStartPlaygroundTask(curveadm *cli.CurveAdm, cfg *configure.PlaygroundConfig) (*task.Task, error) { // new task subname := fmt.Sprintf("kind=%s name=%s", cfg.GetKind(), cfg.GetName()) - t := task.NewTask("Start Playground", subname, nil) + t := task.NewTask("Start Playground", subname, nil, nil) // add step to task containerId := cfg.GetName() diff --git a/internal/task/task/task.go b/internal/task/task/task.go index 47a6fa6f2..be836c006 100644 --- a/internal/task/task/task.go +++ b/internal/task/task/task.go @@ -44,25 +44,27 @@ type ( } Task struct { - tid string // task id - ptid string // parent task id - name string - subname string - steps []Step - postSteps []Step - sshConfig *module.SSHConfig - context context.Context + tid string // task id + ptid string // parent task id + name string + subname string + steps []Step + postSteps []Step + sshConfig *module.SSHConfig + httpConfig *module.HttpConfig + context context.Context } ) -func NewTask(name, subname string, sshConfig *module.SSHConfig) *Task { +func NewTask(name, subname string, sshConfig *module.SSHConfig, httpConfig *module.HttpConfig) *Task { tid := uuid.NewString()[:12] return &Task{ - tid: tid, - ptid: tid, - name: name, - subname: subname, - sshConfig: sshConfig, + tid: tid, + ptid: tid, + name: name, + subname: subname, + sshConfig: sshConfig, + httpConfig: httpConfig, } } @@ -112,16 +114,22 @@ func (t *Task) executePost(ctx *context.Context) { } func (t *Task) Execute() error { - var sshClient *module.SSHClient + var remoteClient module.RemoteClient if t.sshConfig != nil { client, err := module.NewSSHClient(*t.sshConfig) if err != nil { return errno.ERR_SSH_CONNECT_FAILED.E(err) } - sshClient = client + remoteClient = client + } else if t.httpConfig != nil { + client, err := module.NewHttpClient(*t.httpConfig) + if err != nil { + return errno.ERR_HTTP_CONNECT_FAILED.E(err) + } + remoteClient = client } - ctx, err := context.NewContext(sshClient) + ctx, err := context.NewContext(remoteClient) if err != nil { return err } diff --git a/internal/task/tasks/tasks.go b/internal/task/tasks/tasks.go index 4322dc9d7..a680a68dc 100644 --- a/internal/task/tasks/tasks.go +++ b/internal/task/tasks/tasks.go @@ -121,7 +121,7 @@ func (ts *Tasks) displayStatus() func(static decor.Statistics) string { } } -func (ts *Tasks) displayReplica(t *task.Task) func(static decor.Statistics) string { +func (ts *Tasks) displayInstance(t *task.Task) func(static decor.Statistics) string { total := ts.CountPtid(t.Ptid()) return func(static decor.Statistics) string { nsucc, nskip, _ := ts.monitor.sum(static.ID) @@ -149,7 +149,7 @@ func (ts *Tasks) addSubBar(t *task.Task) { mpb.PrependDecorators( decor.Name(" + "), decor.Name(t.Subname()+" "), - decor.Any(ts.displayReplica(t), decor.WCSyncWidthR), + decor.Any(ts.displayInstance(t), decor.WCSyncWidthR), decor.Name(" "), decor.OnComplete(decor.Spinner([]string{}), ""), decor.Any(ts.displayStatus()), diff --git a/internal/tasks/tasks.go b/internal/tasks/tasks.go index 687317c31..6e32c9029 100644 --- a/internal/tasks/tasks.go +++ b/internal/tasks/tasks.go @@ -123,7 +123,7 @@ func (ts *Tasks) displayStatus() func(static decor.Statistics) string { } } -func (ts *Tasks) displayReplicas(t *task.Task) func(static decor.Statistics) string { +func (ts *Tasks) displayInstances(t *task.Task) func(static decor.Statistics) string { total := ts.CountPtid(t.Ptid()) return func(static decor.Statistics) string { nsucc, nskip, _ := ts.monitor.sum(static.ID) @@ -151,7 +151,7 @@ func (ts *Tasks) addSubBar(t *task.Task) { mpb.PrependDecorators( decor.Name(" + "), decor.Name(t.Subname()+" "), - decor.Any(ts.displayReplicas(t), decor.WCSyncWidthR), + decor.Any(ts.displayInstances(t), decor.WCSyncWidthR), decor.Name(" "), decor.OnComplete(decor.Spinner([]string{}), ""), decor.Any(ts.displayStatus()), diff --git a/internal/tools/ssh.go b/internal/tools/ssh.go index 25f1a19b7..ec516018c 100644 --- a/internal/tools/ssh.go +++ b/internal/tools/ssh.go @@ -40,9 +40,9 @@ const ( TEMPLATE_SCP = `scp -P {{.port}} {{or .options ""}} {{.source}} {{.user}}@{{.host}}:{{.target}}` TEMPLATE_SSH_COMMAND = `ssh {{.user}}@{{.host}} -p {{.port}} {{or .options ""}} {{or .become ""}} {{.command}}` TEMPLATE_SSH_ATTACH = `ssh -tt {{.user}}@{{.host}} -p {{.port}} {{or .options ""}} {{or .become ""}} {{.command}}` - TEMPLATE_COMMAND_EXEC_CONTAINER = `{{.sudo}} docker exec -it {{.container_id}} /bin/bash -c "cd {{.home_dir}}; /bin/bash"` - TEMPLATE_LOCAL_EXEC_CONTAINER = `docker exec -it {{.container_id}} /bin/bash` // FIXME: merge it - TEMPLATE_COMMAND_EXEC_CONTAINER_NOATTACH = `{{.sudo}} docker exec -t {{.container_id}} /bin/bash -c "{{.command}}"` + TEMPLATE_COMMAND_EXEC_CONTAINER = `{{.sudo}} {{.engine}} exec -it {{.container_id}} /bin/bash -c "cd {{.home_dir}}; /bin/bash"` + TEMPLATE_LOCAL_EXEC_CONTAINER = `{{.engine}} exec -it {{.container_id}} /bin/bash` // FIXME: merge it + TEMPLATE_COMMAND_EXEC_CONTAINER_NOATTACH = `{{.sudo}} {{.engine}} exec -t {{.container_id}} /bin/bash -c "{{.command}}"` ) func prepareOptions(curveadm *cli.CurveAdm, host string, become bool, extra map[string]interface{}) (map[string]interface{}, error) { @@ -138,6 +138,7 @@ func AttachRemoteHost(curveadm *cli.CurveAdm, host string, become bool) error { func AttachRemoteContainer(curveadm *cli.CurveAdm, host, containerId, home string) error { data := map[string]interface{}{ "sudo": curveadm.Config().GetSudoAlias(), + "engine": curveadm.Config().GetEngine(), "container_id": containerId, "home_dir": home, } @@ -159,6 +160,7 @@ func AttachRemoteContainer(curveadm *cli.CurveAdm, host, containerId, home strin func AttachLocalContainer(curveadm *cli.CurveAdm, containerId string) error { data := map[string]interface{}{ "container_id": containerId, + "engine": curveadm.Config().GetEngine(), } tmpl := template.Must(template.New("command").Parse(TEMPLATE_LOCAL_EXEC_CONTAINER)) buffer := bytes.NewBufferString("") @@ -172,6 +174,7 @@ func AttachLocalContainer(curveadm *cli.CurveAdm, containerId string) error { func ExecCmdInRemoteContainer(curveadm *cli.CurveAdm, host, containerId, cmd string) error { data := map[string]interface{}{ "sudo": curveadm.Config().GetSudoAlias(), + "engine": curveadm.Config().GetEngine(), "container_id": containerId, "command": cmd, } diff --git a/internal/tui/client/status.go b/internal/tui/client/status.go index b61ed0c31..8544707e1 100644 --- a/internal/tui/client/status.go +++ b/internal/tui/client/status.go @@ -33,7 +33,7 @@ import ( func statusDecorate(status string) string { switch status { - case comm.CLIENT_STATUS_LOSED: + case comm.CLIENT_STATUS_LOSED, comm.CLIENT_STATUS_UNKNOWN: return color.RedString(status) } return status @@ -61,6 +61,9 @@ func FormatStatus(statuses []task.ClientStatus, verbose bool) string { "Status", "Aux Info", } + if verbose { + title = append(title, "Config Dumpfile") + } first, second := tui.FormatTitle(title) lines = append(lines, first) lines = append(lines, second) @@ -68,14 +71,21 @@ func FormatStatus(statuses []task.ClientStatus, verbose bool) string { // status sortStatues(statuses) for _, status := range statuses { - lines = append(lines, []interface{}{ + // line + line := []interface{}{ status.Id, status.Kind, status.Host, tui.TrimContainerId(status.ContainerId), tui.DecorateMessage{Message: status.Status, Decorate: statusDecorate}, status.AuxInfo, - }) + } + if verbose { + line = append(line, status.CfgPath) + } + + // lines + lines = append(lines, line) } output := tui.FixedFormat(lines, 2) diff --git a/internal/tui/hosts.go b/internal/tui/hosts.go index 9a19ba983..67366c89c 100644 --- a/internal/tui/hosts.go +++ b/internal/tui/hosts.go @@ -45,6 +45,8 @@ func FormatHosts(hcs []*configure.HostConfig, verbose bool) string { "Hostname", "User", "Port", + "Protocol", + "HTTP Port", "Private Key File", "Forward Agent", "Become User", @@ -60,8 +62,10 @@ func FormatHosts(hcs []*configure.HostConfig, verbose bool) string { host := hc.GetHost() hostname := hc.GetHostname() + protocol := hc.GetProtocol() user := hc.GetUser() port := strconv.Itoa(hc.GetSSHPort()) + httpPort := strconv.Itoa(hc.GetHTTPPort()) forwardAgent := utils.Choose(hc.GetForwardAgent(), "Y", "N") becomeUser := utils.Choose(len(hc.GetBecomeUser()) > 0, hc.GetBecomeUser(), "-") labels := utils.Choose(len(hc.GetLabels()) > 0, strings.Join(hc.GetLabels(), ","), "-") @@ -78,6 +82,8 @@ func FormatHosts(hcs []*configure.HostConfig, verbose bool) string { hostname, user, port, + protocol, + httpPort, privateKeyFile, forwardAgent, becomeUser, diff --git a/internal/tui/service/status.go b/internal/tui/service/status.go index f743dbbcd..23117b178 100644 --- a/internal/tui/service/status.go +++ b/internal/tui/service/status.go @@ -32,8 +32,10 @@ import ( "github.com/fatih/color" longest "github.com/jpillora/longestcommon" comm "github.com/opencurve/curveadm/internal/common" + "github.com/opencurve/curveadm/internal/configure" "github.com/opencurve/curveadm/internal/configure/topology" task "github.com/opencurve/curveadm/internal/task/task/common" + "github.com/opencurve/curveadm/internal/task/task/monitor" tui "github.com/opencurve/curveadm/internal/tui/common" "github.com/opencurve/curveadm/internal/utils" ) @@ -55,7 +57,7 @@ const ( STATUS_CLEANED = comm.SERVICE_STATUS_CLEANED STATUS_LOSED = comm.SERVICE_STATUS_LOSED STATUS_UNKNWON = comm.SERVICE_STATUS_UNKNOWN - // for replica merged status + // for instance merged status STATUS_RUNNING = "RUNNING" STATUS_STOPPED = "STOPPED" STATUS_ABNORMAL = "ABNORMAL" @@ -69,6 +71,11 @@ var ( ROLE_METASERVER: 2, ROLE_SNAPSHOTCLONE: 3, } + MONITOT_ROLE_SCORE = map[string]int{ + configure.ROLE_NODE_EXPORTER: 0, + configure.ROLE_PROMETHEUS: 1, + configure.ROLE_GRAFANA: 2, + } ) func statusDecorate(status string) string { @@ -87,7 +94,7 @@ func sortStatues(statuses []task.ServiceStatus) { c1, c2 := s1.Config, s2.Config if s1.Role == s2.Role { if c1.GetHostSequence() == c2.GetHostSequence() { - return c1.GetReplicasSequence() < c2.GetReplicasSequence() + return c1.GetInstancesSequence() < c2.GetInstancesSequence() } return c1.GetHostSequence() < c2.GetHostSequence() } @@ -99,7 +106,7 @@ func id(items []string) string { if len(items) == 1 { return items[0] } - return "" + return "" } func status(items []string) string { @@ -186,7 +193,7 @@ func mergeStatues(statuses []task.ServiceStatus) []task.ServiceStatus { Id: merge(statuses[i:j], ITEM_ID), Role: status.Role, Host: status.Host, - Replica: fmt.Sprintf("%d/%s", j-i, strings.Split(status.Replica, "/")[1]), + Instances: fmt.Sprintf("%d/%s", j-i, strings.Split(status.Instances, "/")[1]), ContainerId: merge(statuses[i:j], ITEM_CONTAINER_ID), Status: merge(statuses[i:j], ITEM_STATUS), Ports: merge(statuses[i:j], ITEM_PORTS), @@ -206,7 +213,7 @@ func FormatStatus(statuses []task.ServiceStatus, verbose, expand bool) string { "Id", "Role", "Host", - "Replicas", + "Instances", "Container Id", "Status", "Ports", @@ -227,7 +234,7 @@ func FormatStatus(statuses []task.ServiceStatus, verbose, expand bool) string { status.Id, status.Role, status.Host, - status.Replica, + status.Instances, status.ContainerId, tui.DecorateMessage{Message: status.Status, Decorate: statusDecorate}, utils.Choose(len(status.Ports) == 0, "-", status.Ports), @@ -247,3 +254,55 @@ func FormatStatus(statuses []task.ServiceStatus, verbose, expand bool) string { output := tui.FixedFormat(lines, 2) return output } + +func sortMonitorStatues(statuses []monitor.MonitorStatus) { + sort.Slice(statuses, func(i, j int) bool { + s1, s2 := statuses[i], statuses[j] + if s1.Role == s2.Role { + return s1.Host < s1.Host + } + return MONITOT_ROLE_SCORE[s1.Role] < ROLE_SCORE[s2.Role] + }) +} + +func FormatMonitorStatus(statuses []monitor.MonitorStatus, verbose bool) string { + lines := [][]interface{}{} + + // title + title := []string{ + "Id", + "Role", + "Host", + "Container Id", + "Status", + "Ports", + "Data Dir", + } + first, second := tui.FormatTitle(title) + lines = append(lines, first) + lines = append(lines, second) + + // status + sortMonitorStatues(statuses) + for _, status := range statuses { + lines = append(lines, []interface{}{ + status.Id, + status.Role, + status.Host, + status.ContainerId, + tui.DecorateMessage{Message: status.Status, Decorate: statusDecorate}, + utils.Choose(len(status.Ports) == 0, "-", status.Ports), + status.DataDir, + }) + } + + // cut column + locate := utils.Locate(title) + if !verbose { + tui.CutColumn(lines, locate["Ports"]) // Data Dir + tui.CutColumn(lines, locate["Data Dir"]) // Data Dir + } + + output := tui.FixedFormat(lines, 2) + return output +} diff --git a/internal/utils/file.go b/internal/utils/file.go index cca1bf602..0ecd12aa3 100644 --- a/internal/utils/file.go +++ b/internal/utils/file.go @@ -33,6 +33,7 @@ import ( type VariantName struct { Name string CompressName string + LocalCompressName string EncryptCompressName string } @@ -44,6 +45,7 @@ func NewVariantName(name string) VariantName { return VariantName{ Name: name, CompressName: fmt.Sprintf("%s.tar.gz", name), + LocalCompressName: fmt.Sprintf("%s.local.tar.gz", name), EncryptCompressName: fmt.Sprintf("%s-encrypted.tar.gz", name), } } diff --git a/internal/utils/file_test.go b/internal/utils/file_test.go new file mode 100644 index 000000000..108149afe --- /dev/null +++ b/internal/utils/file_test.go @@ -0,0 +1,16 @@ +package utils + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestVariantName(t *testing.T) { + assert := assert.New(t) + vname := NewVariantName("test") + assert.Equal("test", vname.Name) + assert.Equal("test.tar.gz", vname.CompressName) + assert.Equal("test.local.tar.gz", vname.LocalCompressName) + assert.Equal("test-encrypted.tar.gz", vname.EncryptCompressName) +} diff --git a/pkg/module/docker_cli.go b/pkg/module/docker_cli.go index 83fe1ccfd..926fc5fef 100644 --- a/pkg/module/docker_cli.go +++ b/pkg/module/docker_cli.go @@ -31,35 +31,36 @@ import ( ) const ( - TEMPLATE_DOCKER_INFO = "docker info" - TEMPLATE_PULL_IMAGE = "docker pull {{.options}} {{.name}}" - TEMPLATE_CREATE_CONTAINER = "docker create {{.options}} {{.image}} {{.command}}" - TEMPLATE_START_CONTAINER = "docker start {{.options}} {{.containers}}" - TEMPLATE_STOP_CONTAINER = "docker stop {{.options}} {{.containers}}" - TEMPLATE_RESTART_CONTAINER = "docker restart {{.options}} {{.containers}}" - TEMPLATE_WAIT_CONTAINER = "docker wait {{.options}} {{.containers}}" - TEMPLATE_REMOVE_CONTAINER = "docker rm {{.options}} {{.containers}}" - TEMPLATE_LIST_CONTAINERS = "docker ps {{.options}}" - TEMPLATE_CONTAINER_EXEC = "docker exec {{.options}} {{.container}} {{.command}}" - TEMPLATE_COPY_FROM_CONTAINER = "docker cp {{.options}} {{.container}}:{{.srcPath}} {{.destPath}}" - TEMPLATE_COPY_INTO_CONTAINER = "docker cp {{.options}} {{.srcPath}} {{.container}}:{{.destPath}}" - TEMPLATE_INSPECT_CONTAINER = "docker inspect {{.options}} {{.container}}" - TEMPLATE_CONTAINER_LOGS = "docker logs {{.options}} {{.container}}" + TEMPLATE_DOCKER_INFO = "{{.engine}} info" + TEMPLATE_PULL_IMAGE = "{{.engine}} pull {{.options}} {{.name}}" + TEMPLATE_CREATE_CONTAINER = "{{.engine}} create {{.options}} {{.image}} {{.command}}" + TEMPLATE_START_CONTAINER = "{{.engine}} start {{.options}} {{.containers}}" + TEMPLATE_STOP_CONTAINER = "{{.engine}} stop {{.options}} {{.containers}}" + TEMPLATE_RESTART_CONTAINER = "{{.engine}} restart {{.options}} {{.containers}}" + TEMPLATE_WAIT_CONTAINER = "{{.engine}} wait {{.options}} {{.containers}}" + TEMPLATE_REMOVE_CONTAINER = "{{.engine}} rm {{.options}} {{.containers}}" + TEMPLATE_LIST_CONTAINERS = "{{.engine}} ps {{.options}}" + TEMPLATE_CONTAINER_EXEC = "{{.engine}} exec {{.options}} {{.container}} {{.command}}" + TEMPLATE_COPY_FROM_CONTAINER = "{{.engine}} cp {{.options}} {{.container}}:{{.srcPath}} {{.destPath}}" + TEMPLATE_COPY_INTO_CONTAINER = "{{.engine}} cp {{.options}} {{.srcPath}} {{.container}}:{{.destPath}}" + TEMPLATE_INSPECT_CONTAINER = "{{.engine}} inspect {{.options}} {{.container}}" + TEMPLATE_CONTAINER_LOGS = "{{.engine}} logs {{.options}} {{.container}}" + TEMPLATE_UPDATE_CONTAINER = "{{.engine}} update {{.options}} {{.container}}" ) type DockerCli struct { - sshClient *SSHClient - options []string - tmpl *template.Template - data map[string]interface{} + options []string + tmpl *template.Template + data map[string]interface{} + remoteClient RemoteClient } -func NewDockerCli(sshClient *SSHClient) *DockerCli { +func NewDockerCli(remoteClient RemoteClient) *DockerCli { return &DockerCli{ - sshClient: sshClient, - options: []string{}, - tmpl: nil, - data: map[string]interface{}{}, + remoteClient: remoteClient, + options: []string{}, + tmpl: nil, + data: map[string]interface{}{}, } } @@ -70,7 +71,8 @@ func (s *DockerCli) AddOption(format string, args ...interface{}) *DockerCli { func (cli *DockerCli) Execute(options ExecOptions) (string, error) { cli.data["options"] = strings.Join(cli.options, " ") - return execCommand(cli.sshClient, cli.tmpl, cli.data, options) + cli.data["engine"] = options.ExecWithEngine + return execCommand(cli.remoteClient, cli.tmpl, cli.data, options) } func (cli *DockerCli) DockerInfo() *DockerCli { diff --git a/pkg/module/file.go b/pkg/module/file.go index 6d428d87b..4a8f49062 100644 --- a/pkg/module/file.go +++ b/pkg/module/file.go @@ -27,7 +27,6 @@ package module import ( "errors" "fmt" - "io/ioutil" "os" log "github.com/opencurve/curveadm/pkg/log/glg" @@ -42,35 +41,36 @@ var ( ) type FileManager struct { - sshClient *SSHClient + remoteClient RemoteClient } -func NewFileManager(sshClient *SSHClient) *FileManager { - return &FileManager{sshClient: sshClient} +func NewFileManager(remoteClient RemoteClient) *FileManager { + return &FileManager{remoteClient: remoteClient} } func (f *FileManager) Upload(localPath, remotePath string) error { - if f.sshClient == nil { + if f.remoteClient == nil { return ERR_UNREACHED } - err := f.sshClient.Client().Upload(localPath, remotePath) + err := f.remoteClient.Upload(localPath, remotePath) log.SwitchLevel(err)("UploadFile", - log.Field("remoteAddress", remoteAddr(f.sshClient)), + log.Field("remoteAddress", remoteAddr(f.remoteClient)), log.Field("localPath", localPath), log.Field("remotePath", remotePath), - log.Field("error", err)) + log.Field("error", err), + log.Field("protocol", f.remoteClient.Protocol())) return err } func (f *FileManager) Download(remotePath, localPath string) error { - if f.sshClient == nil { + if f.remoteClient == nil { return ERR_UNREACHED } - err := f.sshClient.Client().Download(remotePath, localPath) + err := f.remoteClient.Download(remotePath, localPath) log.SwitchLevel(err)("DownloadFile", - log.Field("remoteAddress", remoteAddr(f.sshClient)), + log.Field("remoteAddress", remoteAddr(f.remoteClient)), log.Field("remotePath", remotePath), log.Field("localPath", localPath), log.Field("error", err)) @@ -78,7 +78,7 @@ func (f *FileManager) Download(remotePath, localPath string) error { } func (f *FileManager) Install(content, destPath string) error { - file, err := ioutil.TempFile(TEMP_DIR, "curevadm.*.install") + file, err := os.CreateTemp(TEMP_DIR, "curevadm.*.install") if err != nil { return err } diff --git a/pkg/module/http.go b/pkg/module/http.go new file mode 100644 index 000000000..51213b7b8 --- /dev/null +++ b/pkg/module/http.go @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2021 NetEase Inc. + * + * 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 module + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + log "github.com/opencurve/curveadm/pkg/log/glg" + "io" + "mime/multipart" + "net/http" + "net/url" + "os" +) + +const ( + HTTP_PROTOCOL = "http" +) + +type ( + HttpConfig struct { + Host string + Port uint + } + + HttpClient struct { + config HttpConfig + client *http.Client + } + + HttpResult struct { + Data string `json:"data"` + ErrorCode string `json:"errorCode"` + ErrorMsg string `json:"errorMsg"` + } +) + +func (client *HttpClient) Protocol() string { + return HTTP_PROTOCOL +} + +func (client *HttpClient) WrapperCommand(command string, execInLocal bool) (wrapperCmd string) { + return command +} + +func (client *HttpClient) RunCommand(ctx context.Context, command string) (out []byte, err error) { + data := make(map[string]interface{}) + data["command"] = command + bytesData, _ := json.Marshal(data) + + baseURL, _ := url.Parse(fmt.Sprintf("http://%s:%d", client.config.Host, client.config.Port)) + params := url.Values{} + params.Add("method", "cluster.deploy.cmd") + baseURL.RawQuery = params.Encode() + resp, err := client.client.Post(baseURL.String(), "application/json", bytes.NewReader(bytesData)) + if err != nil { + return + } + respData, err := io.ReadAll(resp.Body) + if err != nil { + return + } + result := &HttpResult{} + err = json.Unmarshal(respData, result) + if err != nil { + return + } + + log.Info("http resp", log.Field("result", result)) + + if result.ErrorCode != "0" { + return []byte(result.Data), fmt.Errorf(result.ErrorMsg) + } + + return []byte(result.Data), nil +} + +func (client *HttpClient) RemoteAddr() (addr string) { + config := client.Config() + return fmt.Sprintf("%s:%d", config.Host, config.Port) +} + +func (client *HttpClient) Upload(localPath string, remotePath string) (err error) { + bodyBuf := &bytes.Buffer{} + bodyWriter := multipart.NewWriter(bodyBuf) + fh, err := os.Open(localPath) + if err != nil { + return err + } + defer fh.Close() + fileWriter, err := bodyWriter.CreateFormFile("file", localPath) + if err != nil { + return err + } + _, err = io.Copy(fileWriter, fh) + if err != nil { + return err + } + + baseURL, _ := url.Parse(fmt.Sprintf("http://%s:%d", client.config.Host, client.config.Port)) + params := url.Values{} + params.Add("method", "cluster.deploy.upload") + baseURL.RawQuery = params.Encode() + boundary := "--boundary" + bodyWriter.SetBoundary(boundary) + bodyWriter.WriteField("filepath", remotePath) + bodyWriter.Close() + resp, err := client.client.Post(baseURL.String(), bodyWriter.FormDataContentType(), bodyBuf) + if err != nil { + return err + } + defer resp.Body.Close() + return err +} + +func (client *HttpClient) Download(remotePath string, localPath string) (err error) { + baseURL, _ := url.Parse(fmt.Sprintf("http://%s:%d", client.config.Host, client.config.Port)) + params := url.Values{} + params.Add("method", "cluster.deploy.download") + params.Add("filepath", remotePath) + baseURL.RawQuery = params.Encode() + resp, err := client.client.Get(baseURL.String()) + if err != nil { + return + } + defer resp.Body.Close() + localFile, err := os.Create(localPath) + if err != nil { + return + } + defer localFile.Close() + _, err = io.Copy(localFile, resp.Body) + return +} + +func (client *HttpClient) Close() { + +} + +func (client *HttpClient) Config() HttpConfig { + return client.config +} + +func NewHttpClient(config HttpConfig) (*HttpClient, error) { + return &HttpClient{ + config: config, + client: &http.Client{}, + }, nil +} diff --git a/pkg/module/module.go b/pkg/module/module.go index 9d82a7fe5..5ff2bbf8b 100644 --- a/pkg/module/module.go +++ b/pkg/module/module.go @@ -33,13 +33,12 @@ import ( "text/template" "time" - "github.com/melbahja/goph" log "github.com/opencurve/curveadm/pkg/log/glg" ) type ( Module struct { - sshClient *SSHClient + remoteClient RemoteClient } ExecOptions struct { @@ -47,6 +46,7 @@ type ( ExecInLocal bool ExecSudoAlias string ExecTimeoutSec int + ExecWithEngine string } TimeoutError struct { @@ -59,33 +59,31 @@ func (e *TimeoutError) Error() string { e.timeout) } -func NewModule(sshClient *SSHClient) *Module { - return &Module{sshClient: sshClient} +func NewModule(remoteClient RemoteClient) *Module { + return &Module{remoteClient: remoteClient} } func (m *Module) Shell() *Shell { - return NewShell(m.sshClient) + return NewShell(m.remoteClient) } func (m *Module) File() *FileManager { - return NewFileManager(m.sshClient) + return NewFileManager(m.remoteClient) } func (m *Module) DockerCli() *DockerCli { - return NewDockerCli(m.sshClient) + return NewDockerCli(m.remoteClient) } // common utils -func remoteAddr(client *SSHClient) string { +func remoteAddr(client RemoteClient) string { if client == nil { return "-" } - - config := client.Config() - return fmt.Sprintf("%s@%s:%d", config.User, config.Host, config.Port) + return client.RemoteAddr() } -func execCommand(sshClient *SSHClient, +func execCommand(remoteClient RemoteClient, tmpl *template.Template, data map[string]interface{}, options ExecOptions) (string, error) { @@ -107,14 +105,8 @@ func execCommand(sshClient *SSHClient, command = strings.TrimLeft(command, " ") // (3) handle 'become_user' - if sshClient != nil { - becomeMethod := sshClient.Config().BecomeMethod - becomeFlags := sshClient.Config().BecomeFlags - becomeUser := sshClient.Config().BecomeUser - if len(becomeUser) > 0 && !options.ExecInLocal { - become := strings.Join([]string{becomeMethod, becomeFlags, becomeUser}, " ") - command = strings.Join([]string{become, command}, " ") - } + if remoteClient != nil { + command = remoteClient.WrapperCommand(command, options.ExecInLocal) } // (4) create context for timeout @@ -133,12 +125,7 @@ func execCommand(sshClient *SSHClient, cmd.Env = []string{"LANG=en_US.UTF-8"} out, err = cmd.CombinedOutput() } else { - var cmd *goph.Cmd - cmd, err = sshClient.Client().CommandContext(ctx, command) - if err == nil { - cmd.Env = []string{"LANG=en_US.UTF-8"} - out, err = cmd.CombinedOutput() - } + out, err = remoteClient.RunCommand(ctx, command) } if ctx.Err() == context.DeadlineExceeded { @@ -146,7 +133,7 @@ func execCommand(sshClient *SSHClient, } log.SwitchLevel(err)("Execute command", - log.Field("remoteAddr", remoteAddr(sshClient)), + log.Field("remoteAddr", remoteAddr(remoteClient)), log.Field("command", command), log.Field("output", strings.TrimSuffix(string(out), "\n")), log.Field("error", err)) diff --git a/pkg/module/remote_client.go b/pkg/module/remote_client.go new file mode 100644 index 000000000..93dcdcac3 --- /dev/null +++ b/pkg/module/remote_client.go @@ -0,0 +1,15 @@ +package module + +import ( + "context" +) + +type RemoteClient interface { + Protocol() string + WrapperCommand(command string, execInLocal bool) (wrapperCmd string) + RunCommand(ctx context.Context, command string) (out []byte, err error) + RemoteAddr() (addr string) + Upload(localPath string, remotePath string) (err error) + Download(remotePath string, localPath string) (err error) + Close() +} diff --git a/pkg/module/shell.go b/pkg/module/shell.go index b9f246a6f..9c7114cc2 100644 --- a/pkg/module/shell.go +++ b/pkg/module/shell.go @@ -48,9 +48,11 @@ const ( TEMPLATE_MKFS = "mkfs.ext4 {{.options}} {{.device}}" TEMPLATE_MOUNT = "mount {{.options}} {{.source}} {{.directory}}" TEMPLATE_UMOUNT = "umount {{.options}} {{.directory}}" + TEMPLATE_TUNE2FS = "tune2fs {{.options}} {{.device}}" TEMPLATE_FUSER = "fuser {{.options}} {{.names}}" TEMPLATE_DISKFREE = "df {{.options}} {{.files}}" TEMPLATE_LSBLK = "lsblk {{.options}} {{.devices}}" + TEMPLATE_BLKID = "blkid {{.options}} {{.device}}" // network TEMPLATE_SS = "ss {{.options}} '{{.filter}}'" @@ -72,23 +74,23 @@ const ( // bash TEMPLATE_COMMAND = "{{.command}}" - TEMPLATE_BASH_SCEIPT = "{{.scriptPath}} {{.arguments}}" + TEMPLATE_BASH_SCEIPT = "bash {{.scriptPath}} {{.arguments}}" ) // TODO(P1): support command pipe type Shell struct { - sshClient *SSHClient - options []string - tmpl *template.Template - data map[string]interface{} + remoteClient RemoteClient + options []string + tmpl *template.Template + data map[string]interface{} } -func NewShell(sshClient *SSHClient) *Shell { +func NewShell(remoteClient RemoteClient) *Shell { return &Shell{ - sshClient: sshClient, - options: []string{}, - tmpl: nil, - data: map[string]interface{}{}, + remoteClient: remoteClient, + options: []string{}, + tmpl: nil, + data: map[string]interface{}{}, } } @@ -109,7 +111,7 @@ func (s *Shell) String() (string, error) { func (s *Shell) Execute(options ExecOptions) (string, error) { s.data["options"] = strings.Join(s.options, " ") - return execCommand(s.sshClient, s.tmpl, s.data, options) + return execCommand(s.remoteClient, s.tmpl, s.data, options) } // text @@ -196,6 +198,12 @@ func (s *Shell) Umount(directory string) *Shell { return s } +func (s *Shell) Tune2FS(device string) *Shell { + s.tmpl = template.Must(template.New("tune2fs").Parse(TEMPLATE_TUNE2FS)) + s.data["device"] = device + return s +} + func (s *Shell) Fuser(name ...string) *Shell { s.tmpl = template.Must(template.New("fuser").Parse(TEMPLATE_FUSER)) s.data["names"] = strings.Join(name, " ") @@ -214,6 +222,12 @@ func (s *Shell) LsBlk(device ...string) *Shell { return s } +func (s *Shell) BlkId(device string) *Shell { + s.tmpl = template.Must(template.New("blkid").Parse(TEMPLATE_BLKID)) + s.data["device"] = device + return s +} + // network func (s *Shell) SocketStatistics(filter string) *Shell { s.tmpl = template.Must(template.New("ss").Parse(TEMPLATE_SS)) diff --git a/pkg/module/ssh.go b/pkg/module/ssh.go index 4e8abf889..990aab263 100644 --- a/pkg/module/ssh.go +++ b/pkg/module/ssh.go @@ -25,8 +25,11 @@ package module import ( + "context" "errors" + "fmt" "net" + "strings" "time" "github.com/melbahja/goph" @@ -34,6 +37,10 @@ import ( "golang.org/x/crypto/ssh" ) +const ( + SSH_PROTOCOL = "ssh" +) + type ( SSHConfig struct { User string @@ -151,3 +158,45 @@ connect: config: config, }, err } + +func (client *SSHClient) WrapperCommand(command string, execInLocal bool) string { + becomeMethod := client.Config().BecomeMethod + becomeFlags := client.Config().BecomeFlags + becomeUser := client.Config().BecomeUser + if len(becomeUser) > 0 && !execInLocal { + become := strings.Join([]string{becomeMethod, becomeFlags, becomeUser}, " ") + command = strings.Join([]string{become, command}, " ") + } + return command +} + +func (client *SSHClient) RunCommand(ctx context.Context, command string) (out []byte, err error) { + var cmd *goph.Cmd + cmd, err = client.Client().CommandContext(ctx, command) + if err == nil { + cmd.Env = []string{"LANG=en_US.UTF-8"} + out, err = cmd.CombinedOutput() + } + return +} + +func (client *SSHClient) RemoteAddr() (addr string) { + config := client.Config() + return fmt.Sprintf("%s@%s:%d", config.User, config.Host, config.Port) +} + +func (client *SSHClient) Upload(localPath string, remotePath string) (err error) { + return client.client.Upload(localPath, remotePath) +} + +func (client *SSHClient) Download(remotePath string, localPath string) (err error) { + return client.client.Download(remotePath, localPath) +} + +func (client *SSHClient) Close() { + client.client.Close() +} + +func (client *SSHClient) Protocol() string { + return SSH_PROTOCOL +} diff --git a/playbook/logs/scripts/rotate.sh b/playbook/logs/scripts/rotate.sh new file mode 100644 index 000000000..57439422a --- /dev/null +++ b/playbook/logs/scripts/rotate.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +# Usage: bash rotate.sh /mnt/logs/curvefs/client 86400 + +############################ GLOBAL VARIABLES +g_log_dir="$1" +g_color_yellow=$(printf '\033[33m') +g_color_red=$(printf '\033[31m') +g_color_normal=$(printf '\033[0m') + +############################ BASIC FUNCTIONS +msg() { + printf '%b' "${1}" >&2 +} + +success() { + msg "${g_color_yellow}[✔]${g_color_normal} ${1}${2}" +} + +die() { + msg "${g_color_red}[✘]${g_color_normal} ${1}${2}" + exit 1 +} + +############################ FUNCTIONS +precheck() { + local log_dir="$1" + if [ ! -d "${log_dir}" ]; then + die "Log directory ${log_dir} does not exist.\n" + fi + + if [ ! -w "${log_dir}" ]; then + die "Log directory ${log_dir} is not writable.\n" + fi +} + +expired() { + local path="$1" + local timeout="$2" + local mtime=$(stat -c %Y "${path}") + local now=$(date +%s) + if (( now - mtime > timeout )); then + return 0 + fi + return 1 +} + +delete() { + local path="$1" + rm "${path}" + success "Delete ${path}\n" +} + +rotate() { + local log_dir="$1" + local timeout="$2" + for file in $(ls "${log_dir}" | grep -E '(access|curve-fuse|aws)(.+)(\.log)?'); do + local path="${log_dir}/${file}" + if expired "${path}" "${timeout}"; then + delete "${path}" + fi + done +} + +main() { + local log_dir="$1" + local timeout="$2" # seconds + precheck "${log_dir}" + rotate "${log_dir}" "${timeout}" +} + +############################ MAIN() +main "$@" diff --git a/playbook/memcached/hosts.yaml b/playbook/memcached/hosts.yaml index d79e2cccd..ee69994cc 100644 --- a/playbook/memcached/hosts.yaml +++ b/playbook/memcached/hosts.yaml @@ -9,6 +9,8 @@ hosts: labels: - memcached envs: + - SUDO_ALIAS=sudo + - ENGINE=docker - IMAGE=memcached:1.6.17 - LISTEN=10.0.1.1 - PORT=11211 @@ -18,11 +20,16 @@ hosts: - EXT_PATH=/mnt/memcachefile/cachefile:1024G - EXT_WBUF_SIZE=8 # size in megabytes of page write buffers. - EXT_ITEM_AGE=1 # store items idle at least this long (seconds, default: no age limit) + - VERBOSE="v" # v: verbose (print errors/warnings while in event loop) + # vv: very verbose (also print client commands/responses) + # vvv: extremely verbose (internal state transitions) - host: server-host2 hostname: 10.0.1.2 labels: - memcached envs: + - SUDO_ALIAS=sudo + - ENGINE=docker - IMAGE=memcached:1.6.17 - LISTEN=10.0.1.2 - PORT=11211 @@ -32,11 +39,16 @@ hosts: - EXT_PATH=/mnt/memcachefile/cachefile:1024G - EXT_WBUF_SIZE=8 # size in megabytes of page write buffers. - EXT_ITEM_AGE=1 # store items idle at least this long (seconds, default: no age limit) + - VERBOSE="v" # v: verbose (print errors/warnings while in event loop) + # vv: very verbose (also print client commands/responses) + # vvv: extremely verbose (internal state transitions) - host: server-host3 hostname: 10.0.1.3 labels: - memcached envs: + - SUDO_ALIAS=sudo + - ENGINE=docker - IMAGE=memcached:1.6.17 - LISTEN=10.0.1.3 - PORT=11211 @@ -46,3 +58,6 @@ hosts: - EXT_PATH=/mnt/memcachefile/cachefile:1024G - EXT_WBUF_SIZE=8 # size in megabytes of page write buffers. - EXT_ITEM_AGE=1 # store items idle at least this long (seconds, default: no age limit) + - VERBOSE="v" # v: verbose (print errors/warnings while in event loop) + # vv: very verbose (also print client commands/responses) + # vvv: extremely verbose (internal state transitions) diff --git a/playbook/memcached/scripts/clean.sh b/playbook/memcached/scripts/clean.sh index 2de697677..84e0f2a6a 100644 --- a/playbook/memcached/scripts/clean.sh +++ b/playbook/memcached/scripts/clean.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash g_container_name="memcached-"${PORT} -g_docker_cmd="${SUDO_ALIAS} docker" +g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" +g_rm_cmd="${SUDO_ALIAS} rm -rf" function msg() { printf '%b' "$1" >&2 @@ -33,5 +34,11 @@ stop_container() { success "rm container[${g_container_name}]\n" } +rm_cachefile() { + cachefile_path=(${EXT_PATH//:/ }) + ${g_rm_cmd} ${cachefile_path} +} + precheck stop_container +rm_cachefile diff --git a/playbook/memcached/scripts/deploy.sh b/playbook/memcached/scripts/deploy.sh index 070dc2437..f2c48b165 100644 --- a/playbook/memcached/scripts/deploy.sh +++ b/playbook/memcached/scripts/deploy.sh @@ -2,8 +2,11 @@ g_container_name="memcached-"${PORT} g_start_args="" -g_docker_cmd="${SUDO_ALIAS} docker" +g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" g_lsof_cmd="${SUDO_ALIAS} lsof" +g_rm_cmd="${SUDO_ALIAS} rm -rf" +g_mkdir_cmd="${SUDO_ALIAS} mkdir -p" +g_touch_cmd="${SUDO_ALIAS} touch" g_volume_bind="" g_status="" g_user="" @@ -37,11 +40,10 @@ precheck() { # check ext path if [ "${EXT_PATH}" ]; then - volume_path=(${EXT_PATH//:/ }) - if [ -f ${volume_path} ]; then - die "no file[${volume_path}]" - exit 1 - fi + cachefile_path=(${EXT_PATH//:/ }) + ${g_rm_cmd} ${cachefile_path} + ${g_mkdir_cmd} $(dirname ${cachefile_path}) + ${g_touch_cmd} ${cachefile_path} fi } @@ -74,6 +76,9 @@ init() { if [ "${EXT_ITEM_AGE}" ]; then g_start_args="${g_start_args} --extended ext_item_age=${EXT_ITEM_AGE}" fi + if [ "${VERBOSE}" ];then + g_start_args="${g_start_args} -${VERBOSE}" + fi } create_container() { diff --git a/playbook/memcached/scripts/start.sh b/playbook/memcached/scripts/start.sh new file mode 100644 index 000000000..9c7c380fa --- /dev/null +++ b/playbook/memcached/scripts/start.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +g_container_name="memcached-"${PORT} +g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" +g_rm_cmd="${SUDO_ALIAS} rm -rf" +g_mkdir_cmd="${SUDO_ALIAS} mkdir -p" +g_touch_cmd="${SUDO_ALIAS} touch" +g_status="running" + +function msg() { + printf '%b' "$1" >&2 +} + +function success() { + msg "\33[32m[✔]\33[0m ${1}${2}" +} + +function die() { + msg "\33[31m[✘]\33[0m ${1}${2}" + exit 1 +} + +precheck() { + # check ext path + get_status_container + if [ "${EXT_PATH}" ] && [ ${g_status} != "running" ]; then + cachefile_path=(${EXT_PATH//:/ }) + ${g_rm_cmd} ${cachefile_path} + ${g_mkdir_cmd} $(dirname ${cachefile_path}) + ${g_touch_cmd} ${cachefile_path} + fi +} + +start_container() { + ${g_docker_cmd} start ${g_container_name} >& /dev/null + success "start container[${g_container_name}]\n" +} + +get_status_container() { + g_status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_container_name}` +} + +precheck +start_container diff --git a/playbook/memcached/scripts/status.sh b/playbook/memcached/scripts/status.sh index f3bc5314b..ed875ec85 100644 --- a/playbook/memcached/scripts/status.sh +++ b/playbook/memcached/scripts/status.sh @@ -2,9 +2,10 @@ g_container_name="memcached-"${PORT} g_start_args="" -g_docker_cmd="${SUDO_ALIAS} docker" +g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" g_volume_bind="" g_container_id="" +g_status="running" function msg() { printf '%b' "$1" >&2 @@ -35,6 +36,14 @@ show_ip_port() { printf "memcached addr:\t%s:%d\n" ${LISTEN} ${PORT} } +get_status_container() { + g_status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_container_name}` + if [ ${g_status} != "running" ]; then + exit 1 + fi +} + precheck +show_ip_port show_info_container -show_ip_port \ No newline at end of file +get_status_container diff --git a/playbook/memcached/scripts/stop.sh b/playbook/memcached/scripts/stop.sh index 117e4ac99..2dc84e53f 100644 --- a/playbook/memcached/scripts/stop.sh +++ b/playbook/memcached/scripts/stop.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash g_container_name="memcached-"${PORT} -g_docker_cmd="${SUDO_ALIAS} docker" +g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" function msg() { printf '%b' "$1" >&2 diff --git a/scripts/install.sh b/scripts/install.sh index c22e34b6d..1a7b2e7d3 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,60 +1,58 @@ #!/usr/bin/env bash ############################ GLOBAL VARIABLES -g_color_yellow=`printf '\033[33m'` -g_color_red=`printf '\033[31m'` -g_color_normal=`printf '\033[0m'` -g_curveadm_home="$HOME/.curveadm" -g_bin_dir="$g_curveadm_home/bin" +g_color_yellow=$(printf '\033[33m') +g_color_red=$(printf '\033[31m') +g_color_normal=$(printf '\033[0m') +g_curveadm_home="${HOME}/.curveadm" +g_bin_dir="${g_curveadm_home}/bin" +g_db_path="${g_curveadm_home}/data/curveadm.db" g_profile="${HOME}/.profile" g_root_url="https://curveadm.nos-eastchina1.126.net/release" g_latest_url="${g_root_url}/__version" g_latest_version=$(curl -Is $g_latest_url | awk 'BEGIN {FS=": "}; /^x-nos-meta-curveadm-latest-version/{print $2}') g_latest_version=${g_latest_version//[$'\t\r\n ']} -g_upgrade="$CURVEADM_UPGRADE" +g_upgrade="${CURVEADM_UPGRADE}" g_version="${CURVEADM_VERSION:=$g_latest_version}" g_download_url="${g_root_url}/curveadm-${g_version}.tar.gz" -g_plugin="$CURVEADM_PLUGIN" -g_plugin_dir="$g_curveadm_home/plugins/$g_plugin" -g_plugin_url="https://curveadm.nos-eastchina1.126.net/plugins/${g_plugin}-$(uname -m).tar.gz" ############################ BASIC FUNCTIONS msg() { - printf '%b' "$1" >&2 + printf '%b' "${1}" >&2 } success() { - msg "$g_color_yellow[✔]$g_color_normal ${1}${2}" + msg "${g_color_yellow}[✔]${g_color_normal} ${1}${2}" } die() { - msg "$g_color_red[✘]$g_color_normal ${1}${2}" + msg "${g_color_red}[✘]${g_color_normal} ${1}${2}" exit 1 } program_must_exist() { local ret='0' - command -v $1 >/dev/null 2>&1 || { local ret='1'; } + command -v "${1}" >/dev/null 2>&1 || { local ret='1'; } - if [ "$ret" -ne 0 ]; then + if [ "${ret}" -ne 0 ]; then die "You must have '$1' installed to continue.\n" fi } ############################ FUNCTIONS backup() { - if [ -d "$g_curveadm_home" ]; then - mv $g_curveadm_home "${g_curveadm_home}-$(date +%s).backup" + if [ -d "${g_curveadm_home}" ]; then + mv "${g_curveadm_home}" "${g_curveadm_home}-$(date +%s).backup" fi } setup() { - mkdir -p $g_curveadm_home/{bin,data,plugins,logs,temp} + mkdir -p "${g_curveadm_home}"/{bin,data,module,logs,temp} # generate config file - local confpath="$g_curveadm_home/curveadm.cfg" - if [ ! -f $confpath ]; then - cat << __EOF__ > $confpath + local confpath="${g_curveadm_home}/curveadm.cfg" + if [ ! -f "${confpath}" ]; then + cat << __EOF__ > "${confpath}" [defaults] log_level = error sudo_alias = "sudo" @@ -64,6 +62,9 @@ auto_upgrade = true [ssh_connections] retries = 3 timeout = 10 + +[database] +url = "${g_db_path}" __EOF__ fi } @@ -71,40 +72,22 @@ __EOF__ install_binray() { local ret=1 local tempfile="/tmp/curveadm-$(date +%s%6N).tar.gz" - curl $g_download_url -skLo $tempfile + curl "${g_download_url}" -skLo "${tempfile}" if [ $? -eq 0 ]; then - tar -zxvf $tempfile -C $g_curveadm_home --strip-components=1 1>/dev/null + tar -zxvf "${tempfile}" -C "${g_curveadm_home}" --strip-components=1 1>/dev/null ret=$? fi - rm $tempfile - if [ $ret -eq 0 ]; then - chmod 755 "$g_bin_dir/curveadm" + rm "${tempfile}" + if [ ${ret} -eq 0 ]; then + chmod 755 "${g_bin_dir}/curveadm" else die "Download curveadm failed\n" fi } -install_plugin() { - local ret=1 - mkdir -p $g_plugin_dir - local tempfile="/tmp/curveadm-plugin-$g_plugin-$(date +%s%6N).tar.gz" - curl $g_plugin_url -sLo $tempfile - if [ $? -eq 0 ]; then - tar -zxvf $tempfile -C $g_plugin_dir --strip-components=1 1>/dev/null - ret=$? - fi - - rm $tempfile - if [ $ret -eq 0 ]; then - success "Plugin '$g_plugin' installed\n" - else - die "Download plugin '$g_plugin' failed\n" - fi -} - set_profile() { - shell=`echo $SHELL | awk 'BEGIN {FS="/";} { print $NF }'` + shell=$(echo "$SHELL" | awk 'BEGIN {FS="/";} { print $NF }') if [ -f "${HOME}/.${shell}_profile" ]; then g_profile="${HOME}/.${shell}_profile" elif [ -f "${HOME}/.${shell}_login" ]; then @@ -113,21 +96,21 @@ set_profile() { g_profile="${HOME}/.${shell}rc" fi - case :$PATH: in - *:$g_bin_dir:*) ;; - *) echo "export PATH=$g_bin_dir:\$PATH" >> $g_profile ;; + case :${PATH}: in + *:${g_bin_dir}:*) ;; + *) echo "export PATH=${g_bin_dir}:\${PATH}" >> "${g_profile}" ;; esac } print_install_success() { - success "Install curveadm $g_version success, please run 'source $g_profile'\n" + success "Install curveadm ${g_version} success, please run 'source ${g_profile}'\n" } print_upgrade_success() { - if [ -f "$g_curveadm_home/CHANGELOG" ]; then - cat "$g_curveadm_home/CHANGELOG" + if [ -f "${g_curveadm_home}/CHANGELOG" ]; then + cat "${g_curveadm_home}/CHANGELOG" fi - success "Upgrade curveadm to $g_version success\n" + success "Upgrade curveadm to ${g_version} success\n" } install() { @@ -144,9 +127,7 @@ upgrade() { } main() { - if [ ! -z $g_plugin ]; then - install_plugin - elif [ "$g_upgrade" == "true" ]; then + if [ "${g_upgrade}" == "true" ]; then upgrade else install