Skip to content

Conversation

@mlimardo1984
Copy link
Contributor

@mlimardo1984 mlimardo1984 commented Jan 11, 2026

Comprehensive Summary of your change

The API call for creating Replication Rules using Swagger with filters fails with error Invalid JSON due to a type mismatch between the swagger schema definition which expects a string, and the actual implementation passing objects/arrays.

This PR is fixing the problem with type mismatch as well as providing a unit test for replication.

How has been tested

  • Environment:
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.5 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

$ go version
go version go1.25.5 linux/amd64

$ docker-compose version
Docker Compose version v5.0.1
  • Values file:
hostname: mlimardo-darling-stingray-worker-0.eastus.cloudapp.azure.com

http:
  port: 80

https:
  port: 443
  certificate: /home/azureuser/mlimardo-darling-stingray-worker-0.eastus.cloudapp.azure.com.crt
  private_key: /home/azureuser/mlimardo-darling-stingray-worker-0.eastus.cloudapp.azure.com.key

harbor_admin_password: Harbor12345

database:
  password: root123
  max_idle_conns: 100
  max_open_conns: 900
  conn_max_lifetime: 5m
  conn_max_idle_time: 0

data_volume: /data

trivy:
  ignore_unfixed: false
  skip_update: false
  skip_java_db_update: false
  offline_scan: false
  security_check: vuln
  insecure: false
  timeout: 5m0s

jobservice:
  max_job_workers: 10
  max_job_duration_hours: 24
  job_loggers:
    - STD_OUTPUT
    - FILE
  logger_sweeper_duration: 1

notification:
  webhook_job_max_retry: 3
  webhook_job_http_client_timeout: 3

log:
  level: debug
  local:
    rotate_count: 50
    rotate_size: 200M
    location: /var/log/harbor

_version: 2.14.0

proxy:
  http_proxy:
  https_proxy:
  no_proxy:
  components:
    - core
    - jobservice
    - trivy

upload_purging:
  enabled: true
  age: 168h
  interval: 24h
  dryrun: false

cache:
  enabled: false
  expire_hours: 24
  • Compile:
$ cd ~/harbor/src
$ go list ./... | grep -v -E 'tests' | xargs -L1 fgt golint
go: downloading github.com/jackc/pgx/v4 v4.18.3
go: downloading github.com/prometheus/client_golang v1.22.0
[..]
/home/azureuser/harbor/src/testing/lib/orm/orm.go:350:1: exported method FakeRawSeter.RowsToMap should have comment or be unexported
/home/azureuser/harbor/src/testing/lib/orm/orm.go:354:1: exported method FakeRawSeter.RowsToStruct should have comment or be unexported
/home/azureuser/harbor/src/testing/lib/orm/orm.go:358:1: exported method FakeRawSeter.Prepare should have comment or be unexported

$ sudo make gen_apis
generate all the files for API from api/v2.0/swagger.yaml
2026/01/11 08:48:09 validating spec /home/azureuser/harbor/api/v2.0/swagger.yaml
2026/01/11 08:48:12 preprocessing spec with option:  minimal flattening
2026/01/11 08:48:12 building a plan for generation
2026/01/11 08:48:12 generation target src/server/v2.0
[..]
2026/01/11 08:48:22 executed template asset:serverConfigureapi
2026/01/11 08:48:22 Generation completed!


$ sudo make install

Note: golang version: 1.25.5

Note: docker version: 25.0.7

Note: docker-compose version: 5.0.1
[..]
loading harbor images...
WARN[0000] No services to build
[+] up 10/10
 ✔ Network make_harbor         Created                                                                                                                                                                                                    0.1s
 ✔ Container harbor-log        Created                                                                                                                                                                                                    0.5s
 ✔ Container registryctl       Created                                                                                                                                                                                                    0.6s
 ✔ Container redis             Created                                                                                                                                                                                                    0.7s
 ✔ Container harbor-db         Created                                                                                                                                                                                                    0.6s
 ✔ Container registry          Created                                                                                                                                                                                                    0.7s
 ✔ Container harbor-portal     Created                                                                                                                                                                                                    0.8s
 ✔ Container harbor-core       Created                                                                                                                                                                                                    0.5s
 ✔ Container nginx             Created                                                                                                                                                                                                    0.3s
 ✔ Container harbor-jobservice Created                                                                                                                                                                                                    0.2s
Start complete. You can visit harbor now.
  • Verify fix:
    JSON content:
{
  "id": 4,
  "name": "test api",
  "description": "test api",
  "src_registry": {
    "id": 1,
    "url": "https://hub.docker.com",
    "name": "Docker Hub",
    "credential": {
      "type": "basic",
      "access_key": "mlimardo",
      "access_secret": "XXXX"
    },
    "type": "docker-hub",
    "insecure": true,
    "description": "test api"
  },
  "dest_registry": {
    "url": "http://msr4-harbor-core:80",
    "name": "Local",
    "credential": {
      "type": "secret",
      "access_secret": "XXXX"
    },
    "type": "harbor",
    "insecure": true,
    "description": "test api"
  },
  "trigger": {
    "type": "manual"
  },
  "filters": [
    {
      "type": "name",
      "value": "library/alpine"
    },
    {
      "decoration": "matches",
      "type": "tag",
      "value": "*latest*"
    }
  ],
  "replicate_deletion": true,
  "deletion": true,
  "override": true,
  "enabled": true,
  "speed": 0,
  "copy_by_chunk": true
}

Swagger/UI:

Screenshot 2026-01-11 at 10 30 19 Screenshot 2026-01-11 at 10 29 24 Screenshot 2026-01-11 at 10 29 34 Screenshot 2026-01-11 at 10 29 44 Screenshot 2026-01-11 at 10 29 51
  • Verify filter with label works as expected:
Screenshot 2026-01-16 at 11 22 27 Screenshot 2026-01-16 at 11 22 18 Screenshot 2026-01-16 at 11 21 57 Screenshot 2026-01-16 at 11 21 51
  • Unit test:
$ cd harbor/src/server/v2.0/handler
$ go test -v
init global config instance failed. If you do not use this, just ignore it.  open conf/app.conf: no such file or directory
2026-01-16T11:23:40Z [INFO] [/controller/artifact/annotation/parser.go:85]: the annotation parser to parser artifact annotation version v1alpha1 registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.cncf.helm.config.v1+json registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.cnab.manifest.v1 registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.cnai.model.manifest.v1+json registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.oci.image.index.v1+json registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.docker.distribution.manifest.list.v2+json registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.docker.distribution.manifest.v1+prettyjws registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.oci.image.config.v1+json registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.docker.container.image.v1+json registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.goharbor.harbor.sbom.v1 registered
2026-01-16T11:23:40Z [INFO] [/controller/artifact/processor/processor.go:59]: the processor to process media type application/vnd.wasm.config.v1+json registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/native/adapter.go:36]: the factory for adapter docker-registry registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/aliacr/adapter.go:54]: the factory for adapter ali-acr registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/awsecr/adapter.go:44]: the factory for adapter aws-ecr registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/azurecr/adapter.go:29]: Factory for adapter azure-acr registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/dockerhub/adapter.go:40]: Factory for adapter docker-hub registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/dtr/adapter.go:36]: the factory of dtr adapter was registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/githubcr/adapter.go:43]: the factory for adapter github-ghcr registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/gitlab/adapter.go:33]: the factory for adapter gitlab registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/googlegcr/adapter.go:38]: the factory for adapter google-gcr registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/huawei/huawei_adapter.go:40]: the factory of Huawei adapter was registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/jfrog/adapter.go:42]: the factory of jfrog artifactory adapter was registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/quay/adapter.go:53]: the factory of Quay adapter was registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/tencentcr/adapter.go:58]: the factory for adapter tencent-tcr registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/volcenginecr/adapter.go:40]: the factory for adapter volcengine-cr registered
2026-01-16T11:23:40Z [INFO] [/pkg/reg/adapter/harbor/adaper.go:31]: the factory for adapter harbor registered
=== RUN   TestParse
--- PASS: TestParse (0.00s)
=== RUN   TestArtifactTestSuite
=== RUN   TestArtifactTestSuite/TestGetVulnerabilitiesAddition
--- PASS: TestArtifactTestSuite (0.74s)
    --- PASS: TestArtifactTestSuite/TestGetVulnerabilitiesAddition (0.04s)
=== RUN   TestBaseHandler
=== RUN   TestBaseHandler/TestBuildQuery
=== RUN   TestBaseHandler/TestLinks
--- PASS: TestBaseHandler (0.00s)
    --- PASS: TestBaseHandler/TestBuildQuery (0.00s)
    --- PASS: TestBaseHandler/TestLinks (0.00s)
=== RUN   TestValidateWorkers
--- PASS: TestValidateWorkers (0.00s)
=== RUN   Test_convertProvidersToFrontend
=== RUN   Test_convertProvidersToFrontend/#00
--- PASS: Test_convertProvidersToFrontend (0.00s)
    --- PASS: Test_convertProvidersToFrontend/#00 (0.00s)
=== RUN   Test_convertPolicyToPayload
=== RUN   Test_convertPolicyToPayload/should_error
=== RUN   Test_convertPolicyToPayload/should_success
--- PASS: Test_convertPolicyToPayload (0.00s)
    --- PASS: Test_convertPolicyToPayload/should_error (0.00s)
    --- PASS: Test_convertPolicyToPayload/should_success (0.00s)
=== RUN   Test_convertParamPolicyToModelPolicy
=== RUN   Test_convertParamPolicyToModelPolicy/should_err
=== RUN   Test_convertParamPolicyToModelPolicy/invalid_name
=== RUN   Test_convertParamPolicyToModelPolicy/should_success
--- PASS: Test_convertParamPolicyToModelPolicy (0.00s)
    --- PASS: Test_convertParamPolicyToModelPolicy/should_err (0.00s)
    --- PASS: Test_convertParamPolicyToModelPolicy/invalid_name (0.00s)
    --- PASS: Test_convertParamPolicyToModelPolicy/should_success (0.00s)
=== RUN   Test_convertInstanceToPayload
=== RUN   Test_convertInstanceToPayload/want_err
=== RUN   Test_convertInstanceToPayload/invalid_authData
=== RUN   Test_convertInstanceToPayload/want_ok
--- PASS: Test_convertInstanceToPayload (0.00s)
    --- PASS: Test_convertInstanceToPayload/want_err (0.00s)
    --- PASS: Test_convertInstanceToPayload/invalid_authData (0.00s)
    --- PASS: Test_convertInstanceToPayload/want_ok (0.00s)
=== RUN   Test_convertParamInstanceToModelInstance
=== RUN   Test_convertParamInstanceToModelInstance/want_err
=== RUN   Test_convertParamInstanceToModelInstance/invalid_name
=== RUN   Test_convertParamInstanceToModelInstance/want_ok
--- PASS: Test_convertParamInstanceToModelInstance (0.00s)
    --- PASS: Test_convertParamInstanceToModelInstance/want_err (0.00s)
    --- PASS: Test_convertParamInstanceToModelInstance/invalid_name (0.00s)
    --- PASS: Test_convertParamInstanceToModelInstance/want_ok (0.00s)
=== RUN   Test_convertExecutionToPayload
=== RUN   Test_convertExecutionToPayload/nil_model
=== RUN   Test_convertExecutionToPayload/should_ok
--- PASS: Test_convertExecutionToPayload (0.00s)
    --- PASS: Test_convertExecutionToPayload/nil_model (0.00s)
    --- PASS: Test_convertExecutionToPayload/should_ok (0.00s)
=== RUN   Test_convertTaskToPayload
=== RUN   Test_convertTaskToPayload/nil_model
=== RUN   Test_convertTaskToPayload/should_ok
--- PASS: Test_convertTaskToPayload (0.00s)
    --- PASS: Test_convertTaskToPayload/nil_model (0.00s)
    --- PASS: Test_convertTaskToPayload/should_ok (0.00s)
=== RUN   TestValidate
=== RUN   TestValidate/Invalid_max_upstream_conn_value
=== RUN   TestValidate/max_upstream_conn_value_0
=== RUN   TestValidate/max_upstream_conn_value_-1
=== RUN   TestValidate/normal_max_upstream_conn_value
=== RUN   TestValidate/Unsupported_key
=== RUN   TestValidate/Empty_map
--- PASS: TestValidate (0.00s)
    --- PASS: TestValidate/Invalid_max_upstream_conn_value (0.00s)
    --- PASS: TestValidate/max_upstream_conn_value_0 (0.00s)
    --- PASS: TestValidate/max_upstream_conn_value_-1 (0.00s)
    --- PASS: TestValidate/normal_max_upstream_conn_value (0.00s)
    --- PASS: TestValidate/Unsupported_key (0.00s)
    --- PASS: TestValidate/Empty_map (0.00s)
=== RUN   TestProjectTestSuite
=== RUN   TestProjectTestSuite/TestGetScannerOfProject
2026-01-16T11:23:42Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to get project"}]}
=== RUN   TestProjectTestSuite/TestListScannerCandidatesOfProject
2026-01-16T11:23:42Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to count scanners"}]}
2026-01-16T11:23:42Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to list scanners"}]}
=== RUN   TestProjectTestSuite/TestSetScannerOfProject
2026-01-16T11:23:42Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to get project"}]}
--- PASS: TestProjectTestSuite (0.85s)
    --- PASS: TestProjectTestSuite/TestGetScannerOfProject (0.01s)
    --- PASS: TestProjectTestSuite/TestListScannerCandidatesOfProject (0.00s)
    --- PASS: TestProjectTestSuite/TestSetScannerOfProject (0.01s)
=== RUN   Test_verifyUpdateRequest
=== RUN   Test_verifyUpdateRequest/normal
=== RUN   Test_verifyUpdateRequest/missing_schedule
=== RUN   Test_verifyUpdateRequest/missing_retention_hour
=== RUN   Test_verifyUpdateRequest/missing_operations
--- PASS: Test_verifyUpdateRequest (0.00s)
    --- PASS: Test_verifyUpdateRequest/normal (0.00s)
    --- PASS: Test_verifyUpdateRequest/missing_schedule (0.00s)
    --- PASS: Test_verifyUpdateRequest/missing_retention_hour (0.00s)
    --- PASS: Test_verifyUpdateRequest/missing_operations (0.00s)
=== RUN   Test_verifyCreateRequest
=== RUN   Test_verifyCreateRequest/normal
=== RUN   Test_verifyCreateRequest/missing_schedule
=== RUN   Test_verifyCreateRequest/missing_retention_hour
=== RUN   Test_verifyCreateRequest/missing_event_types
--- PASS: Test_verifyCreateRequest (0.00s)
    --- PASS: Test_verifyCreateRequest/normal (0.00s)
    --- PASS: Test_verifyCreateRequest/missing_schedule (0.00s)
    --- PASS: Test_verifyCreateRequest/missing_retention_hour (0.00s)
    --- PASS: Test_verifyCreateRequest/missing_event_types (0.00s)
=== RUN   Test_checkRetentionHour
=== RUN   Test_checkRetentionHour/normal
=== RUN   Test_checkRetentionHour/overflow
=== RUN   Test_checkRetentionHour/equal
=== RUN   Test_checkRetentionHour/wrong_type
--- PASS: Test_checkRetentionHour (0.00s)
    --- PASS: Test_checkRetentionHour/normal (0.00s)
    --- PASS: Test_checkRetentionHour/overflow (0.00s)
    --- PASS: Test_checkRetentionHour/equal (0.00s)
    --- PASS: Test_checkRetentionHour/wrong_type (0.00s)
=== RUN   TestQuotaTestSuite
=== RUN   TestQuotaTestSuite/TestAuthorization
=== RUN   TestQuotaTestSuite/TestGetQuota
2026-01-16T11:23:42Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to get quota"}]}
=== RUN   TestQuotaTestSuite/TestListQuotas
2026-01-16T11:23:42Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to count quotas"}]}
2026-01-16T11:23:42Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to list quotas"}]}
=== RUN   TestQuotaTestSuite/TestUpdateQuota
2026-01-16T11:23:42Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to update the quota"}]}
--- PASS: TestQuotaTestSuite (0.85s)
    --- PASS: TestQuotaTestSuite/TestAuthorization (0.03s)
    --- PASS: TestQuotaTestSuite/TestGetQuota (0.01s)
    --- PASS: TestQuotaTestSuite/TestListQuotas (0.02s)
    --- PASS: TestQuotaTestSuite/TestUpdateQuota (0.01s)
=== RUN   TestConvertReplicationPolicy
=== RUN   TestConvertReplicationPolicy/policy_with_string_filter_values
=== RUN   TestConvertReplicationPolicy/policy_with_empty_filters
=== RUN   TestConvertReplicationPolicy/policy_with_nil_registries_and_trigger
--- PASS: TestConvertReplicationPolicy (0.00s)
    --- PASS: TestConvertReplicationPolicy/policy_with_string_filter_values (0.00s)
    --- PASS: TestConvertReplicationPolicy/policy_with_empty_filters (0.00s)
    --- PASS: TestConvertReplicationPolicy/policy_with_nil_registries_and_trigger (0.00s)
=== RUN   TestConvertReplicationPolicyFilterTypeAssertion
--- PASS: TestConvertReplicationPolicyFilterTypeAssertion (0.00s)
=== RUN   TestConvertExecution
--- PASS: TestConvertExecution (0.00s)
=== RUN   TestConvertTask
--- PASS: TestConvertTask (0.00s)
=== RUN   TestConvertFilterValue
--- PASS: TestConvertFilterValue (0.00s)
=== RUN   TestValidLevel
=== RUN   TestValidLevel/project_level_true
=== RUN   TestValidLevel/system_level_true
=== RUN   TestValidLevel/unknown_level_false
=== RUN   TestValidLevel/systemproject_level_false
--- PASS: TestValidLevel (0.00s)
    --- PASS: TestValidLevel/project_level_true (0.00s)
    --- PASS: TestValidLevel/system_level_true (0.00s)
    --- PASS: TestValidLevel/unknown_level_false (0.00s)
    --- PASS: TestValidLevel/systemproject_level_false (0.00s)
=== RUN   TestValidDuration
=== RUN   TestValidDuration/duration_0
=== RUN   TestValidDuration/duration_1
=== RUN   TestValidDuration/duration_-1
=== RUN   TestValidDuration/duration_-10
=== RUN   TestValidDuration/duration_9999
=== RUN   TestValidDuration/duration_max
=== RUN   TestValidDuration/duration_max#01
=== RUN   TestValidDuration/duration_999999999999
--- PASS: TestValidDuration (0.00s)
    --- PASS: TestValidDuration/duration_0 (0.00s)
    --- PASS: TestValidDuration/duration_1 (0.00s)
    --- PASS: TestValidDuration/duration_-1 (0.00s)
    --- PASS: TestValidDuration/duration_-10 (0.00s)
    --- PASS: TestValidDuration/duration_9999 (0.00s)
    --- PASS: TestValidDuration/duration_max (0.00s)
    --- PASS: TestValidDuration/duration_max#01 (0.00s)
    --- PASS: TestValidDuration/duration_999999999999 (0.00s)
=== RUN   TestValidateName
=== RUN   TestValidateName/rname_robotname
=== RUN   TestValidateName/rname_123456
=== RUN   TestValidateName/rname_robot123
=== RUN   TestValidateName/rname_ROBOT
=== RUN   TestValidateName/rname_robot+123
=== RUN   TestValidateName/rname_robot$123
=== RUN   TestValidateName/rname_robot_test123
--- PASS: TestValidateName (0.00s)
    --- PASS: TestValidateName/rname_robotname (0.00s)
    --- PASS: TestValidateName/rname_123456 (0.00s)
    --- PASS: TestValidateName/rname_robot123 (0.00s)
    --- PASS: TestValidateName/rname_ROBOT (0.00s)
    --- PASS: TestValidateName/rname_robot+123 (0.00s)
    --- PASS: TestValidateName/rname_robot$123 (0.00s)
    --- PASS: TestValidateName/rname_robot_test123 (0.00s)
=== RUN   TestContainsAccess
=== RUN   TestContainsAccess/System_ResourceRegistry_push
=== RUN   TestContainsAccess/System_ResourceProject_delete
=== RUN   TestContainsAccess/System_ResourceReplicationPolicy_delete
=== RUN   TestContainsAccess/Project_ResourceLog_delete
=== RUN   TestContainsAccess/Project_ResourceMetadata_read
=== RUN   TestContainsAccess/Project_ResourceRobot_create
--- PASS: TestContainsAccess (0.00s)
    --- PASS: TestContainsAccess/System_ResourceRegistry_push (0.00s)
    --- PASS: TestContainsAccess/System_ResourceProject_delete (0.00s)
    --- PASS: TestContainsAccess/System_ResourceReplicationPolicy_delete (0.00s)
    --- PASS: TestContainsAccess/Project_ResourceLog_delete (0.00s)
    --- PASS: TestContainsAccess/Project_ResourceMetadata_read (0.00s)
    --- PASS: TestContainsAccess/Project_ResourceRobot_create (0.00s)
=== RUN   TestValidPermissionScope
=== RUN   TestValidPermissionScope/Project_-_subset
=== RUN   TestValidPermissionScope/Project_-_not_Subset
=== RUN   TestValidPermissionScope/Project_-_equal
=== RUN   TestValidPermissionScope/Project_-_different
=== RUN   TestValidPermissionScope/Project_-_empty_creator
=== RUN   TestValidPermissionScope/Project_-_empty_creating
=== RUN   TestValidPermissionScope/System_-_subset
=== RUN   TestValidPermissionScope/System_-_not_subset
=== RUN   TestValidPermissionScope/System_-_subset_project
=== RUN   TestValidPermissionScope/System_-_cover_all
=== RUN   TestValidPermissionScope/System_-_cover_all_2
--- PASS: TestValidPermissionScope (0.00s)
    --- PASS: TestValidPermissionScope/Project_-_subset (0.00s)
    --- PASS: TestValidPermissionScope/Project_-_not_Subset (0.00s)
    --- PASS: TestValidPermissionScope/Project_-_equal (0.00s)
    --- PASS: TestValidPermissionScope/Project_-_different (0.00s)
    --- PASS: TestValidPermissionScope/Project_-_empty_creator (0.00s)
    --- PASS: TestValidPermissionScope/Project_-_empty_creating (0.00s)
    --- PASS: TestValidPermissionScope/System_-_subset (0.00s)
    --- PASS: TestValidPermissionScope/System_-_not_subset (0.00s)
    --- PASS: TestValidPermissionScope/System_-_subset_project (0.00s)
    --- PASS: TestValidPermissionScope/System_-_cover_all (0.00s)
    --- PASS: TestValidPermissionScope/System_-_cover_all_2 (0.00s)
=== RUN   TestScanAllTestSuite
=== RUN   TestScanAllTestSuite/TestAuthorization
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"check if scan is enabled: failed"}]}
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:301, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireScanEnabled
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:315, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireAccess
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:173, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).GetLatestScanAllMetrics
/home/azureuser/harbor/src/server/v2.0/restapi/configure_harbor.go:2261, github.com/goharbor/harbor/src/server/v2.0/restapi.HandlerAPI.func93
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/get_latest_scan_all_metrics.go:19, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.GetLatestScanAllMetricsHandlerFunc.Handle
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/get_latest_scan_all_metrics.go:68, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.(*GetLatestScanAllMetrics).ServeHTTP
/home/azureuser/harbor/src/server/v2.0/restapi/operations/harbor_api.go:1971, github.com/goharbor/harbor/src/server/v2.0/restapi/operations.(*HarborAPI).initHandlerCache.(*HarborAPI).handler.func91
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/operation.go:17, github.com/go-openapi/runtime/middleware.(*Context).RoutesHandler.NewOperationExecutor.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/router.go:67, github.com/go-openapi/runtime/middleware.NewRouter.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/ui_options.go:167, github.com/go-openapi/runtime/middleware.Redoc.serveUI.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/spec.go:61, github.com/go-openapi/runtime/middleware.Spec.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/harbor/src/testing/server/v2.0/handler/handler.go:53, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.func2
/home/azureuser/harbor/src/server/middleware/middleware.go:57, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.(*Suite).SetupSuite.New.func3.func4
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/usr/local/go/src/net/http/server.go:3340, net/http.serverHandler.ServeHTTP
/usr/local/go/src/net/http/server.go:2109, net/http.(*conn).serve
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"check if scan is enabled: failed"}]}
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:301, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireScanEnabled
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:315, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireAccess
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:185, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).GetLatestScheduledScanAllMetrics
/home/azureuser/harbor/src/server/v2.0/restapi/configure_harbor.go:2274, github.com/goharbor/harbor/src/server/v2.0/restapi.HandlerAPI.func94
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/get_latest_scheduled_scan_all_metrics.go:19, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.GetLatestScheduledScanAllMetricsHandlerFunc.Handle
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/get_latest_scheduled_scan_all_metrics.go:68, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.(*GetLatestScheduledScanAllMetrics).ServeHTTP
/home/azureuser/harbor/src/server/v2.0/restapi/operations/harbor_api.go:1971, github.com/goharbor/harbor/src/server/v2.0/restapi/operations.(*HarborAPI).initHandlerCache.(*HarborAPI).handler.func92
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/operation.go:17, github.com/go-openapi/runtime/middleware.(*Context).RoutesHandler.NewOperationExecutor.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/router.go:67, github.com/go-openapi/runtime/middleware.NewRouter.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/ui_options.go:167, github.com/go-openapi/runtime/middleware.Redoc.serveUI.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/spec.go:61, github.com/go-openapi/runtime/middleware.Spec.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/harbor/src/testing/server/v2.0/handler/handler.go:53, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.func2
/home/azureuser/harbor/src/server/middleware/middleware.go:57, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.(*Suite).SetupSuite.New.func3.func4
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/usr/local/go/src/net/http/server.go:3340, net/http.serverHandler.ServeHTTP
/usr/local/go/src/net/http/server.go:2109, net/http.(*conn).serve
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"check if scan is enabled: failed"}]}
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:301, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireScanEnabled
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:315, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireAccess
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:161, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).GetScanAllSchedule
/home/azureuser/harbor/src/server/v2.0/restapi/configure_harbor.go:2599, github.com/goharbor/harbor/src/server/v2.0/restapi.HandlerAPI.func119
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/get_scan_all_schedule.go:19, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.GetScanAllScheduleHandlerFunc.Handle
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/get_scan_all_schedule.go:68, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.(*GetScanAllSchedule).ServeHTTP
/home/azureuser/harbor/src/server/v2.0/restapi/operations/harbor_api.go:1971, github.com/goharbor/harbor/src/server/v2.0/restapi/operations.(*HarborAPI).initHandlerCache.(*HarborAPI).handler.func117
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/operation.go:17, github.com/go-openapi/runtime/middleware.(*Context).RoutesHandler.NewOperationExecutor.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/router.go:67, github.com/go-openapi/runtime/middleware.NewRouter.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/ui_options.go:167, github.com/go-openapi/runtime/middleware.Redoc.serveUI.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/spec.go:61, github.com/go-openapi/runtime/middleware.Spec.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/harbor/src/testing/server/v2.0/handler/handler.go:53, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.func2
/home/azureuser/harbor/src/server/middleware/middleware.go:57, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.(*Suite).SetupSuite.New.func3.func4
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/usr/local/go/src/net/http/server.go:3340, net/http.serverHandler.ServeHTTP
/usr/local/go/src/net/http/server.go:2109, net/http.(*conn).serve
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"check if scan is enabled: failed"}]}
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:301, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireScanEnabled
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:315, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireAccess
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:131, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).UpdateScanAllSchedule
/home/azureuser/harbor/src/server/v2.0/restapi/configure_harbor.go:3665, github.com/goharbor/harbor/src/server/v2.0/restapi.HandlerAPI.func201
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/update_scan_all_schedule.go:19, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.UpdateScanAllScheduleHandlerFunc.Handle
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/update_scan_all_schedule.go:68, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.(*UpdateScanAllSchedule).ServeHTTP
/home/azureuser/harbor/src/server/v2.0/restapi/operations/harbor_api.go:1971, github.com/goharbor/harbor/src/server/v2.0/restapi/operations.(*HarborAPI).initHandlerCache.(*HarborAPI).handler.func199
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/operation.go:17, github.com/go-openapi/runtime/middleware.(*Context).RoutesHandler.NewOperationExecutor.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/router.go:67, github.com/go-openapi/runtime/middleware.NewRouter.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/ui_options.go:167, github.com/go-openapi/runtime/middleware.Redoc.serveUI.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/spec.go:61, github.com/go-openapi/runtime/middleware.Spec.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/harbor/src/testing/server/v2.0/handler/handler.go:53, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.func2
/home/azureuser/harbor/src/server/middleware/middleware.go:57, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.(*Suite).SetupSuite.New.func3.func4
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/usr/local/go/src/net/http/server.go:3340, net/http.serverHandler.ServeHTTP
/usr/local/go/src/net/http/server.go:2109, net/http.(*conn).serve
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"check if scan is enabled: failed"}]}
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:301, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireScanEnabled
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:315, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).requireAccess
/home/azureuser/harbor/src/server/v2.0/handler/scan_all.go:87, github.com/goharbor/harbor/src/server/v2.0/handler.(*scanAllAPI).CreateScanAllSchedule
/home/azureuser/harbor/src/server/v2.0/restapi/configure_harbor.go:1845, github.com/goharbor/harbor/src/server/v2.0/restapi.HandlerAPI.func61
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/create_scan_all_schedule.go:19, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.CreateScanAllScheduleHandlerFunc.Handle
/home/azureuser/harbor/src/server/v2.0/restapi/operations/scan_all/create_scan_all_schedule.go:68, github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_all.(*CreateScanAllSchedule).ServeHTTP
/home/azureuser/harbor/src/server/v2.0/restapi/operations/harbor_api.go:1971, github.com/goharbor/harbor/src/server/v2.0/restapi/operations.(*HarborAPI).initHandlerCache.(*HarborAPI).handler.func59
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/operation.go:17, github.com/go-openapi/runtime/middleware.(*Context).RoutesHandler.NewOperationExecutor.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/router.go:67, github.com/go-openapi/runtime/middleware.NewRouter.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/ui_options.go:167, github.com/go-openapi/runtime/middleware.Redoc.serveUI.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/go/pkg/mod/github.com/go-openapi/runtime@v0.29.2/middleware/spec.go:61, github.com/go-openapi/runtime/middleware.Spec.func1
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/home/azureuser/harbor/src/testing/server/v2.0/handler/handler.go:53, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.func2
/home/azureuser/harbor/src/server/middleware/middleware.go:57, github.com/goharbor/harbor/src/testing/server/v2.0/handler.(*Suite).SetupSuite.(*Suite).SetupSuite.New.func3.func4
/usr/local/go/src/net/http/server.go:2322, net/http.HandlerFunc.ServeHTTP
/usr/local/go/src/net/http/server.go:3340, net/http.serverHandler.ServeHTTP
/usr/local/go/src/net/http/server.go:2109, net/http.(*conn).serve
=== RUN   TestScanAllTestSuite/TestCreateScanAllSchedule
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: list executions failed"}]}
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: scan all failed"}]}
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: get schedule failed"}]}
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: create schedule failed"}]}
=== RUN   TestScanAllTestSuite/TestGetLatestScanAllMetrics
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to list executions"}]}
=== RUN   TestScanAllTestSuite/TestGetLatestScheduledScanAllMetrics
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to list executions"}]}
=== RUN   TestScanAllTestSuite/TestGetScanAllSchedule
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: get schedule failed"}]}
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: found more than one scheduled scan all job, please ensure that only one schedule left"}]}
=== RUN   TestScanAllTestSuite/TestStopScanAll
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: list executions failed"}]}
=== RUN   TestScanAllTestSuite/TestUpdateScanAllSchedule
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: get schedule failed"}]}
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: unschedule failed"}]}
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: unschedule failed"}]}
2026-01-16T11:23:43Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: create schedule failed"}]}
--- PASS: TestScanAllTestSuite (0.80s)
    --- PASS: TestScanAllTestSuite/TestAuthorization (0.03s)
    --- PASS: TestScanAllTestSuite/TestCreateScanAllSchedule (0.01s)
    --- PASS: TestScanAllTestSuite/TestGetLatestScanAllMetrics (0.01s)
    --- PASS: TestScanAllTestSuite/TestGetLatestScheduledScanAllMetrics (0.00s)
    --- PASS: TestScanAllTestSuite/TestGetScanAllSchedule (0.01s)
    --- PASS: TestScanAllTestSuite/TestStopScanAll (0.01s)
    --- PASS: TestScanAllTestSuite/TestUpdateScanAllSchedule (0.02s)
=== RUN   TestScanTestSuite
=== RUN   TestScanTestSuite/TestStopScan
2026-01-16T11:23:44Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to get artifact by reference"}]}
2026-01-16T11:23:44Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: nil artifact to stop scan"}]}
--- PASS: TestScanTestSuite (0.76s)
    --- PASS: TestScanTestSuite/TestStopScan (0.01s)
=== RUN   TestScanExportTestSuite
=== RUN   TestScanExportTestSuite/TestAuthorization
=== RUN   TestScanExportTestSuite/TestDownloadScanData
2026-01-16T11:23:45Z [INFO] [/server/v2.0/handler/scanexport.go:196]: reading data from file : scandata_export_100
2026-01-16T11:23:45Z [INFO] [/server/v2.0/handler/scanexport.go:282]: Deleting report artifact : scandata_export_100:datadigest
2026-01-16T11:23:45Z [ERROR] [/server/v2.0/handler/scanexport.go:302]: Error deleting system artifact record for scan_data_export/scandata_export_100/datadigest: cannot get the ORM from context
=== RUN   TestScanExportTestSuite/TestDownloadScanDataExecutionError
2026-01-16T11:23:46Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"test error"}]}
/home/azureuser/harbor/src/server/v2.0/handler/scanexport_test.go:564, github.com/goharbor/harbor/src/server/v2.0/handler.(*ScanExportTestSuite).TestDownloadScanDataExecutionError
/usr/local/go/src/reflect/value.go:581, reflect.Value.call
/usr/local/go/src/reflect/value.go:365, reflect.Value.Call
/home/azureuser/go/pkg/mod/github.com/stretchr/testify@v1.11.1/suite/suite.go:196, github.com/stretchr/testify/suite.Run.func1
/usr/local/go/src/testing/testing.go:1934, testing.tRunner
=== RUN   TestScanExportTestSuite/TestDownloadScanDataExecutionNotPresent
=== RUN   TestScanExportTestSuite/TestDownloadScanDataNoCsvFilePresent
=== RUN   TestScanExportTestSuite/TestDownloadScanDataUserNotOwnerofExport
=== RUN   TestScanExportTestSuite/TestExportScanData
=== RUN   TestScanExportTestSuite/TestExportScanDataGetUserIdError
2026-01-16T11:23:50Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"test error"}]}
/home/azureuser/harbor/src/server/v2.0/handler/scanexport_test.go:262, github.com/goharbor/harbor/src/server/v2.0/handler.(*ScanExportTestSuite).TestExportScanDataGetUserIdError
/usr/local/go/src/reflect/value.go:581, reflect.Value.call
/usr/local/go/src/reflect/value.go:365, reflect.Value.Call
/home/azureuser/go/pkg/mod/github.com/stretchr/testify@v1.11.1/suite/suite.go:196, github.com/stretchr/testify/suite.Run.func1
/usr/local/go/src/testing/testing.go:1934, testing.tRunner
=== RUN   TestScanExportTestSuite/TestExportScanDataGetUserIdNotFound
=== RUN   TestScanExportTestSuite/TestExportScanDataNoPrivileges
=== RUN   TestScanExportTestSuite/TestGetScanDataExportExecution
=== RUN   TestScanExportTestSuite/TestGetScanDataExportExecutionList
URL string :  /export/cve/executions?user_name=test-user
=== RUN   TestScanExportTestSuite/TestGetScanDataExportExecutionListFilterNotOwned
URL string :  /export/cve/executions?user_name=test-user
=== RUN   TestScanExportTestSuite/TestGetScanDataExportExecutionUserNotOwnerOfExport
=== RUN   TestScanExportTestSuite/TestValidateScanExportParams
--- PASS: TestScanExportTestSuite (11.15s)
    --- PASS: TestScanExportTestSuite/TestAuthorization (0.66s)
    --- PASS: TestScanExportTestSuite/TestDownloadScanData (0.63s)
    --- PASS: TestScanExportTestSuite/TestDownloadScanDataExecutionError (0.94s)
    --- PASS: TestScanExportTestSuite/TestDownloadScanDataExecutionNotPresent (0.89s)
    --- PASS: TestScanExportTestSuite/TestDownloadScanDataNoCsvFilePresent (0.79s)
    --- PASS: TestScanExportTestSuite/TestDownloadScanDataUserNotOwnerofExport (0.73s)
    --- PASS: TestScanExportTestSuite/TestExportScanData (0.79s)
    --- PASS: TestScanExportTestSuite/TestExportScanDataGetUserIdError (0.85s)
    --- PASS: TestScanExportTestSuite/TestExportScanDataGetUserIdNotFound (0.80s)
    --- PASS: TestScanExportTestSuite/TestExportScanDataNoPrivileges (0.52s)
    --- PASS: TestScanExportTestSuite/TestGetScanDataExportExecution (0.90s)
    --- PASS: TestScanExportTestSuite/TestGetScanDataExportExecutionList (0.93s)
    --- PASS: TestScanExportTestSuite/TestGetScanDataExportExecutionListFilterNotOwned (0.49s)
    --- PASS: TestScanExportTestSuite/TestGetScanDataExportExecutionUserNotOwnerOfExport (0.79s)
    --- PASS: TestScanExportTestSuite/TestValidateScanExportParams (0.44s)
=== RUN   TestScannerTestSuite
=== RUN   TestScannerTestSuite/TestAuthorization
=== RUN   TestScannerTestSuite/TestCreateScanner
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to create registration"}]}
=== RUN   TestScannerTestSuite/TestCreateScannerWithInvalidBody
=== RUN   TestScannerTestSuite/TestDeleteScanner
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to get registration"}]}
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to delete registration"}]}
=== RUN   TestScannerTestSuite/TestGetScanner
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to get registration"}]}
=== RUN   TestScannerTestSuite/TestGetScannerMetadata
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to get metadata"}]}
=== RUN   TestScannerTestSuite/TestListScanners
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to count scanners"}]}
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to list scanners"}]}
=== RUN   TestScannerTestSuite/TestPingScanner
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to ping scanner"}]}
=== RUN   TestScannerTestSuite/TestSetScannerAsDefault
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to set default"}]}
=== RUN   TestScannerTestSuite/TestUpdateScanner
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to get registration"}]}
2026-01-16T11:23:56Z [ERROR] [/lib/http/error.go:58]: {"errors":[{"code":"UNKNOWN","message":"unknown: failed to update the scanner"}]}
--- PASS: TestScannerTestSuite (1.04s)
    --- PASS: TestScannerTestSuite/TestAuthorization (0.02s)
    --- PASS: TestScannerTestSuite/TestCreateScanner (0.01s)
    --- PASS: TestScannerTestSuite/TestCreateScannerWithInvalidBody (0.00s)
    --- PASS: TestScannerTestSuite/TestDeleteScanner (0.01s)
    --- PASS: TestScannerTestSuite/TestGetScanner (0.01s)
    --- PASS: TestScannerTestSuite/TestGetScannerMetadata (0.00s)
    --- PASS: TestScannerTestSuite/TestListScanners (0.00s)
    --- PASS: TestScannerTestSuite/TestPingScanner (0.01s)
    --- PASS: TestScannerTestSuite/TestSetScannerAsDefault (0.00s)
    --- PASS: TestScannerTestSuite/TestUpdateScanner (0.01s)
=== RUN   TestStatisticsSuite
=== RUN   TestStatisticsSuite/TestGetStatistic
--- PASS: TestStatisticsSuite (0.58s)
    --- PASS: TestStatisticsSuite/TestGetStatistic (0.00s)
=== RUN   TestRequireValidSecret
--- PASS: TestRequireValidSecret (0.00s)
=== RUN   TestUserTestSuite
=== RUN   TestUserTestSuite/TestGetRandomSecret
=== RUN   TestUserTestSuite/TestUpdateUserPassword
--- PASS: TestUserTestSuite (1.44s)
    --- PASS: TestUserTestSuite/TestGetRandomSecret (0.50s)
    --- PASS: TestUserTestSuite/TestUpdateUserPassword (0.00s)
=== RUN   Test_validateUserProfile
=== RUN   Test_validateUserProfile/normal_test
=== RUN   Test_validateUserProfile/illegall_username_,
=== RUN   Test_validateUserProfile/illegall_username_$
=== RUN   Test_validateUserProfile/illegall_username_%
=== RUN   Test_validateUserProfile/illegall_username_#
=== RUN   Test_validateUserProfile/illegall_realname
=== RUN   Test_validateUserProfile/update_profile
=== RUN   Test_validateUserProfile/username_too_long
=== RUN   Test_validateUserProfile/invalid_email
=== RUN   Test_validateUserProfile/invalid_comment
--- PASS: Test_validateUserProfile (0.00s)
    --- PASS: Test_validateUserProfile/normal_test (0.00s)
    --- PASS: Test_validateUserProfile/illegall_username_, (0.00s)
    --- PASS: Test_validateUserProfile/illegall_username_$ (0.00s)
    --- PASS: Test_validateUserProfile/illegall_username_% (0.00s)
    --- PASS: Test_validateUserProfile/illegall_username_# (0.00s)
    --- PASS: Test_validateUserProfile/illegall_realname (0.00s)
    --- PASS: Test_validateUserProfile/update_profile (0.00s)
    --- PASS: Test_validateUserProfile/username_too_long (0.00s)
    --- PASS: Test_validateUserProfile/invalid_email (0.00s)
    --- PASS: Test_validateUserProfile/invalid_comment (0.00s)
=== RUN   Test_unescapePathParams
=== RUN   Test_unescapePathParams/non_ptr
=== RUN   Test_unescapePathParams/non_struct
=== RUN   Test_unescapePathParams/ptr_of_struct
=== RUN   Test_unescapePathParams/non_string_filed
=== RUN   Test_unescapePathParams/field_not_found
=== RUN   Test_unescapePathParams/ok
--- PASS: Test_unescapePathParams (0.00s)
    --- PASS: Test_unescapePathParams/non_ptr (0.00s)
    --- PASS: Test_unescapePathParams/non_struct (0.00s)
    --- PASS: Test_unescapePathParams/ptr_of_struct (0.00s)
    --- PASS: Test_unescapePathParams/non_string_filed (0.00s)
    --- PASS: Test_unescapePathParams/field_not_found (0.00s)
    --- PASS: Test_unescapePathParams/ok (0.00s)
=== RUN   TestWebhookJobTestSuite
=== RUN   TestWebhookJobTestSuite/TestListWebhookJobs
--- PASS: TestWebhookJobTestSuite (0.48s)
    --- PASS: TestWebhookJobTestSuite/TestListWebhookJobs (0.00s)
=== RUN   TestWebhookTestSuite
2026-01-16T11:23:59Z [INFO] [/pkg/notification/notification.go:77]: notification initialization completed
=== RUN   TestWebhookTestSuite/TestCreateWebhookPolicyOfProject
=== RUN   TestWebhookTestSuite/TestDeleteWebhookPolicyOfProject
=== RUN   TestWebhookTestSuite/TestGetLogsOfWebhookTask
=== RUN   TestWebhookTestSuite/TestGetSupportedEventTypes
=== RUN   TestWebhookTestSuite/TestGetWebhookPolicyOfProject
=== RUN   TestWebhookTestSuite/TestLastTrigger
=== RUN   TestWebhookTestSuite/TestListExecutionsOfWebhookPolicy
=== RUN   TestWebhookTestSuite/TestListTasksOfWebhookExecution
=== RUN   TestWebhookTestSuite/TestListWebhookPoliciesOfProject
=== RUN   TestWebhookTestSuite/TestUpdateWebhookPolicyOfProject
--- PASS: TestWebhookTestSuite (0.60s)
    --- PASS: TestWebhookTestSuite/TestCreateWebhookPolicyOfProject (0.01s)
    --- PASS: TestWebhookTestSuite/TestDeleteWebhookPolicyOfProject (0.00s)
    --- PASS: TestWebhookTestSuite/TestGetLogsOfWebhookTask (0.00s)
    --- PASS: TestWebhookTestSuite/TestGetSupportedEventTypes (0.00s)
    --- PASS: TestWebhookTestSuite/TestGetWebhookPolicyOfProject (0.00s)
    --- PASS: TestWebhookTestSuite/TestLastTrigger (0.00s)
    --- PASS: TestWebhookTestSuite/TestListExecutionsOfWebhookPolicy (0.00s)
    --- PASS: TestWebhookTestSuite/TestListTasksOfWebhookExecution (0.00s)
    --- PASS: TestWebhookTestSuite/TestListWebhookPoliciesOfProject (0.00s)
    --- PASS: TestWebhookTestSuite/TestUpdateWebhookPolicyOfProject (0.01s)
PASS
ok      github.com/goharbor/harbor/src/server/v2.0/handler      19.434s

Issue being fixed

Fixes #(22718)
Fixes #(21032)

Please indicate you've done the following:

  • Well Written Title and Summary of the PR
  • Label the PR as needed. "release-note/ignore-for-release, release-note/new-feature, release-note/update, release-note/enhancement, release-note/community, release-note/breaking-change, release-note/docs, release-note/infra, release-note/deprecation"
  • Accepted the DCO. Commits without the DCO will delay acceptance.
  • Made sure tests are passing and test coverage is added if needed.
  • Considered the docs impact and opened a new docs issue or PR with docs changes if needed in website repository.

@codecov
Copy link

codecov bot commented Jan 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.01%. Comparing base (c8c11b4) to head (4e15a3f).
⚠️ Report is 671 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main   #22724       +/-   ##
===========================================
+ Coverage   45.36%   66.01%   +20.64%     
===========================================
  Files         244     1074      +830     
  Lines       13333   116417   +103084     
  Branches     2719     2937      +218     
===========================================
+ Hits         6049    76855    +70806     
- Misses       6983    35313    +28330     
- Partials      301     4249     +3948     
Flag Coverage Δ
unittests 66.01% <ø> (+20.64%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 989 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mlimardo1984 mlimardo1984 marked this pull request as ready for review January 12, 2026 08:02
@mlimardo1984 mlimardo1984 requested a review from a team as a code owner January 12, 2026 08:02
@Vad1mo Vad1mo enabled auto-merge (squash) January 12, 2026 09:49
auto-merge was automatically disabled January 13, 2026 09:46

Head branch was pushed to by a user without write access

@mlimardo1984 mlimardo1984 force-pushed the 21032-swagger-replication-rule-invalid-json branch 2 times, most recently from cce9a54 to 516b5fe Compare January 14, 2026 10:37
@mlimardo1984 mlimardo1984 marked this pull request as draft January 15, 2026 14:21
@mlimardo1984 mlimardo1984 force-pushed the 21032-swagger-replication-rule-invalid-json branch 5 times, most recently from 8368dba to 3166ba9 Compare January 16, 2026 10:39
@mlimardo1984 mlimardo1984 marked this pull request as ready for review January 16, 2026 10:40
@mlimardo1984 mlimardo1984 force-pushed the 21032-swagger-replication-rule-invalid-json branch from 3166ba9 to fed2ca9 Compare January 16, 2026 10:40
@mlimardo1984 mlimardo1984 force-pushed the 21032-swagger-replication-rule-invalid-json branch 3 times, most recently from 64e3744 to db99cec Compare January 26, 2026 07:48
@mlimardo1984 mlimardo1984 force-pushed the 21032-swagger-replication-rule-invalid-json branch from db99cec to c29d508 Compare January 26, 2026 10:56
@Vad1mo Vad1mo enabled auto-merge (squash) January 26, 2026 11:05
@reasonerjt reasonerjt self-assigned this Jan 27, 2026
Copy link
Contributor

@reasonerjt reasonerjt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also manually squash the commits and explain it's for backward compatibility of API to remove the "type" feild? (which I believe it's true)?

auto-merge was automatically disabled January 29, 2026 09:51

Head branch was pushed to by a user without write access

@mlimardo1984
Copy link
Contributor Author

@reasonerjt After the code change, all the tests in the description have been re-run successfully.

Thanks!

@mlimardo1984 mlimardo1984 force-pushed the 21032-swagger-replication-rule-invalid-json branch 6 times, most recently from 6501346 to 15081f4 Compare February 2, 2026 10:42
Copy link
Contributor

@reasonerjt reasonerjt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@Vad1mo Vad1mo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have run some tests, and it looks like the only change really needed is the removal of type: object from swagger.yaml

Can you elaborate on why the conversion and converter is needed?

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes a critical bug in the Harbor API where creating replication rules via Swagger with filters fails with "Invalid JSON" errors. The issue stemmed from a type mismatch between the Swagger schema definition (which expected a string for filter values) and the actual implementation (which uses objects/arrays for label filters).

Changes:

  • Modified Swagger API schema to accept any JSON type for replication filter values instead of constraining to type: object
  • Added convertFilterValue function in the backend to properly handle filter value type conversion, particularly for label filters which require arrays
  • Enhanced frontend TypeScript components to gracefully handle different filter value types (arrays, strings, and other types)
  • Added comprehensive unit tests for filter value conversion and replication policy operations

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
api/v2.0/swagger.yaml Removed type: object constraint from ReplicationFilter value field to allow any JSON type
src/server/v2.0/handler/replication.go Added convertFilterValue function to handle label filter array conversion and applied it in Create/Update operations
src/server/v2.0/handler/replication_test.go New test file with 384 lines covering filter conversions, policy conversions, and edge cases
src/portal/src/app/base/project/p2p-provider/policy/policy.component.ts Added convertFilterValueToString helper to handle array-to-string conversion for UI display
src/portal/src/app/base/left-side-nav/replication/replication/create-edit-rule/create-edit-rule.component.ts Enhanced type checking for label filter values to handle arrays, strings, and other types gracefully

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mlimardo1984
Copy link
Contributor Author

I have run some tests, and it looks like the only change really needed is the removal of type: object from swagger.yaml

Can you elaborate on why the conversion and converter is needed?

@Vad1mo As discussed in Slack, the reason behind this was to ensure data is correctly provided but it has been decided to not modify user input, if the data is wrong, it should be clearly reported.

Thanks!

@mlimardo1984 mlimardo1984 force-pushed the 21032-swagger-replication-rule-invalid-json branch 2 times, most recently from 917e6f7 to cb00c4c Compare February 3, 2026 09:11
The 'type' field in ReplicationFilter schema caused JSON serialization issues
because swagger codegen generates it as a required string field, but the actual
value is interface{} which can be string, []string, or other types depending on
the filter type.

Removing the 'type' field from the schema fixes serialization while maintaining
backward compatibility, as the field wasn't documented or used by clients.

Changes:
- Remove 'type' from ReplicationFilter schema in swagger.yaml
- Simplify filter conversion logic in handler
- Add validation to skip invalid filters
- Add comprehensive tests for filter handling

Signed-off-by: Matteo Limardo <mlimardo@mirantis.com>

remove converFilterValue func

Signed-off-by: Matteo Limardo <mlimardo@mirantis.com>
@mlimardo1984 mlimardo1984 force-pushed the 21032-swagger-replication-rule-invalid-json branch from cb00c4c to aaf00e5 Compare February 3, 2026 09:12
@mlimardo1984 mlimardo1984 requested a review from Vad1mo February 3, 2026 09:12
@Vad1mo Vad1mo requested a review from Copilot February 3, 2026 09:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Vadim Bauer <Bauer.vadim@gmail.com>
@Vad1mo Vad1mo enabled auto-merge (squash) February 3, 2026 10:51
@Vad1mo Vad1mo merged commit ba13f6c into goharbor:main Feb 11, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/update Update or Fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error with invalid json while using Swagger API to create a new replication rule Issue creating replication policy through the API

7 participants