c9e076db68
Fix #64 (incompletely). It's still not ideal. It makes more sense to use the gateway IP address of container network as outbound IP of cache server. However, this requires act to cooperate, some think like: - act creates the network for new container, and returns the network to runner. - runner extracts the gateway IP in the network. - runner uses the gateway IP as outbound IP, and pass it to act as cache server endpoint. - act It continues to create the container with the created network. Reviewed-on: https://gitea.com/gitea/act_runner/pulls/74 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
100 lines
2.2 KiB
Go
100 lines
2.2 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package artifactcache
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/go-chi/render"
|
|
"xorm.io/xorm"
|
|
)
|
|
|
|
func responseJson(w http.ResponseWriter, r *http.Request, code int, v ...any) {
|
|
render.Status(r, code)
|
|
if len(v) == 0 || v[0] == nil {
|
|
render.JSON(w, r, struct{}{})
|
|
} else if err, ok := v[0].(error); ok {
|
|
logger.Errorf("%v %v: %v", r.Method, r.RequestURI, err)
|
|
render.JSON(w, r, map[string]any{
|
|
"error": err.Error(),
|
|
})
|
|
} else {
|
|
render.JSON(w, r, v[0])
|
|
}
|
|
}
|
|
|
|
func parseContentRange(s string) (int64, int64, error) {
|
|
// support the format like "bytes 11-22/*" only
|
|
s, _, _ = strings.Cut(strings.TrimPrefix(s, "bytes "), "/")
|
|
s1, s2, _ := strings.Cut(s, "-")
|
|
|
|
start, err := strconv.ParseInt(s1, 10, 64)
|
|
if err != nil {
|
|
return 0, 0, fmt.Errorf("parse %q: %w", s, err)
|
|
}
|
|
stop, err := strconv.ParseInt(s2, 10, 64)
|
|
if err != nil {
|
|
return 0, 0, fmt.Errorf("parse %q: %w", s, err)
|
|
}
|
|
return start, stop, nil
|
|
}
|
|
|
|
func getOutboundIP() (net.IP, error) {
|
|
// FIXME: It makes more sense to use the gateway IP address of container network
|
|
if conn, err := net.Dial("udp", "8.8.8.8:80"); err == nil {
|
|
defer conn.Close()
|
|
return conn.LocalAddr().(*net.UDPAddr).IP, nil
|
|
}
|
|
if ifaces, err := net.Interfaces(); err == nil {
|
|
for _, i := range ifaces {
|
|
if addrs, err := i.Addrs(); err == nil {
|
|
for _, addr := range addrs {
|
|
var ip net.IP
|
|
switch v := addr.(type) {
|
|
case *net.IPNet:
|
|
ip = v.IP
|
|
case *net.IPAddr:
|
|
ip = v.IP
|
|
}
|
|
if ip.IsGlobalUnicast() {
|
|
return ip, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("no outbound IP address found")
|
|
}
|
|
|
|
// engine is a wrapper of *xorm.Engine, with a lock.
|
|
// To avoid racing of sqlite, we don't care performance here.
|
|
type engine struct {
|
|
e *xorm.Engine
|
|
m sync.Mutex
|
|
}
|
|
|
|
func (e *engine) Exec(f func(*xorm.Session) error) error {
|
|
e.m.Lock()
|
|
defer e.m.Unlock()
|
|
|
|
sess := e.e.NewSession()
|
|
defer sess.Close()
|
|
|
|
return f(sess)
|
|
}
|
|
|
|
func (e *engine) ExecBool(f func(*xorm.Session) (bool, error)) (bool, error) {
|
|
e.m.Lock()
|
|
defer e.m.Unlock()
|
|
|
|
sess := e.e.NewSession()
|
|
defer sess.Close()
|
|
|
|
return f(sess)
|
|
}
|