mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 14:11:31 +00:00
M-2 PR-B: Collapse IssuerService + TargetService to ctx-first signatures
- Delete bare TestConnection wrapper in IssuerService; rename
TestConnectionWithContext → TestConnection
- Delete TestTargetConnection delegate shim in TargetService (canonical
TestConnection already ctx-first)
- Add ctx first param to 10 handler-interface methods
(ListIssuers/GetIssuer/CreateIssuer/UpdateIssuer/DeleteIssuer and
ListTargets/GetTarget/CreateTarget/UpdateTarget/DeleteTarget)
- Replace 16 context.Background() call sites with received ctx
- Thread r.Context() through 12 HTTP handler sites in issuers.go and
targets.go (outer TargetHandler.TestTargetConnection HTTP method name
preserved for router compatibility)
- Update MockIssuerService, MockTargetService, and mockTargetService
(integration) for ctx-first forwarding; update test callsite literals
Audit complete. Commit: 1f6cf0eafa. Sections: 12. Findings: 2/7/10/4/6.
This commit is contained in:
@@ -2,6 +2,7 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -15,52 +16,52 @@ import (
|
|||||||
|
|
||||||
// MockIssuerService is a mock implementation of IssuerService interface.
|
// MockIssuerService is a mock implementation of IssuerService interface.
|
||||||
type MockIssuerService struct {
|
type MockIssuerService struct {
|
||||||
ListIssuersFn func(page, perPage int) ([]domain.Issuer, int64, error)
|
ListIssuersFn func(ctx context.Context, page, perPage int) ([]domain.Issuer, int64, error)
|
||||||
GetIssuerFn func(id string) (*domain.Issuer, error)
|
GetIssuerFn func(ctx context.Context, id string) (*domain.Issuer, error)
|
||||||
CreateIssuerFn func(issuer domain.Issuer) (*domain.Issuer, error)
|
CreateIssuerFn func(ctx context.Context, issuer domain.Issuer) (*domain.Issuer, error)
|
||||||
UpdateIssuerFn func(id string, issuer domain.Issuer) (*domain.Issuer, error)
|
UpdateIssuerFn func(ctx context.Context, id string, issuer domain.Issuer) (*domain.Issuer, error)
|
||||||
DeleteIssuerFn func(id string) error
|
DeleteIssuerFn func(ctx context.Context, id string) error
|
||||||
TestConnectionFn func(id string) error
|
TestConnectionFn func(ctx context.Context, id string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockIssuerService) ListIssuers(page, perPage int) ([]domain.Issuer, int64, error) {
|
func (m *MockIssuerService) ListIssuers(ctx context.Context, page, perPage int) ([]domain.Issuer, int64, error) {
|
||||||
if m.ListIssuersFn != nil {
|
if m.ListIssuersFn != nil {
|
||||||
return m.ListIssuersFn(page, perPage)
|
return m.ListIssuersFn(ctx, page, perPage)
|
||||||
}
|
}
|
||||||
return nil, 0, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockIssuerService) GetIssuer(id string) (*domain.Issuer, error) {
|
func (m *MockIssuerService) GetIssuer(ctx context.Context, id string) (*domain.Issuer, error) {
|
||||||
if m.GetIssuerFn != nil {
|
if m.GetIssuerFn != nil {
|
||||||
return m.GetIssuerFn(id)
|
return m.GetIssuerFn(ctx, id)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockIssuerService) CreateIssuer(issuer domain.Issuer) (*domain.Issuer, error) {
|
func (m *MockIssuerService) CreateIssuer(ctx context.Context, issuer domain.Issuer) (*domain.Issuer, error) {
|
||||||
if m.CreateIssuerFn != nil {
|
if m.CreateIssuerFn != nil {
|
||||||
return m.CreateIssuerFn(issuer)
|
return m.CreateIssuerFn(ctx, issuer)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockIssuerService) UpdateIssuer(id string, issuer domain.Issuer) (*domain.Issuer, error) {
|
func (m *MockIssuerService) UpdateIssuer(ctx context.Context, id string, issuer domain.Issuer) (*domain.Issuer, error) {
|
||||||
if m.UpdateIssuerFn != nil {
|
if m.UpdateIssuerFn != nil {
|
||||||
return m.UpdateIssuerFn(id, issuer)
|
return m.UpdateIssuerFn(ctx, id, issuer)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockIssuerService) DeleteIssuer(id string) error {
|
func (m *MockIssuerService) DeleteIssuer(ctx context.Context, id string) error {
|
||||||
if m.DeleteIssuerFn != nil {
|
if m.DeleteIssuerFn != nil {
|
||||||
return m.DeleteIssuerFn(id)
|
return m.DeleteIssuerFn(ctx, id)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockIssuerService) TestConnection(id string) error {
|
func (m *MockIssuerService) TestConnection(ctx context.Context, id string) error {
|
||||||
if m.TestConnectionFn != nil {
|
if m.TestConnectionFn != nil {
|
||||||
return m.TestConnectionFn(id)
|
return m.TestConnectionFn(ctx, id)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ func TestListIssuers_Success(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
ListIssuersFn: func(page, perPage int) ([]domain.Issuer, int64, error) {
|
ListIssuersFn: func(_ context.Context, page, perPage int) ([]domain.Issuer, int64, error) {
|
||||||
return []domain.Issuer{iss1, iss2}, 2, nil
|
return []domain.Issuer{iss1, iss2}, 2, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ func TestListIssuers_Success(t *testing.T) {
|
|||||||
func TestListIssuers_Pagination(t *testing.T) {
|
func TestListIssuers_Pagination(t *testing.T) {
|
||||||
var capturedPage, capturedPerPage int
|
var capturedPage, capturedPerPage int
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
ListIssuersFn: func(page, perPage int) ([]domain.Issuer, int64, error) {
|
ListIssuersFn: func(_ context.Context, page, perPage int) ([]domain.Issuer, int64, error) {
|
||||||
capturedPage = page
|
capturedPage = page
|
||||||
capturedPerPage = perPage
|
capturedPerPage = perPage
|
||||||
return []domain.Issuer{}, 0, nil
|
return []domain.Issuer{}, 0, nil
|
||||||
@@ -137,7 +138,7 @@ func TestListIssuers_Pagination(t *testing.T) {
|
|||||||
|
|
||||||
func TestListIssuers_ServiceError(t *testing.T) {
|
func TestListIssuers_ServiceError(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
ListIssuersFn: func(page, perPage int) ([]domain.Issuer, int64, error) {
|
ListIssuersFn: func(_ context.Context, page, perPage int) ([]domain.Issuer, int64, error) {
|
||||||
return nil, 0, ErrMockServiceFailed
|
return nil, 0, ErrMockServiceFailed
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -169,7 +170,7 @@ func TestListIssuers_MethodNotAllowed(t *testing.T) {
|
|||||||
func TestGetIssuer_Success(t *testing.T) {
|
func TestGetIssuer_Success(t *testing.T) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
GetIssuerFn: func(id string) (*domain.Issuer, error) {
|
GetIssuerFn: func(_ context.Context, id string) (*domain.Issuer, error) {
|
||||||
return &domain.Issuer{
|
return &domain.Issuer{
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: "Local CA",
|
Name: "Local CA",
|
||||||
@@ -195,7 +196,7 @@ func TestGetIssuer_Success(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetIssuer_NotFound(t *testing.T) {
|
func TestGetIssuer_NotFound(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
GetIssuerFn: func(id string) (*domain.Issuer, error) {
|
GetIssuerFn: func(_ context.Context, id string) (*domain.Issuer, error) {
|
||||||
return nil, ErrMockNotFound
|
return nil, ErrMockNotFound
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -228,7 +229,7 @@ func TestGetIssuer_EmptyID(t *testing.T) {
|
|||||||
func TestCreateIssuer_Success(t *testing.T) {
|
func TestCreateIssuer_Success(t *testing.T) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
CreateIssuerFn: func(issuer domain.Issuer) (*domain.Issuer, error) {
|
CreateIssuerFn: func(_ context.Context, issuer domain.Issuer) (*domain.Issuer, error) {
|
||||||
issuer.ID = "iss-new"
|
issuer.ID = "iss-new"
|
||||||
issuer.CreatedAt = now
|
issuer.CreatedAt = now
|
||||||
issuer.UpdatedAt = now
|
issuer.UpdatedAt = now
|
||||||
@@ -328,7 +329,7 @@ func TestCreateIssuer_NameTooLong(t *testing.T) {
|
|||||||
|
|
||||||
func TestCreateIssuer_DuplicateName(t *testing.T) {
|
func TestCreateIssuer_DuplicateName(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
CreateIssuerFn: func(issuer domain.Issuer) (*domain.Issuer, error) {
|
CreateIssuerFn: func(_ context.Context, issuer domain.Issuer) (*domain.Issuer, error) {
|
||||||
return nil, fmt.Errorf("failed to create issuer: duplicate key value violates unique constraint \"issuers_name_key\"")
|
return nil, fmt.Errorf("failed to create issuer: duplicate key value violates unique constraint \"issuers_name_key\"")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -361,7 +362,7 @@ func TestCreateIssuer_DuplicateName(t *testing.T) {
|
|||||||
|
|
||||||
func TestCreateIssuer_UnsupportedType(t *testing.T) {
|
func TestCreateIssuer_UnsupportedType(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
CreateIssuerFn: func(issuer domain.Issuer) (*domain.Issuer, error) {
|
CreateIssuerFn: func(_ context.Context, issuer domain.Issuer) (*domain.Issuer, error) {
|
||||||
return nil, fmt.Errorf("unsupported issuer type: FakeCA")
|
return nil, fmt.Errorf("unsupported issuer type: FakeCA")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -394,7 +395,7 @@ func TestCreateIssuer_UnsupportedType(t *testing.T) {
|
|||||||
|
|
||||||
func TestCreateIssuer_GenericServiceError(t *testing.T) {
|
func TestCreateIssuer_GenericServiceError(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
CreateIssuerFn: func(issuer domain.Issuer) (*domain.Issuer, error) {
|
CreateIssuerFn: func(_ context.Context, issuer domain.Issuer) (*domain.Issuer, error) {
|
||||||
return nil, fmt.Errorf("failed to encrypt config: cipher error")
|
return nil, fmt.Errorf("failed to encrypt config: cipher error")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -419,7 +420,7 @@ func TestCreateIssuer_GenericServiceError(t *testing.T) {
|
|||||||
|
|
||||||
func TestUpdateIssuer_DuplicateName(t *testing.T) {
|
func TestUpdateIssuer_DuplicateName(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
UpdateIssuerFn: func(id string, issuer domain.Issuer) (*domain.Issuer, error) {
|
UpdateIssuerFn: func(_ context.Context, id string, issuer domain.Issuer) (*domain.Issuer, error) {
|
||||||
return nil, fmt.Errorf("failed to update issuer: duplicate key value violates unique constraint")
|
return nil, fmt.Errorf("failed to update issuer: duplicate key value violates unique constraint")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -445,7 +446,7 @@ func TestUpdateIssuer_DuplicateName(t *testing.T) {
|
|||||||
func TestDeleteIssuer_Success(t *testing.T) {
|
func TestDeleteIssuer_Success(t *testing.T) {
|
||||||
var deletedID string
|
var deletedID string
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
DeleteIssuerFn: func(id string) error {
|
DeleteIssuerFn: func(_ context.Context, id string) error {
|
||||||
deletedID = id
|
deletedID = id
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@@ -468,7 +469,7 @@ func TestDeleteIssuer_Success(t *testing.T) {
|
|||||||
|
|
||||||
func TestDeleteIssuer_ServiceError(t *testing.T) {
|
func TestDeleteIssuer_ServiceError(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
DeleteIssuerFn: func(id string) error {
|
DeleteIssuerFn: func(_ context.Context, id string) error {
|
||||||
return ErrMockServiceFailed
|
return ErrMockServiceFailed
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -487,7 +488,7 @@ func TestDeleteIssuer_ServiceError(t *testing.T) {
|
|||||||
|
|
||||||
func TestTestConnection_Success(t *testing.T) {
|
func TestTestConnection_Success(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
TestConnectionFn: func(id string) error {
|
TestConnectionFn: func(_ context.Context, id string) error {
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -514,7 +515,7 @@ func TestTestConnection_Success(t *testing.T) {
|
|||||||
|
|
||||||
func TestTestConnection_Failure(t *testing.T) {
|
func TestTestConnection_Failure(t *testing.T) {
|
||||||
mock := &MockIssuerService{
|
mock := &MockIssuerService{
|
||||||
TestConnectionFn: func(id string) error {
|
TestConnectionFn: func(_ context.Context, id string) error {
|
||||||
return ErrMockServiceFailed
|
return ErrMockServiceFailed
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -13,12 +14,12 @@ import (
|
|||||||
|
|
||||||
// IssuerService defines the service interface for issuer operations.
|
// IssuerService defines the service interface for issuer operations.
|
||||||
type IssuerService interface {
|
type IssuerService interface {
|
||||||
ListIssuers(page, perPage int) ([]domain.Issuer, int64, error)
|
ListIssuers(ctx context.Context, page, perPage int) ([]domain.Issuer, int64, error)
|
||||||
GetIssuer(id string) (*domain.Issuer, error)
|
GetIssuer(ctx context.Context, id string) (*domain.Issuer, error)
|
||||||
CreateIssuer(issuer domain.Issuer) (*domain.Issuer, error)
|
CreateIssuer(ctx context.Context, issuer domain.Issuer) (*domain.Issuer, error)
|
||||||
UpdateIssuer(id string, issuer domain.Issuer) (*domain.Issuer, error)
|
UpdateIssuer(ctx context.Context, id string, issuer domain.Issuer) (*domain.Issuer, error)
|
||||||
DeleteIssuer(id string) error
|
DeleteIssuer(ctx context.Context, id string) error
|
||||||
TestConnection(id string) error
|
TestConnection(ctx context.Context, id string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// IssuerHandler handles HTTP requests for issuer operations.
|
// IssuerHandler handles HTTP requests for issuer operations.
|
||||||
@@ -61,7 +62,7 @@ func (h IssuerHandler) ListIssuers(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
issuers, total, err := h.svc.ListIssuers(page, perPage)
|
issuers, total, err := h.svc.ListIssuers(r.Context(), page, perPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to list issuers", requestID)
|
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to list issuers", requestID)
|
||||||
return
|
return
|
||||||
@@ -93,7 +94,7 @@ func (h IssuerHandler) GetIssuer(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
issuer, err := h.svc.GetIssuer(id)
|
issuer, err := h.svc.GetIssuer(r.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorWithRequestID(w, http.StatusNotFound, "Issuer not found", requestID)
|
ErrorWithRequestID(w, http.StatusNotFound, "Issuer not found", requestID)
|
||||||
return
|
return
|
||||||
@@ -132,7 +133,7 @@ func (h IssuerHandler) CreateIssuer(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
created, err := h.svc.CreateIssuer(issuer)
|
created, err := h.svc.CreateIssuer(r.Context(), issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("failed to create issuer", "error", err, "name", issuer.Name, "type", issuer.Type)
|
h.logger.Error("failed to create issuer", "error", err, "name", issuer.Name, "type", issuer.Type)
|
||||||
errMsg := err.Error()
|
errMsg := err.Error()
|
||||||
@@ -174,7 +175,7 @@ func (h IssuerHandler) UpdateIssuer(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
updated, err := h.svc.UpdateIssuer(id, issuer)
|
updated, err := h.svc.UpdateIssuer(r.Context(), id, issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("failed to update issuer", "error", err, "id", id)
|
h.logger.Error("failed to update issuer", "error", err, "id", id)
|
||||||
errMsg := err.Error()
|
errMsg := err.Error()
|
||||||
@@ -208,7 +209,7 @@ func (h IssuerHandler) DeleteIssuer(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.svc.DeleteIssuer(id); err != nil {
|
if err := h.svc.DeleteIssuer(r.Context(), id); err != nil {
|
||||||
if strings.Contains(err.Error(), "violates foreign key") || strings.Contains(err.Error(), "RESTRICT") {
|
if strings.Contains(err.Error(), "violates foreign key") || strings.Contains(err.Error(), "RESTRICT") {
|
||||||
ErrorWithRequestID(w, http.StatusConflict, "Cannot delete issuer: certificates are still using this issuer", requestID)
|
ErrorWithRequestID(w, http.StatusConflict, "Cannot delete issuer: certificates are still using this issuer", requestID)
|
||||||
} else if strings.Contains(err.Error(), "not found") {
|
} else if strings.Contains(err.Error(), "not found") {
|
||||||
@@ -241,7 +242,7 @@ func (h IssuerHandler) TestConnection(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
issuerID := parts[0]
|
issuerID := parts[0]
|
||||||
|
|
||||||
if err := h.svc.TestConnection(issuerID); err != nil {
|
if err := h.svc.TestConnection(r.Context(), issuerID); err != nil {
|
||||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Connection test failed", requestID)
|
ErrorWithRequestID(w, http.StatusInternalServerError, "Connection test failed", requestID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -13,52 +14,52 @@ import (
|
|||||||
|
|
||||||
// MockTargetService is a mock implementation of TargetService interface.
|
// MockTargetService is a mock implementation of TargetService interface.
|
||||||
type MockTargetService struct {
|
type MockTargetService struct {
|
||||||
ListTargetsFn func(page, perPage int) ([]domain.DeploymentTarget, int64, error)
|
ListTargetsFn func(ctx context.Context, page, perPage int) ([]domain.DeploymentTarget, int64, error)
|
||||||
GetTargetFn func(id string) (*domain.DeploymentTarget, error)
|
GetTargetFn func(ctx context.Context, id string) (*domain.DeploymentTarget, error)
|
||||||
CreateTargetFn func(target domain.DeploymentTarget) (*domain.DeploymentTarget, error)
|
CreateTargetFn func(ctx context.Context, target domain.DeploymentTarget) (*domain.DeploymentTarget, error)
|
||||||
UpdateTargetFn func(id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error)
|
UpdateTargetFn func(ctx context.Context, id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error)
|
||||||
DeleteTargetFn func(id string) error
|
DeleteTargetFn func(ctx context.Context, id string) error
|
||||||
TestTargetConnectionFn func(id string) error
|
TestConnectionFn func(ctx context.Context, id string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockTargetService) ListTargets(page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
func (m *MockTargetService) ListTargets(ctx context.Context, page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
||||||
if m.ListTargetsFn != nil {
|
if m.ListTargetsFn != nil {
|
||||||
return m.ListTargetsFn(page, perPage)
|
return m.ListTargetsFn(ctx, page, perPage)
|
||||||
}
|
}
|
||||||
return nil, 0, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockTargetService) GetTarget(id string) (*domain.DeploymentTarget, error) {
|
func (m *MockTargetService) GetTarget(ctx context.Context, id string) (*domain.DeploymentTarget, error) {
|
||||||
if m.GetTargetFn != nil {
|
if m.GetTargetFn != nil {
|
||||||
return m.GetTargetFn(id)
|
return m.GetTargetFn(ctx, id)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockTargetService) CreateTarget(target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
func (m *MockTargetService) CreateTarget(ctx context.Context, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
||||||
if m.CreateTargetFn != nil {
|
if m.CreateTargetFn != nil {
|
||||||
return m.CreateTargetFn(target)
|
return m.CreateTargetFn(ctx, target)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockTargetService) UpdateTarget(id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
func (m *MockTargetService) UpdateTarget(ctx context.Context, id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
||||||
if m.UpdateTargetFn != nil {
|
if m.UpdateTargetFn != nil {
|
||||||
return m.UpdateTargetFn(id, target)
|
return m.UpdateTargetFn(ctx, id, target)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockTargetService) DeleteTarget(id string) error {
|
func (m *MockTargetService) DeleteTarget(ctx context.Context, id string) error {
|
||||||
if m.DeleteTargetFn != nil {
|
if m.DeleteTargetFn != nil {
|
||||||
return m.DeleteTargetFn(id)
|
return m.DeleteTargetFn(ctx, id)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockTargetService) TestTargetConnection(id string) error {
|
func (m *MockTargetService) TestConnection(ctx context.Context, id string) error {
|
||||||
if m.TestTargetConnectionFn != nil {
|
if m.TestConnectionFn != nil {
|
||||||
return m.TestTargetConnectionFn(id)
|
return m.TestConnectionFn(ctx, id)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ func TestListTargets_Success(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
ListTargetsFn: func(page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
ListTargetsFn: func(_ context.Context, page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
||||||
return []domain.DeploymentTarget{t1, t2}, 2, nil
|
return []domain.DeploymentTarget{t1, t2}, 2, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ func TestListTargets_Success(t *testing.T) {
|
|||||||
func TestListTargets_Pagination(t *testing.T) {
|
func TestListTargets_Pagination(t *testing.T) {
|
||||||
var capturedPage, capturedPerPage int
|
var capturedPage, capturedPerPage int
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
ListTargetsFn: func(page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
ListTargetsFn: func(_ context.Context, page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
||||||
capturedPage = page
|
capturedPage = page
|
||||||
capturedPerPage = perPage
|
capturedPerPage = perPage
|
||||||
return []domain.DeploymentTarget{}, 0, nil
|
return []domain.DeploymentTarget{}, 0, nil
|
||||||
@@ -137,7 +138,7 @@ func TestListTargets_Pagination(t *testing.T) {
|
|||||||
|
|
||||||
func TestListTargets_ServiceError(t *testing.T) {
|
func TestListTargets_ServiceError(t *testing.T) {
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
ListTargetsFn: func(page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
ListTargetsFn: func(_ context.Context, page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
||||||
return nil, 0, ErrMockServiceFailed
|
return nil, 0, ErrMockServiceFailed
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -169,7 +170,7 @@ func TestListTargets_MethodNotAllowed(t *testing.T) {
|
|||||||
func TestGetTarget_Success(t *testing.T) {
|
func TestGetTarget_Success(t *testing.T) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
GetTargetFn: func(id string) (*domain.DeploymentTarget, error) {
|
GetTargetFn: func(_ context.Context, id string) (*domain.DeploymentTarget, error) {
|
||||||
return &domain.DeploymentTarget{
|
return &domain.DeploymentTarget{
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: "NGINX Proxy",
|
Name: "NGINX Proxy",
|
||||||
@@ -196,7 +197,7 @@ func TestGetTarget_Success(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetTarget_NotFound(t *testing.T) {
|
func TestGetTarget_NotFound(t *testing.T) {
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
GetTargetFn: func(id string) (*domain.DeploymentTarget, error) {
|
GetTargetFn: func(_ context.Context, id string) (*domain.DeploymentTarget, error) {
|
||||||
return nil, ErrMockNotFound
|
return nil, ErrMockNotFound
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -229,7 +230,7 @@ func TestGetTarget_EmptyID(t *testing.T) {
|
|||||||
func TestCreateTarget_Success(t *testing.T) {
|
func TestCreateTarget_Success(t *testing.T) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
CreateTargetFn: func(target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
CreateTargetFn: func(_ context.Context, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
||||||
target.ID = "t-new"
|
target.ID = "t-new"
|
||||||
target.CreatedAt = now
|
target.CreatedAt = now
|
||||||
target.UpdatedAt = now
|
target.UpdatedAt = now
|
||||||
@@ -342,7 +343,7 @@ func TestCreateTarget_MethodNotAllowed(t *testing.T) {
|
|||||||
func TestUpdateTarget_Success(t *testing.T) {
|
func TestUpdateTarget_Success(t *testing.T) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
UpdateTargetFn: func(id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
UpdateTargetFn: func(_ context.Context, id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
||||||
return &domain.DeploymentTarget{
|
return &domain.DeploymentTarget{
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: target.Name,
|
Name: target.Name,
|
||||||
@@ -375,7 +376,7 @@ func TestUpdateTarget_Success(t *testing.T) {
|
|||||||
func TestDeleteTarget_Success(t *testing.T) {
|
func TestDeleteTarget_Success(t *testing.T) {
|
||||||
var deletedID string
|
var deletedID string
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
DeleteTargetFn: func(id string) error {
|
DeleteTargetFn: func(_ context.Context, id string) error {
|
||||||
deletedID = id
|
deletedID = id
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@@ -398,7 +399,7 @@ func TestDeleteTarget_Success(t *testing.T) {
|
|||||||
|
|
||||||
func TestDeleteTarget_ServiceError(t *testing.T) {
|
func TestDeleteTarget_ServiceError(t *testing.T) {
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
DeleteTargetFn: func(id string) error {
|
DeleteTargetFn: func(_ context.Context, id string) error {
|
||||||
return ErrMockServiceFailed
|
return ErrMockServiceFailed
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -430,7 +431,7 @@ func TestDeleteTarget_EmptyID(t *testing.T) {
|
|||||||
|
|
||||||
func TestTestTargetConnection_Success(t *testing.T) {
|
func TestTestTargetConnection_Success(t *testing.T) {
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
TestTargetConnectionFn: func(id string) error {
|
TestConnectionFn: func(_ context.Context, id string) error {
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -457,7 +458,7 @@ func TestTestTargetConnection_Success(t *testing.T) {
|
|||||||
|
|
||||||
func TestTestTargetConnection_Failed(t *testing.T) {
|
func TestTestTargetConnection_Failed(t *testing.T) {
|
||||||
mock := &MockTargetService{
|
mock := &MockTargetService{
|
||||||
TestTargetConnectionFn: func(id string) error {
|
TestConnectionFn: func(_ context.Context, id string) error {
|
||||||
return ErrMockServiceFailed
|
return ErrMockServiceFailed
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -12,12 +13,12 @@ import (
|
|||||||
|
|
||||||
// TargetService defines the service interface for deployment target operations.
|
// TargetService defines the service interface for deployment target operations.
|
||||||
type TargetService interface {
|
type TargetService interface {
|
||||||
ListTargets(page, perPage int) ([]domain.DeploymentTarget, int64, error)
|
ListTargets(ctx context.Context, page, perPage int) ([]domain.DeploymentTarget, int64, error)
|
||||||
GetTarget(id string) (*domain.DeploymentTarget, error)
|
GetTarget(ctx context.Context, id string) (*domain.DeploymentTarget, error)
|
||||||
CreateTarget(target domain.DeploymentTarget) (*domain.DeploymentTarget, error)
|
CreateTarget(ctx context.Context, target domain.DeploymentTarget) (*domain.DeploymentTarget, error)
|
||||||
UpdateTarget(id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error)
|
UpdateTarget(ctx context.Context, id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error)
|
||||||
DeleteTarget(id string) error
|
DeleteTarget(ctx context.Context, id string) error
|
||||||
TestTargetConnection(id string) error
|
TestConnection(ctx context.Context, id string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// TargetHandler handles HTTP requests for deployment target operations.
|
// TargetHandler handles HTTP requests for deployment target operations.
|
||||||
@@ -54,7 +55,7 @@ func (h TargetHandler) ListTargets(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
targets, total, err := h.svc.ListTargets(page, perPage)
|
targets, total, err := h.svc.ListTargets(r.Context(), page, perPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to list targets", requestID)
|
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to list targets", requestID)
|
||||||
return
|
return
|
||||||
@@ -86,7 +87,7 @@ func (h TargetHandler) GetTarget(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
target, err := h.svc.GetTarget(id)
|
target, err := h.svc.GetTarget(r.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorWithRequestID(w, http.StatusNotFound, "Target not found", requestID)
|
ErrorWithRequestID(w, http.StatusNotFound, "Target not found", requestID)
|
||||||
return
|
return
|
||||||
@@ -125,7 +126,7 @@ func (h TargetHandler) CreateTarget(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
created, err := h.svc.CreateTarget(target)
|
created, err := h.svc.CreateTarget(r.Context(), target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to create target", requestID)
|
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to create target", requestID)
|
||||||
return
|
return
|
||||||
@@ -158,7 +159,7 @@ func (h TargetHandler) UpdateTarget(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
updated, err := h.svc.UpdateTarget(id, target)
|
updated, err := h.svc.UpdateTarget(r.Context(), id, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to update target", requestID)
|
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to update target", requestID)
|
||||||
return
|
return
|
||||||
@@ -183,7 +184,7 @@ func (h TargetHandler) DeleteTarget(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.svc.DeleteTarget(id); err != nil {
|
if err := h.svc.DeleteTarget(r.Context(), id); err != nil {
|
||||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to delete target", requestID)
|
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to delete target", requestID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -210,7 +211,7 @@ func (h TargetHandler) TestTargetConnection(w http.ResponseWriter, r *http.Reque
|
|||||||
}
|
}
|
||||||
id := parts[0]
|
id := parts[0]
|
||||||
|
|
||||||
if err := h.svc.TestTargetConnection(id); err != nil {
|
if err := h.svc.TestConnection(r.Context(), id); err != nil {
|
||||||
JSON(w, http.StatusOK, map[string]interface{}{
|
JSON(w, http.StatusOK, map[string]interface{}{
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
|
|||||||
@@ -1036,8 +1036,8 @@ type mockTargetService struct {
|
|||||||
auditService *service.AuditService
|
auditService *service.AuditService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockTargetService) ListTargets(page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
func (m *mockTargetService) ListTargets(ctx context.Context, page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
||||||
targets, err := m.targetRepo.List(context.Background())
|
targets, err := m.targetRepo.List(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
@@ -1048,30 +1048,30 @@ func (m *mockTargetService) ListTargets(page, perPage int) ([]domain.DeploymentT
|
|||||||
return result, int64(len(result)), nil
|
return result, int64(len(result)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockTargetService) GetTarget(id string) (*domain.DeploymentTarget, error) {
|
func (m *mockTargetService) GetTarget(ctx context.Context, id string) (*domain.DeploymentTarget, error) {
|
||||||
return m.targetRepo.Get(context.Background(), id)
|
return m.targetRepo.Get(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockTargetService) CreateTarget(target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
func (m *mockTargetService) CreateTarget(ctx context.Context, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
||||||
if err := m.targetRepo.Create(context.Background(), &target); err != nil {
|
if err := m.targetRepo.Create(ctx, &target); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &target, nil
|
return &target, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockTargetService) UpdateTarget(id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
func (m *mockTargetService) UpdateTarget(ctx context.Context, id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
||||||
target.ID = id
|
target.ID = id
|
||||||
if err := m.targetRepo.Update(context.Background(), &target); err != nil {
|
if err := m.targetRepo.Update(ctx, &target); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &target, nil
|
return &target, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockTargetService) DeleteTarget(id string) error {
|
func (m *mockTargetService) DeleteTarget(ctx context.Context, id string) error {
|
||||||
return m.targetRepo.Delete(context.Background(), id)
|
return m.targetRepo.Delete(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockTargetService) TestTargetConnection(id string) error {
|
func (m *mockTargetService) TestConnection(ctx context.Context, id string) error {
|
||||||
return nil // No-op for integration tests
|
return nil // No-op for integration tests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-20
@@ -260,9 +260,9 @@ func (s *IssuerService) Delete(ctx context.Context, id string, actor string) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestConnectionWithContext tests the connection to an issuer by instantiating a throwaway
|
// TestConnection tests the connection to an issuer by instantiating a throwaway
|
||||||
// connector and calling ValidateConfig. Records the result in the database.
|
// connector and calling ValidateConfig. Records the result in the database.
|
||||||
func (s *IssuerService) TestConnectionWithContext(ctx context.Context, id string) error {
|
func (s *IssuerService) TestConnection(ctx context.Context, id string) error {
|
||||||
iss, err := s.issuerRepo.Get(ctx, id)
|
iss, err := s.issuerRepo.Get(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("issuer not found: %w", err)
|
return fmt.Errorf("issuer not found: %w", err)
|
||||||
@@ -291,11 +291,6 @@ func (s *IssuerService) TestConnectionWithContext(ctx context.Context, id string
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestConnection verifies the issuer connection (handler interface method).
|
|
||||||
func (s *IssuerService) TestConnection(id string) error {
|
|
||||||
return s.TestConnectionWithContext(context.Background(), id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildRegistry loads all enabled issuers from the database and rebuilds the dynamic registry.
|
// BuildRegistry loads all enabled issuers from the database and rebuilds the dynamic registry.
|
||||||
// Called at server startup. Partial failures (individual issuers failing to load) are logged
|
// Called at server startup. Partial failures (individual issuers failing to load) are logged
|
||||||
// as warnings but don't prevent the server from starting.
|
// as warnings but don't prevent the server from starting.
|
||||||
@@ -633,7 +628,7 @@ func (s *IssuerService) buildEnvVarSeeds(cfg *config.Config) []*domain.Issuer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListIssuers returns paginated issuers (handler interface method).
|
// ListIssuers returns paginated issuers (handler interface method).
|
||||||
func (s *IssuerService) ListIssuers(page, perPage int) ([]domain.Issuer, int64, error) {
|
func (s *IssuerService) ListIssuers(ctx context.Context, page, perPage int) ([]domain.Issuer, int64, error) {
|
||||||
if page < 1 {
|
if page < 1 {
|
||||||
page = 1
|
page = 1
|
||||||
}
|
}
|
||||||
@@ -641,7 +636,7 @@ func (s *IssuerService) ListIssuers(page, perPage int) ([]domain.Issuer, int64,
|
|||||||
perPage = 50
|
perPage = 50
|
||||||
}
|
}
|
||||||
|
|
||||||
issuers, err := s.issuerRepo.List(context.Background())
|
issuers, err := s.issuerRepo.List(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, fmt.Errorf("failed to list issuers: %w", err)
|
return nil, 0, fmt.Errorf("failed to list issuers: %w", err)
|
||||||
}
|
}
|
||||||
@@ -658,12 +653,12 @@ func (s *IssuerService) ListIssuers(page, perPage int) ([]domain.Issuer, int64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetIssuer returns a single issuer (handler interface method).
|
// GetIssuer returns a single issuer (handler interface method).
|
||||||
func (s *IssuerService) GetIssuer(id string) (*domain.Issuer, error) {
|
func (s *IssuerService) GetIssuer(ctx context.Context, id string) (*domain.Issuer, error) {
|
||||||
return s.issuerRepo.Get(context.Background(), id)
|
return s.issuerRepo.Get(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateIssuer creates a new issuer (handler interface method).
|
// CreateIssuer creates a new issuer (handler interface method).
|
||||||
func (s *IssuerService) CreateIssuer(iss domain.Issuer) (*domain.Issuer, error) {
|
func (s *IssuerService) CreateIssuer(ctx context.Context, iss domain.Issuer) (*domain.Issuer, error) {
|
||||||
iss.Type = normalizeIssuerType(iss.Type)
|
iss.Type = normalizeIssuerType(iss.Type)
|
||||||
if !isValidIssuerType(iss.Type) {
|
if !isValidIssuerType(iss.Type) {
|
||||||
return nil, fmt.Errorf("unsupported issuer type: %s", iss.Type)
|
return nil, fmt.Errorf("unsupported issuer type: %s", iss.Type)
|
||||||
@@ -700,26 +695,26 @@ func (s *IssuerService) CreateIssuer(iss domain.Issuer) (*domain.Issuer, error)
|
|||||||
iss.Config = redactConfigJSON(iss.Config)
|
iss.Config = redactConfigJSON(iss.Config)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.issuerRepo.Create(context.Background(), &iss); err != nil {
|
if err := s.issuerRepo.Create(ctx, &iss); err != nil {
|
||||||
return nil, fmt.Errorf("failed to create issuer: %w", err)
|
return nil, fmt.Errorf("failed to create issuer: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild registry
|
// Rebuild registry
|
||||||
if iss.Enabled {
|
if iss.Enabled {
|
||||||
s.rebuildRegistryQuiet(context.Background())
|
s.rebuildRegistryQuiet(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &iss, nil
|
return &iss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateIssuer modifies an issuer (handler interface method).
|
// UpdateIssuer modifies an issuer (handler interface method).
|
||||||
func (s *IssuerService) UpdateIssuer(id string, iss domain.Issuer) (*domain.Issuer, error) {
|
func (s *IssuerService) UpdateIssuer(ctx context.Context, id string, iss domain.Issuer) (*domain.Issuer, error) {
|
||||||
iss.ID = id
|
iss.ID = id
|
||||||
iss.UpdatedAt = time.Now()
|
iss.UpdatedAt = time.Now()
|
||||||
|
|
||||||
// Merge redacted fields with existing config
|
// Merge redacted fields with existing config
|
||||||
if len(iss.Config) > 0 {
|
if len(iss.Config) > 0 {
|
||||||
mergedConfig, err := s.mergeRedactedConfig(context.Background(), id, iss.Config)
|
mergedConfig, err := s.mergeRedactedConfig(ctx, id, iss.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to merge config: %w", err)
|
return nil, fmt.Errorf("failed to merge config: %w", err)
|
||||||
}
|
}
|
||||||
@@ -732,18 +727,18 @@ func (s *IssuerService) UpdateIssuer(id string, iss domain.Issuer) (*domain.Issu
|
|||||||
iss.Config = redactConfigJSON(json.RawMessage(mergedConfig))
|
iss.Config = redactConfigJSON(json.RawMessage(mergedConfig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.issuerRepo.Update(context.Background(), &iss); err != nil {
|
if err := s.issuerRepo.Update(ctx, &iss); err != nil {
|
||||||
return nil, fmt.Errorf("failed to update issuer: %w", err)
|
return nil, fmt.Errorf("failed to update issuer: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.rebuildRegistryQuiet(context.Background())
|
s.rebuildRegistryQuiet(ctx)
|
||||||
|
|
||||||
return &iss, nil
|
return &iss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteIssuer removes an issuer (handler interface method).
|
// DeleteIssuer removes an issuer (handler interface method).
|
||||||
func (s *IssuerService) DeleteIssuer(id string) error {
|
func (s *IssuerService) DeleteIssuer(ctx context.Context, id string) error {
|
||||||
if err := s.issuerRepo.Delete(context.Background(), id); err != nil {
|
if err := s.issuerRepo.Delete(ctx, id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if s.registry != nil {
|
if s.registry != nil {
|
||||||
|
|||||||
@@ -484,10 +484,10 @@ func TestIssuerService_TestConnection_Success(t *testing.T) {
|
|||||||
|
|
||||||
svc := NewIssuerService(repo, auditService, NewIssuerRegistry(slog.Default()), "", slog.Default())
|
svc := NewIssuerService(repo, auditService, NewIssuerRegistry(slog.Default()), "", slog.Default())
|
||||||
|
|
||||||
err := svc.TestConnectionWithContext(ctx, "iss-test-conn")
|
err := svc.TestConnection(ctx, "iss-test-conn")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("TestConnectionWithContext failed: %v", err)
|
t.Fatalf("TestConnection failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,7 +502,7 @@ func TestIssuerService_TestConnection_NotFound(t *testing.T) {
|
|||||||
registry := NewIssuerRegistry(slog.Default())
|
registry := NewIssuerRegistry(slog.Default())
|
||||||
service := NewIssuerService(repo, auditService, registry, "", slog.Default())
|
service := NewIssuerService(repo, auditService, registry, "", slog.Default())
|
||||||
|
|
||||||
err := service.TestConnectionWithContext(ctx, "nonexistent-issuer")
|
err := service.TestConnection(ctx, "nonexistent-issuer")
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected error for nonexistent issuer")
|
t.Fatal("expected error for nonexistent issuer")
|
||||||
@@ -542,7 +542,8 @@ func TestIssuerService_ListIssuers_HandlerInterface(t *testing.T) {
|
|||||||
|
|
||||||
service := NewIssuerService(repo, auditService, NewIssuerRegistry(slog.Default()), "", slog.Default())
|
service := NewIssuerService(repo, auditService, NewIssuerRegistry(slog.Default()), "", slog.Default())
|
||||||
|
|
||||||
issuers, total, err := service.ListIssuers(1, 50)
|
ctx := context.Background()
|
||||||
|
issuers, total, err := service.ListIssuers(ctx, 1, 50)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ListIssuers failed: %v", err)
|
t.Fatalf("ListIssuers failed: %v", err)
|
||||||
@@ -580,7 +581,8 @@ func TestIssuerService_CreateIssuer_HandlerInterface(t *testing.T) {
|
|||||||
Enabled: true,
|
Enabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := service.CreateIssuer(issuer)
|
ctx := context.Background()
|
||||||
|
result, err := service.CreateIssuer(ctx, issuer)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateIssuer failed: %v", err)
|
t.Fatalf("CreateIssuer failed: %v", err)
|
||||||
@@ -608,7 +610,8 @@ func TestIssuerService_DeleteIssuer_HandlerInterface(t *testing.T) {
|
|||||||
registry := NewIssuerRegistry(slog.Default())
|
registry := NewIssuerRegistry(slog.Default())
|
||||||
service := NewIssuerService(repo, auditService, registry, "", slog.Default())
|
service := NewIssuerService(repo, auditService, registry, "", slog.Default())
|
||||||
|
|
||||||
err := service.DeleteIssuer("iss-handler-delete")
|
ctx := context.Background()
|
||||||
|
err := service.DeleteIssuer(ctx, "iss-handler-delete")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("DeleteIssuer failed: %v", err)
|
t.Fatalf("DeleteIssuer failed: %v", err)
|
||||||
@@ -722,7 +725,8 @@ func TestIssuerService_CreateIssuer_LowercaseType(t *testing.T) {
|
|||||||
Enabled: true,
|
Enabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := service.CreateIssuer(issuer)
|
ctx := context.Background()
|
||||||
|
result, err := service.CreateIssuer(ctx, issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateIssuer with lowercase 'stepca' should succeed, got: %v", err)
|
t.Fatalf("CreateIssuer with lowercase 'stepca' should succeed, got: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-16
@@ -242,7 +242,7 @@ func (s *TargetService) TestConnection(ctx context.Context, id string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListTargets returns paginated targets (handler interface method).
|
// ListTargets returns paginated targets (handler interface method).
|
||||||
func (s *TargetService) ListTargets(page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
func (s *TargetService) ListTargets(ctx context.Context, page, perPage int) ([]domain.DeploymentTarget, int64, error) {
|
||||||
if page < 1 {
|
if page < 1 {
|
||||||
page = 1
|
page = 1
|
||||||
}
|
}
|
||||||
@@ -250,7 +250,7 @@ func (s *TargetService) ListTargets(page, perPage int) ([]domain.DeploymentTarge
|
|||||||
perPage = 50
|
perPage = 50
|
||||||
}
|
}
|
||||||
|
|
||||||
targets, err := s.targetRepo.List(context.Background())
|
targets, err := s.targetRepo.List(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, fmt.Errorf("failed to list targets: %w", err)
|
return nil, 0, fmt.Errorf("failed to list targets: %w", err)
|
||||||
}
|
}
|
||||||
@@ -267,12 +267,12 @@ func (s *TargetService) ListTargets(page, perPage int) ([]domain.DeploymentTarge
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTarget returns a single target (handler interface method).
|
// GetTarget returns a single target (handler interface method).
|
||||||
func (s *TargetService) GetTarget(id string) (*domain.DeploymentTarget, error) {
|
func (s *TargetService) GetTarget(ctx context.Context, id string) (*domain.DeploymentTarget, error) {
|
||||||
return s.targetRepo.Get(context.Background(), id)
|
return s.targetRepo.Get(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTarget creates a new target (handler interface method).
|
// CreateTarget creates a new target (handler interface method).
|
||||||
func (s *TargetService) CreateTarget(target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
func (s *TargetService) CreateTarget(ctx context.Context, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
||||||
if !isValidTargetType(target.Type) {
|
if !isValidTargetType(target.Type) {
|
||||||
return nil, fmt.Errorf("unsupported target type: %s", target.Type)
|
return nil, fmt.Errorf("unsupported target type: %s", target.Type)
|
||||||
}
|
}
|
||||||
@@ -308,20 +308,20 @@ func (s *TargetService) CreateTarget(target domain.DeploymentTarget) (*domain.De
|
|||||||
target.Config = redactConfigJSON(target.Config)
|
target.Config = redactConfigJSON(target.Config)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.targetRepo.Create(context.Background(), &target); err != nil {
|
if err := s.targetRepo.Create(ctx, &target); err != nil {
|
||||||
return nil, fmt.Errorf("failed to create target: %w", err)
|
return nil, fmt.Errorf("failed to create target: %w", err)
|
||||||
}
|
}
|
||||||
return &target, nil
|
return &target, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTarget modifies a target (handler interface method).
|
// UpdateTarget modifies a target (handler interface method).
|
||||||
func (s *TargetService) UpdateTarget(id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
func (s *TargetService) UpdateTarget(ctx context.Context, id string, target domain.DeploymentTarget) (*domain.DeploymentTarget, error) {
|
||||||
target.ID = id
|
target.ID = id
|
||||||
target.UpdatedAt = time.Now()
|
target.UpdatedAt = time.Now()
|
||||||
|
|
||||||
// Merge redacted fields with existing config
|
// Merge redacted fields with existing config
|
||||||
if len(target.Config) > 0 {
|
if len(target.Config) > 0 {
|
||||||
mergedConfig, err := s.mergeRedactedConfig(context.Background(), id, target.Config)
|
mergedConfig, err := s.mergeRedactedConfig(ctx, id, target.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to merge config: %w", err)
|
return nil, fmt.Errorf("failed to merge config: %w", err)
|
||||||
}
|
}
|
||||||
@@ -334,20 +334,15 @@ func (s *TargetService) UpdateTarget(id string, target domain.DeploymentTarget)
|
|||||||
target.Config = redactConfigJSON(json.RawMessage(mergedConfig))
|
target.Config = redactConfigJSON(json.RawMessage(mergedConfig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.targetRepo.Update(context.Background(), &target); err != nil {
|
if err := s.targetRepo.Update(ctx, &target); err != nil {
|
||||||
return nil, fmt.Errorf("failed to update target: %w", err)
|
return nil, fmt.Errorf("failed to update target: %w", err)
|
||||||
}
|
}
|
||||||
return &target, nil
|
return &target, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteTarget removes a target (handler interface method).
|
// DeleteTarget removes a target (handler interface method).
|
||||||
func (s *TargetService) DeleteTarget(id string) error {
|
func (s *TargetService) DeleteTarget(ctx context.Context, id string) error {
|
||||||
return s.targetRepo.Delete(context.Background(), id)
|
return s.targetRepo.Delete(ctx, id)
|
||||||
}
|
|
||||||
|
|
||||||
// TestTargetConnection tests target connectivity (handler interface method).
|
|
||||||
func (s *TargetService) TestTargetConnection(id string) error {
|
|
||||||
return s.TestConnection(context.Background(), id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Internal helpers ---
|
// --- Internal helpers ---
|
||||||
|
|||||||
@@ -344,7 +344,8 @@ func TestTargetService_ListTargets_Success(t *testing.T) {
|
|||||||
targetRepo.AddTarget(target2)
|
targetRepo.AddTarget(target2)
|
||||||
|
|
||||||
// Call handler-interface method
|
// Call handler-interface method
|
||||||
targets, total, err := svc.ListTargets(1, 50)
|
ctx := context.Background()
|
||||||
|
targets, total, err := svc.ListTargets(ctx, 1, 50)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -364,7 +365,8 @@ func TestTargetService_GetTarget_Success(t *testing.T) {
|
|||||||
target := &domain.DeploymentTarget{ID: "t-1", Name: "Target 1", Type: domain.TargetTypeNGINX}
|
target := &domain.DeploymentTarget{ID: "t-1", Name: "Target 1", Type: domain.TargetTypeNGINX}
|
||||||
targetRepo.AddTarget(target)
|
targetRepo.AddTarget(target)
|
||||||
|
|
||||||
result, err := svc.GetTarget("t-1")
|
ctx := context.Background()
|
||||||
|
result, err := svc.GetTarget(ctx, "t-1")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -382,7 +384,8 @@ func TestTargetService_CreateTarget_Success(t *testing.T) {
|
|||||||
Type: domain.TargetTypeNGINX,
|
Type: domain.TargetTypeNGINX,
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := svc.CreateTarget(target)
|
ctx := context.Background()
|
||||||
|
result, err := svc.CreateTarget(ctx, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -405,7 +408,8 @@ func TestTargetService_CreateTarget_InvalidType(t *testing.T) {
|
|||||||
Type: domain.TargetType("Unknown"),
|
Type: domain.TargetType("Unknown"),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := svc.CreateTarget(target)
|
ctx := context.Background()
|
||||||
|
_, err := svc.CreateTarget(ctx, target)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected error for invalid type, got nil")
|
t.Fatalf("expected error for invalid type, got nil")
|
||||||
}
|
}
|
||||||
@@ -424,7 +428,8 @@ func TestTargetService_UpdateTarget_Success(t *testing.T) {
|
|||||||
Type: domain.TargetTypeApache,
|
Type: domain.TargetTypeApache,
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := svc.UpdateTarget("t-1", updated)
|
ctx := context.Background()
|
||||||
|
result, err := svc.UpdateTarget(ctx, "t-1", updated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -442,7 +447,8 @@ func TestTargetService_DeleteTarget_Success(t *testing.T) {
|
|||||||
targetRepo.AddTarget(target)
|
targetRepo.AddTarget(target)
|
||||||
|
|
||||||
// Delete it
|
// Delete it
|
||||||
err := svc.DeleteTarget("t-1")
|
ctx := context.Background()
|
||||||
|
err := svc.DeleteTarget(ctx, "t-1")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user