Function bodies 128 total
main.main function · go · L19-L41 (23 LOC)cmd/ddl-guest/main.go
func main() {
jsonFlag := flag.Bool("json", false, "output raw JSON")
flag.Parse()
apiURL, err := resolveAPIURL(defaultCandidates)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
body, err := fetchStatus(apiURL)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
if *jsonFlag {
printJSON(os.Stdout, body)
} else {
hostname, _ := os.Hostname()
printStatus(os.Stdout, hostname, body)
}
}main.resolveAPIURL function · go · L43-L57 (15 LOC)cmd/ddl-guest/main.go
func resolveAPIURL(candidates []string) (string, error) {
if url := os.Getenv("DDL_API_URL"); url != "" {
return url, nil
}
client := &http.Client{Timeout: 1 * time.Second}
for _, candidate := range candidates {
resp, err := client.Get(candidate + "/containers")
if err == nil {
resp.Body.Close()
return candidate, nil
}
}
return "", fmt.Errorf("cannot reach ddld API; set DDL_API_URL or ensure ddld is running")
}main.printStatus function · go · L86-L114 (29 LOC)cmd/ddl-guest/main.go
func printStatus(w io.Writer, containerID string, body map[string]interface{}) {
fmt.Fprintf(w, "Container: %s\n\n", containerID)
usageMap, _ := body["usage"].(map[string]interface{})
limitsMap, _ := body["limits"].(map[string]interface{})
tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
fmt.Fprintf(tw, "TYPE\tUSAGE\tLIMIT\tSTATUS\n")
types := []string{"cpu", "ram", "disk", "net", "disk-io-bytes", "disk-io-ops", "spending"}
for _, t := range types {
usage := getJSONInt64(usageMap, t)
limit := getJSONInt64(limitsMap, t)
usageStr := formatValue(t, usage)
limitStr := formatValue(t, limit)
var statusStr string
if limit > 0 {
pct := float64(usage) / float64(limit) * 100
statusStr = fmt.Sprintf("%.1f%%", pct)
} else {
statusStr = "-"
}
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", t, usageStr, limitStr, statusStr)
}
tw.Flush()
}main.getJSONInt64 function · go · L116-L132 (17 LOC)cmd/ddl-guest/main.go
func getJSONInt64(m map[string]interface{}, key string) int64 {
if m == nil {
return 0
}
v, ok := m[key]
if !ok {
return 0
}
switch v := v.(type) {
case float64:
return int64(v)
case json.Number:
n, _ := v.Int64()
return n
}
return 0
}main.formatValue function · go · L135-L155 (21 LOC)cmd/ddl-guest/main.go
func formatValue(limitType string, v int64) string {
if v == 0 {
return "-"
}
switch limitType {
case "cpu":
if v >= 3600 {
return fmt.Sprintf("%dh%dm%ds", v/3600, (v%3600)/60, v%60)
}
if v >= 60 {
return fmt.Sprintf("%dm%ds", v/60, v%60)
}
return fmt.Sprintf("%ds", v)
case "ram", "disk", "net", "disk-io-bytes":
return formatBytesHuman(v)
case "spending":
return fmt.Sprintf("$%.2f", float64(v)/100)
default:
return fmt.Sprintf("%d", v)
}
}main.formatBytesHuman function · go · L157-L176 (20 LOC)cmd/ddl-guest/main.go
func formatBytesHuman(b int64) string {
const (
kb = 1024
mb = kb * 1024
gb = mb * 1024
tb = gb * 1024
)
switch {
case b >= tb:
return fmt.Sprintf("%.1fT", float64(b)/float64(tb))
case b >= gb:
return fmt.Sprintf("%.1fG", float64(b)/float64(gb))
case b >= mb:
return fmt.Sprintf("%.1fM", float64(b)/float64(mb))
case b >= kb:
return fmt.Sprintf("%.1fK", float64(b)/float64(kb))
default:
return fmt.Sprintf("%dB", b)
}
}api.NewServer function · go · L35-L49 (15 LOC)internal/api/api.go
func NewServer(st store.DataStore, dc docker.DockerClient, em enforcement.EnforcementController, px proxy.SpendingProxy) *Server {
s := &Server{
store: st,
docker: dc,
enforcement: em,
proxy: px,
mux: http.NewServeMux(),
ipMap: make(map[string]string),
done: make(chan struct{}),
}
s.registerRoutes()
s.refreshIPs()
go s.ipRefreshLoop()
return s
}Repobility analyzer · published findings · https://repobility.com
api.Server.registerRoutes method · go · L56-L63 (8 LOC)internal/api/api.go
func (s *Server) registerRoutes() {
s.mux.HandleFunc("/containers", s.handleContainers)
s.mux.HandleFunc("/containers/", s.handleContainer)
s.mux.HandleFunc("/register", s.handleRegister)
// In-container query endpoints (container identifies itself by source IP or token)
s.mux.HandleFunc("/usage", s.handleSelfUsage)
s.mux.HandleFunc("/limits", s.handleSelfLimits)
}api.Server.ReadOnlyHandler method · go · L73-L79 (7 LOC)internal/api/api.go
func (s *Server) ReadOnlyHandler() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/containers", s.handleContainersReadOnly)
mux.HandleFunc("/usage", s.handleSelfUsageByIP)
mux.HandleFunc("/limits", s.handleSelfLimitsByIP)
return mux
}api.Server.handleContainersReadOnly method · go · L81-L87 (7 LOC)internal/api/api.go
func (s *Server) handleContainersReadOnly(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
s.handleContainers(w, r)
}api.Server.handleContainers method · go · L91-L109 (19 LOC)internal/api/api.go
func (s *Server) handleContainers(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
containers, err := s.store.ListContainers()
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
var result []model.ContainerStatus
for _, c := range containers {
status := s.buildStatus(c)
result = append(result, status)
}
writeJSON(w, result)
}api.Server.handleRegister method · go · L111-L159 (49 LOC)internal/api/api.go
func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
var req struct {
ContainerID string `json:"container_id"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, err)
return
}
if req.ContainerID == "" {
writeError(w, http.StatusBadRequest, fmt.Errorf("container_id required"))
return
}
// Inspect the Docker container to validate it exists
ctx := context.Background()
info, err := s.docker.InspectContainer(ctx, req.ContainerID)
if err != nil {
writeError(w, http.StatusNotFound, fmt.Errorf("container not found: %w", err))
return
}
name := strings.TrimPrefix(info.Name, "/")
c, err := s.store.RegisterContainer(info.ID, name)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
// Start enforcement
s.enforcement.StartContainer(c.ID, c.DockerID)
// Sapi.Server.handleContainer method · go · L161-L188 (28 LOC)internal/api/api.go
func (s *Server) handleContainer(w http.ResponseWriter, r *http.Request) {
// Parse: /containers/{id}, /containers/{id}/limits, /containers/{id}/usage, /containers/{id}/clone
path := strings.TrimPrefix(r.URL.Path, "/containers/")
parts := strings.SplitN(path, "/", 2)
containerQuery := parts[0]
containerID, err := s.store.ResolveContainerID(containerQuery)
if err != nil {
writeError(w, http.StatusNotFound, err)
return
}
if len(parts) == 1 {
s.handleContainerInfo(w, r, containerID)
return
}
switch parts[1] {
case "limits":
s.handleLimits(w, r, containerID)
case "usage":
s.handleUsage(w, r, containerID)
case "clone":
s.handleClone(w, r, containerID)
default:
http.NotFound(w, r)
}
}api.Server.handleContainerInfo method · go · L190-L213 (24 LOC)internal/api/api.go
func (s *Server) handleContainerInfo(w http.ResponseWriter, r *http.Request, containerID string) {
if r.Method != http.MethodGet && r.Method != http.MethodDelete {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if r.Method == http.MethodDelete {
s.enforcement.StopContainer(containerID)
if err := s.store.RemoveContainer(containerID); err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
writeJSON(w, map[string]string{"status": "removed"})
return
}
c, err := s.store.GetContainer(containerID)
if err != nil {
writeError(w, http.StatusNotFound, err)
return
}
status := s.buildStatus(*c)
writeJSON(w, status)
}api.Server.handleLimits method · go · L215-L285 (71 LOC)internal/api/api.go
func (s *Server) handleLimits(w http.ResponseWriter, r *http.Request, containerID string) {
switch r.Method {
case http.MethodGet:
limits, err := s.store.GetAllLimits(containerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
writeJSON(w, limits)
case http.MethodPut:
var req struct {
Type string `json:"type"`
Value int64 `json:"value"`
Operation string `json:"operation"` // "set", "increase", "decrease"
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, err)
return
}
lt := model.LimitType(req.Type)
var newValue int64
switch req.Operation {
case "set", "":
newValue = req.Value
case "increase":
current, _ := s.store.GetLimit(containerID, lt)
newValue = current + req.Value
case "decrease":
current, _ := s.store.GetLimit(containerID, lt)
newValue = current - req.Value
if newValue < 0 {
newValue = 0
}
default:
writeErroProvenance: Repobility (https://repobility.com) — every score reproducible from /scan/
api.Server.handleUsage method · go · L287-L299 (13 LOC)internal/api/api.go
func (s *Server) handleUsage(w http.ResponseWriter, r *http.Request, containerID string) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
usage, err := s.store.GetAllUsage(containerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
writeJSON(w, usage)
}api.Server.handleClone method · go · L301-L349 (49 LOC)internal/api/api.go
func (s *Server) handleClone(w http.ResponseWriter, r *http.Request, containerID string) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
var req struct {
Name string `json:"name"`
}
json.NewDecoder(r.Body).Decode(&req)
c, err := s.store.GetContainer(containerID)
if err != nil {
writeError(w, http.StatusNotFound, err)
return
}
ctx := context.Background()
newDockerID, err := s.docker.CloneContainer(ctx, c.DockerID, req.Name)
if err != nil {
writeError(w, http.StatusInternalServerError, fmt.Errorf("clone failed: %w", err))
return
}
// Inspect the new container
info, err := s.docker.InspectContainer(ctx, newDockerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
name := strings.TrimPrefix(info.Name, "/")
newContainer, err := s.store.RegisterContainer(info.ID, name)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
// Copy limiapi.Server.handleSelfUsage method · go · L353-L381 (29 LOC)internal/api/api.go
func (s *Server) handleSelfUsage(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
containerID := s.resolveContainerFromRequest(r)
if containerID == "" {
writeError(w, http.StatusBadRequest, fmt.Errorf("cannot identify container; use ?id=<container_id> or X-Container-ID header"))
return
}
usage, err := s.store.GetAllUsage(containerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
limits, err := s.store.GetAllLimits(containerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
writeJSON(w, map[string]interface{}{
"usage": usage,
"limits": limits,
})
}api.Server.handleSelfLimits method · go · L383-L402 (20 LOC)internal/api/api.go
func (s *Server) handleSelfLimits(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
containerID := s.resolveContainerFromRequest(r)
if containerID == "" {
writeError(w, http.StatusBadRequest, fmt.Errorf("cannot identify container; use ?id=<container_id> or X-Container-ID header"))
return
}
limits, err := s.store.GetAllLimits(containerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
writeJSON(w, limits)
}api.Server.ipRefreshLoop method · go · L404-L415 (12 LOC)internal/api/api.go
func (s *Server) ipRefreshLoop() {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-s.done:
return
case <-ticker.C:
s.refreshIPs()
}
}
}api.Server.refreshIPs method · go · L417-L435 (19 LOC)internal/api/api.go
func (s *Server) refreshIPs() {
containers, err := s.store.ListContainers()
if err != nil {
log.Printf("[api] refreshIPs: list containers: %v", err)
return
}
newMap := make(map[string]string, len(containers))
ctx := context.Background()
for _, c := range containers {
ip, err := s.docker.ContainerIP(ctx, c.DockerID)
if err != nil {
continue
}
newMap[ip] = c.ID
}
s.ipMu.Lock()
s.ipMap = newMap
s.ipMu.Unlock()
}api.extractIP function · go · L443-L449 (7 LOC)internal/api/api.go
func extractIP(remoteAddr string) string {
host, _, err := net.SplitHostPort(remoteAddr)
if err != nil {
return remoteAddr
}
return host
}api.Server.handleSelfUsageByIP method · go · L451-L480 (30 LOC)internal/api/api.go
func (s *Server) handleSelfUsageByIP(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
ip := extractIP(r.RemoteAddr)
containerID := s.resolveContainerByIP(ip)
if containerID == "" {
writeError(w, http.StatusForbidden, fmt.Errorf("unknown container"))
return
}
usage, err := s.store.GetAllUsage(containerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
limits, err := s.store.GetAllLimits(containerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
writeJSON(w, map[string]interface{}{
"usage": usage,
"limits": limits,
})
}Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
api.Server.handleSelfLimitsByIP method · go · L482-L502 (21 LOC)internal/api/api.go
func (s *Server) handleSelfLimitsByIP(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
ip := extractIP(r.RemoteAddr)
containerID := s.resolveContainerByIP(ip)
if containerID == "" {
writeError(w, http.StatusForbidden, fmt.Errorf("unknown container"))
return
}
limits, err := s.store.GetAllLimits(containerID)
if err != nil {
writeError(w, http.StatusInternalServerError, err)
return
}
writeJSON(w, limits)
}api.Server.resolveContainerFromRequest method · go · L504-L520 (17 LOC)internal/api/api.go
func (s *Server) resolveContainerFromRequest(r *http.Request) string {
// Try query parameter
if id := r.URL.Query().Get("id"); id != "" {
resolved, err := s.store.ResolveContainerID(id)
if err == nil {
return resolved
}
}
// Try header
if id := r.Header.Get("X-Container-ID"); id != "" {
resolved, err := s.store.ResolveContainerID(id)
if err == nil {
return resolved
}
}
return ""
}api.Server.buildStatus method · go · L522-L533 (12 LOC)internal/api/api.go
func (s *Server) buildStatus(c model.Container) model.ContainerStatus {
limits, _ := s.store.GetAllLimits(c.ID)
usage, _ := s.store.GetAllUsage(c.ID)
enforced := s.enforcement.GetEnforced(c.ID)
return model.ContainerStatus{
Container: c,
Limits: limits,
Usage: usage,
Enforced: enforced,
}
}cgroup.NewReader function · go · L30-L35 (6 LOC)internal/cgroup/cgroup.go
func NewReader(basePath string) *Reader {
if basePath == "" {
basePath = "/sys/fs/cgroup"
}
return &Reader{basePath: basePath}
}cgroup.Reader.FindCgroupPath method · go · L38-L52 (15 LOC)internal/cgroup/cgroup.go
func (r *Reader) FindCgroupPath(dockerID string) (string, error) {
// Docker typically places containers at:
// /sys/fs/cgroup/system.slice/docker-<id>.scope (systemd driver)
// /sys/fs/cgroup/docker/<id> (cgroupfs driver)
candidates := []string{
filepath.Join(r.basePath, "system.slice", "docker-"+dockerID+".scope"),
filepath.Join(r.basePath, "docker", dockerID),
}
for _, p := range candidates {
if _, err := os.Stat(p); err == nil {
return p, nil
}
}
return "", fmt.Errorf("cgroup path not found for container %s", dockerID[:12])
}cgroup.ParseCPUUsageMicroseconds function · go · L55-L67 (13 LOC)internal/cgroup/cgroup.go
func ParseCPUUsageMicroseconds(content string) (int64, error) {
scanner := bufio.NewScanner(strings.NewReader(content))
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "usage_usec ") {
parts := strings.Fields(line)
if len(parts) == 2 {
return strconv.ParseInt(parts[1], 10, 64)
}
}
}
return 0, fmt.Errorf("usage_usec not found in cpu.stat")
}cgroup.Reader.CPUUsageMicroseconds method · go · L70-L76 (7 LOC)internal/cgroup/cgroup.go
func (r *Reader) CPUUsageMicroseconds(cgroupPath string) (int64, error) {
data, err := os.ReadFile(filepath.Join(cgroupPath, "cpu.stat"))
if err != nil {
return 0, fmt.Errorf("read cpu.stat: %w", err)
}
return ParseCPUUsageMicroseconds(string(data))
}cgroup.Reader.SetMemoryMax method · go · L84-L90 (7 LOC)internal/cgroup/cgroup.go
func (r *Reader) SetMemoryMax(cgroupPath string, bytes int64) error {
val := "max"
if bytes > 0 {
val = strconv.FormatInt(bytes, 10)
}
return os.WriteFile(filepath.Join(cgroupPath, "memory.max"), []byte(val), 0644)
}Open data scored by Repobility · https://repobility.com
cgroup.ParseIOStat function · go · L100-L125 (26 LOC)internal/cgroup/cgroup.go
func ParseIOStat(content string) (*IOStats, error) {
stats := &IOStats{}
scanner := bufio.NewScanner(strings.NewReader(content))
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
// Each line: "major:minor rbytes=X wbytes=X rios=X wios=X ..."
for _, f := range fields {
kv := strings.SplitN(f, "=", 2)
if len(kv) != 2 {
continue
}
val, err := strconv.ParseInt(kv[1], 10, 64)
if err != nil {
continue
}
switch kv[0] {
case "rbytes", "wbytes":
stats.TotalBytes += val
case "rios", "wios":
stats.TotalOps += val
}
}
}
return stats, nil
}cgroup.Reader.ReadIOStat method · go · L127-L133 (7 LOC)internal/cgroup/cgroup.go
func (r *Reader) ReadIOStat(cgroupPath string) (*IOStats, error) {
data, err := os.ReadFile(filepath.Join(cgroupPath, "io.stat"))
if err != nil {
return nil, fmt.Errorf("read io.stat: %w", err)
}
return ParseIOStat(string(data))
}cgroup.Reader.ReadNetworkStats method · go · L155-L166 (12 LOC)internal/cgroup/cgroup.go
func (r *Reader) ReadNetworkStats(vethName string) (*NetworkStats, error) {
base := filepath.Join("/sys/class/net", vethName, "statistics")
rx, err := r.readSingleInt(filepath.Join(base, "rx_bytes"))
if err != nil {
return nil, fmt.Errorf("read rx_bytes: %w", err)
}
tx, err := r.readSingleInt(filepath.Join(base, "tx_bytes"))
if err != nil {
return nil, fmt.Errorf("read tx_bytes: %w", err)
}
return &NetworkStats{RxBytes: rx, TxBytes: tx}, nil
}cgroup.Reader.readSingleInt method · go · L168-L174 (7 LOC)internal/cgroup/cgroup.go
func (r *Reader) readSingleInt(path string) (int64, error) {
data, err := os.ReadFile(path)
if err != nil {
return 0, err
}
return strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64)
}docker.NewClient function · go · L36-L42 (7 LOC)internal/docker/docker.go
func NewClient() (*Client, error) {
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil, fmt.Errorf("create docker client: %w", err)
}
return &Client{cli: cli}, nil
}docker.Client.IsContainerPaused method · go · L65-L71 (7 LOC)internal/docker/docker.go
func (c *Client) IsContainerPaused(ctx context.Context, id string) (bool, error) {
info, err := c.cli.ContainerInspect(ctx, id)
if err != nil {
return false, err
}
return info.State.Paused, nil
}docker.Client.IsContainerRunning method · go · L74-L80 (7 LOC)internal/docker/docker.go
func (c *Client) IsContainerRunning(ctx context.Context, id string) (bool, error) {
info, err := c.cli.ContainerInspect(ctx, id)
if err != nil {
return false, err
}
return info.State.Running, nil
}docker.Client.UpdateMemoryLimit method · go · L83-L91 (9 LOC)internal/docker/docker.go
func (c *Client) UpdateMemoryLimit(ctx context.Context, id string, memoryBytes int64) error {
_, err := c.cli.ContainerUpdate(ctx, id, container.UpdateConfig{
Resources: container.Resources{
Memory: memoryBytes,
MemorySwap: memoryBytes,
},
})
return err
}Repobility analyzer · published findings · https://repobility.com
docker.Client.ContainerVethName method · go · L96-L140 (45 LOC)internal/docker/docker.go
func (c *Client) ContainerVethName(ctx context.Context, id string) (string, error) {
info, err := c.cli.ContainerInspect(ctx, id)
if err != nil {
return "", err
}
// The sandbox key is the path to the network namespace
sandboxKey := info.NetworkSettings.SandboxKey
if sandboxKey == "" {
return "", fmt.Errorf("no sandbox key for container %s", id[:12])
}
// Extract the PID-based interface index from the container's eth0
// We need to exec into the container to read the iflink
execCfg := types.ExecConfig{
Cmd: []string{"cat", "/sys/class/net/eth0/iflink"},
AttachStdout: true,
}
execResp, err := c.cli.ContainerExecCreate(ctx, id, execCfg)
if err != nil {
return "", fmt.Errorf("exec create: %w", err)
}
attachResp, err := c.cli.ContainerExecAttach(ctx, execResp.ID, types.ExecStartCheck{})
if err != nil {
return "", fmt.Errorf("exec attach: %w", err)
}
defer attachResp.Close()
output, err := io.ReadAll(attachResp.Reader)
if err != nil {
return "", fdocker.Client.CloneContainer method · go · L143-L183 (41 LOC)internal/docker/docker.go
func (c *Client) CloneContainer(ctx context.Context, sourceID string, newName string) (string, error) {
// Inspect the source container
info, err := c.cli.ContainerInspect(ctx, sourceID)
if err != nil {
return "", fmt.Errorf("inspect source: %w", err)
}
// Commit the container to create a new image
commitResp, err := c.cli.ContainerCommit(ctx, sourceID, types.ContainerCommitOptions{
Reference: "ddl-clone-" + sourceID[:12],
Comment: "cloned by ddl",
})
if err != nil {
return "", fmt.Errorf("commit: %w", err)
}
// Prepare the new container config based on the original
config := info.Config
hostConfig := info.HostConfig
if newName == "" {
newName = info.Name + "-clone"
}
newName = strings.TrimPrefix(newName, "/")
// Override the image to the committed snapshot
config.Image = commitResp.ID
// Create the new container
createResp, err := c.cli.ContainerCreate(ctx, config, hostConfig, nil, nil, newName)
if err != nil {
return "", fmt.Errorf("create clonedocker.Client.GetContainerDiskUsage method · go · L186-L195 (10 LOC)internal/docker/docker.go
func (c *Client) GetContainerDiskUsage(ctx context.Context, id string) (int64, error) {
info, err := c.cli.ContainerInspect(ctx, id)
if err != nil {
return 0, err
}
if info.SizeRw != nil {
return *info.SizeRw, nil
}
return 0, nil
}docker.Client.DisconnectNetwork method · go · L198-L209 (12 LOC)internal/docker/docker.go
func (c *Client) DisconnectNetwork(ctx context.Context, id string) error {
info, err := c.cli.ContainerInspect(ctx, id)
if err != nil {
return err
}
for netName := range info.NetworkSettings.Networks {
if err := c.cli.NetworkDisconnect(ctx, netName, id, true); err != nil {
return fmt.Errorf("disconnect from %s: %w", netName, err)
}
}
return nil
}docker.Client.ContainerIP method · go · L217-L231 (15 LOC)internal/docker/docker.go
func (c *Client) ContainerIP(ctx context.Context, id string) (string, error) {
info, err := c.cli.ContainerInspect(ctx, id)
if err != nil {
return "", err
}
if ip := info.NetworkSettings.IPAddress; ip != "" {
return ip, nil
}
for _, net := range info.NetworkSettings.Networks {
if net.IPAddress != "" {
return net.IPAddress, nil
}
}
return "", fmt.Errorf("no IP address for container %s", id)
}enforcement.NewManager function · go · L40-L50 (11 LOC)internal/enforcement/enforcement.go
func NewManager(st store.DataStore, dc docker.DockerClient, cg cgroup.CgroupReader, px proxy.SpendingProxy) *Manager {
return &Manager{
store: st,
docker: dc,
cgroup: cg,
proxy: px,
interval: time.Second,
workers: make(map[string]context.CancelFunc),
enforced: make(map[string]map[model.LimitType]bool),
}
}enforcement.Manager.StartContainer method · go · L53-L66 (14 LOC)internal/enforcement/enforcement.go
func (m *Manager) StartContainer(containerID string, dockerID string) {
m.mu.Lock()
if _, exists := m.workers[containerID]; exists {
m.mu.Unlock()
return
}
ctx, cancel := context.WithCancel(context.Background())
m.workers[containerID] = cancel
m.enforced[containerID] = make(map[model.LimitType]bool)
m.mu.Unlock()
go m.enforcementLoop(ctx, containerID, dockerID)
log.Printf("[enforcement] started monitoring container %s", containerID)
}enforcement.Manager.StopContainer method · go · L69-L78 (10 LOC)internal/enforcement/enforcement.go
func (m *Manager) StopContainer(containerID string) {
m.mu.Lock()
defer m.mu.Unlock()
if cancel, ok := m.workers[containerID]; ok {
cancel()
delete(m.workers, containerID)
delete(m.enforced, containerID)
log.Printf("[enforcement] stopped monitoring container %s", containerID)
}
}Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
enforcement.Manager.IsEnforced method · go · L81-L88 (8 LOC)internal/enforcement/enforcement.go
func (m *Manager) IsEnforced(containerID string, lt model.LimitType) bool {
m.mu.Lock()
defer m.mu.Unlock()
if e, ok := m.enforced[containerID]; ok {
return e[lt]
}
return false
}enforcement.Manager.GetEnforced method · go · L91-L101 (11 LOC)internal/enforcement/enforcement.go
func (m *Manager) GetEnforced(containerID string) map[model.LimitType]bool {
m.mu.Lock()
defer m.mu.Unlock()
result := make(map[model.LimitType]bool)
if e, ok := m.enforced[containerID]; ok {
for k, v := range e {
result[k] = v
}
}
return result
}enforcement.Manager.enforcementLoop method · go · L111-L123 (13 LOC)internal/enforcement/enforcement.go
func (m *Manager) enforcementLoop(ctx context.Context, containerID, dockerID string) {
ticker := time.NewTicker(m.interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
m.checkAndEnforce(ctx, containerID, dockerID)
}
}
}page 1 / 3next ›