Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce4baacd47 | ||
|
|
cb1243e4ed | ||
|
|
122fade954 | ||
|
|
416b921d71 |
No files matched your search
@@ -39,6 +39,13 @@ type Edge struct {
|
|||||||
OrgIDs []string `json:"orgIds"` // orgs allowed to use this edge; empty = all
|
OrgIDs []string `json:"orgIds"` // orgs allowed to use this edge; empty = all
|
||||||
IPs []string `json:"ips"` // addresses the edge reported it can bind
|
IPs []string `json:"ips"` // addresses the edge reported it can bind
|
||||||
LastSeen time.Time `json:"lastSeen"`
|
LastSeen time.Time `json:"lastSeen"`
|
||||||
|
|
||||||
|
// Version is the release the program reports (e.g. v0.1.5). AutoUpdate says whether it may update
|
||||||
|
// itself; only then will it act on an update request (UpdateID). UpdateMsg is the outcome of the last requested update.
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
AutoUpdate bool `json:"autoUpdate,omitempty"`
|
||||||
|
UpdateID string `json:"updateId,omitempty"` // set while an update requested by an administrator is pending
|
||||||
|
UpdateMsg string `json:"updateMsg,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Site is a bamboo agent: a private network that holds the real services.
|
// Site is a bamboo agent: a private network that holds the real services.
|
||||||
@@ -56,6 +63,13 @@ type Site struct {
|
|||||||
|
|
||||||
TunnelIP string `json:"tunnelIp,omitempty"` // the site's address inside the tunnel network
|
TunnelIP string `json:"tunnelIp,omitempty"` // the site's address inside the tunnel network
|
||||||
PublicKey string `json:"publicKey,omitempty"` // WireGuard public key, reported by the agent
|
PublicKey string `json:"publicKey,omitempty"` // WireGuard public key, reported by the agent
|
||||||
|
|
||||||
|
// Version is the release the program reports (e.g. v0.1.5). AutoUpdate says whether it may update
|
||||||
|
// itself; only then will it act on an update request (UpdateID). UpdateMsg is the outcome of the last requested update.
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
AutoUpdate bool `json:"autoUpdate,omitempty"`
|
||||||
|
UpdateID string `json:"updateId,omitempty"` // set while an update requested by an administrator is pending
|
||||||
|
UpdateMsg string `json:"updateMsg,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Domain is a base domain an org owns. Hostnames of web/tls mappings must sit under one.
|
// Domain is a base domain an org owns. Hostnames of web/tls mappings must sit under one.
|
||||||
@@ -216,6 +230,7 @@ type EdgeConfig struct {
|
|||||||
Local []string `json:"local"` // site IDs the edge dials directly on its own machine
|
Local []string `json:"local"` // site IDs the edge dials directly on its own machine
|
||||||
AcmeEmail string `json:"acmeEmail"`
|
AcmeEmail string `json:"acmeEmail"`
|
||||||
AcmeStages bool `json:"acmeStaging"`
|
AcmeStages bool `json:"acmeStaging"`
|
||||||
|
UpdateID string `json:"updateId,omitempty"` // an administrator asked this edge to update itself now; echoed back in its report
|
||||||
|
|
||||||
MailEgress []MailPolicy `json:"mailEgress"`
|
MailEgress []MailPolicy `json:"mailEgress"`
|
||||||
}
|
}
|
||||||
@@ -289,6 +304,10 @@ type EdgeReport struct {
|
|||||||
Stats map[string]Stat `json:"stats"` // deltas since last report
|
Stats map[string]Stat `json:"stats"` // deltas since last report
|
||||||
Containers []Container `json:"containers"`
|
Containers []Container `json:"containers"`
|
||||||
MailChecks map[string]MailCheck `json:"mailChecks"` // by mail-egress ID
|
MailChecks map[string]MailCheck `json:"mailChecks"` // by mail-egress ID
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
AutoUpdate bool `json:"autoUpdate,omitempty"`
|
||||||
|
UpdateMsg string `json:"updateMsg,omitempty"` // outcome of the update asked for by UpdateID
|
||||||
|
UpdateID string `json:"updateId,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EdgeRef tells a site where to dial.
|
// EdgeRef tells a site where to dial.
|
||||||
@@ -306,6 +325,7 @@ type SiteConfig struct {
|
|||||||
SiteID string `json:"siteId"`
|
SiteID string `json:"siteId"`
|
||||||
TunnelIP string `json:"tunnelIp"` // this site's WireGuard address
|
TunnelIP string `json:"tunnelIp"` // this site's WireGuard address
|
||||||
Edges []EdgeRef `json:"edges"`
|
Edges []EdgeRef `json:"edges"`
|
||||||
|
UpdateID string `json:"updateId,omitempty"` // an administrator asked this agent to update itself now; echoed back in its report
|
||||||
|
|
||||||
MailEgress []MailSpec `json:"mailEgress"`
|
MailEgress []MailSpec `json:"mailEgress"`
|
||||||
}
|
}
|
||||||
@@ -316,6 +336,10 @@ type SiteReport struct {
|
|||||||
MailEgress map[string]string `json:"mailEgress"` // egress ID -> "" (listening) or an error
|
MailEgress map[string]string `json:"mailEgress"` // egress ID -> "" (listening) or an error
|
||||||
Connected []string `json:"connected"`
|
Connected []string `json:"connected"`
|
||||||
Containers []Container `json:"containers"`
|
Containers []Container `json:"containers"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
AutoUpdate bool `json:"autoUpdate,omitempty"`
|
||||||
|
UpdateMsg string `json:"updateMsg,omitempty"`
|
||||||
|
UpdateID string `json:"updateId,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostMatches reports whether host matches an exact name or a "*.example.com" pattern.
|
// HostMatches reports whether host matches an exact name or a "*.example.com" pattern.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// restart replaces this process with the new binary, with the same arguments and environment.
|
// Restart replaces this process with the new binary, with the same arguments and environment.
|
||||||
func restart(exe string) error {
|
func Restart(exe string) error {
|
||||||
return syscall.Exec(exe, os.Args, os.Environ())
|
return syscall.Exec(exe, os.Args, os.Environ())
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,6 @@ package selfupdate
|
|||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
func restart(string) error {
|
func Restart(string) error {
|
||||||
return errors.New("restarting in place is not supported on Windows")
|
return errors.New("restarting in place is not supported on Windows")
|
||||||
}
|
}
|
||||||
+44
-15
@@ -72,7 +72,7 @@ func (c *Config) defaults() {
|
|||||||
c.Verify = verifyRuns(c.App)
|
c.Verify = verifyRuns(c.App)
|
||||||
}
|
}
|
||||||
if c.Restart == nil {
|
if c.Restart == nil {
|
||||||
c.Restart = restart
|
c.Restart = Restart
|
||||||
}
|
}
|
||||||
c.Server = strings.TrimRight(c.Server, "/")
|
c.Server = strings.TrimRight(c.Server, "/")
|
||||||
}
|
}
|
||||||
@@ -111,21 +111,9 @@ func CheckOnce(ctx context.Context, cfg Config) (string, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("%q is not a release version", cfg.Current)
|
return "", fmt.Errorf("%q is not a release version", cfg.Current)
|
||||||
}
|
}
|
||||||
var rel struct {
|
rel, err := latestRelease(ctx, cfg)
|
||||||
Tag string `json:"tag_name"`
|
|
||||||
Prerelease bool `json:"prerelease"`
|
|
||||||
Draft bool `json:"draft"`
|
|
||||||
Assets []struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
URL string `json:"browser_download_url"`
|
|
||||||
} `json:"assets"`
|
|
||||||
}
|
|
||||||
body, err := get(ctx, cfg.HTTP, cfg.Server+"/api/v1/repos/"+cfg.Repo+"/releases/latest", 1<<20)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("checking for a new release: %w", err)
|
return "", err
|
||||||
}
|
|
||||||
if err := json.Unmarshal(body, &rel); err != nil {
|
|
||||||
return "", fmt.Errorf("reading the latest release: %w", err)
|
|
||||||
}
|
}
|
||||||
if rel.Prerelease || rel.Draft {
|
if rel.Prerelease || rel.Draft {
|
||||||
return "", nil
|
return "", nil
|
||||||
@@ -208,6 +196,47 @@ func CheckOnce(ctx context.Context, cfg Config) (string, error) {
|
|||||||
return rel.Tag, nil
|
return rel.Tag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type release struct {
|
||||||
|
Tag string `json:"tag_name"`
|
||||||
|
Prerelease bool `json:"prerelease"`
|
||||||
|
Draft bool `json:"draft"`
|
||||||
|
Assets []struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
URL string `json:"browser_download_url"`
|
||||||
|
} `json:"assets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func latestRelease(ctx context.Context, cfg Config) (release, error) {
|
||||||
|
var rel release
|
||||||
|
body, err := get(ctx, cfg.HTTP, cfg.Server+"/api/v1/repos/"+cfg.Repo+"/releases/latest", 1<<20)
|
||||||
|
if err != nil {
|
||||||
|
return rel, fmt.Errorf("checking for a new release: %w", err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(body, &rel); err != nil {
|
||||||
|
return rel, fmt.Errorf("reading the latest release: %w", err)
|
||||||
|
}
|
||||||
|
return rel, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check reports the newest full release and whether it is newer than cfg.Current, without
|
||||||
|
// installing anything. A development build (a Current that isn't vX.Y.Z) is never "newer".
|
||||||
|
func Check(ctx context.Context, cfg Config) (latest string, newer bool, err error) {
|
||||||
|
cfg.defaults()
|
||||||
|
rel, err := latestRelease(ctx, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return "", false, err
|
||||||
|
}
|
||||||
|
if rel.Prerelease || rel.Draft {
|
||||||
|
return "", false, nil
|
||||||
|
}
|
||||||
|
l, ok := parseVersion(rel.Tag)
|
||||||
|
if !ok {
|
||||||
|
return rel.Tag, false, nil
|
||||||
|
}
|
||||||
|
cur, ok := parseVersion(cfg.Current)
|
||||||
|
return rel.Tag, ok && l.newerThan(cur), nil
|
||||||
|
}
|
||||||
|
|
||||||
func get(ctx context.Context, c *http.Client, url string, max int64) ([]byte, error) {
|
func get(ctx context.Context, c *http.Client, url string, max int64) ([]byte, error) {
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -135,3 +135,20 @@ func TestVersionOrdering(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckReportsWithoutInstalling(t *testing.T) {
|
||||||
|
srv := fakeGitea(t, "v0.2.0", false, false)
|
||||||
|
for _, c := range []struct {
|
||||||
|
current string
|
||||||
|
newer bool
|
||||||
|
}{{"v0.1.0", true}, {"v0.2.0", false}, {"v0.3.0", false}, {"dev", false}, {"v0.1.0-local", false}} {
|
||||||
|
cfg, exe, restarted := setup(t, srv, c.current)
|
||||||
|
tag, newer, err := Check(context.Background(), cfg)
|
||||||
|
if err != nil || tag != "v0.2.0" || newer != c.newer {
|
||||||
|
t.Errorf("%s: tag=%q newer=%v err=%v", c.current, tag, newer, err)
|
||||||
|
}
|
||||||
|
if b, _ := os.ReadFile(exe); string(b) != "OLD-BINARY" || *restarted != "" {
|
||||||
|
t.Errorf("%s: Check changed things", c.current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user