mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-14 08:18:52 +00:00
feat(M31): agent work routing — scope jobs to assigned agents
Deployment jobs now set agent_id from target→agent relationship at creation time. GetPendingWork() uses ListPendingByAgentID() with a 3-way UNION query (direct match, legacy NULL fallback via target JOIN, AwaitingCSR via cert→target→agent chain) so each agent only receives its own jobs. - Added AgentID *string to Job domain struct - Added agent_id to all job SQL queries (5 SELECTs, INSERT, UPDATE, scanJob) - New ListPendingByAgentID() repository method - Rewrote GetPendingWork() from ~25 lines to single scoped query - 4 new Go tests (3 agent routing + 1 deployment agent_id) - Frontend: agent_id/target_id on Job type Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,12 +26,18 @@ type RenewalService struct {
|
||||
jobRepo repository.JobRepository
|
||||
renewalPolicyRepo repository.RenewalPolicyRepository
|
||||
profileRepo repository.CertificateProfileRepository
|
||||
targetRepo repository.TargetRepository
|
||||
auditService *AuditService
|
||||
notificationSvc *NotificationService
|
||||
issuerRegistry map[string]IssuerConnector
|
||||
keygenMode string // "agent" (default) or "server" (demo only)
|
||||
}
|
||||
|
||||
// SetTargetRepo sets the target repository for resolving agent_id on deployment jobs.
|
||||
func (s *RenewalService) SetTargetRepo(repo repository.TargetRepository) {
|
||||
s.targetRepo = repo
|
||||
}
|
||||
|
||||
// IssuerConnector defines the service-layer interface for interacting with certificate issuers.
|
||||
// This is distinct from the connector-layer issuer.Connector interface to maintain dependency
|
||||
// inversion. Use IssuerConnectorAdapter to bridge between the two.
|
||||
@@ -636,12 +642,26 @@ func (s *RenewalService) createDeploymentJobs(ctx context.Context, cert *domain.
|
||||
}
|
||||
for _, targetID := range cert.TargetIDs {
|
||||
tid := targetID
|
||||
|
||||
// Resolve agent_id from target for job routing
|
||||
var agentIDPtr *string
|
||||
if s.targetRepo != nil {
|
||||
target, err := s.targetRepo.Get(ctx, tid)
|
||||
if err != nil {
|
||||
slog.Warn("failed to resolve agent for deployment job", "target_id", tid, "error", err)
|
||||
} else if target.AgentID != "" {
|
||||
agentID := target.AgentID
|
||||
agentIDPtr = &agentID
|
||||
}
|
||||
}
|
||||
|
||||
deployJob := &domain.Job{
|
||||
ID: generateID("job"),
|
||||
CertificateID: cert.ID,
|
||||
Type: domain.JobTypeDeployment,
|
||||
Status: domain.JobStatusPending,
|
||||
TargetID: &tid,
|
||||
AgentID: agentIDPtr,
|
||||
MaxAttempts: 3,
|
||||
ScheduledAt: time.Now(),
|
||||
CreatedAt: time.Now(),
|
||||
|
||||
Reference in New Issue
Block a user