Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2ffed5c98 |
No files matched your search
+6
-59
@@ -27,7 +27,6 @@ type buildResult struct {
|
||||
Verified []string `json:"verified"`
|
||||
Problems []string `json:"problems"`
|
||||
Summary string `json:"summary"`
|
||||
Tried []string `json:"tried,omitempty"` // each image tried, and how it went
|
||||
}
|
||||
|
||||
const defaultAgentImage = "www.gitea.gbreed.com/gbreed-public/gbr-node-agent:latest"
|
||||
@@ -94,67 +93,21 @@ type buildOptions struct {
|
||||
agentImage string
|
||||
}
|
||||
|
||||
// build tries the variant's images in order (research puts SteamCMD first when the game ships a Linux
|
||||
// server) and keeps the first draft that boots. A draft that can't be made to work with one image is set
|
||||
// aside and the next image gets a fresh start; if none works, the draft that got furthest is returned.
|
||||
// build drafts the template for exactly the option the admin chose: one image (research lists each way to
|
||||
// run a game as its own option). It never switches to another image; if the chosen one can't be made to
|
||||
// work, the result says so and the admin can pick a different option.
|
||||
func build(o buildOptions) (*buildResult, error) {
|
||||
var candidates []string
|
||||
for _, image := range o.variant.Images {
|
||||
if isSteamCMDImage(image) && o.variant.SteamAppID == "" {
|
||||
continue // the SteamCMD image alone runs nothing
|
||||
}
|
||||
candidates = append(candidates, image)
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
return nil, errors.New("the variant has no image to build from")
|
||||
}
|
||||
dir := filepath.Join(o.gamesDir, o.id)
|
||||
setAside := filepath.Join("firstboot-out", o.id+"-best-draft")
|
||||
var best *buildResult
|
||||
var tried []string
|
||||
for i, image := range candidates {
|
||||
if i > 0 {
|
||||
fmt.Printf("[build] trying the next image: %s\n", image)
|
||||
}
|
||||
res, err := buildWithImage(o, image)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
tried = append(tried, attemptNote(res))
|
||||
if res.Passed {
|
||||
res.Tried = tried
|
||||
if res != nil {
|
||||
res.Summary = buildSummary(o, res)
|
||||
return res, nil
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(dir, "game.yaml")); err == nil {
|
||||
// This one got a draft written: keep it in case no later image does better
|
||||
os.RemoveAll(setAside)
|
||||
if err := os.Rename(dir, setAside); err != nil {
|
||||
return res, err
|
||||
}
|
||||
best = res
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
if best == nil {
|
||||
return &buildResult{GameID: o.id, Dir: dir, Tried: tried, Problems: []string{"no image of this variant could be drafted"}},
|
||||
errors.New("no image of this variant could be drafted: " + strings.Join(tried, "; "))
|
||||
}
|
||||
if err := os.Rename(setAside, dir); err != nil {
|
||||
return best, err
|
||||
}
|
||||
best.Tried = tried
|
||||
best.Summary = buildSummary(o, best)
|
||||
return best, nil
|
||||
}
|
||||
|
||||
func attemptNote(res *buildResult) string {
|
||||
switch {
|
||||
case res.Passed:
|
||||
return res.Image + ": booted"
|
||||
case len(res.Problems) > 0:
|
||||
return res.Image + ": " + firstLine(res.Problems[0])
|
||||
}
|
||||
return res.Image + ": did not boot"
|
||||
return nil, errors.New("the variant has no image to build from")
|
||||
}
|
||||
|
||||
// buildWithImage drafts the template for one image: first boot, draft, then boots of the draft with
|
||||
@@ -461,12 +414,6 @@ func buildSummary(o buildOptions, res *buildResult) string {
|
||||
fmt.Fprintf(&b, ", Steam app %s", o.variant.SteamAppID)
|
||||
}
|
||||
fmt.Fprintf(&b, "\n- Model rounds: %d\n", res.Rounds)
|
||||
if len(res.Tried) > 1 {
|
||||
b.WriteString("\n**Images tried, in order**\n")
|
||||
for _, t := range res.Tried {
|
||||
fmt.Fprintf(&b, "- %s\n", firstLine(t))
|
||||
}
|
||||
}
|
||||
if len(res.Verified) > 0 {
|
||||
b.WriteString("\n**Checked for real**\n")
|
||||
for _, v := range res.Verified {
|
||||
|
||||
@@ -329,7 +329,7 @@ func verifyVariants(res *researchResult) {
|
||||
v.Verified = append(v.Verified, fmt.Sprintf("Steam app %s is %q", v.SteamAppID, app.name))
|
||||
v.Images = withSteamCMD(v.Images, app.linux)
|
||||
if app.linux {
|
||||
v.Verified = append(v.Verified, "it ships a Linux server, so SteamCMD (installing it into /server) is tried first")
|
||||
v.Verified = append(v.Verified, "it ships a Linux server, so the SteamCMD option (installing it into /server) is recommended")
|
||||
}
|
||||
} else {
|
||||
v.Problems = append(v.Problems, "Steam app "+v.SteamAppID+" not found for anonymous SteamCMD")
|
||||
@@ -348,6 +348,7 @@ func verifyVariants(res *researchResult) {
|
||||
res.Reason = "unknown"
|
||||
res.Message = "No variant has a Docker image or Steam app that could be confirmed. " + res.Message
|
||||
}
|
||||
res.Variants = oneOptionPerImage(res.Variants)
|
||||
recommend(res.Variants)
|
||||
}
|
||||
|
||||
@@ -431,3 +432,37 @@ func withSteamCMD(images []string, linux bool) []string {
|
||||
}
|
||||
return append(others, "cm2network/steamcmd")
|
||||
}
|
||||
|
||||
// oneOptionPerImage turns a variant that can run on several images into one choice per image, so the
|
||||
// admin picks exactly how the server runs and the build uses that and nothing else.
|
||||
func oneOptionPerImage(variants []variant) []variant {
|
||||
var out []variant
|
||||
for _, v := range variants {
|
||||
if len(v.Images) <= 1 {
|
||||
out = append(out, v)
|
||||
continue
|
||||
}
|
||||
for _, img := range v.Images {
|
||||
o := v
|
||||
o.Images = []string{img}
|
||||
o.Verified = nil
|
||||
for _, line := range v.Verified {
|
||||
if !strings.HasPrefix(line, "image ") || line == "image "+img+" exists" {
|
||||
o.Verified = append(o.Verified, line)
|
||||
}
|
||||
}
|
||||
if isSteamCMDImage(img) {
|
||||
o.ID = v.ID + "-steamcmd"
|
||||
o.Title = v.Title + " (SteamCMD)"
|
||||
o.Description = strings.TrimSpace(v.Description + " Installed with SteamCMD into the server volume.")
|
||||
} else {
|
||||
o.ID = v.ID + "-" + gameID(img)
|
||||
o.Title = v.Title + " (image " + img + ")"
|
||||
o.Description = strings.TrimSpace(v.Description + " Runs in the ready-made image " + img + ".")
|
||||
o.SteamAppID = ""
|
||||
}
|
||||
out = append(out, o)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -88,3 +88,27 @@ func TestRecommendPrefersTheSteamCMDVariant(t *testing.T) {
|
||||
t.Errorf("got %+v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOneOptionPerImageThenSteamCMDRecommended(t *testing.T) {
|
||||
v := oneOptionPerImage([]variant{{
|
||||
ID: "dedicated", Title: "Example Dedicated Server", Recommended: true, SteamAppID: "1000000",
|
||||
Images: withSteamCMD([]string{"someone/example-server"}, true),
|
||||
Verified: []string{"image someone/example-server exists", "Steam app 1000000 is \"Example Dedicated Server\""},
|
||||
}})
|
||||
recommend(v)
|
||||
if len(v) != 2 {
|
||||
t.Fatalf("want one option per image, got %+v", v)
|
||||
}
|
||||
steam, image := v[0], v[1]
|
||||
if steam.Title != "Example Dedicated Server (SteamCMD)" || !steam.Recommended || steam.SteamAppID != "1000000" || len(steam.Images) != 1 {
|
||||
t.Errorf("SteamCMD option: %+v", steam)
|
||||
}
|
||||
if image.Title != "Example Dedicated Server (image someone/example-server)" || image.Recommended || image.SteamAppID != "" {
|
||||
t.Errorf("image option: %+v", image)
|
||||
}
|
||||
for _, line := range steam.Verified {
|
||||
if line == "image someone/example-server exists" {
|
||||
t.Error("SteamCMD option lists the other option's image check")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user