Skip to content

Commit

Permalink
playground: support semver constraint (#1325)
Browse files Browse the repository at this point in the history
  • Loading branch information
unbyte authored Apr 22, 2021
1 parent 77a57d1 commit 4ffe6e5
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 48 deletions.
2 changes: 1 addition & 1 deletion cmd/mirror.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ func newMirrorRotateCmd() *cobra.Command {
}

func editLatestRootManifest() (*v1manifest.Root, error) {
root, err := environment.GlobalEnv().V1Repository().FetchRootManfiest()
root, err := environment.GlobalEnv().V1Repository().FetchRootManifest()
if err != nil {
return nil, err
}
Expand Down
92 changes: 47 additions & 45 deletions components/playground/playground.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/pingcap/tiup/components/playground/instance"
"github.com/pingcap/tiup/pkg/cliutil/progress"
"github.com/pingcap/tiup/pkg/cluster/api"
"github.com/pingcap/tiup/pkg/cluster/spec"
"github.com/pingcap/tiup/pkg/environment"
"github.com/pingcap/tiup/pkg/utils"
"golang.org/x/mod/semver"
Expand Down Expand Up @@ -264,7 +265,7 @@ func (p *Playground) handleScaleIn(w io.Writer, pid int) error {
}

switch cid {
case "pd":
case spec.ComponentPD:
for i := 0; i < len(p.pds); i++ {
if p.pds[i].Pid() == pid {
inst := p.pds[i]
Expand All @@ -275,7 +276,7 @@ func (p *Playground) handleScaleIn(w io.Writer, pid int) error {
p.pds = append(p.pds[:i], p.pds[i+1:]...)
}
}
case "tikv":
case spec.ComponentTiKV:
for i := 0; i < len(p.tikvs); i++ {
if p.tikvs[i].Pid() == pid {
inst := p.tikvs[i]
Expand All @@ -289,19 +290,19 @@ func (p *Playground) handleScaleIn(w io.Writer, pid int) error {
return nil
}
}
case "tidb":
case spec.ComponentTiDB:
for i := 0; i < len(p.tidbs); i++ {
if p.tidbs[i].Pid() == pid {
p.tidbs = append(p.tidbs[:i], p.tidbs[i+1:]...)
}
}
case "ticdc":
case spec.ComponentCDC:
for i := 0; i < len(p.ticdcs); i++ {
if p.ticdcs[i].Pid() == pid {
p.ticdcs = append(p.ticdcs[:i], p.ticdcs[i+1:]...)
}
}
case "tiflash":
case spec.ComponentTiFlash:
for i := 0; i < len(p.tiflashs); i++ {
if p.tiflashs[i].Pid() == pid {
inst := p.tiflashs[i]
Expand All @@ -315,7 +316,7 @@ func (p *Playground) handleScaleIn(w io.Writer, pid int) error {
return nil
}
}
case "pump":
case spec.ComponentPump:
for i := 0; i < len(p.pumps); i++ {
if p.pumps[i].Pid() == pid {
inst := p.pumps[i]
Expand All @@ -334,7 +335,7 @@ func (p *Playground) handleScaleIn(w io.Writer, pid int) error {
return nil
}
}
case "drainer":
case spec.ComponentDrainer:
for i := 0; i < len(p.drainers); i++ {
if p.drainers[i].Pid() == pid {
inst := p.drainers[i]
Expand Down Expand Up @@ -391,19 +392,19 @@ func (p *Playground) sanitizeConfig(boot instance.Config, cfg *instance.Config)

func (p *Playground) sanitizeComponentConfig(cid string, cfg *instance.Config) error {
switch cid {
case "pd":
case spec.ComponentPD:
return p.sanitizeConfig(p.bootOptions.pd, cfg)
case "tikv":
case spec.ComponentTiKV:
return p.sanitizeConfig(p.bootOptions.tikv, cfg)
case "tidb":
case spec.ComponentTiDB:
return p.sanitizeConfig(p.bootOptions.tidb, cfg)
case "tiflash":
case spec.ComponentTiFlash:
return p.sanitizeConfig(p.bootOptions.tiflash, cfg)
case "ticdc":
case spec.ComponentCDC:
return p.sanitizeConfig(p.bootOptions.ticdc, cfg)
case "pump":
case spec.ComponentPump:
return p.sanitizeConfig(p.bootOptions.pump, cfg)
case "drainer":
case spec.ComponentDrainer:
return p.sanitizeConfig(p.bootOptions.drainer, cfg)
default:
return fmt.Errorf("unknown %s in sanitizeConfig", cid)
Expand Down Expand Up @@ -530,48 +531,48 @@ func (p *Playground) RWalkInstances(fn func(componentID string, ins instance.Ins
// WalkInstances call fn for every instance and stop if return not nil.
func (p *Playground) WalkInstances(fn func(componentID string, ins instance.Instance) error) error {
for _, ins := range p.pds {
err := fn("pd", ins)
err := fn(spec.ComponentPD, ins)
if err != nil {
return err
}
}
for _, ins := range p.tikvs {
err := fn("tikv", ins)
err := fn(spec.ComponentTiKV, ins)
if err != nil {
return err
}
}

for _, ins := range p.pumps {
err := fn("pump", ins)
err := fn(spec.ComponentPump, ins)
if err != nil {
return err
}
}

for _, ins := range p.tidbs {
err := fn("tidb", ins)
err := fn(spec.ComponentTiDB, ins)
if err != nil {
return err
}
}

for _, ins := range p.ticdcs {
err := fn("ticdc", ins)
err := fn(spec.ComponentCDC, ins)
if err != nil {
return err
}
}

for _, ins := range p.drainers {
err := fn("drainer", ins)
err := fn(spec.ComponentDrainer, ins)
if err != nil {
return err
}
}

for _, ins := range p.tiflashs {
err := fn("tiflash", ins)
err := fn(spec.ComponentTiFlash, ins)
if err != nil {
return err
}
Expand Down Expand Up @@ -612,7 +613,7 @@ func (p *Playground) addInstance(componentID string, cfg instance.Config) (ins i
host = instance.AdvertiseHost(host)

switch componentID {
case "pd":
case spec.ComponentPD:
inst := instance.NewPDInstance(cfg.BinPath, dir, host, cfg.ConfigPath, id)
ins = inst
if p.booted {
Expand All @@ -624,27 +625,27 @@ func (p *Playground) addInstance(componentID string, cfg instance.Config) (ins i
pd.InitCluster(p.pds)
}
}
case "tidb":
case spec.ComponentTiDB:
inst := instance.NewTiDBInstance(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds, p.enableBinlog())
ins = inst
p.tidbs = append(p.tidbs, inst)
case "tikv":
case spec.ComponentTiKV:
inst := instance.NewTiKVInstance(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds)
ins = inst
p.tikvs = append(p.tikvs, inst)
case "tiflash":
case spec.ComponentTiFlash:
inst := instance.NewTiFlashInstance(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds, p.tidbs)
ins = inst
p.tiflashs = append(p.tiflashs, inst)
case "ticdc":
case spec.ComponentCDC:
inst := instance.NewTiCDC(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds)
ins = inst
p.ticdcs = append(p.ticdcs, inst)
case "pump":
case spec.ComponentPump:
inst := instance.NewPump(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds)
ins = inst
p.pumps = append(p.pumps, inst)
case "drainer":
case spec.ComponentDrainer:
inst := instance.NewDrainer(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds)
ins = inst
p.drainers = append(p.drainers, inst)
Expand All @@ -670,19 +671,20 @@ func (p *Playground) bootCluster(ctx context.Context, env *environment.Environme
return fmt.Errorf("all components count must be great than 0 (tikv=%v, pd=%v)", options.tikv.Num, options.pd.Num)
}

if options.version == "" {
version, _, err := env.V1Repository().LatestStableVersion("tidb", false)
{
version, err := env.V1Repository().ResolveComponentVersion(spec.ComponentTiDB, options.version)
if err != nil {
return err
}
options.version = version.String()

fmt.Println(color.YellowString(`No TiDB version specified, using the latest stable version: %s
fmt.Println(color.YellowString(`Using the version %s for version constraint "%s".
If you'd like to use a TiDB version other than %s, cancel and retry with the following arguments:
Specify version manually: tiup playground <version>
Specify version range: tiup playground ^5
The nightly version: tiup playground nightly
`, options.version, options.version))
`, version, options.version, version))

options.version = version.String()
}

if !utils.Version(options.version).IsNightly() {
Expand All @@ -700,13 +702,13 @@ If you'd like to use a TiDB version other than %s, cancel and retry with the fol
comp string
instance.Config
}{
{"pd", options.pd},
{"tikv", options.tikv},
{"pump", options.pump},
{"tidb", options.tidb},
{"ticdc", options.ticdc},
{"drainer", options.drainer},
{"tiflash", options.tiflash},
{spec.ComponentPD, options.pd},
{spec.ComponentTiKV, options.tikv},
{spec.ComponentPump, options.pump},
{spec.ComponentTiDB, options.tidb},
{spec.ComponentCDC, options.ticdc},
{spec.ComponentDrainer, options.drainer},
{spec.ComponentTiFlash, options.tiflash},
}

for _, inst := range instances {
Expand Down Expand Up @@ -758,7 +760,7 @@ If you'd like to use a TiDB version other than %s, cancel and retry with the fol
anyPumpReady := false
// Start all instance except tiflash.
err := p.WalkInstances(func(cid string, ins instance.Instance) error {
if cid == "tiflash" {
if cid == spec.ComponentTiFlash {
return nil
}

Expand All @@ -768,7 +770,7 @@ If you'd like to use a TiDB version other than %s, cancel and retry with the fol
}

// if no any pump, tidb will quit right away.
if cid == "pump" && !anyPumpReady {
if cid == spec.ComponentPump && !anyPumpReady {
ctx, cancel := context.WithTimeout(context.TODO(), time.Second*120)
err = ins.(*instance.Pump).Ready(ctx)
cancel()
Expand Down Expand Up @@ -883,7 +885,7 @@ If you'd like to use a TiDB version other than %s, cancel and retry with the fol
}

if monitorInfo != nil {
p.updateMonitorTopology("prometheus", *monitorInfo)
p.updateMonitorTopology(spec.ComponentPrometheus, *monitorInfo)
}

dumpDSN(filepath.Join(p.dataDir, "dsn"), p.tidbs)
Expand All @@ -899,7 +901,7 @@ If you'd like to use a TiDB version other than %s, cancel and retry with the fol
logIfErr(p.renderSDFile())

if g := p.grafana; g != nil {
p.updateMonitorTopology("grafana", MonitorInfo{g.host, g.port, g.cmd.Path})
p.updateMonitorTopology(spec.ComponentGrafana, MonitorInfo{g.host, g.port, g.cmd.Path})
}

return nil
Expand Down
57 changes: 55 additions & 2 deletions pkg/repository/v1_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"path"
"path/filepath"
"runtime"
"sort"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -635,8 +636,8 @@ func (r *V1Repository) loadRoot() (*v1manifest.Root, error) {
return root, nil
}

// FetchRootManfiest fetch the root manifest.
func (r *V1Repository) FetchRootManfiest() (root *v1manifest.Root, err error) {
// FetchRootManifest fetch the root manifest.
func (r *V1Repository) FetchRootManifest() (root *v1manifest.Root, err error) {
err = r.ensureManifests()
if err != nil {
return nil, err
Expand Down Expand Up @@ -740,6 +741,58 @@ func (r *V1Repository) ComponentVersion(id, ver string, includeYanked bool) (*v1
return vi, nil
}

// ResolveComponentVersion resolves the latest version of a component that satisfies the constraint
func (r *V1Repository) ResolveComponentVersion(id, constraint string) (utils.Version, error) {
manifest, err := r.FetchComponentManifest(id, false)
if err != nil {
return "", err
}
var ver string
switch constraint {
case "", utils.LatestVersionAlias:
v, _, err := r.LatestStableVersion(id, false)
if err != nil {
return "", err
}
ver = v.String()
case utils.NightlyVersionAlias:
if !manifest.HasNightly(r.PlatformString()) {
return "", errors.Annotatef(ErrUnknownVersion, "component %s does not have nightly on %s", id, r.PlatformString())
}
ver = manifest.Nightly
default:
cons, err := utils.NewConstraint(constraint)
if err != nil {
return "", err
}
versions := manifest.VersionList(r.PlatformString())
verList := make([]string, 0, len(versions))
for v := range versions {
if v == manifest.Nightly {
continue
}
verList = append(verList, v)
}
sort.Slice(verList, func(p, q int) bool {
return semver.Compare(verList[p], verList[q]) > 0
})
for _, v := range verList {
if cons.Check(v) {
ver = v
break
}
}
}
if ver == "" {
return "", fmt.Errorf(`no version on %s for component %s satisfies constraint "%s"`, r.PlatformString(), id, constraint)
}
vi := manifest.VersionItem(r.PlatformString(), ver, false)
if vi == nil {
return "", errors.Annotatef(ErrUnknownVersion, "version %s on %s for component %s not found", ver, r.PlatformString(), id)
}
return utils.Version(ver), nil
}

// LatestNightlyVersion returns the latest nightly version of specific component
func (r *V1Repository) LatestNightlyVersion(id string) (utils.Version, *v1manifest.VersionItem, error) {
com, err := r.FetchComponentManifest(id, false)
Expand Down
14 changes: 14 additions & 0 deletions pkg/utils/regexp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package utils

import "regexp"

// MatchGroups turns a slice of matched string to a map according to capture group name
func MatchGroups(r *regexp.Regexp, str string) map[string]string {
matched := r.FindStringSubmatch(str)
results := make(map[string]string)
names := r.SubexpNames()
for i, value := range matched {
results[names[i]] = value
}
return results
}
Loading

0 comments on commit 4ffe6e5

Please sign in to comment.