Function bodies 128 total
enforcement.Manager.checkAndEnforce method · go · L125-L167 (43 LOC)internal/enforcement/enforcement.go
func (m *Manager) checkAndEnforce(ctx context.Context, containerID, dockerID string) {
// Check if container is still running
running, err := m.docker.IsContainerRunning(ctx, dockerID)
if err != nil || !running {
return
}
limits, err := m.store.GetAllLimits(containerID)
if err != nil {
log.Printf("[enforcement] error getting limits for %s: %v", containerID, err)
return
}
// Find cgroup path
cgroupPath, cgroupErr := m.cgroup.FindCgroupPath(dockerID)
// Check each limit type
for _, lt := range model.AllLimitTypes {
limit, hasLimit := limits[lt]
if !hasLimit || limit == 0 {
continue
}
usage, err := m.getCurrentUsage(ctx, containerID, dockerID, lt, cgroupPath, cgroupErr)
if err != nil {
continue
}
// Persist usage to store
m.store.SetUsage(containerID, lt, usage)
exceeded := usage >= limit
m.mu.Lock()
wasEnforced := m.enforced[containerID][lt]
m.mu.Unlock()
if exceeded && !wasEnforced {
m.enforce(ctx, containerID, dockerID, lt, cgrenforcement.Manager.getCurrentUsage method · go · L169-L228 (60 LOC)internal/enforcement/enforcement.go
func (m *Manager) getCurrentUsage(ctx context.Context, containerID, dockerID string, lt model.LimitType, cgroupPath string, cgroupErr error) (int64, error) {
switch lt {
case model.LimitCPU:
if cgroupErr != nil {
return 0, cgroupErr
}
usec, err := m.cgroup.CPUUsageMicroseconds(cgroupPath)
if err != nil {
return 0, err
}
return usec / 1_000_000, nil // convert to seconds
case model.LimitRAM:
if cgroupErr != nil {
return 0, cgroupErr
}
return m.cgroup.MemoryCurrent(cgroupPath)
case model.LimitDisk:
return m.docker.GetContainerDiskUsage(ctx, dockerID)
case model.LimitNetwork:
if cgroupErr != nil {
return 0, cgroupErr
}
// Try to get network stats from stored veth name or default
// For simplicity, read from stored usage + incremental
usage, _ := m.store.GetUsage(containerID, lt)
return usage, nil
case model.LimitDiskIOByte:
if cgroupErr != nil {
return 0, cgroupErr
}
stats, err := m.cgroup.ReadIOStat(cgroupPath)
if err != nienforcement.Manager.enforce method · go · L230-L284 (55 LOC)internal/enforcement/enforcement.go
func (m *Manager) enforce(ctx context.Context, containerID, dockerID string, lt model.LimitType, cgroupPath string) {
var err error
switch lt {
case model.LimitCPU:
err = m.docker.PauseContainer(ctx, dockerID)
if err == nil {
log.Printf("[enforcement] paused container %s: CPU limit exceeded", containerID)
}
case model.LimitRAM:
// RAM is enforced by the kernel via memory.max — we just update it
limit, _ := m.store.GetLimit(containerID, lt)
err = m.docker.UpdateMemoryLimit(ctx, dockerID, limit)
if err == nil {
log.Printf("[enforcement] set memory limit for %s to %d bytes", containerID, limit)
}
case model.LimitDisk:
err = m.docker.PauseContainer(ctx, dockerID)
if err == nil {
log.Printf("[enforcement] paused container %s: disk limit exceeded", containerID)
}
case model.LimitNetwork:
err = m.docker.DisconnectNetwork(ctx, dockerID)
if err == nil {
log.Printf("[enforcement] disconnected network for %s: network limit exceeded", containerID)
}enforcement.Manager.release method · go · L286-L345 (60 LOC)internal/enforcement/enforcement.go
func (m *Manager) release(ctx context.Context, containerID, dockerID string, lt model.LimitType, cgroupPath string) {
var err error
switch lt {
case model.LimitCPU:
paused, _ := m.docker.IsContainerPaused(ctx, dockerID)
if paused {
// Only unpause if no other limit type is also enforcing pause
if !m.isOtherPauseActive(containerID, lt) {
err = m.docker.UnpauseContainer(ctx, dockerID)
if err == nil {
log.Printf("[enforcement] resumed container %s: CPU limit increased", containerID)
}
}
}
case model.LimitRAM:
limit, _ := m.store.GetLimit(containerID, lt)
err = m.docker.UpdateMemoryLimit(ctx, dockerID, limit)
if err == nil {
log.Printf("[enforcement] updated memory limit for %s to %d bytes", containerID, limit)
}
case model.LimitDisk:
paused, _ := m.docker.IsContainerPaused(ctx, dockerID)
if paused && !m.isOtherPauseActive(containerID, lt) {
err = m.docker.UnpauseContainer(ctx, dockerID)
if err == nil {
log.Printf("[enforcemenenforcement.Manager.isOtherPauseActive method · go · L348-L358 (11 LOC)internal/enforcement/enforcement.go
func (m *Manager) isOtherPauseActive(containerID string, except model.LimitType) bool {
m.mu.Lock()
defer m.mu.Unlock()
pauseTypes := []model.LimitType{model.LimitCPU, model.LimitDisk}
for _, lt := range pauseTypes {
if lt != except && m.enforced[containerID][lt] {
return true
}
}
return false
}enforcement.Manager.StartAll method · go · L361-L370 (10 LOC)internal/enforcement/enforcement.go
func (m *Manager) StartAll() error {
containers, err := m.store.ListContainers()
if err != nil {
return err
}
for _, c := range containers {
m.StartContainer(c.ID, c.DockerID)
}
return nil
}enforcement.Manager.StopAll method · go · L373-L380 (8 LOC)internal/enforcement/enforcement.go
func (m *Manager) StopAll() {
m.mu.Lock()
defer m.mu.Unlock()
for id, cancel := range m.workers {
cancel()
delete(m.workers, id)
}
}Repobility — same analyzer, your code, free for public repos · /scan/
proxy.NewSpendingTracker function · go · L47-L55 (9 LOC)internal/proxy/proxy.go
func NewSpendingTracker(onUpdate func(containerID string, totalCents int64)) *SpendingTracker {
return &SpendingTracker{
containerByAddr: make(map[string]string),
spending: make(map[string]int64),
budgets: make(map[string]int64),
prices: defaultPrices(),
onSpendingUpdate: onUpdate,
}
}proxy.defaultPrices function · go · L57-L72 (16 LOC)internal/proxy/proxy.go
func defaultPrices() map[string]ModelPricing {
// Prices in micro-cents per token (1 cent = 1_000_000 micro-cents)
// These are approximate — users can override via config
return map[string]ModelPricing{
// OpenAI
"gpt-4": {InputPerToken: 3000, OutputPerToken: 6000}, // $0.03/$0.06 per 1K
"gpt-4-turbo": {InputPerToken: 1000, OutputPerToken: 3000}, // $0.01/$0.03 per 1K
"gpt-4o": {InputPerToken: 250, OutputPerToken: 1000}, // $0.0025/$0.01 per 1K
"gpt-4o-mini": {InputPerToken: 15, OutputPerToken: 60}, // $0.00015/$0.0006 per 1K
"gpt-3.5-turbo": {InputPerToken: 50, OutputPerToken: 150}, // $0.0005/$0.0015 per 1K
// Anthropic
"claude-3-opus": {InputPerToken: 1500, OutputPerToken: 7500}, // $0.015/$0.075 per 1K
"claude-3-sonnet": {InputPerToken: 300, OutputPerToken: 1500}, // $0.003/$0.015 per 1K
"claude-3-haiku": {InputPerToken: 25, OutputPerToken: 125}, // $0.00025/$0.00125 per 1K
}
}proxy.SpendingTracker.RegisterContainer method · go · L76-L97 (22 LOC)internal/proxy/proxy.go
func (st *SpendingTracker) RegisterContainer(containerID string, budget int64, existingSpending int64) (string, error) {
// Start a per-container proxy listener
listener, err := net.Listen("tcp", "0.0.0.0:0")
if err != nil {
return "", fmt.Errorf("listen: %w", err)
}
addr := listener.Addr().String()
st.mu.Lock()
st.containerByAddr[addr] = containerID
st.spending[containerID] = existingSpending
st.budgets[containerID] = budget
st.mu.Unlock()
proxy := &http.Server{
Handler: st.proxyHandler(containerID),
}
go proxy.Serve(listener)
log.Printf("[proxy] started proxy for container %s on %s (budget: %d cents)", containerID, addr, budget)
return addr, nil
}proxy.SpendingTracker.proxyHandler method · go · L120-L180 (61 LOC)internal/proxy/proxy.go
func (st *SpendingTracker) proxyHandler(containerID string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check if budget is exceeded before proxying
st.mu.RLock()
budget := st.budgets[containerID]
spent := st.spending[containerID]
st.mu.RUnlock()
isAPICall := st.isTrackedAPI(r.Host)
if isAPICall && budget > 0 && spent >= budget {
http.Error(w, `{"error":"spending budget exceeded"}`, http.StatusTooManyRequests)
return
}
// Forward the request
outReq, err := http.NewRequestWithContext(r.Context(), r.Method, r.URL.String(), r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadGateway)
return
}
outReq.Header = r.Header.Clone()
outReq.ContentLength = r.ContentLength
transport := st.transport
if transport == nil {
transport = http.DefaultTransport
}
resp, err := transport.RoundTrip(outReq)
if err != nil {
http.Error(w, err.Error(), http.StatusBadGateway)
return
}
defer proxy.IsTrackedAPIHost function · go · L183-L194 (12 LOC)internal/proxy/proxy.go
func IsTrackedAPIHost(host string) bool {
tracked := []string{
"api.openai.com",
"api.anthropic.com",
}
for _, h := range tracked {
if strings.Contains(host, h) {
return true
}
}
return false
}proxy.SpendingTracker.trackSpending method · go · L211-L247 (37 LOC)internal/proxy/proxy.go
func (st *SpendingTracker) trackSpending(containerID string, host string, body []byte) {
var resp apiUsage
if err := json.Unmarshal(body, &resp); err != nil {
return
}
inputTokens := resp.Usage.PromptTokens + resp.Usage.InputTokens
outputTokens := resp.Usage.CompletionTokens + resp.Usage.OutputTokens
if inputTokens == 0 && outputTokens == 0 {
return
}
// Find pricing for this model
modelName := normalizeModelName(resp.Model)
st.mu.RLock()
pricing, ok := st.prices[modelName]
st.mu.RUnlock()
if !ok {
// Use a conservative default
pricing = ModelPricing{InputPerToken: 1000, OutputPerToken: 3000}
}
costCents := CalculateSpendingCents(inputTokens, outputTokens, pricing)
st.mu.Lock()
st.spending[containerID] += costCents
newTotal := st.spending[containerID]
st.mu.Unlock()
if st.onSpendingUpdate != nil {
st.onSpendingUpdate(containerID, newTotal)
}
log.Printf("[proxy] container %s: %d input + %d output tokens (%s) = %d cents (total: %d)",
containerID, proxy.CalculateSpendingCents function · go · L250-L257 (8 LOC)internal/proxy/proxy.go
func CalculateSpendingCents(inputTokens, outputTokens int64, pricing ModelPricing) int64 {
costMicroCents := inputTokens*pricing.InputPerToken + outputTokens*pricing.OutputPerToken
costCents := costMicroCents / 1_000_000
if costCents == 0 && costMicroCents > 0 {
costCents = 1 // minimum 1 cent charge to avoid free-riding
}
return costCents
}proxy.normalizeModelName function · go · L259-L273 (15 LOC)internal/proxy/proxy.go
func normalizeModelName(model string) string {
// Strip date suffixes and version details
model = strings.ToLower(model)
// Map known prefixes
prefixes := []string{
"gpt-4o-mini", "gpt-4o", "gpt-4-turbo", "gpt-4", "gpt-3.5-turbo",
"claude-3-opus", "claude-3-sonnet", "claude-3-haiku",
}
for _, p := range prefixes {
if strings.HasPrefix(model, p) {
return p
}
}
return model
}Open data scored by Repobility · https://repobility.com
proxy.SpendingTracker.ConnectHandler method · go · L276-L284 (9 LOC)internal/proxy/proxy.go
func (st *SpendingTracker) ConnectHandler(containerID string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodConnect {
st.handleConnect(containerID, w, r)
return
}
st.proxyHandler(containerID).ServeHTTP(w, r)
})
}proxy.SpendingTracker.handleConnect method · go · L286-L324 (39 LOC)internal/proxy/proxy.go
func (st *SpendingTracker) handleConnect(containerID string, w http.ResponseWriter, r *http.Request) {
// For CONNECT (HTTPS), we just tunnel the connection
// We can't inspect the content, but we can block by host
st.mu.RLock()
budget := st.budgets[containerID]
spent := st.spending[containerID]
st.mu.RUnlock()
if st.isTrackedAPI(r.Host) && budget > 0 && spent >= budget {
http.Error(w, "spending budget exceeded", http.StatusTooManyRequests)
return
}
destConn, err := net.Dial("tcp", r.Host)
if err != nil {
http.Error(w, err.Error(), http.StatusBadGateway)
return
}
defer destConn.Close()
hijacker, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "hijacking not supported", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
clientConn, _, err := hijacker.Hijack()
if err != nil {
return
}
defer clientConn.Close()
// Bidirectional copy
done := make(chan struct{}, 2)
go func() { io.Copy(destConn, clientConn); done <- struct{}{} }()
gproxy.SpendingTracker.LoadPrices method · go · L327-L342 (16 LOC)internal/proxy/proxy.go
func (st *SpendingTracker) LoadPrices(r io.Reader) error {
var prices map[string]ModelPricing
data, err := io.ReadAll(r)
if err != nil {
return err
}
if err := json.Unmarshal(data, &prices); err != nil {
return err
}
st.mu.Lock()
defer st.mu.Unlock()
for k, v := range prices {
st.prices[k] = v
}
return nil
}proxy.SpendingTracker.SetResolveOverrides method · go · L347-L359 (13 LOC)internal/proxy/proxy.go
func (st *SpendingTracker) SetResolveOverrides(overrides map[string]string) {
st.transport = &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
host, port, err := net.SplitHostPort(addr)
if err == nil {
if override, ok := overrides[host]; ok {
addr = net.JoinHostPort(override, port)
}
}
return (&net.Dialer{}).DialContext(ctx, network, addr)
},
}
}store.New function · go · L38-L49 (12 LOC)internal/store/store.go
func New(dbPath string) (*Store, error) {
db, err := sql.Open("sqlite3", dbPath+"?_journal_mode=WAL&_busy_timeout=5000")
if err != nil {
return nil, fmt.Errorf("open db: %w", err)
}
s := &Store{db: db}
if err := s.migrate(); err != nil {
db.Close()
return nil, fmt.Errorf("migrate: %w", err)
}
return s, nil
}store.Store.migrate method · go · L51-L80 (30 LOC)internal/store/store.go
func (s *Store) migrate() error {
stmts := []string{
`CREATE TABLE IF NOT EXISTS containers (
id TEXT PRIMARY KEY,
docker_id TEXT NOT NULL,
name TEXT NOT NULL DEFAULT '',
registered_at TEXT NOT NULL
)`,
`CREATE TABLE IF NOT EXISTS limits (
container_id TEXT NOT NULL,
type TEXT NOT NULL,
value INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (container_id, type),
FOREIGN KEY (container_id) REFERENCES containers(id)
)`,
`CREATE TABLE IF NOT EXISTS usage (
container_id TEXT NOT NULL,
type TEXT NOT NULL,
value INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (container_id, type),
FOREIGN KEY (container_id) REFERENCES containers(id)
)`,
}
for _, stmt := range stmts {
if _, err := s.db.Exec(stmt); err != nil {
return fmt.Errorf("exec %q: %w", stmt[:40], err)
}
}
return nil
}store.Store.RegisterContainer method · go · L88-L106 (19 LOC)internal/store/store.go
func (s *Store) RegisterContainer(dockerID, name string) (*model.Container, error) {
s.mu.Lock()
defer s.mu.Unlock()
c := &model.Container{
ID: dockerID[:12],
DockerID: dockerID,
Name: name,
RegisteredAt: time.Now().UTC(),
}
_, err := s.db.Exec(
`INSERT OR REPLACE INTO containers (id, docker_id, name, registered_at) VALUES (?, ?, ?, ?)`,
c.ID, c.DockerID, c.Name, c.RegisteredAt.Format(time.RFC3339),
)
if err != nil {
return nil, fmt.Errorf("insert container: %w", err)
}
return c, nil
}store.Store.GetContainer method · go · L109-L121 (13 LOC)internal/store/store.go
func (s *Store) GetContainer(id string) (*model.Container, error) {
row := s.db.QueryRow(`SELECT id, docker_id, name, registered_at FROM containers WHERE id = ?`, id)
c := &model.Container{}
var regAt string
if err := row.Scan(&c.ID, &c.DockerID, &c.Name, ®At); err != nil {
if err == sql.ErrNoRows {
return nil, fmt.Errorf("container %s not found", id)
}
return nil, err
}
c.RegisteredAt, _ = time.Parse(time.RFC3339, regAt)
return c, nil
}All rows above produced by Repobility · https://repobility.com
store.Store.ListContainers method · go · L124-L142 (19 LOC)internal/store/store.go
func (s *Store) ListContainers() ([]model.Container, error) {
rows, err := s.db.Query(`SELECT id, docker_id, name, registered_at FROM containers ORDER BY registered_at`)
if err != nil {
return nil, err
}
defer rows.Close()
var result []model.Container
for rows.Next() {
var c model.Container
var regAt string
if err := rows.Scan(&c.ID, &c.DockerID, &c.Name, ®At); err != nil {
return nil, err
}
c.RegisteredAt, _ = time.Parse(time.RFC3339, regAt)
result = append(result, c)
}
return result, rows.Err()
}store.Store.RemoveContainer method · go · L145-L159 (15 LOC)internal/store/store.go
func (s *Store) RemoveContainer(id string) error {
s.mu.Lock()
defer s.mu.Unlock()
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
tx.Exec(`DELETE FROM usage WHERE container_id = ?`, id)
tx.Exec(`DELETE FROM limits WHERE container_id = ?`, id)
tx.Exec(`DELETE FROM containers WHERE id = ?`, id)
return tx.Commit()
}store.Store.SetLimit method · go · L162-L171 (10 LOC)internal/store/store.go
func (s *Store) SetLimit(containerID string, limitType model.LimitType, value int64) error {
s.mu.Lock()
defer s.mu.Unlock()
_, err := s.db.Exec(
`INSERT OR REPLACE INTO limits (container_id, type, value) VALUES (?, ?, ?)`,
containerID, string(limitType), value,
)
return err
}store.Store.GetLimit method · go · L174-L187 (14 LOC)internal/store/store.go
func (s *Store) GetLimit(containerID string, limitType model.LimitType) (int64, error) {
row := s.db.QueryRow(
`SELECT value FROM limits WHERE container_id = ? AND type = ?`,
containerID, string(limitType),
)
var val int64
if err := row.Scan(&val); err != nil {
if err == sql.ErrNoRows {
return 0, nil
}
return 0, err
}
return val, nil
}store.Store.GetAllLimits method · go · L190-L209 (20 LOC)internal/store/store.go
func (s *Store) GetAllLimits(containerID string) (map[model.LimitType]int64, error) {
rows, err := s.db.Query(
`SELECT type, value FROM limits WHERE container_id = ?`, containerID,
)
if err != nil {
return nil, err
}
defer rows.Close()
result := make(map[model.LimitType]int64)
for rows.Next() {
var t string
var v int64
if err := rows.Scan(&t, &v); err != nil {
return nil, err
}
result[model.LimitType(t)] = v
}
return result, rows.Err()
}store.Store.SetUsage method · go · L212-L221 (10 LOC)internal/store/store.go
func (s *Store) SetUsage(containerID string, limitType model.LimitType, value int64) error {
s.mu.Lock()
defer s.mu.Unlock()
_, err := s.db.Exec(
`INSERT OR REPLACE INTO usage (container_id, type, value) VALUES (?, ?, ?)`,
containerID, string(limitType), value,
)
return err
}store.Store.GetUsage method · go · L224-L237 (14 LOC)internal/store/store.go
func (s *Store) GetUsage(containerID string, limitType model.LimitType) (int64, error) {
row := s.db.QueryRow(
`SELECT value FROM usage WHERE container_id = ? AND type = ?`,
containerID, string(limitType),
)
var val int64
if err := row.Scan(&val); err != nil {
if err == sql.ErrNoRows {
return 0, nil
}
return 0, err
}
return val, nil
}store.Store.GetAllUsage method · go · L240-L259 (20 LOC)internal/store/store.go
func (s *Store) GetAllUsage(containerID string) (map[model.LimitType]int64, error) {
rows, err := s.db.Query(
`SELECT type, value FROM usage WHERE container_id = ?`, containerID,
)
if err != nil {
return nil, err
}
defer rows.Close()
result := make(map[model.LimitType]int64)
for rows.Next() {
var t string
var v int64
if err := rows.Scan(&t, &v); err != nil {
return nil, err
}
result[model.LimitType(t)] = v
}
return result, rows.Err()
}Want this analysis on your repo? https://repobility.com/scan/
store.Store.AddUsage method · go · L262-L272 (11 LOC)internal/store/store.go
func (s *Store) AddUsage(containerID string, limitType model.LimitType, delta int64) error {
s.mu.Lock()
defer s.mu.Unlock()
_, err := s.db.Exec(
`INSERT INTO usage (container_id, type, value) VALUES (?, ?, ?)
ON CONFLICT(container_id, type) DO UPDATE SET value = value + ?`,
containerID, string(limitType), delta, delta,
)
return err
}store.Store.CopyLimits method · go · L275-L285 (11 LOC)internal/store/store.go
func (s *Store) CopyLimits(fromID, toID string) error {
s.mu.Lock()
defer s.mu.Unlock()
_, err := s.db.Exec(
`INSERT OR REPLACE INTO limits (container_id, type, value)
SELECT ?, type, value FROM limits WHERE container_id = ?`,
toID, fromID,
)
return err
}store.Store.ResolveContainerID method · go · L288-L309 (22 LOC)internal/store/store.go
func (s *Store) ResolveContainerID(query string) (string, error) {
// Try exact match on ID first
row := s.db.QueryRow(`SELECT id FROM containers WHERE id = ?`, query)
var id string
if err := row.Scan(&id); err == nil {
return id, nil
}
// Try prefix match on docker_id
row = s.db.QueryRow(`SELECT id FROM containers WHERE docker_id LIKE ? LIMIT 1`, query+"%")
if err := row.Scan(&id); err == nil {
return id, nil
}
// Try name match
row = s.db.QueryRow(`SELECT id FROM containers WHERE name = ?`, query)
if err := row.Scan(&id); err == nil {
return id, nil
}
return "", fmt.Errorf("container %q not found", query)
}testutil.NewMockStore function · go · L23-L29 (7 LOC)internal/testutil/mocks.go
func NewMockStore() *MockStore {
return &MockStore{
Containers: make(map[string]*model.Container),
Limits: make(map[string]map[model.LimitType]int64),
Usages: make(map[string]map[model.LimitType]int64),
}
}testutil.MockStore.RegisterContainer method · go · L31-L41 (11 LOC)internal/testutil/mocks.go
func (s *MockStore) RegisterContainer(dockerID, name string) (*model.Container, error) {
s.mu.Lock()
defer s.mu.Unlock()
id := dockerID
if len(dockerID) >= 12 {
id = dockerID[:12]
}
c := &model.Container{ID: id, DockerID: dockerID, Name: name}
s.Containers[id] = c
return c, nil
}testutil.MockStore.GetContainer method · go · L43-L51 (9 LOC)internal/testutil/mocks.go
func (s *MockStore) GetContainer(id string) (*model.Container, error) {
s.mu.Lock()
defer s.mu.Unlock()
c, ok := s.Containers[id]
if !ok {
return nil, fmt.Errorf("container %s not found", id)
}
return c, nil
}testutil.MockStore.ListContainers method · go · L53-L61 (9 LOC)internal/testutil/mocks.go
func (s *MockStore) ListContainers() ([]model.Container, error) {
s.mu.Lock()
defer s.mu.Unlock()
var result []model.Container
for _, c := range s.Containers {
result = append(result, *c)
}
return result, nil
}testutil.MockStore.RemoveContainer method · go · L63-L70 (8 LOC)internal/testutil/mocks.go
func (s *MockStore) RemoveContainer(id string) error {
s.mu.Lock()
defer s.mu.Unlock()
delete(s.Containers, id)
delete(s.Limits, id)
delete(s.Usages, id)
return nil
}Repobility — same analyzer, your code, free for public repos · /scan/
testutil.MockStore.SetLimit method · go · L72-L80 (9 LOC)internal/testutil/mocks.go
func (s *MockStore) SetLimit(containerID string, limitType model.LimitType, value int64) error {
s.mu.Lock()
defer s.mu.Unlock()
if s.Limits[containerID] == nil {
s.Limits[containerID] = make(map[model.LimitType]int64)
}
s.Limits[containerID][limitType] = value
return nil
}testutil.MockStore.GetLimit method · go · L82-L89 (8 LOC)internal/testutil/mocks.go
func (s *MockStore) GetLimit(containerID string, limitType model.LimitType) (int64, error) {
s.mu.Lock()
defer s.mu.Unlock()
if m, ok := s.Limits[containerID]; ok {
return m[limitType], nil
}
return 0, nil
}testutil.MockStore.GetAllLimits method · go · L91-L101 (11 LOC)internal/testutil/mocks.go
func (s *MockStore) GetAllLimits(containerID string) (map[model.LimitType]int64, error) {
s.mu.Lock()
defer s.mu.Unlock()
result := make(map[model.LimitType]int64)
if m, ok := s.Limits[containerID]; ok {
for k, v := range m {
result[k] = v
}
}
return result, nil
}testutil.MockStore.SetUsage method · go · L103-L111 (9 LOC)internal/testutil/mocks.go
func (s *MockStore) SetUsage(containerID string, limitType model.LimitType, value int64) error {
s.mu.Lock()
defer s.mu.Unlock()
if s.Usages[containerID] == nil {
s.Usages[containerID] = make(map[model.LimitType]int64)
}
s.Usages[containerID][limitType] = value
return nil
}testutil.MockStore.GetUsage method · go · L113-L120 (8 LOC)internal/testutil/mocks.go
func (s *MockStore) GetUsage(containerID string, limitType model.LimitType) (int64, error) {
s.mu.Lock()
defer s.mu.Unlock()
if m, ok := s.Usages[containerID]; ok {
return m[limitType], nil
}
return 0, nil
}testutil.MockStore.GetAllUsage method · go · L122-L132 (11 LOC)internal/testutil/mocks.go
func (s *MockStore) GetAllUsage(containerID string) (map[model.LimitType]int64, error) {
s.mu.Lock()
defer s.mu.Unlock()
result := make(map[model.LimitType]int64)
if m, ok := s.Usages[containerID]; ok {
for k, v := range m {
result[k] = v
}
}
return result, nil
}testutil.MockStore.AddUsage method · go · L134-L142 (9 LOC)internal/testutil/mocks.go
func (s *MockStore) AddUsage(containerID string, limitType model.LimitType, delta int64) error {
s.mu.Lock()
defer s.mu.Unlock()
if s.Usages[containerID] == nil {
s.Usages[containerID] = make(map[model.LimitType]int64)
}
s.Usages[containerID][limitType] += delta
return nil
}testutil.MockStore.CopyLimits method · go · L144-L157 (14 LOC)internal/testutil/mocks.go
func (s *MockStore) CopyLimits(fromID, toID string) error {
s.mu.Lock()
defer s.mu.Unlock()
src := s.Limits[fromID]
if src == nil {
return nil
}
dst := make(map[model.LimitType]int64)
for k, v := range src {
dst[k] = v
}
s.Limits[toID] = dst
return nil
}Open data scored by Repobility · https://repobility.com
testutil.MockStore.ResolveContainerID method · go · L159-L173 (15 LOC)internal/testutil/mocks.go
func (s *MockStore) ResolveContainerID(query string) (string, error) {
s.mu.Lock()
defer s.mu.Unlock()
// Exact ID match
if _, ok := s.Containers[query]; ok {
return query, nil
}
// Name match
for id, c := range s.Containers {
if c.Name == query {
return id, nil
}
}
return "", fmt.Errorf("container %q not found", query)
}testutil.MockDocker.AddContainer method · go · L202-L210 (9 LOC)internal/testutil/mocks.go
func (d *MockDocker) AddContainer(id string, name string, running bool) {
d.mu.Lock()
defer d.mu.Unlock()
d.Containers[id] = &MockContainerState{
Running: running,
Networks: []string{"bridge"},
Name: name,
}
}testutil.MockDocker.InspectContainer method · go · L212-L229 (18 LOC)internal/testutil/mocks.go
func (d *MockDocker) InspectContainer(ctx context.Context, id string) (types.ContainerJSON, error) {
d.mu.Lock()
defer d.mu.Unlock()
state, ok := d.Containers[id]
if !ok {
return types.ContainerJSON{}, fmt.Errorf("container %s not found", id)
}
return types.ContainerJSON{
ContainerJSONBase: &types.ContainerJSONBase{
ID: id,
Name: "/" + state.Name,
State: &types.ContainerState{
Running: state.Running,
Paused: state.Paused,
},
},
}, nil
}