Files
atlantis/server/core/locking/apply_locking.go
Rui Chen 591931a81c chore: fix typos (#5202)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2024-12-28 17:50:53 -05:00

122 lines
3.3 KiB
Go

package locking
import (
"errors"
"time"
"github.com/runatlantis/atlantis/server/events/command"
)
//go:generate pegomock generate --package mocks -o mocks/mock_apply_lock_checker.go ApplyLockChecker
// ApplyLockChecker is an implementation of the global apply lock retrieval.
// It returns an object that contains information about apply locks status.
type ApplyLockChecker interface {
CheckApplyLock() (ApplyCommandLock, error)
}
//go:generate pegomock generate --package mocks -o mocks/mock_apply_locker.go ApplyLocker
// ApplyLocker interface that manages locks for apply command runner
type ApplyLocker interface {
// LockApply creates a lock for ApplyCommand if lock already exists it will
// return existing lock without any changes
LockApply() (ApplyCommandLock, error)
// UnlockApply deletes apply lock created by LockApply if present, otherwise
// it is a no-op
UnlockApply() error
ApplyLockChecker
}
// ApplyCommandLock contains information about apply command lock status.
type ApplyCommandLock struct {
// Locked is true is when apply commands are locked
// Either by using omitting apply from AllowCommands or creating a global ApplyCommandLock
// DisableApply lock take precedence when set
Locked bool
GlobalApplyLockEnabled bool
Time time.Time
Failure string
}
type ApplyClient struct {
backend Backend
disableApply bool
disableGlobalApplyLock bool
}
func NewApplyClient(backend Backend, disableApply bool, disableGlobalApplyLock bool) ApplyLocker {
return &ApplyClient{
backend: backend,
disableApply: disableApply,
disableGlobalApplyLock: disableGlobalApplyLock,
}
}
// LockApply acquires global apply lock.
// DisableApply takes precedence to any existing locks, if it is set to true
// this function returns an error
func (c *ApplyClient) LockApply() (ApplyCommandLock, error) {
response := ApplyCommandLock{}
if c.disableApply {
return response, errors.New("apply is omitted from AllowCommands; Apply commands are locked globally until flag is updated")
}
applyCmdLock, err := c.backend.LockCommand(command.Apply, time.Now())
if err != nil {
return response, err
}
if applyCmdLock != nil {
response.Locked = true
response.Time = applyCmdLock.LockTime()
}
return response, nil
}
// UnlockApply releases a global apply lock.
// DisableApply takes precedence to any existing locks, if it is set to true
// this function returns an error
func (c *ApplyClient) UnlockApply() error {
if c.disableApply {
return errors.New("apply commands are disabled until AllowCommands flag is updated")
}
err := c.backend.UnlockCommand(command.Apply)
if err != nil {
return err
}
return nil
}
// CheckApplyLock retrieves an apply command lock if present.
// If DisableApply is set it will always return a lock.
func (c *ApplyClient) CheckApplyLock() (ApplyCommandLock, error) {
response := ApplyCommandLock{
GlobalApplyLockEnabled: true,
}
if c.disableApply {
return ApplyCommandLock{
Locked: true,
}, nil
}
applyCmdLock, err := c.backend.CheckCommandLock(command.Apply)
if err != nil {
return response, err
}
if applyCmdLock != nil {
response.Locked = true
response.Time = applyCmdLock.LockTime()
}
if c.disableGlobalApplyLock {
response.GlobalApplyLockEnabled = false
}
return response, nil
}