mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 01:18:42 +00:00
Support operation type in android cert status API (#37400)
This commit is contained in:
parent
01746ed6ab
commit
4e472b188a
11 changed files with 175 additions and 51 deletions
|
|
@ -51,9 +51,13 @@ func (ds *Datastore) ListCertificateTemplatesForHosts(ctx context.Context, hostU
|
|||
hosts.uuid AS host_uuid,
|
||||
certificate_templates.id AS certificate_template_id,
|
||||
host_certificate_templates.fleet_challenge AS fleet_challenge,
|
||||
host_certificate_templates.status AS status
|
||||
host_certificate_templates.status AS status,
|
||||
host_certificate_templates.operation_type AS operation_type,
|
||||
certificate_authorities.type AS ca_type,
|
||||
certificate_authorities.name AS ca_name
|
||||
FROM certificate_templates
|
||||
INNER JOIN hosts ON hosts.team_id = certificate_templates.team_id
|
||||
INNER JOIN certificate_authorities ON certificate_authorities.id = certificate_templates.certificate_authority_id
|
||||
LEFT JOIN host_certificate_templates
|
||||
ON host_certificate_templates.host_uuid = hosts.uuid
|
||||
AND host_certificate_templates.certificate_template_id = certificate_templates.id
|
||||
|
|
@ -81,6 +85,7 @@ func (ds *Datastore) GetCertificateTemplateForHost(ctx context.Context, hostUUID
|
|||
certificate_templates.id AS certificate_template_id,
|
||||
host_certificate_templates.fleet_challenge AS fleet_challenge,
|
||||
host_certificate_templates.status AS status,
|
||||
host_certificate_templates.operation_type AS operation_type,
|
||||
certificate_authorities.type AS ca_type,
|
||||
certificate_authorities.name AS ca_name
|
||||
FROM certificate_templates
|
||||
|
|
@ -176,23 +181,20 @@ func (ds *Datastore) UpsertCertificateStatus(
|
|||
certificateTemplateID uint,
|
||||
status fleet.MDMDeliveryStatus,
|
||||
detail *string,
|
||||
operationType fleet.MDMOperationType,
|
||||
) error {
|
||||
updateStmt := `
|
||||
UPDATE host_certificate_templates
|
||||
SET status = ?, detail = ?
|
||||
WHERE host_uuid = ? AND certificate_template_id = ?`
|
||||
|
||||
insertStmt := `
|
||||
INSERT INTO host_certificate_templates (host_uuid, certificate_template_id, status, detail, fleet_challenge, operation_type)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`
|
||||
|
||||
// Validate the status.
|
||||
if !status.IsValid() {
|
||||
return ctxerr.Wrap(ctx, fmt.Errorf("Invalid status '%s'", string(status)))
|
||||
}
|
||||
|
||||
updateStmt := `
|
||||
UPDATE host_certificate_templates
|
||||
SET status = ?, detail = ?, operation_type = ?
|
||||
WHERE host_uuid = ? AND certificate_template_id = ?`
|
||||
|
||||
// Attempt to update the certificate status for the given host and template.
|
||||
result, err := ds.writer(ctx).ExecContext(ctx, updateStmt, status, detail, hostUUID, certificateTemplateID)
|
||||
result, err := ds.writer(ctx).ExecContext(ctx, updateStmt, status, detail, operationType, hostUUID, certificateTemplateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -216,8 +218,10 @@ func (ds *Datastore) UpsertCertificateStatus(
|
|||
return ctxerr.Wrap(ctx, err, "could not read certificate template for inserting new record")
|
||||
}
|
||||
|
||||
// Default to install operation type for new records
|
||||
params := []any{hostUUID, certificateTemplateID, status, detail, "", fleet.MDMOperationTypeInstall}
|
||||
insertStmt := `
|
||||
INSERT INTO host_certificate_templates (host_uuid, certificate_template_id, status, detail, fleet_challenge, operation_type)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`
|
||||
params := []any{hostUUID, certificateTemplateID, status, detail, "", operationType}
|
||||
if _, err := ds.writer(ctx).ExecContext(ctx, insertStmt, params...); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "could not insert new host certificate template")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,6 +366,15 @@ func testUpsertHostCertificateTemplateStatus(t *testing.T, ds *Datastore) {
|
|||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a third template for testing insert with operation type
|
||||
templateThree, err := ds.CreateCertificateTemplate(ctx, &fleet.CertificateTemplate{
|
||||
Name: "Cert3",
|
||||
TeamID: setup.team.ID,
|
||||
CertificateAuthorityID: setup.ca.ID,
|
||||
SubjectName: "CN=Test Subject 3",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
hostUUID := uuid.New().String()
|
||||
_, err = ds.NewHost(ctx, &fleet.Host{
|
||||
UUID: hostUUID,
|
||||
|
|
@ -377,55 +386,82 @@ func testUpsertHostCertificateTemplateStatus(t *testing.T, ds *Datastore) {
|
|||
// Create an initial record for the first template
|
||||
ExecAdhocSQL(t, ds, func(q sqlx.ExtContext) error {
|
||||
_, err = q.ExecContext(ctx,
|
||||
"INSERT INTO host_certificate_templates (host_uuid, certificate_template_id, status, fleet_challenge) VALUES (?, ?, ?, ?)",
|
||||
hostUUID, setup.template.ID, "pending", "some_challenge_value")
|
||||
"INSERT INTO host_certificate_templates (host_uuid, certificate_template_id, status, fleet_challenge, operation_type) VALUES (?, ?, ?, ?, ?)",
|
||||
hostUUID, setup.template.ID, fleet.MDMDeliveryPending, "some_challenge_value", fleet.MDMOperationTypeInstall)
|
||||
return err
|
||||
})
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
templateID uint
|
||||
newStatus string
|
||||
expectedErrorMsg string
|
||||
detail *string
|
||||
name string
|
||||
templateID uint
|
||||
newStatus string
|
||||
expectedErrorMsg string
|
||||
detail *string
|
||||
operationType fleet.MDMOperationType
|
||||
expectedOperationType string
|
||||
}{
|
||||
{
|
||||
name: "valid update",
|
||||
templateID: setup.template.ID,
|
||||
newStatus: "verified",
|
||||
name: "valid update with install operation type",
|
||||
templateID: setup.template.ID,
|
||||
newStatus: "verified",
|
||||
operationType: fleet.MDMOperationTypeInstall,
|
||||
expectedOperationType: "install",
|
||||
},
|
||||
{
|
||||
name: "valid update with details",
|
||||
templateID: setup.template.ID,
|
||||
newStatus: "failed",
|
||||
detail: ptr.String("some details"),
|
||||
name: "valid update with details",
|
||||
templateID: setup.template.ID,
|
||||
newStatus: "failed",
|
||||
detail: ptr.String("some details"),
|
||||
operationType: fleet.MDMOperationTypeInstall,
|
||||
expectedOperationType: "install",
|
||||
},
|
||||
{
|
||||
name: "invalid status",
|
||||
templateID: setup.template.ID,
|
||||
newStatus: "invalid_status",
|
||||
operationType: fleet.MDMOperationTypeInstall,
|
||||
expectedErrorMsg: "Invalid status 'invalid_status'",
|
||||
},
|
||||
{
|
||||
name: "creates new record if does not exist",
|
||||
templateID: templateTwo.ID,
|
||||
newStatus: "verified",
|
||||
detail: ptr.String("some details"),
|
||||
name: "creates new record with install operation type",
|
||||
templateID: templateTwo.ID,
|
||||
newStatus: "verified",
|
||||
detail: ptr.String("some details"),
|
||||
operationType: fleet.MDMOperationTypeInstall,
|
||||
expectedOperationType: "install",
|
||||
},
|
||||
{
|
||||
name: "update operation type to remove",
|
||||
templateID: setup.template.ID,
|
||||
newStatus: "pending",
|
||||
operationType: fleet.MDMOperationTypeRemove,
|
||||
expectedOperationType: "remove",
|
||||
},
|
||||
{
|
||||
name: "creates new record with remove operation type",
|
||||
templateID: templateThree.ID,
|
||||
newStatus: "pending",
|
||||
operationType: fleet.MDMOperationTypeRemove,
|
||||
expectedOperationType: "remove",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := ds.UpsertCertificateStatus(ctx, hostUUID, tc.templateID, fleet.MDMDeliveryStatus(tc.newStatus), tc.detail)
|
||||
err := ds.UpsertCertificateStatus(ctx, hostUUID, tc.templateID, fleet.MDMDeliveryStatus(tc.newStatus), tc.detail, tc.operationType)
|
||||
if tc.expectedErrorMsg == "" {
|
||||
require.NoError(t, err)
|
||||
var status string
|
||||
var result struct {
|
||||
Status string `db:"status"`
|
||||
OperationType string `db:"operation_type"`
|
||||
}
|
||||
ExecAdhocSQL(t, ds, func(q sqlx.ExtContext) error {
|
||||
return sqlx.GetContext(ctx, q, &status,
|
||||
"SELECT status FROM host_certificate_templates WHERE host_uuid = ? AND certificate_template_id = ?",
|
||||
return sqlx.GetContext(ctx, q, &result,
|
||||
"SELECT status, operation_type FROM host_certificate_templates WHERE host_uuid = ? AND certificate_template_id = ?",
|
||||
hostUUID, tc.templateID)
|
||||
})
|
||||
require.Equal(t, tc.newStatus, status)
|
||||
require.Equal(t, tc.newStatus, result.Status)
|
||||
require.Equal(t, tc.expectedOperationType, result.OperationType)
|
||||
} else {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expectedErrorMsg)
|
||||
|
|
|
|||
|
|
@ -2539,7 +2539,7 @@ type Datastore interface {
|
|||
// processed together as upserts using INSERT...ON DUPLICATE KEY UPDATE.
|
||||
BatchApplyCertificateAuthorities(ctx context.Context, ops CertificateAuthoritiesBatchOperations) error
|
||||
// UpdateCertificateStatus allows a host to update the installation status of a certificate given its template.
|
||||
UpsertCertificateStatus(ctx context.Context, hostUUID string, certificateTemplateID uint, status MDMDeliveryStatus, detail *string) error
|
||||
UpsertCertificateStatus(ctx context.Context, hostUUID string, certificateTemplateID uint, status MDMDeliveryStatus, detail *string, operationType MDMOperationType) error
|
||||
|
||||
// BatchUpsertCertificateTemplates upserts a batch of certificates.
|
||||
// Returns a map of team IDs that had certificates inserted or updated.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ type CertificateTemplateForHost struct {
|
|||
CertificateTemplateID uint `db:"certificate_template_id"`
|
||||
FleetChallenge *string `db:"fleet_challenge"`
|
||||
Status *CertificateTemplateStatus `db:"status"`
|
||||
OperationType *MDMOperationType `db:"operation_type"`
|
||||
CAType CAConfigAssetType `db:"ca_type"`
|
||||
CAName string `db:"ca_name"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -529,6 +529,15 @@ const (
|
|||
MDMOperationTypeRemove MDMOperationType = "remove"
|
||||
)
|
||||
|
||||
func (o MDMOperationType) IsValid() bool {
|
||||
switch o {
|
||||
case MDMOperationTypeInstall, MDMOperationTypeRemove:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MDMConfigProfileAuthz is used to check user authorization to read/write an
|
||||
// MDM configuration profile.
|
||||
type MDMConfigProfileAuthz struct {
|
||||
|
|
|
|||
|
|
@ -648,7 +648,7 @@ type Service interface {
|
|||
DeleteCertificateTemplate(ctx context.Context, id uint) error
|
||||
ApplyCertificateTemplateSpecs(ctx context.Context, specs []*CertificateRequestSpec) error
|
||||
DeleteCertificateTemplateSpecs(ctx context.Context, certificateTemplateIDs []uint, teamID uint) error
|
||||
UpdateCertificateStatus(ctx context.Context, certificateTemplateID uint, status MDMDeliveryStatus, detail *string) error
|
||||
UpdateCertificateStatus(ctx context.Context, certificateTemplateID uint, status MDMDeliveryStatus, detail *string, operationType *string) error
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// GlobalScheduleService
|
||||
|
|
|
|||
|
|
@ -1655,7 +1655,7 @@ type UpdateCertificateAuthorityByIDFunc func(ctx context.Context, id uint, certi
|
|||
|
||||
type BatchApplyCertificateAuthoritiesFunc func(ctx context.Context, ops fleet.CertificateAuthoritiesBatchOperations) error
|
||||
|
||||
type UpsertCertificateStatusFunc func(ctx context.Context, hostUUID string, certificateTemplateID uint, status fleet.MDMDeliveryStatus, detail *string) error
|
||||
type UpsertCertificateStatusFunc func(ctx context.Context, hostUUID string, certificateTemplateID uint, status fleet.MDMDeliveryStatus, detail *string, operationType fleet.MDMOperationType) error
|
||||
|
||||
type BatchUpsertCertificateTemplatesFunc func(ctx context.Context, certificates []*fleet.CertificateTemplate) ([]uint, error)
|
||||
|
||||
|
|
@ -9929,11 +9929,11 @@ func (s *DataStore) BatchApplyCertificateAuthorities(ctx context.Context, ops fl
|
|||
return s.BatchApplyCertificateAuthoritiesFunc(ctx, ops)
|
||||
}
|
||||
|
||||
func (s *DataStore) UpsertCertificateStatus(ctx context.Context, hostUUID string, certificateTemplateID uint, status fleet.MDMDeliveryStatus, detail *string) error {
|
||||
func (s *DataStore) UpsertCertificateStatus(ctx context.Context, hostUUID string, certificateTemplateID uint, status fleet.MDMDeliveryStatus, detail *string, operationType fleet.MDMOperationType) error {
|
||||
s.mu.Lock()
|
||||
s.UpsertCertificateStatusFuncInvoked = true
|
||||
s.mu.Unlock()
|
||||
return s.UpsertCertificateStatusFunc(ctx, hostUUID, certificateTemplateID, status, detail)
|
||||
return s.UpsertCertificateStatusFunc(ctx, hostUUID, certificateTemplateID, status, detail, operationType)
|
||||
}
|
||||
|
||||
func (s *DataStore) BatchUpsertCertificateTemplates(ctx context.Context, certificates []*fleet.CertificateTemplate) ([]uint, error) {
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ type ApplyCertificateTemplateSpecsFunc func(ctx context.Context, specs []*fleet.
|
|||
|
||||
type DeleteCertificateTemplateSpecsFunc func(ctx context.Context, certificateTemplateIDs []uint, teamID uint) error
|
||||
|
||||
type UpdateCertificateStatusFunc func(ctx context.Context, certificateTemplateID uint, status fleet.MDMDeliveryStatus, detail *string) error
|
||||
type UpdateCertificateStatusFunc func(ctx context.Context, certificateTemplateID uint, status fleet.MDMDeliveryStatus, detail *string, operationType *string) error
|
||||
|
||||
type GlobalScheduleQueryFunc func(ctx context.Context, sq *fleet.ScheduledQuery) (*fleet.ScheduledQuery, error)
|
||||
|
||||
|
|
@ -3511,11 +3511,11 @@ func (s *Service) DeleteCertificateTemplateSpecs(ctx context.Context, certificat
|
|||
return s.DeleteCertificateTemplateSpecsFunc(ctx, certificateTemplateIDs, teamID)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateCertificateStatus(ctx context.Context, certificateTemplateID uint, status fleet.MDMDeliveryStatus, detail *string) error {
|
||||
func (s *Service) UpdateCertificateStatus(ctx context.Context, certificateTemplateID uint, status fleet.MDMDeliveryStatus, detail *string, operationType *string) error {
|
||||
s.mu.Lock()
|
||||
s.UpdateCertificateStatusFuncInvoked = true
|
||||
s.mu.Unlock()
|
||||
return s.UpdateCertificateStatusFunc(ctx, certificateTemplateID, status, detail)
|
||||
return s.UpdateCertificateStatusFunc(ctx, certificateTemplateID, status, detail, operationType)
|
||||
}
|
||||
|
||||
func (s *Service) GlobalScheduleQuery(ctx context.Context, sq *fleet.ScheduledQuery) (*fleet.ScheduledQuery, error) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
hostctx "github.com/fleetdm/fleet/v4/server/contexts/host"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
)
|
||||
|
||||
type createCertificateTemplateRequest struct {
|
||||
|
|
@ -204,6 +205,7 @@ func (svc *Service) GetDeviceCertificateTemplate(ctx context.Context, id uint) (
|
|||
certificate.ID,
|
||||
fleet.MDMDeliveryFailed,
|
||||
&errorMsg,
|
||||
fleet.MDMOperationTypeInstall,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -511,6 +513,8 @@ func (svc *Service) DeleteCertificateTemplateSpecs(ctx context.Context, certific
|
|||
type updateCertificateStatusRequest struct {
|
||||
CertificateTemplateID uint `url:"id"`
|
||||
Status string `json:"status"`
|
||||
// OperationType is optional and defaults to "install" if not provided.
|
||||
OperationType *string `json:"operation_type,omitempty"`
|
||||
// Detail provides additional information about the status change.
|
||||
// For example, it can be used to provide a reason for a failed status change.
|
||||
Detail *string `json:"detail,omitempty"`
|
||||
|
|
@ -528,7 +532,7 @@ func updateCertificateStatusEndpoint(ctx context.Context, request interface{}, s
|
|||
return nil, errors.New("invalid request")
|
||||
}
|
||||
|
||||
err := svc.UpdateCertificateStatus(ctx, req.CertificateTemplateID, fleet.MDMDeliveryStatus(req.Status), req.Detail)
|
||||
err := svc.UpdateCertificateStatus(ctx, req.CertificateTemplateID, fleet.MDMDeliveryStatus(req.Status), req.Detail, req.OperationType)
|
||||
if err != nil {
|
||||
return updateCertificateStatusResponse{Err: err}, nil
|
||||
}
|
||||
|
|
@ -541,6 +545,7 @@ func (svc *Service) UpdateCertificateStatus(
|
|||
certificateTemplateID uint,
|
||||
status fleet.MDMDeliveryStatus,
|
||||
detail *string,
|
||||
operationType *string,
|
||||
) error {
|
||||
// this is not a user-authenticated endpoint
|
||||
svc.authz.SkipAuthorization(ctx)
|
||||
|
|
@ -556,5 +561,30 @@ func (svc *Service) UpdateCertificateStatus(
|
|||
return fleet.NewInvalidArgumentError("status", string(status))
|
||||
}
|
||||
|
||||
return svc.ds.UpsertCertificateStatus(ctx, host.UUID, certificateTemplateID, status, detail)
|
||||
// Default operation_type to "install" if not provided.
|
||||
opType := fleet.MDMOperationTypeInstall
|
||||
if operationType != nil && *operationType != "" {
|
||||
opType = fleet.MDMOperationType(*operationType)
|
||||
}
|
||||
|
||||
if !opType.IsValid() {
|
||||
return fleet.NewInvalidArgumentError("operation_type", string(opType))
|
||||
}
|
||||
|
||||
certificate, err := svc.ds.GetCertificateTemplateForHost(ctx, host.UUID, certificateTemplateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if certificate.Status != nil && *certificate.Status != fleet.CertificateTemplateDelivered {
|
||||
level.Info(svc.logger).Log("msg", "ignoring certificate status update for non-delivered certificate", "host_uuid", host.UUID, "certificate_template_id", certificateTemplateID, "current_status", certificate.Status, "new_status", status)
|
||||
return nil
|
||||
}
|
||||
|
||||
if certificate.OperationType != nil && *certificate.OperationType != opType {
|
||||
level.Info(svc.logger).Log("msg", "ignoring certificate status update for different operation type", "host_uuid", host.UUID, "certificate_template_id", certificateTemplateID, "current_operation_type", certificate.OperationType, "new_operation_type", opType)
|
||||
return nil
|
||||
}
|
||||
|
||||
return svc.ds.UpsertCertificateStatus(ctx, host.UUID, certificateTemplateID, status, detail, opType)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -244,7 +244,8 @@ func (s *integrationMDMTestSuite) TestCertificateTemplateLifecycle() {
|
|||
// Step: Verify the status is 'verified'
|
||||
s.verifyCertificateStatus(t, host, orbitNodeKey, certificateTemplateID, certTemplateName, caID, fleet.CertificateTemplateVerified, successDetail)
|
||||
|
||||
// Step: Host updates the certificate status to 'failed' via fleetd API
|
||||
// Step: Host attempts to update the certificate status to 'failed' via fleetd API
|
||||
// This should be ignored since the current status is not 'delivered'
|
||||
failedDetail := "Certificate installation failed: invalid challenge"
|
||||
updateReq, err = json.Marshal(updateCertificateStatusRequest{
|
||||
Status: string(fleet.CertificateTemplateFailed),
|
||||
|
|
@ -257,8 +258,8 @@ func (s *integrationMDMTestSuite) TestCertificateTemplateLifecycle() {
|
|||
})
|
||||
_ = resp.Body.Close()
|
||||
|
||||
// Step: Verify the status is 'failed' with details
|
||||
s.verifyCertificateStatus(t, host, orbitNodeKey, certificateTemplateID, certTemplateName, caID, fleet.CertificateTemplateFailed, failedDetail)
|
||||
// Step: Verify the status is still 'verified' with details
|
||||
s.verifyCertificateStatus(t, host, orbitNodeKey, certificateTemplateID, certTemplateName, caID, fleet.CertificateTemplateVerified, successDetail)
|
||||
|
||||
// Delete the cert
|
||||
s.Do("DELETE", fmt.Sprintf("/api/latest/fleet/certificates/%d", certificateTemplateID), nil, http.StatusOK)
|
||||
|
|
|
|||
|
|
@ -14953,6 +14953,7 @@ INSERT INTO host_certificate_templates (
|
|||
name string
|
||||
templateID uint
|
||||
newStatus string
|
||||
newOperationType *string
|
||||
detail *string
|
||||
expectedResponseStatus int
|
||||
expectedResponseMessage string
|
||||
|
|
@ -15005,13 +15006,55 @@ INSERT INTO host_certificate_templates (
|
|||
"Authorization": fmt.Sprintf("Node key %s", orbitNodeKey),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with operation_type install",
|
||||
templateID: certificateTemplateID,
|
||||
newStatus: "verified",
|
||||
expectedResponseStatus: http.StatusOK,
|
||||
newOperationType: ptr.String("install"),
|
||||
headers: map[string]string{
|
||||
"Authorization": fmt.Sprintf("Node key %s", orbitNodeKey),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with operation_type remove",
|
||||
templateID: certificateTemplateID,
|
||||
newStatus: "verified",
|
||||
expectedResponseStatus: http.StatusOK,
|
||||
newOperationType: ptr.String("remove"),
|
||||
headers: map[string]string{
|
||||
"Authorization": fmt.Sprintf("Node key %s", orbitNodeKey),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with operation_type empty string",
|
||||
templateID: certificateTemplateID,
|
||||
newStatus: "verified",
|
||||
expectedResponseStatus: http.StatusOK,
|
||||
newOperationType: ptr.String(""),
|
||||
headers: map[string]string{
|
||||
"Authorization": fmt.Sprintf("Node key %s", orbitNodeKey),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with invalid operation_type",
|
||||
templateID: certificateTemplateID,
|
||||
newStatus: "verified",
|
||||
expectedResponseStatus: http.StatusUnprocessableEntity,
|
||||
expectedResponseMessage: "must be 'install' or 'remove'",
|
||||
newOperationType: ptr.String("invalid_operation"),
|
||||
headers: map[string]string{
|
||||
"Authorization": fmt.Sprintf("Node key %s", orbitNodeKey),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(fmt.Sprintf("TestUpdateHostCertificateTemplate:%s", tc.name), func(t *testing.T) {
|
||||
req, err := json.Marshal(updateCertificateStatusRequest{
|
||||
Status: tc.newStatus,
|
||||
Detail: tc.detail,
|
||||
Status: tc.newStatus,
|
||||
Detail: tc.detail,
|
||||
OperationType: tc.newOperationType,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue