From ef857baa9e80ff9b23208ae6705d11954927e585 Mon Sep 17 00:00:00 2001 From: Avgustin Marinov Date: Tue, 5 Nov 2024 09:54:34 +0200 Subject: [PATCH] Code format hawkbit-repository-jpa (#1928) Signed-off-by: Marinov Avgustin --- .../hawkbit-repository-jpa/README.md | 3 +- .../hawkbit-repository-jpa/pom.xml | 298 ++--- .../jpa/CurrentTenantCacheKeyGenerator.java | 5 +- .../jpa/CustomBaseRepositoryFactoryBean.java | 5 +- .../jpa/DefaultRolloutApprovalStrategy.java | 48 +- .../repository/jpa/EntityInterceptor.java | 35 +- .../jpa/HawkBitEclipseLinkJpaDialect.java | 6 +- .../repository/jpa/JpaEntityFactory.java | 62 +- .../repository/jpa/JpaManagementHelper.java | 4 +- .../repository/jpa/JpaRolloutExecutor.java | 129 +- .../repository/jpa/JpaRolloutHandler.java | 44 +- .../RepositoryApplicationConfiguration.java | 354 +++--- .../SystemManagementCacheKeyGenerator.java | 41 +- .../repository/jpa/TenantKeyGenerator.java | 1 - .../repository/jpa/acm/AccessController.java | 20 +- .../ExceptionMappingAspectHandler.java | 13 +- .../AbstractAutoAssignExecutor.java | 62 +- .../jpa/autoassign/AutoAssignChecker.java | 18 +- .../jpa/autoassign/AutoAssignScheduler.java | 16 +- .../jpa/autocleanup/AutoActionCleanup.java | 10 +- .../jpa/autocleanup/AutoCleanupScheduler.java | 14 +- .../jpa/builder/JpaActionStatusBuilder.java | 1 - .../jpa/builder/JpaActionStatusCreate.java | 1 - .../builder/JpaDistributionSetBuilder.java | 1 - .../jpa/builder/JpaDistributionSetCreate.java | 18 +- .../JpaDistributionSetTypeBuilder.java | 1 - .../builder/JpaDistributionSetTypeCreate.java | 1 - .../jpa/builder/JpaRolloutBuilder.java | 2 +- .../jpa/builder/JpaRolloutCreate.java | 61 +- .../jpa/builder/JpaRolloutGroupBuilder.java | 2 +- .../jpa/builder/JpaRolloutGroupCreate.java | 101 +- .../jpa/builder/JpaSoftwareModuleBuilder.java | 1 - .../jpa/builder/JpaSoftwareModuleCreate.java | 9 +- .../JpaSoftwareModuleMetadataBuilder.java | 1 - .../JpaSoftwareModuleMetadataCreate.java | 1 - .../builder/JpaSoftwareModuleTypeBuilder.java | 1 - .../builder/JpaSoftwareModuleTypeCreate.java | 1 - .../repository/jpa/builder/JpaTagBuilder.java | 1 - .../repository/jpa/builder/JpaTagCreate.java | 2 +- .../jpa/builder/JpaTargetBuilder.java | 5 +- .../jpa/builder/JpaTargetCreate.java | 6 +- .../builder/JpaTargetFilterQueryBuilder.java | 12 +- .../builder/JpaTargetFilterQueryCreate.java | 1 - .../jpa/builder/JpaTargetTypeBuilder.java | 6 +- .../jpa/builder/JpaTargetTypeCreate.java | 10 +- .../MultiTenantJpaTransactionManager.java | 1 - ...ansactionCommitDefaultServiceExecutor.java | 18 +- .../AfterTransactionCommitExecutor.java | 7 +- .../AbstractDsAssignmentStrategy.java | 225 ++-- .../jpa/management/JpaActionManagement.java | 122 +- .../jpa/management/JpaArtifactManagement.java | 185 +-- .../management/JpaConfirmationManagement.java | 60 +- .../management/JpaControllerManagement.java | 1037 ++++++++-------- .../management/JpaDeploymentManagement.java | 888 +++++++------- ...DistributionSetInvalidationManagement.java | 40 +- .../JpaDistributionSetManagement.java | 930 +++++++-------- .../JpaDistributionSetTagManagement.java | 116 +- .../JpaDistributionSetTypeManagement.java | 277 +++-- .../management/JpaRolloutGroupManagement.java | 234 ++-- .../jpa/management/JpaRolloutManagement.java | 732 ++++++------ .../JpaSoftwareModuleManagement.java | 410 +++---- .../JpaSoftwareModuleTypeManagement.java | 97 +- .../jpa/management/JpaSystemManagement.java | 221 ++-- .../JpaTargetFilterQueryManagement.java | 59 +- .../jpa/management/JpaTargetManagement.java | 1055 +++++++++-------- .../management/JpaTargetTagManagement.java | 43 +- .../management/JpaTargetTypeManagement.java | 25 +- .../JpaTenantConfigurationManagement.java | 185 ++- .../management/JpaTenantStatsManagement.java | 1 - .../OfflineDsAssignmentStrategy.java | 62 +- .../OnlineDsAssignmentStrategy.java | 122 +- .../jpa/model/AbstractJpaBaseEntity.java | 91 +- .../jpa/model/AbstractJpaMetaData.java | 12 +- .../jpa/model/AbstractJpaNamedEntity.java | 18 +- .../AbstractJpaNamedVersionedEntity.java | 8 +- .../AbstractJpaTenantAwareBaseEntity.java | 52 +- .../jpa/model/AbstractJpaTypeEntity.java | 21 +- .../jpa/model/DistributionSetTypeElement.java | 31 +- ...istributionSetTypeElementCompositeKey.java | 7 +- .../jpa/model/DsMetadataCompositeKey.java | 8 +- .../jpa/model/EntityInterceptorListener.java | 21 +- .../model/EntityPropertyChangeListener.java | 17 +- .../jpa/model/EventAwareEntity.java | 6 +- .../repository/jpa/model/JpaAction.java | 182 ++- .../repository/jpa/model/JpaActionStatus.java | 93 +- .../repository/jpa/model/JpaArtifact.java | 40 +- .../jpa/model/JpaAutoConfirmationStatus.java | 20 +- .../jpa/model/JpaDistributionSet.java | 30 +- .../jpa/model/JpaDistributionSetMetadata.java | 10 +- .../jpa/model/JpaDistributionSetTag.java | 14 +- .../jpa/model/JpaDistributionSetType.java | 139 ++- .../repository/jpa/model/JpaRollout.java | 209 ++-- .../repository/jpa/model/JpaRolloutGroup.java | 72 +- .../jpa/model/JpaSoftwareModule.java | 12 +- .../jpa/model/JpaSoftwareModuleMetadata.java | 2 +- .../jpa/model/JpaSoftwareModuleType.java | 44 +- .../repository/jpa/model/JpaStatistic.java | 1 - .../hawkbit/repository/jpa/model/JpaTag.java | 11 +- .../repository/jpa/model/JpaTarget.java | 297 +++-- .../jpa/model/JpaTargetFilterQuery.java | 22 +- .../jpa/model/JpaTargetMetadata.java | 41 +- .../repository/jpa/model/JpaTargetTag.java | 2 +- .../repository/jpa/model/JpaTargetType.java | 56 +- .../jpa/model/JpaTenantConfiguration.java | 8 +- .../jpa/model/JpaTenantMetaData.java | 7 +- .../jpa/model/RolloutTargetGroup.java | 1 - .../jpa/model/RolloutTargetGroupId.java | 10 +- .../jpa/model/SwMetadataCompositeKey.java | 13 +- .../jpa/model/TargetMetadataCompositeKey.java | 8 +- .../AfterTransactionCommitExecutorHolder.java | 4 +- .../model/helper/EntityInterceptorHolder.java | 1 - .../helper/SecurityTokenGeneratorHolder.java | 6 +- .../jpa/model/helper/TenantAwareHolder.java | 4 - .../jpa/repository/ACMRepository.java | 20 +- .../jpa/repository/ActionRepository.java | 138 +-- .../repository/ActionStatusRepository.java | 13 +- .../jpa/repository/BaseEntityRepository.java | 39 +- .../repository/BaseEntityRepositoryACM.java | 237 ++-- .../DistributionSetMetadataRepository.java | 2 +- .../repository/DistributionSetRepository.java | 28 +- .../DistributionSetTagRepository.java | 10 +- .../DistributionSetTypeRepository.java | 15 +- .../jpa/repository/HawkBitBaseRepository.java | 17 +- .../repository/LocalArtifactRepository.java | 8 +- .../repository/NoCountSliceRepository.java | 12 +- .../repository/RolloutGroupRepository.java | 65 +- .../jpa/repository/RolloutRepository.java | 21 +- .../RolloutTargetGroupRepository.java | 6 +- .../SoftwareModuleMetadataRepository.java | 17 +- .../repository/SoftwareModuleRepository.java | 7 +- .../SoftwareModuleTypeRepository.java | 12 +- .../TargetFilterQueryRepository.java | 8 +- .../repository/TargetMetadataRepository.java | 2 +- .../jpa/repository/TargetRepository.java | 5 +- .../jpa/repository/TargetTagRepository.java | 7 +- .../jpa/repository/TargetTypeRepository.java | 6 +- .../TenantConfigurationRepository.java | 17 +- .../repository/TenantMetaDataRepository.java | 6 +- .../jpa/rollout/RolloutScheduler.java | 11 +- .../EvaluatorNotConfiguredException.java | 5 +- .../condition/PauseRolloutGroupAction.java | 2 +- .../RolloutGroupEvaluationManager.java | 22 +- .../jpa/rsql/AbstractRSQLVisitor.java | 31 +- .../jpa/rsql/DefaultRsqlVisitorFactory.java | 3 +- .../jpa/rsql/FieldValidationRsqlVisitor.java | 5 +- .../jpa/rsql/JpaQueryRsqlVisitor.java | 306 ++--- .../jpa/rsql/JpaQueryRsqlVisitorG2.java | 108 +- .../jpa/rsql/ParseExceptionWrapper.java | 26 +- .../repository/jpa/rsql/PropertyMapper.java | 14 +- .../repository/jpa/rsql/RSQLUtility.java | 30 +- .../jpa/rsql/RsqlParserValidationOracle.java | 9 +- .../specifications/ActionSpecifications.java | 41 +- .../DistributionSetSpecification.java | 221 ++-- .../DistributionSetTagSpecifications.java | 4 +- .../DistributionSetTypeSpecification.java | 7 +- .../specifications/RolloutSpecification.java | 16 +- .../SoftwareModuleSpecification.java | 24 +- .../specifications/SpecificationsBuilder.java | 4 +- .../jpa/specifications/TagSpecification.java | 2 +- .../TargetFilterQuerySpecification.java | 13 +- .../specifications/TargetSpecifications.java | 190 ++- .../TargetTypeSpecification.java | 7 +- .../jpa/utils/DeploymentHelper.java | 36 +- ...izeAndStorageQuotaCheckingInputStream.java | 9 +- .../repository/jpa/utils/QuotaHelper.java | 96 +- .../jpa/utils/WeightValidationHelper.java | 44 +- ..._length_of_target_attributes_key___DB2.sql | 3 +- ..._11__add_auto_assign_action_type___DB2.sql | 3 +- ...length_of_controller_id_and_name___DB2.sql | 33 +- ...V1_12_13__add_action_external_id___DB2.sql | 3 +- .../DB2/V1_12_14__add_sha256_hash___DB2.sql | 3 +- .../DB2/V1_12_15__add_weight___DB2.sql | 9 +- ...1_12_16__add_action_initiated_by___DB2.sql | 9 +- .../DB2/V1_12_18__add_target_type___DB2.sql | 31 +- .../V1_12_19__add_valid_flag_to_ds___DB2.sql | 6 +- ...12_20__add_encryption_flag_to_sm___DB2.sql | 6 +- ...__change_target_type_name_length___DB2.sql | 3 +- ...V1_12_23__add_action_status_code___DB2.sql | 3 +- ..._24__add_last_action_status_code___DB2.sql | 3 +- .../V1_12_25__add_confirmation_flag___DB2.sql | 32 +- ...2_26__add_access_control_context___DB2.sql | 6 +- ..._12_27__target_type_inherit_type___DB2.sql | 9 +- .../V1_12_28__add_dynamic_rollout___DB2.sql | 27 +- .../DB2/V1_12_29__add_ds_sm_locked___DB2.sql | 6 +- .../migration/DB2/V1_12_5__baseline___DB2.sql | 858 +++++++------- .../DB2/V1_12_6__add_index___DB2.sql | 2 +- ...2_7__add_rollout_approval_fields___DB2.sql | 6 +- ...ngth_of_created_last_modified_by___DB2.sql | 93 +- .../V1_12_9__add_target_metadata___DB2.sql | 17 +- .../db/migration/H2/V1_0_1__init___H2.sql | 898 +++++++------- .../H2/V1_10_0__advanced_rolloutgroup__H2.sql | 4 +- .../H2/V1_10_2__rollout_auto_start__H2.sql | 2 +- .../V1_10_3__add_rollout_deleted_flag__H2.sql | 30 +- .../H2/V1_11_0__drop_target_info__H2.sql | 60 +- .../V1_11_1__target_filter_query_UQ___H2.sql | 4 +- .../V1_11_3__add_module_md_targetvis__H2.sql | 3 +- .../H2/V1_12_0__action_performance___H2.sql | 43 +- ...2_11__add_auto_assign_action_type___H2.sql | 3 +- .../V1_12_13__add_action_external_id___H2.sql | 3 +- .../H2/V1_12_14__add_sha256_hash___H2.sql | 3 +- .../H2/V1_12_15__add_weight___H2.sql | 9 +- ...V1_12_16__add_action_initiated_by___H2.sql | 6 +- .../V1_12_19__add_valid_flag_to_ds___H2.sql | 6 +- ..._12_20__add_encryption_flag_to_sm___H2.sql | 6 +- .../V1_12_23__add_action_status_code___H2.sql | 3 +- ...2_24__add_last_action_status_code___H2.sql | 3 +- .../V1_12_25__add_confirmation_flag___H2.sql | 32 +- ...12_26__add_access_control_context___H2.sql | 6 +- ...1_12_27__target_type_inherit_type___H2.sql | 9 +- .../H2/V1_12_28__add_dynamic_rollout___H2.sql | 18 +- .../H2/V1_12_29__add_ds_sm_locked___H2.sql | 6 +- .../V1_12_4__add_maintenance_window___H2.sql | 9 +- .../migration/H2/V1_12_6__add_index___H2.sql | 2 +- ...12_7__add_rollout_approval_fields___H2.sql | 6 +- .../H2/V1_12_9__add_target_metadata___H2.sql | 23 +- ...0__update_target_info_for_message___H2.sql | 12 +- .../H2/V1_4_0__cascade_delete___H2.sql | 114 +- .../H2/V1_4_1__cascade_delete___H2.sql | 10 +- .../H2/V1_5_0__target_filter_query___H2.sql | 23 +- .../H2/V1_6_0__rollout_management___H2.sql | 207 ++-- ...0__swmType_maxAssignment_greater_0__H2.sql | 4 +- .../H2/V1_8_0__auto_assign_ds_filter__H2.sql | 10 +- .../H2/V1_8_1__cascade_delete___H2.sql | 40 +- ...1_9_0__add_rollout_groups_created___H2.sql | 3 +- .../migration/MYSQL/V1_0_1__init___MYSQL.sql | 898 +++++++------- .../V1_10_0__advanced_rolloutgroup__MYSQL.sql | 4 +- ...10_1__consolidate_artifact_sha1__MYSQL.sql | 2 +- .../V1_10_2__rollout_auto_start__MYSQL.sql | 2 +- ..._10_3__add_rollout_deleted_flag__MYSQL.sql | 26 +- .../V1_11_0__drop_target_info__MYSQL.sql | 44 +- ...1_11_1__target_filter_query_UQ___MYSQL.sql | 4 +- ...1_11_3__add_module_md_targetvis__MYSQL.sql | 3 +- .../V1_12_0__action_performance___MYSQL.sql | 43 +- ...ength_of_target_attributes_key___MYSQL.sql | 2 +- ...1__add_auto_assign_action_type___MYSQL.sql | 3 +- ...ngth_of_controller_id_and_name___MYSQL.sql | 22 +- ..._12_13__add_action_external_id___MYSQL.sql | 3 +- .../V1_12_14__add_sha256_hash___MYSQL.sql | 3 +- .../MYSQL/V1_12_15__add_weight___MYSQL.sql | 9 +- ...12_16__add_action_initiated_by___MYSQL.sql | 6 +- ...V1_12_19__add_valid_flag_to_ds___MYSQL.sql | 6 +- .../V1_12_1__missing_non_null___MYSQL.sql | 6 +- ..._20__add_encryption_flag_to_sm___MYSQL.sql | 6 +- ...change_target_type_name_length___MYSQL.sql | 2 +- ..._12_23__add_action_status_code___MYSQL.sql | 3 +- ...4__add_last_action_status_code___MYSQL.sql | 3 +- ...1_12_25__add_confirmation_flag___MYSQL.sql | 32 +- ...26__add_access_control_context___MYSQL.sql | 6 +- ...2_27__target_type_inherit_type___MYSQL.sql | 9 +- .../V1_12_28__add_dynamic_rollout___MYSQL.sql | 18 +- .../V1_12_29__add_ds_sm_locked___MYSQL.sql | 6 +- ...1_12_4__add_maintenance_window___MYSQL.sql | 9 +- .../MYSQL/V1_12_6__add_index___MYSQL.sql | 2 +- ...7__add_rollout_approval_fields___MYSQL.sql | 6 +- ...th_of_created_last_modified_by___MYSQL.sql | 30 +- .../V1_12_9__add_target_metadata___MYSQL.sql | 23 +- ...update_target_info_for_message___MYSQL.sql | 4 +- .../MYSQL/V1_4_0__cascade_delete___MYSQL.sql | 106 +- .../MYSQL/V1_4_1__cascade_delete___MYSQL.sql | 10 +- .../V1_5_0__target_filter_query___MYSQL.sql | 31 +- .../V1_6_0__rollout_management___MYSQL.sql | 207 ++-- ...swmType_maxAssignment_greater_0__MYSQL.sql | 4 +- .../V1_7_1__reduce_length_enums___MYSQL.sql | 10 +- .../V1_8_0__auto_assign_ds_filter__MYSQL.sql | 10 +- .../MYSQL/V1_8_1__cascade_delete___MYSQL.sql | 40 +- ..._0__add_rollout_groups_created___MYSQL.sql | 3 +- .../V1_12_15__baseline___POSTGRESQL.sql | 1001 ++++++++-------- ...__add_action_initiated_by___POSTGRESQL.sql | 6 +- ...add_index_target_modified___POSTGRESQL.sql | 4 +- ...V1_12_18__add_target_type___POSTGRESQL.sql | 50 +- ..._19__add_valid_flag_to_ds___POSTGRESQL.sql | 6 +- ...add_encryption_flag_to_sm___POSTGRESQL.sql | 6 +- ...add_rollouts_status_index___POSTGRESQL.sql | 4 +- ...3__add_action_status_code___POSTGRESQL.sql | 3 +- ...d_last_action_status_code___POSTGRESQL.sql | 3 +- ...25__add_confirmation_flag___POSTGRESQL.sql | 6 +- ...dd_access_control_context___POSTGRESQL.sql | 6 +- ..._target_type_inherit_type___POSTGRESQL.sql | 9 +- ...2_28__add_dynamic_rollout___POSTGRESQL.sql | 27 +- ...1_12_29__add_ds_sm_locked___POSTGRESQL.sql | 6 +- ...d_auto_assign_action_type___SQL_SERVER.sql | 3 +- ...3__add_action_external_id___SQL_SERVER.sql | 3 +- ...V1_12_14__add_sha256_hash___SQL_SERVER.sql | 3 +- .../V1_12_15__add_weight___SQL_SERVER.sql | 9 +- ...__add_action_initiated_by___SQL_SERVER.sql | 6 +- ...V1_12_18__add_target_type___SQL_SERVER.sql | 31 +- ..._19__add_valid_flag_to_ds___SQL_SERVER.sql | 3 +- ...add_encryption_flag_to_sm___SQL_SERVER.sql | 3 +- ...3__add_action_status_code___SQL_SERVER.sql | 3 +- ...d_last_action_status_code___SQL_SERVER.sql | 3 +- ...25__add_confirmation_flag___SQL_SERVER.sql | 26 +- ...dd_access_control_context___SQL_SERVER.sql | 6 +- ..._target_type_inherit_type___SQL_SERVER.sql | 9 +- ...2_28__add_dynamic_rollout___SQL_SERVER.sql | 18 +- ...1_12_29__add_ds_sm_locked___SQL_SERVER.sql | 6 +- .../V1_12_5__baseline___SQL_SERVER.sql | 506 ++++---- .../V1_12_6__add_index___SQL_SERVER.sql | 2 +- ...d_rollout_approval_fields___SQL_SERVER.sql | 6 +- ...12_9__add_target_metadata___SQL_SERVER.sql | 11 +- .../resources/hawkbit-jpa-defaults.properties | 2 - .../event/remote/AbstractRemoteEventTest.java | 39 +- .../event/remote/RemoteIdEventTest.java | 2 - .../remote/RemoteTenantAwareEventTest.java | 27 +- .../entity/AbstractRemoteEntityEventTest.java | 3 +- .../event/remote/entity/ActionEventTest.java | 8 +- .../DistributionSetCreatedEventTest.java | 3 +- .../entity/DistributionSetTagEventTest.java | 5 +- .../DistributionSetUpdatedEventTest.java | 5 +- .../event/remote/entity/RolloutEventTest.java | 7 +- .../remote/entity/RolloutGroupEventTest.java | 7 +- .../entity/SoftwareModuleEventTest.java | 5 +- .../event/remote/entity/TargetEventTest.java | 7 +- .../remote/entity/TargetTagEventTest.java | 5 +- .../jpa/AbstractJpaIntegrationTest.java | 74 +- ...urrentDistributionSetInvalidationTest.java | 96 +- .../jpa/HawkBitEclipseLinkJpaDialectTest.java | 11 +- .../jpa/RandomGeneratedInputStream.java | 5 +- .../jpa/acm/context/ContextAwareTest.java | 7 +- .../AbstractAccessControllerTest.java | 37 +- .../DistributionSetAccessControllerTest.java | 9 +- .../TargetAccessControllerTest.java | 14 +- .../TargetTypeAccessControllerTest.java | 4 +- .../controller/TestAccessControlManger.java | 23 +- .../autoassign/AutoAssignCheckerIntTest.java | 202 ++-- .../jpa/autoassign/AutoAssignCheckerTest.java | 39 +- .../autocleanup/AutoActionCleanupTest.java | 8 +- .../autocleanup/AutoCleanupSchedulerTest.java | 8 +- .../jpa/event/RepositoryEntityEventTest.java | 7 +- .../repository/jpa/management/ActionTest.java | 11 +- .../management/ArtifactManagementTest.java | 35 +- .../ConfirmationManagementTest.java | 38 +- .../management/ControllerManagementTest.java | 1041 ++++++++-------- .../management/DeploymentManagementTest.java | 206 ++-- ...ributionSetInvalidationManagementTest.java | 66 +- .../DistributionSetManagementTest.java | 630 +++++----- .../DistributionSetTagManagementTest.java | 44 +- .../DistributionSetTypeManagementTest.java | 216 ++-- .../LazyControllerManagementTest.java | 7 +- .../RolloutGroupManagementTest.java | 71 +- .../management/RolloutManagementFlowTest.java | 15 +- .../jpa/management/RolloutManagementTest.java | 529 +++++---- .../SoftwareModuleManagementTest.java | 324 +++-- .../SoftwareModuleTypeManagementTest.java | 7 +- .../jpa/management/SystemManagementTest.java | 39 +- .../TargetFilterQueryManagementTest.java | 202 ++-- .../TargetManagementSearchTest.java | 815 +++++++------ .../jpa/management/TargetManagementTest.java | 480 ++++---- .../management/TargetTagManagementTest.java | 269 +++-- .../management/TargetTypeManagementTest.java | 145 +-- .../TenantConfigurationManagementTest.java | 20 +- .../model/EntityInterceptorListenerTest.java | 14 +- .../jpa/model/ModelEqualsHashcodeTest.java | 7 +- .../jpa/rsql/RSQLActionFieldsTest.java | 46 +- .../rsql/RSQLDistributionSetFieldTest.java | 9 +- ...RSQLDistributionSetMetadataFieldsTest.java | 7 +- .../rsql/RSQLParserValidationOracleTest.java | 13 +- .../jpa/rsql/RSQLRolloutGroupFieldTest.java | 7 +- .../jpa/rsql/RSQLSoftwareModuleFieldTest.java | 8 +- .../RSQLSoftwareModuleMetadataFieldsTest.java | 7 +- .../RSQLSoftwareModuleTypeFieldsTest.java | 7 +- .../jpa/rsql/RSQLTagFieldsTest.java | 7 +- .../jpa/rsql/RSQLTargetFieldTest.java | 12 +- .../rsql/RSQLTargetFilterQueryFieldsTest.java | 7 +- .../rsql/RSQLTargetMetadataFieldsTest.java | 8 +- .../repository/jpa/rsql/RSQLToSQL.java | 21 +- .../repository/jpa/rsql/RSQLToSQLTest.java | 24 +- .../repository/jpa/rsql/RSQLUtilityTest.java | 154 ++- .../jpa/rsql/VirtualPropertyResolverTest.java | 76 +- .../SpecificationsBuilderTest.java | 5 +- .../jpa/tenancy/MultiTenancyEntityTest.java | 12 +- .../src/test/resources/jpa-test.properties | 2 - 371 files changed, 12299 insertions(+), 12525 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-jpa/README.md b/hawkbit-repository/hawkbit-repository-jpa/README.md index 6dd0217e7..7e4a1b54e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/README.md +++ b/hawkbit-repository/hawkbit-repository-jpa/README.md @@ -1,3 +1,4 @@ # hawkBit JPA implementation -JPA implementation of the repository. Based on [EclipseLink](http://www.eclipse.org/eclipselink/) and [Spring Data Jpa](http://projects.spring.io/spring-data-jpa/). \ No newline at end of file +JPA implementation of the repository. Based on [EclipseLink](http://www.eclipse.org/eclipselink/) +and [Spring Data Jpa](http://projects.spring.io/spring-data-jpa/). \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/pom.xml b/hawkbit-repository/hawkbit-repository-jpa/pom.xml index 3b900e3f2..ffca77c19 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/pom.xml +++ b/hawkbit-repository/hawkbit-repository-jpa/pom.xml @@ -9,155 +9,155 @@ SPDX-License-Identifier: EPL-2.0 --> - - 4.0.0 - - org.eclipse.hawkbit - ${revision} - hawkbit-repository - - hawkbit-repository-jpa - hawkBit :: Repository :: JPA Implementation - - - ${project.build.directory}/generated-sources/apt/ - - - - - - org.eclipse.hawkbit - hawkbit-repository-api - ${project.version} - - - org.eclipse.hawkbit - hawkbit-repository-core - ${project.version} - - - org.eclipse.hawkbit - hawkbit-artifact-repository-filesystem - ${project.version} - - - org.springframework - spring-core - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.eclipse.persistence - org.eclipse.persistence.jpa - - - org.springframework.security - spring-security-core - - - org.flywaydb - flyway-core - - - org.flywaydb - flyway-mysql - - - cz.jirutka.rsql - rsql-parser - - - org.jsoup - jsoup - - - javax.xml.bind - jaxb-api - - - org.hibernate.validator - hibernate-validator - - - org.apache.commons - commons-collections4 - - - - - org.eclipse.hawkbit - hawkbit-repository-test - ${project.version} - test - - - javax.el - javax.el-api - test - - - io.qameta.allure - allure-junit5 - test - - - - - - - - com.ethlo.persistence.tools - eclipselink-maven-plugin - - - modelgen - generate-sources - - modelgen - - - - process-classes - - weave - - - - - org.eclipse.hawkbit.repository.jpa.model - - - - org.eclipse.persistence - org.eclipse.persistence.jpa - ${eclipselink.version} - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - add-source - generate-sources - - add-source - - - - ${apt.source.dir} - - - - - - - + 4.0.0 + + org.eclipse.hawkbit + ${revision} + hawkbit-repository + + hawkbit-repository-jpa + hawkBit :: Repository :: JPA Implementation + + + ${project.build.directory}/generated-sources/apt/ + + + + + + org.eclipse.hawkbit + hawkbit-repository-api + ${project.version} + + + org.eclipse.hawkbit + hawkbit-repository-core + ${project.version} + + + org.eclipse.hawkbit + hawkbit-artifact-repository-filesystem + ${project.version} + + + org.springframework + spring-core + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.eclipse.persistence + org.eclipse.persistence.jpa + + + org.springframework.security + spring-security-core + + + org.flywaydb + flyway-core + + + org.flywaydb + flyway-mysql + + + cz.jirutka.rsql + rsql-parser + + + org.jsoup + jsoup + + + javax.xml.bind + jaxb-api + + + org.hibernate.validator + hibernate-validator + + + org.apache.commons + commons-collections4 + + + + + org.eclipse.hawkbit + hawkbit-repository-test + ${project.version} + test + + + javax.el + javax.el-api + test + + + io.qameta.allure + allure-junit5 + test + + + + + + + + com.ethlo.persistence.tools + eclipselink-maven-plugin + + + modelgen + generate-sources + + modelgen + + + + process-classes + + weave + + + + + org.eclipse.hawkbit.repository.jpa.model + + + + org.eclipse.persistence + org.eclipse.persistence.jpa + ${eclipselink.version} + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${apt.source.dir} + + + + + + + diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CurrentTenantCacheKeyGenerator.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CurrentTenantCacheKeyGenerator.java index 0e889cddc..2f37a3f84 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CurrentTenantCacheKeyGenerator.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CurrentTenantCacheKeyGenerator.java @@ -19,13 +19,12 @@ import org.springframework.stereotype.Service; * used by spring caching framework to resolve the key-generator. The * key-generator must registered as bean so spring can resolve the key-generator * by its name. - * + * * When using the {@link Service} annotation e.g. by {@link JpaSystemManagement} * the bean registration must be declared by the interface due spring registers * the bean by the implemented interfaces. So introduce a single interface for * the {@link JpaSystemManagement} implementation to allow it to register the * key-generator bean. - * */ @FunctionalInterface public interface CurrentTenantCacheKeyGenerator { @@ -33,7 +32,7 @@ public interface CurrentTenantCacheKeyGenerator { /** * Bean declaration to register a {@code currentTenantKeyGenerator} bean * which is used by the caching framework. - * + * * @return the {@link KeyGenerator} to be used to cache the values of the * current used tenant in the {@link JpaSystemManagement} */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CustomBaseRepositoryFactoryBean.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CustomBaseRepositoryFactoryBean.java index b8e081726..1886d935a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CustomBaseRepositoryFactoryBean.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CustomBaseRepositoryFactoryBean.java @@ -21,7 +21,7 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport * A {@link JpaRepositoryFactoryBean} extension that allow injection of custom * repository factories by using a {@link BaseRepositoryTypeProvider} * implementation, allows injecting different base repository implementations based on repository type - * + * * @param * @param * @param @@ -36,8 +36,7 @@ public class CustomBaseRepositoryFactoryBean, S, ID> * Creates a new {@link JpaRepositoryFactoryBean} for the given repository * interface. * - * @param repositoryInterface - * must not be {@literal null}. + * @param repositoryInterface must not be {@literal null}. */ public CustomBaseRepositoryFactoryBean(final Class repositoryInterface) { super(repositoryInterface); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DefaultRolloutApprovalStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DefaultRolloutApprovalStrategy.java index b2c6e8511..256c49ef3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DefaultRolloutApprovalStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DefaultRolloutApprovalStrategy.java @@ -57,6 +57,30 @@ public class DefaultRolloutApprovalStrategy implements RolloutApprovalStrategy { return isApprovalEnabled() && hasNoApproveRolloutPermission(getActorAuthorities(rollout)); } + /*** + * Per default do nothing. + * + * @param rollout + * rollout to create approval task for. + */ + @Override + public void onApprovalRequired(final Rollout rollout) { + // do nothing per default, can be extended by further implementations. + } + + @Override + public String getApprovalUser(final Rollout rollout) { + return getCurrentAuthentication().getName(); + } + + private static Authentication getCurrentAuthentication() { + return SecurityContextHolder.getContext().getAuthentication(); + } + + private static boolean hasNoApproveRolloutPermission(final Collection authorities) { + return authorities.stream().noneMatch(SpPermission.APPROVE_ROLLOUT::equals); + } + private boolean isApprovalEnabled() { return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement .getConfigurationValue(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class).getValue()); @@ -78,28 +102,4 @@ public class DefaultRolloutApprovalStrategy implements RolloutApprovalStrategy { return ((User) getCurrentAuthentication().getPrincipal()).getAuthorities().stream() .map(GrantedAuthority::getAuthority).toList(); } - - private static Authentication getCurrentAuthentication() { - return SecurityContextHolder.getContext().getAuthentication(); - } - - private static boolean hasNoApproveRolloutPermission(final Collection authorities) { - return authorities.stream().noneMatch(SpPermission.APPROVE_ROLLOUT::equals); - } - - /*** - * Per default do nothing. - * - * @param rollout - * rollout to create approval task for. - */ - @Override - public void onApprovalRequired(final Rollout rollout) { - // do nothing per default, can be extended by further implementations. - } - - @Override - public String getApprovalUser(final Rollout rollout) { - return getCurrentAuthentication().getName(); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/EntityInterceptor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/EntityInterceptor.java index 2a8b4c8f7..9ac7bfe18 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/EntityInterceptor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/EntityInterceptor.java @@ -27,63 +27,56 @@ public interface EntityInterceptor { /** * Callback for the {@link PrePersist} lifecycle event. - * - * @param entity - * the model entity + * + * @param entity the model entity */ default void prePersist(final Object entity) { } /** * Callback for the {@link PostPersist} lifecycle event. - * - * @param entity - * the model entity + * + * @param entity the model entity */ default void postPersist(final Object entity) { } /** * Callback for the {@link PostRemove} lifecycle event. - * - * @param entity - * the model entity + * + * @param entity the model entity */ default void postRemove(final Object entity) { } /** * Callback for the {@link PreRemove} lifecycle event. - * - * @param entity - * the model entity + * + * @param entity the model entity */ default void preRemove(final Object entity) { } /** * Callback for the {@link PostLoad} lifecycle event. - * - * @param entity - * the model entity + * + * @param entity the model entity */ default void postLoad(final Object entity) { } /** * Callback for the {@link PreUpdate} lifecycle event. - * - * @param entity - * the model entity + * + * @param entity the model entity */ default void preUpdate(final Object entity) { } /** * Callback for the {@link PostUpdate} lifecycle event. - * - * @param entity - * the model entity + * + * @param entity the model entity */ default void postUpdate(final Object entity) { } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkBitEclipseLinkJpaDialect.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkBitEclipseLinkJpaDialect.java index 885b778db..087dcca53 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkBitEclipseLinkJpaDialect.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkBitEclipseLinkJpaDialect.java @@ -22,10 +22,10 @@ import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect; /** * {@link EclipseLinkJpaDialect} with additional exception translation * mechanisms based on {@link SQLStateSQLExceptionTranslator}. - * + * * There are multiple variations of exceptions coming out of persistence * provider: - * + * *

* 1) {@link PersistenceException}s that can be mapped by * {@link EclipseLinkJpaDialect} into corresponding {@link DataAccessException}. @@ -47,9 +47,9 @@ import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect; *

* 3.b.) the cause is not an {@link SQLException} and as a result cannot be * mapped. - * */ public class HawkBitEclipseLinkJpaDialect extends EclipseLinkJpaDialect { + private static final long serialVersionUID = 1L; private static final SQLStateSQLExceptionTranslator SQLSTATE_EXCEPTION_TRANSLATOR = new SQLStateSQLExceptionTranslator(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java index 7187d3c88..04f6bcf04 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java @@ -26,7 +26,6 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaTagBuilder; -import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetBuilder; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetMetadata; import org.eclipse.hawkbit.repository.model.MetaData; @@ -36,7 +35,6 @@ import org.springframework.validation.annotation.Validated; /** * JPA Implementation of {@link EntityFactory}. - * */ @Validated public class JpaEntityFactory implements EntityFactory { @@ -65,6 +63,16 @@ public class JpaEntityFactory implements EntityFactory { @Autowired private TargetTypeBuilder targetTypeBuilder; + @Override + public ActionStatusBuilder actionStatus() { + return new JpaActionStatusBuilder(); + } + + @Override + public DistributionSetBuilder distributionSet() { + return distributionSetBuilder; + } + @Override public MetaData generateDsMetadata(final String key, final String value) { return new JpaDistributionSetMetadata(key, StringUtils.trimWhitespace(value)); @@ -76,23 +84,8 @@ public class JpaEntityFactory implements EntityFactory { } @Override - public DistributionSetTypeBuilder distributionSetType() { - return distributionSetTypeBuilder; - } - - @Override - public DistributionSetBuilder distributionSet() { - return distributionSetBuilder; - } - - @Override - public TargetBuilder target() { - return targetBuilder; - } - - @Override - public TargetTypeBuilder targetType() { - return targetTypeBuilder; + public SoftwareModuleMetadataBuilder softwareModuleMetadata() { + return softwareModuleMetadataBuilder; } @Override @@ -101,8 +94,18 @@ public class JpaEntityFactory implements EntityFactory { } @Override - public TargetFilterQueryBuilder targetFilterQuery() { - return targetFilterQueryBuilder; + public RolloutGroupBuilder rolloutGroup() { + return new JpaRolloutGroupBuilder(); + } + + @Override + public DistributionSetTypeBuilder distributionSetType() { + return distributionSetTypeBuilder; + } + + @Override + public RolloutBuilder rollout() { + return rolloutBuilder; } @Override @@ -116,23 +119,18 @@ public class JpaEntityFactory implements EntityFactory { } @Override - public ActionStatusBuilder actionStatus() { - return new JpaActionStatusBuilder(); + public TargetBuilder target() { + return targetBuilder; } @Override - public RolloutBuilder rollout() { - return rolloutBuilder; + public TargetTypeBuilder targetType() { + return targetTypeBuilder; } @Override - public RolloutGroupBuilder rolloutGroup() { - return new JpaRolloutGroupBuilder(); - } - - @Override - public SoftwareModuleMetadataBuilder softwareModuleMetadata() { - return softwareModuleMetadataBuilder; + public TargetFilterQueryBuilder targetFilterQuery() { + return targetFilterQueryBuilder; } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java index ee6accc9f..880e69a62 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java @@ -15,10 +15,7 @@ import java.util.Optional; import jakarta.persistence.EntityManager; -import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; -import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaTenantAwareBaseEntity; -import org.eclipse.hawkbit.repository.jpa.repository.BaseEntityRepository; import org.eclipse.hawkbit.repository.jpa.repository.NoCountSliceRepository; import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.springframework.data.domain.Page; @@ -36,6 +33,7 @@ import org.springframework.util.StringUtils; * A collection of static helper methods for the management classes */ public final class JpaManagementHelper { + private JpaManagementHelper() { } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java index 48ff6d134..bd06edacb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa; +import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.addSuccessAndErrorConditionsAndActions; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; import java.util.Arrays; @@ -73,8 +75,6 @@ import org.springframework.data.domain.Sort.Direction; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionException; -import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.addSuccessAndErrorConditionsAndActions; - /** * A Jpa implementation of {@link RolloutExecutor} */ @@ -101,28 +101,25 @@ public class JpaRolloutExecutor implements RolloutExecutor { */ private static final List DOWNLOAD_ONLY_ACTION_TERMINATION_STATUSES = Arrays.asList(Status.ERROR, Status.FINISHED, Status.CANCELED, Status.DOWNLOADED); - + private static final Comparator DESC_COMP = Comparator.comparingLong(RolloutGroup::getId).reversed(); private final ActionRepository actionRepository; private final RolloutGroupRepository rolloutGroupRepository; private final RolloutTargetGroupRepository rolloutTargetGroupRepository; private final RolloutRepository rolloutRepository; - private final TargetManagement targetManagement; private final DeploymentManagement deploymentManagement; private final RolloutGroupManagement rolloutGroupManagement; private final RolloutManagement rolloutManagement; private final QuotaManagement quotaManagement; - private final RolloutGroupEvaluationManager evaluationManager; private final RolloutApprovalStrategy rolloutApprovalStrategy; - private final EntityManager entityManager; private final PlatformTransactionManager txManager; private final AfterTransactionCommitExecutor afterCommit; private final EventPublisherHolder eventPublisherHolder; - private final TenantAware tenantAware; private final RepositoryProperties repositoryProperties; + private final Map lastDynamicGroupFill = new ConcurrentHashMap<>(); public JpaRolloutExecutor( final ActionRepository actionRepository, final RolloutGroupRepository rolloutGroupRepository, @@ -158,48 +155,48 @@ public class JpaRolloutExecutor implements RolloutExecutor { log.debug("Processing rollout {}", rollout.getId()); switch (rollout.getStatus()) { - case CREATING: - handleCreateRollout((JpaRollout) rollout); - break; - case READY: - handleReadyRollout(rollout); - break; - case STARTING: - // the lastModifiedBy user is probably the user that has actually called the rollout start (unless overridden) - not the creator - SpringSecurityAuditorAware.setAuditorOverride(rollout.getLastModifiedBy()); - try { - handleStartingRollout(rollout); - } finally { - // clear, ALWAYS, the set auditor override - SpringSecurityAuditorAware.clearAuditorOverride(); - } - break; - case RUNNING: - handleRunningRollout((JpaRollout) rollout); - break; - case STOPPING: - // the lastModifiedBy user is probably the user that has actually called the rollout stop (unless overridden) - not the creator - SpringSecurityAuditorAware.setAuditorOverride(rollout.getLastModifiedBy()); - try { - handleStopRollout((JpaRollout) rollout); - } finally { - // clear, ALWAYS, the set auditor override - SpringSecurityAuditorAware.clearAuditorOverride(); - } - break; - case DELETING: - // the lastModifiedBy user is probably the user that has actually called the rollout delete (unless overridden) - not the creator - SpringSecurityAuditorAware.setAuditorOverride(rollout.getLastModifiedBy()); - try { - handleDeleteRollout((JpaRollout) rollout); - } finally { - // clear, ALWAYS, the set auditor override - SpringSecurityAuditorAware.clearAuditorOverride(); - } - break; - default: - log.error("Rollout in status {} not supposed to be handled!", rollout.getStatus()); - break; + case CREATING: + handleCreateRollout((JpaRollout) rollout); + break; + case READY: + handleReadyRollout(rollout); + break; + case STARTING: + // the lastModifiedBy user is probably the user that has actually called the rollout start (unless overridden) - not the creator + SpringSecurityAuditorAware.setAuditorOverride(rollout.getLastModifiedBy()); + try { + handleStartingRollout(rollout); + } finally { + // clear, ALWAYS, the set auditor override + SpringSecurityAuditorAware.clearAuditorOverride(); + } + break; + case RUNNING: + handleRunningRollout((JpaRollout) rollout); + break; + case STOPPING: + // the lastModifiedBy user is probably the user that has actually called the rollout stop (unless overridden) - not the creator + SpringSecurityAuditorAware.setAuditorOverride(rollout.getLastModifiedBy()); + try { + handleStopRollout((JpaRollout) rollout); + } finally { + // clear, ALWAYS, the set auditor override + SpringSecurityAuditorAware.clearAuditorOverride(); + } + break; + case DELETING: + // the lastModifiedBy user is probably the user that has actually called the rollout delete (unless overridden) - not the creator + SpringSecurityAuditorAware.setAuditorOverride(rollout.getLastModifiedBy()); + try { + handleDeleteRollout((JpaRollout) rollout); + } finally { + // clear, ALWAYS, the set auditor override + SpringSecurityAuditorAware.clearAuditorOverride(); + } + break; + default: + log.error("Rollout in status {} not supposed to be handled!", rollout.getStatus()); + break; } log.debug("Rollout {} processed", rollout.getId()); @@ -312,9 +309,9 @@ public class JpaRolloutExecutor implements RolloutExecutor { rolloutGroupRepository.findByRolloutAndStatusNotIn(rollout, Arrays.asList(RolloutGroupStatus.FINISHED, RolloutGroupStatus.ERROR)).forEach(rolloutGroup -> { - rolloutGroup.setStatus(RolloutGroupStatus.FINISHED); - rolloutGroupRepository.save(rolloutGroup); - }); + rolloutGroup.setStatus(RolloutGroupStatus.FINISHED); + rolloutGroupRepository.save(rolloutGroup); + }); rollout.setStatus(RolloutStatus.FINISHED); rolloutRepository.save(rollout); @@ -417,7 +414,6 @@ public class JpaRolloutExecutor implements RolloutExecutor { return groupsActiveLeft == 0; } - private static final Comparator DESC_COMP = Comparator.comparingLong(RolloutGroup::getId).reversed(); private void executeLatestRolloutGroup(final JpaRollout rollout) { // was - rolloutGroupRepository.findByRolloutAndStatusNotOrderByIdDesc(rollout, RolloutGroupStatus.SCHEDULED); final List latestRolloutGroup = rollout.getRolloutGroups().stream() @@ -435,10 +431,10 @@ public class JpaRolloutExecutor implements RolloutExecutor { // so the evaluation to use total targets to properly private RolloutGroup evalProxy(final RolloutGroup group) { if (group.isDynamic()) { - final int expected = Math.max((int)group.getTargetPercentage(), 1); + final int expected = Math.max((int) group.getTargetPercentage(), 1); return (RolloutGroup) Proxy.newProxyInstance( RolloutGroup.class.getClassLoader(), - new Class[] {RolloutGroup.class}, + new Class[] { RolloutGroup.class }, (proxy, method, args) -> { if ("getTotalTargets".equals(method.getName())) { return expected; @@ -601,14 +597,14 @@ public class JpaRolloutExecutor implements RolloutExecutor { long targetsInGroupFilter; if (!RolloutHelper.isRolloutRetried(rollout.getTargetFilterQuery())) { targetsInGroupFilter = DeploymentHelper.runInNewTransaction(txManager, - "countAllTargetsByTargetFilterQueryAndNotInRolloutGroups", - count -> targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(readyGroups, - groupTargetFilter, rollout.getDistributionSet().getType())); + "countAllTargetsByTargetFilterQueryAndNotInRolloutGroups", + count -> targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(readyGroups, + groupTargetFilter, rollout.getDistributionSet().getType())); } else { targetsInGroupFilter = DeploymentHelper.runInNewTransaction(txManager, - "countByFailedRolloutAndNotInRolloutGroupsAndCompatible", - count -> targetManagement.countByFailedRolloutAndNotInRolloutGroups(readyGroups, - RolloutHelper.getIdFromRetriedTargetFilter(rollout.getTargetFilterQuery()))); + "countByFailedRolloutAndNotInRolloutGroupsAndCompatible", + count -> targetManagement.countByFailedRolloutAndNotInRolloutGroups(readyGroups, + RolloutHelper.getIdFromRetriedTargetFilter(rollout.getTargetFilterQuery()))); } final double percentFromTheRest; @@ -677,7 +673,6 @@ public class JpaRolloutExecutor implements RolloutExecutor { }); } - private final Map lastDynamicGroupFill = new ConcurrentHashMap<>(); // return if group change is made private boolean fillDynamicRolloutGroupsWithTargets(final JpaRollout rollout) { final AtomicLong lastFill = lastDynamicGroupFill.computeIfAbsent(rollout.getId(), id -> new AtomicLong(0)); @@ -690,9 +685,9 @@ public class JpaRolloutExecutor implements RolloutExecutor { RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.RUNNING); final List rolloutGroups = rollout.getRolloutGroups(); - final JpaRolloutGroup group = (JpaRolloutGroup)rolloutGroups.get(rolloutGroups.size() - 1); + final JpaRolloutGroup group = (JpaRolloutGroup) rolloutGroups.get(rolloutGroups.size() - 1); - final long expectedInGroup = Math.max((int)group.getTargetPercentage(), 1); + final long expectedInGroup = Math.max((int) group.getTargetPercentage(), 1); final long currentlyInGroup = group.getTotalTargets(); if (currentlyInGroup >= expectedInGroup || group.getStatus() == RolloutGroupStatus.FINISHED) { // the last one is full. create new and start filling it on the next iteration @@ -741,7 +736,8 @@ public class JpaRolloutExecutor implements RolloutExecutor { return false; } - private void createDynamicGroup(final JpaRollout rollout, final RolloutGroup lastGroup, final int groupCount, final RolloutGroupStatus status) { + private void createDynamicGroup(final JpaRollout rollout, final RolloutGroup lastGroup, final int groupCount, + final RolloutGroupStatus status) { try { RolloutHelper.verifyRolloutGroupAmount(groupCount + 1, quotaManagement); } catch (final AssignmentQuotaExceededException e) { @@ -755,7 +751,8 @@ public class JpaRolloutExecutor implements RolloutExecutor { final JpaRolloutGroup group = new JpaRolloutGroup(); final String lastGroupWithoutSuffix = "group-" + groupCount; - final String suffix = lastGroup.getName().startsWith(lastGroupWithoutSuffix) ? lastGroup.getName().substring(lastGroupWithoutSuffix.length()) : ""; + final String suffix = lastGroup.getName().startsWith(lastGroupWithoutSuffix) ? lastGroup.getName() + .substring(lastGroupWithoutSuffix.length()) : ""; final String nameAndDesc = "group-" + (groupCount + 1) + suffix; group.setName(nameAndDesc); group.setDescription(nameAndDesc); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHandler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHandler.java index 05b2b93ef..0f4277ce4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHandler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutHandler.java @@ -37,17 +37,12 @@ public class JpaRolloutHandler implements RolloutHandler { /** * Constructor - * - * @param tenantAware - * the {@link TenantAware} bean holding the tenant information - * @param rolloutManagement - * to fetch rollout related information from the datasource - * @param rolloutExecutor - * to trigger executions for a specific rollout - * @param lockRegistry - * to lock processes - * @param txManager - * transaction manager interface + * + * @param tenantAware the {@link TenantAware} bean holding the tenant information + * @param rolloutManagement to fetch rollout related information from the datasource + * @param rolloutExecutor to trigger executions for a specific rollout + * @param lockRegistry to lock processes + * @param txManager transaction manager interface */ public JpaRolloutHandler(final TenantAware tenantAware, final RolloutManagement rolloutManagement, final RolloutExecutor rolloutExecutor, final LockRegistry lockRegistry, @@ -83,8 +78,9 @@ public class JpaRolloutHandler implements RolloutHandler { try { handleRolloutInNewTransaction(rolloutId, handlerId); } catch (final Throwable throwable) { - log.error("Failed to process rollout with id {}", rolloutId , throwable); - }}); + log.error("Failed to process rollout with id {}", rolloutId, throwable); + } + }); log.debug("Finished handling of the rollouts."); } finally { if (log.isTraceEnabled()) { @@ -107,17 +103,17 @@ public class JpaRolloutHandler implements RolloutHandler { // auditor is retrieved and set on transaction commit // if not overridden, the system user will be the auditor rollout.getAccessControlContext().ifPresentOrElse( - context -> // has stored context - executes it with it - contextAware.runInContext( - context, - () -> rolloutExecutor.execute(rollout)), - () -> // has no stored context - executes it in the tenant & user scope - contextAware.runAsTenantAsUser( - contextAware.getCurrentTenant(), - rollout.getCreatedBy(), () -> { - rolloutExecutor.execute(rollout); - return null; - }) + context -> // has stored context - executes it with it + contextAware.runInContext( + context, + () -> rolloutExecutor.execute(rollout)), + () -> // has no stored context - executes it in the tenant & user scope + contextAware.runAsTenantAsUser( + contextAware.getCurrentTenant(), + rollout.getCreatedBy(), () -> { + rolloutExecutor.execute(rollout); + return null; + }) ); }, () -> log.error("Could not retrieve rollout with id {}. Will not continue with execution.", diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java index 89d0ba309..be9248de2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java @@ -14,8 +14,9 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; -import jakarta.persistence.EntityManager; import javax.sql.DataSource; + +import jakarta.persistence.EntityManager; import jakarta.validation.Validation; import org.eclipse.hawkbit.ContextAware; @@ -120,11 +121,11 @@ import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetMetadataRepo import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTypeRepository; +import org.eclipse.hawkbit.repository.jpa.repository.HawkBitBaseRepository; import org.eclipse.hawkbit.repository.jpa.repository.LocalArtifactRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutTargetGroupRepository; -import org.eclipse.hawkbit.repository.jpa.repository.HawkBitBaseRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleMetadataRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepository; @@ -155,9 +156,9 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; import org.eclipse.hawkbit.repository.model.helper.SystemManagementHolder; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder; +import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder; import org.eclipse.hawkbit.repository.rsql.RsqlValidationOracle; import org.eclipse.hawkbit.repository.rsql.RsqlVisitorFactory; -import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.SecurityTokenGenerator; @@ -202,7 +203,6 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess /** * General configuration for hawkBit's Repository. - * */ @EnableJpaRepositories(value = "org.eclipse.hawkbit.repository.jpa.repository", repositoryFactoryBeanClass = CustomBaseRepositoryFactoryBean.class) @EnableTransactionManagement @@ -223,10 +223,110 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { super(dataSource, properties, jtaTransactionManagerProvider); } + /** + * Defines the validation processor bean. + * + * @return the {@link MethodValidationPostProcessor} + */ + @Bean + public MethodValidationPostProcessor methodValidationPostProcessor() { + final MethodValidationPostProcessor processor = new MethodValidationPostProcessor(); + // ValidatorFactory shall NOT be closed because after closing the generated Validator + // methods shall not be called - we need the validator in future + processor.setValidator(Validation.byDefaultProvider().configure() + .addProperty(BaseHibernateValidatorConfiguration.ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS, + "true") + .buildValidatorFactory().getValidator()); + return processor; + } + + /** + * {@link MultiTenantJpaTransactionManager} bean. + * + * @return a new {@link PlatformTransactionManager} + * @see org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#transactionManager(ObjectProvider) + */ + @Override + @Bean + public PlatformTransactionManager transactionManager( + final ObjectProvider transactionManagerCustomizers) { + return new MultiTenantJpaTransactionManager(); + } + + @Override + protected AbstractJpaVendorAdapter createJpaVendorAdapter() { + return new EclipseLinkJpaVendorAdapter() { + + private final HawkBitEclipseLinkJpaDialect jpaDialect = new HawkBitEclipseLinkJpaDialect(); + + @Override + public EclipseLinkJpaDialect getJpaDialect() { + return jpaDialect; + } + }; + } + + @Override + protected Map getVendorProperties() { + final Map properties = new HashMap<>(7); + // Turn off dynamic weaving to disable LTW lookup in static weaving mode + properties.put(PersistenceUnitProperties.WEAVING, "false"); + // needed for reports + properties.put(PersistenceUnitProperties.ALLOW_NATIVE_SQL_QUERIES, "true"); + // flyway + properties.put(PersistenceUnitProperties.DDL_GENERATION, "none"); + // Embed into hawkBit logging + properties.put(PersistenceUnitProperties.LOGGING_LOGGER, "JavaLogger"); + // Ensure that we flush only at the end of the transaction + properties.put(PersistenceUnitProperties.PERSISTENCE_CONTEXT_FLUSH_MODE, "COMMIT"); + // Enable batch writing + properties.put(PersistenceUnitProperties.BATCH_WRITING, "JDBC"); + // Batch size + properties.put(PersistenceUnitProperties.BATCH_WRITING_SIZE, "500"); + return properties; + } + + @Bean + public BeanPostProcessor entityManagerBeanPostProcessor( + @Autowired(required = false) final AccessController artifactAccessController, + @Autowired(required = false) final AccessController softwareModuleTypeAccessController, + @Autowired(required = false) final AccessController softwareModuleAccessController, + @Autowired(required = false) final AccessController distributionSetTypeAccessController, + @Autowired(required = false) final AccessController distributionSetAccessController, + @Autowired(required = false) final AccessController targetTypeAccessControlManager, + @Autowired(required = false) final AccessController targetAccessControlManager, + @Autowired(required = false) final AccessController actionAccessController) { + return new BeanPostProcessor() { + + @Override + public Object postProcessAfterInitialization(@NonNull final Object bean, @NonNull final String beanName) + throws BeansException { + if (bean instanceof LocalArtifactRepository repo) { + return repo.withACM(artifactAccessController); + } else if (bean instanceof SoftwareModuleTypeRepository repo) { + return repo.withACM(softwareModuleTypeAccessController); + } else if (bean instanceof SoftwareModuleRepository repo) { + return repo.withACM(softwareModuleAccessController); + } else if (bean instanceof DistributionSetTypeRepository repo) { + return repo.withACM(distributionSetTypeAccessController); + } else if (bean instanceof DistributionSetRepository repo) { + return repo.withACM(distributionSetAccessController); + } else if (bean instanceof TargetTypeRepository repo) { + return repo.withACM(targetTypeAccessControlManager); + } else if (bean instanceof TargetRepository repo) { + return repo.withACM(targetAccessControlManager); + } else if (bean instanceof ActionRepository repo) { + return repo.withACM(actionAccessController); + } + return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); + } + }; + } + @Bean @ConditionalOnMissingBean PauseRolloutGroupAction pauseRolloutGroupAction(final RolloutManagement rolloutManagement, - final RolloutGroupRepository rolloutGroupRepository, final SystemSecurityContext systemSecurityContext) { + final RolloutGroupRepository rolloutGroupRepository, final SystemSecurityContext systemSecurityContext) { return new PauseRolloutGroupAction(rolloutManagement, rolloutGroupRepository, systemSecurityContext); } @@ -299,10 +399,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { } /** - * @param distributionSetTypeManagement - * to loading the {@link DistributionSetType} - * @param softwareManagement - * for loading {@link DistributionSet#getModules()} + * @param distributionSetTypeManagement to loading the {@link DistributionSetType} + * @param softwareManagement for loading {@link DistributionSet#getModules()} * @return DistributionSetBuilder bean */ @Bean @@ -317,8 +415,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { } /** - * @param dsTypeManagement - * for loading {@link TargetType#getCompatibleDistributionSetTypes()} + * @param dsTypeManagement for loading {@link TargetType#getCompatibleDistributionSetTypes()} * @return TargetTypeBuilder bean */ @Bean @@ -333,9 +430,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { } /** - * @param softwareModuleTypeManagement - * for loading {@link DistributionSetType#getMandatoryModuleTypes()} - * and {@link DistributionSetType#getOptionalModuleTypes()} + * @param softwareModuleTypeManagement for loading {@link DistributionSetType#getMandatoryModuleTypes()} + * and {@link DistributionSetType#getOptionalModuleTypes()} * @return DistributionSetTypeBuilder bean */ @Bean @@ -345,8 +441,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { } /** - * @param softwareModuleTypeManagement - * for loading {@link SoftwareModule#getType()} + * @param softwareModuleTypeManagement for loading {@link SoftwareModule#getType()} * @return SoftwareModuleBuilder bean */ @Bean @@ -355,8 +450,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { } /** - * @param distributionSetManagement - * for loading {@link Rollout#getDistributionSet()} + * @param distributionSetManagement for loading {@link Rollout#getDistributionSet()} * @return RolloutBuilder bean */ @Bean @@ -365,9 +459,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { } /** - * @param distributionSetManagement - * for loading - * {@link TargetFilterQuery#getAutoAssignDistributionSet()} + * @param distributionSetManagement for loading + * {@link TargetFilterQuery#getAutoAssignDistributionSet()} * @return TargetFilterQueryBuilder bean */ @Bean @@ -434,7 +527,6 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { } /** - * * @return the singleton instance of the * {@link AfterTransactionCommitExecutorHolder} */ @@ -443,23 +535,6 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { return AfterTransactionCommitExecutorHolder.getInstance(); } - /** - * Defines the validation processor bean. - * - * @return the {@link MethodValidationPostProcessor} - */ - @Bean - public MethodValidationPostProcessor methodValidationPostProcessor() { - final MethodValidationPostProcessor processor = new MethodValidationPostProcessor(); - // ValidatorFactory shall NOT be closed because after closing the generated Validator - // methods shall not be called - we need the validator in future - processor.setValidator(Validation.byDefaultProvider().configure() - .addProperty(BaseHibernateValidatorConfiguration.ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS, - "true") - .buildValidatorFactory().getValidator()); - return processor; - } - /** * @return {@link ExceptionMappingAspectHandler} aspect bean */ @@ -468,51 +543,6 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { return new ExceptionMappingAspectHandler(); } - @Override - protected AbstractJpaVendorAdapter createJpaVendorAdapter() { - return new EclipseLinkJpaVendorAdapter() { - private final HawkBitEclipseLinkJpaDialect jpaDialect = new HawkBitEclipseLinkJpaDialect(); - - @Override - public EclipseLinkJpaDialect getJpaDialect() { - return jpaDialect; - } - }; - } - - @Override - protected Map getVendorProperties() { - final Map properties = new HashMap<>(7); - // Turn off dynamic weaving to disable LTW lookup in static weaving mode - properties.put(PersistenceUnitProperties.WEAVING, "false"); - // needed for reports - properties.put(PersistenceUnitProperties.ALLOW_NATIVE_SQL_QUERIES, "true"); - // flyway - properties.put(PersistenceUnitProperties.DDL_GENERATION, "none"); - // Embed into hawkBit logging - properties.put(PersistenceUnitProperties.LOGGING_LOGGER, "JavaLogger"); - // Ensure that we flush only at the end of the transaction - properties.put(PersistenceUnitProperties.PERSISTENCE_CONTEXT_FLUSH_MODE, "COMMIT"); - // Enable batch writing - properties.put(PersistenceUnitProperties.BATCH_WRITING, "JDBC"); - // Batch size - properties.put(PersistenceUnitProperties.BATCH_WRITING_SIZE, "500"); - return properties; - } - - /** - * {@link MultiTenantJpaTransactionManager} bean. - * - * @see org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#transactionManager(ObjectProvider) - * @return a new {@link PlatformTransactionManager} - */ - @Override - @Bean - public PlatformTransactionManager transactionManager( - final ObjectProvider transactionManagerCustomizers) { - return new MultiTenantJpaTransactionManager(); - } - /** * {@link JpaSystemManagement} bean. * @@ -614,13 +644,13 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { @Bean @ConditionalOnMissingBean TargetManagement targetManagement(final EntityManager entityManager, final QuotaManagement quotaManagement, - final TargetRepository targetRepository, final TargetMetadataRepository targetMetadataRepository, - final RolloutGroupRepository rolloutGroupRepository, - final TargetFilterQueryRepository targetFilterQueryRepository, - final TargetTypeRepository targetTypeRepository, final TargetTagRepository targetTagRepository, - final EventPublisherHolder eventPublisherHolder, final TenantAware tenantAware, - final VirtualPropertyReplacer virtualPropertyReplacer, - final JpaProperties properties, final DistributionSetManagement distributionSetManagement) { + final TargetRepository targetRepository, final TargetMetadataRepository targetMetadataRepository, + final RolloutGroupRepository rolloutGroupRepository, + final TargetFilterQueryRepository targetFilterQueryRepository, + final TargetTypeRepository targetTypeRepository, final TargetTagRepository targetTagRepository, + final EventPublisherHolder eventPublisherHolder, final TenantAware tenantAware, + final VirtualPropertyReplacer virtualPropertyReplacer, + final JpaProperties properties, final DistributionSetManagement distributionSetManagement) { return new JpaTargetManagement(entityManager, distributionSetManagement, quotaManagement, targetRepository, targetTypeRepository, targetMetadataRepository, rolloutGroupRepository, targetFilterQueryRepository, targetTagRepository, eventPublisherHolder, tenantAware, virtualPropertyReplacer, @@ -630,19 +660,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { /** * {@link JpaTargetFilterQueryManagement} bean. * - * @param targetFilterQueryRepository - * holding {@link TargetFilterQuery} entities - * @param targetManagement - * managing {@link Target} entities - * @param virtualPropertyReplacer - * for RSQL handling - * @param distributionSetManagement - * for auto assign DS access - * @param quotaManagement - * to access quotas - * @param properties - * JPA properties - * + * @param targetFilterQueryRepository holding {@link TargetFilterQuery} entities + * @param targetManagement managing {@link Target} entities + * @param virtualPropertyReplacer for RSQL handling + * @param distributionSetManagement for auto assign DS access + * @param quotaManagement to access quotas + * @param properties JPA properties * @return a new {@link TargetFilterQueryManagement} */ @Bean @@ -659,7 +682,6 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { tenantConfigurationManagement, repositoryProperties, systemSecurityContext, contextAware, auditorAware); } - /** * {@link JpaTargetTagManagement} bean. * @@ -792,10 +814,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { @Bean @ConditionalOnMissingBean RolloutGroupManagement rolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository, - final RolloutRepository rolloutRepository, final ActionRepository actionRepository, - final TargetRepository targetRepository, final EntityManager entityManager, - final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache, - final JpaProperties properties) { + final RolloutRepository rolloutRepository, final ActionRepository actionRepository, + final TargetRepository targetRepository, final EntityManager entityManager, + final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache, + final JpaProperties properties) { return new JpaRolloutGroupManagement(rolloutGroupRepository, rolloutRepository, actionRepository, targetRepository, entityManager, virtualPropertyReplacer, rolloutStatusCache, properties.getDatabase()); } @@ -808,15 +830,16 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { @Bean @ConditionalOnMissingBean DeploymentManagement deploymentManagement(final EntityManager entityManager, - final ActionRepository actionRepository, - final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository, - final ActionStatusRepository actionStatusRepository, final AuditorAware auditorProvider, - final EventPublisherHolder eventPublisherHolder, final AfterTransactionCommitExecutor afterCommit, - final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager, - final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement, - final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final AuditorAware auditorAware, - final JpaProperties properties, final RepositoryProperties repositoryProperties) { - return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetManagement, targetRepository, actionStatusRepository, auditorProvider, + final ActionRepository actionRepository, + final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository, + final ActionStatusRepository actionStatusRepository, final AuditorAware auditorProvider, + final EventPublisherHolder eventPublisherHolder, final AfterTransactionCommitExecutor afterCommit, + final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager, + final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement, + final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final AuditorAware auditorAware, + final JpaProperties properties, final RepositoryProperties repositoryProperties) { + return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetManagement, targetRepository, actionStatusRepository, + auditorProvider, eventPublisherHolder, afterCommit, virtualPropertyReplacer, txManager, tenantConfigurationManagement, quotaManagement, systemSecurityContext, tenantAware, auditorAware, properties.getDatabase(), repositoryProperties); } @@ -880,10 +903,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { /** * {@link EventEntityManager} bean. * - * @param aware - * the tenant aware - * @param entityManager - * the entity manager + * @param aware the tenant aware + * @param entityManager the entity manager * @return a new {@link EventEntityManager} */ @Bean @@ -895,14 +916,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { /** * {@link AutoAssignChecker} bean. * - * @param targetFilterQueryManagement - * to get all target filter queries - * @param targetManagement - * to get targets - * @param deploymentManagement - * to assign distribution sets to targets - * @param transactionManager - * to run transactions + * @param targetFilterQueryManagement to get all target filter queries + * @param targetManagement to get targets + * @param deploymentManagement to assign distribution sets to targets + * @param transactionManager to run transactions * @return a new {@link AutoAssignChecker} */ @Bean @@ -920,14 +937,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { * Note: does not activate in test profile, otherwise it is hard to test the * auto assign functionality. * - * @param systemManagement - * to find all tenants - * @param systemSecurityContext - * to run as system - * @param autoAssignExecutor - * to run a check as tenant - * @param lockRegistry - * to lock the tenant for auto assignment + * @param systemManagement to find all tenants + * @param systemSecurityContext to run as system + * @param autoAssignExecutor to run a check as tenant + * @param lockRegistry to lock the tenant for auto assignment * @return a new {@link AutoAssignChecker} */ @Bean @@ -945,11 +958,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { /** * {@link AutoActionCleanup} bean. * - * @param deploymentManagement - * Deployment management service - * @param configManagement - * Tenant configuration service - * + * @param deploymentManagement Deployment management service + * @param configManagement Tenant configuration service * @return a new {@link AutoActionCleanup} bean */ @Bean @@ -961,15 +971,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { /** * {@link AutoCleanupScheduler} bean. * - * @param systemManagement - * to find all tenants - * @param systemSecurityContext - * to run as system - * @param lockRegistry - * to lock the tenant for auto assignment - * @param cleanupTasks - * a list of cleanup tasks - * + * @param systemManagement to find all tenants + * @param systemSecurityContext to run as system + * @param lockRegistry to lock the tenant for auto assignment + * @param cleanupTasks a list of cleanup tasks * @return a new {@link AutoCleanupScheduler} bean */ @Bean @@ -988,12 +993,9 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { * Note: does not activate in test profile, otherwise it is hard to test the * rollout handling functionality. * - * @param systemManagement - * to find all tenants - * @param rolloutHandler - * to run the rollout handler - * @param systemSecurityContext - * to run as system + * @param systemManagement to find all tenants + * @param rolloutHandler to run the rollout handler + * @param systemSecurityContext to run as system * @return a new {@link RolloutScheduler} bean. */ @Bean @@ -1069,40 +1071,4 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { ArtifactEncryptionService artifactEncryptionService() { return ArtifactEncryptionService.getInstance(); } - - @Bean - public BeanPostProcessor entityManagerBeanPostProcessor( - @Autowired(required = false) final AccessController artifactAccessController, - @Autowired(required = false) final AccessController softwareModuleTypeAccessController, - @Autowired(required = false) final AccessController softwareModuleAccessController, - @Autowired(required = false) final AccessController distributionSetTypeAccessController, - @Autowired(required = false) final AccessController distributionSetAccessController, - @Autowired(required = false) final AccessController targetTypeAccessControlManager, - @Autowired(required = false) final AccessController targetAccessControlManager, - @Autowired(required = false) final AccessController actionAccessController) { - return new BeanPostProcessor() { - @Override - public Object postProcessAfterInitialization(@NonNull final Object bean, @NonNull final String beanName) - throws BeansException { - if (bean instanceof LocalArtifactRepository repo) { - return repo.withACM(artifactAccessController); - } else if (bean instanceof SoftwareModuleTypeRepository repo) { - return repo.withACM(softwareModuleTypeAccessController); - } else if (bean instanceof SoftwareModuleRepository repo) { - return repo.withACM(softwareModuleAccessController); - } else if (bean instanceof DistributionSetTypeRepository repo) { - return repo.withACM(distributionSetTypeAccessController); - } else if (bean instanceof DistributionSetRepository repo) { - return repo.withACM(distributionSetAccessController); - } else if (bean instanceof TargetTypeRepository repo) { - return repo.withACM(targetTypeAccessControlManager); - } else if (bean instanceof TargetRepository repo) { - return repo.withACM(targetAccessControlManager); - } else if (bean instanceof ActionRepository repo) { - return repo.withACM(actionAccessController); - } - return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); - } - }; - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SystemManagementCacheKeyGenerator.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SystemManagementCacheKeyGenerator.java index ffe36abff..1060e3049 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SystemManagementCacheKeyGenerator.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SystemManagementCacheKeyGenerator.java @@ -26,26 +26,10 @@ import org.springframework.context.annotation.Bean; */ public class SystemManagementCacheKeyGenerator implements CurrentTenantCacheKeyGenerator { + private final ThreadLocal createInitialTenant = new ThreadLocal<>(); @Autowired private TenantAware tenantAware; - private final ThreadLocal createInitialTenant = new ThreadLocal<>(); - - /** - * An implementation of the {@link KeyGenerator} to generate a key based on - * either the {@code createInitialTenant} thread local and the - * {@link TenantAware}, but in case we are in a tenant creation with its default - * types we need to use as the tenant the current tenant which is currently - * created and not the one currently in the {@link TenantAware}. - */ - public class CurrentTenantKeyGenerator implements KeyGenerator { - @Override - public Object generate(final Object target, final Method method, final Object... params) { - String tenant = getTenantInCreation().orElseGet(() -> tenantAware.getCurrentTenant()).toUpperCase(); - return SimpleKeyGenerator.generateKey(tenant, tenant); - } - } - @Override @Bean public KeyGenerator currentTenantKeyGenerator() { @@ -55,7 +39,7 @@ public class SystemManagementCacheKeyGenerator implements CurrentTenantCacheKeyG /** * Get the tenant which overwrites the actual tenant used by the * {@linkplain #currentTenantKeyGenerator()}. - * + * * @return A present optional in case that there is a tenant in the progress of * creation. */ @@ -66,9 +50,8 @@ public class SystemManagementCacheKeyGenerator implements CurrentTenantCacheKeyG /** * Overwrite the tenant used by the key generator in case that the tenant is in * the process of creation. - * - * @param tenant - * the tenant which should be used instead of the actual one. + * + * @param tenant the tenant which should be used instead of the actual one. */ public void setTenantInCreation(@NotNull String tenant) { createInitialTenant.set(Objects.requireNonNull(tenant)); @@ -81,4 +64,20 @@ public class SystemManagementCacheKeyGenerator implements CurrentTenantCacheKeyG public void removeTenantInCreation() { createInitialTenant.remove(); } + + /** + * An implementation of the {@link KeyGenerator} to generate a key based on + * either the {@code createInitialTenant} thread local and the + * {@link TenantAware}, but in case we are in a tenant creation with its default + * types we need to use as the tenant the current tenant which is currently + * created and not the one currently in the {@link TenantAware}. + */ + public class CurrentTenantKeyGenerator implements KeyGenerator { + + @Override + public Object generate(final Object target, final Method method, final Object... params) { + String tenant = getTenantInCreation().orElseGet(() -> tenantAware.getCurrentTenant()).toUpperCase(); + return SimpleKeyGenerator.generateKey(tenant, tenant); + } + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantKeyGenerator.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantKeyGenerator.java index 813de05c0..29b0655ae 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantKeyGenerator.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantKeyGenerator.java @@ -18,7 +18,6 @@ import org.springframework.stereotype.Service; /** * {@link KeyGenerator} for tenant related caches. - * */ @Service public class TenantKeyGenerator implements KeyGenerator { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/acm/AccessController.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/acm/AccessController.java index 4cbdf3a5a..1cc10c022 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/acm/AccessController.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/acm/AccessController.java @@ -24,7 +24,7 @@ import org.springframework.lang.Nullable; * additional restrictions (e.g. entity based) could be applied. *

* Note: Experimental, only - * + * * @param the domain type the repository manages */ public interface AccessController { @@ -33,16 +33,15 @@ public interface AccessController { * Introduce a new specification to limit the access to a specific entity. * * @return a new specification limiting the access, if empty no access restrictions - * are to be applied + * are to be applied */ Optional> getAccessRules(Operation operation); /** * Append the resource limitation on an already existing specification. - * - * @param specification - * is the root specification which needs to be appended by the - * resource limitation + * + * @param specification is the root specification which needs to be appended by the + * resource limitation * @return a new appended specification */ @Nullable @@ -55,18 +54,17 @@ public interface AccessController { /** * Verify if the given {@link Operation} is permitted for the provided entity. * - * @throws InsufficientPermissionException - * if operation is not permitted for given entities + * @throws InsufficientPermissionException if operation is not permitted for given entities */ void assertOperationAllowed(final Operation operation, final T entity) throws InsufficientPermissionException; /** * Verify if the given {@link Operation} is permitted for the provided entities. * - * @throws InsufficientPermissionException - * if operation is not permitted for given entities + * @throws InsufficientPermissionException if operation is not permitted for given entities */ - default void assertOperationAllowed(final Operation operation, final Iterable entities) throws InsufficientPermissionException { + default void assertOperationAllowed(final Operation operation, final Iterable entities) + throws InsufficientPermissionException { for (final T entity : entities) { assertOperationAllowed(operation, entity); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java index e0c57a634..9788376ee 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java @@ -68,8 +68,7 @@ public class ExceptionMappingAspectHandler implements Ordered { * catch exceptions of the {@link TransactionManager} and wrap them to * custom exceptions. * - * @param ex - * the thrown and catched exception + * @param ex the thrown and catched exception * @throws Throwable */ @AfterThrowing(pointcut = "execution( * org.eclipse.hawkbit.repository.jpa.management.*Management.*(..))", throwing = "ex") @@ -103,6 +102,11 @@ public class ExceptionMappingAspectHandler implements Ordered { throw ex; } + @Override + public int getOrder() { + return 1; + } + private static Exception replaceWithCauseIfConstraintViolationException(final TransactionSystemException rex) { Throwable exception = rex; do { @@ -115,9 +119,4 @@ public class ExceptionMappingAspectHandler implements Ordered { return rex; } - - @Override - public int getOrder() { - return 1; - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AbstractAutoAssignExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AbstractAutoAssignExecutor.java index 3e23fb0a5..44ab49f0c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AbstractAutoAssignExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AbstractAutoAssignExecutor.java @@ -56,15 +56,11 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { /** * Constructor - * - * @param targetFilterQueryManagement - * to get all target filter queries - * @param deploymentManagement - * to assign distribution sets to targets - * @param transactionManager - * to run transactions - * @param contextAware - * to handle the context + * + * @param targetFilterQueryManagement to get all target filter queries + * @param deploymentManagement to assign distribution sets to targets + * @param transactionManager to run transactions + * @param contextAware to handle the context */ protected AbstractAutoAssignExecutor(final TargetFilterQueryManagement targetFilterQueryManagement, final DeploymentManagement deploymentManagement, final PlatformTransactionManager transactionManager, @@ -75,6 +71,12 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { this.contextAware = contextAware; } + protected static String getAutoAssignmentInitiatedBy(final TargetFilterQuery targetFilterQuery) { + return StringUtils.hasText(targetFilterQuery.getAutoAssignInitiatedBy()) + ? targetFilterQuery.getAutoAssignInitiatedBy() + : targetFilterQuery.getCreatedBy(); + } + protected DeploymentManagement getDeploymentManagement() { return deploymentManagement; } @@ -100,17 +102,17 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { filterQueries.forEach(filterQuery -> { try { filterQuery.getAccessControlContext().ifPresentOrElse( - context -> // has stored context - executes it with it - contextAware.runInContext( - context, - () -> consumer.accept(filterQuery)), - () -> // has no stored context - executes it in the tenant & user scope - contextAware.runAsTenantAsUser( - contextAware.getCurrentTenant(), - getAutoAssignmentInitiatedBy(filterQuery), () -> { - consumer.accept(filterQuery); - return null; - }) + context -> // has stored context - executes it with it + contextAware.runInContext( + context, + () -> consumer.accept(filterQuery)), + () -> // has no stored context - executes it in the tenant & user scope + contextAware.runAsTenantAsUser( + contextAware.getCurrentTenant(), + getAutoAssignmentInitiatedBy(filterQuery), () -> { + consumer.accept(filterQuery); + return null; + }) ); } catch (final RuntimeException ex) { log.debug( @@ -128,11 +130,9 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { /** * Runs target assignments within a dedicated transaction for a given list of * controllerIDs - * - * @param targetFilterQuery - * the target filter query - * @param controllerIds - * the controllerIDs + * + * @param targetFilterQuery the target filter query + * @param controllerIds the controllerIDs * @return count of targets */ protected int runTransactionalAssignment(final TargetFilterQuery targetFilterQuery, @@ -158,10 +158,8 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { * Creates a list of {@link DeploymentRequest} for given list of controllerIds * and {@link TargetFilterQuery} * - * @param controllerIds - * list of controllerIds - * @param filterQuery - * the query the targets have to match + * @param controllerIds list of controllerIds + * @param filterQuery the query the targets have to match * @return list of deployment request */ protected List mapToDeploymentRequests(final List controllerIds, @@ -179,10 +177,4 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor { .setConfirmationRequired(filterQuery.isConfirmationRequired()).build()) .toList(); } - - protected static String getAutoAssignmentInitiatedBy(final TargetFilterQuery targetFilterQuery) { - return StringUtils.hasText(targetFilterQuery.getAutoAssignInitiatedBy()) - ? targetFilterQuery.getAutoAssignInitiatedBy() - : targetFilterQuery.getCreatedBy(); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java index 37bb100a2..2bbe35ab6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java @@ -43,16 +43,11 @@ public class AutoAssignChecker extends AbstractAutoAssignExecutor { /** * Instantiates a new auto assign checker * - * @param targetFilterQueryManagement - * to get all target filter queries - * @param targetManagement - * to get targets - * @param deploymentManagement - * to assign distribution sets to targets - * @param transactionManager - * to run transactions - * @param contextAware - * to handle the context + * @param targetFilterQueryManagement to get all target filter queries + * @param targetManagement to get targets + * @param deploymentManagement to assign distribution sets to targets + * @param transactionManager to run transactions + * @param contextAware to handle the context */ public AutoAssignChecker(final TargetFilterQueryManagement targetFilterQueryManagement, final TargetManagement targetManagement, final DeploymentManagement deploymentManagement, @@ -83,8 +78,7 @@ public class AutoAssignChecker extends AbstractAutoAssignExecutor { * them. Catches PersistenceException and own exceptions derived from * AbstractServerRtException * - * @param targetFilterQuery - * the target filter query + * @param targetFilterQuery the target filter query */ private void checkByTargetFilterQueryAndAssignDS(final TargetFilterQuery targetFilterQuery) { log.debug("Auto assign check call for tenant {} and target filter query id {} started", diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignScheduler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignScheduler.java index d02228050..0d2b6b09e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignScheduler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignScheduler.java @@ -23,7 +23,7 @@ import org.springframework.scheduling.annotation.Scheduled; */ @Slf4j public class AutoAssignScheduler { - + private static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${hawkbit.autoassign.scheduler.fixedDelay:2000}"; private final SystemManagement systemManagement; @@ -36,15 +36,11 @@ public class AutoAssignScheduler { /** * Instantiates a new AutoAssignScheduler - * - * @param systemManagement - * to find all tenants - * @param systemSecurityContext - * to run as system - * @param autoAssignExecutor - * to run a check as tenant - * @param lockRegistry - * to acquire a lock per tenant + * + * @param systemManagement to find all tenants + * @param systemSecurityContext to run as system + * @param autoAssignExecutor to run a check as tenant + * @param lockRegistry to acquire a lock per tenant */ public AutoAssignScheduler(final SystemManagement systemManagement, final SystemSecurityContext systemSecurityContext, final AutoAssignExecutor autoAssignExecutor, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanup.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanup.java index a2894ad8c..e186d631f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanup.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanup.java @@ -32,7 +32,7 @@ import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; * actions which are in a certain {@link Action.Status}. It is recommended to * only clean up actions which have terminated already (i.e. actions in status * CANCELLED or ERROR). - * + * * The cleanup task can be enabled /disabled and configured on a per tenant * basis. */ @@ -49,11 +49,9 @@ public class AutoActionCleanup implements CleanupTask { /** * Constructs the action cleanup handler. - * - * @param deploymentMgmt - * The {@link DeploymentManagement} to operate on. - * @param configMgmt - * The {@link TenantConfigurationManagement} service. + * + * @param deploymentMgmt The {@link DeploymentManagement} to operate on. + * @param configMgmt The {@link TenantConfigurationManagement} service. */ public AutoActionCleanup(final DeploymentManagement deploymentMgmt, final TenantConfigurationManagement configMgmt) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoCleanupScheduler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoCleanupScheduler.java index 0b9c6168c..e283c961a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoCleanupScheduler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoCleanupScheduler.java @@ -36,15 +36,11 @@ public class AutoCleanupScheduler { /** * Constructs the cleanup schedulers and initializes it with a set of * cleanup handlers. - * - * @param systemManagement - * Management APIs to invoke actions in a certain tenant context. - * @param systemSecurityContext - * The system security context. - * @param lockRegistry - * A registry for shared locks. - * @param cleanupTasks - * A list of cleanup tasks. + * + * @param systemManagement Management APIs to invoke actions in a certain tenant context. + * @param systemSecurityContext The system security context. + * @param lockRegistry A registry for shared locks. + * @param cleanupTasks A list of cleanup tasks. */ public AutoCleanupScheduler(final SystemManagement systemManagement, final SystemSecurityContext systemSecurityContext, final LockRegistry lockRegistry, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusBuilder.java index 5946eb8b8..8a2c791c4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusBuilder.java @@ -15,7 +15,6 @@ import org.eclipse.hawkbit.repository.model.ActionStatus; /** * Builder implementation for {@link ActionStatus}. - * */ public class JpaActionStatusBuilder implements ActionStatusBuilder { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusCreate.java index a4151e936..0b5b930cc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaActionStatusCreate.java @@ -15,7 +15,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; /** * Create/build implementation. - * */ public class JpaActionStatusCreate extends AbstractActionStatusCreate implements ActionStatusCreate { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetBuilder.java index bd06c8dc1..6169e93af 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetBuilder.java @@ -19,7 +19,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; /** * Builder implementation for {@link DistributionSet}. - * */ public class JpaDistributionSetBuilder implements DistributionSetBuilder { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetCreate.java index 708563d73..35afc2669 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetCreate.java @@ -27,16 +27,14 @@ import org.springframework.util.StringUtils; /** * Create/build implementation. - * */ public class JpaDistributionSetCreate extends AbstractDistributionSetUpdateCreate implements DistributionSetCreate { - @ValidString - private String type; - private final DistributionSetTypeManagement distributionSetTypeManagement; private final SoftwareModuleManagement softwareModuleManagement; + @ValidString + private String type; JpaDistributionSetCreate(final DistributionSetTypeManagement distributionSetTypeManagement, final SoftwareModuleManagement softwareManagement) { @@ -44,6 +42,12 @@ public class JpaDistributionSetCreate extends AbstractDistributionSetUpdateCreat this.softwareModuleManagement = softwareManagement; } + @Override + public DistributionSetCreate type(final String type) { + this.type = StringUtils.trimWhitespace(type); + return this; + } + @Override public JpaDistributionSet build() { return new JpaDistributionSet(name, version, description, @@ -52,12 +56,6 @@ public class JpaDistributionSetCreate extends AbstractDistributionSetUpdateCreat Optional.ofNullable(requiredMigrationStep).orElse(Boolean.FALSE)); } - @Override - public DistributionSetCreate type(final String type) { - this.type = StringUtils.trimWhitespace(type); - return this; - } - public String getType() { return type; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeBuilder.java index 134b1bba2..f992808db 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeBuilder.java @@ -18,7 +18,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType; /** * Builder implementation for {@link DistributionSetType}. - * */ public class JpaDistributionSetTypeBuilder implements DistributionSetTypeBuilder { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeCreate.java index 110cc5456..27fbf422c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeCreate.java @@ -22,7 +22,6 @@ import org.springframework.util.CollectionUtils; /** * Create/build implementation. - * */ public class JpaDistributionSetTypeCreate extends AbstractDistributionSetTypeUpdateCreate implements DistributionSetTypeCreate { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutBuilder.java index 11dbcb278..11811de71 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutBuilder.java @@ -18,9 +18,9 @@ import org.eclipse.hawkbit.repository.model.Rollout; /** * Builder implementation for {@link Rollout}. - * */ public class JpaRolloutBuilder implements RolloutBuilder { + private final DistributionSetManagement distributionSetManagement; public JpaRolloutBuilder(final DistributionSetManagement distributionSetManagement) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutCreate.java index f686a95ee..649dc4e70 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutCreate.java @@ -9,8 +9,11 @@ */ package org.eclipse.hawkbit.repository.jpa.builder; +import java.util.Optional; + import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; + import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.ValidString; import org.eclipse.hawkbit.repository.builder.AbstractNamedEntityBuilder; @@ -20,12 +23,8 @@ import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.springframework.util.StringUtils; -import java.util.Optional; - public class JpaRolloutCreate extends AbstractNamedEntityBuilder implements RolloutCreate { - private final DistributionSetManagement distributionSetManagement; - protected Long distributionSetId; @ValidString protected String targetFilterQuery; @@ -35,12 +34,13 @@ public class JpaRolloutCreate extends AbstractNamedEntityBuilder @Min(Action.WEIGHT_MIN) @Max(Action.WEIGHT_MAX) protected Integer weight; - + private final DistributionSetManagement distributionSetManagement; private boolean dynamic; JpaRolloutCreate(final DistributionSetManagement distributionSetManagement) { this.distributionSetManagement = distributionSetManagement; } + /** * {@link DistributionSet} of rollout * @@ -62,6 +62,7 @@ public class JpaRolloutCreate extends AbstractNamedEntityBuilder this.targetFilterQuery = StringUtils.trimWhitespace(targetFilterQuery); return this; } + /** * {@link Action.ActionType} used for {@link Action}s * @@ -95,6 +96,11 @@ public class JpaRolloutCreate extends AbstractNamedEntityBuilder return this; } + public RolloutCreate dynamic(final boolean dynamic) { + this.dynamic = dynamic; + return this; + } + /** * Set start of the Rollout * @@ -106,31 +112,6 @@ public class JpaRolloutCreate extends AbstractNamedEntityBuilder return this; } - public Optional getDistributionSetId() { - return Optional.ofNullable(distributionSetId); - } - - public Optional getActionType() { - return Optional.ofNullable(actionType); - } - - public Optional getForcedTime() { - return Optional.ofNullable(forcedTime); - } - - public Optional getWeight() { - return Optional.ofNullable(weight); - } - - public Optional getStartAt() { - return Optional.ofNullable(startAt); - } - - public RolloutCreate dynamic(final boolean dynamic) { - this.dynamic = dynamic; - return this; - } - @Override public JpaRollout build() { final JpaRollout rollout = new JpaRollout(); @@ -153,4 +134,24 @@ public class JpaRolloutCreate extends AbstractNamedEntityBuilder return rollout; } + + public Optional getDistributionSetId() { + return Optional.ofNullable(distributionSetId); + } + + public Optional getActionType() { + return Optional.ofNullable(actionType); + } + + public Optional getForcedTime() { + return Optional.ofNullable(forcedTime); + } + + public Optional getWeight() { + return Optional.ofNullable(weight); + } + + public Optional getStartAt() { + return Optional.ofNullable(startAt); + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupBuilder.java index 4afa5128a..ea937e2ee 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupBuilder.java @@ -15,9 +15,9 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup; /** * Builder implementation for {@link RolloutGroup}. - * */ public class JpaRolloutGroupBuilder implements RolloutGroupBuilder { + @Override public RolloutGroupCreate create() { return new JpaRolloutGroupCreate(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupCreate.java index 21a33b328..5cb56821a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaRolloutGroupCreate.java @@ -18,6 +18,51 @@ import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; public class JpaRolloutGroupCreate extends AbstractRolloutGroupCreate implements RolloutGroupCreate { + /** + * Set the Success And Error conditions for the rollout group + * + * @param group The Rollout group + * @param conditions The Rollout Success and Error Conditions + */ + public static void addSuccessAndErrorConditionsAndActions(final JpaRolloutGroup group, + final RolloutGroupConditions conditions) { + addSuccessAndErrorConditionsAndActions(group, conditions.getSuccessCondition(), + conditions.getSuccessConditionExp(), conditions.getSuccessAction(), conditions.getSuccessActionExp(), + conditions.getErrorCondition(), conditions.getErrorConditionExp(), conditions.getErrorAction(), + conditions.getErrorActionExp()); + } + + /** + * Set the Success And Error conditions for the rollout group + * + * @param group The Rollout group + * @param successCondition The Rollout group success condition + * @param successConditionExp The Rollout group success expression + * @param successAction The Rollout group success action + * @param successActionExp The Rollout group success action expression + * @param errorCondition The Rollout group error condition + * @param errorConditionExp The Rollout group error expression + * @param errorAction The Rollout group error action + * @param errorActionExp The Rollout group error action expression + */ + public static void addSuccessAndErrorConditionsAndActions(final JpaRolloutGroup group, + final RolloutGroup.RolloutGroupSuccessCondition successCondition, final String successConditionExp, + final RolloutGroup.RolloutGroupSuccessAction successAction, final String successActionExp, + final RolloutGroup.RolloutGroupErrorCondition errorCondition, final String errorConditionExp, + final RolloutGroup.RolloutGroupErrorAction errorAction, final String errorActionExp) { + group.setSuccessCondition(successCondition); + group.setSuccessConditionExp(successConditionExp); + + group.setSuccessAction(successAction); + group.setSuccessActionExp(successActionExp); + + group.setErrorCondition(errorCondition); + group.setErrorConditionExp(errorConditionExp); + + group.setErrorAction(errorAction); + group.setErrorActionExp(errorActionExp); + } + @Override public JpaRolloutGroup build() { final JpaRolloutGroup group = new JpaRolloutGroup(); @@ -40,60 +85,4 @@ public class JpaRolloutGroupCreate extends AbstractRolloutGroupCreate implements SoftwareModuleCreate { @@ -39,16 +38,16 @@ public class JpaSoftwareModuleCreate extends AbstractSoftwareModuleUpdateCreate< return this; } - public boolean isEncrypted() { - return encrypted; - } - @Override public JpaSoftwareModule build() { return new JpaSoftwareModule(getSoftwareModuleTypeFromKeyString(type), name, version, description, vendor, encrypted); } + public boolean isEncrypted() { + return encrypted; + } + private SoftwareModuleType getSoftwareModuleTypeFromKeyString(final String type) { if (type == null) { throw new ValidationException("type cannot be null"); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataBuilder.java index 004f777e7..0ee173f7b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataBuilder.java @@ -18,7 +18,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; /** * Builder implementation for {@link SoftwareModuleMetadata}. - * */ public class JpaSoftwareModuleMetadataBuilder implements SoftwareModuleMetadataBuilder { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataCreate.java index 31536c5c5..8b83dccb9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataCreate.java @@ -18,7 +18,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; /** * Create/build implementation. - * */ public class JpaSoftwareModuleMetadataCreate extends AbstractSoftwareModuleMetadataUpdateCreate diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeBuilder.java index 3df3eb843..4ad36bae1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeBuilder.java @@ -17,7 +17,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType; /** * Builder implementation for {@link SoftwareModuleType}. - * */ public class JpaSoftwareModuleTypeBuilder implements SoftwareModuleTypeBuilder { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeCreate.java index 7045f338e..9f618205b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeCreate.java @@ -15,7 +15,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; /** * Create/build implementation. - * */ public class JpaSoftwareModuleTypeCreate extends AbstractSoftwareModuleTypeUpdateCreate implements SoftwareModuleTypeCreate { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagBuilder.java index 336767449..b6b3c1c08 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagBuilder.java @@ -17,7 +17,6 @@ import org.eclipse.hawkbit.repository.model.Tag; /** * Builder implementation for {@link Tag}. - * */ public class JpaTagBuilder implements TagBuilder { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagCreate.java index 0739fb5aa..049e668de 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagCreate.java @@ -18,9 +18,9 @@ import org.eclipse.hawkbit.repository.model.Tag; /** * Create/build implementation. - * */ public class JpaTagCreate extends AbstractTagUpdateCreate implements TagCreate { + JpaTagCreate() { } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetBuilder.java index 4245453e9..20f6b1339 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetBuilder.java @@ -17,14 +17,13 @@ import org.eclipse.hawkbit.repository.model.Target; /** * Builder implementation for {@link Target}. - * */ public class JpaTargetBuilder implements TargetBuilder { + final private TargetTypeManagement targetTypeManagement; /** - * @param targetTypeManagement - * Target type management + * @param targetTypeManagement Target type management */ public JpaTargetBuilder(TargetTypeManagement targetTypeManagement) { this.targetTypeManagement = targetTypeManagement; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetCreate.java index 4594e8e62..03ea57b87 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetCreate.java @@ -20,7 +20,6 @@ import org.springframework.util.StringUtils; /** * Create/build implementation. - * */ public class JpaTargetCreate extends AbstractTargetUpdateCreate implements TargetCreate { @@ -29,8 +28,7 @@ public class JpaTargetCreate extends AbstractTargetUpdateCreate im /** * Constructor * - * @param targetTypeManagement - * Target type management + * @param targetTypeManagement Target type management */ JpaTargetCreate(final TargetTypeManagement targetTypeManagement) { super(null); @@ -51,7 +49,7 @@ public class JpaTargetCreate extends AbstractTargetUpdateCreate im target.setName(name); } - if (targetTypeId != null){ + if (targetTypeId != null) { TargetType targetType = targetTypeManagement.get(targetTypeId) .orElseThrow(() -> new EntityNotFoundException(TargetType.class, targetTypeId)); target.setTargetType(targetType); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetFilterQueryBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetFilterQueryBuilder.java index fc4150755..0981f6c8e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetFilterQueryBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetFilterQueryBuilder.java @@ -19,9 +19,9 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery; /** * Builder implementation for {@link TargetFilterQuery}. - * */ public class JpaTargetFilterQueryBuilder implements TargetFilterQueryBuilder { + private final DistributionSetManagement distributionSetManagement; public JpaTargetFilterQueryBuilder(final DistributionSetManagement distributionSetManagement) { @@ -33,14 +33,14 @@ public class JpaTargetFilterQueryBuilder implements TargetFilterQueryBuilder { return new GenericTargetFilterQueryUpdate(id); } - @Override - public TargetFilterQueryCreate create() { - return new JpaTargetFilterQueryCreate(distributionSetManagement); - } - @Override public AutoAssignDistributionSetUpdate updateAutoAssign(final long id) { return new AutoAssignDistributionSetUpdate(id); } + @Override + public TargetFilterQueryCreate create() { + return new JpaTargetFilterQueryCreate(distributionSetManagement); + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetFilterQueryCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetFilterQueryCreate.java index fa35bb83b..a7f6c806a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetFilterQueryCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetFilterQueryCreate.java @@ -19,7 +19,6 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery; /** * Create/build implementation. - * */ public class JpaTargetFilterQueryCreate extends AbstractTargetFilterQueryUpdateCreate implements TargetFilterQueryCreate { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetTypeBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetTypeBuilder.java index 662ed84c7..46a57bace 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetTypeBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetTypeBuilder.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.jpa.builder; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.builder.GenericTargetTypeUpdate; import org.eclipse.hawkbit.repository.builder.TargetTypeBuilder; import org.eclipse.hawkbit.repository.builder.TargetTypeCreate; @@ -19,16 +18,15 @@ import org.eclipse.hawkbit.repository.model.TargetType; /** * Builder implementation for {@link TargetType}. - * */ public class JpaTargetTypeBuilder implements TargetTypeBuilder { + private final DistributionSetTypeManagement distributionSetTypeManagement; /** * Constructor * - * @param distributionSetTypeManagement - * Distribution set type management + * @param distributionSetTypeManagement Distribution set type management */ public JpaTargetTypeBuilder(DistributionSetTypeManagement distributionSetTypeManagement) { this.distributionSetTypeManagement = distributionSetTypeManagement; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetTypeCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetTypeCreate.java index 43ce272b7..fc7a7c935 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetTypeCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTargetTypeCreate.java @@ -9,6 +9,9 @@ */ package org.eclipse.hawkbit.repository.jpa.builder; +import java.util.Collection; +import java.util.Collections; + import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.builder.AbstractTargetTypeUpdateCreate; import org.eclipse.hawkbit.repository.builder.TargetTypeCreate; @@ -19,12 +22,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.springframework.util.CollectionUtils; -import java.util.Collection; -import java.util.Collections; - /** * Create/build implementation. - * */ public class JpaTargetTypeCreate extends AbstractTargetTypeUpdateCreate implements TargetTypeCreate { @@ -34,8 +33,7 @@ public class JpaTargetTypeCreate extends AbstractTargetTypeUpdateCreate> THREAD_LOCAL_RUNNABLES = new ThreadLocal<>(); @Override @@ -42,6 +42,14 @@ public class AfterTransactionCommitDefaultServiceExecutor extends TransactionSyn } } + @Override + @SuppressWarnings({ "squid:S1217" }) + public void afterCompletion(final int status) { + final String transactionStatus = status == STATUS_COMMITTED ? "COMMITTED" : "ROLLEDBACK"; + log.debug("Transaction completed after commit with status {}", transactionStatus); + THREAD_LOCAL_RUNNABLES.remove(); + } + @Override // Exception squid:S1217 - we want to run this synchronous @SuppressWarnings("squid:S1217") @@ -62,12 +70,4 @@ public class AfterTransactionCommitDefaultServiceExecutor extends TransactionSyn runnable.run(); } - @Override - @SuppressWarnings({ "squid:S1217" }) - public void afterCompletion(final int status) { - final String transactionStatus = status == STATUS_COMMITTED ? "COMMITTED" : "ROLLEDBACK"; - log.debug("Transaction completed after commit with status {}", transactionStatus); - THREAD_LOCAL_RUNNABLES.remove(); - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitExecutor.java index 024b55703..a63a6ba34 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/executor/AfterTransactionCommitExecutor.java @@ -10,10 +10,8 @@ package org.eclipse.hawkbit.repository.jpa.executor; /** - * * A interface to register a runnable, which will be executed after a successful * spring transaction. - * */ @FunctionalInterface public interface AfterTransactionCommitExecutor { @@ -21,9 +19,8 @@ public interface AfterTransactionCommitExecutor { /** * Register a runnable which will be executed after a successful spring * transaction. - * - * @param runnable - * the after commit runnable + * + * @param runnable the after commit runnable */ void afterCommit(Runnable runnable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java index 04c0a3be4..b2ea16f65 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java @@ -17,6 +17,8 @@ import java.util.Set; import java.util.function.BooleanSupplier; import java.util.stream.Collectors; +import jakarta.persistence.criteria.JoinType; + import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; @@ -48,8 +50,6 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import jakarta.persistence.criteria.JoinType; - /** * {@link DistributionSet} to {@link Target} assignment strategy as utility for * {@link JpaDeploymentManagement}. @@ -68,10 +68,10 @@ public abstract class AbstractDsAssignmentStrategy { private final RepositoryProperties repositoryProperties; AbstractDsAssignmentStrategy(final TargetRepository targetRepository, - final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, - final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, - final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, - final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { + final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, + final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, + final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, + final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { this.targetRepository = targetRepository; this.afterCommit = afterCommit; this.eventPublisherHolder = eventPublisherHolder; @@ -83,63 +83,47 @@ public abstract class AbstractDsAssignmentStrategy { this.repositoryProperties = repositoryProperties; } - /** - * Find targets to be considered for assignment. - * - * @param controllerIDs - * as provided by repository caller - * @param distributionSetId - * to assign - * @return list of targets up to {@link Constants#MAX_ENTRIES_IN_STATEMENT} - */ - abstract List findTargetsForAssignment(final List controllerIDs, final long distributionSetId); + public JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType, + final List targets, final JpaDistributionSet set) { + final Optional optTarget = targets.stream() + .filter(t -> t.getControllerId().equals(targetWithActionType.getControllerId())).findFirst(); - /** - * - * @param set - * @param targets - */ - abstract void sendTargetUpdatedEvents(final DistributionSet set, final List targets); + // create the action + return optTarget.map(target -> { + assertActionsPerTargetQuota(target, 1); + final JpaAction actionForTarget = new JpaAction(); + actionForTarget.setActionType(targetWithActionType.getActionType()); + actionForTarget.setForcedTime(targetWithActionType.getForceTime()); + actionForTarget.setWeight( + targetWithActionType.getWeight() == null ? + repositoryProperties.getActionWeightIfAbsent() : targetWithActionType.getWeight()); + actionForTarget.setActive(true); + actionForTarget.setTarget(target); + actionForTarget.setDistributionSet(set); + actionForTarget.setMaintenanceWindowSchedule(targetWithActionType.getMaintenanceSchedule()); + actionForTarget.setMaintenanceWindowDuration(targetWithActionType.getMaintenanceWindowDuration()); + actionForTarget.setMaintenanceWindowTimeZone(targetWithActionType.getMaintenanceWindowTimeZone()); + actionForTarget.setInitiatedBy(initiatedBy); + return actionForTarget; + }).orElseGet(() -> { + log.warn("Cannot find target for targetWithActionType '{}'.", targetWithActionType.getControllerId()); + return null; + }); + } - /** - * Update status and DS fields of given target. - * - * @param distributionSet - * to set - * @param targetIds - * to change - * @param currentUser - * for auditing - */ - abstract void setAssignedDistributionSetAndTargetStatus(final JpaDistributionSet distributionSet, - final List> targetIds, final String currentUser); + public JpaActionStatus createActionStatus(final JpaAction action, final String actionMessage) { + final JpaActionStatus actionStatus = new JpaActionStatus(); + actionStatus.setAction(action); + actionStatus.setOccurredAt(action.getCreatedAt()); - /** - * Cancels actions that can be canceled (i.e. - * {@link DistributionSet#isRequiredMigrationStep() is false}) - * as a result of the new assignment and returns all {@link Target}s where - * such actions existed. - * - * @param targetIds - * to cancel actions for - * @return {@link Set} of {@link Target#getId()}s - */ - abstract Set cancelActiveActions(List> targetIds); + if (StringUtils.hasText(actionMessage)) { + actionStatus.addMessage(actionMessage); + } else { + actionStatus.addMessage(getActionMessage(action)); + } - /** - * Cancels actions that can be canceled (i.e. - * {@link DistributionSet#isRequiredMigrationStep() is false}) - * as a result of the new assignment and returns all {@link Target}s where - * such actions existed. - * - * @param targetIds - * to cancel actions for - */ - abstract void closeActiveActions(List> targetIds); - - abstract void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult); - - abstract void sendDeploymentEvents(final List assignmentResults); + return actionStatus; + } protected void sendTargetUpdatedEvent(final JpaTarget target) { afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher() @@ -172,7 +156,7 @@ public abstract class AbstractDsAssignmentStrategy { // document that the status has been retrieved actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELING, System.currentTimeMillis(), - RepositoryConstants.SERVER_MESSAGE_PREFIX + "cancel obsolete action due to new update")); + RepositoryConstants.SERVER_MESSAGE_PREFIX + "cancel obsolete action due to new update")); actionRepository.save(action); return action.getTarget().getId(); @@ -223,65 +207,70 @@ public abstract class AbstractDsAssignmentStrategy { * Sends the {@link CancelTargetAssignmentEvent} for a specific action to * the eventPublisher. * - * @param action - * the action of the assignment + * @param action the action of the assignment */ protected void cancelAssignDistributionSetEvent(final Action action) { afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent( - new CancelTargetAssignmentEvent(action, eventPublisherHolder.getApplicationId()))); + new CancelTargetAssignmentEvent(action, eventPublisherHolder.getApplicationId()))); } - private void cancelAssignDistributionSetEvent(final List actions) { - if (CollectionUtils.isEmpty(actions)) { - return; - } - final String tenant = actions.get(0).getTenant(); - afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher() - .publishEvent(new CancelTargetAssignmentEvent(tenant, - actions, eventPublisherHolder.getApplicationId()))); + protected boolean isMultiAssignmentsEnabled() { + return multiAssignmentsConfig.getAsBoolean(); } - public JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType, - final List targets, final JpaDistributionSet set) { - final Optional optTarget = targets.stream() - .filter(t -> t.getControllerId().equals(targetWithActionType.getControllerId())).findFirst(); - - // create the action - return optTarget.map(target -> { - assertActionsPerTargetQuota(target, 1); - final JpaAction actionForTarget = new JpaAction(); - actionForTarget.setActionType(targetWithActionType.getActionType()); - actionForTarget.setForcedTime(targetWithActionType.getForceTime()); - actionForTarget.setWeight( - targetWithActionType.getWeight() == null ? - repositoryProperties.getActionWeightIfAbsent() : targetWithActionType.getWeight()); - actionForTarget.setActive(true); - actionForTarget.setTarget(target); - actionForTarget.setDistributionSet(set); - actionForTarget.setMaintenanceWindowSchedule(targetWithActionType.getMaintenanceSchedule()); - actionForTarget.setMaintenanceWindowDuration(targetWithActionType.getMaintenanceWindowDuration()); - actionForTarget.setMaintenanceWindowTimeZone(targetWithActionType.getMaintenanceWindowTimeZone()); - actionForTarget.setInitiatedBy(initiatedBy); - return actionForTarget; - }).orElseGet(() -> { - log.warn("Cannot find target for targetWithActionType '{}'.", targetWithActionType.getControllerId()); - return null; - }); + protected boolean isConfirmationFlowEnabled() { + return confirmationFlowConfig.getAsBoolean(); } - public JpaActionStatus createActionStatus(final JpaAction action, final String actionMessage) { - final JpaActionStatus actionStatus = new JpaActionStatus(); - actionStatus.setAction(action); - actionStatus.setOccurredAt(action.getCreatedAt()); + /** + * Find targets to be considered for assignment. + * + * @param controllerIDs as provided by repository caller + * @param distributionSetId to assign + * @return list of targets up to {@link Constants#MAX_ENTRIES_IN_STATEMENT} + */ + abstract List findTargetsForAssignment(final List controllerIDs, final long distributionSetId); - if (StringUtils.hasText(actionMessage)) { - actionStatus.addMessage(actionMessage); - } else { - actionStatus.addMessage(getActionMessage(action)); - } + /** + * @param set + * @param targets + */ + abstract void sendTargetUpdatedEvents(final DistributionSet set, final List targets); - return actionStatus; - } + /** + * Update status and DS fields of given target. + * + * @param distributionSet to set + * @param targetIds to change + * @param currentUser for auditing + */ + abstract void setAssignedDistributionSetAndTargetStatus(final JpaDistributionSet distributionSet, + final List> targetIds, final String currentUser); + + /** + * Cancels actions that can be canceled (i.e. + * {@link DistributionSet#isRequiredMigrationStep() is false}) + * as a result of the new assignment and returns all {@link Target}s where + * such actions existed. + * + * @param targetIds to cancel actions for + * @return {@link Set} of {@link Target#getId()}s + */ + abstract Set cancelActiveActions(List> targetIds); + + /** + * Cancels actions that can be canceled (i.e. + * {@link DistributionSet#isRequiredMigrationStep() is false}) + * as a result of the new assignment and returns all {@link Target}s where + * such actions existed. + * + * @param targetIds to cancel actions for + */ + abstract void closeActiveActions(List> targetIds); + + abstract void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult); + + abstract void sendDeploymentEvents(final List assignmentResults); private static String getActionMessage(final Action action) { final RolloutGroup rolloutGroup = action.getRolloutGroup(); @@ -292,18 +281,20 @@ public abstract class AbstractDsAssignmentStrategy { } return String.format("Assignment initiated by user '%s'", action.getInitiatedBy()); } - + + private void cancelAssignDistributionSetEvent(final List actions) { + if (CollectionUtils.isEmpty(actions)) { + return; + } + final String tenant = actions.get(0).getTenant(); + afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher() + .publishEvent(new CancelTargetAssignmentEvent(tenant, + actions, eventPublisherHolder.getApplicationId()))); + } + private void assertActionsPerTargetQuota(final Target target, final int requested) { final int quota = quotaManagement.getMaxActionsPerTarget(); QuotaHelper.assertAssignmentQuota(target.getId(), requested, quota, Action.class, Target.class, actionRepository::countByTargetId); } - - protected boolean isMultiAssignmentsEnabled() { - return multiAssignmentsConfig.getAsBoolean(); - } - - protected boolean isConfirmationFlowEnabled() { - return confirmationFlowConfig.getAsBoolean(); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java index dda243e02..a8344bd1b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java @@ -9,6 +9,15 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY; +import static org.eclipse.hawkbit.repository.model.Action.Status.ERROR; +import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryProperties; @@ -27,15 +36,6 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY; -import static org.eclipse.hawkbit.repository.model.Action.Status.ERROR; -import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; - /** * Implements utility methods for managing {@link Action}s */ @@ -56,6 +56,54 @@ public class JpaActionManagement { this.repositoryProperties = repositoryProperties; } + public int getWeightConsideringDefault(final Action action) { + return action.getWeight().orElse(repositoryProperties.getActionWeightIfAbsent()); + } + + protected static boolean isDownloadOnly(final JpaAction action) { + return DOWNLOAD_ONLY == action.getActionType(); + } + + protected List findActiveActionsHavingStatus(final String controllerId, final Action.Status status) { + return actionRepository.findAll( + ActionSpecifications.byTargetControllerIdAndIsActiveAndStatus(controllerId, status)); + } + + protected Action addActionStatus(final JpaActionStatusCreate statusCreate) { + final Long actionId = statusCreate.getActionId(); + final JpaActionStatus actionStatus = statusCreate.build(); + final JpaAction action = getActionAndThrowExceptionIfNotFound(actionId); + + if (isUpdatingActionStatusAllowed(action, actionStatus)) { + return handleAddUpdateActionStatus(actionStatus, action); + } + + log.debug("Update of actionStatus {} for action {} not possible since action not active anymore.", + actionStatus.getStatus(), action.getId()); + return action; + } + + protected JpaAction getActionAndThrowExceptionIfNotFound(final Long actionId) { + return actionRepository.findById(actionId) + .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); + } + + protected void onActionStatusUpdate(final Action.Status updatedActionStatus, final JpaAction action) { + // can be overwritten to intercept the persistence of the action status + } + + protected void assertActionStatusQuota(final JpaActionStatus newActionStatus, final JpaAction action) { + if (isIntermediateStatus(newActionStatus)) {// check for quota only for intermediate statuses + QuotaHelper.assertAssignmentQuota(action.getId(), 1, quotaManagement.getMaxStatusEntriesPerAction(), + ActionStatus.class, Action.class, actionStatusRepository::countByActionId); + } + } + + protected void assertActionStatusMessageQuota(final JpaActionStatus actionStatus) { + QuotaHelper.assertAssignmentQuota(actionStatus.getId(), actionStatus.getMessages().size(), + quotaManagement.getMaxMessagesPerActionStatus(), "Message", ActionStatus.class.getSimpleName(), null); + } + List findActiveActionsWithHighestWeightConsideringDefault(final String controllerId, final int maxActionCount) { final List actions = new ArrayList<>(); @@ -84,23 +132,8 @@ public class JpaActionManagement { return actions.stream().sorted(actionImportance).limit(maxActionCount).collect(Collectors.toList()); } - protected List findActiveActionsHavingStatus(final String controllerId, final Action.Status status) { - return actionRepository.findAll( - ActionSpecifications.byTargetControllerIdAndIsActiveAndStatus(controllerId, status)); - } - - protected Action addActionStatus(final JpaActionStatusCreate statusCreate) { - final Long actionId = statusCreate.getActionId(); - final JpaActionStatus actionStatus = statusCreate.build(); - final JpaAction action = getActionAndThrowExceptionIfNotFound(actionId); - - if (isUpdatingActionStatusAllowed(action, actionStatus)) { - return handleAddUpdateActionStatus(actionStatus, action); - } - - log.debug("Update of actionStatus {} for action {} not possible since action not active anymore.", - actionStatus.getStatus(), action.getId()); - return action; + private static boolean isIntermediateStatus(final JpaActionStatus actionStatus) { + return FINISHED != actionStatus.getStatus() && ERROR != actionStatus.getStatus(); } /** @@ -117,25 +150,12 @@ public class JpaActionManagement { final boolean isAllowedByRepositoryConfiguration = intermediateStatus && !repositoryProperties.isRejectActionStatusForClosedAction(); //in case of download_only action Status#DOWNLOADED is treated as 'final' already, so we accept one final status from device in case it sends - final boolean isAllowedForDownloadOnlyActions = isDownloadOnly(action) && action.getStatus() == Action.Status.DOWNLOADED && !intermediateStatus; + final boolean isAllowedForDownloadOnlyActions = isDownloadOnly( + action) && action.getStatus() == Action.Status.DOWNLOADED && !intermediateStatus; return action.isActive() || isAllowedByRepositoryConfiguration || isAllowedForDownloadOnlyActions; } - public int getWeightConsideringDefault(final Action action) { - return action.getWeight().orElse(repositoryProperties.getActionWeightIfAbsent()); - } - - protected JpaAction getActionAndThrowExceptionIfNotFound(final Long actionId) { - return actionRepository.findById(actionId) - .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); - } - - protected static boolean isDownloadOnly(final JpaAction action) { - return DOWNLOAD_ONLY == action.getActionType(); - } - - /** * Sets {@link TargetUpdateStatus} based on given {@link ActionStatus}. */ @@ -152,24 +172,4 @@ public class JpaActionManagement { action.setLastActionStatusCode(actionStatus.getCode().orElse(null)); return actionRepository.save(action); } - - protected void onActionStatusUpdate(final Action.Status updatedActionStatus, final JpaAction action){ - // can be overwritten to intercept the persistence of the action status - } - - protected void assertActionStatusQuota(final JpaActionStatus newActionStatus, final JpaAction action) { - if (isIntermediateStatus(newActionStatus)) {// check for quota only for intermediate statuses - QuotaHelper.assertAssignmentQuota(action.getId(), 1, quotaManagement.getMaxStatusEntriesPerAction(), - ActionStatus.class, Action.class, actionStatusRepository::countByActionId); - } - } - - protected void assertActionStatusMessageQuota(final JpaActionStatus actionStatus) { - QuotaHelper.assertAssignmentQuota(actionStatus.getId(), actionStatus.getMessages().size(), - quotaManagement.getMaxMessagesPerActionStatus(), "Message", ActionStatus.class.getSimpleName(), null); - } - - private static boolean isIntermediateStatus(final JpaActionStatus actionStatus) { - return FINISHED != actionStatus.getStatus() && ERROR != actionStatus.getStatus(); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java index 977a2dfce..fd88026fa 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java @@ -13,6 +13,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Optional; +import jakarta.persistence.EntityManager; + import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.artifact.repository.ArtifactRepository; import org.eclipse.hawkbit.artifact.repository.ArtifactStoreException; @@ -58,8 +60,6 @@ import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.validation.annotation.Validated; -import jakarta.persistence.EntityManager; - /** * JPA based {@link ArtifactManagement} implementation. */ @@ -92,6 +92,11 @@ public class JpaArtifactManagement implements ArtifactManagement { this.tenantAware = tenantAware; } + @Override + public long count() { + return localArtifactRepository.count(); + } + @Override @Transactional @Retryable(include = { @@ -127,90 +132,6 @@ public class JpaArtifactManagement implements ArtifactManagement { } } - private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload, final boolean isSmEncrypted) { - final String tenant = tenantAware.getCurrentTenant(); - final long smId = artifactUpload.getModuleId(); - final InputStream stream = artifactUpload.getInputStream(); - final String fileName = artifactUpload.getFilename(); - final String contentType = artifactUpload.getContentType(); - final String providedSha1 = artifactUpload.getProvidedSha1Sum(); - final String providedMd5 = artifactUpload.getProvidedMd5Sum(); - final String providedSha256 = artifactUpload.getProvidedSha256Sum(); - - try (final InputStream wrappedStream = wrapInQuotaStream( - isSmEncrypted ? wrapInEncryptionStream(smId, stream) : stream)) { - return artifactRepository.store(tenant, wrappedStream, fileName, contentType, - new DbArtifactHash(providedSha1, providedMd5, providedSha256)); - } catch (final ArtifactStoreException | IOException e) { - throw new ArtifactUploadFailedException(e); - } catch (final HashNotMatchException e) { - if (e.getHashFunction().equals(HashNotMatchException.SHA1)) { - throw new InvalidSHA1HashException(e.getMessage(), e); - } else if (e.getHashFunction().equals(HashNotMatchException.SHA256)) { - throw new InvalidSHA256HashException(e.getMessage(), e); - } else { - throw new InvalidMD5HashException(e.getMessage(), e); - } - } - } - - private InputStream wrapInEncryptionStream(final long smId, final InputStream stream) { - return ArtifactEncryptionService.getInstance().encryptSoftwareModuleArtifact(smId, stream); - } - - private void assertArtifactQuota(final long moduleId, final int requested) { - QuotaHelper.assertAssignmentQuota( - moduleId, requested, quotaManagement.getMaxArtifactsPerSoftwareModule(), - Artifact.class, SoftwareModule.class, - // get all artifacts without user context - softwareModuleId -> localArtifactRepository - .count(null, ArtifactSpecifications.bySoftwareModuleId(softwareModuleId))); - } - - private InputStream wrapInQuotaStream(final InputStream in) { - final long maxArtifactSize = quotaManagement.getMaxArtifactSize(); - - final long currentlyUsed = localArtifactRepository.sumOfNonDeletedArtifactSize().orElse(0L); - final long maxArtifactSizeTotal = quotaManagement.getMaxArtifactStorage(); - - return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize, - maxArtifactSizeTotal - currentlyUsed); - } - - /** - * Garbage collects artifact binaries if only referenced by given - * {@link SoftwareModule#getId()} or {@link SoftwareModule}'s that are - * marked as deleted. - *

- * Software module related UPDATE permission shall be checked by the callers! - * - * @param sha1Hash no longer needed - * @param softwareModuleId the garbage collection call is made for - */ - @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void clearArtifactBinary(final String sha1Hash) { - // countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse will skip ACM checks and - // will return total count as it should be - final long count = localArtifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse( - sha1Hash, - tenantAware.getCurrentTenant()); - if (count <= 1) { // 1 artifact is the one being deleted! - // removes the real artifact ONLY AFTER the delete of artifact or software module - // in local history has passed successfully (caller has permission and no errors) - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCommit() { - try { - log.debug("deleting artifact from repository {}", sha1Hash); - artifactRepository.deleteBySha1(tenantAware.getCurrentTenant(), sha1Hash); - } catch (final ArtifactStoreException e) { - throw new ArtifactDeleteFailedException(e); - } - } - }); - } // else there are still other artifacts that need the binary - } - @Override @Transactional @Retryable(include = { @@ -222,7 +143,7 @@ public class JpaArtifactManagement implements ArtifactManagement { // clearArtifactBinary checks (unconditionally) software module UPDATE access softwareModuleRepository.getAccessController().ifPresent(accessController -> accessController.assertOperationAllowed(AccessController.Operation.UPDATE, - (JpaSoftwareModule) toDelete.getSoftwareModule())); + (JpaSoftwareModule) toDelete.getSoftwareModule())); ((JpaSoftwareModule) toDelete.getSoftwareModule()).removeArtifact(toDelete); softwareModuleRepository.save((JpaSoftwareModule) toDelete.getSoftwareModule()); @@ -268,11 +189,6 @@ public class JpaArtifactManagement implements ArtifactManagement { return localArtifactRepository.count(ArtifactSpecifications.bySoftwareModuleId(softwareModuleId)); } - @Override - public long count() { - return localArtifactRepository.count(); - } - @Override public Optional loadArtifactBinary(final String sha1Hash, final long softwareModuleId, final boolean isEncrypted) { @@ -293,6 +209,91 @@ public class JpaArtifactManagement implements ArtifactManagement { return Optional.empty(); } + /** + * Garbage collects artifact binaries if only referenced by given + * {@link SoftwareModule#getId()} or {@link SoftwareModule}'s that are + * marked as deleted. + *

+ * Software module related UPDATE permission shall be checked by the callers! + * + * @param sha1Hash no longer needed + * @param softwareModuleId the garbage collection call is made for + */ + @PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) + void clearArtifactBinary(final String sha1Hash) { + // countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse will skip ACM checks and + // will return total count as it should be + final long count = localArtifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse( + sha1Hash, + tenantAware.getCurrentTenant()); + if (count <= 1) { // 1 artifact is the one being deleted! + // removes the real artifact ONLY AFTER the delete of artifact or software module + // in local history has passed successfully (caller has permission and no errors) + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + + @Override + public void afterCommit() { + try { + log.debug("deleting artifact from repository {}", sha1Hash); + artifactRepository.deleteBySha1(tenantAware.getCurrentTenant(), sha1Hash); + } catch (final ArtifactStoreException e) { + throw new ArtifactDeleteFailedException(e); + } + } + }); + } // else there are still other artifacts that need the binary + } + + private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload, final boolean isSmEncrypted) { + final String tenant = tenantAware.getCurrentTenant(); + final long smId = artifactUpload.getModuleId(); + final InputStream stream = artifactUpload.getInputStream(); + final String fileName = artifactUpload.getFilename(); + final String contentType = artifactUpload.getContentType(); + final String providedSha1 = artifactUpload.getProvidedSha1Sum(); + final String providedMd5 = artifactUpload.getProvidedMd5Sum(); + final String providedSha256 = artifactUpload.getProvidedSha256Sum(); + + try (final InputStream wrappedStream = wrapInQuotaStream( + isSmEncrypted ? wrapInEncryptionStream(smId, stream) : stream)) { + return artifactRepository.store(tenant, wrappedStream, fileName, contentType, + new DbArtifactHash(providedSha1, providedMd5, providedSha256)); + } catch (final ArtifactStoreException | IOException e) { + throw new ArtifactUploadFailedException(e); + } catch (final HashNotMatchException e) { + if (e.getHashFunction().equals(HashNotMatchException.SHA1)) { + throw new InvalidSHA1HashException(e.getMessage(), e); + } else if (e.getHashFunction().equals(HashNotMatchException.SHA256)) { + throw new InvalidSHA256HashException(e.getMessage(), e); + } else { + throw new InvalidMD5HashException(e.getMessage(), e); + } + } + } + + private InputStream wrapInEncryptionStream(final long smId, final InputStream stream) { + return ArtifactEncryptionService.getInstance().encryptSoftwareModuleArtifact(smId, stream); + } + + private void assertArtifactQuota(final long moduleId, final int requested) { + QuotaHelper.assertAssignmentQuota( + moduleId, requested, quotaManagement.getMaxArtifactsPerSoftwareModule(), + Artifact.class, SoftwareModule.class, + // get all artifacts without user context + softwareModuleId -> localArtifactRepository + .count(null, ArtifactSpecifications.bySoftwareModuleId(softwareModuleId))); + } + + private InputStream wrapInQuotaStream(final InputStream in) { + final long maxArtifactSize = quotaManagement.getMaxArtifactSize(); + + final long currentlyUsed = localArtifactRepository.sumOfNonDeletedArtifactSize().orElse(0L); + final long maxArtifactSizeTotal = quotaManagement.getMaxArtifactStorage(); + + return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize, + maxArtifactSizeTotal - currentlyUsed); + } + private DbArtifact wrapInEncryptionAwareDbArtifact(final long softwareModuleId, final DbArtifact dbArtifact) { if (dbArtifact == null) { return null; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java index a1f91f717..3dd974d1c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java @@ -65,9 +65,9 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co * Constructor */ public JpaConfirmationManagement(final TargetRepository targetRepository, - final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, - final RepositoryProperties repositoryProperties, final QuotaManagement quotaManagement, - final EntityFactory entityFactory) { + final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, + final RepositoryProperties repositoryProperties, final QuotaManagement quotaManagement, + final EntityFactory entityFactory) { super(actionRepository, actionStatusRepository, quotaManagement, repositoryProperties); this.targetRepository = targetRepository; this.entityFactory = entityFactory; @@ -96,7 +96,7 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co final AutoConfirmationStatus autoConfStatus = updatedTarget.getAutoConfirmationStatus(); if (autoConfStatus == null) { final String message = String.format("Persisted auto confirmation status is null. " - + "Cannot proceed with giving confirmations for active actions for device %s with initiator %s.", + + "Cannot proceed with giving confirmations for active actions for device %s with initiator %s.", controllerId, initiator); log.error("message"); throw new IllegalStateException(message); @@ -159,17 +159,20 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co return addActionStatus((JpaActionStatusCreate) statusCreate); } - private ActionStatusCreate createConfirmationActionStatus(final long actionId, final Integer code, - final Collection messages) { - final ActionStatusCreate statusCreate = entityFactory.actionStatus().create(actionId); - if (!CollectionUtils.isEmpty(messages)) { - statusCreate.messages(messages); + @Override + @Transactional + public void deactivateAutoConfirmation(String controllerId) { + log.debug("Deactivate auto confirmation for controllerId '{}'", controllerId); + final JpaTarget target = getTargetByControllerIdAndThrowIfNotFound(controllerId); + target.setAutoConfirmationStatus(null); + targetRepository.save(target); + } + + @Override + protected void onActionStatusUpdate(final Status updatedActionStatus, final JpaAction action) { + if (updatedActionStatus == Status.RUNNING && action.isActive()) { + action.setStatus(Status.RUNNING); } - if (code != null) { - statusCreate.code(code); - statusCreate.message(String.format(CONFIRMATION_CODE_MSG_PREFIX, code)); - } - return statusCreate; } private static void assertActionCanAcceptFeedback(final Action action) { @@ -188,6 +191,19 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co } } + private ActionStatusCreate createConfirmationActionStatus(final long actionId, final Integer code, + final Collection messages) { + final ActionStatusCreate statusCreate = entityFactory.actionStatus().create(actionId); + if (!CollectionUtils.isEmpty(messages)) { + statusCreate.messages(messages); + } + if (code != null) { + statusCreate.code(code); + statusCreate.message(String.format(CONFIRMATION_CODE_MSG_PREFIX, code)); + } + return statusCreate; + } + private List giveConfirmationForActiveActions(final AutoConfirmationStatus autoConfirmationStatus) { final Target target = autoConfirmationStatus.getTarget(); return findActiveActionsHavingStatus(target.getControllerId(), Status.WAIT_FOR_CONFIRMATION).stream() @@ -218,24 +234,8 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co return actionRepository.save(action); } - @Override - @Transactional - public void deactivateAutoConfirmation(String controllerId) { - log.debug("Deactivate auto confirmation for controllerId '{}'", controllerId); - final JpaTarget target = getTargetByControllerIdAndThrowIfNotFound(controllerId); - target.setAutoConfirmationStatus(null); - targetRepository.save(target); - } - private JpaTarget getTargetByControllerIdAndThrowIfNotFound(final String controllerId) { return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); } - - @Override - protected void onActionStatusUpdate(final Status updatedActionStatus, final JpaAction action) { - if (updatedActionStatus == Status.RUNNING && action.isActive()) { - action.setStatus(Status.RUNNING); - } - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java index d5a51d672..e82a9f292 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java @@ -9,12 +9,37 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED; +import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; +import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_KEY_SIZE; +import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE; + +import java.net.URI; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalUnit; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.BlockingDeque; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Root; import jakarta.validation.constraints.NotEmpty; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.ListUtils; import org.eclipse.hawkbit.repository.ConfirmationManagement; @@ -90,30 +115,6 @@ import org.springframework.transaction.support.TransactionCallback; import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; -import java.net.URI; -import java.time.Duration; -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; -import java.time.temporal.TemporalUnit; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.BlockingDeque; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED; -import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; -import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_KEY_SIZE; -import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE; - /** * JPA based {@link ControllerManagement} implementation. */ @@ -170,8 +171,8 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont private DistributionSetManagement distributionSetManagement; public JpaControllerManagement(final ScheduledExecutorService executorService, - final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, - final QuotaManagement quotaManagement, final RepositoryProperties repositoryProperties) { + final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, + final QuotaManagement quotaManagement, final RepositoryProperties repositoryProperties) { super(actionRepository, actionStatusRepository, quotaManagement, repositoryProperties); if (!repositoryProperties.isEagerPollPersistence()) { @@ -185,6 +186,172 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } } + @Override + public int getWeightConsideringDefault(final Action action) { + return super.getWeightConsideringDefault(action); + } + + @Override + protected void onActionStatusUpdate(final Action.Status updatedActionStatus, final JpaAction action) { + switch (updatedActionStatus) { + case ERROR: + final JpaTarget target = (JpaTarget) action.getTarget(); + target.setUpdateStatus(TargetUpdateStatus.ERROR); + handleErrorOnAction(action, target); + break; + case FINISHED: + handleFinishedAndStoreInTargetStatus(action).ifPresent(this::requestControllerAttributes); + break; + case DOWNLOADED: + handleDownloadedActionStatus(action).ifPresent(this::requestControllerAttributes); + break; + default: + break; + } + } + + @Override + @Transactional(isolation = Isolation.READ_COMMITTED) + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Action addCancelActionStatus(final ActionStatusCreate c) { + final JpaActionStatusCreate create = (JpaActionStatusCreate) c; + + final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId()); + + if (!action.isCancelingOrCanceled()) { + throw new CancelActionNotAllowedException("The action is not in canceling state."); + } + + final JpaActionStatus actionStatus = create.build(); + + switch (actionStatus.getStatus()) { + case CANCELED: + case FINISHED: + handleFinishedCancelation(actionStatus, action); + break; + case ERROR: + case CANCEL_REJECTED: + // Cancellation rejected. Back to running. + action.setStatus(Status.RUNNING); + break; + default: + // information status entry - check for a potential DOS attack + assertActionStatusQuota(actionStatus, action); + assertActionStatusMessageQuota(actionStatus); + break; + } + + actionStatus.setAction(actionRepository.save(action)); + actionStatusRepository.save(actionStatus); + + return action; + } + + @Override + public Optional getSoftwareModule(final long id) { + return softwareModuleRepository.findById(id).map(s -> (SoftwareModule) s); + } + + @Override + public Map> findTargetVisibleMetaDataBySoftwareModuleId( + final Collection moduleId) { + + return softwareModuleMetadataRepository + .findBySoftwareModuleIdInAndTargetVisible(PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT), + moduleId, true) + .getContent().stream().collect(Collectors.groupingBy(o -> (Long) o[0], + Collectors.mapping(o -> (SoftwareModuleMetadata) o[1], Collectors.toList()))); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public ActionStatus addInformationalActionStatus(final ActionStatusCreate c) { + final JpaActionStatusCreate create = (JpaActionStatusCreate) c; + final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId()); + final JpaActionStatus statusMessage = create.build(); + statusMessage.setAction(action); + + assertActionStatusQuota(statusMessage, action); + assertActionStatusMessageQuota(statusMessage); + + return actionStatusRepository.save(statusMessage); + } + + @Override + @Transactional(isolation = Isolation.READ_COMMITTED) + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Action addUpdateActionStatus(final ActionStatusCreate statusCreate) { + return addActionStatus((JpaActionStatusCreate) statusCreate); + } + + @Override + public Optional findActiveActionWithHighestWeight(final String controllerId) { + return findActiveActionsWithHighestWeight(controllerId, 1).stream().findFirst(); + } + + @Override + public List findActiveActionsWithHighestWeight(final String controllerId, final int maxActionCount) { + return findActiveActionsWithHighestWeightConsideringDefault(controllerId, maxActionCount); + } + + @Override + public Optional findActionWithDetails(final long actionId) { + return actionRepository.findWithDetailsById(actionId); + } + + @Override + public Page findActionStatusByAction(final Pageable pageReq, final long actionId) { + if (!actionRepository.existsById(actionId)) { + throw new EntityNotFoundException(Action.class, actionId); + } + + return actionStatusRepository.findByActionId(pageReq, actionId); + } + + @Override + @Transactional(isolation = Isolation.READ_COMMITTED) + @Retryable(include = ConcurrencyFailureException.class, exclude = EntityAlreadyExistsException.class, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Target findOrRegisterTargetIfItDoesNotExist(final String controllerId, final URI address) { + return findOrRegisterTargetIfItDoesNotExist(controllerId, address, null, null); + } + + @Override + @Transactional(isolation = Isolation.READ_COMMITTED) + @Retryable(include = ConcurrencyFailureException.class, exclude = EntityAlreadyExistsException.class, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Target findOrRegisterTargetIfItDoesNotExist(final String controllerId, final URI address, + final String name, final String type) { + final Specification spec = + (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.controllerId), controllerId); + + return targetRepository.findOne(spec).map(target -> updateTarget(target, address, name, type)) + .orElseGet(() -> createTarget(controllerId, address, name, type)); + } + + @Override + public Optional getActionForDownloadByTargetAndSoftwareModule(final String controllerId, + final long moduleId) { + throwExceptionIfTargetDoesNotExist(controllerId); + throwExceptionIfSoftwareModuleDoesNotExist(moduleId); + + // it used to perform 3-table join query + // @Query("Select a from JpaAction a join a.distributionSet ds join ds.modules modul where a.target.controllerId = :target and modul.id = :module order by a.id desc") + // final List actions = actionRepository.findActionByTargetAndSoftwareModule(controllerId, moduleId); + // TODO AC - we could fetch distribution sets in order to skip calls to serarch for modules + return actionRepository + .findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, true)) + .stream() + .filter(action -> !action.isCancelingOrCanceled()) + .filter(action -> action.getDistributionSet().getModules() + .stream() + .anyMatch(module -> module.getId() == moduleId)) + .map(Action.class::cast) + .findFirst(); + } + @Override public String getPollingTime() { return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement @@ -228,108 +395,265 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont .timeToNextEvent(getMaintenanceWindowPollCount(), action.getMaintenanceWindowStartTime().orElse(null)); } - /** - * EventTimer to handle reduction of polling interval based on maintenance - * window start time. Class models the next polling time as an event to be - * raised and time to next polling as a timer. The event, in this case the - * polling, should happen when timer expires. Class makes use of java.time - * package to manipulate and calculate timer duration. - */ - private static class EventTimer { + @Override + public boolean hasTargetArtifactAssigned(final String controllerId, final String sha1Hash) { + throwExceptionIfTargetDoesNotExist(controllerId); + return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(controllerId, sha1Hash)) > 0; + } - private final String defaultEventInterval; - private final Duration defaultEventIntervalDuration; + @Override + public boolean hasTargetArtifactAssigned(final long targetId, final String sha1Hash) { + throwExceptionIfTargetDoesNotExist(targetId); + return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(targetId, sha1Hash)) > 0; + } - private final String minimumEventInterval; - private final Duration minimumEventIntervalDuration; + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Action registerRetrieved(final long actionId, final String message) { + return handleRegisterRetrieved(actionId, message); + } - private final TemporalUnit timeUnit; + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Target updateControllerAttributes(final String controllerId, final Map data, + final UpdateMode mode) { - /** - * Constructor. - * - * @param defaultEventInterval - * default timer value to use for interval between events. - * This puts an upper bound for the timer value - * @param minimumEventInterval - * for loading {@link DistributionSet#getModules()}. This - * puts a lower bound to the timer value - * @param timeUnit - * representing the unit of time to be used for timer. + /* + * Constraints on attribute keys & values are not validated by + * EclipseLink. Hence, they are validated here. */ - EventTimer(final String defaultEventInterval, final String minimumEventInterval, final TemporalUnit timeUnit) { - this.defaultEventInterval = defaultEventInterval; - this.defaultEventIntervalDuration = MaintenanceScheduleHelper.convertToISODuration(defaultEventInterval); - - this.minimumEventInterval = minimumEventInterval; - this.minimumEventIntervalDuration = MaintenanceScheduleHelper.convertToISODuration(minimumEventInterval); - - this.timeUnit = timeUnit; + if (data.entrySet().stream().anyMatch(e -> !isAttributeEntryValid(e))) { + throw new InvalidTargetAttributeException(); } - /** - * This method calculates the time interval until the next event based - * on the desired number of events before the time when interval is - * reset to default. The return value is bounded by - * {@link EventTimer#defaultEventInterval} and - * {@link EventTimer#minimumEventInterval}. - * - * @param eventCount - * number of events desired until the interval is reset to - * default. This is not guaranteed as the interval between - * events cannot be less than the minimum interval - * @param timerResetTime - * time when exponential forwarding should reset to default - * - * @return String in HH:mm:ss format for time to next event. - */ - String timeToNextEvent(final int eventCount, final ZonedDateTime timerResetTime) { - final ZonedDateTime currentTime = ZonedDateTime.now(); + final JpaTarget target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) + .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); - // If there is no reset time, or if we already past the reset time, - // return the default interval. - if (timerResetTime == null || currentTime.compareTo(timerResetTime) > 0) { - return defaultEventInterval; - } + // get the modifiable attribute map + final Map controllerAttributes = target.getControllerAttributes(); + final UpdateMode updateMode = mode != null ? mode : UpdateMode.MERGE; + switch (updateMode) { + case REMOVE: + // remove the addressed attributes + data.keySet().forEach(controllerAttributes::remove); + break; + case REPLACE: + // clear the attributes before adding the new attributes + controllerAttributes.clear(); + copy(data, controllerAttributes); + target.setRequestControllerAttributes(false); + break; + case MERGE: + // just merge the attributes in + copy(data, controllerAttributes); + target.setRequestControllerAttributes(false); + break; + default: + // unknown update mode + throw new IllegalStateException("The update mode " + updateMode + " is not supported."); + } + assertTargetAttributesQuota(target); - // Calculate the interval timer based on desired event count. - final Duration currentIntervalDuration = Duration.of(currentTime.until(timerResetTime, timeUnit), timeUnit) - .dividedBy(eventCount); + return targetRepository.save(target); + } - // Need not return interval greater than the default. - if (currentIntervalDuration.compareTo(defaultEventIntervalDuration) > 0) { - return defaultEventInterval; - } + @Override + public Optional getByControllerId(final String controllerId) { + return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)).map(Target.class::cast); + } - // Should not return interval less than minimum. - if (currentIntervalDuration.compareTo(minimumEventIntervalDuration) < 0) { - return minimumEventInterval; - } + @Override + public Optional get(final long targetId) { + return targetRepository.findById(targetId).map(t -> (Target) t); + } - return String.format("%02d:%02d:%02d", currentIntervalDuration.toHours(), - currentIntervalDuration.toMinutes() % 60, currentIntervalDuration.getSeconds() % 60); + @Override + public List getActionHistoryMessages(final long actionId, final int messageCount) { + // Just return empty list in case messageCount is zero. + if (messageCount == 0) { + return Collections.emptyList(); + } + + // For negative and large value of messageCount, limit the number of + // messages. + final int limit = messageCount < 0 || messageCount >= RepositoryConstants.MAX_ACTION_HISTORY_MSG_COUNT + ? RepositoryConstants.MAX_ACTION_HISTORY_MSG_COUNT + : messageCount; + + final PageRequest pageable = PageRequest.of(0, limit, Sort.by(Direction.DESC, "occurredAt")); + final Page messages = actionStatusRepository.findMessagesByActionIdAndMessageNotLike(pageable, actionId, + RepositoryConstants.SERVER_MESSAGE_PREFIX + "%"); + + log.debug("Retrieved {} message(s) from action history for action {}.", messages.getNumberOfElements(), + actionId); + + return messages.getContent(); + } + + /** + * Cancels given {@link Action} for this {@link Target}. The method will + * immediately add a {@link Status#CANCELED} status to the action. However, + * it might be possible that the controller will continue to work on the + * cancellation. The controller needs to acknowledge or reject the + * cancellation using {@link DdiRootController#postCancelActionFeedback}. + * + * @param actionId to be canceled + * @return canceled {@link Action} + * @throws CancelActionNotAllowedException in case the given action is not active or is already canceled + * @throws EntityNotFoundException if action with given actionId does not exist. + */ + @Override + @Modifying + @Transactional(isolation = Isolation.READ_COMMITTED) + public Action cancelAction(final long actionId) { + log.debug("cancelAction({})", actionId); + + final JpaAction action = actionRepository.findById(actionId) + .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); + + if (action.isCancelingOrCanceled()) { + throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled"); + } + + if (action.isActive()) { + log.debug("action ({}) was still active. Change to {}.", action, Status.CANCELING); + action.setStatus(Status.CANCELING); + + // document that the status has been retrieved + actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELING, System.currentTimeMillis(), + "manual cancelation requested")); + final Action saveAction = actionRepository.save(action); + cancelAssignDistributionSetEvent(action); + + return saveAction; + } else { + throw new CancelActionNotAllowedException( + "Action [id: " + action.getId() + "] is not active and cannot be canceled"); } } @Override - public Optional getActionForDownloadByTargetAndSoftwareModule(final String controllerId, - final long moduleId) { - throwExceptionIfTargetDoesNotExist(controllerId); - throwExceptionIfSoftwareModuleDoesNotExist(moduleId); + public void updateActionExternalRef(final long actionId, @NotEmpty final String externalRef) { + // if access control for target repository is present check that caller has + // UPDATE access to the target of the action + targetRepository.getAccessController().ifPresent( + accessController -> accessController.assertOperationAllowed( + AccessController.Operation.UPDATE, + (JpaTarget) actionRepository + .findById(actionId) + .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)) + .getTarget())); + actionRepository.updateExternalRef(actionId, externalRef); + } - // it used to perform 3-table join query - // @Query("Select a from JpaAction a join a.distributionSet ds join ds.modules modul where a.target.controllerId = :target and modul.id = :module order by a.id desc") - // final List actions = actionRepository.findActionByTargetAndSoftwareModule(controllerId, moduleId); - // TODO AC - we could fetch distribution sets in order to skip calls to serarch for modules - return actionRepository - .findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, true)) - .stream() - .filter(action -> !action.isCancelingOrCanceled()) - .filter(action -> action.getDistributionSet().getModules() - .stream() - .anyMatch(module -> module.getId() == moduleId)) - .map(Action.class::cast) - .findFirst(); + @Override + public Optional getActionByExternalRef(@NotEmpty final String externalRef) { + return actionRepository.findByExternalRef(externalRef); + } + + @Override + public void deleteExistingTarget(@NotEmpty final String controllerId) { + final Target target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) + .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); + targetRepository.deleteById(target.getId()); + } + + @Override + public Optional getInstalledActionByTarget(final String controllerId) { + final JpaTarget jpaTarget = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) + .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); + + final JpaDistributionSet installedDistributionSet = jpaTarget.getInstalledDistributionSet(); + if (null != installedDistributionSet) { + return actionRepository.findFirstByTargetIdAndDistributionSetIdAndStatusOrderByIdDesc(jpaTarget.getId(), + installedDistributionSet.getId(), FINISHED); + } else { + return Optional.empty(); + } + } + + @Override + public AutoConfirmationStatus activateAutoConfirmation(final String controllerId, final String initiator, + final String remark) { + return confirmationManagement.activateAutoConfirmation(controllerId, initiator, remark); + } + + @Override + public void deactivateAutoConfirmation(final String controllerId) { + confirmationManagement.deactivateAutoConfirmation(controllerId); + } + + @Override + public boolean updateOfflineAssignedVersion(@NotEmpty final String controllerId, final String distributionName, final String version) { + List distributionSetAssignmentResults = + systemSecurityContext.runAsSystem(() -> + distributionSetManagement.getByNameAndVersion(distributionName, version).map( + distributionSet -> deploymentManagement.offlineAssignedDistributionSets( + List.of(Map.entry(controllerId, distributionSet.getId())), controllerId)) + .orElseThrow(() -> + new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version)))); + + return distributionSetAssignmentResults.stream().findFirst() + .map(result -> result.getAlreadyAssigned() == 0) + .orElseThrow(); + } + + Optional getTargetType(String targetTypeName) { + return systemSecurityContext.runAsSystem(() -> targetTypeManagement.getByName(targetTypeName)); + } + + // for testing + void setTargetRepository(final TargetRepository targetRepositorySpy) { + this.targetRepository = targetRepositorySpy; + } + + private static String formatQueryInStatementParams(final Collection paramNames) { + return "#" + String.join(",#", paramNames); + } + + private static boolean isAddressChanged(final URI addressToUpdate, final URI address) { + return addressToUpdate == null || !addressToUpdate.equals(address); + } + + private static boolean isNameChanged(final String nameToUpdate, final String name) { + return StringUtils.hasText(name) && !nameToUpdate.equals(name); + } + + private static boolean isTypeChanged(final TargetType targetTypeToUpdate, final String type) { + return (type != null) && (targetTypeToUpdate == null || !targetTypeToUpdate.getName().equals(type)); + } + + private static boolean isStatusUnknown(final TargetUpdateStatus statusToUpdate) { + return TargetUpdateStatus.UNKNOWN == statusToUpdate; + } + + private static boolean isAttributeEntryValid(final Map.Entry e) { + return isAttributeKeyValid(e.getKey()) && isAttributeValueValid(e.getValue()); + } + + private static boolean isAttributeKeyValid(final String key) { + return key != null && key.length() <= CONTROLLER_ATTRIBUTE_KEY_SIZE; + } + + private static boolean isAttributeValueValid(final String value) { + return value == null || value.length() <= CONTROLLER_ATTRIBUTE_VALUE_SIZE; + } + + private static void copy(final Map src, final Map trg) { + if (src == null || src.isEmpty()) { + return; + } + src.forEach((key, value) -> { + if (value != null) { + trg.put(key, value); + } else { + trg.remove(key); + } + }); } private void throwExceptionIfTargetDoesNotExist(final String controllerId) { @@ -350,64 +674,6 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } } - @Override - public boolean hasTargetArtifactAssigned(final String controllerId, final String sha1Hash) { - throwExceptionIfTargetDoesNotExist(controllerId); - return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(controllerId, sha1Hash)) > 0; - } - - @Override - public boolean hasTargetArtifactAssigned(final long targetId, final String sha1Hash) { - throwExceptionIfTargetDoesNotExist(targetId); - return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(targetId, sha1Hash)) > 0; - } - - @Override - public Optional findActiveActionWithHighestWeight(final String controllerId) { - return findActiveActionsWithHighestWeight(controllerId, 1).stream().findFirst(); - } - - @Override - public List findActiveActionsWithHighestWeight(final String controllerId, final int maxActionCount) { - return findActiveActionsWithHighestWeightConsideringDefault(controllerId, maxActionCount); - } - - @Override - public int getWeightConsideringDefault(final Action action) { - return super.getWeightConsideringDefault(action); - } - - @Override - public Optional findActionWithDetails(final long actionId) { - return actionRepository.findWithDetailsById(actionId); - } - - @Override - public void deleteExistingTarget(@NotEmpty final String controllerId) { - final Target target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) - .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); - targetRepository.deleteById(target.getId()); - } - - @Override - @Transactional(isolation = Isolation.READ_COMMITTED) - @Retryable(include = ConcurrencyFailureException.class, exclude = EntityAlreadyExistsException.class, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Target findOrRegisterTargetIfItDoesNotExist(final String controllerId, final URI address) { - return findOrRegisterTargetIfItDoesNotExist(controllerId, address, null, null); - } - - @Override - @Transactional(isolation = Isolation.READ_COMMITTED) - @Retryable(include = ConcurrencyFailureException.class, exclude = EntityAlreadyExistsException.class, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Target findOrRegisterTargetIfItDoesNotExist(final String controllerId, final URI address, - final String name, final String type) { - final Specification spec = - (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.controllerId), controllerId); - - return targetRepository.findOne(spec).map(target -> updateTarget(target, address, name, type)) - .orElseGet(() -> createTarget(controllerId, address, name, type)); - } - private Target createTarget(final String controllerId, final URI address, final String name, final String type) { log.debug("Creating target for thing ID \"{}\".", controllerId); @@ -436,10 +702,6 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont return result; } - Optional getTargetType(String targetTypeName) { - return systemSecurityContext.runAsSystem(() -> targetTypeManagement.getByName(targetTypeName)); - } - /** * Flush the update queue by means to persisting * {@link Target#getLastTargetQuery()}. @@ -518,15 +780,10 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } } - private static String formatQueryInStatementParams(final Collection paramNames) { - return "#" + String.join(",#", paramNames); - } - /** * Stores target directly to DB in case either {@link Target#getAddress()} * or {@link Target#getUpdateStatus()} or {@link Target#getName()} changes * or the buffer queue is full. - * */ private Target updateTarget(final JpaTarget toUpdate, final URI address, final String name, final String type) { if (isStoreEager(toUpdate, address, name, type) || !queue.offer(new TargetPoll(toUpdate))) { @@ -569,60 +826,6 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont || isStatusUnknown(toUpdate.getUpdateStatus()); } - private static boolean isAddressChanged(final URI addressToUpdate, final URI address) { - return addressToUpdate == null || !addressToUpdate.equals(address); - } - - private static boolean isNameChanged(final String nameToUpdate, final String name) { - return StringUtils.hasText(name) && !nameToUpdate.equals(name); - } - - private static boolean isTypeChanged(final TargetType targetTypeToUpdate, final String type) { - return (type != null) && (targetTypeToUpdate == null || !targetTypeToUpdate.getName().equals(type)); - } - - private static boolean isStatusUnknown(final TargetUpdateStatus statusToUpdate) { - return TargetUpdateStatus.UNKNOWN == statusToUpdate; - } - - @Override - @Transactional(isolation = Isolation.READ_COMMITTED) - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Action addCancelActionStatus(final ActionStatusCreate c) { - final JpaActionStatusCreate create = (JpaActionStatusCreate) c; - - final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId()); - - if (!action.isCancelingOrCanceled()) { - throw new CancelActionNotAllowedException("The action is not in canceling state."); - } - - final JpaActionStatus actionStatus = create.build(); - - switch (actionStatus.getStatus()) { - case CANCELED: - case FINISHED: - handleFinishedCancelation(actionStatus, action); - break; - case ERROR: - case CANCEL_REJECTED: - // Cancellation rejected. Back to running. - action.setStatus(Status.RUNNING); - break; - default: - // information status entry - check for a potential DOS attack - assertActionStatusQuota(actionStatus, action); - assertActionStatusMessageQuota(actionStatus); - break; - } - - actionStatus.setAction(actionRepository.save(action)); - actionStatusRepository.save(actionStatus); - - return action; - } - private void handleFinishedCancelation(final JpaActionStatus actionStatus, final JpaAction action) { // in case of successful cancellation we also report the success at // the canceled action itself. @@ -631,40 +834,12 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont DeploymentHelper.successCancellation(action, actionRepository, targetRepository); } - @Override - @Transactional(isolation = Isolation.READ_COMMITTED) - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Action addUpdateActionStatus(final ActionStatusCreate statusCreate) { - return addActionStatus((JpaActionStatusCreate) statusCreate); - } - - @Override - protected void onActionStatusUpdate(final Action.Status updatedActionStatus, final JpaAction action) { - switch (updatedActionStatus) { - case ERROR: - final JpaTarget target = (JpaTarget) action.getTarget(); - target.setUpdateStatus(TargetUpdateStatus.ERROR); - handleErrorOnAction(action, target); - break; - case FINISHED: - handleFinishedAndStoreInTargetStatus(action).ifPresent(this::requestControllerAttributes); - break; - case DOWNLOADED: - handleDownloadedActionStatus(action).ifPresent(this::requestControllerAttributes); - break; - default: - break; - } - } - /** * Handles the case where the {@link Action.Status#DOWNLOADED} status is * reported by the device. In case the update is finished, a controllerId * will be returned to trigger a request for attributes. * - * @param action - * updated action + * @param action updated action * @return a present controllerId in case the attributes needs to be * requested. */ @@ -707,8 +882,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont * reported by the device. In case the update is finished, a controllerId * will be returned to trigger a request for attributes. * - * @param action - * updated action + * @param action updated action * @return a present controllerId in case the attributes needs to be * requested. */ @@ -742,99 +916,18 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont return Optional.of(target.getControllerId()); } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Target updateControllerAttributes(final String controllerId, final Map data, - final UpdateMode mode) { - - /* - * Constraints on attribute keys & values are not validated by - * EclipseLink. Hence, they are validated here. - */ - if (data.entrySet().stream().anyMatch(e -> !isAttributeEntryValid(e))) { - throw new InvalidTargetAttributeException(); - } - - final JpaTarget target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) - .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); - - // get the modifiable attribute map - final Map controllerAttributes = target.getControllerAttributes(); - final UpdateMode updateMode = mode != null ? mode : UpdateMode.MERGE; - switch (updateMode) { - case REMOVE: - // remove the addressed attributes - data.keySet().forEach(controllerAttributes::remove); - break; - case REPLACE: - // clear the attributes before adding the new attributes - controllerAttributes.clear(); - copy(data, controllerAttributes); - target.setRequestControllerAttributes(false); - break; - case MERGE: - // just merge the attributes in - copy(data, controllerAttributes); - target.setRequestControllerAttributes(false); - break; - default: - // unknown update mode - throw new IllegalStateException("The update mode " + updateMode + " is not supported."); - } - assertTargetAttributesQuota(target); - - return targetRepository.save(target); - } - - private static boolean isAttributeEntryValid(final Map.Entry e) { - return isAttributeKeyValid(e.getKey()) && isAttributeValueValid(e.getValue()); - } - - private static boolean isAttributeKeyValid(final String key) { - return key != null && key.length() <= CONTROLLER_ATTRIBUTE_KEY_SIZE; - } - - private static boolean isAttributeValueValid(final String value) { - return value == null || value.length() <= CONTROLLER_ATTRIBUTE_VALUE_SIZE; - } - - private static void copy(final Map src, final Map trg) { - if (src == null || src.isEmpty()) { - return; - } - src.forEach((key, value) -> { - if (value != null) { - trg.put(key, value); - } else { - trg.remove(key); - } - }); - } - private void assertTargetAttributesQuota(final JpaTarget target) { final int limit = quotaManagement.getMaxAttributeEntriesPerTarget(); QuotaHelper.assertAssignmentQuota(target.getId(), target.getControllerAttributes().size(), limit, "Attribute", Target.class.getSimpleName(), null); } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Action registerRetrieved(final long actionId, final String message) { - return handleRegisterRetrieved(actionId, message); - } - /** * Registers retrieved status for given {@link Target} and {@link Action} if * it does not exist yet. * - * @param actionId - * to the handle status for - * @param message - * for the status + * @param actionId to the handle status for + * @param message for the status * @return the updated action in case the status has been changed to * {@link Status#RETRIEVED} */ @@ -880,78 +973,86 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont return action; } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public ActionStatus addInformationalActionStatus(final ActionStatusCreate c) { - final JpaActionStatusCreate create = (JpaActionStatusCreate) c; - final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId()); - final JpaActionStatus statusMessage = create.build(); - statusMessage.setAction(action); - - assertActionStatusQuota(statusMessage, action); - assertActionStatusMessageQuota(statusMessage); - - return actionStatusRepository.save(statusMessage); + private void cancelAssignDistributionSetEvent(final Action action) { + afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher() + .publishEvent(new CancelTargetAssignmentEvent(action, eventPublisherHolder.getApplicationId()))); } - @Override - public Optional getByControllerId(final String controllerId) { - return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)).map(Target.class::cast); - } + /** + * EventTimer to handle reduction of polling interval based on maintenance + * window start time. Class models the next polling time as an event to be + * raised and time to next polling as a timer. The event, in this case the + * polling, should happen when timer expires. Class makes use of java.time + * package to manipulate and calculate timer duration. + */ + private static class EventTimer { - @Override - public Optional get(final long targetId) { - return targetRepository.findById(targetId).map(t -> (Target) t); - } + private final String defaultEventInterval; + private final Duration defaultEventIntervalDuration; - @Override - public Page findActionStatusByAction(final Pageable pageReq, final long actionId) { - if (!actionRepository.existsById(actionId)) { - throw new EntityNotFoundException(Action.class, actionId); + private final String minimumEventInterval; + private final Duration minimumEventIntervalDuration; + + private final TemporalUnit timeUnit; + + /** + * Constructor. + * + * @param defaultEventInterval default timer value to use for interval between events. + * This puts an upper bound for the timer value + * @param minimumEventInterval for loading {@link DistributionSet#getModules()}. This + * puts a lower bound to the timer value + * @param timeUnit representing the unit of time to be used for timer. + */ + EventTimer(final String defaultEventInterval, final String minimumEventInterval, final TemporalUnit timeUnit) { + this.defaultEventInterval = defaultEventInterval; + this.defaultEventIntervalDuration = MaintenanceScheduleHelper.convertToISODuration(defaultEventInterval); + + this.minimumEventInterval = minimumEventInterval; + this.minimumEventIntervalDuration = MaintenanceScheduleHelper.convertToISODuration(minimumEventInterval); + + this.timeUnit = timeUnit; } - return actionStatusRepository.findByActionId(pageReq, actionId); - } + /** + * This method calculates the time interval until the next event based + * on the desired number of events before the time when interval is + * reset to default. The return value is bounded by + * {@link EventTimer#defaultEventInterval} and + * {@link EventTimer#minimumEventInterval}. + * + * @param eventCount number of events desired until the interval is reset to + * default. This is not guaranteed as the interval between + * events cannot be less than the minimum interval + * @param timerResetTime time when exponential forwarding should reset to default + * @return String in HH:mm:ss format for time to next event. + */ + String timeToNextEvent(final int eventCount, final ZonedDateTime timerResetTime) { + final ZonedDateTime currentTime = ZonedDateTime.now(); - @Override - public List getActionHistoryMessages(final long actionId, final int messageCount) { - // Just return empty list in case messageCount is zero. - if (messageCount == 0) { - return Collections.emptyList(); + // If there is no reset time, or if we already past the reset time, + // return the default interval. + if (timerResetTime == null || currentTime.compareTo(timerResetTime) > 0) { + return defaultEventInterval; + } + + // Calculate the interval timer based on desired event count. + final Duration currentIntervalDuration = Duration.of(currentTime.until(timerResetTime, timeUnit), timeUnit) + .dividedBy(eventCount); + + // Need not return interval greater than the default. + if (currentIntervalDuration.compareTo(defaultEventIntervalDuration) > 0) { + return defaultEventInterval; + } + + // Should not return interval less than minimum. + if (currentIntervalDuration.compareTo(minimumEventIntervalDuration) < 0) { + return minimumEventInterval; + } + + return String.format("%02d:%02d:%02d", currentIntervalDuration.toHours(), + currentIntervalDuration.toMinutes() % 60, currentIntervalDuration.getSeconds() % 60); } - - // For negative and large value of messageCount, limit the number of - // messages. - final int limit = messageCount < 0 || messageCount >= RepositoryConstants.MAX_ACTION_HISTORY_MSG_COUNT - ? RepositoryConstants.MAX_ACTION_HISTORY_MSG_COUNT - : messageCount; - - final PageRequest pageable = PageRequest.of(0, limit, Sort.by(Direction.DESC, "occurredAt")); - final Page messages = actionStatusRepository.findMessagesByActionIdAndMessageNotLike(pageable, actionId, - RepositoryConstants.SERVER_MESSAGE_PREFIX + "%"); - - log.debug("Retrieved {} message(s) from action history for action {}.", messages.getNumberOfElements(), - actionId); - - return messages.getContent(); - } - - @Override - public Optional getSoftwareModule(final long id) { - return softwareModuleRepository.findById(id).map(s -> (SoftwareModule) s); - } - - @Override - public Map> findTargetVisibleMetaDataBySoftwareModuleId( - final Collection moduleId) { - - return softwareModuleMetadataRepository - .findBySoftwareModuleIdInAndTargetVisible(PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT), - moduleId, true) - .getContent().stream().collect(Collectors.groupingBy(o -> (Long) o[0], - Collectors.mapping(o -> (SoftwareModuleMetadata) o[1], Collectors.toList()))); } private static class TargetPoll { @@ -1011,120 +1112,4 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } } - - /** - * Cancels given {@link Action} for this {@link Target}. The method will - * immediately add a {@link Status#CANCELED} status to the action. However, - * it might be possible that the controller will continue to work on the - * cancellation. The controller needs to acknowledge or reject the - * cancellation using {@link DdiRootController#postCancelActionFeedback}. - * - * @param actionId - * to be canceled - * - * @return canceled {@link Action} - * - * @throws CancelActionNotAllowedException - * in case the given action is not active or is already canceled - * @throws EntityNotFoundException - * if action with given actionId does not exist. - */ - @Override - @Modifying - @Transactional(isolation = Isolation.READ_COMMITTED) - public Action cancelAction(final long actionId) { - log.debug("cancelAction({})", actionId); - - final JpaAction action = actionRepository.findById(actionId) - .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); - - if (action.isCancelingOrCanceled()) { - throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled"); - } - - if (action.isActive()) { - log.debug("action ({}) was still active. Change to {}.", action, Status.CANCELING); - action.setStatus(Status.CANCELING); - - // document that the status has been retrieved - actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELING, System.currentTimeMillis(), - "manual cancelation requested")); - final Action saveAction = actionRepository.save(action); - cancelAssignDistributionSetEvent(action); - - return saveAction; - } else { - throw new CancelActionNotAllowedException( - "Action [id: " + action.getId() + "] is not active and cannot be canceled"); - } - } - - @Override - public void updateActionExternalRef(final long actionId, @NotEmpty final String externalRef) { - // if access control for target repository is present check that caller has - // UPDATE access to the target of the action - targetRepository.getAccessController().ifPresent( - accessController -> accessController.assertOperationAllowed( - AccessController.Operation.UPDATE, - (JpaTarget) actionRepository - .findById(actionId) - .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)) - .getTarget())); - actionRepository.updateExternalRef(actionId, externalRef); - } - - @Override - public Optional getActionByExternalRef(@NotEmpty final String externalRef) { - return actionRepository.findByExternalRef(externalRef); - } - - @Override - public Optional getInstalledActionByTarget(final String controllerId) { - final JpaTarget jpaTarget = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) - .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); - - final JpaDistributionSet installedDistributionSet = jpaTarget.getInstalledDistributionSet(); - if (null != installedDistributionSet) { - return actionRepository.findFirstByTargetIdAndDistributionSetIdAndStatusOrderByIdDesc(jpaTarget.getId(), - installedDistributionSet.getId(), FINISHED); - } else { - return Optional.empty(); - } - } - - @Override - public AutoConfirmationStatus activateAutoConfirmation(final String controllerId, final String initiator, - final String remark) { - return confirmationManagement.activateAutoConfirmation(controllerId, initiator, remark); - } - - @Override - public void deactivateAutoConfirmation(final String controllerId) { - confirmationManagement.deactivateAutoConfirmation(controllerId); - } - - @Override - public boolean updateOfflineAssignedVersion(@NotEmpty final String controllerId, final String distributionName, final String version){ - List distributionSetAssignmentResults = - systemSecurityContext.runAsSystem(() -> - distributionSetManagement.getByNameAndVersion(distributionName,version).map( - distributionSet -> deploymentManagement.offlineAssignedDistributionSets( - List.of(Map.entry(controllerId, distributionSet.getId())),controllerId)) - .orElseThrow(() -> - new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version)))); - - return distributionSetAssignmentResults.stream().findFirst() - .map(result-> result.getAlreadyAssigned()==0) - .orElseThrow(); - } - - private void cancelAssignDistributionSetEvent(final Action action) { - afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher() - .publishEvent(new CancelTargetAssignmentEvent(action, eventPublisherHolder.getApplicationId()))); - } - - // for testing - void setTargetRepository(final TargetRepository targetRepositorySpy) { - this.targetRepository = targetRepositorySpy; - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java index 69f9bb1b4..93a43ca7f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java @@ -127,16 +127,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl + ACTION_PAGE_LIMIT; private static final EnumMap QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED; - - static { - QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED = new EnumMap<>(Database.class); - QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(Database.SQL_SERVER, "DELETE TOP (" + ACTION_PAGE_LIMIT - + ") FROM sp_action WHERE tenant=#tenant AND status IN (%s) AND last_modified_at<#last_modified_at "); - QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(Database.POSTGRESQL, - "DELETE FROM sp_action WHERE id IN (SELECT id FROM sp_action WHERE tenant=#tenant AND status IN (%s) AND last_modified_at<#last_modified_at LIMIT " - + ACTION_PAGE_LIMIT + ")"); - } - private final EntityManager entityManager; private final DistributionSetManagement distributionSetManagement; private final TargetRepository targetRepository; @@ -152,6 +142,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl private final Database database; private final RetryTemplate retryTemplate; + static { + QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED = new EnumMap<>(Database.class); + QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(Database.SQL_SERVER, "DELETE TOP (" + ACTION_PAGE_LIMIT + + ") FROM sp_action WHERE tenant=#tenant AND status IN (%s) AND last_modified_at<#last_modified_at "); + QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(Database.POSTGRESQL, + "DELETE FROM sp_action WHERE id IN (SELECT id FROM sp_action WHERE tenant=#tenant AND status IN (%s) AND last_modified_at<#last_modified_at LIMIT " + + ACTION_PAGE_LIMIT + ")"); + } + public JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository, final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository, final ActionStatusRepository actionStatusRepository, final AuditorAware auditorProvider, @@ -183,9 +182,18 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Override @Transactional(isolation = Isolation.READ_COMMITTED) - public List offlineAssignedDistributionSets( - final Collection> assignments) { - return offlineAssignedDistributionSets(assignments,tenantAware.getCurrentUsername()); + public List assignDistributionSets( + final List deploymentRequests) { + return assignDistributionSets(tenantAware.getCurrentUsername(), deploymentRequests, null); + } + + @Override + @Transactional(isolation = Isolation.READ_COMMITTED) + public List assignDistributionSets(final String initiatedBy, + final List deploymentRequests, final String actionMessage) { + WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement) + .validate(deploymentRequests); + return assignDistributionSets(initiatedBy, deploymentRequests, actionMessage, onlineDsAssignmentStrategy); } @Override @@ -205,18 +213,422 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Override @Transactional(isolation = Isolation.READ_COMMITTED) - public List assignDistributionSets( - final List deploymentRequests) { - return assignDistributionSets(tenantAware.getCurrentUsername(), deploymentRequests, null); + public List offlineAssignedDistributionSets( + final Collection> assignments) { + return offlineAssignedDistributionSets(assignments, tenantAware.getCurrentUsername()); } @Override @Transactional(isolation = Isolation.READ_COMMITTED) - public List assignDistributionSets(final String initiatedBy, - final List deploymentRequests, final String actionMessage) { - WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement) - .validate(deploymentRequests); - return assignDistributionSets(initiatedBy, deploymentRequests, actionMessage, onlineDsAssignmentStrategy); + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Action cancelAction(final long actionId) { + log.debug("cancelAction({})", actionId); + + final JpaAction action = actionRepository.findById(actionId) + .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); + + if (action.isCancelingOrCanceled()) { + throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled"); + } + + assertTargetUpdateAllowed(action); + + if (action.isActive()) { + log.debug("action ({}) was still active. Change to {}.", action, Status.CANCELING); + action.setStatus(Status.CANCELING); + + // document that the status has been retrieved + actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELING, System.currentTimeMillis(), + RepositoryConstants.SERVER_MESSAGE_PREFIX + "manual cancelation requested")); + final Action saveAction = actionRepository.save(action); + + onlineDsAssignmentStrategy.cancelAssignment(action); + + return saveAction; + } else { + throw new CancelActionNotAllowedException(action.getId() + " is not active and cannot be canceled"); + } + } + + @Override + public long countActionsByTarget(final String rsqlParam, final String controllerId) { + assertTargetReadAllowed(controllerId); + + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database), + ActionSpecifications.byTargetControllerId(controllerId)); + + return JpaManagementHelper.countBySpec(actionRepository, specList); + } + + @Override + public long countActionsAll() { + return actionRepository.count(); + } + + @Override + public long countActions(final String rsqlParam) { + final List> specList = List.of( + RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database)); + return JpaManagementHelper.countBySpec(actionRepository, specList); + } + + @Override + public long countActionsByTarget(final String controllerId) { + assertTargetReadAllowed(controllerId); + return actionRepository.countByTargetControllerId(controllerId); + } + + @Override + public Optional findAction(final long actionId) { + return actionRepository.findById(actionId) + .filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))) + .map(JpaAction.class::cast); + } + + @Override + public Slice findActionsAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, pageable, null); + } + + @Override + public Slice findActions(final String rsqlParam, final Pageable pageable) { + final List> specList = List.of( + RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database)); + return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, pageable, specList); + } + + @Override + public Page findActionsByTarget(final String rsqlParam, final String controllerId, + final Pageable pageable) { + assertTargetReadAllowed(controllerId); + + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database), + ActionSpecifications.byTargetControllerId(controllerId)); + + return JpaManagementHelper.findAllWithCountBySpec(actionRepository, pageable, specList); + } + + @Override + public Slice findActionsByTarget(final String controllerId, final Pageable pageable) { + assertTargetReadAllowed(controllerId); + return actionRepository.findAll(ActionSpecifications.byTargetControllerId(controllerId), pageable) + .map(Action.class::cast); + } + + @Override + public Page findActionStatusByAction(final Pageable pageReq, final long actionId) { + assertActionExistsAndAccessible(actionId); + + return actionStatusRepository.findByActionId(pageReq, actionId); + } + + @Override + public long countActionStatusByAction(final long actionId) { + assertActionExistsAndAccessible(actionId); + + return actionStatusRepository.countByActionId(actionId); + } + + // action is already got and there are checked read permissions - do not check + // permissions + // and UI which is to be removed + @Override + public Page findMessagesByActionStatusId(final Pageable pageable, final long actionStatusId) { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + final CriteriaQuery msgQuery = cb.createQuery(String.class); + final Root as = msgQuery.from(JpaActionStatus.class); + final ListJoin join = as.joinList("messages", JoinType.LEFT); + final CriteriaQuery selMsgQuery = msgQuery.select(join); + selMsgQuery.where(cb.equal(as.get(JpaActionStatus_.id), actionStatusId)); + + final List result = new ArrayList<>(entityManager.createQuery(selMsgQuery) + .setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList()); + + return new PageImpl<>(result, pageable, result.size()); + } + + @Override + public Optional findActionWithDetails(final long actionId) { + return actionRepository.findWithDetailsById(actionId) + .filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))); + } + + @Override + public Page findActiveActionsByTarget(final Pageable pageable, final String controllerId) { + assertTargetReadAllowed(controllerId); + return actionRepository + .findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, true), pageable) + .map(Action.class::cast); + } + + @Override + public Page findInActiveActionsByTarget(final Pageable pageable, final String controllerId) { + assertTargetReadAllowed(controllerId); + return actionRepository + .findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, false), pageable) + .map(Action.class::cast); + } + + @Override + public List findActiveActionsWithHighestWeight(final String controllerId, final int maxActionCount) { + assertTargetReadAllowed(controllerId); + return findActiveActionsWithHighestWeightConsideringDefault(controllerId, maxActionCount); + } + + @Override + @Transactional(isolation = Isolation.READ_COMMITTED) + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Action forceQuitAction(final long actionId) { + final JpaAction action = actionRepository.findById(actionId) + .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); + + if (!action.isCancelingOrCanceled()) { + throw new ForceQuitActionNotAllowedException( + action.getId() + " is not canceled yet and cannot be force quit"); + } + + if (!action.isActive()) { + throw new ForceQuitActionNotAllowedException(action.getId() + " is not active and cannot be force quit"); + } + + assertTargetUpdateAllowed(action); + + log.warn("action ({}) was still active and has been force quite.", action); + + // document that the status has been retrieved + actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELED, System.currentTimeMillis(), + RepositoryConstants.SERVER_MESSAGE_PREFIX + "A force quit has been performed.")); + + DeploymentHelper.successCancellation(action, actionRepository, targetRepository); + + return actionRepository.save(action); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Action forceTargetAction(final long actionId) { + final JpaAction action = actionRepository.findById(actionId).map(this::assertTargetUpdateAllowed) + .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); + + if (!action.isForcedOrTimeForced()) { + action.setActionType(ActionType.FORCED); + return actionRepository.save(action); + } + return action; + } + + @Override + @Transactional(isolation = Isolation.READ_COMMITTED) + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void cancelInactiveScheduledActionsForTargets(final List targetIds) { + if (!isMultiAssignmentsEnabled()) { + targetRepository.getAccessController().ifPresent(v -> { + if (targetRepository.count(AccessController.Operation.UPDATE, + TargetSpecifications.hasIdIn(targetIds)) != targetIds.size()) { + throw new EntityNotFoundException(Target.class, targetIds); + } + }); + actionRepository.switchStatus(Status.CANCELED, targetIds, false, Status.SCHEDULED); + } else { + log.debug("The Multi Assignments feature is enabled: No need to cancel inactive scheduled actions."); + } + } + + @Override + public void startScheduledActionsByRolloutGroupParent(final long rolloutId, final long distributionSetId, + final Long rolloutGroupParentId) { + while (DeploymentHelper.runInNewTransaction( + txManager, + "startScheduledActions-" + rolloutId, + status -> { + final PageRequest pageRequest = PageRequest.of(0, ACTION_PAGE_LIMIT); + final Page groupScheduledActions; + if (rolloutGroupParentId == null) { + groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIsNullAndStatus(pageRequest, rolloutId, + Action.Status.SCHEDULED); + } else { + groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIdAndStatus(pageRequest, rolloutId, + rolloutGroupParentId, Action.Status.SCHEDULED); + } + + if (groupScheduledActions.getContent().isEmpty()) { + return 0L; + } else { + // self invocation won't check @PreAuthorize but it is already checked for the method + startScheduledActions(groupScheduledActions.getContent()); + return groupScheduledActions.getTotalElements(); + } + }) > 0) ; + } + + @Override + public void startScheduledActions(final List rolloutGroupActions) { + // Close actions already assigned and collect pending assignments + final List pendingTargetAssignments = rolloutGroupActions.stream() + .map(JpaAction.class::cast) + .map(this::closeActionIfSetWasAlreadyAssigned) + .filter(Objects::nonNull) + .toList(); + if (pendingTargetAssignments.isEmpty()) { + return; + } + // check if old actions needs to be canceled first + final List newTargetAssignments = startScheduledActionsAndHandleOpenCancellationFirst(pendingTargetAssignments); + if (!newTargetAssignments.isEmpty()) { + onlineDsAssignmentStrategy.sendDeploymentEvents(newTargetAssignments.get(0).getDistributionSet().getId(), newTargetAssignments); + } + } + + @Override + public Optional getAssignedDistributionSet(final String controllerId) { + return targetRepository + .findOne(TargetSpecifications.hasControllerId(controllerId)) + .map(JpaTarget::getAssignedDistributionSet); + } + + @Override + public Optional getInstalledDistributionSet(final String controllerId) { + return targetRepository + .findOne(TargetSpecifications.hasControllerId(controllerId)) + .map(JpaTarget::getInstalledDistributionSet); + } + + @Override + @Transactional(readOnly = false) + public int deleteActionsByStatusAndLastModifiedBefore(final Set status, final long lastModified) { + if (status.isEmpty()) { + return 0; + } + /* + * We use a native query here because Spring JPA does not support to specify a + * LIMIT clause on a DELETE statement. However, for this specific use case + * (action cleanup), we must specify a row limit to reduce the overall load on + * the database. + */ + + final int statusCount = status.size(); + final Status[] statusArr = status.toArray(new Status[statusCount]); + + final String queryStr = String.format(getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(database), + formatInClauseWithNumberKeys(statusCount)); + final Query deleteQuery = entityManager.createNativeQuery(queryStr); + + IntStream.range(0, statusCount) + .forEach(i -> deleteQuery.setParameter(String.valueOf(i), statusArr[i].ordinal())); + deleteQuery.setParameter("tenant", tenantAware.getCurrentTenant().toUpperCase()); + deleteQuery.setParameter("last_modified_at", lastModified); + + log.debug("Action cleanup: Executing the following (native) query: {}", deleteQuery); + return deleteQuery.executeUpdate(); + } + + @Override + public boolean hasPendingCancellations(final Long targetId) { + // target access checked in assertTargetReadAllowed + assertTargetReadAllowed(targetId); + return actionRepository + .exists(ActionSpecifications.byTargetIdAndIsActiveAndStatus(targetId, Action.Status.CANCELING)); + } + + @Override + @Transactional + public void cancelActionsForDistributionSet(final CancelationType cancelationType, + final DistributionSet distributionSet) { + actionRepository.findAll(ActionSpecifications + .byDistributionSetIdAndActiveAndStatusIsNot(distributionSet.getId(), Status.CANCELING)) + .forEach(action -> { + try { + assertTargetUpdateAllowed(action); + cancelAction(action.getId()); + log.debug("Action {} canceled", action.getId()); + } catch (final InsufficientPermissionException e) { + log.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e); + } catch (final EntityNotFoundException e) { + log.trace("Could not cancel action {} due to entity not found exception.", action.getId(), e); + } + }); + if (cancelationType == CancelationType.FORCE) { + actionRepository.findAll(ActionSpecifications.byDistributionSetIdAndActive(distributionSet.getId())) + .forEach(action -> { + try { + assertTargetUpdateAllowed(action); + forceQuitAction(action.getId()); + log.debug("Action {} force canceled", action.getId()); + } catch (final InsufficientPermissionException e) { + log.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e); + } catch (final EntityNotFoundException e) { + log.trace("Could not cancel action {} due to entity not found exception.", action.getId(), + e); + } + }); + } + } + + protected ActionRepository getActionRepository() { + return actionRepository; + } + + protected boolean isActionsAutocloseEnabled() { + return getConfigValue(REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, Boolean.class); + } + + private static Map> convertRequest( + final Collection deploymentRequests) { + return deploymentRequests.stream().collect(Collectors.groupingBy(DeploymentRequest::getDistributionSetId, + Collectors.mapping(DeploymentRequest::getTargetWithActionType, Collectors.toList()))); + } + + /** + * split tIDs length into max entries in-statement because many database have + * constraint of max entries in in-statements e.g. Oracle with maximum 1000 + * elements, so we need to split the entries here and execute multiple + * statements + */ + private static List> getTargetEntitiesAsChunks(final List targetEntities) { + return ListUtils.partition(targetEntities.stream().map(Target::getId).collect(Collectors.toList()), + Constants.MAX_ENTRIES_IN_STATEMENT); + } + + private static DistributionSetAssignmentResult buildAssignmentResult(final JpaDistributionSet distributionSet, + final List assignedActions, final int totalTargetsForAssignment) { + final int alreadyAssignedTargetsCount = totalTargetsForAssignment - assignedActions.size(); + + return new DistributionSetAssignmentResult(distributionSet, alreadyAssignedTargetsCount, assignedActions); + } + + private static String getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(final Database database) { + return QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.getOrDefault(database, + QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT); + } + + private static String formatInClauseWithNumberKeys(final int count) { + return formatInClause(IntStream.range(0, count).mapToObj(String::valueOf).collect(Collectors.toList())); + } + + private static String formatInClause(final Collection elements) { + return "#" + String.join(",#", elements); + } + + private static RetryTemplate createRetryTemplate() { + final RetryTemplate template = new RetryTemplate(); + + final FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); + backOffPolicy.setBackOffPeriod(Constants.TX_RT_DELAY); + template.setBackOffPolicy(backOffPolicy); + + final SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(Constants.TX_RT_MAX, + Collections.singletonMap(ConcurrencyFailureException.class, true)); + template.setRetryPolicy(retryPolicy); + + return template; } private List assignDistributionSets(final String initiatedBy, @@ -327,12 +739,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl return deploymentRequests; } - private static Map> convertRequest( - final Collection deploymentRequests) { - return deploymentRequests.stream().collect(Collectors.groupingBy(DeploymentRequest::getDistributionSetId, - Collectors.mapping(DeploymentRequest::getTargetWithActionType, Collectors.toList()))); - } - private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(final String initiatedBy, final Long dsId, final Collection targetsWithActionType, final String actionMessage, final AbstractDsAssignmentStrategy assignmentStrategy) { @@ -355,21 +761,14 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl * to {@link TargetUpdateStatus#IN_SYNC}
* D. does not send a {@link TargetAssignDistributionSetEvent}.
* - * @param initiatedBy - * the username of the user who initiated the assignment - * @param dsId - * the ID of the distribution set to assign - * @param targetsWithActionType - * a list of all targets and their action type - * @param actionMessage - * an optional message to be written into the action status - * @param assignmentStrategy - * the assignment strategy (online /offline) + * @param initiatedBy the username of the user who initiated the assignment + * @param dsId the ID of the distribution set to assign + * @param targetsWithActionType a list of all targets and their action type + * @param actionMessage an optional message to be written into the action status + * @param assignmentStrategy the assignment strategy (online /offline) * @return the assignment result - * - * @throws IncompleteDistributionSetException - * if mandatory {@link SoftwareModuleType} are not assigned as - * define by the {@link DistributionSetType}. + * @throws IncompleteDistributionSetException if mandatory {@link SoftwareModuleType} are not assigned as + * define by the {@link DistributionSetType}. */ private DistributionSetAssignmentResult assignDistributionSetToTargets(final String initiatedBy, final Long dsId, final Collection targetsWithActionType, final String actionMessage, @@ -377,7 +776,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement.getValidAndComplete(dsId); - if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) { + if (((JpaDistributionSetManagement) distributionSetManagement).isImplicitLockApplicable(distributionSet)) { // without new transaction DS changed event is not thrown DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> { distributionSetManagement.lock(distributionSet.getId()); @@ -446,24 +845,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl return new ArrayList<>(assignedActions.values()); } - /** - * split tIDs length into max entries in-statement because many database have - * constraint of max entries in in-statements e.g. Oracle with maximum 1000 - * elements, so we need to split the entries here and execute multiple - * statements - */ - private static List> getTargetEntitiesAsChunks(final List targetEntities) { - return ListUtils.partition(targetEntities.stream().map(Target::getId).collect(Collectors.toList()), - Constants.MAX_ENTRIES_IN_STATEMENT); - } - - private static DistributionSetAssignmentResult buildAssignmentResult(final JpaDistributionSet distributionSet, - final List assignedActions, final int totalTargetsForAssignment) { - final int alreadyAssignedTargetsCount = totalTargetsForAssignment - assignedActions.size(); - - return new DistributionSetAssignmentResult(distributionSet, alreadyAssignedTargetsCount, assignedActions); - } - private void enforceMaxAssignmentsPerRequest(final int requestedActions) { QuotaHelper.assertAssignmentRequestSizeQuota(requestedActions, quotaManagement.getMaxTargetDistributionSetAssignmentsPerManualAssignment()); @@ -489,24 +870,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl } } - @Override - @Transactional(isolation = Isolation.READ_COMMITTED) - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void cancelInactiveScheduledActionsForTargets(final List targetIds) { - if (!isMultiAssignmentsEnabled()) { - targetRepository.getAccessController().ifPresent(v -> { - if (targetRepository.count(AccessController.Operation.UPDATE, - TargetSpecifications.hasIdIn(targetIds)) != targetIds.size()) { - throw new EntityNotFoundException(Target.class, targetIds); - } - }); - actionRepository.switchStatus(Status.CANCELED, targetIds, false, Status.SCHEDULED); - } else { - log.debug("The Multi Assignments feature is enabled: No need to cancel inactive scheduled actions."); - } - } - private void setAssignedDistributionSetAndTargetUpdateStatus(final AbstractDsAssignmentStrategy assignmentStrategy, final JpaDistributionSet set, final List> targetIdsChunks) { final String currentUser = auditorProvider.getCurrentAuditor().orElse(null); @@ -581,112 +944,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl assignmentStrategy.sendTargetUpdatedEvents(set, targets); } - @Override - @Transactional(isolation = Isolation.READ_COMMITTED) - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Action cancelAction(final long actionId) { - log.debug("cancelAction({})", actionId); - - final JpaAction action = actionRepository.findById(actionId) - .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); - - if (action.isCancelingOrCanceled()) { - throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled"); - } - - assertTargetUpdateAllowed(action); - - if (action.isActive()) { - log.debug("action ({}) was still active. Change to {}.", action, Status.CANCELING); - action.setStatus(Status.CANCELING); - - // document that the status has been retrieved - actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELING, System.currentTimeMillis(), - RepositoryConstants.SERVER_MESSAGE_PREFIX + "manual cancelation requested")); - final Action saveAction = actionRepository.save(action); - - onlineDsAssignmentStrategy.cancelAssignment(action); - - return saveAction; - } else { - throw new CancelActionNotAllowedException(action.getId() + " is not active and cannot be canceled"); - } - } - - @Override - @Transactional(isolation = Isolation.READ_COMMITTED) - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Action forceQuitAction(final long actionId) { - final JpaAction action = actionRepository.findById(actionId) - .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); - - if (!action.isCancelingOrCanceled()) { - throw new ForceQuitActionNotAllowedException( - action.getId() + " is not canceled yet and cannot be force quit"); - } - - if (!action.isActive()) { - throw new ForceQuitActionNotAllowedException(action.getId() + " is not active and cannot be force quit"); - } - - assertTargetUpdateAllowed(action); - - log.warn("action ({}) was still active and has been force quite.", action); - - // document that the status has been retrieved - actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELED, System.currentTimeMillis(), - RepositoryConstants.SERVER_MESSAGE_PREFIX + "A force quit has been performed.")); - - DeploymentHelper.successCancellation(action, actionRepository, targetRepository); - - return actionRepository.save(action); - } - - @Override - public void startScheduledActionsByRolloutGroupParent(final long rolloutId, final long distributionSetId, - final Long rolloutGroupParentId) { - while (DeploymentHelper.runInNewTransaction( - txManager, - "startScheduledActions-" + rolloutId, - status -> { - final PageRequest pageRequest = PageRequest.of(0, ACTION_PAGE_LIMIT); - final Page groupScheduledActions; - if (rolloutGroupParentId == null) { - groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIsNullAndStatus(pageRequest, rolloutId, Action.Status.SCHEDULED); - } else { - groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIdAndStatus(pageRequest, rolloutId, rolloutGroupParentId, Action.Status.SCHEDULED); - } - - if (groupScheduledActions.getContent().isEmpty()) { - return 0L; - } else { - // self invocation won't check @PreAuthorize but it is already checked for the method - startScheduledActions(groupScheduledActions.getContent()); - return groupScheduledActions.getTotalElements(); - } - }) > 0); - } - - @Override - public void startScheduledActions(final List rolloutGroupActions) { - // Close actions already assigned and collect pending assignments - final List pendingTargetAssignments = rolloutGroupActions.stream() - .map(JpaAction.class::cast) - .map(this::closeActionIfSetWasAlreadyAssigned) - .filter(Objects::nonNull) - .toList(); - if (pendingTargetAssignments.isEmpty()) { - return; - } - // check if old actions needs to be canceled first - final List newTargetAssignments = startScheduledActionsAndHandleOpenCancellationFirst(pendingTargetAssignments); - if (!newTargetAssignments.isEmpty()) { - onlineDsAssignmentStrategy.sendDeploymentEvents(newTargetAssignments.get(0).getDistributionSet().getId(), newTargetAssignments); - } - } - private JpaAction closeActionIfSetWasAlreadyAssigned(final JpaAction action) { if (isMultiAssignmentsEnabled()) { return action; @@ -764,221 +1021,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl actionStatusRepository.save(actionStatus); } - @Override - public Optional findAction(final long actionId) { - return actionRepository.findById(actionId) - .filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))) - .map(JpaAction.class::cast); - } - - @Override - public Optional findActionWithDetails(final long actionId) { - return actionRepository.findWithDetailsById(actionId) - .filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))); - } - - @Override - public Slice findActionsByTarget(final String controllerId, final Pageable pageable) { - assertTargetReadAllowed(controllerId); - return actionRepository.findAll(ActionSpecifications.byTargetControllerId(controllerId), pageable) - .map(Action.class::cast); - } - - @Override - public Page findActionsByTarget(final String rsqlParam, final String controllerId, - final Pageable pageable) { - assertTargetReadAllowed(controllerId); - - final List> specList = Arrays.asList( - RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database), - ActionSpecifications.byTargetControllerId(controllerId)); - - return JpaManagementHelper.findAllWithCountBySpec(actionRepository, pageable, specList); - } - - @Override - public Page findActiveActionsByTarget(final Pageable pageable, final String controllerId) { - assertTargetReadAllowed(controllerId); - return actionRepository - .findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, true), pageable) - .map(Action.class::cast); - } - - @Override - public Page findInActiveActionsByTarget(final Pageable pageable, final String controllerId) { - assertTargetReadAllowed(controllerId); - return actionRepository - .findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, false), pageable) - .map(Action.class::cast); - } - - @Override - public List findActiveActionsWithHighestWeight(final String controllerId, final int maxActionCount) { - assertTargetReadAllowed(controllerId); - return findActiveActionsWithHighestWeightConsideringDefault(controllerId, maxActionCount); - } - - @Override - public long countActionsByTarget(final String controllerId) { - assertTargetReadAllowed(controllerId); - return actionRepository.countByTargetControllerId(controllerId); - } - - @Override - public long countActionsByTarget(final String rsqlParam, final String controllerId) { - assertTargetReadAllowed(controllerId); - - final List> specList = Arrays.asList( - RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database), - ActionSpecifications.byTargetControllerId(controllerId)); - - return JpaManagementHelper.countBySpec(actionRepository, specList); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Action forceTargetAction(final long actionId) { - final JpaAction action = actionRepository.findById(actionId).map(this::assertTargetUpdateAllowed) - .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); - - if (!action.isForcedOrTimeForced()) { - action.setActionType(ActionType.FORCED); - return actionRepository.save(action); - } - return action; - } - - @Override - public Page findActionStatusByAction(final Pageable pageReq, final long actionId) { - assertActionExistsAndAccessible(actionId); - - return actionStatusRepository.findByActionId(pageReq, actionId); - } - - @Override - public long countActionStatusByAction(final long actionId) { - assertActionExistsAndAccessible(actionId); - - return actionStatusRepository.countByActionId(actionId); - } - - // action is already got and there are checked read permissions - do not check - // permissions - // and UI which is to be removed - @Override - public Page findMessagesByActionStatusId(final Pageable pageable, final long actionStatusId) { - final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - - final CriteriaQuery msgQuery = cb.createQuery(String.class); - final Root as = msgQuery.from(JpaActionStatus.class); - final ListJoin join = as.joinList("messages", JoinType.LEFT); - final CriteriaQuery selMsgQuery = msgQuery.select(join); - selMsgQuery.where(cb.equal(as.get(JpaActionStatus_.id), actionStatusId)); - - final List result = new ArrayList<>(entityManager.createQuery(selMsgQuery) - .setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList()); - - return new PageImpl<>(result, pageable, result.size()); - } - - @Override - public long countActionsAll() { - return actionRepository.count(); - } - - @Override - public long countActions(final String rsqlParam) { - final List> specList = List.of( - RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database)); - return JpaManagementHelper.countBySpec(actionRepository, specList); - } - - @Override - public Slice findActionsAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, pageable, null); - } - - @Override - public Slice findActions(final String rsqlParam, final Pageable pageable) { - final List> specList = List.of( - RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database)); - return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, pageable, specList); - } - - @Override - public Optional getAssignedDistributionSet(final String controllerId) { - return targetRepository - .findOne(TargetSpecifications.hasControllerId(controllerId)) - .map(JpaTarget::getAssignedDistributionSet); - } - - @Override - public Optional getInstalledDistributionSet(final String controllerId) { - return targetRepository - .findOne(TargetSpecifications.hasControllerId(controllerId)) - .map(JpaTarget::getInstalledDistributionSet); - } - - @Override - @Transactional(readOnly = false) - public int deleteActionsByStatusAndLastModifiedBefore(final Set status, final long lastModified) { - if (status.isEmpty()) { - return 0; - } - /* - * We use a native query here because Spring JPA does not support to specify a - * LIMIT clause on a DELETE statement. However, for this specific use case - * (action cleanup), we must specify a row limit to reduce the overall load on - * the database. - */ - - final int statusCount = status.size(); - final Status[] statusArr = status.toArray(new Status[statusCount]); - - final String queryStr = String.format(getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(database), - formatInClauseWithNumberKeys(statusCount)); - final Query deleteQuery = entityManager.createNativeQuery(queryStr); - - IntStream.range(0, statusCount) - .forEach(i -> deleteQuery.setParameter(String.valueOf(i), statusArr[i].ordinal())); - deleteQuery.setParameter("tenant", tenantAware.getCurrentTenant().toUpperCase()); - deleteQuery.setParameter("last_modified_at", lastModified); - - log.debug("Action cleanup: Executing the following (native) query: {}", deleteQuery); - return deleteQuery.executeUpdate(); - } - - @Override - public boolean hasPendingCancellations(final Long targetId) { - // target access checked in assertTargetReadAllowed - assertTargetReadAllowed(targetId); - return actionRepository - .exists(ActionSpecifications.byTargetIdAndIsActiveAndStatus(targetId, Action.Status.CANCELING)); - } - - private static String getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(final Database database) { - return QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.getOrDefault(database, - QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT); - } - - private static String formatInClauseWithNumberKeys(final int count) { - return formatInClause(IntStream.range(0, count).mapToObj(String::valueOf).collect(Collectors.toList())); - } - - private static String formatInClause(final Collection elements) { - return "#" + String.join(",#", elements); - } - - protected ActionRepository getActionRepository() { - return actionRepository; - } - - protected boolean isActionsAutocloseEnabled() { - return getConfigValue(REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, Boolean.class); - } - private boolean isMultiAssignmentsEnabled() { return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement) .isMultiAssignmentsEnabled(); @@ -994,54 +1036,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl .runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue()); } - private static RetryTemplate createRetryTemplate() { - final RetryTemplate template = new RetryTemplate(); - - final FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); - backOffPolicy.setBackOffPeriod(Constants.TX_RT_DELAY); - template.setBackOffPolicy(backOffPolicy); - - final SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(Constants.TX_RT_MAX, - Collections.singletonMap(ConcurrencyFailureException.class, true)); - template.setRetryPolicy(retryPolicy); - - return template; - } - - @Override - @Transactional - public void cancelActionsForDistributionSet(final CancelationType cancelationType, - final DistributionSet distributionSet) { - actionRepository.findAll(ActionSpecifications - .byDistributionSetIdAndActiveAndStatusIsNot(distributionSet.getId(), Status.CANCELING)) - .forEach(action -> { - try { - assertTargetUpdateAllowed(action); - cancelAction(action.getId()); - log.debug("Action {} canceled", action.getId()); - } catch (final InsufficientPermissionException e) { - log.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e); - } catch (final EntityNotFoundException e) { - log.trace("Could not cancel action {} due to entity not found exception.", action.getId(), e); - } - }); - if (cancelationType == CancelationType.FORCE) { - actionRepository.findAll(ActionSpecifications.byDistributionSetIdAndActive(distributionSet.getId())) - .forEach(action -> { - try { - assertTargetUpdateAllowed(action); - forceQuitAction(action.getId()); - log.debug("Action {} force canceled", action.getId()); - } catch (final InsufficientPermissionException e) { - log.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e); - } catch (final EntityNotFoundException e) { - log.trace("Could not cancel action {} due to entity not found exception.", action.getId(), - e); - } - }); - } - } - private void assertTargetReadAllowed(final Long targetId) { if (!targetRepository.existsById(targetId)) { throw new EntityNotFoundException(Target.class, targetId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java index 8be6a0ad6..ce418ac79 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java @@ -97,6 +97,26 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet } } + @Override + public DistributionSetInvalidationCount countEntitiesForInvalidation( + final DistributionSetInvalidation distributionSetInvalidation) { + return systemSecurityContext.runAsSystem(() -> { + final Collection setIds = distributionSetInvalidation.getDistributionSetIds(); + final long rolloutsCount = shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(), + distributionSetInvalidation.isCancelRollouts()) ? countRolloutsForInvalidation(setIds) : 0; + final long autoAssignmentsCount = countAutoAssignmentsForInvalidation(setIds); + final long actionsCount = countActionsForInvalidation(setIds, + distributionSetInvalidation.getCancelationType()); + + return new DistributionSetInvalidationCount(rolloutsCount, autoAssignmentsCount, actionsCount); + }); + } + + private static boolean shouldRolloutsBeCanceled(final CancelationType cancelationType, + final boolean cancelRollouts) { + return cancelationType != CancelationType.NONE || cancelRollouts; + } + private void invalidateDistributionSetsInTransaction(final DistributionSetInvalidation distributionSetInvalidation, final String tenant) { DeploymentHelper.runInNewTransaction(txManager, tenant + "-invalidateDS", status -> { @@ -135,26 +155,6 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet }); } - private static boolean shouldRolloutsBeCanceled(final CancelationType cancelationType, - final boolean cancelRollouts) { - return cancelationType != CancelationType.NONE || cancelRollouts; - } - - @Override - public DistributionSetInvalidationCount countEntitiesForInvalidation( - final DistributionSetInvalidation distributionSetInvalidation) { - return systemSecurityContext.runAsSystem(() -> { - final Collection setIds = distributionSetInvalidation.getDistributionSetIds(); - final long rolloutsCount = shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(), - distributionSetInvalidation.isCancelRollouts()) ? countRolloutsForInvalidation(setIds) : 0; - final long autoAssignmentsCount = countAutoAssignmentsForInvalidation(setIds); - final long actionsCount = countActionsForInvalidation(setIds, - distributionSetInvalidation.getCancelationType()); - - return new DistributionSetInvalidationCount(rolloutsCount, autoAssignmentsCount, actionsCount); - }); - } - private long countRolloutsForInvalidation(final Collection setIds) { return setIds.stream().mapToLong(rolloutManagement::countByDistributionSetIdAndRolloutIsStoppable).sum(); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java index 7b36423fd..4a530b3e1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -75,7 +77,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Statistic; -import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.utils.TenantConfigHelper; import org.springframework.dao.ConcurrencyFailureException; @@ -92,11 +93,8 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; -import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED; - /** * JPA implementation of {@link DistributionSetManagement}. - * */ @Transactional(readOnly = true) @Validated @@ -152,91 +150,25 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - public Optional getWithDetails(final long id) { - return distributionSetRepository.findById(id).map(DistributionSet.class::cast); - } + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List create(final Collection creates) { + final List toCreate = creates.stream().map(JpaDistributionSetCreate.class::cast) + .map(this::setDefaultTypeIfMissing).map(JpaDistributionSetCreate::build).toList(); - @Override - public long countByTypeId(final long typeId) { - if (!distributionSetTypeManagement.exists(typeId)) { - throw new EntityNotFoundException(DistributionSetType.class, typeId); - } - - return distributionSetRepository.count(DistributionSetSpecification.byType(typeId)); - } - - @Override - public List countRolloutsByStatusForDistributionSet(final Long id) { - assertDistributionSetExists(id); - - return distributionSetRepository.countRolloutsByStatusForDistributionSet(id).stream() - .map(Statistic.class::cast).toList(); - } - - @Override - public List countActionsByStatusForDistributionSet(final Long id) { - assertDistributionSetExists(id); - - return distributionSetRepository.countActionsByStatusForDistributionSet(id).stream() - .map(Statistic.class::cast).toList(); - } - - @Override - public Long countAutoAssignmentsForDistributionSet(final Long id) { - assertDistributionSetExists(id); - - return distributionSetRepository.countAutoAssignmentsForDistributionSet(id); + return Collections.unmodifiableList(distributionSetRepository.saveAll(AccessController.Operation.CREATE, toCreate)); } @Override @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List assignTag(final Collection ids, final long dsTagId) { - return updateTag(ids, dsTagId, (tag, distributionSet) -> { - if (distributionSet.getTags().contains(tag)) { - return distributionSet; - } else { - distributionSet.addTag(tag); - return distributionSetRepository.save(distributionSet); - } - }); - } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List unassignTag(final Collection ids, final long dsTagId) { - return updateTag(ids, dsTagId, (tag, distributionSet) -> { - if (distributionSet.getTags().contains(tag)) { - distributionSet.removeTag(tag); - return distributionSetRepository.save(distributionSet); - } else { - return distributionSet; - } - }); - } - private List updateTag( - final Collection dsIds, final long dsTagId, - final BiFunction updater) { - final DistributionSetTag tag = distributionSetTagManagement.get(dsTagId) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId)); - final List allDs = dsIds.size() == 1 ? - distributionSetRepository.findById(dsIds.iterator().next()) - .map(List::of) - .orElseGet(Collections::emptyList) : - distributionSetRepository.findAll(DistributionSetSpecification.byIds(dsIds)); - if (allDs.size() < dsIds.size()) { - throw new EntityNotFoundException(DistributionSet.class, notFound(dsIds, allDs)); - } + public DistributionSet create(final DistributionSetCreate c) { + final JpaDistributionSetCreate create = (JpaDistributionSetCreate) c; + setDefaultTypeIfMissing(create); - try { - // apply update and collect modified targets - return allDs.stream().map(distributionSet -> updater.apply(tag, distributionSet)).toList(); - } finally { - // No reason to save the tag - entityManager.detach(tag); - } + return distributionSetRepository.save(AccessController.Operation.CREATE, create.build()); } @Override @@ -273,9 +205,17 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { return distributionSetRepository.save(set); } - private JpaSoftwareModule findSoftwareModuleAndThrowExceptionIfNotFound(final Long softwareModuleId) { - return softwareModuleRepository.findById(softwareModuleId) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); + @Override + public long count() { + return distributionSetRepository.count(DistributionSetSpecification.isNotDeleted()); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void delete(final long id) { + delete(List.of(id)); } @Override @@ -315,32 +255,32 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSet create(final DistributionSetCreate c) { - final JpaDistributionSetCreate create = (JpaDistributionSetCreate) c; - setDefaultTypeIfMissing(create); - - return distributionSetRepository.save(AccessController.Operation.CREATE, create.build()); + public List get(final Collection ids) { + return Collections.unmodifiableList(getDistributionSets(ids)); } @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection creates) { - final List toCreate = creates.stream().map(JpaDistributionSetCreate.class::cast) - .map(this::setDefaultTypeIfMissing).map(JpaDistributionSetCreate::build).toList(); - - return Collections.unmodifiableList(distributionSetRepository.saveAll(AccessController.Operation.CREATE, toCreate)); + public boolean exists(final long id) { + return distributionSetRepository.existsById(id); } - private JpaDistributionSetCreate setDefaultTypeIfMissing(final JpaDistributionSetCreate create) { - if (create.getType() == null) { - create.type(systemManagement.getTenantMetadata().getDefaultDsType().getKey()); - } - return create; + @Override + public Optional get(final long id) { + return distributionSetRepository.findById(id).map(DistributionSet.class::cast); + } + + @Override + public Slice findAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable, List.of( + DistributionSetSpecification.isNotDeleted())); + } + + @Override + public Page findByRsql(final Pageable pageable, final String rsqlParam) { + return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, List.of( + RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer, + database), + DistributionSetSpecification.isNotDeleted())); } @Override @@ -367,81 +307,30 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSet unassignSoftwareModule(final long id, final long moduleId) { - final JpaDistributionSet set = (JpaDistributionSet) getValid(id); - assertDistributionSetIsNotAssignedToTargets(id); - - final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId); - set.removeModule(module); - - return distributionSetRepository.save(set); + public List assignTag(final Collection ids, final long dsTagId) { + return updateTag(ids, dsTagId, (tag, distributionSet) -> { + if (distributionSet.getTags().contains(tag)) { + return distributionSet; + } else { + distributionSet.addTag(tag); + return distributionSetRepository.save(distributionSet); + } + }); } @Override - public Slice findByDistributionSetFilter(final Pageable pageable, - final DistributionSetFilter distributionSetFilter) { - final List> specList = buildDistributionSetSpecifications( - distributionSetFilter); - - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable, specList); - } - - @Override - public long countByDistributionSetFilter(@NotNull final DistributionSetFilter distributionSetFilter) { - final List> specList = buildDistributionSetSpecifications( - distributionSetFilter); - - return JpaManagementHelper.countBySpec(distributionSetRepository, specList); - } - - @Override - public Slice findByCompleted(final Pageable pageReq, final Boolean complete) { - final List> specifications = buildSpecsByComplete(complete); - - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageReq, specifications); - } - - @Override - public long countByCompleted(final Boolean complete) { - final List> specifications = buildSpecsByComplete(complete); - - return JpaManagementHelper.countBySpec(distributionSetRepository, specifications); - } - - private List> buildSpecsByComplete(final Boolean complete) { - final List> specifications = new ArrayList<>(); - specifications.add(DistributionSetSpecification.isNotDeleted()); - if (complete != null) { - specifications.add(DistributionSetSpecification.isCompleted(complete)); - } - return specifications; - } - - @Override - public Slice findByDistributionSetFilterOrderByLinkedTarget(final Pageable pageable, - final DistributionSetFilter distributionSetFilter, final String assignedOrInstalled) { - // remove default sort from pageable to not overwrite sorted spec - final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(), - pageable.getPageSize(), Sort.unsorted()); - - final List> specList = buildDistributionSetSpecifications( - distributionSetFilter); - specList.add(DistributionSetSpecification.orderedByLinkedTarget(assignedOrInstalled, pageable.getSort())); - - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, unsortedPage, specList); - } - - @Override - public Optional getByNameAndVersion(final String distributionName, final String version) { - return distributionSetRepository - .findOne(DistributionSetSpecification.equalsNameAndVersionIgnoreCase(distributionName, version)) - .map(DistributionSet.class::cast); - - } - - @Override - public long count() { - return distributionSetRepository.count(DistributionSetSpecification.isNotDeleted()); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List unassignTag(final Collection ids, final long dsTagId) { + return updateTag(ids, dsTagId, (tag, distributionSet) -> { + if (distributionSet.getTags().contains(tag)) { + distributionSet.removeTag(tag); + return distributionSetRepository.save(distributionSet); + } else { + return distributionSet; + } + }); } @Override @@ -449,7 +338,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public List createMetaData(final long id, final Collection md) { - final JpaDistributionSet distributionSet = (JpaDistributionSet)getValid(id); + final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id); assertMetaDataQuota(id, md.size()); md.forEach(meta -> checkAndThrowIfDistributionSetMetadataAlreadyExists( @@ -463,34 +352,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { .collect(Collectors.toUnmodifiableList()); } - private void assertMetaDataQuota(final Long dsId, final int requested) { - QuotaHelper.assertAssignmentQuota(dsId, requested, quotaManagement.getMaxMetaDataEntriesPerDistributionSet(), - DistributionSetMetadata.class, DistributionSet.class, - distributionSetMetadataRepository::countByDistributionSetId); - } - - private void assertSoftwareModuleQuota(final Long id, final int requested) { - QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxSoftwareModulesPerDistributionSet(), - SoftwareModule.class, DistributionSet.class, softwareModuleRepository::countByAssignedToId); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetMetadata updateMetaData(final long id, final MetaData md) { - // check if exists otherwise throw entity not found exception - final JpaDistributionSetMetadata toUpdate = (JpaDistributionSetMetadata) getMetaDataByDistributionSetId(id, - md.getKey()) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetMetadata.class, id, md.getKey())); - toUpdate.setValue(md.getValue()); - - // touch it to update the lock revision because we are modifying the - // DS indirectly, it will, also check UPDATE access - JpaManagementHelper.touch(entityManager, distributionSetRepository, (JpaDistributionSet) getValid(id)); - return distributionSetMetadataRepository.save(toUpdate); - } - @Override @Transactional @Retryable(include = { @@ -508,45 +369,28 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - public Page findMetaDataByDistributionSetId(final Pageable pageable, - final long id) { - assertDistributionSetExists(id); - - return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable, - Collections.singletonList(byDsIdSpec(id))); - } - - private Specification byDsIdSpec(final long dsId) { - return (root, query, cb) -> cb - .equal(root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), dsId); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void lock(final long id) { + final JpaDistributionSet distributionSet = getById(id); + if (!distributionSet.isLocked()) { + lockSoftwareModules(distributionSet); + distributionSet.lock(); + distributionSetRepository.save(distributionSet); + } } @Override - public long countMetaDataByDistributionSetId(final long id) { - assertDistributionSetExists(id); - - return distributionSetMetadataRepository.countByDistributionSetId(id); - } - - @Override - public Page findMetaDataByDistributionSetIdAndRsql(final Pageable pageable, - final long id, final String rsqlParam) { - assertDistributionSetExists(id); - - final List> specList = Arrays - .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetMetadataFields.class, - virtualPropertyReplacer, database), byDsIdSpec(id)); - - return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable, specList); - } - - @Override - public Optional getMetaDataByDistributionSetId(final long id, final String key) { - assertDistributionSetExists(id); - - return distributionSetMetadataRepository - .findById(new DsMetadataCompositeKey(id, key)) - .map(DistributionSetMetadata.class::cast); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void unlock(final long id) { + final JpaDistributionSet distributionSet = getById(id); + if (distributionSet.isLocked()) { + distributionSet.unlock(); + distributionSetRepository.save(distributionSet); + } } @Override @@ -568,6 +412,152 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { }); } + @Override + public Optional getWithDetails(final long id) { + return distributionSetRepository.findById(id).map(DistributionSet.class::cast); + } + + @Override + public Optional getByNameAndVersion(final String distributionName, final String version) { + return distributionSetRepository + .findOne(DistributionSetSpecification.equalsNameAndVersionIgnoreCase(distributionName, version)) + .map(DistributionSet.class::cast); + + } + + @Override + public DistributionSet getValidAndComplete(final long id) { + final DistributionSet distributionSet = getValid(id); + + if (!distributionSet.isComplete()) { + throw new IncompleteDistributionSetException("Distribution set of type " + + distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId()); + } + + if (distributionSet.isDeleted()) { + throw new DeletedException(DistributionSet.class, id); + } + + return distributionSet; + } + + @Override + public DistributionSet getValid(final long id) { + final DistributionSet distributionSet = getOrElseThrowException(id); + + if (!distributionSet.isValid()) { + throw new InvalidDistributionSetException("Distribution set of type " + distributionSet.getType().getKey() + + " is invalid: " + distributionSet.getId()); + } + + return distributionSet; + } + + @Override + public DistributionSet getOrElseThrowException(final long id) { + return getById(id); + } + + @Override + public Page findMetaDataByDistributionSetId(final Pageable pageable, + final long id) { + assertDistributionSetExists(id); + + return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable, + Collections.singletonList(byDsIdSpec(id))); + } + + @Override + public long countMetaDataByDistributionSetId(final long id) { + assertDistributionSetExists(id); + + return distributionSetMetadataRepository.countByDistributionSetId(id); + } + + @Override + public Page findMetaDataByDistributionSetIdAndRsql(final Pageable pageable, + final long id, final String rsqlParam) { + assertDistributionSetExists(id); + + final List> specList = Arrays + .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetMetadataFields.class, + virtualPropertyReplacer, database), byDsIdSpec(id)); + + return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable, specList); + } + + @Override + public Slice findByCompleted(final Pageable pageReq, final Boolean complete) { + final List> specifications = buildSpecsByComplete(complete); + + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageReq, specifications); + } + + @Override + public long countByCompleted(final Boolean complete) { + final List> specifications = buildSpecsByComplete(complete); + + return JpaManagementHelper.countBySpec(distributionSetRepository, specifications); + } + + @Override + public Slice findByDistributionSetFilter(final Pageable pageable, + final DistributionSetFilter distributionSetFilter) { + final List> specList = buildDistributionSetSpecifications( + distributionSetFilter); + + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable, specList); + } + + @Override + public Slice findByDistributionSetFilterOrderByLinkedTarget(final Pageable pageable, + final DistributionSetFilter distributionSetFilter, final String assignedOrInstalled) { + // remove default sort from pageable to not overwrite sorted spec + final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(), + pageable.getPageSize(), Sort.unsorted()); + + final List> specList = buildDistributionSetSpecifications( + distributionSetFilter); + specList.add(DistributionSetSpecification.orderedByLinkedTarget(assignedOrInstalled, pageable.getSort())); + + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, unsortedPage, specList); + } + + @Override + public long countByDistributionSetFilter(@NotNull final DistributionSetFilter distributionSetFilter) { + final List> specList = buildDistributionSetSpecifications( + distributionSetFilter); + + return JpaManagementHelper.countBySpec(distributionSetRepository, specList); + } + + @Override + public Page findByTag(final Pageable pageable, final long tagId) { + assertDsTagExists(tagId); + + return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, List.of( + DistributionSetSpecification.hasTag(tagId))); + } + + @Override + public Page findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) { + assertDsTagExists(tagId); + + return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, List.of( + RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer, + database), + DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isNotDeleted())); + } + + @Override + public Optional getMetaDataByDistributionSetId(final long id, final String key) { + assertDistributionSetExists(id); + + return distributionSetMetadataRepository + .findById(new DsMetadataCompositeKey(id, key)) + .map(DistributionSetMetadata.class::cast); + } + @Override public boolean isInUse(final long id) { assertDistributionSetExists(id); @@ -575,6 +565,163 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { return actionRepository.countByDistributionSetId(id) > 0; } + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public DistributionSet unassignSoftwareModule(final long id, final long moduleId) { + final JpaDistributionSet set = (JpaDistributionSet) getValid(id); + assertDistributionSetIsNotAssignedToTargets(id); + + final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId); + set.removeModule(module); + + return distributionSetRepository.save(set); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public DistributionSetMetadata updateMetaData(final long id, final MetaData md) { + // check if exists otherwise throw entity not found exception + final JpaDistributionSetMetadata toUpdate = (JpaDistributionSetMetadata) getMetaDataByDistributionSetId(id, + md.getKey()) + .orElseThrow(() -> new EntityNotFoundException(DistributionSetMetadata.class, id, md.getKey())); + toUpdate.setValue(md.getValue()); + + // touch it to update the lock revision because we are modifying the + // DS indirectly, it will, also check UPDATE access + JpaManagementHelper.touch(entityManager, distributionSetRepository, (JpaDistributionSet) getValid(id)); + return distributionSetMetadataRepository.save(toUpdate); + } + + @Override + public long countByTypeId(final long typeId) { + if (!distributionSetTypeManagement.exists(typeId)) { + throw new EntityNotFoundException(DistributionSetType.class, typeId); + } + + return distributionSetRepository.count(DistributionSetSpecification.byType(typeId)); + } + + @Override + public List countRolloutsByStatusForDistributionSet(final Long id) { + assertDistributionSetExists(id); + + return distributionSetRepository.countRolloutsByStatusForDistributionSet(id).stream() + .map(Statistic.class::cast).toList(); + } + + @Override + public List countActionsByStatusForDistributionSet(final Long id) { + assertDistributionSetExists(id); + + return distributionSetRepository.countActionsByStatusForDistributionSet(id).stream() + .map(Statistic.class::cast).toList(); + } + + @Override + public Long countAutoAssignmentsForDistributionSet(final Long id) { + assertDistributionSetExists(id); + + return distributionSetRepository.countAutoAssignmentsForDistributionSet(id); + } + + @Override + @Transactional + public void invalidate(final DistributionSet distributionSet) { + final JpaDistributionSet jpaSet = (JpaDistributionSet) distributionSet; + jpaSet.invalidate(); + distributionSetRepository.save(jpaSet); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public DistributionSetTagAssignmentResult toggleTagAssignment(final Collection ids, final String tagName) { + return updateTag( + ids, + () -> distributionSetTagManagement + .getByName(tagName) + .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, tagName)), + (allDs, distributionSetTag) -> { + final List toBeChangedDSs = allDs.stream().filter(set -> set.addTag(distributionSetTag)) + .collect(Collectors.toList()); + + final DistributionSetTagAssignmentResult result; + // un-assignment case + if (toBeChangedDSs.isEmpty()) { + for (final JpaDistributionSet set : allDs) { + if (set.removeTag(distributionSetTag)) { + toBeChangedDSs.add(set); + } + } + result = new DistributionSetTagAssignmentResult(ids.size() - toBeChangedDSs.size(), + Collections.emptyList(), + Collections.unmodifiableList( + toBeChangedDSs.stream().map(distributionSetRepository::save).collect(Collectors.toList())), + distributionSetTag); + } else { + result = new DistributionSetTagAssignmentResult(ids.size() - toBeChangedDSs.size(), + Collections.unmodifiableList( + toBeChangedDSs.stream().map(distributionSetRepository::save).collect(Collectors.toList())), + Collections.emptyList(), distributionSetTag); + } + return result; + }); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public DistributionSet unassignTag(final long id, final long dsTagId) { + final JpaDistributionSet set = (JpaDistributionSet) getWithDetails(id) + .orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id)); + + final DistributionSetTag distributionSetTag = distributionSetTagManagement.get(dsTagId) + .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId)); + set.removeTag(distributionSetTag); + + final JpaDistributionSet result = distributionSetRepository.save(set); + + // No reason to save the tag + entityManager.detach(distributionSetTag); + return result; + } + + // check if shall implicitly lock a distribution set + boolean isImplicitLockApplicable(final DistributionSet distributionSet) { + final JpaDistributionSet jpaDistributionSet = (JpaDistributionSet) distributionSet; + if (jpaDistributionSet.isLocked()) { + // already locked + return false; + } + + if (!tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) { + // implicit lock disabled + return false; + } + + final List skipForTags = repositoryProperties.getSkipImplicitLockForTags(); + if (!ObjectUtils.isEmpty(skipForTags)) { + final Set tags = jpaDistributionSet.getTags(); + if (!ObjectUtils.isEmpty(tags)) { + for (final DistributionSetTag tag : tags) { + if (skipForTags.contains(tag.getName())) { + // has a skip tag + return false; + } + } + } + } + + // finally - implicit lock is applicable + return true; + } + private static List> buildDistributionSetSpecifications( final DistributionSetFilter distributionSetFilter) { final List> specList = new ArrayList<>(10); @@ -617,13 +764,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { return specList; } - private void assertDistributionSetIsNotAssignedToTargets(final Long distributionSet) { - if (actionRepository.countByDistributionSetId(distributionSet) > 0) { - throw new EntityReadOnlyException(String.format( - "Distribution set %s is already assigned to targets and cannot be changed", distributionSet)); - } - } - private static boolean hasTagsFilterActive(final DistributionSetFilter distributionSetFilter) { final boolean isNoTagActive = Boolean.TRUE.equals(distributionSetFilter.getSelectDSWithNoTag()); final boolean isAtLeastOneTagActive = !CollectionUtils.isEmpty(distributionSetFilter.getTagNames()); @@ -631,6 +771,79 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { return isNoTagActive || isAtLeastOneTagActive; } + private static Collection notFound(final Collection distributionSetIds, final List foundDistributionSets) { + final Map foundDistributionSetMap = foundDistributionSets.stream() + .collect(Collectors.toMap(JpaDistributionSet::getId, Function.identity())); + return distributionSetIds.stream().filter(id -> !foundDistributionSetMap.containsKey(id)).toList(); + } + + private List updateTag( + final Collection dsIds, final long dsTagId, + final BiFunction updater) { + final DistributionSetTag tag = distributionSetTagManagement.get(dsTagId) + .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId)); + final List allDs = dsIds.size() == 1 ? + distributionSetRepository.findById(dsIds.iterator().next()) + .map(List::of) + .orElseGet(Collections::emptyList) : + distributionSetRepository.findAll(DistributionSetSpecification.byIds(dsIds)); + if (allDs.size() < dsIds.size()) { + throw new EntityNotFoundException(DistributionSet.class, notFound(dsIds, allDs)); + } + + try { + // apply update and collect modified targets + return allDs.stream().map(distributionSet -> updater.apply(tag, distributionSet)).toList(); + } finally { + // No reason to save the tag + entityManager.detach(tag); + } + } + + private JpaSoftwareModule findSoftwareModuleAndThrowExceptionIfNotFound(final Long softwareModuleId) { + return softwareModuleRepository.findById(softwareModuleId) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); + } + + private JpaDistributionSetCreate setDefaultTypeIfMissing(final JpaDistributionSetCreate create) { + if (create.getType() == null) { + create.type(systemManagement.getTenantMetadata().getDefaultDsType().getKey()); + } + return create; + } + + private List> buildSpecsByComplete(final Boolean complete) { + final List> specifications = new ArrayList<>(); + specifications.add(DistributionSetSpecification.isNotDeleted()); + if (complete != null) { + specifications.add(DistributionSetSpecification.isCompleted(complete)); + } + return specifications; + } + + private void assertMetaDataQuota(final Long dsId, final int requested) { + QuotaHelper.assertAssignmentQuota(dsId, requested, quotaManagement.getMaxMetaDataEntriesPerDistributionSet(), + DistributionSetMetadata.class, DistributionSet.class, + distributionSetMetadataRepository::countByDistributionSetId); + } + + private void assertSoftwareModuleQuota(final Long id, final int requested) { + QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxSoftwareModulesPerDistributionSet(), + SoftwareModule.class, DistributionSet.class, softwareModuleRepository::countByAssignedToId); + } + + private Specification byDsIdSpec(final long dsId) { + return (root, query, cb) -> cb + .equal(root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), dsId); + } + + private void assertDistributionSetIsNotAssignedToTargets(final Long distributionSet) { + if (actionRepository.countByDistributionSetId(distributionSet) > 0) { + throw new EntityReadOnlyException(String.format( + "Distribution set %s is already assigned to targets and cannot be changed", distributionSet)); + } + } + private void checkAndThrowIfDistributionSetMetadataAlreadyExists(final DsMetadataCompositeKey metadataId) { if (distributionSetMetadataRepository.existsById(metadataId)) { throw new EntityAlreadyExistsException( @@ -638,44 +851,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void lock(final long id) { - final JpaDistributionSet distributionSet = getById(id); - if (!distributionSet.isLocked()) { - lockSoftwareModules(distributionSet); - distributionSet.lock(); - distributionSetRepository.save(distributionSet); - } - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void unlock(final long id) { - final JpaDistributionSet distributionSet = getById(id); - if (distributionSet.isLocked()) { - distributionSet.unlock(); - distributionSetRepository.save(distributionSet); - } - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long id) { - delete(List.of(id)); - } - - @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(getDistributionSets(ids)); - } - private List getDistributionSets(final Collection ids) { final List foundDs = distributionSetRepository.findAllById(ids); if (foundDs.size() != ids.size()) { @@ -685,130 +860,10 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { return foundDs; } - @Override - public Page findByTag(final Pageable pageable, final long tagId) { - assertDsTagExists(tagId); - - return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, List.of( - DistributionSetSpecification.hasTag(tagId))); - } - - @Override - public Page findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) { - assertDsTagExists(tagId); - - return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, List.of( - RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer, - database), - DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isNotDeleted())); - } - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable, List.of( - DistributionSetSpecification.isNotDeleted())); - } - - @Override - public Page findByRsql(final Pageable pageable, final String rsqlParam) { - return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, List.of( - RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer, - database), - DistributionSetSpecification.isNotDeleted())); - } - - @Override - public Optional get(final long id) { - return distributionSetRepository.findById(id).map(DistributionSet.class::cast); - } - - @Override - public boolean exists(final long id) { - return distributionSetRepository.existsById(id); - } - - @Override - public DistributionSet getOrElseThrowException(final long id) { - return getById(id); - } - - @Override - public DistributionSet getValidAndComplete(final long id) { - final DistributionSet distributionSet = getValid(id); - - if (!distributionSet.isComplete()) { - throw new IncompleteDistributionSetException("Distribution set of type " - + distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId()); - } - - if (distributionSet.isDeleted()) { - throw new DeletedException(DistributionSet.class, id); - } - - return distributionSet; - } - - @Override - public DistributionSet getValid(final long id) { - final DistributionSet distributionSet = getOrElseThrowException(id); - - if (!distributionSet.isValid()) { - throw new InvalidDistributionSetException("Distribution set of type " + distributionSet.getType().getKey() - + " is invalid: " + distributionSet.getId()); - } - - return distributionSet; - } - - @Override - @Transactional - public void invalidate(final DistributionSet distributionSet) { - final JpaDistributionSet jpaSet = (JpaDistributionSet) distributionSet; - jpaSet.invalidate(); - distributionSetRepository.save(jpaSet); - } - - // check if shall implicitly lock a distribution set - boolean isImplicitLockApplicable(final DistributionSet distributionSet) { - final JpaDistributionSet jpaDistributionSet = (JpaDistributionSet) distributionSet; - if (jpaDistributionSet.isLocked()) { - // already locked - return false; - } - - if (!tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) { - // implicit lock disabled - return false; - } - - final List skipForTags = repositoryProperties.getSkipImplicitLockForTags(); - if (!ObjectUtils.isEmpty(skipForTags)) { - final Set tags = jpaDistributionSet.getTags(); - if (!ObjectUtils.isEmpty(tags)) { - for (final DistributionSetTag tag : tags) { - if (skipForTags.contains(tag.getName())) { - // has a skip tag - return false; - } - } - } - } - - // finally - implicit lock is applicable - return true; - } - - private static Collection notFound(final Collection distributionSetIds, final List foundDistributionSets) { - final Map foundDistributionSetMap = foundDistributionSets.stream() - .collect(Collectors.toMap(JpaDistributionSet::getId, Function.identity())); - return distributionSetIds.stream().filter(id -> !foundDistributionSetMap.containsKey(id)).toList(); - } - - private void lockSoftwareModules(final JpaDistributionSet distributionSet) { distributionSet.getModules().forEach(module -> { if (!module.isLocked()) { - final JpaSoftwareModule jpaSoftwareModule = (JpaSoftwareModule)module; + final JpaSoftwareModule jpaSoftwareModule = (JpaSoftwareModule) module; jpaSoftwareModule.lock(); softwareModuleRepository.save(jpaSoftwareModule); } @@ -823,7 +878,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { private void assertDistributionSetExists(final long id) { if (!distributionSetRepository.existsById(id)) { - throw new EntityNotFoundException(DistributionSet.class, id); + throw new EntityNotFoundException(DistributionSet.class, id); } } @@ -833,46 +888,10 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetTagAssignmentResult toggleTagAssignment(final Collection ids, final String tagName) { - return updateTag( - ids, - () -> distributionSetTagManagement - .getByName(tagName) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, tagName)), - (allDs, distributionSetTag) -> { - final List toBeChangedDSs = allDs.stream().filter(set -> set.addTag(distributionSetTag)) - .collect(Collectors.toList()); - - final DistributionSetTagAssignmentResult result; - // un-assignment case - if (toBeChangedDSs.isEmpty()) { - for (final JpaDistributionSet set : allDs) { - if (set.removeTag(distributionSetTag)) { - toBeChangedDSs.add(set); - } - } - result = new DistributionSetTagAssignmentResult(ids.size() - toBeChangedDSs.size(), - Collections.emptyList(), - Collections.unmodifiableList( - toBeChangedDSs.stream().map(distributionSetRepository::save).collect(Collectors.toList())), - distributionSetTag); - } else { - result = new DistributionSetTagAssignmentResult(ids.size() - toBeChangedDSs.size(), - Collections.unmodifiableList( - toBeChangedDSs.stream().map(distributionSetRepository::save).collect(Collectors.toList())), - Collections.emptyList(), distributionSetTag); - } - return result; - }); - } private T updateTag( final Collection dsIds, final Supplier tagSupplier, final BiFunction, DistributionSetTag, T> updater) { - final List allDs = dsIds.size() == 1 ? + final List allDs = dsIds.size() == 1 ? distributionSetRepository.findById(dsIds.iterator().next()).map(List::of).orElseGet(Collections::emptyList) : distributionSetRepository.findAll(DistributionSetSpecification.byIds(dsIds)); if (allDs.size() < dsIds.size()) { @@ -887,23 +906,4 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { entityManager.detach(distributionSetTag); } } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSet unassignTag(final long id, final long dsTagId) { - final JpaDistributionSet set = (JpaDistributionSet) getWithDetails(id) - .orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id)); - - final DistributionSetTag distributionSetTag = distributionSetTagManagement.get(dsTagId) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId)); - set.removeTag(distributionSetTag); - - final JpaDistributionSet result = distributionSetRepository.save(set); - - // No reason to save the tag - entityManager.detach(distributionSetTag); - return result; - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTagManagement.java index bb07e2b10..5f775a008 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTagManagement.java @@ -27,7 +27,6 @@ import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.builder.JpaTagCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; @@ -49,7 +48,6 @@ import org.springframework.validation.annotation.Validated; /** * JPA implementation of {@link TargetTagManagement}. - * */ @Transactional(readOnly = true) @Validated @@ -76,22 +74,11 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetTag update(final TagUpdate u) { - final GenericTagUpdate update = (GenericTagUpdate) u; - - final JpaDistributionSetTag tag = distributionSetTagRepository.findById(update.getId()) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, update.getId())); - - update.getName().ifPresent(tag::setName); - update.getDescription().ifPresent(tag::setDescription); - update.getColour().ifPresent(tag::setColour); - - return distributionSetTagRepository.save(tag); - } - - @Override - public Optional getByName(final String name) { - return distributionSetTagRepository.findByNameEquals(name); + public List create(final Collection dst) { + final List toCreate = dst.stream().map(JpaTagCreate.class::cast) + .map(JpaTagCreate::buildDistributionSetTag).toList(); + return Collections + .unmodifiableList(distributionSetTagRepository.saveAll(AccessController.Operation.CREATE, toCreate)); } @Override @@ -107,47 +94,30 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection dst) { - final List toCreate = dst.stream().map(JpaTagCreate.class::cast) - .map(JpaTagCreate::buildDistributionSetTag).toList(); - return Collections - .unmodifiableList(distributionSetTagRepository.saveAll(AccessController.Operation.CREATE, toCreate)); + public DistributionSetTag update(final TagUpdate u) { + final GenericTagUpdate update = (GenericTagUpdate) u; + + final JpaDistributionSetTag tag = distributionSetTagRepository.findById(update.getId()) + .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, update.getId())); + + update.getName().ifPresent(tag::setName); + update.getDescription().ifPresent(tag::setDescription); + update.getColour().ifPresent(tag::setColour); + + return distributionSetTagRepository.save(tag); + } + + @Override + public long count() { + return distributionSetTagRepository.count(); } @Override @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final String tagName) { - final JpaDistributionSetTag dsTag = distributionSetTagRepository - .findOne(DistributionSetTagSpecifications.byName(tagName)) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, tagName)); - - distributionSetTagRepository.delete(dsTag); - } - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTagRepository, pageable, null); - } - - @Override - public Page findByRsql(final Pageable pageable, final String rsqlParam) { - final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTagFields.class, - virtualPropertyReplacer, database); - - return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable, - Collections.singletonList(spec)); - } - - @Override - public Page findByDistributionSet(final Pageable pageable, final long distributionSetId) { - if (!distributionSetRepository.existsById(distributionSetId)) { - throw new EntityNotFoundException(DistributionSet.class, distributionSetId); - } - - return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable, - Collections.singletonList(TagSpecification.ofDistributionSet(distributionSetId))); + public void delete(final long id) { + distributionSetTagRepository.deleteById(id); } @Override @@ -170,26 +140,54 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage return Collections.unmodifiableList(distributionSetTagRepository.findAllById(ids)); } + @Override + public boolean exists(final long id) { + return distributionSetTagRepository.existsById(id); + } + @Override public Optional get(final long id) { return distributionSetTagRepository.findById(id).map(DistributionSetTag.class::cast); } + @Override + public Slice findAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTagRepository, pageable, null); + } + + @Override + public Page findByRsql(final Pageable pageable, final String rsqlParam) { + final Specification spec = RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTagFields.class, + virtualPropertyReplacer, database); + + return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable, + Collections.singletonList(spec)); + } + @Override @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long id) { - distributionSetTagRepository.deleteById(id); + public void delete(final String tagName) { + final JpaDistributionSetTag dsTag = distributionSetTagRepository + .findOne(DistributionSetTagSpecifications.byName(tagName)) + .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, tagName)); + + distributionSetTagRepository.delete(dsTag); } @Override - public boolean exists(final long id) { - return distributionSetTagRepository.existsById(id); + public Optional getByName(final String name) { + return distributionSetTagRepository.findByNameEquals(name); } @Override - public long count() { - return distributionSetTagRepository.count(); + public Page findByDistributionSet(final Pageable pageable, final long distributionSetId) { + if (!distributionSetRepository.existsById(distributionSetId)) { + throw new EntityNotFoundException(DistributionSet.class, distributionSetId); + } + + return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable, + Collections.singletonList(TagSpecification.ofDistributionSet(distributionSetId))); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java index 691f3a296..288fabe85 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java @@ -58,7 +58,6 @@ import org.springframework.validation.annotation.Validated; /** * JPA implementation of {@link DistributionSetTypeManagement}. - * */ @Transactional(readOnly = true) @Validated @@ -92,6 +91,72 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana this.quotaManagement = quotaManagement; } + @Override + public Optional getByKey(final String key) { + return distributionSetTypeRepository + .findOne(DistributionSetTypeSpecification.byKey(key)).map(DistributionSetType.class::cast); + } + + @Override + public Optional getByName(final String name) { + return distributionSetTypeRepository + .findOne(DistributionSetTypeSpecification.byName(name)).map(DistributionSetType.class::cast); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public DistributionSetType assignOptionalSoftwareModuleTypes(final long id, + final Collection softwareModulesTypeIds) { + return assignSoftwareModuleTypes(id, softwareModulesTypeIds, false); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public DistributionSetType assignMandatorySoftwareModuleTypes(final long id, + final Collection softwareModuleTypeIds) { + return assignSoftwareModuleTypes(id, softwareModuleTypeIds, true); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public DistributionSetType unassignSoftwareModuleType(final long id, final long softwareModuleTypeId) { + final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(id); + + checkDistributionSetTypeNotAssigned(id); + + type.removeModuleType(softwareModuleTypeId); + + return distributionSetTypeRepository.save(type); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List create(final Collection types) { + final List typesToCreate = types.stream().map(JpaDistributionSetTypeCreate.class::cast) + .map(JpaDistributionSetTypeCreate::build).toList(); + + return Collections.unmodifiableList( + distributionSetTypeRepository.saveAll(AccessController.Operation.CREATE, typesToCreate)); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public DistributionSetType create(final DistributionSetTypeCreate c) { + final JpaDistributionSetType distributionSetType = ((JpaDistributionSetTypeCreate) c).build(); + + return distributionSetTypeRepository.save(AccessController.Operation.CREATE, distributionSetType); + } + @Override @Transactional @Retryable(include = { @@ -130,15 +195,66 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana return distributionSetTypeRepository.save(type); } - private void addModuleTypes(final Collection currentSmTypeIds, final Collection updatedSmTypeIds, - final Function addModuleTypeCallback) { - final Set smTypeIdsToAdd = updatedSmTypeIds.stream().filter(id -> !currentSmTypeIds.contains(id)) - .collect(Collectors.toSet()); - if (!CollectionUtils.isEmpty(smTypeIdsToAdd)) { - softwareModuleTypeRepository.findAllById(smTypeIdsToAdd).forEach(addModuleTypeCallback::apply); + @Override + public long count() { + return distributionSetTypeRepository.count(DistributionSetTypeSpecification.isNotDeleted()); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void delete(final long id) { + final JpaDistributionSetType toDelete = distributionSetTypeRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, id)); + + unassignDsTypeFromTargetTypes(id); + + if (distributionSetRepository.countByTypeId(id) > 0) { + toDelete.setDeleted(true); + distributionSetTypeRepository.save(AccessController.Operation.DELETE, toDelete); + } else { + distributionSetTypeRepository.deleteById(id); } } + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void delete(final Collection ids) { + distributionSetTypeRepository.deleteAllById(ids); + } + + @Override + public List get(final Collection ids) { + return Collections.unmodifiableList(distributionSetTypeRepository.findAllById(ids)); + } + + @Override + public boolean exists(final long id) { + return distributionSetTypeRepository.existsById(id); + } + + @Override + public Optional get(final long id) { + return distributionSetTypeRepository.findById(id).map(DistributionSetType.class::cast); + } + + @Override + public Slice findAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTypeRepository, pageable, List.of( + DistributionSetTypeSpecification.isNotDeleted())); + } + + @Override + public Page findByRsql(final Pageable pageable, final String rsqlParam) { + return JpaManagementHelper.findAllWithCountBySpec(distributionSetTypeRepository, pageable, List.of( + RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTypeFields.class, virtualPropertyReplacer, + database), + DistributionSetTypeSpecification.isNotDeleted())); + } + private static void removeModuleTypes(final Collection currentSmTypeIds, final Collection updatedSmTypeIds, final LongFunction removeModuleTypeCallback) { @@ -149,22 +265,17 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana } } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType assignMandatorySoftwareModuleTypes(final long id, - final Collection softwareModuleTypeIds) { - return assignSoftwareModuleTypes(id, softwareModuleTypeIds, true); + private static boolean hasModuleChanges(final GenericDistributionSetTypeUpdate update) { + return update.getOptional().isPresent() || update.getMandatory().isPresent(); } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType assignOptionalSoftwareModuleTypes(final long id, - final Collection softwareModulesTypeIds) { - return assignSoftwareModuleTypes(id, softwareModulesTypeIds, false); + private void addModuleTypes(final Collection currentSmTypeIds, final Collection updatedSmTypeIds, + final Function addModuleTypeCallback) { + final Set smTypeIdsToAdd = updatedSmTypeIds.stream().filter(id -> !currentSmTypeIds.contains(id)) + .collect(Collectors.toSet()); + if (!CollectionUtils.isEmpty(smTypeIdsToAdd)) { + softwareModuleTypeRepository.findAllById(smTypeIdsToAdd).forEach(addModuleTypeCallback::apply); + } } private DistributionSetType assignSoftwareModuleTypes( @@ -189,14 +300,10 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana /** * Enforces the quota specifying the maximum number of * {@link SoftwareModuleType}s per {@link DistributionSetType}. - * - * @param id - * of the distribution set type - * @param requested - * number of software module types to check - * - * @throws AssignmentQuotaExceededException - * if the software module type quota is exceeded + * + * @param id of the distribution set type + * @param requested number of software module types to check + * @throws AssignmentQuotaExceededException if the software module type quota is exceeded */ private void assertSoftwareModuleTypeQuota(final long id, final int requested) { QuotaHelper.assertAssignmentQuota(id, requested, @@ -204,79 +311,6 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana DistributionSetType.class, distributionSetTypeRepository::countSmTypesById); } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType unassignSoftwareModuleType(final long id, final long softwareModuleTypeId) { - final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(id); - - checkDistributionSetTypeNotAssigned(id); - - type.removeModuleType(softwareModuleTypeId); - - return distributionSetTypeRepository.save(type); - } - - @Override - public Page findByRsql(final Pageable pageable, final String rsqlParam) { - return JpaManagementHelper.findAllWithCountBySpec(distributionSetTypeRepository, pageable, List.of( - RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTypeFields.class, virtualPropertyReplacer, - database), - DistributionSetTypeSpecification.isNotDeleted())); - } - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTypeRepository, pageable, List.of( - DistributionSetTypeSpecification.isNotDeleted())); - } - - @Override - public long count() { - return distributionSetTypeRepository.count(DistributionSetTypeSpecification.isNotDeleted()); - } - - @Override - public Optional getByName(final String name) { - return distributionSetTypeRepository - .findOne(DistributionSetTypeSpecification.byName(name)).map(DistributionSetType.class::cast); - } - - @Override - public Optional getByKey(final String key) { - return distributionSetTypeRepository - .findOne(DistributionSetTypeSpecification.byKey(key)).map(DistributionSetType.class::cast); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType create(final DistributionSetTypeCreate c) { - final JpaDistributionSetType distributionSetType = ((JpaDistributionSetTypeCreate) c).build(); - - return distributionSetTypeRepository.save(AccessController.Operation.CREATE, distributionSetType); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long id) { - final JpaDistributionSetType toDelete = distributionSetTypeRepository.findById(id) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, id)); - - unassignDsTypeFromTargetTypes(id); - - if (distributionSetRepository.countByTypeId(id) > 0) { - toDelete.setDeleted(true); - distributionSetTypeRepository.save(AccessController.Operation.DELETE, toDelete); - } else { - distributionSetTypeRepository.deleteById(id); - } - } - private void unassignDsTypeFromTargetTypes(final long typeId) { final List targetTypesByDsType = targetTypeRepository.findByDsType(typeId); targetTypesByDsType.forEach(targetType -> { @@ -285,54 +319,15 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana }); } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection types) { - final List typesToCreate = types.stream().map(JpaDistributionSetTypeCreate.class::cast) - .map(JpaDistributionSetTypeCreate::build).toList(); - - return Collections.unmodifiableList( - distributionSetTypeRepository.saveAll(AccessController.Operation.CREATE, typesToCreate)); - } - private JpaDistributionSetType findDistributionSetTypeAndThrowExceptionIfNotFound(final Long setId) { return (JpaDistributionSetType) get(setId) .orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, setId)); } - private static boolean hasModuleChanges(final GenericDistributionSetTypeUpdate update) { - return update.getOptional().isPresent() || update.getMandatory().isPresent(); - } - private void checkDistributionSetTypeNotAssigned(final Long id) { if (distributionSetRepository.countByTypeId(id) > 0) { throw new EntityReadOnlyException(String.format( "Distribution set type %s is already assigned to distribution sets and cannot be changed!", id)); } } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final Collection ids) { - distributionSetTypeRepository.deleteAllById(ids); - } - - @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(distributionSetTypeRepository.findAllById(ids)); - } - - @Override - public Optional get(final long id) { - return distributionSetTypeRepository.findById(id).map(DistributionSetType.class::cast); - } - - @Override - public boolean exists(final long id) { - return distributionSetTypeRepository.existsById(id); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java index 3e7753121..389a589a7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java @@ -91,10 +91,10 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { private final Database database; public JpaRolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository, - final RolloutRepository rolloutRepository, final ActionRepository actionRepository, - final TargetRepository targetRepository, final EntityManager entityManager, - final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache, - final Database database) { + final RolloutRepository rolloutRepository, final ActionRepository actionRepository, + final TargetRepository targetRepository, final EntityManager entityManager, + final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache, + final Database database) { this.rolloutGroupRepository = rolloutGroupRepository; this.rolloutRepository = rolloutRepository; this.actionRepository = actionRepository; @@ -105,37 +105,6 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { this.database = database; } - @Override - public Optional get(final long rolloutGroupId) { - return rolloutGroupRepository.findById(rolloutGroupId).map(RolloutGroup.class::cast); - } - - @Override - public Page findByRollout(final Pageable pageable, final long rolloutId) { - throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); - - return JpaManagementHelper.convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable); - } - - @Override - public Page findByRolloutAndRsql(final Pageable pageable, final long rolloutId, - final String rsqlParam) { - throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); - - final List> specList = Arrays.asList( - RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutGroupFields.class, virtualPropertyReplacer, - database), - (root, query, cb) -> cb.equal(root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId)); - - return JpaManagementHelper.findAllWithCountBySpec(rolloutGroupRepository, pageable, specList); - } - - private void throwEntityNotFoundExceptionIfRolloutDoesNotExist(final Long rolloutId) { - if (!rolloutRepository.existsById(rolloutId)) { - throw new EntityNotFoundException(Rollout.class, rolloutId); - } - } - @Override public Page findByRolloutWithDetailedStatus(final Pageable pageable, final long rolloutId) { throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); @@ -154,7 +123,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { for (final JpaRolloutGroup rolloutGroup : rolloutGroups) { final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus( - allStatesForRollout.get(rolloutGroup.getId()), (long)rolloutGroup.getTotalTargets(), + allStatesForRollout.get(rolloutGroup.getId()), (long) rolloutGroup.getTotalTargets(), rolloutGroup.getRollout().getActionType()); rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus); } @@ -162,6 +131,49 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { return JpaManagementHelper.convertPage(rolloutGroups, pageable); } + @Override + public Page findAllTargetsOfRolloutGroupWithActionStatus(final Pageable pageRequest, + final long rolloutGroupId) { + + throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); + + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = cb.createQuery(Object[].class); + final Root targetRoot = query.distinct(true).from(RolloutTargetGroup.class); + final Join targetJoin = targetRoot.join(RolloutTargetGroup_.target); + final ListJoin actionJoin = targetRoot.join(RolloutTargetGroup_.actions, + JoinType.LEFT); + + final CriteriaQuery multiselect = query + .multiselect(targetJoin, actionJoin.get(JpaAction_.status), + actionJoin.get(JpaAction_.lastActionStatusCode)) + .where(getRolloutGroupTargetWithRolloutGroupJoinCondition(rolloutGroupId, cb, targetRoot)) + .orderBy(getOrderBy(pageRequest, cb, targetJoin, actionJoin)); + final List targetWithActionStatus = entityManager.createQuery(multiselect) + .setFirstResult((int) pageRequest.getOffset()).setMaxResults(pageRequest.getPageSize()).getResultList() + .stream().map(this::getTargetWithActionStatusFromQuery).collect(Collectors.toList()); + + return new PageImpl<>(targetWithActionStatus, pageRequest, 0); + } + + @Override + public Optional get(final long rolloutGroupId) { + return rolloutGroupRepository.findById(rolloutGroupId).map(RolloutGroup.class::cast); + } + + @Override + public Page findByRolloutAndRsql(final Pageable pageable, final long rolloutId, + final String rsqlParam) { + throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); + + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutGroupFields.class, virtualPropertyReplacer, + database), + (root, query, cb) -> cb.equal(root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId)); + + return JpaManagementHelper.findAllWithCountBySpec(rolloutGroupRepository, pageable, specList); + } + @Override public Page findByRolloutAndRsqlWithDetailedStatus(final Pageable pageable, final long rolloutId, final String rsqlParam) { @@ -189,6 +201,53 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { return JpaManagementHelper.convertPage(rolloutGroups, pageable); } + @Override + public Page findByRollout(final Pageable pageable, final long rolloutId) { + throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); + + return JpaManagementHelper.convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable); + } + + @Override + public long countByRollout(final long rolloutId) { + throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); + + return rolloutGroupRepository.countByRolloutId(rolloutId); + } + + @Override + public Page findTargetsOfRolloutGroup(final Pageable page, final long rolloutGroupId) { + final JpaRolloutGroup rolloutGroup = rolloutGroupRepository.findById(rolloutGroupId) + .orElseThrow(() -> new EntityNotFoundException(RolloutGroup.class, rolloutGroupId)); + + if (isRolloutStatusReady(rolloutGroup)) { + // in case of status ready the action has not been created yet and + // the relation information between target and rollout-group is + // stored in the #TargetRolloutGroup. + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page, + Collections.singletonList(TargetSpecifications.isInRolloutGroup(rolloutGroupId))); + } + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page, + Collections.singletonList(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId))); + } + + @Override + public Page findTargetsOfRolloutGroupByRsql(final Pageable pageable, final long rolloutGroupId, + final String rsqlParam) { + throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); + + final List> specList = Arrays.asList( + RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), + (root, query, cb) -> { + final ListJoin rolloutTargetJoin = root + .join(JpaTarget_.rolloutTargetGroup); + return cb.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), + rolloutGroupId); + }); + + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList); + } + @Override public Optional getWithDetailedStatus(final long rolloutGroupId) { final Optional rolloutGroup = get(rolloutGroupId); @@ -214,6 +273,28 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { } + @Override + public long countTargetsOfRolloutsGroup(final long rolloutGroupId) { + throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); + + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + final CriteriaQuery countQuery = cb.createQuery(Long.class); + final Root countQueryFrom = countQuery.from(RolloutTargetGroup.class); + countQuery.select(cb.count(countQueryFrom)) + .where(getRolloutGroupTargetWithRolloutGroupJoinCondition(rolloutGroupId, cb, countQueryFrom)); + return entityManager.createQuery(countQuery).getSingleResult(); + } + + private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) { + return rolloutGroup != null && (RolloutStatus.READY == rolloutGroup.getRollout().getStatus()); + } + + private void throwEntityNotFoundExceptionIfRolloutDoesNotExist(final Long rolloutId) { + if (!rolloutRepository.existsById(rolloutId)) { + throw new EntityNotFoundException(Rollout.class, rolloutId); + } + } + private Map> getStatusCountItemForRolloutGroup(final List groupIds) { final Map> fromCache = rolloutStatusCache .getRolloutGroupStatus(groupIds); @@ -235,68 +316,6 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { return fromCache; } - @Override - public Page findTargetsOfRolloutGroupByRsql(final Pageable pageable, final long rolloutGroupId, - final String rsqlParam) { - throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); - - final List> specList = Arrays.asList( - RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), - (root, query, cb) -> { - final ListJoin rolloutTargetJoin = root - .join(JpaTarget_.rolloutTargetGroup); - return cb.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), - rolloutGroupId); - }); - - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList); - } - - @Override - public Page findTargetsOfRolloutGroup(final Pageable page, final long rolloutGroupId) { - final JpaRolloutGroup rolloutGroup = rolloutGroupRepository.findById(rolloutGroupId) - .orElseThrow(() -> new EntityNotFoundException(RolloutGroup.class, rolloutGroupId)); - - if (isRolloutStatusReady(rolloutGroup)) { - // in case of status ready the action has not been created yet and - // the relation information between target and rollout-group is - // stored in the #TargetRolloutGroup. - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page, - Collections.singletonList(TargetSpecifications.isInRolloutGroup(rolloutGroupId))); - } - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page, - Collections.singletonList(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId))); - } - - private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) { - return rolloutGroup != null && (RolloutStatus.READY == rolloutGroup.getRollout().getStatus()); - } - - @Override - public Page findAllTargetsOfRolloutGroupWithActionStatus(final Pageable pageRequest, - final long rolloutGroupId) { - - throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); - - final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - final CriteriaQuery query = cb.createQuery(Object[].class); - final Root targetRoot = query.distinct(true).from(RolloutTargetGroup.class); - final Join targetJoin = targetRoot.join(RolloutTargetGroup_.target); - final ListJoin actionJoin = targetRoot.join(RolloutTargetGroup_.actions, - JoinType.LEFT); - - final CriteriaQuery multiselect = query - .multiselect(targetJoin, actionJoin.get(JpaAction_.status), - actionJoin.get(JpaAction_.lastActionStatusCode)) - .where(getRolloutGroupTargetWithRolloutGroupJoinCondition(rolloutGroupId, cb, targetRoot)) - .orderBy(getOrderBy(pageRequest, cb, targetJoin, actionJoin)); - final List targetWithActionStatus = entityManager.createQuery(multiselect) - .setFirstResult((int) pageRequest.getOffset()).setMaxResults(pageRequest.getPageSize()).getResultList() - .stream().map(this::getTargetWithActionStatusFromQuery).collect(Collectors.toList()); - - return new PageImpl<>(targetWithActionStatus, pageRequest, 0); - } - private Predicate getRolloutGroupTargetWithRolloutGroupJoinCondition(final long rolloutGroupId, final CriteriaBuilder cb, final Root targetRoot) { return cb.equal(targetRoot.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), // @@ -327,29 +346,10 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { }).collect(Collectors.toList()); } - @Override - public long countTargetsOfRolloutsGroup(final long rolloutGroupId) { - throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); - - final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - final CriteriaQuery countQuery = cb.createQuery(Long.class); - final Root countQueryFrom = countQuery.from(RolloutTargetGroup.class); - countQuery.select(cb.count(countQueryFrom)) - .where(getRolloutGroupTargetWithRolloutGroupJoinCondition(rolloutGroupId, cb, countQueryFrom)); - return entityManager.createQuery(countQuery).getSingleResult(); - } - private void throwExceptionIfRolloutGroupDoesNotExist(final Long rolloutGroupId) { if (!rolloutGroupRepository.existsById(rolloutGroupId)) { throw new EntityNotFoundException(RolloutGroup.class, rolloutGroupId); } } - @Override - public long countByRollout(final long rolloutId) { - throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); - - return rolloutGroupRepository.countByRolloutId(rolloutId); - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java index ee4dcbc11..fe21bc29e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java @@ -24,9 +24,10 @@ import java.util.stream.Collectors; import jakarta.validation.ConstraintDeclarationException; import jakarta.validation.Valid; import jakarta.validation.ValidationException; - import jakarta.validation.constraints.NotNull; + import lombok.extern.slf4j.Slf4j; +import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryProperties; @@ -37,7 +38,6 @@ import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.repository.builder.DynamicRolloutGroupTemplate; import org.eclipse.hawkbit.repository.builder.GenericRolloutUpdate; import org.eclipse.hawkbit.repository.builder.RolloutCreate; @@ -110,31 +110,6 @@ public class JpaRolloutManagement implements RolloutManagement { private static final List ROLLOUT_STATUS_STOPPABLE = Arrays.asList(RolloutStatus.RUNNING, RolloutStatus.CREATING, RolloutStatus.PAUSED, RolloutStatus.READY, RolloutStatus.STARTING, RolloutStatus.WAITING_FOR_APPROVAL, RolloutStatus.APPROVAL_DENIED); - - @Autowired - private RepositoryProperties repositoryProperties; - - @Autowired - private RolloutRepository rolloutRepository; - - @Autowired - private RolloutGroupRepository rolloutGroupRepository; - - @Autowired - private ActionRepository actionRepository; - - @Autowired - private AfterTransactionCommitExecutor afterCommit; - - @Autowired - private QuotaManagement quotaManagement; - - @Autowired - private RolloutStatusCache rolloutStatusCache; - - @Autowired - private StartNextGroupRolloutGroupSuccessAction startNextRolloutGroupAction; - private final TargetManagement targetManagement; private final DistributionSetManagement distributionSetManagement; private final VirtualPropertyReplacer virtualPropertyReplacer; @@ -144,6 +119,22 @@ public class JpaRolloutManagement implements RolloutManagement { private final EventPublisherHolder eventPublisherHolder; private final ContextAware contextAware; private final Database database; + @Autowired + private RepositoryProperties repositoryProperties; + @Autowired + private RolloutRepository rolloutRepository; + @Autowired + private RolloutGroupRepository rolloutGroupRepository; + @Autowired + private ActionRepository actionRepository; + @Autowired + private AfterTransactionCommitExecutor afterCommit; + @Autowired + private QuotaManagement quotaManagement; + @Autowired + private RolloutStatusCache rolloutStatusCache; + @Autowired + private StartNextGroupRolloutGroupSuccessAction startNextRolloutGroupAction; public JpaRolloutManagement(final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement, final EventPublisherHolder eventPublisherHolder, @@ -163,34 +154,29 @@ public class JpaRolloutManagement implements RolloutManagement { this.contextAware = contextAware; } - @Override - public Page findAll(final Pageable pageable, final boolean deleted) { - return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, Collections - .singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort()))); + public static String createRolloutLockKey(final String tenant) { + return tenant + "-rollout"; + } + + public void publishRolloutGroupCreatedEventAfterCommit(final RolloutGroup group, final Rollout rollout) { + afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent( + new RolloutGroupCreatedEvent(group, rollout.getId(), eventPublisherHolder.getApplicationId()))); } @Override - public Page findByRsql(final Pageable pageable, final String rsqlParam, final boolean deleted) { - final List> specList = new ArrayList<>(2); - specList.add( - RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database)); - specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort())); - - return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, specList); + public long count() { + return rolloutRepository.count( + RolloutSpecification.isDeletedWithDistributionSet(false, Sort.by(Direction.DESC, JpaRollout_.ID))); } @Override - public Optional get(final long rolloutId) { - return rolloutRepository.findById(rolloutId).map(Rollout.class::cast); + public long countByFilters(final String searchText) { + return rolloutRepository.count(RolloutSpecification.likeName(searchText, false)); } @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Rollout create(@NotNull @Valid RolloutCreate create, int amountGroup, boolean confirmationRequired, - @NotNull RolloutGroupConditions conditions) { - return create(create, amountGroup, confirmationRequired, conditions, null); + public long countByDistributionSetIdAndRolloutIsStoppable(final long setId) { + return rolloutRepository.countByDistributionSetIdAndStatusIn(setId, ROLLOUT_STATUS_STOPPABLE); } @Override @@ -204,7 +190,7 @@ public class JpaRolloutManagement implements RolloutManagement { } else if (amountGroup == 0) { if (dynamicRolloutGroupTemplate == null) { throw new ValidationException( - "When amount of groups is 0, the rollouts shall be dynamic and a dynamic group template must be provided"); + "When amount of groups is 0, the rollouts shall be dynamic and a dynamic group template must be provided"); } } else { RolloutHelper.verifyRolloutGroupAmount(amountGroup, quotaManagement); @@ -219,6 +205,15 @@ public class JpaRolloutManagement implements RolloutManagement { return createRolloutGroups(amountGroup, conditions, savedRollout, confirmationRequired, dynamicRolloutGroupTemplate); } + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Rollout create(@NotNull @Valid RolloutCreate create, int amountGroup, boolean confirmationRequired, + @NotNull RolloutGroupConditions conditions) { + return create(create, amountGroup, confirmationRequired, conditions, null); + } + @Override @Transactional @Retryable(include = { @@ -234,6 +229,314 @@ public class JpaRolloutManagement implements RolloutManagement { return createRolloutGroups(groups, conditions, savedRollout); } + @Override + @Async + public ListenableFuture validateTargetsInGroups(final List groups, + final String targetFilter, final Long createdAt, final Long dsTypeId) { + + final TargetCount targets = calculateTargets(targetFilter, createdAt, dsTypeId); + long totalTargets = targets.total(); + final String baseFilter = targets.filter(); + + if (totalTargets == 0) { + throw new ConstraintDeclarationException("Rollout target filter does not match any targets"); + } + + return new AsyncResult<>( + validateTargetsInGroups(groups.stream().map(RolloutGroupCreate::build).collect(Collectors.toList()), + baseFilter, totalTargets, dsTypeId)); + } + + @Override + public Page findAll(final Pageable pageable, final boolean deleted) { + return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, Collections + .singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort()))); + } + + @Override + public Slice findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) { + final Slice rollouts = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable, + Collections + .singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort()))); + setRolloutStatusDetails(rollouts); + return rollouts; + } + + @Override + public Page findByRsql(final Pageable pageable, final String rsqlParam, final boolean deleted) { + final List> specList = new ArrayList<>(2); + specList.add( + RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database)); + specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort())); + + return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, specList); + } + + @Override + public Slice findByFiltersWithDetailedStatus(final Pageable pageable, final String searchText, + final boolean deleted) { + final Slice findAll = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable, + Collections.singletonList(RolloutSpecification.likeName(searchText, deleted))); + setRolloutStatusDetails(findAll); + return findAll; + } + + @Override + public List findActiveRollouts() { + return rolloutRepository.findByStatusIn(ACTIVE_ROLLOUTS); + } + + @Override + public Optional get(final long rolloutId) { + return rolloutRepository.findById(rolloutId).map(Rollout.class::cast); + } + + @Override + public Optional getByName(final String rolloutName) { + return rolloutRepository.findByName(rolloutName); + } + + @Override + public Optional getWithDetailedStatus(final long rolloutId) { + final Optional rollout = get(rolloutId); + + if (!rollout.isPresent()) { + return rollout; + } + + List rolloutStatusCountItems = rolloutStatusCache.getRolloutStatus(rolloutId); + + if (CollectionUtils.isEmpty(rolloutStatusCountItems)) { + rolloutStatusCountItems = actionRepository.getStatusCountByRolloutId(rolloutId); + rolloutStatusCache.putRolloutStatus(rolloutId, rolloutStatusCountItems); + } + + final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems, + rollout.get().getTotalTargets(), rollout.get().getActionType()); + ((JpaRollout) rollout.get()).setTotalTargetCountStatus(totalTargetCountStatus); + return rollout; + } + + @Override + public boolean exists(final long rolloutId) { + return rolloutRepository.existsById(rolloutId); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void pauseRollout(final long rolloutId) { + final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); + if (RolloutStatus.RUNNING != rollout.getStatus()) { + throw new RolloutIllegalStateException("Rollout can only be paused in state running but current state is " + + rollout.getStatus().name().toLowerCase()); + } + // setting the complete rollout only in paused state. This is sufficient + // due the currently running groups will be completed and new groups are + // not started until rollout goes back to running state again. The + // periodically check for running rollouts will skip rollouts in pause + // state. + rollout.setStatus(RolloutStatus.PAUSED); + rolloutRepository.save(rollout); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void resumeRollout(final long rolloutId) { + final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); + if (RolloutStatus.PAUSED != rollout.getStatus()) { + throw new RolloutIllegalStateException("Rollout can only be resumed in state paused but current state is " + + rollout.getStatus().name().toLowerCase()); + } + rollout.setStatus(RolloutStatus.RUNNING); + rolloutRepository.save(rollout); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Rollout approveOrDeny(final long rolloutId, final Rollout.ApprovalDecision decision) { + return this.approveOrDeny(rolloutId, decision, null); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Rollout approveOrDeny(final long rolloutId, final Rollout.ApprovalDecision decision, final String remark) { + log.debug("approveOrDeny rollout called for rollout {} with decision {}", rolloutId, decision); + final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); + RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.WAITING_FOR_APPROVAL); + switch (decision) { + case APPROVED: + rollout.setStatus(RolloutStatus.READY); + break; + case DENIED: + rollout.setStatus(RolloutStatus.APPROVAL_DENIED); + break; + default: + throw new IllegalArgumentException("Unknown approval decision: " + decision); + } + rollout.setApprovalDecidedBy(rolloutApprovalStrategy.getApprovalUser(rollout)); + if (remark != null) { + rollout.setApprovalRemark(remark); + } + return rolloutRepository.save(rollout); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Rollout start(final long rolloutId) { + log.debug("startRollout called for rollout {}", rolloutId); + + final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); + RolloutHelper.checkIfRolloutCanStarted(rollout, rollout); + rollout.setStatus(RolloutStatus.STARTING); + rollout.setLastCheck(0); + return rolloutRepository.save(rollout); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Rollout update(final RolloutUpdate u) { + final GenericRolloutUpdate update = (GenericRolloutUpdate) u; + final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(update.getId()); + + checkIfDeleted(update.getId(), rollout.getStatus()); + + update.getName().ifPresent(rollout::setName); + update.getDescription().ifPresent(rollout::setDescription); + return rolloutRepository.save(rollout); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void delete(final long rolloutId) { + final JpaRollout jpaRollout = rolloutRepository.findById(rolloutId) + .orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId)); + + if (jpaRollout == null) { + throw new EntityNotFoundException(Rollout.class, rolloutId); + } + + if (RolloutStatus.DELETING == jpaRollout.getStatus()) { + return; + } + + jpaRollout.setStatus(RolloutStatus.DELETING); + rolloutRepository.save(jpaRollout); + } + + @Override + @Transactional + public void cancelRolloutsForDistributionSet(final DistributionSet set) { + // stop all rollouts for this distribution set + rolloutRepository.findByDistributionSetAndStatusIn(set, ROLLOUT_STATUS_STOPPABLE).forEach(rollout -> { + final JpaRollout jpaRollout = (JpaRollout) rollout; + jpaRollout.setStatus(RolloutStatus.STOPPING); + rolloutRepository.save(jpaRollout); + log.debug("Rollout {} stopped", jpaRollout.getId()); + }); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void triggerNextGroup(final long rolloutId) { + final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); + if (RolloutStatus.RUNNING != rollout.getStatus()) { + throw new RolloutIllegalStateException("Rollout is not in running state"); + } + final List groups = rollout.getRolloutGroups(); + + final boolean isNextGroupTriggerable = groups.stream() + .anyMatch(g -> RolloutGroupStatus.SCHEDULED.equals(g.getStatus())); + + if (!isNextGroupTriggerable) { + throw new RolloutIllegalStateException("Rollout does not have any groups left to be triggered"); + } + + final RolloutGroup latestRunning = groups.stream() + .sorted(Comparator.comparingLong(RolloutGroup::getId).reversed()) + .filter(g -> RolloutGroupStatus.RUNNING.equals(g.getStatus())) + .findFirst() + .orElseThrow(() -> new RolloutIllegalStateException("No group is running")); + + startNextRolloutGroupAction.exec(rollout, latestRunning); + } + + @Override + public void setRolloutStatusDetails(final Slice rollouts) { + final List rolloutIds = rollouts.getContent().stream().map(Rollout::getId).collect(Collectors.toList()); + final Map> allStatesForRollout = getStatusCountItemForRollout( + rolloutIds); + + if (allStatesForRollout != null) { + rollouts.forEach(rollout -> { + final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus( + allStatesForRollout.get(rollout.getId()), rollout.getTotalTargets(), rollout.getActionType()); + ((JpaRollout) rollout).setTotalTargetCountStatus(totalTargetCountStatus); + }); + } + } + + /** + * In case the given group is missing conditions or actions, they will be set + * from the supplied default conditions. + * + * @param create group to check + * @param conditions default conditions and actions + */ + private static JpaRolloutGroup prepareRolloutGroupWithDefaultConditions(final RolloutGroupCreate create, + final RolloutGroupConditions conditions) { + final JpaRolloutGroup group = ((JpaRolloutGroupCreate) create).build(); + + if (group.getSuccessCondition() == null) { + group.setSuccessCondition(conditions.getSuccessCondition()); + } + if (group.getSuccessConditionExp() == null) { + group.setSuccessConditionExp(conditions.getSuccessConditionExp()); + } + if (group.getSuccessAction() == null) { + group.setSuccessAction(conditions.getSuccessAction()); + } + if (group.getSuccessActionExp() == null) { + group.setSuccessActionExp(conditions.getSuccessActionExp()); + } + + if (group.getErrorCondition() == null) { + group.setErrorCondition(conditions.getErrorCondition()); + } + if (group.getErrorConditionExp() == null) { + group.setErrorConditionExp(conditions.getErrorConditionExp()); + } + if (group.getErrorAction() == null) { + group.setErrorAction(conditions.getErrorAction()); + } + if (group.getErrorActionExp() == null) { + group.setErrorActionExp(conditions.getErrorActionExp()); + } + + return group; + } + + private static void checkIfDeleted(final Long rolloutId, final RolloutStatus status) { + if (RolloutStatus.DELETING == status || RolloutStatus.DELETED == status) { + throw new EntityReadOnlyException("Rollout " + rolloutId + " is soft deleted and cannot be changed"); + } + } + private JpaRollout createRollout(final JpaRollout rollout, final boolean pureDynamic) { WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(rollout); final JpaDistributionSet distributionSet = (JpaDistributionSet) rollout.getDistributionSet(); @@ -259,7 +562,7 @@ public class JpaRolloutManagement implements RolloutManagement { rollout.setTotalTargets(totalTargets); } - if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) { + if (((JpaDistributionSetManagement) distributionSetManagement).isImplicitLockApplicable(distributionSet)) { distributionSetManagement.lock(distributionSet.getId()); } @@ -391,253 +694,11 @@ public class JpaRolloutManagement implements RolloutManagement { return rolloutRepository.save(savedRollout); } - /** - * In case the given group is missing conditions or actions, they will be set - * from the supplied default conditions. - * - * @param create - * group to check - * @param conditions - * default conditions and actions - */ - private static JpaRolloutGroup prepareRolloutGroupWithDefaultConditions(final RolloutGroupCreate create, - final RolloutGroupConditions conditions) { - final JpaRolloutGroup group = ((JpaRolloutGroupCreate) create).build(); - - if (group.getSuccessCondition() == null) { - group.setSuccessCondition(conditions.getSuccessCondition()); - } - if (group.getSuccessConditionExp() == null) { - group.setSuccessConditionExp(conditions.getSuccessConditionExp()); - } - if (group.getSuccessAction() == null) { - group.setSuccessAction(conditions.getSuccessAction()); - } - if (group.getSuccessActionExp() == null) { - group.setSuccessActionExp(conditions.getSuccessActionExp()); - } - - if (group.getErrorCondition() == null) { - group.setErrorCondition(conditions.getErrorCondition()); - } - if (group.getErrorConditionExp() == null) { - group.setErrorConditionExp(conditions.getErrorConditionExp()); - } - if (group.getErrorAction() == null) { - group.setErrorAction(conditions.getErrorAction()); - } - if (group.getErrorActionExp() == null) { - group.setErrorActionExp(conditions.getErrorActionExp()); - } - - return group; - } - - public void publishRolloutGroupCreatedEventAfterCommit(final RolloutGroup group, final Rollout rollout) { - afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent( - new RolloutGroupCreatedEvent(group, rollout.getId(), eventPublisherHolder.getApplicationId()))); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Rollout approveOrDeny(final long rolloutId, final Rollout.ApprovalDecision decision) { - return this.approveOrDeny(rolloutId, decision, null); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Rollout approveOrDeny(final long rolloutId, final Rollout.ApprovalDecision decision, final String remark) { - log.debug("approveOrDeny rollout called for rollout {} with decision {}", rolloutId, decision); - final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); - RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.WAITING_FOR_APPROVAL); - switch (decision) { - case APPROVED: - rollout.setStatus(RolloutStatus.READY); - break; - case DENIED: - rollout.setStatus(RolloutStatus.APPROVAL_DENIED); - break; - default: - throw new IllegalArgumentException("Unknown approval decision: " + decision); - } - rollout.setApprovalDecidedBy(rolloutApprovalStrategy.getApprovalUser(rollout)); - if (remark != null) { - rollout.setApprovalRemark(remark); - } - return rolloutRepository.save(rollout); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Rollout start(final long rolloutId) { - log.debug("startRollout called for rollout {}", rolloutId); - - final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); - RolloutHelper.checkIfRolloutCanStarted(rollout, rollout); - rollout.setStatus(RolloutStatus.STARTING); - rollout.setLastCheck(0); - return rolloutRepository.save(rollout); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void pauseRollout(final long rolloutId) { - final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); - if (RolloutStatus.RUNNING != rollout.getStatus()) { - throw new RolloutIllegalStateException("Rollout can only be paused in state running but current state is " - + rollout.getStatus().name().toLowerCase()); - } - // setting the complete rollout only in paused state. This is sufficient - // due the currently running groups will be completed and new groups are - // not started until rollout goes back to running state again. The - // periodically check for running rollouts will skip rollouts in pause - // state. - rollout.setStatus(RolloutStatus.PAUSED); - rolloutRepository.save(rollout); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void resumeRollout(final long rolloutId) { - final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); - if (RolloutStatus.PAUSED != rollout.getStatus()) { - throw new RolloutIllegalStateException("Rollout can only be resumed in state paused but current state is " - + rollout.getStatus().name().toLowerCase()); - } - rollout.setStatus(RolloutStatus.RUNNING); - rolloutRepository.save(rollout); - } - - public static String createRolloutLockKey(final String tenant) { - return tenant + "-rollout"; - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long rolloutId) { - final JpaRollout jpaRollout = rolloutRepository.findById(rolloutId) - .orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId)); - - if (jpaRollout == null) { - throw new EntityNotFoundException(Rollout.class, rolloutId); - } - - if (RolloutStatus.DELETING == jpaRollout.getStatus()) { - return; - } - - jpaRollout.setStatus(RolloutStatus.DELETING); - rolloutRepository.save(jpaRollout); - } - - @Override - public long count() { - return rolloutRepository.count( - RolloutSpecification.isDeletedWithDistributionSet(false, Sort.by(Direction.DESC, JpaRollout_.ID))); - } - - @Override - public long countByFilters(final String searchText) { - return rolloutRepository.count(RolloutSpecification.likeName(searchText, false)); - } - - @Override - public long countByDistributionSetIdAndRolloutIsStoppable(final long setId) { - return rolloutRepository.countByDistributionSetIdAndStatusIn(setId, ROLLOUT_STATUS_STOPPABLE); - } - - @Override - public Slice findByFiltersWithDetailedStatus(final Pageable pageable, final String searchText, - final boolean deleted) { - final Slice findAll = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable, - Collections.singletonList(RolloutSpecification.likeName(searchText, deleted))); - setRolloutStatusDetails(findAll); - return findAll; - } - - @Override - public List findActiveRollouts() { - return rolloutRepository.findByStatusIn(ACTIVE_ROLLOUTS); - } - - @Override - public Optional getByName(final String rolloutName) { - return rolloutRepository.findByName(rolloutName); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Rollout update(final RolloutUpdate u) { - final GenericRolloutUpdate update = (GenericRolloutUpdate) u; - final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(update.getId()); - - checkIfDeleted(update.getId(), rollout.getStatus()); - - update.getName().ifPresent(rollout::setName); - update.getDescription().ifPresent(rollout::setDescription); - return rolloutRepository.save(rollout); - } - - private static void checkIfDeleted(final Long rolloutId, final RolloutStatus status) { - if (RolloutStatus.DELETING == status || RolloutStatus.DELETED == status) { - throw new EntityReadOnlyException("Rollout " + rolloutId + " is soft deleted and cannot be changed"); - } - } - private JpaRollout getRolloutOrThrowExceptionIfNotFound(final Long rolloutId) { return rolloutRepository.findById(rolloutId) .orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId)); } - @Override - public Slice findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) { - final Slice rollouts = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable, - Collections - .singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort()))); - setRolloutStatusDetails(rollouts); - return rollouts; - } - - @Override - public Optional getWithDetailedStatus(final long rolloutId) { - final Optional rollout = get(rolloutId); - - if (!rollout.isPresent()) { - return rollout; - } - - List rolloutStatusCountItems = rolloutStatusCache.getRolloutStatus(rolloutId); - - if (CollectionUtils.isEmpty(rolloutStatusCountItems)) { - rolloutStatusCountItems = actionRepository.getStatusCountByRolloutId(rolloutId); - rolloutStatusCache.putRolloutStatus(rolloutId, rolloutStatusCountItems); - } - - final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems, - rollout.get().getTotalTargets(), rollout.get().getActionType()); - ((JpaRollout) rollout.get()).setTotalTargetCountStatus(totalTargetCountStatus); - return rollout; - } - - @Override - public boolean exists(final long rolloutId) { - return rolloutRepository.existsById(rolloutId); - } - private Map> getStatusCountItemForRollout(final List rollouts) { if (rollouts.isEmpty()) { return null; @@ -662,60 +723,32 @@ public class JpaRolloutManagement implements RolloutManagement { return fromCache; } - @Override - public void setRolloutStatusDetails(final Slice rollouts) { - final List rolloutIds = rollouts.getContent().stream().map(Rollout::getId).collect(Collectors.toList()); - final Map> allStatesForRollout = getStatusCountItemForRollout( - rolloutIds); - - if (allStatesForRollout != null) { - rollouts.forEach(rollout -> { - final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus( - allStatesForRollout.get(rollout.getId()), rollout.getTotalTargets(), rollout.getActionType()); - ((JpaRollout) rollout).setTotalTargetCountStatus(totalTargetCountStatus); - }); - } - } - /** * Enforces the quota defining the maximum number of {@link Target}s per * {@link RolloutGroup}. * - * @param requested - * number of targets to check + * @param requested number of targets to check */ private void assertTargetsPerRolloutGroupQuota(final long requested) { final int quota = quotaManagement.getMaxTargetsPerRolloutGroup(); QuotaHelper.assertAssignmentQuota(requested, quota, Target.class, RolloutGroup.class); } - @Override - @Transactional - public void cancelRolloutsForDistributionSet(final DistributionSet set) { - // stop all rollouts for this distribution set - rolloutRepository.findByDistributionSetAndStatusIn(set, ROLLOUT_STATUS_STOPPABLE).forEach(rollout -> { - final JpaRollout jpaRollout = (JpaRollout) rollout; - jpaRollout.setStatus(RolloutStatus.STOPPING); - rolloutRepository.save(jpaRollout); - log.debug("Rollout {} stopped", jpaRollout.getId()); - }); - } - private RolloutGroupsValidation validateTargetsInGroups(final List groups, final String baseFilter, final long totalTargets, final Long dsTypeId) { final List groupTargetCounts = new ArrayList<>(groups.size()); Map targetFilterCounts; if (!RolloutHelper.isRolloutRetried(baseFilter)) { targetFilterCounts = groups.stream() - .map(group -> RolloutHelper.getGroupTargetFilter(baseFilter, group)).distinct() - .collect(Collectors.toMap(Function.identity(), - groupTargetFilter -> targetManagement.countByRsqlAndCompatible(groupTargetFilter, dsTypeId))); + .map(group -> RolloutHelper.getGroupTargetFilter(baseFilter, group)).distinct() + .collect(Collectors.toMap(Function.identity(), + groupTargetFilter -> targetManagement.countByRsqlAndCompatible(groupTargetFilter, dsTypeId))); } else { targetFilterCounts = groups.stream() - .map(group -> RolloutHelper.getGroupTargetFilter(baseFilter, group)).distinct() - .collect(Collectors.toMap(Function.identity(), - groupTargetFilter -> targetManagement.countByFailedInRollout( - RolloutHelper.getIdFromRetriedTargetFilter(baseFilter), dsTypeId))); + .map(group -> RolloutHelper.getGroupTargetFilter(baseFilter, group)).distinct() + .collect(Collectors.toMap(Function.identity(), + groupTargetFilter -> targetManagement.countByFailedInRollout( + RolloutHelper.getIdFromRetriedTargetFilter(baseFilter), dsTypeId))); } long unusedTargetsCount = 0; @@ -786,51 +819,6 @@ public class JpaRolloutManagement implements RolloutManagement { return totalTargets - validation.getTargetsInGroups(); } - @Override - @Async - public ListenableFuture validateTargetsInGroups(final List groups, - final String targetFilter, final Long createdAt, final Long dsTypeId) { - - final TargetCount targets = calculateTargets(targetFilter, createdAt, dsTypeId); - long totalTargets = targets.total(); - final String baseFilter = targets.filter(); - - if (totalTargets == 0) { - throw new ConstraintDeclarationException("Rollout target filter does not match any targets"); - } - - return new AsyncResult<>( - validateTargetsInGroups(groups.stream().map(RolloutGroupCreate::build).collect(Collectors.toList()), - baseFilter, totalTargets, dsTypeId)); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void triggerNextGroup(final long rolloutId) { - final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId); - if (RolloutStatus.RUNNING != rollout.getStatus()) { - throw new RolloutIllegalStateException("Rollout is not in running state"); - } - final List groups = rollout.getRolloutGroups(); - - final boolean isNextGroupTriggerable = groups.stream() - .anyMatch(g -> RolloutGroupStatus.SCHEDULED.equals(g.getStatus())); - - if (!isNextGroupTriggerable) { - throw new RolloutIllegalStateException("Rollout does not have any groups left to be triggered"); - } - - final RolloutGroup latestRunning = groups.stream() - .sorted(Comparator.comparingLong(RolloutGroup::getId).reversed()) - .filter(g -> RolloutGroupStatus.RUNNING.equals(g.getStatus())) - .findFirst() - .orElseThrow(() -> new RolloutIllegalStateException("No group is running")); - - startNextRolloutGroupAction.exec(rollout, latestRunning); - } - private TargetCount calculateTargets(final String targetFilter, final Long createdAt, final Long dsTypeId) { String baseFilter; long totalTargets; @@ -839,7 +827,7 @@ public class JpaRolloutManagement implements RolloutManagement { totalTargets = targetManagement.countByRsqlAndCompatible(baseFilter, dsTypeId); } else { totalTargets = targetManagement.countByFailedInRollout( - RolloutHelper.getIdFromRetriedTargetFilter(targetFilter), dsTypeId); + RolloutHelper.getIdFromRetriedTargetFilter(targetFilter), dsTypeId); baseFilter = targetFilter; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java index 4025172a8..7d0d3eb35 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java @@ -22,15 +22,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jakarta.persistence.EntityManager; -import jakarta.persistence.Tuple; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Expression; -import jakarta.persistence.criteria.JoinType; -import jakarta.persistence.criteria.ListJoin; -import jakarta.persistence.criteria.Order; -import jakarta.persistence.criteria.Predicate; -import jakarta.persistence.criteria.Root; import org.eclipse.hawkbit.repository.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.ArtifactManagement; @@ -47,14 +38,11 @@ import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataUpdate; import org.eclipse.hawkbit.repository.builder.SoftwareModuleUpdate; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleCreate; import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata_; @@ -68,7 +56,6 @@ import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Artifact; -import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; @@ -80,10 +67,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; -import org.springframework.data.domain.SliceImpl; -import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.query.QueryUtils; import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; @@ -133,23 +117,20 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModule update(final SoftwareModuleUpdate u) { - final GenericSoftwareModuleUpdate update = (GenericSoftwareModuleUpdate) u; + public List create(final Collection swModules) { + final List modulesToCreate = swModules.stream().map(JpaSoftwareModuleCreate.class::cast) + .map(JpaSoftwareModuleCreate::build).toList(); - final JpaSoftwareModule module = softwareModuleRepository.findById(update.getId()) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, update.getId())); + final List createdModules = Collections + .unmodifiableList(softwareModuleRepository.saveAll(AccessController.Operation.CREATE, modulesToCreate)); - update.getDescription().ifPresent(module::setDescription); - update.getVendor().ifPresent(module::setVendor); - - // lock/unlock ONLY if locked flag is present! - if (Boolean.TRUE.equals(update.locked())) { - module.lock(); - } else if (Boolean.FALSE.equals(update.locked())) { - module.unlock(); + if (createdModules.stream().anyMatch(SoftwareModule::isEncrypted)) { + entityManager.flush(); + createdModules.stream().filter(SoftwareModule::isEncrypted).map(SoftwareModule::getId) + .forEach(encryptedModuleId -> ArtifactEncryptionService.getInstance() + .addSoftwareModuleEncryptionSecrets(encryptedModuleId)); } - - return softwareModuleRepository.save(module); + return createdModules; } @Override @@ -173,61 +154,36 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection swModules) { - final List modulesToCreate = swModules.stream().map(JpaSoftwareModuleCreate.class::cast) - .map(JpaSoftwareModuleCreate::build).toList(); + public SoftwareModule update(final SoftwareModuleUpdate u) { + final GenericSoftwareModuleUpdate update = (GenericSoftwareModuleUpdate) u; - final List createdModules = Collections - .unmodifiableList(softwareModuleRepository.saveAll(AccessController.Operation.CREATE, modulesToCreate)); + final JpaSoftwareModule module = softwareModuleRepository.findById(update.getId()) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, update.getId())); - if (createdModules.stream().anyMatch(SoftwareModule::isEncrypted)) { - entityManager.flush(); - createdModules.stream().filter(SoftwareModule::isEncrypted).map(SoftwareModule::getId) - .forEach(encryptedModuleId -> ArtifactEncryptionService.getInstance() - .addSoftwareModuleEncryptionSecrets(encryptedModuleId)); + update.getDescription().ifPresent(module::setDescription); + update.getVendor().ifPresent(module::setVendor); + + // lock/unlock ONLY if locked flag is present! + if (Boolean.TRUE.equals(update.locked())) { + module.lock(); + } else if (Boolean.FALSE.equals(update.locked())) { + module.unlock(); } - return createdModules; + + return softwareModuleRepository.save(module); } @Override - public Slice findByType(final Pageable pageable, final long typeId) { - assertSoftwareModuleTypeExists(typeId); - - return JpaManagementHelper.findAllWithoutCountBySpec( - softwareModuleRepository, - pageable, - List.of( - SoftwareModuleSpecification.equalType(typeId), - SoftwareModuleSpecification.isNotDeleted())); + public long count() { + return softwareModuleRepository.count(SoftwareModuleSpecification.isNotDeleted()); } @Override - public Optional get(final long id) { - return softwareModuleRepository.findById(id).map(SoftwareModule.class::cast); - } - - @Override - public Optional getByNameAndVersionAndType(final String name, final String version, - final long typeId) { - assertSoftwareModuleTypeExists(typeId); - - // TODO AC - Access is restricted. This could have problem with UI when access control is enabled. - // Vaadin UI use this for validation. May need to be called via elevated access - return JpaManagementHelper - .findOneBySpec(softwareModuleRepository, List.of( - SoftwareModuleSpecification.likeNameAndVersion(name, version), - SoftwareModuleSpecification.equalType(typeId), - SoftwareModuleSpecification.fetchType())) - .map(SoftwareModule.class::cast); - } - - private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) { - softwareModuleRepository.getAccessController().ifPresent(accessController -> - accessController.assertOperationAllowed(AccessController.Operation.DELETE, swModule)); - for (final Artifact localArtifact : swModule.getArtifacts()) { - ((JpaArtifactManagement)artifactManagement) - .clearArtifactBinary(localArtifact.getSha1Hash()); - } + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void delete(final long id) { + delete(List.of(id)); } @Override @@ -279,6 +235,21 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { } } + @Override + public List get(final Collection ids) { + return Collections.unmodifiableList(softwareModuleRepository.findAllById(ids)); + } + + @Override + public boolean exists(final long id) { + return softwareModuleRepository.existsById(id); + } + + @Override + public Optional get(final long id) { + return softwareModuleRepository.findById(id).map(SoftwareModule.class::cast); + } + @Override public Slice findAll(final Pageable pageable) { return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, List.of( @@ -286,11 +257,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { SoftwareModuleSpecification.fetchType())); } - @Override - public long count() { - return softwareModuleRepository.count(SoftwareModuleSpecification.isNotDeleted()); - } - @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, pageable, List.of( @@ -299,70 +265,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { SoftwareModuleSpecification.isNotDeleted())); } - @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(softwareModuleRepository.findAllById(ids)); - } - - @Override - public Slice findByTextAndType(final Pageable pageable, final String searchText, - final Long typeId) { - final List> specList = new ArrayList<>(3); - specList.add(SoftwareModuleSpecification.isNotDeleted()); - - if (!ObjectUtils.isEmpty(searchText)) { - specList.add(buildSmSearchQuerySpec(searchText)); - } - - if (null != typeId) { - assertSoftwareModuleTypeExists(typeId); - specList.add(SoftwareModuleSpecification.equalType(typeId)); - } - - specList.add(SoftwareModuleSpecification.fetchType()); - - return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList); - } - - private Specification buildSmSearchQuerySpec(final String searchText) { - final String[] smFilterNameAndVersionEntries = JpaManagementHelper - .getFilterNameAndVersionEntries(searchText.trim()); - return SoftwareModuleSpecification.likeNameAndVersion(smFilterNameAndVersionEntries[0], - smFilterNameAndVersionEntries[1]); - } - - @Override - public Page findByAssignedTo(final Pageable pageable, final long distributionSetId) { - assertDistributionSetExists(distributionSetId); - - return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, pageable, - Collections.singletonList(SoftwareModuleSpecification.byAssignedToDs(distributionSetId))); - } - - @Override - public long countByAssignedTo(final long distributionSetId) { - assertDistributionSetExists(distributionSetId); - - return softwareModuleRepository.count(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleMetadata createMetaData(final SoftwareModuleMetadataCreate c) { - final JpaSoftwareModuleMetadataCreate create = (JpaSoftwareModuleMetadataCreate) c; - final Long id = create.getSoftwareModuleId(); - - assertSoftwareModuleExists(id); - assertMetaDataQuota(id, 1); - - // touch to update revision and last modified timestamp - JpaManagementHelper.touch(entityManager, softwareModuleRepository, (JpaSoftwareModule) get(id) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); - return saveMetadata(create); - } - @Override @Transactional @Retryable(include = { @@ -400,56 +302,21 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { return Collections.emptyList(); } - private static Stream createJpaMetadataCreateStream( - final Collection create) { - return create.stream().map(JpaSoftwareModuleMetadataCreate.class::cast); - } - - private SoftwareModuleMetadata saveMetadata(final JpaSoftwareModuleMetadataCreate create) { - assertSoftwareModuleMetadataDoesNotExist(create.getSoftwareModuleId(), create); - return softwareModuleMetadataRepository.save(create.build()); - } - - private void assertSoftwareModuleMetadataDoesNotExist(final Long id, - final JpaSoftwareModuleMetadataCreate md) { - if (softwareModuleMetadataRepository.existsById(new SwMetadataCompositeKey(id, md.getKey()))) { - throw new EntityAlreadyExistsException("Metadata entry with key '" + md.getKey() + "' already exists!"); - } - } - - /** - * Asserts the meta data quota for the software module with the given ID. - * - * @param id - * The software module ID. - * @param requested - * Number of meta data entries to be created. - */ - private void assertMetaDataQuota(final Long id, final int requested) { - final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerSoftwareModule(); - QuotaHelper.assertAssignmentQuota(id, requested, maxMetaData, SoftwareModuleMetadata.class, - SoftwareModule.class, softwareModuleMetadataRepository::countBySoftwareModuleId); - } - @Override @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleMetadata updateMetaData(final SoftwareModuleMetadataUpdate u) { - final GenericSoftwareModuleMetadataUpdate update = (GenericSoftwareModuleMetadataUpdate) u; + public SoftwareModuleMetadata createMetaData(final SoftwareModuleMetadataCreate c) { + final JpaSoftwareModuleMetadataCreate create = (JpaSoftwareModuleMetadataCreate) c; + final Long id = create.getSoftwareModuleId(); - // check if exists otherwise throw entity not found exception - final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId( - update.getSoftwareModuleId(), update.getKey()) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, - update.getSoftwareModuleId(), update.getKey())); + assertSoftwareModuleExists(id); + assertMetaDataQuota(id, 1); - update.getValue().ifPresent(metadata::setValue); - update.isTargetVisible().ifPresent(metadata::setTargetVisible); - - JpaManagementHelper.touch(entityManager, softwareModuleRepository, - (JpaSoftwareModule) metadata.getSoftwareModule()); - return softwareModuleMetadataRepository.save(metadata); + // touch to update revision and last modified timestamp + JpaManagementHelper.touch(entityManager, softwareModuleRepository, (JpaSoftwareModule) get(id) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); + return saveMetadata(create); } @Override @@ -466,14 +333,61 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { } @Override - public Page findMetaDataByRsql(final Pageable pageable, final long id, - final String rsqlParam) { + public Page findByAssignedTo(final Pageable pageable, final long distributionSetId) { + assertDistributionSetExists(distributionSetId); + + return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, pageable, + Collections.singletonList(SoftwareModuleSpecification.byAssignedToDs(distributionSetId))); + } + + @Override + public long countByAssignedTo(final long distributionSetId) { + assertDistributionSetExists(distributionSetId); + + return softwareModuleRepository.count(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)); + } + + @Override + public Slice findByTextAndType(final Pageable pageable, final String searchText, + final Long typeId) { + final List> specList = new ArrayList<>(3); + specList.add(SoftwareModuleSpecification.isNotDeleted()); + + if (!ObjectUtils.isEmpty(searchText)) { + specList.add(buildSmSearchQuerySpec(searchText)); + } + + if (null != typeId) { + assertSoftwareModuleTypeExists(typeId); + specList.add(SoftwareModuleSpecification.equalType(typeId)); + } + + specList.add(SoftwareModuleSpecification.fetchType()); + + return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList); + } + + @Override + public Optional getByNameAndVersionAndType(final String name, final String version, + final long typeId) { + assertSoftwareModuleTypeExists(typeId); + + // TODO AC - Access is restricted. This could have problem with UI when access control is enabled. + // Vaadin UI use this for validation. May need to be called via elevated access + return JpaManagementHelper + .findOneBySpec(softwareModuleRepository, List.of( + SoftwareModuleSpecification.likeNameAndVersion(name, version), + SoftwareModuleSpecification.equalType(typeId), + SoftwareModuleSpecification.fetchType())) + .map(SoftwareModule.class::cast); + } + + @Override + public Optional getMetaDataBySoftwareModuleId(final long id, final String key) { assertSoftwareModuleExists(id); - final List> specList = Arrays - .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleMetadataFields.class, - virtualPropertyReplacer, database), metadataBySoftwareModuleIdSpec(id)); - return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, pageable, specList); + return softwareModuleMetadataRepository.findById(new SwMetadataCompositeKey(id, key)) + .map(SoftwareModuleMetadata.class::cast); } @Override @@ -492,11 +406,35 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { } @Override - public Optional getMetaDataBySoftwareModuleId(final long id, final String key) { + public Page findMetaDataBySoftwareModuleIdAndTargetVisible(final Pageable pageable, + final long id) { assertSoftwareModuleExists(id); - return softwareModuleMetadataRepository.findById(new SwMetadataCompositeKey(id, key)) - .map(SoftwareModuleMetadata.class::cast); + return JpaManagementHelper.convertPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( + PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT), id, true), pageable); + } + + @Override + public Page findMetaDataByRsql(final Pageable pageable, final long id, + final String rsqlParam) { + assertSoftwareModuleExists(id); + + final List> specList = Arrays + .asList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleMetadataFields.class, + virtualPropertyReplacer, database), metadataBySoftwareModuleIdSpec(id)); + return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, pageable, specList); + } + + @Override + public Slice findByType(final Pageable pageable, final long typeId) { + assertSoftwareModuleTypeExists(typeId); + + return JpaManagementHelper.findAllWithoutCountBySpec( + softwareModuleRepository, + pageable, + List.of( + SoftwareModuleSpecification.equalType(typeId), + SoftwareModuleSpecification.isNotDeleted())); } @Override @@ -531,22 +469,71 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long id) { - delete(List.of(id)); + public SoftwareModuleMetadata updateMetaData(final SoftwareModuleMetadataUpdate u) { + final GenericSoftwareModuleMetadataUpdate update = (GenericSoftwareModuleMetadataUpdate) u; + + // check if exists otherwise throw entity not found exception + final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId( + update.getSoftwareModuleId(), update.getKey()) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, + update.getSoftwareModuleId(), update.getKey())); + + update.getValue().ifPresent(metadata::setValue); + update.isTargetVisible().ifPresent(metadata::setTargetVisible); + + JpaManagementHelper.touch(entityManager, softwareModuleRepository, + (JpaSoftwareModule) metadata.getSoftwareModule()); + return softwareModuleMetadataRepository.save(metadata); } - @Override - public boolean exists(final long id) { - return softwareModuleRepository.existsById(id); + private static Stream createJpaMetadataCreateStream( + final Collection create) { + return create.stream().map(JpaSoftwareModuleMetadataCreate.class::cast); } - @Override - public Page findMetaDataBySoftwareModuleIdAndTargetVisible(final Pageable pageable, - final long id) { - assertSoftwareModuleExists(id); + private static Specification metadataBySoftwareModuleIdSpec(final long id) { + return (root, query, cb) -> cb + .equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), id); + } - return JpaManagementHelper.convertPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( - PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT), id, true), pageable); + private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) { + softwareModuleRepository.getAccessController().ifPresent(accessController -> + accessController.assertOperationAllowed(AccessController.Operation.DELETE, swModule)); + for (final Artifact localArtifact : swModule.getArtifacts()) { + ((JpaArtifactManagement) artifactManagement) + .clearArtifactBinary(localArtifact.getSha1Hash()); + } + } + + private Specification buildSmSearchQuerySpec(final String searchText) { + final String[] smFilterNameAndVersionEntries = JpaManagementHelper + .getFilterNameAndVersionEntries(searchText.trim()); + return SoftwareModuleSpecification.likeNameAndVersion(smFilterNameAndVersionEntries[0], + smFilterNameAndVersionEntries[1]); + } + + private SoftwareModuleMetadata saveMetadata(final JpaSoftwareModuleMetadataCreate create) { + assertSoftwareModuleMetadataDoesNotExist(create.getSoftwareModuleId(), create); + return softwareModuleMetadataRepository.save(create.build()); + } + + private void assertSoftwareModuleMetadataDoesNotExist(final Long id, + final JpaSoftwareModuleMetadataCreate md) { + if (softwareModuleMetadataRepository.existsById(new SwMetadataCompositeKey(id, md.getKey()))) { + throw new EntityAlreadyExistsException("Metadata entry with key '" + md.getKey() + "' already exists!"); + } + } + + /** + * Asserts the meta data quota for the software module with the given ID. + * + * @param id The software module ID. + * @param requested Number of meta data entries to be created. + */ + private void assertMetaDataQuota(final Long id, final int requested) { + final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerSoftwareModule(); + QuotaHelper.assertAssignmentQuota(id, requested, maxMetaData, SoftwareModuleMetadata.class, + SoftwareModule.class, softwareModuleMetadataRepository::countBySoftwareModuleId); } private void assertSoftwareModuleExists(final Long id) { @@ -566,9 +553,4 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { throw new EntityNotFoundException(DistributionSet.class, distributionSetId); } } - - private static Specification metadataBySoftwareModuleIdSpec(final long id) { - return (root, query, cb) -> cb - .equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), id); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java index 02255cd37..b3822b6d0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java @@ -44,7 +44,6 @@ import org.springframework.validation.annotation.Validated; /** * JPA implementation of {@link SoftwareModuleTypeManagement}. - * */ @Transactional(readOnly = true) @Validated @@ -68,6 +67,37 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage this.database = database; } + @Override + public Optional getByKey(final String key) { + return softwareModuleTypeRepository.findByKey(key); + } + + @Override + public Optional getByName(final String name) { + return softwareModuleTypeRepository.findByName(name); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List create(final Collection c) { + final List creates = c.stream().map(JpaSoftwareModuleTypeCreate.class::cast) + .map(JpaSoftwareModuleTypeCreate::build).toList(); + return Collections.unmodifiableList( + softwareModuleTypeRepository.saveAll(AccessController.Operation.CREATE, creates)); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public SoftwareModuleType create(final SoftwareModuleTypeCreate c) { + final JpaSoftwareModuleTypeCreate create = (JpaSoftwareModuleTypeCreate) c; + + return softwareModuleTypeRepository.save(AccessController.Operation.CREATE, create.build()); + } + @Override @Transactional @Retryable(include = { @@ -84,46 +114,11 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage return softwareModuleTypeRepository.save(type); } - @Override - public Page findByRsql(final Pageable pageable, final String rsqlParam) { - return JpaManagementHelper.findAllWithCountBySpec(softwareModuleTypeRepository, pageable, - List.of( - RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleTypeFields.class, - virtualPropertyReplacer, database), - SoftwareModuleTypeSpecification.isNotDeleted())); - } - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleTypeRepository, pageable, - List.of(SoftwareModuleTypeSpecification.isNotDeleted())); - } - @Override public long count() { return softwareModuleTypeRepository.count(SoftwareModuleTypeSpecification.isNotDeleted()); } - @Override - public Optional getByKey(final String key) { - return softwareModuleTypeRepository.findByKey(key); - } - - @Override - public Optional getByName(final String name) { - return softwareModuleTypeRepository.findByName(name); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleType create(final SoftwareModuleTypeCreate c) { - final JpaSoftwareModuleTypeCreate create = (JpaSoftwareModuleTypeCreate) c; - - return softwareModuleTypeRepository.save(AccessController.Operation.CREATE, create.build()); - } - @Override @Transactional @Retryable(include = { @@ -135,17 +130,6 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage delete(toDelete); } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection c) { - final List creates = c.stream().map(JpaSoftwareModuleTypeCreate.class::cast) - .map(JpaSoftwareModuleTypeCreate::build).toList(); - return Collections.unmodifiableList( - softwareModuleTypeRepository.saveAll(AccessController.Operation.CREATE, creates)); - } - @Override @Transactional @Retryable(include = { @@ -161,14 +145,29 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage return Collections.unmodifiableList(softwareModuleTypeRepository.findAllById(ids)); } + @Override + public boolean exists(final long id) { + return softwareModuleTypeRepository.existsById(id); + } + @Override public Optional get(final long id) { return softwareModuleTypeRepository.findById(id).map(SoftwareModuleType.class::cast); } @Override - public boolean exists(final long id) { - return softwareModuleTypeRepository.existsById(id); + public Slice findAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleTypeRepository, pageable, + List.of(SoftwareModuleTypeSpecification.isNotDeleted())); + } + + @Override + public Page findByRsql(final Pageable pageable, final String rsqlParam) { + return JpaManagementHelper.findAllWithCountBySpec(softwareModuleTypeRepository, pageable, + List.of( + RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleTypeFields.class, + virtualPropertyReplacer, database), + SoftwareModuleTypeSpecification.isNotDeleted())); } private void delete(JpaSoftwareModuleType toDelete) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java index 768ddf77d..6897ed6e9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java @@ -74,81 +74,57 @@ import org.springframework.validation.annotation.Validated; public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, SystemManagement { private static final int MAX_TENANTS_QUERY = 1000; - + private final String countArtifactQuery; + private final String countSoftwareModulesQuery; @Autowired private EntityManager entityManager; - @Autowired private TargetRepository targetRepository; - @Autowired private TargetFilterQueryRepository targetFilterQueryRepository; - @Autowired private DistributionSetRepository distributionSetRepository; - @Autowired private SoftwareModuleRepository softwareModuleRepository; - @Autowired private TenantMetaDataRepository tenantMetaDataRepository; - @Autowired private DistributionSetTypeRepository distributionSetTypeRepository; - @Autowired private SoftwareModuleTypeRepository softwareModuleTypeRepository; - @Autowired private TargetTagRepository targetTagRepository; - @Autowired private TargetTypeRepository targetTypeRepository; - @Autowired private DistributionSetTagRepository distributionSetTagRepository; - @Autowired private TenantConfigurationRepository tenantConfigurationRepository; - @Autowired private RolloutRepository rolloutRepository; - @Autowired private TenantAware tenantAware; - @Autowired private TenantStatsManagement systemStatsManagement; - @Autowired private TenancyCacheManager cacheManager; - @Autowired private SystemManagementCacheKeyGenerator currentTenantCacheKeyGenerator; - @Autowired private SystemSecurityContext systemSecurityContext; - @Autowired private PlatformTransactionManager txManager; - @Autowired private RolloutStatusCache rolloutStatusCache; - @Autowired private ArtifactRepository artifactRepository; - @Autowired private RepositoryProperties repositoryProperties; - private final String countArtifactQuery; - private final String countSoftwareModulesQuery; - /** * Constructor. - * - * @param properties - * properties to get the underlying database + * + * @param properties properties to get the underlying database */ public JpaSystemManagement(final JpaProperties properties) { @@ -159,48 +135,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst + isDeleted; } - @Override - public SystemUsageReport getSystemUsageStatistics() { - - final Number count = (Number) entityManager.createNativeQuery(countSoftwareModulesQuery).getSingleResult(); - - long sumOfArtifacts = 0; - if (count != null) { - sumOfArtifacts = count.longValue(); - } - - // we use native queries to punch through the tenant boundaries. This - // has to be used with care! - final long targets = ((Number) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_target") - .getSingleResult()).longValue(); - - final long artifacts = ((Number) entityManager.createNativeQuery(countArtifactQuery).getSingleResult()) - .longValue(); - - final long actions = ((Number) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_action") - .getSingleResult()).longValue(); - - return new SystemUsageReportWithTenants(targets, artifacts, actions, sumOfArtifacts, - tenantMetaDataRepository.count()); - } - - private static boolean isPostgreSql(final JpaProperties properties) { - return Database.POSTGRESQL == properties.getDatabase(); - } - - @Override - public SystemUsageReportWithTenants getSystemUsageStatisticsWithTenants() { - final SystemUsageReportWithTenants result = (SystemUsageReportWithTenants) getSystemUsageStatistics(); - - usageStatsPerTenant(result); - - return result; - } - - private void usageStatsPerTenant(final SystemUsageReportWithTenants report) { - forEachTenant(tenant -> report.addTenantData(systemStatsManagement.getStatsOfTenant())); - } - @Override @Transactional(propagation = Propagation.SUPPORTS) public KeyGenerator currentTenantKeyGenerator() { @@ -208,18 +142,13 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst } @Override - public TenantMetaData createTenantMetadata(final String tenant) { - final TenantMetaData result = tenantMetaDataRepository.findByTenantIgnoreCase(tenant); - // Create if it does not exist - if (result == null) { - return createTenantMetadata0(tenant); - } - return result; - } - - @Override - public Page findTenants(final Pageable pageable) { - return tenantMetaDataRepository.findTenants(pageable); + @Cacheable(value = "currentTenant", keyGenerator = "currentTenantKeyGenerator", cacheManager = "directCacheManager", unless = "#result == null") + public String currentTenant() { + return currentTenantCacheKeyGenerator.getTenantInCreation().orElseGet(() -> { + final TenantMetaData findByTenant = tenantMetaDataRepository + .findByTenantIgnoreCase(tenantAware.getCurrentTenant()); + return findByTenant != null ? findByTenant.getTenant() : null; + }); } @Override @@ -249,6 +178,70 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst }); } + @Override + public Page findTenants(final Pageable pageable) { + return tenantMetaDataRepository.findTenants(pageable); + } + + @Override + @Transactional(propagation = Propagation.NOT_SUPPORTED) + // Exception squid:S2229 - calling findTenants without transaction is + // intended in this case + @SuppressWarnings("squid:S2229") + public void forEachTenant(final Consumer consumer) { + Page tenants; + Pageable query = PageRequest.of(0, MAX_TENANTS_QUERY); + do { + tenants = findTenants(query); + tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> { + try { + consumer.accept(tenant); + } catch (final RuntimeException ex) { + log.debug("Exception on forEachTenant execution for tenant {}. Continue with next tenant.", + tenant, ex); + log.error("Exception on forEachTenant execution for tenant {} with error message [{}]. " + + "Continue with next tenant.", tenant, ex.getMessage()); + } + return null; + })); + } while ((query = tenants.nextPageable()) != Pageable.unpaged()); + + } + + @Override + public SystemUsageReportWithTenants getSystemUsageStatisticsWithTenants() { + final SystemUsageReportWithTenants result = (SystemUsageReportWithTenants) getSystemUsageStatistics(); + + usageStatsPerTenant(result); + + return result; + } + + @Override + public SystemUsageReport getSystemUsageStatistics() { + + final Number count = (Number) entityManager.createNativeQuery(countSoftwareModulesQuery).getSingleResult(); + + long sumOfArtifacts = 0; + if (count != null) { + sumOfArtifacts = count.longValue(); + } + + // we use native queries to punch through the tenant boundaries. This + // has to be used with care! + final long targets = ((Number) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_target") + .getSingleResult()).longValue(); + + final long artifacts = ((Number) entityManager.createNativeQuery(countArtifactQuery).getSingleResult()) + .longValue(); + + final long actions = ((Number) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_action") + .getSingleResult()).longValue(); + + return new SystemUsageReportWithTenants(targets, artifacts, actions, sumOfArtifacts, + tenantMetaDataRepository.count()); + } + @Override public TenantMetaData getTenantMetadata() { final String tenant = tenantAware.getCurrentTenant(); @@ -270,13 +263,13 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst } @Override - @Cacheable(value = "currentTenant", keyGenerator = "currentTenantKeyGenerator", cacheManager = "directCacheManager", unless = "#result == null") - public String currentTenant() { - return currentTenantCacheKeyGenerator.getTenantInCreation().orElseGet(() -> { - final TenantMetaData findByTenant = tenantMetaDataRepository - .findByTenantIgnoreCase(tenantAware.getCurrentTenant()); - return findByTenant != null ? findByTenant.getTenant() : null; - }); + public TenantMetaData createTenantMetadata(final String tenant) { + final TenantMetaData result = tenantMetaDataRepository.findByTenantIgnoreCase(tenant); + // Create if it does not exist + if (result == null) { + return createTenantMetadata0(tenant); + } + return result; } @Override @@ -292,6 +285,20 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst return tenantMetaDataRepository.save(data); } + @Override + public TenantMetaData getTenantMetadata(final long tenantId) { + return tenantMetaDataRepository.findById(tenantId) + .orElseThrow(() -> new EntityNotFoundException(TenantMetaData.class, tenantId)); + } + + private static boolean isPostgreSql(final JpaProperties properties) { + return Database.POSTGRESQL == properties.getDatabase(); + } + + private void usageStatsPerTenant(final SystemUsageReportWithTenants report) { + forEachTenant(tenant -> report.addTenantData(systemStatsManagement.getStatsOfTenant())); + } + private DistributionSetType createStandardSoftwareDataSetup() { final SoftwareModuleType app = softwareModuleTypeRepository .save(new JpaSoftwareModuleType(org.eclipse.hawkbit.repository.Constants.SMT_DEFAULT_APP_KEY, @@ -318,38 +325,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst .save(new JpaDistributionSetType(org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_WITH_APPS_KEY, org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_WITH_APPS_NAME, "Default type with Firmware/OS and optional app(s).").addMandatoryModuleType(os) - .addOptionalModuleType(app)); - } - - @Override - public TenantMetaData getTenantMetadata(final long tenantId) { - return tenantMetaDataRepository.findById(tenantId) - .orElseThrow(() -> new EntityNotFoundException(TenantMetaData.class, tenantId)); - } - - @Override - @Transactional(propagation = Propagation.NOT_SUPPORTED) - // Exception squid:S2229 - calling findTenants without transaction is - // intended in this case - @SuppressWarnings("squid:S2229") - public void forEachTenant(final Consumer consumer) { - Page tenants; - Pageable query = PageRequest.of(0, MAX_TENANTS_QUERY); - do { - tenants = findTenants(query); - tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> { - try { - consumer.accept(tenant); - } catch (final RuntimeException ex) { - log.debug("Exception on forEachTenant execution for tenant {}. Continue with next tenant.", - tenant, ex); - log.error("Exception on forEachTenant execution for tenant {} with error message [{}]. " - + "Continue with next tenant.", tenant, ex.getMessage()); - } - return null; - })); - } while ((query = tenants.nextPageable()) != Pageable.unpaged()); - + .addOptionalModuleType(app)); } private TenantMetaData createTenantMetadata0(final String tenant) { @@ -371,8 +347,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst * {@link MultiTenantJpaTransactionManager} is called again and set the * tenant for this transaction. * - * @param tenant - * the tenant to be created + * @param tenant the tenant to be created * @return the initial created {@link TenantMetaData} */ private TenantMetaData createInitialTenantMetaData(final String tenant) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java index 164eb11a1..24d83db99 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java @@ -16,7 +16,9 @@ import java.util.Optional; import jakarta.validation.constraints.NotNull; +import cz.jirutka.rsql.parser.RSQLParserException; import lombok.extern.slf4j.Slf4j; +import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryProperties; @@ -25,7 +27,6 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryFields; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.builder.GenericTargetFilterQueryUpdate; import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate; @@ -64,8 +65,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; -import cz.jirutka.rsql.parser.RSQLParserException; - /** * JPA implementation of {@link TargetFilterQueryManagement}. */ @@ -140,6 +139,17 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme targetFilterQueryRepository.deleteById(targetFilterQueryId); } + @Override + public boolean verifyTargetFilterQuerySyntax(final String query) { + try { + RSQLUtility.validateRsqlFor(query, TargetFields.class); + return true; + } catch (final RSQLParserException | RSQLParameterUnsupportedFieldException e) { + log.debug("The RSQL query '" + query + "' is invalid.", e); + return false; + } + } + @Override public Slice findAll(final Pageable pageable) { return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, null); @@ -179,7 +189,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme public Page findByRsql(final Pageable pageable, final String rsqlFilter) { final List> specList = !ObjectUtils.isEmpty(rsqlFilter) ? Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter, - TargetFilterQueryFields.class, virtualPropertyReplacer, database)) + TargetFilterQueryFields.class, virtualPropertyReplacer, database)) : Collections.emptyList(); return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, pageable, specList); @@ -225,13 +235,13 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme } @Override - public Optional getByName(final String targetFilterQueryName) { - return targetFilterQueryRepository.findByName(targetFilterQueryName); + public Optional get(final long targetFilterQueryId) { + return targetFilterQueryRepository.findById(targetFilterQueryId).map(TargetFilterQuery.class::cast); } @Override - public Optional get(final long targetFilterQueryId) { - return targetFilterQueryRepository.findById(targetFilterQueryId).map(TargetFilterQuery.class::cast); + public Optional getByName(final String targetFilterQueryName) { + return targetFilterQueryRepository.findByName(targetFilterQueryName); } @Override @@ -279,7 +289,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement .getValidAndComplete(update.getDsId()); - if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) { + if (((JpaDistributionSetManagement) distributionSetManagement).isImplicitLockApplicable(distributionSet)) { distributionSetManagement.lock(distributionSet.getId()); } @@ -298,9 +308,11 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme return targetFilterQueryRepository.save(targetFilterQuery); } - private boolean isConfirmationFlowEnabled() { - return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement) - .isConfirmationFlowEnabled(); + @Override + @Transactional + public void cancelAutoAssignmentForDistributionSet(final long distributionSetId) { + targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext(distributionSetId); + log.debug("Auto assignments for distribution sets {} deactivated", distributionSetId); } private static ActionType sanitizeAutoAssignActionType(final ActionType actionType) { @@ -315,32 +327,19 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme return actionType; } + private boolean isConfirmationFlowEnabled() { + return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement) + .isConfirmationFlowEnabled(); + } + private JpaTargetFilterQuery findTargetFilterQueryOrThrowExceptionIfNotFound(final Long queryId) { return targetFilterQueryRepository.findById(queryId) .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, queryId)); } - @Override - public boolean verifyTargetFilterQuerySyntax(final String query) { - try { - RSQLUtility.validateRsqlFor(query, TargetFields.class); - return true; - } catch (final RSQLParserException | RSQLParameterUnsupportedFieldException e) { - log.debug("The RSQL query '" + query + "' is invalid.", e); - return false; - } - } - private void assertMaxTargetsQuota(final String query, final String filterName, final long dsId) { QuotaHelper.assertAssignmentQuota(filterName, targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(dsId, query), quotaManagement.getMaxTargetsPerAutoAssignment(), Target.class, TargetFilterQuery.class, null); } - - @Override - @Transactional - public void cancelAutoAssignmentForDistributionSet(final long distributionSetId) { - targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext(distributionSetId); - log.debug("Auto assignments for distribution sets {} deactivated", distributionSetId); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java index 25647f01f..8233203aa 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.JpaManagementHelper.combineWithAnd; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -96,11 +98,8 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; -import static org.eclipse.hawkbit.repository.jpa.JpaManagementHelper.combineWithAnd; - /** * JPA implementation of {@link TargetManagement}. - * */ @Transactional(readOnly = true) @Validated @@ -157,23 +156,77 @@ public class JpaTargetManagement implements TargetManagement { } @Override - public Optional getByControllerID(final String controllerId) { - return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)).map(Target.class::cast); - } + public long countByAssignedDistributionSet(final long distributionSetId) { + final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId)); - private JpaTarget getByControllerIdAndThrowIfNotFound(final String controllerId) { - return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) - .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); - } - - private JpaTargetType getTargetTypeByIdAndThrowIfNotFound(final long id) { - return targetTypeRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(TargetType.class, id)); + return targetRepository.count(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())); } @Override - public List getByControllerID(final Collection controllerIDs) { - return Collections.unmodifiableList( - targetRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs))); + public long countByFilters(final FilterParams filterParams) { + final List> specList = buildSpecificationList(filterParams); + return JpaManagementHelper.countBySpec(targetRepository, specList); + } + + @Override + public long countByInstalledDistributionSet(final long distributionSetId) { + final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId)); + + return targetRepository.count(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())); + } + + @Override + public boolean existsByInstalledOrAssignedDistributionSet(final long distributionSetId) { + final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId)); + + return targetRepository + .exists(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId())); + } + + @Override + public long countByRsql(final String targetFilterQuery) { + return JpaManagementHelper.countBySpec(targetRepository, List.of(RSQLUtility + .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database))); + } + + @Override + public long countByRsqlAndUpdatable(String targetFilterQuery) { + final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery, + TargetFields.class, virtualPropertyReplacer, database)); + return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList)); + } + + @Override + public long countByRsqlAndCompatible(final String targetFilterQuery, final Long distributionSetIdTypeId) { + final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery, + TargetFields.class, virtualPropertyReplacer, database), + TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId)); + + return JpaManagementHelper.countBySpec(targetRepository, specList); + } + + @Override + public long countByRsqlAndCompatibleAndUpdatable(String targetFilterQuery, Long distributionSetIdTypeId) { + final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery, + TargetFields.class, virtualPropertyReplacer, database), + TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId)); + return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList)); + } + + @Override + public long countByFailedInRollout(final String rolloutId, final Long dsTypeId) { + final List> specList = List + .of(TargetSpecifications.failedActionsForRollout(rolloutId)); + + return JpaManagementHelper.countBySpec(targetRepository, specList); + } + + @Override + public long countByTargetFilterQuery(final long targetFilterQueryId) { + final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) + .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); + + return countByRsql(targetFilterQuery.getQuery()); } @Override @@ -182,175 +235,22 @@ public class JpaTargetManagement implements TargetManagement { } @Override - public Set getTagsByControllerId(@NotEmpty String controllerId) { - // the method has PreAuthorized by itself - return getByControllerID(controllerId).map(JpaTarget.class::cast).map(JpaTarget::getTags) - .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Target create(final TargetCreate c) { + final JpaTargetCreate create = (JpaTargetCreate) c; + return targetRepository.save(AccessController.Operation.CREATE, create.build()); } @Override @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List createMetaData(final String controllerId, final Collection md) { - final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId); - - md.forEach(meta -> checkAndThrowIfTargetMetadataAlreadyExists( - new TargetMetadataCompositeKey(target.getId(), meta.getKey()))); - - assertMetaDataQuota(target.getId(), md.size()); - - final JpaTarget updatedTarget = JpaManagementHelper.touch(entityManager, targetRepository, target); - - final List createdMetadata = md.stream() - .map(meta -> targetMetadataRepository - .save(new JpaTargetMetadata(meta.getKey(), meta.getValue(), updatedTarget))) - .collect(Collectors.toUnmodifiableList()); - - // TargetUpdatedEvent is not sent within the touch() method due to the - // "lastModifiedAt" field being ignored in JpaTarget - eventPublisherHolder.getEventPublisher() - .publishEvent(new TargetUpdatedEvent(updatedTarget, eventPublisherHolder.getApplicationId())); - - return createdMetadata; - } - - private void checkAndThrowIfTargetMetadataAlreadyExists(final TargetMetadataCompositeKey metadataId) { - if (targetMetadataRepository.existsById(metadataId)) { - throw new EntityAlreadyExistsException( - "Metadata entry with key '" + metadataId.getKey() + "' already exists"); - } - } - - private void assertMetaDataQuota(final Long targetId, final int requested) { - QuotaHelper.assertAssignmentQuota(targetId, requested, quotaManagement.getMaxMetaDataEntriesPerTarget(), - TargetMetadata.class, Target.class, targetMetadataRepository::countByTargetId); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public TargetMetadata updateMetadata(final String controllerId, final MetaData md) { - - // check if exists otherwise throw entity not found exception - final JpaTargetMetadata updatedMetadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, - md.getKey()) - .orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, controllerId, md.getKey())); - updatedMetadata.setValue(md.getValue()); - // touch it to update the lock revision because we are modifying the - // target indirectly - final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository, - getByControllerIdAndThrowIfNotFound(controllerId)); - - final JpaTargetMetadata metadata = targetMetadataRepository.save(updatedMetadata); - // target update event is set to ignore "lastModifiedAt" field, so it is - // not send automatically within the touch() method - eventPublisherHolder.getEventPublisher() - .publishEvent(new TargetUpdatedEvent(target, eventPublisherHolder.getApplicationId())); - return metadata; - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void deleteMetaData(final String controllerId, final String key) { - final JpaTargetMetadata metadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, key) - .orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, controllerId, key)); - - final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository, - getByControllerIdAndThrowIfNotFound(controllerId)); - - targetRepository.getAccessController() - .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target)); - - targetMetadataRepository.deleteById(metadata.getId()); - // target update event is set to ignore "lastModifiedAt" field, so it is - // not send automatically within the touch() method - eventPublisherHolder.getEventPublisher() - .publishEvent(new TargetUpdatedEvent(target, eventPublisherHolder.getApplicationId())); - } - - @Override - public Page findMetaDataByControllerId(final Pageable pageable, final String controllerId) { - final Long id = getByControllerIdAndThrowIfNotFound(controllerId).getId(); - - return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable, - Collections.singletonList(metadataByTargetIdSpec(id))); - } - - private Specification metadataByTargetIdSpec(final Long targetId) { - return (root, query, cb) -> cb.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId); - } - - @Override - public long countMetaDataByControllerId(@NotEmpty final String controllerId) { - final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); - - return JpaManagementHelper.countBySpec(targetMetadataRepository, - Collections.singletonList(metadataByTargetIdSpec(targetId))); - } - - @Override - public Page findMetaDataByControllerIdAndRsql(final Pageable pageable, final String controllerId, - final String rsqlParam) { - final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); - - final List> specList = Arrays.asList(RSQLUtility - .buildRsqlSpecification(rsqlParam, TargetMetadataFields.class, virtualPropertyReplacer, database), - metadataByTargetIdSpec(targetId)); - - return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable, specList); - } - - @Override - public Optional getMetaDataByControllerId(final String controllerId, final String key) { - final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); - - return targetMetadataRepository.findById(new TargetMetadataCompositeKey(targetId, key)).map(t -> t); - } - - @Override - public Slice findAll(final Pageable pageable) { - return targetRepository.findAllWithoutCount(pageable).map(Target.class::cast); - } - - @Override - public Slice findByTargetFilterQuery(final Pageable pageable, final long targetFilterQueryId) { - final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) - .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); - - return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, - List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), TargetFields.class, - virtualPropertyReplacer, database))); - } - - @Override - public Slice findByRsql(final Pageable pageable, final String targetFilterQuery) { - return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, List.of(RSQLUtility - .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database))); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Target update(final TargetUpdate u) { - final JpaTargetUpdate update = (JpaTargetUpdate) u; - - final JpaTarget target = getByControllerIdAndThrowIfNotFound(update.getControllerId()); - - update.getName().ifPresent(target::setName); - update.getDescription().ifPresent(target::setDescription); - update.getAddress().ifPresent(target::setAddress); - update.getSecurityToken().ifPresent(target::setSecurityToken); - if (update.getTargetTypeId() != null) { - final TargetType targetType = getTargetTypeByIdAndThrowIfNotFound(update.getTargetTypeId()); - target.setTargetType(targetType); - } - - return targetRepository.save(target); + public List create(final Collection targets) { + final List targetList = targets.stream().map(JpaTargetCreate.class::cast).map(JpaTargetCreate::build) + .toList(); + return Collections.unmodifiableList(targetRepository.saveAll(AccessController.Operation.CREATE, targetList)); } @Override @@ -375,281 +275,6 @@ public class JpaTargetManagement implements TargetManagement { targetRepository.delete(getByControllerIdAndThrowIfNotFound(controllerId)); } - @Override - public Page findByAssignedDistributionSet(final Pageable pageReq, final long distributionSetId) { - final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); - - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, - List.of(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()))); - } - - @Override - public Page findByAssignedDistributionSetAndRsql(final Pageable pageReq, final long distributionSetId, - final String rsqlParam) { - final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); - - final List> specList = List.of( - RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), - TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())); - - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, specList); - } - - @Override - public Page findByInstalledDistributionSet(final Pageable pageReq, final long distributionSetId) { - final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); - - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, - List.of(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()))); - } - - @Override - public Page findByInstalledDistributionSetAndRsql(final Pageable pageable, final long distributionSetId, - final String rsqlParam) { - final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); - - final List> specList = List.of( - RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), - TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())); - - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList); - } - - @Override - public Page findByUpdateStatus(final Pageable pageable, final TargetUpdateStatus status) { - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, - List.of(TargetSpecifications.hasTargetUpdateStatus(status))); - } - - @Override - public Slice findByFilters(final Pageable pageable, final FilterParams filterParams) { - final List> specList = buildSpecificationList(filterParams); - return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, specList); - } - - @Override - public long countByFilters(final FilterParams filterParams) { - final List> specList = buildSpecificationList(filterParams); - return JpaManagementHelper.countBySpec(targetRepository, specList); - } - - private List> buildSpecificationList(final FilterParams filterParams) { - final List> specList = new ArrayList<>(); - if ((filterParams.getFilterByStatus() != null) && !filterParams.getFilterByStatus().isEmpty()) { - specList.add(TargetSpecifications.hasTargetUpdateStatus(filterParams.getFilterByStatus())); - } - if (filterParams.getOverdueState() != null && filterParams.getOverdueState()) { - specList.add(TargetSpecifications.isOverdue(TimestampCalculator.calculateOverdueTimestamp())); - } - if (filterParams.getFilterByDistributionId() != null) { - final DistributionSet validDistSet = distributionSetManagement - .getOrElseThrowException(filterParams.getFilterByDistributionId()); - - specList.add(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId())); - } - if (!ObjectUtils.isEmpty(filterParams.getFilterBySearchText())) { - specList.add(TargetSpecifications.likeControllerIdOrName(filterParams.getFilterBySearchText())); - } - if (hasTagsFilterActive(filterParams)) { - specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(), - filterParams.getSelectTargetWithNoTag())); - } - - if (hasTypesFilterActive(filterParams)) { - specList.add(TargetSpecifications.hasTargetType(filterParams.getFilterByTargetType())); - } else if (hasNoTypeFilterActive(filterParams)) { - specList.add(TargetSpecifications.hasNoTargetType()); - } - - return specList; - } - - private static boolean hasTagsFilterActive(final FilterParams filterParams) { - final boolean isNoTagActive = Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTag()); - final boolean isAtLeastOneTagActive = filterParams.getFilterByTagNames() != null - && filterParams.getFilterByTagNames().length > 0; - - return isNoTagActive || isAtLeastOneTagActive; - } - - private static boolean hasTypesFilterActive(final FilterParams filterParams) { - return filterParams.getFilterByTargetType() != null; - } - - private static boolean hasNoTypeFilterActive(final FilterParams filterParams) { - return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType()); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public TargetTypeAssignmentResult assignType(final Collection controllerIds, final Long typeId) { - final JpaTargetType type = targetTypeRepository.findById(typeId) - .orElseThrow(() -> new EntityNotFoundException(TargetType.class, typeId)); - - final List targetsWithSameType = findTargetsByInSpecification(controllerIds, - TargetSpecifications.hasTargetType(typeId)); - - final List targetsWithoutSameType = findTargetsByInSpecification(controllerIds, - TargetSpecifications.hasTargetTypeNot(typeId)); - - // set new target type to all targets without that type - targetsWithoutSameType.forEach(target -> target.setTargetType(type)); - - final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(), - targetRepository.saveAll(targetsWithoutSameType), Collections.emptyList(), type); - - // no reason to persist the type - entityManager.detach(type); - return result; - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public TargetTypeAssignmentResult unassignType(final Collection controllerIds) { - final List allTargets = findTargetsByInSpecification(controllerIds, null); - - if (allTargets.size() < controllerIds.size()) { - throw new EntityNotFoundException(Target.class, controllerIds, - allTargets.stream().map(Target::getControllerId).toList()); - } - - // set new target type to null for all targets - allTargets.forEach(target -> target.setTargetType(null)); - - return new TargetTypeAssignmentResult(0, Collections.emptyList(), targetRepository.saveAll(allTargets), null); - } - - private List findTargetsByInSpecification(final Collection controllerIds, - final Specification specification) { - return ListUtils.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream() - .map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification))) - .flatMap(List::stream).toList(); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List assignTag(final Collection controllerIds, final long targetTagId, final Consumer> notFoundHandler) { - return updateTag(controllerIds, targetTagId, notFoundHandler, (tag, target) -> { - if (target.getTags().contains(tag)) { - return target; - } else { - target.addTag(tag); - return targetRepository.save(target); - } - }); - } - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List unassignTag(final Collection controllerIds, final long targetTagId, final Consumer> notFoundHandler) { - return updateTag(controllerIds, targetTagId, notFoundHandler, (tag, target) -> { - if (target.getTags().contains(tag)) { - target.removeTag(tag); - return targetRepository.save(target); - } else { - return target; - } - }); - } - private List updateTag( - final Collection controllerIds, final long targetTagId, final Consumer> notFoundHandler, - final BiFunction updater) { - final JpaTargetTag tag = targetTagRepository.findById(targetTagId) - .orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId)); - final List targets = controllerIds.size() == 1 ? - targetRepository.findOne(TargetSpecifications.hasControllerId(controllerIds.iterator().next())) - .map(List::of) - .orElseGet(Collections::emptyList) : - targetRepository - .findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds)); - if (targets.size() < controllerIds.size()) { - final Collection notFound = notFound(controllerIds, targets); - if (notFoundHandler == null) { - throw new EntityNotFoundException(Target.class, notFound); - } else { - notFoundHandler.accept(notFound); - } - } - - targetRepository.getAccessController() - .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, targets)); - - try { - return targets.stream().map(target -> updater.apply(tag, target)).toList(); - } finally { - // No reason to save the tag - entityManager.detach(tag); - } - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Target unassignType(final String controllerId) { - final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId); - target.setTargetType(null); - return targetRepository.save(target); - } - - @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Target assignType(final String controllerId, final Long targetTypeId) { - final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId); - - targetRepository.getAccessController().ifPresent(acm -> { - acm.assertOperationAllowed(AccessController.Operation.UPDATE, target); - }); - - final JpaTargetType targetType = getTargetTypeByIdAndThrowIfNotFound(targetTypeId); - target.setTargetType(targetType); - return targetRepository.save(target); - } - - @Override - public Slice findByFilterOrderByLinkedDistributionSet(final Pageable pageable, - final long orderByDistributionSetId, final FilterParams filterParams) { - // remove default sort from pageable to not overwrite sorted spec - final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(), - pageable.getPageSize(), Sort.unsorted()); - - final List> specList = buildSpecificationList(filterParams); - specList.add(TargetSpecifications.orderedByLinkedDistributionSet(orderByDistributionSetId, pageable.getSort())); - - return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, unsortedPage, specList); - } - - @Override - public long countByAssignedDistributionSet(final long distributionSetId) { - final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId)); - - return targetRepository.count(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())); - } - - @Override - public long countByInstalledDistributionSet(final long distributionSetId) { - final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId)); - - return targetRepository.count(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())); - } - - @Override - public boolean existsByInstalledOrAssignedDistributionSet(final long distributionSetId) { - final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId)); - - return targetRepository - .exists(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId())); - } - @Override public Slice findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(final Pageable pageRequest, final long distributionSetId, final String targetFilterQuery) { @@ -667,6 +292,20 @@ public class JpaTargetManagement implements TargetManagement { .map(Target.class::cast); } + @Override + public long countByRsqlAndNonDSAndCompatibleAndUpdatable(final long distributionSetId, + final String targetFilterQuery) { + final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId); + final Long distSetTypeId = jpaDistributionSet.getType().getId(); + + return targetRepository.count(AccessController.Operation.UPDATE, + combineWithAnd(List.of( + RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, + virtualPropertyReplacer, database), + TargetSpecifications.hasNotDistributionSetInActions(distributionSetId), + TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId)))); + } + @Override public Slice findByTargetFilterQueryAndNotInRolloutGroupsAndCompatibleAndUpdatable( final Pageable pageRequest, final Collection groups, final String targetFilterQuery, @@ -713,16 +352,6 @@ public class JpaTargetManagement implements TargetManagement { return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageRequest, specList); } - @Override - public Slice findByInRolloutGroupWithoutAction(final Pageable pageRequest, final long group) { - if (!rolloutGroupRepository.existsById(group)) { - throw new EntityNotFoundException(RolloutGroup.class, group); - } - - return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, - List.of(TargetSpecifications.hasNoActionInRolloutGroup(group))); - } - @Override public long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(final Collection groups, final String targetFilterQuery, final DistributionSetType dsType) { @@ -744,36 +373,110 @@ public class JpaTargetManagement implements TargetManagement { } @Override - public long countByRsqlAndNonDSAndCompatibleAndUpdatable(final long distributionSetId, - final String targetFilterQuery) { - final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId); - final Long distSetTypeId = jpaDistributionSet.getType().getId(); + public Slice findByInRolloutGroupWithoutAction(final Pageable pageRequest, final long group) { + if (!rolloutGroupRepository.existsById(group)) { + throw new EntityNotFoundException(RolloutGroup.class, group); + } - return targetRepository.count(AccessController.Operation.UPDATE, - combineWithAnd(List.of( - RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer, database), - TargetSpecifications.hasNotDistributionSetInActions(distributionSetId), - TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId)))); + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, + List.of(TargetSpecifications.hasNoActionInRolloutGroup(group))); } @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public Target create(final TargetCreate c) { - final JpaTargetCreate create = (JpaTargetCreate) c; - return targetRepository.save(AccessController.Operation.CREATE, create.build()); + public Page findByAssignedDistributionSet(final Pageable pageReq, final long distributionSetId) { + final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); + + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, + List.of(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()))); } @Override - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection targets) { - final List targetList = targets.stream().map(JpaTargetCreate.class::cast).map(JpaTargetCreate::build) - .toList(); - return Collections.unmodifiableList(targetRepository.saveAll(AccessController.Operation.CREATE, targetList)); + public Page findByAssignedDistributionSetAndRsql(final Pageable pageReq, final long distributionSetId, + final String rsqlParam) { + final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); + + final List> specList = List.of( + RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), + TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())); + + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, specList); + } + + @Override + public List getByControllerID(final Collection controllerIDs) { + return Collections.unmodifiableList( + targetRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs))); + } + + @Override + public Optional getByControllerID(final String controllerId) { + return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)).map(Target.class::cast); + } + + @Override + public Slice findByFilters(final Pageable pageable, final FilterParams filterParams) { + final List> specList = buildSpecificationList(filterParams); + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, specList); + } + + @Override + public Page findByInstalledDistributionSet(final Pageable pageReq, final long distributionSetId) { + final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); + + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, + List.of(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()))); + } + + @Override + public Page findByInstalledDistributionSetAndRsql(final Pageable pageable, final long distributionSetId, + final String rsqlParam) { + final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId); + + final List> specList = List.of( + RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database), + TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())); + + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList); + } + + @Override + public Page findByUpdateStatus(final Pageable pageable, final TargetUpdateStatus status) { + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, + List.of(TargetSpecifications.hasTargetUpdateStatus(status))); + } + + @Override + public Slice findAll(final Pageable pageable) { + return targetRepository.findAllWithoutCount(pageable).map(Target.class::cast); + } + + @Override + public Slice findByRsql(final Pageable pageable, final String targetFilterQuery) { + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, List.of(RSQLUtility + .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database))); + } + + @Override + public Slice findByTargetFilterQuery(final Pageable pageable, final long targetFilterQueryId) { + final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) + .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); + + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, + List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), TargetFields.class, + virtualPropertyReplacer, database))); + } + + @Override + public Slice findByFilterOrderByLinkedDistributionSet(final Pageable pageable, + final long orderByDistributionSetId, final FilterParams filterParams) { + // remove default sort from pageable to not overwrite sorted spec + final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(), + pageable.getPageSize(), Sort.unsorted()); + + final List> specList = buildSpecificationList(filterParams); + specList.add(TargetSpecifications.orderedByLinkedDistributionSet(orderByDistributionSetId, pageable.getSort())); + + return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, unsortedPage, specList); } @Override @@ -784,12 +487,6 @@ public class JpaTargetManagement implements TargetManagement { List.of(TargetSpecifications.hasTag(tagId))); } - private void throwEntityNotFoundExceptionIfTagDoesNotExist(final Long tagId) { - if (!targetTagRepository.existsById(tagId)) { - throw new EntityNotFoundException(TargetTag.class, tagId); - } - } - @Override public Page findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) { throwEntityNotFoundExceptionIfTagDoesNotExist(tagId); @@ -802,49 +499,125 @@ public class JpaTargetManagement implements TargetManagement { } @Override - public long countByTargetFilterQuery(final long targetFilterQueryId) { - final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) - .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public TargetTypeAssignmentResult assignType(final Collection controllerIds, final Long typeId) { + final JpaTargetType type = targetTypeRepository.findById(typeId) + .orElseThrow(() -> new EntityNotFoundException(TargetType.class, typeId)); - return countByRsql(targetFilterQuery.getQuery()); + final List targetsWithSameType = findTargetsByInSpecification(controllerIds, + TargetSpecifications.hasTargetType(typeId)); + + final List targetsWithoutSameType = findTargetsByInSpecification(controllerIds, + TargetSpecifications.hasTargetTypeNot(typeId)); + + // set new target type to all targets without that type + targetsWithoutSameType.forEach(target -> target.setTargetType(type)); + + final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(), + targetRepository.saveAll(targetsWithoutSameType), Collections.emptyList(), type); + + // no reason to persist the type + entityManager.detach(type); + return result; } @Override - public long countByRsql(final String targetFilterQuery) { - return JpaManagementHelper.countBySpec(targetRepository, List.of(RSQLUtility - .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database))); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public TargetTypeAssignmentResult unassignType(final Collection controllerIds) { + final List allTargets = findTargetsByInSpecification(controllerIds, null); + + if (allTargets.size() < controllerIds.size()) { + throw new EntityNotFoundException(Target.class, controllerIds, + allTargets.stream().map(Target::getControllerId).toList()); + } + + // set new target type to null for all targets + allTargets.forEach(target -> target.setTargetType(null)); + + return new TargetTypeAssignmentResult(0, Collections.emptyList(), targetRepository.saveAll(allTargets), null); } @Override - public long countByRsqlAndUpdatable(String targetFilterQuery) { - final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery, - TargetFields.class, virtualPropertyReplacer, database)); - return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList)); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List assignTag(final Collection controllerIds, final long targetTagId, + final Consumer> notFoundHandler) { + return updateTag(controllerIds, targetTagId, notFoundHandler, (tag, target) -> { + if (target.getTags().contains(tag)) { + return target; + } else { + target.addTag(tag); + return targetRepository.save(target); + } + }); } @Override - public long countByRsqlAndCompatible(final String targetFilterQuery, final Long distributionSetIdTypeId) { - final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery, - TargetFields.class, virtualPropertyReplacer, database), - TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId)); - - return JpaManagementHelper.countBySpec(targetRepository, specList); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List unassignTag(final Collection controllerIds, final long targetTagId, + final Consumer> notFoundHandler) { + return updateTag(controllerIds, targetTagId, notFoundHandler, (tag, target) -> { + if (target.getTags().contains(tag)) { + target.removeTag(tag); + return targetRepository.save(target); + } else { + return target; + } + }); } @Override - public long countByRsqlAndCompatibleAndUpdatable(String targetFilterQuery, Long distributionSetIdTypeId) { - final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery, - TargetFields.class, virtualPropertyReplacer, database), - TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId)); - return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList)); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Target unassignType(final String controllerId) { + final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId); + target.setTargetType(null); + return targetRepository.save(target); } @Override - public long countByFailedInRollout(final String rolloutId, final Long dsTypeId) { - final List> specList = List - .of(TargetSpecifications.failedActionsForRollout(rolloutId)); + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Target assignType(final String controllerId, final Long targetTypeId) { + final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId); - return JpaManagementHelper.countBySpec(targetRepository, specList); + targetRepository.getAccessController().ifPresent(acm -> { + acm.assertOperationAllowed(AccessController.Operation.UPDATE, target); + }); + + final JpaTargetType targetType = getTargetTypeByIdAndThrowIfNotFound(targetTypeId); + target.setTargetType(targetType); + return targetRepository.save(target); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public Target update(final TargetUpdate u) { + final JpaTargetUpdate update = (JpaTargetUpdate) u; + + final JpaTarget target = getByControllerIdAndThrowIfNotFound(update.getControllerId()); + + update.getName().ifPresent(target::setName); + update.getDescription().ifPresent(target::setDescription); + update.getAddress().ifPresent(target::setAddress); + update.getSecurityToken().ifPresent(target::setSecurityToken); + if (update.getTargetTypeId() != null) { + final TargetType targetType = getTargetTypeByIdAndThrowIfNotFound(update.getTargetTypeId()); + target.setTargetType(targetType); + } + + return targetRepository.save(target); } @Override @@ -896,6 +669,12 @@ public class JpaTargetManagement implements TargetManagement { return target.isRequestControllerAttributes(); } + @Override + public Page findByControllerAttributesRequested(final Pageable pageReq) { + return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, + List.of(TargetSpecifications.hasRequestControllerAttributesTrue())); + } + @Override public boolean existsByControllerId(final String controllerId) { return targetRepository.exists(TargetSpecifications.hasControllerId(controllerId)); @@ -921,15 +700,117 @@ public class JpaTargetManagement implements TargetManagement { } @Override - public Page findByControllerAttributesRequested(final Pageable pageReq) { - return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, - List.of(TargetSpecifications.hasRequestControllerAttributesTrue())); + public Set getTagsByControllerId(@NotEmpty String controllerId) { + // the method has PreAuthorized by itself + return getByControllerID(controllerId).map(JpaTarget.class::cast).map(JpaTarget::getTags) + .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); } - private static Collection notFound(final Collection controllerIds, final List foundTargets) { - final Map foundTargetMap = foundTargets.stream() - .collect(Collectors.toMap(Target::getControllerId, Function.identity())); - return controllerIds.stream().filter(id -> !foundTargetMap.containsKey(id)).toList(); + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List createMetaData(final String controllerId, final Collection md) { + final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId); + + md.forEach(meta -> checkAndThrowIfTargetMetadataAlreadyExists( + new TargetMetadataCompositeKey(target.getId(), meta.getKey()))); + + assertMetaDataQuota(target.getId(), md.size()); + + final JpaTarget updatedTarget = JpaManagementHelper.touch(entityManager, targetRepository, target); + + final List createdMetadata = md.stream() + .map(meta -> targetMetadataRepository + .save(new JpaTargetMetadata(meta.getKey(), meta.getValue(), updatedTarget))) + .collect(Collectors.toUnmodifiableList()); + + // TargetUpdatedEvent is not sent within the touch() method due to the + // "lastModifiedAt" field being ignored in JpaTarget + eventPublisherHolder.getEventPublisher() + .publishEvent(new TargetUpdatedEvent(updatedTarget, eventPublisherHolder.getApplicationId())); + + return createdMetadata; + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void deleteMetaData(final String controllerId, final String key) { + final JpaTargetMetadata metadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, key) + .orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, controllerId, key)); + + final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository, + getByControllerIdAndThrowIfNotFound(controllerId)); + + targetRepository.getAccessController() + .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target)); + + targetMetadataRepository.deleteById(metadata.getId()); + // target update event is set to ignore "lastModifiedAt" field, so it is + // not send automatically within the touch() method + eventPublisherHolder.getEventPublisher() + .publishEvent(new TargetUpdatedEvent(target, eventPublisherHolder.getApplicationId())); + } + + @Override + public Page findMetaDataByControllerId(final Pageable pageable, final String controllerId) { + final Long id = getByControllerIdAndThrowIfNotFound(controllerId).getId(); + + return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable, + Collections.singletonList(metadataByTargetIdSpec(id))); + } + + @Override + public long countMetaDataByControllerId(@NotEmpty final String controllerId) { + final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); + + return JpaManagementHelper.countBySpec(targetMetadataRepository, + Collections.singletonList(metadataByTargetIdSpec(targetId))); + } + + @Override + public Page findMetaDataByControllerIdAndRsql(final Pageable pageable, final String controllerId, + final String rsqlParam) { + final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); + + final List> specList = Arrays.asList(RSQLUtility + .buildRsqlSpecification(rsqlParam, TargetMetadataFields.class, virtualPropertyReplacer, database), + metadataByTargetIdSpec(targetId)); + + return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable, specList); + } + + @Override + public Optional getMetaDataByControllerId(final String controllerId, final String key) { + final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId(); + + return targetMetadataRepository.findById(new TargetMetadataCompositeKey(targetId, key)).map(t -> t); + } + + @Override + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public TargetMetadata updateMetadata(final String controllerId, final MetaData md) { + + // check if exists otherwise throw entity not found exception + final JpaTargetMetadata updatedMetadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, + md.getKey()) + .orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, controllerId, md.getKey())); + updatedMetadata.setValue(md.getValue()); + // touch it to update the lock revision because we are modifying the + // target indirectly + final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository, + getByControllerIdAndThrowIfNotFound(controllerId)); + + final JpaTargetMetadata metadata = targetMetadataRepository.save(updatedMetadata); + // target update event is set to ignore "lastModifiedAt" field, so it is + // not send automatically within the touch() method + eventPublisherHolder.getEventPublisher() + .publishEvent(new TargetUpdatedEvent(target, eventPublisherHolder.getApplicationId())); + return metadata; } @Override @@ -987,4 +868,126 @@ public class JpaTargetManagement implements TargetManagement { entityManager.detach(tag); return result; } + + private static boolean hasTagsFilterActive(final FilterParams filterParams) { + final boolean isNoTagActive = Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTag()); + final boolean isAtLeastOneTagActive = filterParams.getFilterByTagNames() != null + && filterParams.getFilterByTagNames().length > 0; + + return isNoTagActive || isAtLeastOneTagActive; + } + + private static boolean hasTypesFilterActive(final FilterParams filterParams) { + return filterParams.getFilterByTargetType() != null; + } + + private static boolean hasNoTypeFilterActive(final FilterParams filterParams) { + return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType()); + } + + private static Collection notFound(final Collection controllerIds, final List foundTargets) { + final Map foundTargetMap = foundTargets.stream() + .collect(Collectors.toMap(Target::getControllerId, Function.identity())); + return controllerIds.stream().filter(id -> !foundTargetMap.containsKey(id)).toList(); + } + + private JpaTarget getByControllerIdAndThrowIfNotFound(final String controllerId) { + return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) + .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); + } + + private JpaTargetType getTargetTypeByIdAndThrowIfNotFound(final long id) { + return targetTypeRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(TargetType.class, id)); + } + + private void checkAndThrowIfTargetMetadataAlreadyExists(final TargetMetadataCompositeKey metadataId) { + if (targetMetadataRepository.existsById(metadataId)) { + throw new EntityAlreadyExistsException( + "Metadata entry with key '" + metadataId.getKey() + "' already exists"); + } + } + + private void assertMetaDataQuota(final Long targetId, final int requested) { + QuotaHelper.assertAssignmentQuota(targetId, requested, quotaManagement.getMaxMetaDataEntriesPerTarget(), + TargetMetadata.class, Target.class, targetMetadataRepository::countByTargetId); + } + + private Specification metadataByTargetIdSpec(final Long targetId) { + return (root, query, cb) -> cb.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId); + } + + private List> buildSpecificationList(final FilterParams filterParams) { + final List> specList = new ArrayList<>(); + if ((filterParams.getFilterByStatus() != null) && !filterParams.getFilterByStatus().isEmpty()) { + specList.add(TargetSpecifications.hasTargetUpdateStatus(filterParams.getFilterByStatus())); + } + if (filterParams.getOverdueState() != null && filterParams.getOverdueState()) { + specList.add(TargetSpecifications.isOverdue(TimestampCalculator.calculateOverdueTimestamp())); + } + if (filterParams.getFilterByDistributionId() != null) { + final DistributionSet validDistSet = distributionSetManagement + .getOrElseThrowException(filterParams.getFilterByDistributionId()); + + specList.add(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId())); + } + if (!ObjectUtils.isEmpty(filterParams.getFilterBySearchText())) { + specList.add(TargetSpecifications.likeControllerIdOrName(filterParams.getFilterBySearchText())); + } + if (hasTagsFilterActive(filterParams)) { + specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(), + filterParams.getSelectTargetWithNoTag())); + } + + if (hasTypesFilterActive(filterParams)) { + specList.add(TargetSpecifications.hasTargetType(filterParams.getFilterByTargetType())); + } else if (hasNoTypeFilterActive(filterParams)) { + specList.add(TargetSpecifications.hasNoTargetType()); + } + + return specList; + } + + private List findTargetsByInSpecification(final Collection controllerIds, + final Specification specification) { + return ListUtils.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream() + .map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification))) + .flatMap(List::stream).toList(); + } + + private List updateTag( + final Collection controllerIds, final long targetTagId, final Consumer> notFoundHandler, + final BiFunction updater) { + final JpaTargetTag tag = targetTagRepository.findById(targetTagId) + .orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId)); + final List targets = controllerIds.size() == 1 ? + targetRepository.findOne(TargetSpecifications.hasControllerId(controllerIds.iterator().next())) + .map(List::of) + .orElseGet(Collections::emptyList) : + targetRepository + .findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds)); + if (targets.size() < controllerIds.size()) { + final Collection notFound = notFound(controllerIds, targets); + if (notFoundHandler == null) { + throw new EntityNotFoundException(Target.class, notFound); + } else { + notFoundHandler.accept(notFound); + } + } + + targetRepository.getAccessController() + .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, targets)); + + try { + return targets.stream().map(target -> updater.apply(tag, target)).toList(); + } finally { + // No reason to save the tag + entityManager.detach(tag); + } + } + + private void throwEntityNotFoundExceptionIfTagDoesNotExist(final Long tagId) { + if (!targetTagRepository.existsById(tagId)) { + throw new EntityNotFoundException(TargetTag.class, tagId); + } + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java index edb44345e..380d070fc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java @@ -41,7 +41,6 @@ import org.springframework.validation.annotation.Validated; /** * JPA implementation of {@link TargetTagManagement}. - * */ @Transactional(readOnly = true) @Validated @@ -62,8 +61,8 @@ public class JpaTargetTagManagement implements TargetTagManagement { } @Override - public Optional getByName(final String name) { - return targetTagRepository.findByNameEquals(name); + public long count() { + return targetTagRepository.count(); } @Override @@ -94,8 +93,13 @@ public class JpaTargetTagManagement implements TargetTagManagement { public void delete(final String targetTagName) { targetTagRepository.delete( targetTagRepository - .findOne(((root, query, cb) -> cb.equal(root.get(JpaTargetTag_.name), targetTagName))) - .orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagName))); + .findOne(((root, query, cb) -> cb.equal(root.get(JpaTargetTag_.name), targetTagName))) + .orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagName))); + } + + @Override + public Page findAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, null); } @Override @@ -105,8 +109,18 @@ public class JpaTargetTagManagement implements TargetTagManagement { } @Override - public long count() { - return targetTagRepository.count(); + public Optional getByName(final String name) { + return targetTagRepository.findByNameEquals(name); + } + + @Override + public Optional get(final long id) { + return targetTagRepository.findById(id).map(TargetTag.class::cast); + } + + @Override + public List get(final Collection ids) { + return Collections.unmodifiableList(targetTagRepository.findAllById(ids)); } @Override @@ -125,19 +139,4 @@ public class JpaTargetTagManagement implements TargetTagManagement { return targetTagRepository.save(tag); } - - @Override - public Optional get(final long id) { - return targetTagRepository.findById(id).map(TargetTag.class::cast); - } - - @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(targetTagRepository.findAllById(ids)); - } - - @Override - public Page findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, null); - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java index 043f54528..47a344e7d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java @@ -50,7 +50,6 @@ import org.springframework.validation.annotation.Validated; /** * JPA implementation of {@link TargetTypeManagement}. - * */ @Transactional(readOnly = true) @Validated @@ -68,14 +67,10 @@ public class JpaTargetTypeManagement implements TargetTypeManagement { /** * Constructor * - * @param targetTypeRepository - * Target type repository - * @param targetRepository - * Target repository - * @param virtualPropertyReplacer - * replacer - * @param database - * database + * @param targetTypeRepository Target type repository + * @param targetRepository Target repository + * @param virtualPropertyReplacer replacer + * @param database database */ public JpaTargetTypeManagement(final TargetTypeRepository targetTypeRepository, final TargetRepository targetRepository, final DistributionSetTypeRepository distributionSetTypeRepository, @@ -152,7 +147,7 @@ public class JpaTargetTypeManagement implements TargetTypeManagement { return JpaManagementHelper.findAllWithCountBySpec(targetTypeRepository, pageable, List.of( RSQLUtility.buildRsqlSpecification( - rsqlParam, TargetTypeFields.class, virtualPropertyReplacer,database))); + rsqlParam, TargetTypeFields.class, virtualPropertyReplacer, database))); } @Override @@ -236,13 +231,9 @@ public class JpaTargetTypeManagement implements TargetTypeManagement { * Enforces the quota specifying the maximum number of * {@link DistributionSetType}s per {@link TargetType}. * - * @param id - * of the target type - * @param requested - * number of distribution set types to check - * - * @throws AssignmentQuotaExceededException - * if the software module type quota is exceeded + * @param id of the target type + * @param requested number of distribution set types to check + * @throws AssignmentQuotaExceededException if the software module type quota is exceeded */ private void assertDistributionSetTypeQuota(final long id, final int requested) { QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxDistributionSetTypesPerTargetType(), diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java index ac27eefcb..dbb1e9332 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java @@ -58,76 +58,18 @@ import org.springframework.validation.annotation.Validated; @Validated public class JpaTenantConfigurationManagement implements TenantConfigurationManagement { + private static final ConfigurableConversionService conversionService = new DefaultConversionService(); @Autowired private TenantConfigurationRepository tenantConfigurationRepository; - @Autowired private TenantConfigurationProperties tenantConfigurationProperties; - @Autowired private ApplicationContext applicationContext; - @Autowired private CacheManager cacheManager; - @Autowired private AfterTransactionCommitExecutor afterCommitExecutor; - private static final ConfigurableConversionService conversionService = new DefaultConversionService(); - - @Override - @Cacheable(value = "tenantConfiguration", key = "#configurationKeyName") - public TenantConfigurationValue getConfigurationValue(final String configurationKeyName, - final Class propertyType) { - checkAccess(configurationKeyName); - - final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(configurationKeyName); - - validateTenantConfigurationDataType(configurationKey, propertyType); - - final TenantConfiguration tenantConfiguration = tenantConfigurationRepository - .findByKey(configurationKey.getKeyName()); - - return buildTenantConfigurationValueByKey(configurationKey, propertyType, tenantConfiguration); - } - - @Override - public TenantConfigurationValue getConfigurationValue( - final String configurationKeyName) { - checkAccess(configurationKeyName); - - final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(configurationKeyName); - - return getConfigurationValue(configurationKeyName, (Class)configurationKey.getDataType()); - } - - @Override - public T getGlobalConfigurationValue(final String configurationKeyName, final Class propertyType) { - checkAccess(configurationKeyName); - - final TenantConfigurationKey key = tenantConfigurationProperties.fromKeyName(configurationKeyName); - - if (!key.getDataType().isAssignableFrom(propertyType)) { - throw new TenantConfigurationValidatorException(String.format( - "Cannot parse the database value of type %s into the type %s.", key.getDataType(), propertyType)); - } - - return conversionService.convert(key.getDefaultValue(), propertyType); - } - - private void checkAccess(final String configurationKeyName) { - if (TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY - .equalsIgnoreCase(configurationKeyName)) { - final SystemSecurityContext systemSecurityContext = - SystemSecurityContextHolder.getInstance().getSystemSecurityContext(); - if (!systemSecurityContext.isCurrentThreadSystemCode() && - !systemSecurityContext.hasPermission(SpPermission.READ_GATEWAY_SEC_TOKEN)) { - throw new InsufficientPermissionException( - "Can't read gateway security token! " + SpPermission.READ_GATEWAY_SEC_TOKEN + " is required!"); - } - } - } - @Override @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName") @Transactional @@ -154,6 +96,85 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana return addOrUpdateConfiguration0(configurations); } + @Override + @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName") + @Transactional + @Retryable(include = { + ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public void deleteConfiguration(final String configurationKeyName) { + tenantConfigurationRepository.deleteByKey(configurationKeyName); + } + + @Override + public TenantConfigurationValue getConfigurationValue( + final String configurationKeyName) { + checkAccess(configurationKeyName); + + final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(configurationKeyName); + + return getConfigurationValue(configurationKeyName, (Class) configurationKey.getDataType()); + } + + @Override + @Cacheable(value = "tenantConfiguration", key = "#configurationKeyName") + public TenantConfigurationValue getConfigurationValue(final String configurationKeyName, + final Class propertyType) { + checkAccess(configurationKeyName); + + final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(configurationKeyName); + + validateTenantConfigurationDataType(configurationKey, propertyType); + + final TenantConfiguration tenantConfiguration = tenantConfigurationRepository + .findByKey(configurationKey.getKeyName()); + + return buildTenantConfigurationValueByKey(configurationKey, propertyType, tenantConfiguration); + } + + @Override + public T getGlobalConfigurationValue(final String configurationKeyName, final Class propertyType) { + checkAccess(configurationKeyName); + + final TenantConfigurationKey key = tenantConfigurationProperties.fromKeyName(configurationKeyName); + + if (!key.getDataType().isAssignableFrom(propertyType)) { + throw new TenantConfigurationValidatorException(String.format( + "Cannot parse the database value of type %s into the type %s.", key.getDataType(), propertyType)); + } + + return conversionService.convert(key.getDefaultValue(), propertyType); + } + + /** + * Validates the data type of the tenant configuration. If it is possible to + * cast to the given data type. + * + * @param configurationKey the key + * @param propertyType the class + */ + private static void validateTenantConfigurationDataType(final TenantConfigurationKey configurationKey, + final Class propertyType) { + + if (!configurationKey.getDataType().isAssignableFrom(propertyType)) { + throw new TenantConfigurationValidatorException( + String.format("Cannot parse the database value of type %s into the type %s.", + configurationKey.getDataType(), propertyType)); + } + } + + private void checkAccess(final String configurationKeyName) { + if (TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY + .equalsIgnoreCase(configurationKeyName)) { + final SystemSecurityContext systemSecurityContext = + SystemSecurityContextHolder.getInstance().getSystemSecurityContext(); + if (!systemSecurityContext.isCurrentThreadSystemCode() && + !systemSecurityContext.hasPermission(SpPermission.READ_GATEWAY_SEC_TOKEN)) { + throw new InsufficientPermissionException( + "Can't read gateway security token! " + SpPermission.READ_GATEWAY_SEC_TOKEN + " is required!"); + } + } + } + private Map> addOrUpdateConfiguration0(Map configurations) { List configurationList = new ArrayList<>(); configurations.forEach((configurationKeyName, value) -> { @@ -187,9 +208,9 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana JpaTenantConfiguration::getKey, updatedTenantConfiguration -> { - @SuppressWarnings("unchecked") - final Class clazzT = (Class) configurations.get(updatedTenantConfiguration.getKey()).getClass(); - return TenantConfigurationValue.builder().global(false) + @SuppressWarnings("unchecked") final Class clazzT = (Class) configurations.get(updatedTenantConfiguration.getKey()) + .getClass(); + return TenantConfigurationValue. builder().global(false) .createdBy(updatedTenantConfiguration.getCreatedBy()) .createdAt(updatedTenantConfiguration.getCreatedAt()) .lastModifiedAt(updatedTenantConfiguration.getLastModifiedAt()) @@ -199,32 +220,6 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana })); } - @Override - @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName") - @Transactional - @Retryable(include = { - ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void deleteConfiguration(final String configurationKeyName) { - tenantConfigurationRepository.deleteByKey(configurationKeyName); - } - - /** - * Validates the data type of the tenant configuration. If it is possible to - * cast to the given data type. - * - * @param configurationKey the key - * @param propertyType the class - */ - private static void validateTenantConfigurationDataType(final TenantConfigurationKey configurationKey, - final Class propertyType) { - - if (!configurationKey.getDataType().isAssignableFrom(propertyType)) { - throw new TenantConfigurationValidatorException( - String.format("Cannot parse the database value of type %s into the type %s.", - configurationKey.getDataType(), propertyType)); - } - } - private TenantConfigurationValue buildTenantConfigurationValueByKey( final TenantConfigurationKey configurationKey, final Class propertyType, final TenantConfiguration tenantConfiguration) { @@ -247,14 +242,10 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana /** * Asserts that the requested configuration value change is allowed. Throws * a {@link TenantConfigurationValueChangeNotAllowedException} otherwise. - * - * @param key - * The configuration key. - * @param valueChange - * The configuration to be validated. - * - * @throws TenantConfigurationValueChangeNotAllowedException - * if the requested configuration change is not allowed. + * + * @param key The configuration key. + * @param valueChange The configuration to be validated. + * @throws TenantConfigurationValueChangeNotAllowedException if the requested configuration change is not allowed. */ private void assertValueChangeIsAllowed(final String key, final JpaTenantConfiguration valueChange) { assertMultiAssignmentsValueChange(key, valueChange); @@ -280,7 +271,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana } if (MULTI_ASSIGNMENTS_ENABLED.equals(key) && Boolean.parseBoolean(valueChange.getValue())) { JpaTenantConfiguration batchConfig = tenantConfigurationRepository.findByKey(BATCH_ASSIGNMENTS_ENABLED); - if (batchConfig!=null && Boolean.parseBoolean(batchConfig.getValue())) { + if (batchConfig != null && Boolean.parseBoolean(batchConfig.getValue())) { log.debug("The Multi-Assignments '{}' feature cannot be enabled as it contradicts with " + "The Batch-Assignments feature, which is already enabled .", key); throw new TenantConfigurationValueChangeNotAllowedException(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java index 5e5f0e77d..14bce52e8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java @@ -22,7 +22,6 @@ import org.springframework.validation.annotation.Validated; /** * Management service for statistics of a single tenant. - * */ @Validated public class JpaTenantStatsManagement implements TenantStatsManagement { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java index b4c6e2faa..b41b16b79 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java @@ -44,27 +44,18 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; /** * AbstractDsAssignmentStrategy for offline assignments, i.e. not managed by * hawkBit. - * */ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { OfflineDsAssignmentStrategy(final TargetRepository targetRepository, - final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, - final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, - final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, - final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { + final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, + final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, + final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, + final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { super(targetRepository, afterCommit, eventPublisherHolder, actionRepository, actionStatusRepository, quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties); } - @Override - public void sendTargetUpdatedEvents(final DistributionSet set, final List targets) { - targets.forEach(target -> { - target.setUpdateStatus(TargetUpdateStatus.IN_SYNC); - sendTargetUpdatedEvent(target); - }); - } - @Override public List findTargetsForAssignment(final List controllerIDs, final long setId) { final Function, List> mapper; @@ -80,13 +71,11 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { } @Override - public Set cancelActiveActions(final List> targetIds) { - return Collections.emptySet(); - } - - @Override - public void closeActiveActions(final List> targetIds) { - // Not supported by offline case + public void sendTargetUpdatedEvents(final DistributionSet set, final List targets) { + targets.forEach(target -> { + target.setUpdateStatus(TargetUpdateStatus.IN_SYNC); + sendTargetUpdatedEvent(target); + }); } @Override @@ -94,7 +83,8 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { final JpaDistributionSet set, final List> targetIds, final String currentUser) { final long now = System.currentTimeMillis(); targetIds.forEach(targetIdsChunk -> { - if (targetRepository.count(AccessController.Operation.UPDATE, targetRepository.byIdsSpec(targetIdsChunk)) != targetIdsChunk.size()) { + if (targetRepository.count(AccessController.Operation.UPDATE, + targetRepository.byIdsSpec(targetIdsChunk)) != targetIdsChunk.size()) { throw new InsufficientPermissionException("No update access to all targets!"); } targetRepository.setAssignedAndInstalledDistributionSetAndUpdateStatus( @@ -116,6 +106,26 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { }); } + @Override + public Set cancelActiveActions(final List> targetIds) { + return Collections.emptySet(); + } + + @Override + public void closeActiveActions(final List> targetIds) { + // Not supported by offline case + } + + @Override + void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult) { + // no need to send deployment events in the offline case + } + + @Override + void sendDeploymentEvents(final List assignmentResults) { + // no need to send deployment events in the offline case + } + @Override public JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType, final List targets, final JpaDistributionSet set) { @@ -135,14 +145,4 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { return result; } - @Override - void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult) { - // no need to send deployment events in the offline case - } - - @Override - void sendDeploymentEvents(final List assignmentResults) { - // no need to send deployment events in the offline case - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java index e7da2956c..8acc2a8d5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java @@ -47,46 +47,18 @@ import org.springframework.util.CollectionUtils; /** * AbstractDsAssignmentStrategy for online assignments, i.e. managed by hawkBit. - * */ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { OnlineDsAssignmentStrategy(final TargetRepository targetRepository, - final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, - final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, - final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, - final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { + final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, + final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, + final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, + final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { super(targetRepository, afterCommit, eventPublisherHolder, actionRepository, actionStatusRepository, quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties); } - @Override - public void sendTargetUpdatedEvents(final DistributionSet set, final List targets) { - targets.forEach(target -> { - target.setUpdateStatus(TargetUpdateStatus.PENDING); - sendTargetUpdatedEvent(target); - }); - } - - @Override - public void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult) { - if (isMultiAssignmentsEnabled()) { - sendDeploymentEvents(Collections.singletonList(assignmentResult)); - } else { - sendDistributionSetAssignedEvent(assignmentResult); - } - } - - @Override - public void sendDeploymentEvents(final List assignmentResults) { - if (isMultiAssignmentsEnabled()) { - sendDeploymentEvent(assignmentResults.stream().flatMap(result -> result.getAssignedEntity().stream()) - .collect(Collectors.toList())); - } else { - assignmentResults.forEach(this::sendDistributionSetAssignedEvent); - } - } - public void sendDeploymentEvents(final long distributionSetId, final List actions) { if (isMultiAssignmentsEnabled()) { sendDeploymentEvent(actions); @@ -114,14 +86,11 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { } @Override - public Set cancelActiveActions(final List> targetIds) { - return targetIds.stream().map(this::overrideObsoleteUpdateActions).flatMap(Collection::stream) - .collect(Collectors.toSet()); - } - - @Override - public void closeActiveActions(final List> targetIds) { - targetIds.forEach(this::closeObsoleteUpdateActions); + public void sendTargetUpdatedEvents(final DistributionSet set, final List targets) { + targets.forEach(target -> { + target.setUpdateStatus(TargetUpdateStatus.PENDING); + sendTargetUpdatedEvent(target); + }); } @Override @@ -129,7 +98,8 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { final String currentUser) { final long now = System.currentTimeMillis(); targetIds.forEach(targetIdsChunk -> { - if (targetRepository.count(AccessController.Operation.UPDATE, targetRepository.byIdsSpec(targetIdsChunk)) != targetIdsChunk.size()) { + if (targetRepository.count(AccessController.Operation.UPDATE, + targetRepository.byIdsSpec(targetIdsChunk)) != targetIdsChunk.size()) { throw new InsufficientPermissionException("No update access to all targets!"); } targetRepository.setAssignedDistributionSetAndUpdateStatus(TargetUpdateStatus.PENDING, @@ -149,6 +119,36 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { }); } + @Override + public Set cancelActiveActions(final List> targetIds) { + return targetIds.stream().map(this::overrideObsoleteUpdateActions).flatMap(Collection::stream) + .collect(Collectors.toSet()); + } + + @Override + public void closeActiveActions(final List> targetIds) { + targetIds.forEach(this::closeObsoleteUpdateActions); + } + + @Override + public void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult) { + if (isMultiAssignmentsEnabled()) { + sendDeploymentEvents(Collections.singletonList(assignmentResult)); + } else { + sendDistributionSetAssignedEvent(assignmentResult); + } + } + + @Override + public void sendDeploymentEvents(final List assignmentResults) { + if (isMultiAssignmentsEnabled()) { + sendDeploymentEvent(assignmentResults.stream().flatMap(result -> result.getAssignedEntity().stream()) + .collect(Collectors.toList())); + } else { + assignmentResults.forEach(this::sendDistributionSetAssignedEvent); + } + } + @Override public JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType, final List targets, final JpaDistributionSet set) { @@ -187,6 +187,20 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { } } + private static Stream filterCancellations(final List actions) { + return actions.stream().filter(action -> { + final Status actionStatus = action.getStatus(); + return Status.CANCELING != actionStatus && Status.CANCELED != actionStatus; + }); + } + + private static List getActionsWithoutCancellations(final List actions) { + if (actions == null || actions.isEmpty()) { + return Collections.emptyList(); + } + return filterCancellations(actions).collect(Collectors.toList()); + } + private void sendMultiActionCancelEvent(final Action action) { sendMultiActionCancelEvent(action.getTenant(), Collections.singletonList(action)); } @@ -224,10 +238,8 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { * Helper to fire a {@link MultiActionCancelEvent}. This method may only be * called if the Multi-Assignments feature is enabled. * - * @param tenant - * the event is scoped to - * @param actions - * assigned to the targets + * @param tenant the event is scoped to + * @param actions assigned to the targets */ private void sendMultiActionCancelEvent(final String tenant, final List actions) { afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher() @@ -238,28 +250,12 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { * Helper to fire a {@link MultiActionAssignEvent}. This method may only be * called if the Multi-Assignments feature is enabled. * - * @param tenant - * the event is scoped to - * @param actions - * assigned to the targets + * @param tenant the event is scoped to + * @param actions assigned to the targets */ private void sendMultiActionAssignEvent(final String tenant, final List actions) { afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher() .publishEvent(new MultiActionAssignEvent(tenant, eventPublisherHolder.getApplicationId(), actions))); } - private static Stream filterCancellations(final List actions) { - return actions.stream().filter(action -> { - final Status actionStatus = action.getStatus(); - return Status.CANCELING != actionStatus && Status.CANCELED != actionStatus; - }); - } - - private static List getActionsWithoutCancellations(final List actions) { - if (actions == null || actions.isEmpty()) { - return Collections.emptyList(); - } - return filterCancellations(actions).collect(Collectors.toList()); - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index fcc80c46f..3e1bd377b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -30,15 +30,14 @@ import org.springframework.security.core.context.SecurityContextHolder; /** * Holder of the base attributes common to all entities. - * */ @MappedSuperclass @Access(AccessType.FIELD) @EntityListeners({ AuditingEntityListener.class, EntityPropertyChangeListener.class, EntityInterceptorListener.class }) public abstract class AbstractJpaBaseEntity implements BaseEntity { - private static final long serialVersionUID = 1L; - protected static final int USERNAME_FIELD_LENGTH = 64; + protected static final int USERNAME_FIELD_LENGTH = 64; + private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @@ -88,6 +87,34 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { return lastModifiedBy; } + @LastModifiedBy + public void setLastModifiedBy(final String lastModifiedBy) { + if (isController()) { + return; + } + + this.lastModifiedBy = lastModifiedBy; + } + + @Override + public int getOptLockRevision() { + return optLockRevision; + } + + public void setOptLockRevision(final int optLockRevision) { + this.optLockRevision = optLockRevision; + } + + @LastModifiedDate + public void setLastModifiedAt(final long lastModifiedAt) { + + if (isController()) { + return; + } + + this.lastModifiedAt = lastModifiedAt; + } + @CreatedBy public void setCreatedBy(final String createdBy) { if (isController()) { @@ -115,52 +142,11 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { } } - @LastModifiedDate - public void setLastModifiedAt(final long lastModifiedAt) { - - if (isController()) { - return; - } - - this.lastModifiedAt = lastModifiedAt; - } - - @LastModifiedBy - public void setLastModifiedBy(final String lastModifiedBy) { - if (isController()) { - return; - } - - this.lastModifiedBy = lastModifiedBy; - } - - private boolean isController() { - return SecurityContextHolder.getContext().getAuthentication() != null - && SecurityContextHolder.getContext().getAuthentication() - .getDetails() instanceof TenantAwareAuthenticationDetails - && ((TenantAwareAuthenticationDetails) SecurityContextHolder.getContext().getAuthentication() - .getDetails()).isController(); - } - - @Override - public int getOptLockRevision() { - return optLockRevision; - } - - public void setOptLockRevision(final int optLockRevision) { - this.optLockRevision = optLockRevision; - } - @Override public Long getId() { return id; } - @Override - public String toString() { - return this.getClass().getSimpleName() + " [id=" + id + "]"; - } - public void setId(final Long id) { this.id = id; } @@ -169,7 +155,7 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { * Defined equals/hashcode strategy for the repository in general is that an * entity is equal if it has the same {@link #getId()} and * {@link #getOptLockRevision()} and class. - * + * * @see java.lang.Object#hashCode() */ @Override @@ -188,7 +174,7 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { * Defined equals/hashcode strategy for the repository in general is that an * entity is equal if it has the same {@link #getId()} and * {@link #getOptLockRevision()} and class. - * + * * @see java.lang.Object#equals(java.lang.Object) */ @Override @@ -213,4 +199,17 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { return optLockRevision == other.optLockRevision; } + @Override + public String toString() { + return this.getClass().getSimpleName() + " [id=" + id + "]"; + } + + private boolean isController() { + return SecurityContextHolder.getContext().getAuthentication() != null + && SecurityContextHolder.getContext().getAuthentication() + .getDetails() instanceof TenantAwareAuthenticationDetails + && ((TenantAwareAuthenticationDetails) SecurityContextHolder.getContext().getAuthentication() + .getDetails()).isController(); + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java index e77357331..719089a1d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java @@ -22,10 +22,10 @@ import org.eclipse.hawkbit.repository.model.MetaData; /** * Meta data for entities. - * */ @MappedSuperclass public abstract class AbstractJpaMetaData implements MetaData { + private static final long serialVersionUID = 1L; @Id @@ -66,6 +66,11 @@ public abstract class AbstractJpaMetaData implements MetaData { this.value = value; } + @Override + public int hashCode() { + return Objects.hash(key, value); + } + @Override public boolean equals(final Object o) { if (this == o) @@ -75,9 +80,4 @@ public abstract class AbstractJpaMetaData implements MetaData { final AbstractJpaMetaData that = (AbstractJpaMetaData) o; return Objects.equals(key, that.key) && Objects.equals(value, that.value); } - - @Override - public int hashCode() { - return Objects.hash(key, value); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaNamedEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaNamedEntity.java index bccbffa8d..35d7e725c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaNamedEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaNamedEntity.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.model; +import java.io.Serial; + import jakarta.persistence.Column; import jakarta.persistence.MappedSuperclass; import jakarta.validation.constraints.NotNull; @@ -17,8 +19,6 @@ import jakarta.validation.constraints.Size; import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; -import java.io.Serial; - /** * {@link TenantAwareBaseEntity} extension for all entities that are named in * addition to their technical ID. @@ -51,10 +51,8 @@ public abstract class AbstractJpaNamedEntity extends AbstractJpaTenantAwareBaseE /** * Parameterized constructor. * - * @param name - * of the {@link NamedEntity} - * @param description - * of the {@link NamedEntity} + * @param name of the {@link NamedEntity} + * @param description of the {@link NamedEntity} */ AbstractJpaNamedEntity(final String name, final String description) { this.name = name; @@ -71,11 +69,11 @@ public abstract class AbstractJpaNamedEntity extends AbstractJpaTenantAwareBaseE return name; } - public void setDescription(final String description) { - this.description = description; - } - public void setName(final String name) { this.name = name; } + + public void setDescription(final String description) { + this.description = description; + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaNamedVersionedEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaNamedVersionedEntity.java index b44ef2223..17dea311b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaNamedVersionedEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaNamedVersionedEntity.java @@ -19,13 +19,13 @@ import org.eclipse.hawkbit.repository.model.NamedVersionedEntity; /** * Extension for {@link NamedEntity} that are versioned. - * */ @MappedSuperclass // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // sub entities @SuppressWarnings("squid:S2160") public abstract class AbstractJpaNamedVersionedEntity extends AbstractJpaNamedEntity implements NamedVersionedEntity { + private static final long serialVersionUID = 1L; @Column(name = "version", nullable = false, length = NamedVersionedEntity.VERSION_MAX_SIZE) @@ -36,10 +36,8 @@ public abstract class AbstractJpaNamedVersionedEntity extends AbstractJpaNamedEn /** * parameterized constructor. * - * @param name - * of the entity - * @param version - * of the entity + * @param name of the entity + * @param version of the entity * @param description */ AbstractJpaNamedVersionedEntity(final String name, final String version, final String description) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaTenantAwareBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaTenantAwareBaseEntity.java index 9c4cebd5d..734b2cfff 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaTenantAwareBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaTenantAwareBaseEntity.java @@ -25,12 +25,12 @@ import org.eclipse.persistence.annotations.TenantDiscriminatorColumn; /** * Holder of the base attributes common to all tenant aware entities. - * */ @MappedSuperclass @TenantDiscriminatorColumn(name = "tenant", length = 40) @Multitenant(MultitenantType.SINGLE_TABLE) public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEntity implements TenantAwareBaseEntity { + private static final long serialVersionUID = 1L; @Column(name = "tenant", nullable = false, insertable = false, updatable = false, length = 40) @@ -45,24 +45,6 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn // Default constructor needed for JPA entities. } - /** - * PrePersist listener method for all {@link TenantAwareBaseEntity} - * entities. - */ - @PrePersist - void prePersist() { - // before persisting the entity check the current ID of the tenant by - // using the TenantAware - // service - final String currentTenant = SystemManagementHolder.getInstance().currentTenant(); - if (currentTenant == null) { - throw new TenantNotExistException("Tenant " - + TenantAwareHolder.getInstance().getTenantAware().getCurrentTenant() - + " does not exists, cannot create entity " + this.getClass() + " with id " + super.getId()); - } - setTenant(currentTenant.toUpperCase()); - } - @Override public String getTenant() { return tenant; @@ -72,17 +54,12 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn this.tenant = tenant; } - @Override - public String toString() { - return "BaseEntity [id=" + super.getId() + "]"; - } - /** * Tenant aware entities extend the equals/hashcode strategy with the tenant * name. That would allow for instance in a multi-schema based data * separation setup to have the same primary key for different entities of * different tenants. - * + * * @see org.eclipse.hawkbit.repository.model.BaseEntity#hashCode() */ @Override @@ -98,7 +75,7 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn * name. That would allow for instance in a multi-schema based data * separation setup to have the same primary key for different entities of * different tenants. - * + * * @see org.eclipse.hawkbit.repository.model.BaseEntity#equals(java.lang.Object) */ @Override @@ -119,4 +96,27 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn return true; } + @Override + public String toString() { + return "BaseEntity [id=" + super.getId() + "]"; + } + + /** + * PrePersist listener method for all {@link TenantAwareBaseEntity} + * entities. + */ + @PrePersist + void prePersist() { + // before persisting the entity check the current ID of the tenant by + // using the TenantAware + // service + final String currentTenant = SystemManagementHolder.getInstance().currentTenant(); + if (currentTenant == null) { + throw new TenantNotExistException("Tenant " + + TenantAwareHolder.getInstance().getTenantAware().getCurrentTenant() + + " does not exists, cannot create entity " + this.getClass() + " with id " + super.getId()); + } + setTenant(currentTenant.toUpperCase()); + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaTypeEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaTypeEntity.java index b42d9b7e1..7d2b757ff 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaTypeEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaTypeEntity.java @@ -9,14 +9,15 @@ */ package org.eclipse.hawkbit.repository.jpa.model; -import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; -import org.eclipse.hawkbit.repository.model.Type; +import java.io.Serial; import jakarta.persistence.Column; import jakarta.persistence.MappedSuperclass; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import java.io.Serial; + +import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; +import org.eclipse.hawkbit.repository.model.Type; /** * {@link TenantAwareBaseEntity} extension for all entities that are named in @@ -49,10 +50,8 @@ public abstract class AbstractJpaTypeEntity extends AbstractJpaNamedEntity imple /** * Parameterized constructor. * - * @param key - * of the {@link Type} - * @param colour - * of the {@link Type} + * @param key of the {@link Type} + * @param colour of the {@link Type} */ AbstractJpaTypeEntity(final String name, final String description, final String key, final String colour) { super(name, description); @@ -70,11 +69,11 @@ public abstract class AbstractJpaTypeEntity extends AbstractJpaNamedEntity imple return colour; } - public void setKey(final String key) { - this.key = key; - } - public void setColour(final String colour) { this.colour = colour; } + + public void setKey(final String key) { + this.key = key; + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java index fa26d81bc..d89097cb8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java @@ -30,11 +30,11 @@ import org.eclipse.persistence.annotations.CascadeOnDelete; /** * Relation element between a {@link DistributionSetType} and its * {@link SoftwareModuleType} elements. - * */ @Entity @Table(name = "sp_ds_type_element") public class DistributionSetTypeElement implements Serializable { + private static final long serialVersionUID = 1L; @EmbeddedId @@ -62,13 +62,10 @@ public class DistributionSetTypeElement implements Serializable { /** * Standard constructor. * - * @param dsType - * of the element - * @param smType - * of the element - * @param mandatory - * to true if the {@link SoftwareModuleType} if - * mandatory element in the {@link DistributionSet}. + * @param dsType of the element + * @param smType of the element + * @param mandatory to true if the {@link SoftwareModuleType} if + * mandatory element in the {@link DistributionSet}. */ DistributionSetTypeElement(final JpaDistributionSetType dsType, final JpaSoftwareModuleType smType, final boolean mandatory) { @@ -78,15 +75,15 @@ public class DistributionSetTypeElement implements Serializable { this.mandatory = mandatory; } + public boolean isMandatory() { + return mandatory; + } + DistributionSetTypeElement setMandatory(final boolean mandatory) { this.mandatory = mandatory; return this; } - public boolean isMandatory() { - return mandatory; - } - public DistributionSetType getDsType() { return dsType; } @@ -99,11 +96,6 @@ public class DistributionSetTypeElement implements Serializable { return key; } - @Override - public String toString() { - return "DistributionSetTypeElement [mandatory=" + mandatory + ", dsType=" + dsType + ", smType=" + smType + "]"; - } - @Override public int hashCode() { final int prime = 31; @@ -134,4 +126,9 @@ public class DistributionSetTypeElement implements Serializable { return true; } + @Override + public String toString() { + return "DistributionSetTypeElement [mandatory=" + mandatory + ", dsType=" + dsType + ", smType=" + smType + "]"; + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElementCompositeKey.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElementCompositeKey.java index 532428a85..fca65bd84 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElementCompositeKey.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElementCompositeKey.java @@ -19,6 +19,7 @@ import jakarta.persistence.Embeddable; */ @Embeddable public class DistributionSetTypeElementCompositeKey implements Serializable { + private static final long serialVersionUID = 1L; @Column(name = "distribution_set_type", nullable = false, updatable = false) @@ -36,10 +37,8 @@ public class DistributionSetTypeElementCompositeKey implements Serializable { /** * Constructor. * - * @param dsType - * in the key - * @param smType - * in the key + * @param dsType in the key + * @param smType in the key */ DistributionSetTypeElementCompositeKey(final JpaDistributionSetType dsType, final JpaSoftwareModuleType smType) { this.dsType = dsType.getId(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DsMetadataCompositeKey.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DsMetadataCompositeKey.java index fc36b073b..cad6d0c92 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DsMetadataCompositeKey.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DsMetadataCompositeKey.java @@ -14,9 +14,9 @@ import java.io.Serializable; /** * The DistributionSet Metadata composite key which contains the meta data key * and the ID of the DistributionSet itself. - * */ public final class DsMetadataCompositeKey implements Serializable { + private static final long serialVersionUID = 1L; private String key; @@ -28,10 +28,8 @@ public final class DsMetadataCompositeKey implements Serializable { } /** - * @param distributionSet - * the distribution set for this meta data - * @param key - * the key of the meta data + * @param distributionSet the distribution set for this meta data + * @param key the key of the meta data */ public DsMetadataCompositeKey(final Long distributionSet, final String key) { this.distributionSet = distributionSet; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListener.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListener.java index 327749e6c..892d1b38b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListener.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListener.java @@ -31,8 +31,7 @@ public class EntityInterceptorListener { /** * Callback for lifecyle event pre persist. * - * @param entity - * the JPA entity which this listener is associated with + * @param entity the JPA entity which this listener is associated with */ @PrePersist public void prePersist(final Object entity) { @@ -42,8 +41,7 @@ public class EntityInterceptorListener { /** * Callback for lifecyle event post persist. * - * @param entity - * the JPA entity which this listener is associated with + * @param entity the JPA entity which this listener is associated with */ @PostPersist public void postPersist(final Object entity) { @@ -53,8 +51,7 @@ public class EntityInterceptorListener { /** * Callback for lifecyle event post remove. * - * @param entity - * the JPA entity which this listener is associated with + * @param entity the JPA entity which this listener is associated with */ @PostRemove public void postRemove(final Object entity) { @@ -64,8 +61,7 @@ public class EntityInterceptorListener { /** * Callback for lifecyle event pre remove. * - * @param entity - * the JPA entity which this listener is associated with + * @param entity the JPA entity which this listener is associated with */ @PreRemove public void preRemove(final Object entity) { @@ -75,8 +71,7 @@ public class EntityInterceptorListener { /** * Callback for lifecyle event post load. * - * @param entity - * the JPA entity which this listener is associated with + * @param entity the JPA entity which this listener is associated with */ @PostLoad public void postLoad(final Object entity) { @@ -86,8 +81,7 @@ public class EntityInterceptorListener { /** * Callback for lifecyle event pre update. * - * @param entity - * the JPA entity which this listener is associated with + * @param entity the JPA entity which this listener is associated with */ @PreUpdate public void preUpdate(final Object entity) { @@ -97,8 +91,7 @@ public class EntityInterceptorListener { /** * Callback for lifecyle event post update. * - * @param entity - * the JPA entity which this listener is associated with + * @param entity the JPA entity which this listener is associated with */ @PostUpdate public void postUpdate(final Object entity) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java index e08e19715..208aea6cf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java @@ -17,10 +17,17 @@ import org.eclipse.persistence.queries.UpdateObjectQuery; /** * Listens to change in property values of an entity and calls the corresponding * {@link EventAwareEntity}. - * */ public class EntityPropertyChangeListener extends DescriptorEventAdapter { + @Override + public void postDelete(final DescriptorEvent event) { + final Object object = event.getObject(); + if (isEventAwareEntity(object)) { + doNotifiy(() -> ((EventAwareEntity) object).fireDeleteEvent(event)); + } + } + @Override public void postInsert(final DescriptorEvent event) { final Object object = event.getObject(); @@ -40,14 +47,6 @@ public class EntityPropertyChangeListener extends DescriptorEventAdapter { } - @Override - public void postDelete(final DescriptorEvent event) { - final Object object = event.getObject(); - if (isEventAwareEntity(object)) { - doNotifiy(() -> ((EventAwareEntity) object).fireDeleteEvent(event)); - } - } - private static boolean isEventAwareEntity(final Object object) { return object instanceof EventAwareEntity; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java index 9fe2b382d..e89fbb2f9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java @@ -22,21 +22,21 @@ public interface EventAwareEntity { /** * Fired for the Entity creation. - * + * * @param descriptorEvent */ void fireCreateEvent(DescriptorEvent descriptorEvent); /** * Fired for the Entity updation. - * + * * @param descriptorEvent */ void fireUpdateEvent(DescriptorEvent descriptorEvent); /** * Fired for the Entity deletion. - * + * * @param descriptorEvent */ void fireDeleteEvent(DescriptorEvent descriptorEvent); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java index 0a4011d49..cdad62e7b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java @@ -67,6 +67,7 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; // sub entities @SuppressWarnings("squid:S2160") public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action, EventAwareEntity { + private static final long serialVersionUID = 1L; @ManyToOne(fetch = FetchType.LAZY, optional = false) @@ -113,7 +114,7 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio @ConversionValue(objectValue = "SCHEDULED", dataValue = "8"), @ConversionValue(objectValue = "CANCEL_REJECTED", dataValue = "9"), @ConversionValue(objectValue = "DOWNLOADED", dataValue = "10"), - @ConversionValue(objectValue = "WAIT_FOR_CONFIRMATION", dataValue = "11")}) + @ConversionValue(objectValue = "WAIT_FOR_CONFIRMATION", dataValue = "11") }) @Convert("status") @NotNull private Status status; @@ -157,10 +158,6 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio this.distributionSet = (JpaDistributionSet) distributionSet; } - public void setActive(final boolean active) { - this.active = active; - } - @Override public Status getStatus() { return status; @@ -175,8 +172,8 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio return active; } - public void setActionType(final ActionType actionType) { - this.actionType = actionType; + public void setActive(final boolean active) { + this.active = active; } @Override @@ -184,16 +181,8 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio return actionType; } - public List getActionStatus() { - if (actionStatus == null) { - return Collections.emptyList(); - } - - return Collections.unmodifiableList(actionStatus); - } - - public void setTarget(final Target target) { - this.target = (JpaTarget) target; + public void setActionType(final ActionType actionType) { + this.actionType = actionType; } @Override @@ -201,6 +190,10 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio return target; } + public void setTarget(final Target target) { + this.target = (JpaTarget) target; + } + @Override public long getForcedTime() { return forcedTime; @@ -237,35 +230,6 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio this.rollout = (JpaRollout) rollout; } - @Override - public String toString() { - return "JpaAction [distributionSet=" + distributionSet.getId() + ", version=" + getOptLockRevision() + ", id=" - + getId() + ", actionType=" + getActionType() + ", weight=" + getWeight() + ", isActive=" + isActive() - + ", createdAt=" + getCreatedAt() + ", lastModifiedAt=" + getLastModifiedAt() + ", status=" - + getStatus().name() + "]"; - } - - @Override - public void fireCreateEvent(final DescriptorEvent descriptorEvent) { - EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new ActionCreatedEvent(this, BaseEntity.getIdOrNull(target), - BaseEntity.getIdOrNull(rollout), BaseEntity.getIdOrNull(rolloutGroup), - EventPublisherHolder.getInstance().getApplicationId())); - } - - @Override - public void fireUpdateEvent(final DescriptorEvent descriptorEvent) { - EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new ActionUpdatedEvent(this, BaseEntity.getIdOrNull(target), - BaseEntity.getIdOrNull(rollout), BaseEntity.getIdOrNull(rolloutGroup), - EventPublisherHolder.getInstance().getApplicationId())); - } - - @Override - public void fireDeleteEvent(final DescriptorEvent descriptorEvent) { - // there is no action deletion - } - @Override public String getMaintenanceWindowSchedule() { return maintenanceWindowSchedule; @@ -274,8 +238,7 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio /** * Sets the maintenance schedule. * - * @param maintenanceWindowSchedule - * is a cron expression to be used for scheduling. + * @param maintenanceWindowSchedule is a cron expression to be used for scheduling. */ public void setMaintenanceWindowSchedule(final String maintenanceWindowSchedule) { this.maintenanceWindowSchedule = maintenanceWindowSchedule; @@ -289,9 +252,8 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio /** * Sets the maintenance window duration. * - * @param maintenanceWindowDuration - * is the duration of an available maintenance schedule in - * HH:mm:ss format. + * @param maintenanceWindowDuration is the duration of an available maintenance schedule in + * HH:mm:ss format. */ public void setMaintenanceWindowDuration(final String maintenanceWindowDuration) { this.maintenanceWindowDuration = maintenanceWindowDuration; @@ -305,34 +267,45 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio /** * Sets the time zone to be used for maintenance window. * - * @param maintenanceWindowTimeZone - * is the time zone specified as +/-hh:mm offset from UTC for - * example +02:00 for CET summer time and +00:00 for UTC. The - * start time of a maintenance window calculated based on the - * cron expression is relative to this time zone. + * @param maintenanceWindowTimeZone is the time zone specified as +/-hh:mm offset from UTC for + * example +02:00 for CET summer time and +00:00 for UTC. The + * start time of a maintenance window calculated based on the + * cron expression is relative to this time zone. */ public void setMaintenanceWindowTimeZone(final String maintenanceWindowTimeZone) { this.maintenanceWindowTimeZone = maintenanceWindowTimeZone; } + @Override + public String getExternalRef() { + return externalRef; + } + + @Override + public void setExternalRef(final String externalRef) { + this.externalRef = externalRef; + } + + @Override + public String getInitiatedBy() { + return initiatedBy; + } + + public void setInitiatedBy(final String initiatedBy) { + this.initiatedBy = initiatedBy; + } + + @Override + public Optional getLastActionStatusCode() { + return Optional.ofNullable(lastActionStatusCode); + } + @Override public Optional getMaintenanceWindowStartTime() { return MaintenanceScheduleHelper.getNextMaintenanceWindow(maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone); } - /** - * Returns the end time of next available or active maintenance window for - * the {@link Action} as {@link ZonedDateTime}. If a maintenance window is - * already active, the end time of currently active window is returned. - * - * @return the end time of window as { @link Optional}. - */ - private Optional getMaintenanceWindowEndTime() { - return getMaintenanceWindowStartTime() - .map(start -> start.plus(MaintenanceScheduleHelper.convertToISODuration(maintenanceWindowDuration))); - } - @Override public boolean hasMaintenanceSchedule() { return this.maintenanceWindowSchedule != null; @@ -366,35 +339,60 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio } } - @Override - public void setExternalRef(final String externalRef) { - this.externalRef = externalRef; - } - - @Override - public String getExternalRef() { - return externalRef; - } - - public void setInitiatedBy(final String initiatedBy) { - this.initiatedBy = initiatedBy; - } - - @Override - public String getInitiatedBy() { - return initiatedBy; - } - - @Override - public Optional getLastActionStatusCode() { - return Optional.ofNullable(lastActionStatusCode); + public boolean isWaitingConfirmation() { + return status == Status.WAIT_FOR_CONFIRMATION; } public void setLastActionStatusCode(final Integer lastActionStatusCode) { this.lastActionStatusCode = lastActionStatusCode; } - public boolean isWaitingConfirmation() { - return status == Status.WAIT_FOR_CONFIRMATION; + public List getActionStatus() { + if (actionStatus == null) { + return Collections.emptyList(); + } + + return Collections.unmodifiableList(actionStatus); + } + + @Override + public String toString() { + return "JpaAction [distributionSet=" + distributionSet.getId() + ", version=" + getOptLockRevision() + ", id=" + + getId() + ", actionType=" + getActionType() + ", weight=" + getWeight() + ", isActive=" + isActive() + + ", createdAt=" + getCreatedAt() + ", lastModifiedAt=" + getLastModifiedAt() + ", status=" + + getStatus().name() + "]"; + } + + @Override + public void fireCreateEvent(final DescriptorEvent descriptorEvent) { + EventPublisherHolder.getInstance().getEventPublisher() + .publishEvent(new ActionCreatedEvent(this, BaseEntity.getIdOrNull(target), + BaseEntity.getIdOrNull(rollout), BaseEntity.getIdOrNull(rolloutGroup), + EventPublisherHolder.getInstance().getApplicationId())); + } + + @Override + public void fireUpdateEvent(final DescriptorEvent descriptorEvent) { + EventPublisherHolder.getInstance().getEventPublisher() + .publishEvent(new ActionUpdatedEvent(this, BaseEntity.getIdOrNull(target), + BaseEntity.getIdOrNull(rollout), BaseEntity.getIdOrNull(rolloutGroup), + EventPublisherHolder.getInstance().getApplicationId())); + } + + @Override + public void fireDeleteEvent(final DescriptorEvent descriptorEvent) { + // there is no action deletion + } + + /** + * Returns the end time of next available or active maintenance window for + * the {@link Action} as {@link ZonedDateTime}. If a maintenance window is + * already active, the end time of currently active window is returned. + * + * @return the end time of window as { @link Optional}. + */ + private Optional getMaintenanceWindowEndTime() { + return getMaintenanceWindowStartTime() + .map(start -> start.plus(MaintenanceScheduleHelper.convertToISODuration(maintenanceWindowDuration))); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java index 42fa2a10c..0ba275a4d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java @@ -14,7 +14,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; - import jakarta.persistence.CollectionTable; import jakarta.persistence.Column; import jakarta.persistence.ConstraintMode; @@ -50,6 +49,7 @@ import org.eclipse.persistence.annotations.ObjectTypeConverter; // sub entities @SuppressWarnings("squid:S2160") public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements ActionStatus { + private static final int MESSAGE_ENTRY_LENGTH = 512; private static final long serialVersionUID = 1L; @@ -75,7 +75,7 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements @ConversionValue(objectValue = "SCHEDULED", dataValue = "8"), @ConversionValue(objectValue = "CANCEL_REJECTED", dataValue = "9"), @ConversionValue(objectValue = "DOWNLOADED", dataValue = "10"), - @ConversionValue(objectValue = "WAIT_FOR_CONFIRMATION", dataValue = "11")}) + @ConversionValue(objectValue = "WAIT_FOR_CONFIRMATION", dataValue = "11") }) @Convert("status") @NotNull private Status status; @@ -89,16 +89,13 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements @Column(name = "code", nullable = true, updatable = false) private Integer code; - + /** * Creates a new {@link ActionStatus} object. * - * @param action - * the action for this action status - * @param status - * the status for this action status - * @param occurredAt - * the occurred timestamp + * @param action the action for this action status + * @param status the status for this action status + * @param occurredAt the occurred timestamp */ public JpaActionStatus(final Action action, final Status status, final long occurredAt) { this.action = (JpaAction) action; @@ -109,14 +106,10 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements /** * Creates a new {@link ActionStatus} object. * - * @param action - * the action for this action status - * @param status - * the status for this action status - * @param occurredAt - * the occurred timestamp - * @param message - * the message which should be added to this action status + * @param action the action for this action status + * @param status the status for this action status + * @param occurredAt the occurred timestamp + * @param message the message which should be added to this action status */ public JpaActionStatus(final JpaAction action, final Status status, final long occurredAt, final String message) { this.action = action; @@ -128,10 +121,8 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements /** * Creates a new {@link ActionStatus} object. * - * @param status - * the status for this action status - * @param occurredAt - * the occurred timestamp + * @param status the status for this action status + * @param occurredAt the occurred timestamp */ public JpaActionStatus(final Status status, final long occurredAt) { this.status = status; @@ -154,36 +145,6 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements this.occurredAt = occurredAt; } - public final void addMessage(final String message) { - if (message != null) { - if (messages == null) { - messages = new ArrayList<>((message.length() / MESSAGE_ENTRY_LENGTH) + 1); - } - if (message.length() > MESSAGE_ENTRY_LENGTH) { - // split - for (int off = 0; off < message.length();) { - final int end = off + MESSAGE_ENTRY_LENGTH; - if (end < message.length()) { - messages.add(message.substring(off, end)); - } else { - messages.add(message.substring(off)); - } - off = end; - } - } else { - messages.add(message); - } - } - } - - public List getMessages() { - if (messages == null) { - messages = Collections.emptyList(); - } - - return Collections.unmodifiableList(messages); - } - @Override public Action getAction() { return action; @@ -209,4 +170,34 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements public void setCode(final Integer code) { this.code = code; } + + public final void addMessage(final String message) { + if (message != null) { + if (messages == null) { + messages = new ArrayList<>((message.length() / MESSAGE_ENTRY_LENGTH) + 1); + } + if (message.length() > MESSAGE_ENTRY_LENGTH) { + // split + for (int off = 0; off < message.length(); ) { + final int end = off + MESSAGE_ENTRY_LENGTH; + if (end < message.length()) { + messages.add(message.substring(off, end)); + } else { + messages.add(message.substring(off)); + } + off = end; + } + } else { + messages.add(message); + } + } + } + + public List getMessages() { + if (messages == null) { + messages = Collections.emptyList(); + } + + return Collections.unmodifiableList(messages); + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java index 1caee1b90..52ac0478c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java @@ -29,7 +29,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; /** * JPA implementation of {@link Artifact}. - * */ @Table(name = "sp_artifact", indexes = { @Index(name = "sp_idx_artifact_01", columnList = "tenant,software_module"), @Index(name = "sp_idx_artifact_02", columnList = "tenant,sha1_hash"), @@ -39,6 +38,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; // sub entities @SuppressWarnings("squid:S2160") public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Artifact { + private static final long serialVersionUID = 1L; @Column(name = "sha1_hash", length = 40, nullable = false, updatable = false) @@ -74,12 +74,9 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art /** * Constructs artifact. * - * @param sha1Hash - * that is the link to the {@link AbstractDbArtifact} entity. - * @param filename - * that is used by {@link AbstractDbArtifact} store. - * @param softwareModule - * of this artifact + * @param sha1Hash that is the link to the {@link AbstractDbArtifact} entity. + * @param filename that is used by {@link AbstractDbArtifact} store. + * @param softwareModule of this artifact */ public JpaArtifact(@NotEmpty final String sha1Hash, @NotNull final String filename, final SoftwareModule softwareModule) { @@ -89,6 +86,16 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art this.softwareModule.addArtifact(this); } + @Override + public String getFilename() { + return filename; + } + + @Override + public SoftwareModule getSoftwareModule() { + return softwareModule; + } + @Override public String getMd5Hash() { return md5Hash; @@ -104,19 +111,10 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art return sha256Hash; } - public void setMd5Hash(final String md5Hash) { - this.md5Hash = md5Hash; - } - - public void setSha1Hash(final String sha1Hash) { - this.sha1Hash = sha1Hash; - } - public void setSha256Hash(final String sha256Hash) { this.sha256Hash = sha256Hash; } - @Override public long getSize() { return size; @@ -126,13 +124,11 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art this.size = size; } - @Override - public SoftwareModule getSoftwareModule() { - return softwareModule; + public void setSha1Hash(final String sha1Hash) { + this.sha1Hash = sha1Hash; } - @Override - public String getFilename() { - return filename; + public void setMd5Hash(final String md5Hash) { + this.md5Hash = md5Hash; } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAutoConfirmationStatus.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAutoConfirmationStatus.java index dcac51fd8..fef648450 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAutoConfirmationStatus.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAutoConfirmationStatus.java @@ -9,11 +9,6 @@ */ package org.eclipse.hawkbit.repository.jpa.model; -import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus; -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.Target; -import org.springframework.util.StringUtils; - import jakarta.persistence.Column; import jakarta.persistence.ConstraintMode; import jakarta.persistence.Entity; @@ -24,6 +19,11 @@ import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import jakarta.validation.constraints.Size; +import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus; +import org.eclipse.hawkbit.repository.model.NamedEntity; +import org.eclipse.hawkbit.repository.model.Target; +import org.springframework.util.StringUtils; + @Entity @Table(name = "sp_target_conf_status") public class JpaAutoConfirmationStatus extends AbstractJpaTenantAwareBaseEntity implements AutoConfirmationStatus { @@ -81,11 +81,11 @@ public class JpaAutoConfirmationStatus extends AbstractJpaTenantAwareBaseEntity // https://docs.oracle.com/en/java/javase/17/text-blocks/index.html#normalization-of-line-terminators // nevertheless of the end of line of the file (\r\n, \n or \r) the result will contains \n return """ - Assignment automatically confirmed by initiator '%s'.\040 - - Auto confirmation activated by system user: '%s'\040 - - Remark: %s""".formatted(formattedInitiator, createdByRolloutsUser, remarkMessage); + Assignment automatically confirmed by initiator '%s'.\040 + + Auto confirmation activated by system user: '%s'\040 + + Remark: %s""".formatted(formattedInitiator, createdByRolloutsUser, remarkMessage); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java index fe1d7f6ea..54dd3d705 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java @@ -67,8 +67,8 @@ import org.springframework.context.ApplicationEvent; @Entity @Table(name = "sp_distribution_set", uniqueConstraints = { @UniqueConstraint(columnNames = { "name", "version", "tenant" }, name = "uk_distrib_set") }, indexes = { - @Index(name = "sp_idx_distribution_set_01", columnList = "tenant,deleted,complete"), - @Index(name = "sp_idx_distribution_set_prim", columnList = "tenant,id") }) + @Index(name = "sp_idx_distribution_set_01", columnList = "tenant,deleted,complete"), + @Index(name = "sp_idx_distribution_set_prim", columnList = "tenant,id") }) @NamedEntityGraph(name = "DistributionSet.detail", attributeNodes = { @NamedAttributeNode("modules"), @NamedAttributeNode("tags"), @NamedAttributeNode("type") }) // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for @@ -90,7 +90,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen @ManyToMany(targetEntity = JpaSoftwareModule.class, fetch = FetchType.LAZY) @JoinTable(name = "sp_ds_module", joinColumns = { @JoinColumn(name = "ds_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_ds")) }, inverseJoinColumns = { - @JoinColumn(name = "module_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_module")) }) + @JoinColumn(name = "module_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_module")) }) private Set modules; @CascadeOnDelete @@ -284,18 +284,6 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen EventPublisherHolder.getInstance().getApplicationId())); } - private void checkTypeCompatability(final SoftwareModule softwareModule) { - // we cannot allow that modules are added without a type defined - if (type == null) { - throw new DistributionSetTypeUndefinedException(); - } - - // check if it is allowed to such a module to this DS type - if (!type.containsModuleType(softwareModule.getType())) { - throw new UnsupportedSoftwareModuleForThisDistributionSetException(); - } - } - private static void publishEventWithEventPublisher(final ApplicationEvent event) { EventPublisherHolder.getInstance().getEventPublisher().publishEvent(event); } @@ -309,4 +297,16 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute()) && Boolean.parseBoolean(changeRecord.getNewValue().toString())); } + + private void checkTypeCompatability(final SoftwareModule softwareModule) { + // we cannot allow that modules are added without a type defined + if (type == null) { + throw new DistributionSetTypeUndefinedException(); + } + + // check if it is allowed to such a module to this DS type + if (!type.containsModuleType(softwareModule.getType())) { + throw new UnsupportedSoftwareModuleForThisDistributionSetException(); + } + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetMetadata.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetMetadata.java index 02f9f7067..bd3a175c9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetMetadata.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetMetadata.java @@ -24,12 +24,12 @@ import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; /** * Meta data for {@link DistributionSet}. - * */ @IdClass(DsMetadataCompositeKey.class) @Entity @Table(name = "sp_ds_metadata") public class JpaDistributionSetMetadata extends AbstractJpaMetaData implements DistributionSetMetadata { + private static final long serialVersionUID = 1L; @Id @@ -54,15 +54,15 @@ public class JpaDistributionSetMetadata extends AbstractJpaMetaData implements D return new DsMetadataCompositeKey(distributionSet.getId(), getKey()); } - public void setDistributionSet(final DistributionSet distributionSet) { - this.distributionSet = (JpaDistributionSet) distributionSet; - } - @Override public DistributionSet getDistributionSet() { return distributionSet; } + public void setDistributionSet(final DistributionSet distributionSet) { + this.distributionSet = (JpaDistributionSet) distributionSet; + } + @Override public int hashCode() { final int prime = 31; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetTag.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetTag.java index dff7b327a..3235111e1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetTag.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetTag.java @@ -9,7 +9,6 @@ */ package org.eclipse.hawkbit.repository.jpa.model; -import java.util.Collections; import java.util.List; import jakarta.persistence.Entity; @@ -31,14 +30,14 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; /** * A {@link DistributionSetTag} is used to describe DistributionSet attributes * and use them also for filtering the DistributionSet list. - * */ @Entity @Table(name = "sp_distributionset_tag", indexes = { @Index(name = "sp_idx_distribution_set_tag_prim", columnList = "tenant,id"), @Index(name = "sp_idx_distribution_set_tag_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { - "name", "tenant" }, name = "uk_ds_tag")) + "name", "tenant" }, name = "uk_ds_tag")) public class JpaDistributionSetTag extends JpaTag implements DistributionSetTag, EventAwareEntity { + private static final long serialVersionUID = 1L; @CascadeOnDelete @@ -48,12 +47,9 @@ public class JpaDistributionSetTag extends JpaTag implements DistributionSetTag, /** * Public constructor. * - * @param name - * of the {@link DistributionSetTag} - * @param description - * of the {@link DistributionSetTag} - * @param colour - * of tag in UI + * @param name of the {@link DistributionSetTag} + * @param description of the {@link DistributionSetTag} + * @param colour of tag in UI */ public JpaDistributionSetTag(final String name, final String description, final String colour) { super(name, description, colour); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java index afdfda967..2adde365f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java @@ -9,6 +9,24 @@ */ package org.eclipse.hawkbit.repository.jpa.model; +import java.io.Serial; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; + import org.eclipse.hawkbit.repository.event.remote.DistributionSetTypeDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTypeCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTypeUpdatedEvent; @@ -22,34 +40,16 @@ import org.eclipse.persistence.annotations.CascadeOnDelete; import org.eclipse.persistence.descriptors.DescriptorEvent; import org.springframework.util.CollectionUtils; -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.Index; -import jakarta.persistence.ManyToMany; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; -import java.io.Serial; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - /** * A distribution set type defines which software module types can or have to be * {@link DistributionSet}. - * */ @Entity @Table(name = "sp_distribution_set_type", indexes = { @Index(name = "sp_idx_distribution_set_type_01", columnList = "tenant,deleted"), @Index(name = "sp_idx_distribution_set_type_prim", columnList = "tenant,id") }, uniqueConstraints = { - @UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_dst_name"), - @UniqueConstraint(columnNames = { "type_key", "tenant" }, name = "uk_dst_key") }) + @UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_dst_name"), + @UniqueConstraint(columnNames = { "type_key", "tenant" }, name = "uk_dst_key") }) // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // sub entities @SuppressWarnings("squid:S2160") @@ -77,12 +77,9 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis /** * Standard constructor. * - * @param key - * of the type (unique) - * @param name - * of the type (unique) - * @param description - * of the type + * @param key of the type (unique) + * @param name of the type (unique) + * @param description of the type */ public JpaDistributionSetType(final String key, final String name, final String description) { this(key, name, description, null); @@ -91,14 +88,10 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis /** * Constructor. * - * @param key - * of the type - * @param name - * of the type - * @param description - * of the type - * @param colour - * of the type. It will be null by default + * @param key of the type + * @param name of the type + * @param description of the type + * @param colour of the type. It will be null by default */ public JpaDistributionSetType(final String key, final String name, final String description, final String colour) { super(name, description, key, colour); @@ -144,15 +137,14 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis return new HashSet<>(((JpaDistributionSetType) dsType).elements).equals(elements); } - private boolean isOneModuleListEmpty(final DistributionSetType dsType) { - return (!CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements) - && CollectionUtils.isEmpty(elements)) - || (CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements) - && !CollectionUtils.isEmpty(elements)); - } - - private boolean areBothModuleListsEmpty(final DistributionSetType dsType) { - return CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements) && CollectionUtils.isEmpty(elements); + @Override + public boolean checkComplete(final DistributionSet distributionSet) { + final List smTypes = distributionSet.getModules().stream().map(SoftwareModule::getType) + .distinct().collect(Collectors.toList()); + if (smTypes.isEmpty()) { + return false; + } + return smTypes.containsAll(getMandatoryModuleTypes()); } public JpaDistributionSetType addOptionalModuleType(final SoftwareModuleType smType) { @@ -163,26 +155,6 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis return setModuleType(smType, true); } - private JpaDistributionSetType setModuleType(final SoftwareModuleType smType, final boolean mandatory) { - if (elements == null) { - elements = new HashSet<>(); - elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory)); - return this; - } - - // check if this was in the list before before - final Optional existing = elements.stream() - .filter(element -> element.getSmType().getKey().equals(smType.getKey())).findAny(); - - if (existing.isPresent()) { - existing.get().setMandatory(mandatory); - } else { - elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory)); - } - - return this; - } - public JpaDistributionSetType removeModuleType(final Long smTypeId) { if (elements == null) { return this; @@ -195,16 +167,6 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis return this; } - @Override - public boolean checkComplete(final DistributionSet distributionSet) { - final List smTypes = distributionSet.getModules().stream().map(SoftwareModule::getType) - .distinct().collect(Collectors.toList()); - if (smTypes.isEmpty()) { - return false; - } - return smTypes.containsAll(getMandatoryModuleTypes()); - } - public Set getElements() { if (elements == null) { return Collections.emptySet(); @@ -235,4 +197,35 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new DistributionSetTypeDeletedEvent( getTenant(), getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId())); } + + private boolean isOneModuleListEmpty(final DistributionSetType dsType) { + return (!CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements) + && CollectionUtils.isEmpty(elements)) + || (CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements) + && !CollectionUtils.isEmpty(elements)); + } + + private boolean areBothModuleListsEmpty(final DistributionSetType dsType) { + return CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements) && CollectionUtils.isEmpty(elements); + } + + private JpaDistributionSetType setModuleType(final SoftwareModuleType smType, final boolean mandatory) { + if (elements == null) { + elements = new HashSet<>(); + elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory)); + return this; + } + + // check if this was in the list before before + final Optional existing = elements.stream() + .filter(element -> element.getSmType().getKey().equals(smType.getKey())).findAny(); + + if (existing.isPresent()) { + existing.get().setMandatory(mandatory); + } else { + elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory)); + } + + return this; + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java index 4f9d0e7e5..895657498 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java @@ -52,7 +52,6 @@ import org.eclipse.persistence.sessions.changesets.ObjectChangeSet; /** * JPA implementation of a {@link Rollout}. - * */ @Entity @Table(name = "sp_rollout", uniqueConstraints = @UniqueConstraint(columnNames = { "name", @@ -149,6 +148,62 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event @Transient private transient TotalTargetCountStatus totalTargetCountStatus; + public List getRolloutGroups() { + if (rolloutGroups == null) { + return Collections.emptyList(); + } + + return Collections.unmodifiableList(rolloutGroups); + } + + public long getLastCheck() { + return lastCheck; + } + + public void setLastCheck(final long lastCheck) { + this.lastCheck = lastCheck; + } + + // dynamic is null only for old rollouts - could be used for distinguishing + // old once from the other + public boolean isNewStyleTargetPercent() { + return dynamic != null; + } + + @Override + public String toString() { + return "Rollout [ targetFilterQuery=" + targetFilterQuery + ", distributionSet=" + distributionSet + ", status=" + + status + ", lastCheck=" + lastCheck + ", getName()=" + getName() + ", getId()=" + getId() + "]"; + } + + @Override + public void fireCreateEvent(final DescriptorEvent descriptorEvent) { + EventPublisherHolder.getInstance().getEventPublisher() + .publishEvent(new RolloutCreatedEvent(this, EventPublisherHolder.getInstance().getApplicationId())); + } + + @Override + public void fireUpdateEvent(final DescriptorEvent descriptorEvent) { + EventPublisherHolder.getInstance().getEventPublisher() + .publishEvent(new RolloutUpdatedEvent(this, EventPublisherHolder.getInstance().getApplicationId())); + + if (isSoftDeleted(descriptorEvent)) { + EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new RolloutDeletedEvent(getTenant(), + getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId())); + } + } + + @Override + public void fireDeleteEvent(final DescriptorEvent descriptorEvent) { + EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new RolloutDeletedEvent(getTenant(), + getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId())); + } + + @Override + public boolean isDeleted() { + return deleted; + } + @Override public DistributionSet getDistributionSet() { return distributionSet; @@ -158,14 +213,6 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event this.distributionSet = (JpaDistributionSet) distributionSet; } - public List getRolloutGroups() { - if (rolloutGroups == null) { - return Collections.emptyList(); - } - - return Collections.unmodifiableList(rolloutGroups); - } - @Override public String getTargetFilterQuery() { return targetFilterQuery; @@ -184,23 +231,6 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event this.status = status; } - public long getLastCheck() { - return lastCheck; - } - - public void setLastCheck(final long lastCheck) { - this.lastCheck = lastCheck; - } - - @Override - public Long getStartAt() { - return startAt; - } - - public void setStartAt(final Long startAt) { - this.startAt = startAt; - } - @Override public ActionType getActionType() { return actionType; @@ -215,40 +245,13 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event return forcedTime; } - public void setForcedTime(final long forcedTime) { - this.forcedTime = forcedTime; - } - @Override - public Optional getWeight() { - return Optional.ofNullable(weight); + public Long getStartAt() { + return startAt; } - public void setWeight(final Integer weight) { - this.weight = weight; - } - - @Override - public boolean isDynamic() { - return Boolean.TRUE.equals(dynamic); - } - - public void setDynamic(final Boolean dynamic) { - this.dynamic = dynamic; - } - - // dynamic is null only for old rollouts - could be used for distinguishing - // old once from the other - public boolean isNewStyleTargetPercent() { - return dynamic != null; - } - - public Optional getAccessControlContext() { - return Optional.ofNullable(accessControlContext); - } - - public void setAccessControlContext(final String accessControlContext) { - this.accessControlContext = accessControlContext; + public void setStartAt(final Long startAt) { + this.startAt = startAt; } @Override @@ -281,54 +284,6 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event this.totalTargetCountStatus = totalTargetCountStatus; } - @Override - public String toString() { - return "Rollout [ targetFilterQuery=" + targetFilterQuery + ", distributionSet=" + distributionSet + ", status=" - + status + ", lastCheck=" + lastCheck + ", getName()=" + getName() + ", getId()=" + getId() + "]"; - } - - @Override - public void fireCreateEvent(final DescriptorEvent descriptorEvent) { - EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new RolloutCreatedEvent(this, EventPublisherHolder.getInstance().getApplicationId())); - } - - @Override - public void fireUpdateEvent(final DescriptorEvent descriptorEvent) { - EventPublisherHolder.getInstance().getEventPublisher() - .publishEvent(new RolloutUpdatedEvent(this, EventPublisherHolder.getInstance().getApplicationId())); - - if (isSoftDeleted(descriptorEvent)) { - EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new RolloutDeletedEvent(getTenant(), - getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId())); - } - } - - private static boolean isSoftDeleted(final DescriptorEvent event) { - final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet(); - final List changes = changeSet.getChanges().stream() - .filter(DirectToFieldChangeRecord.class::isInstance).map(DirectToFieldChangeRecord.class::cast) - .collect(Collectors.toList()); - - return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute()) - && Boolean.parseBoolean(changeRecord.getNewValue().toString())); - } - - @Override - public void fireDeleteEvent(final DescriptorEvent descriptorEvent) { - EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new RolloutDeletedEvent(getTenant(), - getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId())); - } - - @Override - public boolean isDeleted() { - return deleted; - } - - public void setDeleted(final boolean deleted) { - this.deleted = deleted; - } - @Override public String getApprovalDecidedBy() { return approvalDecidedBy; @@ -343,7 +298,51 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event return approvalRemark; } + @Override + public Optional getWeight() { + return Optional.ofNullable(weight); + } + + public void setWeight(final Integer weight) { + this.weight = weight; + } + + @Override + public boolean isDynamic() { + return Boolean.TRUE.equals(dynamic); + } + + public void setDynamic(final Boolean dynamic) { + this.dynamic = dynamic; + } + + public Optional getAccessControlContext() { + return Optional.ofNullable(accessControlContext); + } + + public void setAccessControlContext(final String accessControlContext) { + this.accessControlContext = accessControlContext; + } + public void setApprovalRemark(final String approvalRemark) { this.approvalRemark = approvalRemark; } + + public void setForcedTime(final long forcedTime) { + this.forcedTime = forcedTime; + } + + public void setDeleted(final boolean deleted) { + this.deleted = deleted; + } + + private static boolean isSoftDeleted(final DescriptorEvent event) { + final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet(); + final List changes = changeSet.getChanges().stream() + .filter(DirectToFieldChangeRecord.class::isInstance).map(DirectToFieldChangeRecord.class::cast) + .collect(Collectors.toList()); + + return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute()) + && Boolean.parseBoolean(changeRecord.getNewValue().toString())); + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java index b17687232..8cb27b175 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java @@ -41,7 +41,6 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; /** * JPA entity definition of persisting a group of an rollout. - * */ @Entity @Table(name = "sp_rolloutgroup", uniqueConstraints = @UniqueConstraint(columnNames = { "name", "rollout", @@ -121,7 +120,7 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr @Column(name = "target_percentage") private float targetPercentage = 100; - + @Column(name = "confirmation_required") private boolean confirmationRequired; @@ -146,14 +145,6 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr this.status = status; } - public List getRolloutTargetGroup() { - if (rolloutTargetGroup == null) { - return Collections.emptyList(); - } - - return Collections.unmodifiableList(rolloutTargetGroup); - } - @Override public RolloutGroup getParent() { return parent; @@ -168,10 +159,6 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr this.dynamic = dynamic; } - public void setParent(final RolloutGroup parent) { - this.parent = (JpaRolloutGroup) parent; - } - @Override public RolloutGroupSuccessCondition getSuccessCondition() { return successCondition; @@ -245,12 +232,15 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr this.totalTargets = totalTargets; } - public void setSuccessAction(final RolloutGroupSuccessAction successAction) { - this.successAction = successAction; - } - - public void setSuccessActionExp(final String successActionExp) { - this.successActionExp = successActionExp; + /** + * @return the totalTargetCountStatus + */ + @Override + public TotalTargetCountStatus getTotalTargetCountStatus() { + if (totalTargetCountStatus == null) { + totalTargetCountStatus = new TotalTargetCountStatus(Long.valueOf(totalTargets), rollout.getActionType()); + } + return totalTargetCountStatus; } @Override @@ -267,38 +257,46 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr return targetPercentage; } - public void setConfirmationRequired(final boolean confirmationRequired) { - this.confirmationRequired = confirmationRequired; - } - @Override public boolean isConfirmationRequired() { return confirmationRequired; } + public void setConfirmationRequired(final boolean confirmationRequired) { + this.confirmationRequired = confirmationRequired; + } + public void setTargetPercentage(final float targetPercentage) { this.targetPercentage = targetPercentage; } /** - * @return the totalTargetCountStatus - */ - @Override - public TotalTargetCountStatus getTotalTargetCountStatus() { - if (totalTargetCountStatus == null) { - totalTargetCountStatus = new TotalTargetCountStatus(Long.valueOf(totalTargets), rollout.getActionType()); - } - return totalTargetCountStatus; - } - - /** - * @param totalTargetCountStatus - * the totalTargetCountStatus to set + * @param totalTargetCountStatus the totalTargetCountStatus to set */ public void setTotalTargetCountStatus(final TotalTargetCountStatus totalTargetCountStatus) { this.totalTargetCountStatus = totalTargetCountStatus; } + public void setSuccessActionExp(final String successActionExp) { + this.successActionExp = successActionExp; + } + + public void setSuccessAction(final RolloutGroupSuccessAction successAction) { + this.successAction = successAction; + } + + public void setParent(final RolloutGroup parent) { + this.parent = (JpaRolloutGroup) parent; + } + + public List getRolloutTargetGroup() { + if (rolloutTargetGroup == null) { + return Collections.emptyList(); + } + + return Collections.unmodifiableList(rolloutTargetGroup); + } + @Override public String toString() { return "RolloutGroup [rollout=" + (rollout != null ? rollout.getId() : "") + ", status=" + status diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java index 5986110c2..738f10a34 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java @@ -62,9 +62,9 @@ import org.eclipse.persistence.sessions.changesets.ObjectChangeSet; @Entity @Table(name = "sp_base_software_module", uniqueConstraints = @UniqueConstraint(columnNames = { "module_type", "name", "version", "tenant" }, name = "uk_base_sw_mod"), indexes = { - @Index(name = "sp_idx_base_sw_module_01", columnList = "tenant,deleted,name,version"), - @Index(name = "sp_idx_base_sw_module_02", columnList = "tenant,deleted,module_type"), - @Index(name = "sp_idx_base_sw_module_prim", columnList = "tenant,id") }) + @Index(name = "sp_idx_base_sw_module_01", columnList = "tenant,deleted,name,version"), + @Index(name = "sp_idx_base_sw_module_02", columnList = "tenant,deleted,module_type"), + @Index(name = "sp_idx_base_sw_module_prim", columnList = "tenant,id") }) @NamedEntityGraph(name = "SoftwareModule.artifacts", attributeNodes = { @NamedAttributeNode("artifacts") }) // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // sub entities @@ -83,7 +83,8 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement private JpaSoftwareModuleType type; @CascadeOnDelete - @OneToMany(fetch = FetchType.LAZY, mappedBy = "softwareModule", cascade = { CascadeType.PERSIST }, targetEntity = JpaArtifact.class, orphanRemoval = true) + @OneToMany(fetch = FetchType.LAZY, mappedBy = "softwareModule", cascade = { + CascadeType.PERSIST }, targetEntity = JpaArtifact.class, orphanRemoval = true) private List artifacts; @Setter @@ -191,7 +192,8 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement } sb.delete(sb.length() - 2, sb.length()); throw new LockedException(JpaSoftwareModule.class, getId(), "DELETE", sb.toString()); - }; + } + ; } this.deleted = deleted; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java index b9c992b48..daaab8a60 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java @@ -25,12 +25,12 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; /** * Metadata for {@link SoftwareModule}. - * */ @IdClass(SwMetadataCompositeKey.class) @Entity @Table(name = "sp_sw_metadata") public class JpaSoftwareModuleMetadata extends AbstractJpaMetaData implements SoftwareModuleMetadata { + private static final long serialVersionUID = 1L; @Id diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleType.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleType.java index 38e5830aa..a0ceb20ec 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleType.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleType.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.model; +import java.io.Serial; + import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Index; @@ -23,18 +25,15 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; import org.eclipse.persistence.descriptors.DescriptorEvent; -import java.io.Serial; - /** * Type of a software modules. - * */ @Entity @Table(name = "sp_software_module_type", indexes = { @Index(name = "sp_idx_software_module_type_01", columnList = "tenant,deleted"), @Index(name = "sp_idx_software_module_type_prim", columnList = "tenant,id") }, uniqueConstraints = { - @UniqueConstraint(columnNames = { "type_key", "tenant" }, name = "uk_smt_type_key"), - @UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_smt_name") }) + @UniqueConstraint(columnNames = { "type_key", "tenant" }, name = "uk_smt_type_key"), + @UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_smt_name") }) // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // sub entities @SuppressWarnings("squid:S2160") @@ -53,14 +52,10 @@ public class JpaSoftwareModuleType extends AbstractJpaTypeEntity implements Soft /** * Constructor. * - * @param key - * of the type - * @param name - * of the type - * @param description - * of the type - * @param maxAssignments - * assignments to a DS + * @param key of the type + * @param name of the type + * @param description of the type + * @param maxAssignments assignments to a DS */ public JpaSoftwareModuleType(final String key, final String name, final String description, final int maxAssignments) { @@ -70,16 +65,11 @@ public class JpaSoftwareModuleType extends AbstractJpaTypeEntity implements Soft /** * Constructor. * - * @param key - * of the type - * @param name - * of the type - * @param description - * of the type - * @param maxAssignments - * assignments to a DS - * @param colour - * of the type. It will be null by default + * @param key of the type + * @param name of the type + * @param description of the type + * @param maxAssignments assignments to a DS + * @param colour of the type. It will be null by default */ public JpaSoftwareModuleType(final String key, final String name, final String description, final int maxAssignments, final String colour) { @@ -94,15 +84,15 @@ public class JpaSoftwareModuleType extends AbstractJpaTypeEntity implements Soft // Default Constructor for JPA. } - public void setMaxAssignments(final int maxAssignments) { - this.maxAssignments = maxAssignments; - } - @Override public int getMaxAssignments() { return maxAssignments; } + public void setMaxAssignments(final int maxAssignments) { + this.maxAssignments = maxAssignments; + } + @Override public boolean isDeleted() { return deleted; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaStatistic.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaStatistic.java index 25b68c6e2..47acc8546 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaStatistic.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaStatistic.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.jpa.model; - import org.eclipse.hawkbit.repository.model.Statistic; public interface JpaStatistic extends Statistic { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTag.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTag.java index dfc8edc12..82a0e0388 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTag.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTag.java @@ -18,13 +18,13 @@ import org.eclipse.hawkbit.repository.model.Tag; /** * A Tag can be used as describing and organizational meta information for any * kind of entity. - * */ @MappedSuperclass // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // sub entities @SuppressWarnings("squid:S2160") public class JpaTag extends AbstractJpaNamedEntity implements Tag { + private static final long serialVersionUID = 1L; @Column(name = "colour", nullable = true, length = Tag.COLOUR_MAX_SIZE) @@ -38,12 +38,9 @@ public class JpaTag extends AbstractJpaNamedEntity implements Tag { /** * Public constructor. * - * @param name - * of the {@link Tag} - * @param description - * of the {@link Tag} - * @param colour - * of tag in UI + * @param name of the {@link Tag} + * @param description of the {@link Tag} + * @param colour of tag in UI */ public JpaTag(final String name, final String description, final String colour) { super(name, description); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java index 4863fbcd0..0db14927e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java @@ -77,7 +77,7 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; @Index(name = "sp_idx_target_04", columnList = "tenant,created_at"), @Index(name = "sp_idx_target_05", columnList = "tenant,last_modified_at"), @Index(name = "sp_idx_target_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = { - "controller_id", "tenant" }, name = "uk_tenant_controller_id")) + "controller_id", "tenant" }, name = "uk_tenant_controller_id")) // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // sub entities @SuppressWarnings("squid:S2160") @@ -218,91 +218,25 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw return assignedDistributionSet; } + /** + * @param assignedDistributionSet Distribution set + */ + public void setAssignedDistributionSet(final DistributionSet assignedDistributionSet) { + this.assignedDistributionSet = (JpaDistributionSet) assignedDistributionSet; + } + @Override public String getControllerId() { return controllerId; } /** - * @return tags - */ - public Set getTags() { - if (tags == null) { - return Collections.emptySet(); - } - - return Collections.unmodifiableSet(tags); - } - - /** - * @return rollouts target group - */ - public List getRolloutTargetGroup() { - if (rolloutTargetGroup == null) { - return Collections.emptyList(); - } - return Collections.unmodifiableList(rolloutTargetGroup); - } - - /** - * @param tag - * to be added - */ - public void addTag(final TargetTag tag) { - if (tags == null) { - tags = new HashSet<>(); - } - tags.add(tag); - } - - /** - * @param tag - * the tag to be removed from the target - */ - public void removeTag(final TargetTag tag) { - if (tags != null) { - tags.remove(tag); - } - } - - /** - * @param assignedDistributionSet - * Distribution set - */ - public void setAssignedDistributionSet(final DistributionSet assignedDistributionSet) { - this.assignedDistributionSet = (JpaDistributionSet) assignedDistributionSet; - } - - /** - * @param controllerId - * Controller ID + * @param controllerId Controller ID */ public void setControllerId(final String controllerId) { this.controllerId = controllerId; } - /** - * @return list of action - */ - public List getActions() { - if (actions == null) { - return Collections.emptyList(); - } - - return Collections.unmodifiableList(actions); - } - - /** - * @param action - * Action - */ - public void addAction(final Action action) { - if (actions == null) { - actions = new ArrayList<>(); - } - actions.add((JpaAction) action); - } - /** * @return the securityToken if the current security context contains the * necessary permission {@link SpPermission#READ_TARGET_SEC_TOKEN} @@ -321,8 +255,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw } /** - * @param securityToken - * token value + * @param securityToken token value */ public void setSecurityToken(final String securityToken) { this.securityToken = securityToken; @@ -344,6 +277,26 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw } } + @Override + public Long getLastTargetQuery() { + return lastTargetQuery; + } + + @Override + public Long getInstallationDate() { + return installationDate; + } + + @Override + public TargetUpdateStatus getUpdateStatus() { + return updateStatus; + } + + @Override + public TargetType getTargetType() { + return targetType; + } + /** * @return the poll time which holds the last poll time of the target, the * next poll time and the overdue time. In case the @@ -366,37 +319,117 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw } public void setAutoConfirmationStatus(final JpaAutoConfirmationStatus autoConfirmationStatus) { - this.autoConfirmationStatus = autoConfirmationStatus; + this.autoConfirmationStatus = autoConfirmationStatus; } @Override - public Long getLastTargetQuery() { - return lastTargetQuery; - } - - @Override - public Long getInstallationDate() { - return installationDate; - } - - @Override - public TargetUpdateStatus getUpdateStatus() { - return updateStatus; - } - - @Override - public TargetType getTargetType() { - return targetType; + public boolean isRequestControllerAttributes() { + return requestControllerAttributes; } /** - * @param type - * Target type + * @param requestControllerAttributes Attributes + */ + public void setRequestControllerAttributes(final boolean requestControllerAttributes) { + this.requestControllerAttributes = requestControllerAttributes; + } + + /** + * @param type Target type */ public void setTargetType(final TargetType type) { this.targetType = type; } + /** + * @param updateStatus Status + */ + public void setUpdateStatus(final TargetUpdateStatus updateStatus) { + this.updateStatus = updateStatus; + } + + /** + * @param installationDate installation date + */ + public void setInstallationDate(final Long installationDate) { + this.installationDate = installationDate; + } + + /** + * @param lastTargetQuery last query ID + */ + public void setLastTargetQuery(final Long lastTargetQuery) { + this.lastTargetQuery = lastTargetQuery; + } + + /** + * @param address Address + */ + public void setAddress(final String address) { + this.address = address; + } + + /** + * @return tags + */ + public Set getTags() { + if (tags == null) { + return Collections.emptySet(); + } + + return Collections.unmodifiableSet(tags); + } + + /** + * @return rollouts target group + */ + public List getRolloutTargetGroup() { + if (rolloutTargetGroup == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(rolloutTargetGroup); + } + + /** + * @param tag to be added + */ + public void addTag(final TargetTag tag) { + if (tags == null) { + tags = new HashSet<>(); + } + tags.add(tag); + } + + /** + * @param tag the tag to be removed from the target + */ + public void removeTag(final TargetTag tag) { + if (tags != null) { + tags.remove(tag); + } + } + + /** + * @return list of action + */ + public List getActions() { + if (actions == null) { + return Collections.emptyList(); + } + + return Collections.unmodifiableList(actions); + } + + /** + * @param action Action + */ + public void addAction(final Action action) { + if (actions == null) { + actions = new ArrayList<>(); + } + actions.add((JpaAction) action); + } + /** * @return Distribution set */ @@ -404,6 +437,13 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw return installedDistributionSet; } + /** + * @param installedDistributionSet Distribution set + */ + public void setInstalledDistributionSet(final JpaDistributionSet installedDistributionSet) { + this.installedDistributionSet = installedDistributionSet; + } + /** * @return controller attributes */ @@ -411,11 +451,6 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw return controllerAttributes; } - @Override - public boolean isRequestControllerAttributes() { - return requestControllerAttributes; - } - /** * @return target metadata */ @@ -433,65 +468,12 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw + "]"; } - /** - * @param address - * Address - */ - public void setAddress(final String address) { - this.address = address; - } - - /** - * @param lastTargetQuery - * last query ID - */ - public void setLastTargetQuery(final Long lastTargetQuery) { - this.lastTargetQuery = lastTargetQuery; - } - - /** - * @param installationDate - * installation date - */ - public void setInstallationDate(final Long installationDate) { - this.installationDate = installationDate; - } - - /** - * @param installedDistributionSet - * Distribution set - */ - public void setInstalledDistributionSet(final JpaDistributionSet installedDistributionSet) { - this.installedDistributionSet = installedDistributionSet; - } - - /** - * @param updateStatus - * Status - */ - public void setUpdateStatus(final TargetUpdateStatus updateStatus) { - this.updateStatus = updateStatus; - } - - /** - * @param requestControllerAttributes - * Attributes - */ - public void setRequestControllerAttributes(final boolean requestControllerAttributes) { - this.requestControllerAttributes = requestControllerAttributes; - } - @Override public void fireCreateEvent(final DescriptorEvent descriptorEvent) { EventPublisherHolder.getInstance().getEventPublisher() .publishEvent(new TargetCreatedEvent(this, EventPublisherHolder.getInstance().getApplicationId())); } - @Override - public List getUpdateIgnoreFields() { - return TARGET_UPDATE_EVENT_IGNORE_FIELDS; - } - @Override public void fireUpdateEvent(final DescriptorEvent descriptorEvent) { EventPublisherHolder.getInstance().getEventPublisher() @@ -504,4 +486,9 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw .publishEvent(new TargetDeletedEvent(getTenant(), getId(), getControllerId(), address, getClass(), EventPublisherHolder.getInstance().getApplicationId())); } + + @Override + public List getUpdateIgnoreFields() { + return TARGET_UPDATE_EVENT_IGNORE_FIELDS; + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetFilterQuery.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetFilterQuery.java index cba41b6f4..d9f894efb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetFilterQuery.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetFilterQuery.java @@ -39,7 +39,6 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; /** * Stored target filter. - * */ @Entity @Table(name = "sp_target_filter_query", uniqueConstraints = @UniqueConstraint(columnNames = { "name", @@ -49,6 +48,7 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; @SuppressWarnings("squid:S2160") public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity implements TargetFilterQuery, EventAwareEntity { + private static final long serialVersionUID = 1L; @Column(name = "name", length = NamedEntity.NAME_MAX_SIZE, nullable = false) @@ -93,19 +93,13 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity /** * Construct a Target filter query with auto assign distribution set - * - * @param name - * of the {@link TargetFilterQuery}. - * @param query - * of the {@link TargetFilterQuery}. - * @param autoAssignDistributionSet - * of the {@link TargetFilterQuery}. - * @param autoAssignActionType - * of the {@link TargetFilterQuery}. - * @param autoAssignWeight - * of the {@link TargetFilterQuery}. - * @param confirmationRequired - * of the {@link TargetFilterQuery}. + * + * @param name of the {@link TargetFilterQuery}. + * @param query of the {@link TargetFilterQuery}. + * @param autoAssignDistributionSet of the {@link TargetFilterQuery}. + * @param autoAssignActionType of the {@link TargetFilterQuery}. + * @param autoAssignWeight of the {@link TargetFilterQuery}. + * @param confirmationRequired of the {@link TargetFilterQuery}. */ public JpaTargetFilterQuery(final String name, final String query, final DistributionSet autoAssignDistributionSet, final ActionType autoAssignActionType, final Integer autoAssignWeight, final boolean confirmationRequired) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetMetadata.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetMetadata.java index 6ad53ec47..6b6167b1c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetMetadata.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetMetadata.java @@ -24,12 +24,12 @@ import org.eclipse.hawkbit.repository.model.TargetMetadata; /** * Meta data for {@link Target}. - * */ @IdClass(TargetMetadataCompositeKey.class) @Entity @Table(name = "sp_target_metadata") public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMetadata { + private static final long serialVersionUID = 1L; @Id @@ -43,11 +43,9 @@ public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMeta /** * Creates a single metadata entry with the given key and value. - * - * @param key - * of the meta data entry - * @param value - * of the meta data entry + * + * @param key of the meta data entry + * @param value of the meta data entry */ public JpaTargetMetadata(final String key, final String value) { super(key, value); @@ -56,13 +54,10 @@ public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMeta /** * Creates a single metadata entry with the given key and value for the * given {@link Target}. - * - * @param key - * of the meta data entry - * @param value - * of the meta data entry - * @param target - * the meta data entry is associated with + * + * @param key of the meta data entry + * @param value of the meta data entry + * @param target the meta data entry is associated with */ public JpaTargetMetadata(final String key, final String value, final Target target) { super(key, value); @@ -73,21 +68,13 @@ public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMeta return new TargetMetadataCompositeKey(target.getId(), getKey()); } - public void setTarget(final Target target) { - this.target = (JpaTarget) target; - } - @Override public Target getTarget() { return target; } - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((target == null) ? 0 : target.hashCode()); - return result; + public void setTarget(final Target target) { + this.target = (JpaTarget) target; } @Override @@ -107,4 +94,12 @@ public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMeta } return true; } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((target == null) ? 0 : target.hashCode()); + return result; + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetTag.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetTag.java index bea23d7d6..e19b86fd9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetTag.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetTag.java @@ -33,7 +33,7 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; @Entity @Table(name = "sp_target_tag", indexes = { @Index(name = "sp_idx_target_tag_prim", columnList = "tenant,id"), @Index(name = "sp_idx_target_tag_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { - "name", "tenant" }, name = "uk_targ_tag")) + "name", "tenant" }, name = "uk_targ_tag")) public class JpaTargetTag extends JpaTag implements TargetTag, EventAwareEntity { @Serial diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetType.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetType.java index bc56a2557..2dc324968 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetType.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetType.java @@ -9,6 +9,21 @@ */ package org.eclipse.hawkbit.repository.jpa.model; +import java.io.Serial; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import jakarta.persistence.ConstraintMode; +import jakarta.persistence.Entity; +import jakarta.persistence.ForeignKey; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; + import lombok.NoArgsConstructor; import lombok.ToString; import org.eclipse.hawkbit.repository.event.remote.TargetTypeDeletedEvent; @@ -21,22 +36,6 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; import org.eclipse.persistence.annotations.CascadeOnDelete; import org.eclipse.persistence.descriptors.DescriptorEvent; -import jakarta.persistence.ConstraintMode; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.ForeignKey; -import jakarta.persistence.Index; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.JoinTable; -import jakarta.persistence.ManyToMany; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; -import java.io.Serial; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - /** * A target type defines which distribution set types can or have to be * {@link Target}. @@ -46,7 +45,7 @@ import java.util.Set; @Entity @Table(name = "sp_target_type", indexes = { @Index(name = "sp_idx_target_type_prim", columnList = "tenant,id") }, uniqueConstraints = { - @UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_target_type_name")}) + @UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_target_type_name") }) public class JpaTargetType extends AbstractJpaTypeEntity implements TargetType, EventAwareEntity { @Serial @@ -55,8 +54,8 @@ public class JpaTargetType extends AbstractJpaTypeEntity implements TargetType, @CascadeOnDelete @ManyToMany(targetEntity = JpaDistributionSetType.class) @JoinTable(name = "sp_target_type_ds_type_relation", joinColumns = { - @JoinColumn(name = "target_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_type_relation_target_type"))}, inverseJoinColumns = { - @JoinColumn(name = "distribution_set_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_type_relation_ds_type"))}) + @JoinColumn(name = "target_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_type_relation_target_type")) }, inverseJoinColumns = { + @JoinColumn(name = "distribution_set_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_type_relation_ds_type")) }) private Set distributionSetTypes; public JpaTargetType(final String key, final String name, final String description, final String colour) { @@ -79,8 +78,18 @@ public class JpaTargetType extends AbstractJpaTypeEntity implements TargetType, return this; } + @Override + public Set getCompatibleDistributionSetTypes() { + if (distributionSetTypes == null) { + return Collections.emptySet(); + } + + return Collections.unmodifiableSet(distributionSetTypes); + } + /** * Remove a compatible distribution set type from this target type. + * * @param dsTypeId Distribution set type ID * @return Target type */ @@ -97,15 +106,6 @@ public class JpaTargetType extends AbstractJpaTypeEntity implements TargetType, return this; } - @Override - public Set getCompatibleDistributionSetTypes() { - if (distributionSetTypes == null) { - return Collections.emptySet(); - } - - return Collections.unmodifiableSet(distributionSetTypes); - } - @Override public void fireCreateEvent(final DescriptorEvent descriptorEvent) { EventPublisherHolder.getInstance().getEventPublisher().publishEvent( diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantConfiguration.java index 7c24cd299..5c8c32d79 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantConfiguration.java @@ -26,7 +26,6 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; /** * A JPA entity which stores the tenant specific configuration. - * */ @Entity @Table(name = "sp_tenant_configuration", uniqueConstraints = @UniqueConstraint(columnNames = { "conf_key", @@ -36,6 +35,7 @@ import org.eclipse.persistence.descriptors.DescriptorEvent; @SuppressWarnings("squid:S2160") public class JpaTenantConfiguration extends AbstractJpaTenantAwareBaseEntity implements TenantConfiguration, EventAwareEntity { + private static final long serialVersionUID = 1L; @Column(name = "conf_key", length = TenantConfiguration.KEY_MAX_SIZE, nullable = false, updatable = false) @@ -57,10 +57,8 @@ public class JpaTenantConfiguration extends AbstractJpaTenantAwareBaseEntity } /** - * @param key - * the key of this configuration - * @param value - * the value of this configuration + * @param key the key of this configuration + * @param value the value of this configuration */ public JpaTenantConfiguration(final String key, final String value) { this.key = key; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java index dc114efd8..0fe857863 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java @@ -33,16 +33,16 @@ import org.eclipse.hawkbit.repository.model.TenantMetaData; * through the {@link EntityManager} even before the actual tenant exists. * * Entities owned by the tenant are based on {@link TenantAwareBaseEntity}. - * */ @Table(name = "sp_tenant", indexes = { @Index(name = "sp_idx_tenant_prim", columnList = "tenant,id") }, uniqueConstraints = { - @UniqueConstraint(columnNames = { "tenant" }, name = "uk_tenantmd_tenant") }) + @UniqueConstraint(columnNames = { "tenant" }, name = "uk_tenantmd_tenant") }) @Entity // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // sub entities @SuppressWarnings("squid:S2160") public class JpaTenantMetaData extends AbstractJpaBaseEntity implements TenantMetaData { + private static final long serialVersionUID = 1L; @Column(name = "tenant", nullable = false, updatable = false, length = 40) @@ -64,8 +64,7 @@ public class JpaTenantMetaData extends AbstractJpaBaseEntity implements TenantMe /** * Standard constructor. * - * @param defaultDsType - * of this tenant + * @param defaultDsType of this tenant * @param tenant */ public JpaTenantMetaData(final DistributionSetType defaultDsType, final String tenant) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/RolloutTargetGroup.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/RolloutTargetGroup.java index 6ed92ac38..af5a57f06 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/RolloutTargetGroup.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/RolloutTargetGroup.java @@ -33,7 +33,6 @@ import org.eclipse.persistence.annotations.ExistenceType; /** * Entity with JPA annotation to store the information which {@link Target} is * in a specific {@link RolloutGroup}. - * */ @IdClass(RolloutTargetGroupId.class) @Entity diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/RolloutTargetGroupId.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/RolloutTargetGroupId.java index c7dc0ff85..169b7d1fb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/RolloutTargetGroupId.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/RolloutTargetGroupId.java @@ -16,9 +16,9 @@ import org.eclipse.hawkbit.repository.model.Target; /** * Combined unique key of the table {@link RolloutTargetGroup}. - * */ public class RolloutTargetGroupId implements Serializable { + private static final long serialVersionUID = 1L; private Long rolloutGroup; @@ -33,11 +33,9 @@ public class RolloutTargetGroupId implements Serializable { /** * Constructor. - * - * @param rolloutGroup - * the rollout group for this key - * @param target - * the target for this key + * + * @param rolloutGroup the rollout group for this key + * @param target the target for this key */ public RolloutTargetGroupId(final RolloutGroup rolloutGroup, final Target target) { this.rolloutGroup = rolloutGroup.getId(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/SwMetadataCompositeKey.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/SwMetadataCompositeKey.java index fd0aae886..90f2ca5d6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/SwMetadataCompositeKey.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/SwMetadataCompositeKey.java @@ -16,6 +16,7 @@ import java.io.Serializable; * and the ID of the software module itself. */ public final class SwMetadataCompositeKey implements Serializable { + private static final long serialVersionUID = 1L; private String key; @@ -30,10 +31,8 @@ public final class SwMetadataCompositeKey implements Serializable { } /** - * @param moduleId - * the software module for this meta data - * @param key - * the key of the meta data + * @param moduleId the software module for this meta data + * @param key the key of the meta data */ public SwMetadataCompositeKey(final Long moduleId, final String key) { this.softwareModule = moduleId; @@ -48,8 +47,7 @@ public final class SwMetadataCompositeKey implements Serializable { } /** - * @param key - * the key to set + * @param key the key to set */ public void setKey(final String key) { this.key = key; @@ -63,8 +61,7 @@ public final class SwMetadataCompositeKey implements Serializable { } /** - * @param softwareModule - * the softwareModule to set + * @param softwareModule the softwareModule to set */ public void setSoftwareModule(final Long softwareModule) { this.softwareModule = softwareModule; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/TargetMetadataCompositeKey.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/TargetMetadataCompositeKey.java index 6217bc98d..8855baae9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/TargetMetadataCompositeKey.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/TargetMetadataCompositeKey.java @@ -15,9 +15,9 @@ import java.util.Objects; /** * The Target Metadata composite key which contains the meta data key and the ID * of the Target itself. - * */ public final class TargetMetadataCompositeKey implements Serializable { + private static final long serialVersionUID = 1L; private String key; @@ -29,10 +29,8 @@ public final class TargetMetadataCompositeKey implements Serializable { } /** - * @param target - * the target Id for this meta data - * @param key - * the key of the meta data + * @param target the target Id for this meta data + * @param key the key of the meta data */ public TargetMetadataCompositeKey(final Long target, final String key) { this.target = target; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/AfterTransactionCommitExecutorHolder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/AfterTransactionCommitExecutorHolder.java index 7c922b91a..46534ba33 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/AfterTransactionCommitExecutorHolder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/AfterTransactionCommitExecutorHolder.java @@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired; * A singleton bean which holds the {@link AfterTransactionCommitExecutor} to * have to the cache manager in beans not instantiated by spring e.g. JPA * entities or {@link EntityPropertyChangeListener} which cannot be autowired. - * */ public final class AfterTransactionCommitExecutorHolder { @@ -45,8 +44,7 @@ public final class AfterTransactionCommitExecutorHolder { } /** - * @param afterCommit - * the afterCommit to set + * @param afterCommit the afterCommit to set */ public void setAfterCommit(final AfterTransactionCommitExecutor afterCommit) { this.afterCommit = afterCommit; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityInterceptorHolder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityInterceptorHolder.java index 3a990d1f7..58e570084 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityInterceptorHolder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityInterceptorHolder.java @@ -18,7 +18,6 @@ import org.springframework.beans.factory.annotation.Autowired; /** * A singleton bean which holds the {@link EntityInterceptor} to have all * interceptors in spring beans. - * */ public final class EntityInterceptorHolder { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/SecurityTokenGeneratorHolder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/SecurityTokenGeneratorHolder.java index 441487e31..3f9a7803b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/SecurityTokenGeneratorHolder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/SecurityTokenGeneratorHolder.java @@ -15,10 +15,6 @@ import org.springframework.beans.factory.annotation.Autowired; /** * A singleton bean which holds the {@link SecurityTokenGenerator} and make it * accessible to beans which are not managed by spring, e.g. JPA entities. - * - * - * - * */ public final class SecurityTokenGeneratorHolder { @@ -43,7 +39,7 @@ public final class SecurityTokenGeneratorHolder { /** * delegates to {@link SecurityTokenGenerator#generateToken()}. - * + * * @return the result {@link SecurityTokenGenerator#generateToken()} */ public String generateToken() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/TenantAwareHolder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/TenantAwareHolder.java index 1cb664fcc..7dc0c5687 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/TenantAwareHolder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/TenantAwareHolder.java @@ -15,10 +15,6 @@ import org.springframework.beans.factory.annotation.Autowired; /** * A singleton bean which holds {@link TenantAware} service and makes it * accessible to beans which are not managed by spring, e.g. JPA entities. - * - * - * - * */ public final class TenantAwareHolder { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ACMRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ACMRepository.java index 953cc0ee2..cbef72ade 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ACMRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ACMRepository.java @@ -9,6 +9,9 @@ */ package org.eclipse.hawkbit.repository.jpa.repository; +import java.util.List; +import java.util.Optional; + import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -16,9 +19,6 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; -import java.util.List; -import java.util.Optional; - /** * Repository interface that offers some actions that takes in account a target operation. * @@ -31,7 +31,7 @@ public interface ACMRepository { * check CREATE access in creating an entity (save without operation would check for UPDATE access). * * @param operation access operationIf operation is null no access is checked! Should be used - * only for tenant context. + * only for tenant context. * @param entity the entity to save * @return the saved entity */ @@ -43,7 +43,7 @@ public interface ACMRepository { * check CREATE access in creating an entity (save without operation would check for UPDATE access). * * @param operation access operationIf operation is null no access is checked! Should be used - * only for tenant context. + * only for tenant context. * @param entities the entities to save * @return the saved entities */ @@ -53,7 +53,7 @@ public interface ACMRepository { * Returns single entry that match specification and the operation is allowed for. * * @param operation access operation. If operation is null no access is checked! Should be used - * only for tenant context. + * only for tenant context. * @param spec specification * @return matching entity */ @@ -64,7 +64,7 @@ public interface ACMRepository { * Returns all entries that match specification and the operation is allowed for. * * @param operation access operation. If operation is null no access is checked! Should be used - * only for tenant context. + * only for tenant context. * @param spec specification * @return matching entities */ @@ -75,7 +75,7 @@ public interface ACMRepository { * Returns all entries that match specification and the operation is allowed for. * * @param operation access operation. If operation is null no access is checked! Should be used - * only for tenant context. + * only for tenant context. * @param spec specification * @return matching entities */ @@ -86,7 +86,7 @@ public interface ACMRepository { * Returns count of all entries that match specification and the operation is allowed for. * * @param operation access operation. If operation is null no access is checked! Should be used - * only for tenant context. + * only for tenant context. * @param spec specification * @return count of matching entities */ @@ -97,7 +97,7 @@ public interface ACMRepository { * Returns all entries, without count, that match specification and the operation is allowed for. * * @param operation access operation. If operation is null no access is checked! Should be used - * only for tenant context. + * only for tenant context. * @param spec specification * @param pageable pageable * @return count of matching entities diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ActionRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ActionRepository.java index 512fb9b35..4e40cdb95 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ActionRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ActionRepository.java @@ -14,10 +14,8 @@ import java.util.List; import java.util.Optional; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; -import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -35,7 +33,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link Action} repository. - * */ @Transactional(readOnly = true) public interface ActionRepository extends BaseEntityRepository { @@ -43,8 +40,7 @@ public interface ActionRepository extends BaseEntityRepository { /** * Retrieves an Action with all lazy attributes. * - * @param actionId - * the ID of the action + * @param actionId the ID of the action * @return the found {@link Action} */ @EntityGraph(value = "Action.all", type = EntityGraphType.LOAD) @@ -53,12 +49,9 @@ public interface ActionRepository extends BaseEntityRepository { /** * Retrieves the latest finished {@link Action} for given target and {@link DistributionSet}. * - * @param targetId - * the action belongs to - * @param dsId - * of the ds that is assigned to the target - * @param status - * of the action + * @param targetId the action belongs to + * @param dsId of the ds that is assigned to the target + * @param status of the action * @return action if there is one with assigned target and assigned * {@link DistributionSet}. */ @@ -71,14 +64,10 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param statusToSet - * the new status the actions should get - * @param targetIds - * the IDs of the targets of the actions which are affected - * @param active - * the active flag of the actions which should be affected - * @param currentStatus - * the current status of the actions which are affected + * @param statusToSet the new status the actions should get + * @param targetIds the IDs of the targets of the actions which are affected + * @param active the active flag of the actions which should be affected + * @param currentStatus the current status of the actions which are affected */ @Modifying @Transactional @@ -89,8 +78,7 @@ public interface ActionRepository extends BaseEntityRepository { /** * Retrieves an {@link Action} that matches the queried externalRef. * - * @param externalRef - * of the action. See {@link Action#getExternalRef()} + * @param externalRef of the action. See {@link Action#getExternalRef()} * @return the found {@link Action} */ Optional findByExternalRef(@Param("externalRef") String externalRef); @@ -100,8 +88,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param controllerId - * the target to count the {@link Action}s + * @param controllerId the target to count the {@link Action}s * @return the count of actions referring to the given target */ Long countByTargetControllerId(String controllerId); @@ -111,8 +98,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param targetId - * the target to count the {@link Action}s + * @param targetId the target to count the {@link Action}s * @return the count of actions referring to the given target */ Long countByTargetId(Long targetId); @@ -122,8 +108,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param distributionSet - * DistributionSet to count the {@link Action}s from + * @param distributionSet DistributionSet to count the {@link Action}s from * @return the count of actions referring to the given distributionSet */ Long countByDistributionSetId(Long distributionSet); @@ -133,8 +118,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param distributionSet - * DistributionSet to count the {@link Action}s from + * @param distributionSet DistributionSet to count the {@link Action}s from * @return the count of actions referring to the given distributionSet */ Long countByDistributionSetIdAndActiveIsTrue(Long distributionSet); @@ -145,10 +129,8 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param distributionSet - * DistributionSet to count the {@link Action}s from - * @param status - * the state the actions should not have + * @param distributionSet DistributionSet to count the {@link Action}s from + * @param status the state the actions should not have * @return the count of actions referring to the given distributionSet */ Long countByDistributionSetIdAndActiveIsTrueAndStatusIsNot(Long distributionSet, Status status); @@ -161,12 +143,9 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rollout - * the rollout the actions are belong to - * @param rolloutGroup - * the rolloutgroup the actions are belong to - * @param statuses - * the list of statuses the action should not have + * @param rollout the rollout the actions are belong to + * @param rolloutGroup the rolloutgroup the actions are belong to + * @param statuses the list of statuses the action should not have * @return the count of actions referring the rollout and rolloutgroup and * are not in given states */ @@ -178,10 +157,8 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rollout - * the rollout the actions belong to - * @param rolloutGroup - * the rolloutgroup the actions belong to + * @param rollout the rollout the actions belong to + * @param rolloutGroup the rolloutgroup the actions belong to * @return the count of actions referring to a rollout and rolloutgroup */ Long countByRolloutAndRolloutGroup(JpaRollout rollout, JpaRolloutGroup rolloutGroup); @@ -191,12 +168,9 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rolloutId - * the ID of rollout the actions belong to - * @param rolloutGroupId - * the ID rolloutgroup the actions belong to - * @param status - * the status the actions should have + * @param rolloutId the ID of rollout the actions belong to + * @param rolloutGroupId the ID rolloutgroup the actions belong to + * @param status the status the actions should have * @return the count of actions referring to a rollout, rolloutgroup and are * in a given status */ @@ -207,10 +181,8 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rolloutId - * the ID of the rollout the actions belong to - * @param status - * the status the actions should have + * @param rolloutId the ID of the rollout the actions belong to + * @param status the status the actions should have * @return the count of actions referring to a rollout and are in a given * status */ @@ -222,8 +194,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rolloutId - * the ID of the rollout the actions belong to + * @param rolloutId the ID of the rollout the actions belong to * @return {@code true} if actions for the given rollout exists, otherwise * {@code false} */ @@ -236,10 +207,8 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rolloutId - * the ID of the rollout the actions belong to - * @param status - * the action is not to be in + * @param rolloutId the ID of the rollout the actions belong to + * @param status the action is not to be in * @return {@code true} if actions for the given rollout exists, otherwise * {@code false} */ @@ -254,14 +223,10 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param pageable - * page parameters - * @param rollout - * the rollout the actions belong to - * @param rolloutGroupParent - * the parent rolloutgroup the actions should reference - * @param actionStatus - * the status the actions have + * @param pageable page parameters + * @param rollout the rollout the actions belong to + * @param rolloutGroupParent the parent rolloutgroup the actions should reference + * @param actionStatus the status the actions have * @return the actions referring a specific rollout and a specific parent * rolloutgroup in a specific status */ @@ -274,12 +239,9 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param pageable - * page parameters - * @param rollout - * the rollout the actions belong to - * @param actionStatus - * the status the actions have + * @param pageable page parameters + * @param rollout the rollout the actions belong to + * @param actionStatus the status the actions have * @return the actions referring a specific rollout and a specific parent * rolloutgroup in a specific status */ @@ -293,12 +255,9 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param pageable - * page parameters - * @param rolloutId - * the rollout the actions belong to - * @param actionStatus - * the status of the actions + * @param pageable page parameters + * @param rolloutId the rollout the actions belong to + * @param actionStatus the status of the actions * @return the actions referring a specific rollout an in a specific status */ Page findByRolloutIdAndStatus(Pageable pageable, Long rolloutId, Status actionStatus); @@ -309,8 +268,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rolloutId - * id of {@link Rollout} + * @param rolloutId id of {@link Rollout} * @return list of objects with status and target count */ @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.id)) FROM JpaAction a WHERE a.rollout.id IN ?1 GROUP BY a.rollout.id,a.status") @@ -322,8 +280,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rolloutId - * id of {@link Rollout} + * @param rolloutId id of {@link Rollout} * @return list of objects with status and target count */ @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.id)) FROM JpaAction a WHERE a.rollout.id = ?1 GROUP BY a.rollout.id,a.status") @@ -335,8 +292,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rolloutGroupId - * id of {@link RolloutGroup} + * @param rolloutGroupId id of {@link RolloutGroup} * @return list of objects with status and target count */ @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.id)) FROM JpaAction a WHERE a.rolloutGroup.id = ?1 GROUP BY a.rolloutGroup.id, a.status") @@ -348,8 +304,7 @@ public interface ActionRepository extends BaseEntityRepository { *

* No access control applied * - * @param rolloutGroupId - * list of id of {@link RolloutGroup} + * @param rolloutGroupId list of id of {@link RolloutGroup} * @return list of objects with status and target count */ @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.id)) FROM JpaAction a WHERE a.rolloutGroup.id IN ?1 GROUP BY a.rolloutGroup.id, a.status") @@ -358,10 +313,8 @@ public interface ActionRepository extends BaseEntityRepository { /** * Updates the externalRef of an action by its actionId. * - * @param actionId - * for which the externalRef is being updated. - * @param externalRef - * value of the external reference for the given action id. + * @param actionId for which the externalRef is being updated. + * @param externalRef value of the external reference for the given action id. */ @Modifying @Transactional @@ -371,8 +324,7 @@ public interface ActionRepository extends BaseEntityRepository { /** * Deletes all actions with the given IDs. * - * @param actionIDs - * the IDs of the actions to be deleted. + * @param actionIDs the IDs of the actions to be deleted. */ @Modifying @Transactional diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ActionStatusRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ActionStatusRepository.java index a6fa1883d..408024990 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ActionStatusRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/ActionStatusRepository.java @@ -20,7 +20,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link ActionStatus} repository. - * */ @Transactional(readOnly = true) public interface ActionStatusRepository extends BaseEntityRepository { @@ -53,14 +52,10 @@ public interface ActionStatusRepository extends BaseEntityRepository * No access control applied * - * @param pageable - * for page configuration - * @param actionId - * for which to get the status messages - * @param filter - * is the SQL like pattern to use for filtering out or excluding - * the messages - * + * @param pageable for page configuration + * @param actionId for which to get the status messages + * @param filter is the SQL like pattern to use for filtering out or excluding + * the messages * @return Page with found status messages. */ @Query("SELECT message FROM JpaActionStatus actionstatus JOIN actionstatus.messages message WHERE actionstatus.action.id = :actionId AND message NOT LIKE :filter") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepository.java index 39a388101..268453e23 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepository.java @@ -14,6 +14,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Optional; +import jakarta.persistence.EntityManager; + import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaTenantAwareBaseEntity; @@ -26,19 +28,30 @@ import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.lang.Nullable; import org.springframework.transaction.annotation.Transactional; -import jakarta.persistence.EntityManager; - /** * Command repository operations for all {@link TenantAwareBaseEntity}s. * - * @param - * type if the entity type + * @param type if the entity type */ @NoRepositoryBean @Transactional(readOnly = true) public interface BaseEntityRepository extends PagingAndSortingRepository, CrudRepository, JpaSpecificationExecutor, - NoCountSliceRepository, ACMRepository { + NoCountSliceRepository, ACMRepository { + + /** + * Overrides + * {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)} + * to return a list of created entities instead of an instance of + * {@link Iterable} to be able to work with it directly in further code + * processing instead of converting the {@link Iterable}. + * + * @param entities to persist in the database + * @return the created entities + */ + @Override + @Transactional + List saveAll(Iterable entities); /** * Overrides @@ -65,24 +78,10 @@ public interface BaseEntityRepository findAllById(final Iterable ids); - /** - * Overrides - * {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)} - * to return a list of created entities instead of an instance of - * {@link Iterable} to be able to work with it directly in further code - * processing instead of converting the {@link Iterable}. - * - * @param entities to persist in the database - * @return the created entities - */ - @Override - @Transactional - List saveAll(Iterable entities); - - // TODO When we switch to Spring 3.0 probably we could remove extending methods using // queries and make here a default implementation using JPASpecificationExecutor delete method // TODO To be considered if this method is needed at all + /** * Deletes all entities of a given tenant from this repository. For safety * reasons (this is a "delete everything" query after all) we add the tenant diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java index 87615a114..19f425fa3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java @@ -9,6 +9,18 @@ */ package org.eclipse.hawkbit.repository.jpa.repository; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; + +import jakarta.transaction.Transactional; + import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; @@ -23,17 +35,6 @@ import org.springframework.data.repository.query.FluentQuery; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; -import jakarta.transaction.Transactional; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; - @Slf4j public class BaseEntityRepositoryACM implements BaseEntityRepository { @@ -45,56 +46,11 @@ public class BaseEntityRepositoryACM this.accessController = accessController; } - @SuppressWarnings("unchecked") - static > R of( - final R repository, @NonNull final AccessController accessController) { - Objects.requireNonNull(repository); - Objects.requireNonNull(accessController); - final BaseEntityRepositoryACM repositoryACM = - new BaseEntityRepositoryACM<>(repository, accessController); - final R acmProxy = (R) Proxy.newProxyInstance( - Thread.currentThread().getContextClassLoader(), - repository.getClass().getInterfaces(), - (proxy, method, args) -> { - try { - try { - // TODO - cache mapping so to speed things - final Method delegateMethod = - BaseEntityRepositoryACM.class.getDeclaredMethod( - method.getName(), method.getParameterTypes()); - return delegateMethod.invoke(repositoryACM, args); - } catch (final NoSuchMethodException e) { - // call to repository itself - } - if (method.getName().startsWith("find") || method.getName().startsWith("get")) { - final Object result = method.invoke(repository, args); - if (Iterable.class.isAssignableFrom(method.getReturnType())) { - for (final Object e : (Iterable) result) { - if (repository.getDomainClass().isAssignableFrom(e.getClass())) { - accessController.assertOperationAllowed(AccessController.Operation.READ, (T) e); - } - } - } else if (Optional.class.isAssignableFrom(method.getReturnType()) && ((Optional) result) - .filter(value -> repository.getDomainClass().isAssignableFrom(value.getClass())) - .isPresent()) { - return ((Optional) result).filter( - t -> isOperationAllowed(AccessController.Operation.READ, t, accessController)); - } else if (repository.getDomainClass().isAssignableFrom(method.getReturnType())) { - accessController.assertOperationAllowed(AccessController.Operation.READ, (T) result); - } - return result; - } else if ("toString".equals(method.getName()) && method.getParameterCount() == 0) { - return BaseEntityRepositoryACM.class.getSimpleName() + - "(repository: " + repository + ", accessController: " + accessController + ")"; - } else { - return method.invoke(repository, args); - } - } catch (final InvocationTargetException e) { - throw e.getCause() == null ? e : e.getCause(); - } - }); - log.info("Proxy created -> {}", acmProxy); - return acmProxy; + @Override + @NonNull + public S save(@NonNull final S entity) { + accessController.assertOperationAllowed(AccessController.Operation.UPDATE, entity); + return repository.save(entity); } @Override @@ -103,18 +59,6 @@ public class BaseEntityRepositoryACM return findOne(byIdSpec(id)); } - @Override - @NonNull - public List findAll() { - return findAll((Specification) null); - } - - @Override - @NonNull - public List findAllById(@NonNull final Iterable ids) { - return findAll(byIdsSpec(ids)); - } - @Override public boolean existsById(@NonNull final Long id) { return exists(byIdSpec(id)); @@ -125,16 +69,10 @@ public class BaseEntityRepositoryACM return count(null); } - @Override - public void delete(@NonNull final T entity) { - accessController.assertOperationAllowed(AccessController.Operation.DELETE, entity); - repository.delete(entity); - } - @Override public void deleteById(@NonNull final Long id) { if (!exists(AccessController.Operation.READ, byIdSpec(id))) { - throw new EntityNotFoundException(repository.getDomainClass(), id); + throw new EntityNotFoundException(repository.getDomainClass(), id); } if (!exists(AccessController.Operation.DELETE, byIdSpec(id))) { throw new InsufficientPermissionException(); @@ -142,6 +80,12 @@ public class BaseEntityRepositoryACM repository.deleteById(id); } + @Override + public void delete(@NonNull final T entity) { + accessController.assertOperationAllowed(AccessController.Operation.DELETE, entity); + repository.delete(entity); + } + @Override public void deleteAllById(@NonNull final Iterable ids) { final Set idList = toSetDistinct(ids); @@ -168,37 +112,44 @@ public class BaseEntityRepositoryACM throw new UnsupportedOperationException(); } - @Override - @NonNull - public S save(@NonNull final S entity) { - accessController.assertOperationAllowed(AccessController.Operation.UPDATE, entity); - return repository.save(entity); - } - @Override public List saveAll(final Iterable entities) { accessController.assertOperationAllowed(AccessController.Operation.UPDATE, entities); return repository.saveAll(entities); } + @Override + @NonNull + public List findAll() { + return findAll((Specification) null); + } + + @Override + @NonNull + public List findAllById(@NonNull final Iterable ids) { + return findAll(byIdsSpec(ids)); + } + + @Override + public void deleteByTenant(final String tenant) { + if (accessController.getAccessRules(AccessController.Operation.DELETE).isPresent()) { + throw new InsufficientPermissionException( + "DELETE operation has restriction for given context! deleteAll can't be executed!"); + } + repository.deleteByTenant(tenant); + } + + @Override + public Optional> getAccessController() { + return Optional.of(accessController); + } + @Override @NonNull public Optional findOne(final Specification spec) { return repository.findOne(accessController.appendAccessRules(AccessController.Operation.READ, spec)); } - @Override - @NonNull - public Iterable findAll(@NonNull final Sort sort) { - return findAll(null, sort); - } - - @Override - @NonNull - public Page findAll(@NonNull final Pageable pageable) { - return findAll(null, pageable); - } - @Override @NonNull public List findAll(final Specification spec) { @@ -218,9 +169,8 @@ public class BaseEntityRepositoryACM } @Override - public R findBy(final Specification spec, - final Function, R> queryFunction) { - return repository.findBy(accessController.appendAccessRules(AccessController.Operation.READ, spec), queryFunction); + public long count(final Specification spec) { + return repository.count(accessController.appendAccessRules(AccessController.Operation.READ, spec)); } @Override @@ -235,8 +185,21 @@ public class BaseEntityRepositoryACM } @Override - public long count(final Specification spec) { - return repository.count(accessController.appendAccessRules(AccessController.Operation.READ, spec)); + public R findBy(final Specification spec, + final Function, R> queryFunction) { + return repository.findBy(accessController.appendAccessRules(AccessController.Operation.READ, spec), queryFunction); + } + + @Override + @NonNull + public Iterable findAll(@NonNull final Sort sort) { + return findAll(null, sort); + } + + @Override + @NonNull + public Page findAll(@NonNull final Pageable pageable) { + return findAll(null, pageable); } @Override @@ -253,7 +216,7 @@ public class BaseEntityRepositoryACM @Override @Transactional @NonNull - public S save(@Nullable AccessController.Operation operation, @NonNull final S entity) { + public S save(@Nullable AccessController.Operation operation, @NonNull final S entity) { if (operation != null) { accessController.assertOperationAllowed(operation, entity); } @@ -326,18 +289,56 @@ public class BaseEntityRepositoryACM return repository.getDomainClass(); } - @Override - public Optional> getAccessController() { - return Optional.of(accessController); - } - - @Override - public void deleteByTenant(final String tenant) { - if (accessController.getAccessRules(AccessController.Operation.DELETE).isPresent()) { - throw new InsufficientPermissionException( - "DELETE operation has restriction for given context! deleteAll can't be executed!"); - } - repository.deleteByTenant(tenant); + @SuppressWarnings("unchecked") + static > R of( + final R repository, @NonNull final AccessController accessController) { + Objects.requireNonNull(repository); + Objects.requireNonNull(accessController); + final BaseEntityRepositoryACM repositoryACM = + new BaseEntityRepositoryACM<>(repository, accessController); + final R acmProxy = (R) Proxy.newProxyInstance( + Thread.currentThread().getContextClassLoader(), + repository.getClass().getInterfaces(), + (proxy, method, args) -> { + try { + try { + // TODO - cache mapping so to speed things + final Method delegateMethod = + BaseEntityRepositoryACM.class.getDeclaredMethod( + method.getName(), method.getParameterTypes()); + return delegateMethod.invoke(repositoryACM, args); + } catch (final NoSuchMethodException e) { + // call to repository itself + } + if (method.getName().startsWith("find") || method.getName().startsWith("get")) { + final Object result = method.invoke(repository, args); + if (Iterable.class.isAssignableFrom(method.getReturnType())) { + for (final Object e : (Iterable) result) { + if (repository.getDomainClass().isAssignableFrom(e.getClass())) { + accessController.assertOperationAllowed(AccessController.Operation.READ, (T) e); + } + } + } else if (Optional.class.isAssignableFrom(method.getReturnType()) && ((Optional) result) + .filter(value -> repository.getDomainClass().isAssignableFrom(value.getClass())) + .isPresent()) { + return ((Optional) result).filter( + t -> isOperationAllowed(AccessController.Operation.READ, t, accessController)); + } else if (repository.getDomainClass().isAssignableFrom(method.getReturnType())) { + accessController.assertOperationAllowed(AccessController.Operation.READ, (T) result); + } + return result; + } else if ("toString".equals(method.getName()) && method.getParameterCount() == 0) { + return BaseEntityRepositoryACM.class.getSimpleName() + + "(repository: " + repository + ", accessController: " + accessController + ")"; + } else { + return method.invoke(repository, args); + } + } catch (final InvocationTargetException e) { + throw e.getCause() == null ? e : e.getCause(); + } + }); + log.info("Proxy created -> {}", acmProxy); + return acmProxy; } private static boolean isOperationAllowed( @@ -351,7 +352,7 @@ public class BaseEntityRepositoryACM } } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings({ "rawtypes", "unchecked" }) private static Set toSetDistinct(final Iterable i) { final Set set = new HashSet<>(); i.forEach(set::add); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetMetadataRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetMetadataRepository.java index bce019a50..790755953 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetMetadataRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetMetadataRepository.java @@ -31,7 +31,7 @@ public interface DistributionSetMetadataRepository * Counts the meta data entries that match the given distribution set ID. *

* No access control applied - * + * * @param id of the distribution set. * @return The number of matching meta data entries. */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetRepository.java index 645bc9245..b4838b35c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetRepository.java @@ -11,7 +11,6 @@ package org.eclipse.hawkbit.repository.jpa.repository; import java.util.Collection; import java.util.List; -import java.util.Optional; import jakarta.persistence.EntityManager; @@ -29,7 +28,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link DistributionSet} repository. - * */ @Transactional(readOnly = true) public interface DistributionSetRepository @@ -51,8 +49,7 @@ public interface DistributionSetRepository *

* No access control applied. * - * @param dsId - * to be found + * @param dsId to be found * @return map for {@link Action}s status counts */ @Query(value = "SELECT a.status as name, COUNT(a.status) as data FROM JpaAction a WHERE a.distributionSet.id = :dsId GROUP BY a.status") @@ -63,8 +60,7 @@ public interface DistributionSetRepository *

* No access control applied. * - * @param dsId - * to be found + * @param dsId to be found * @return number of Auto Assignments for Distribution set */ @Query(value = "SELECT COUNT(f.autoAssignDistributionSet) FROM JpaTargetFilterQuery f WHERE f.autoAssignDistributionSet.id = :dsId GROUP BY f.autoAssignDistributionSet") @@ -74,9 +70,8 @@ public interface DistributionSetRepository * deletes the {@link DistributionSet}s with the given IDs. *

* No access control applied. - * - * @param ids - * to be deleted + * + * @param ids to be deleted */ @Modifying @Transactional @@ -89,8 +84,7 @@ public interface DistributionSetRepository *

* No access control applied. * - * @param moduleId - * to search for + * @param moduleId to search for * @return {@link List} of found {@link DistributionSet}s */ Long countByModulesId(Long moduleId); @@ -101,8 +95,7 @@ public interface DistributionSetRepository *

* No access control applied. * - * @param ids - * to search for + * @param ids to search for * @return list of {@link DistributionSet#getId()} */ @Query("select ac.distributionSet.id from JpaAction ac where ac.distributionSet.id in :ids") @@ -114,8 +107,7 @@ public interface DistributionSetRepository *

* No access control applied. * - * @param ids - * to search for + * @param ids to search for * @return list of {@link DistributionSet#getId()} */ @Query("select ra.distributionSet.id from JpaRollout ra where ra.distributionSet.id in :ids") @@ -126,8 +118,7 @@ public interface DistributionSetRepository *

* No access control applied. * - * @param typeId - * to search for + * @param typeId to search for * @return number of found {@link DistributionSet}s */ long countByTypeId(Long typeId); @@ -138,8 +129,7 @@ public interface DistributionSetRepository * manually to query even if this will by done by {@link EntityManager} * anyhow. The DB should take care of optimizing this away. * - * @param tenant - * to delete data from + * @param tenant to delete data from */ @Modifying @Transactional diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTagRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTagRepository.java index b74ce1b28..9f79071bc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTagRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTagRepository.java @@ -15,7 +15,6 @@ import java.util.Optional; import jakarta.persistence.EntityManager; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; -import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; @@ -26,7 +25,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link TargetTag} repository. - * */ @Transactional(readOnly = true) public interface DistributionSetTagRepository @@ -34,9 +32,8 @@ public interface DistributionSetTagRepository /** * find {@link DistributionSetTag} by its name. - * - * @param tagName - * to filter on + * + * @param tagName to filter on * @return the {@link DistributionSetTag} if found, otherwise null */ Optional findByNameEquals(String tagName); @@ -55,8 +52,7 @@ public interface DistributionSetTagRepository * manually to query even if this will by done by {@link EntityManager} * anyhow. The DB should take care of optimizing this away. * - * @param tenant - * to delete data from + * @param tenant to delete data from */ @Modifying @Transactional diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTypeRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTypeRepository.java index 8699bf4e0..4a5ee23c8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTypeRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTypeRepository.java @@ -25,7 +25,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link PagingAndSortingRepository} and {@link org.springframework.data.repository.CrudRepository} for * {@link DistributionSetType}. - * */ @Transactional(readOnly = true) public interface DistributionSetTypeRepository @@ -36,11 +35,9 @@ public interface DistributionSetTypeRepository * assigned to. *

* No access control applied - * - * @param softwareModuleType - * the software module type to count the distribution set type - * which has this software module type assigned - * + * + * @param softwareModuleType the software module type to count the distribution set type + * which has this software module type assigned * @return the number of {@link DistributionSetType}s in the repository * assigned to the given software module type */ @@ -64,10 +61,8 @@ public interface DistributionSetTypeRepository * addressed {@link DistributionSetType}. *

* No access control applied - * - * @param id - * of the distribution set type - * + * + * @param id of the distribution set type * @return the number of associated software module types */ @Query("SELECT COUNT (e.smType) FROM DistributionSetTypeElement e WHERE e.dsType.id = :id") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/HawkBitBaseRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/HawkBitBaseRepository.java index 521f03b61..3fcc253b9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/HawkBitBaseRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/HawkBitBaseRepository.java @@ -46,22 +46,21 @@ public class HawkBitBaseRepository extends SimpleJpa super(entityInformation, entityManager); } + @Override + public Slice findAllWithoutCount(final Pageable pageable) { + return findAllWithoutCount(null, pageable); + } + @Override public Slice findAllWithoutCount(@Nullable final Specification spec, final Pageable pageable) { final TypedQuery query = getQuery(spec, pageable); return pageable.isUnpaged() ? new PageImpl<>(query.getResultList()) : readPageWithoutCount(query, pageable); } - @Override - public Slice findAllWithoutCount(final Pageable pageable) { - return findAllWithoutCount(null, pageable); - } - - @Override @Transactional @NonNull - public S save(@Nullable AccessController.Operation operation, @NonNull final S entity) { + public S save(@Nullable AccessController.Operation operation, @NonNull final S entity) { return save(entity); } @@ -71,7 +70,6 @@ public class HawkBitBaseRepository extends SimpleJpa return saveAll(entities); } - @NonNull public Optional findOne(@Nullable AccessController.Operation operation, @Nullable Specification spec) { return findOne(spec); @@ -97,7 +95,8 @@ public class HawkBitBaseRepository extends SimpleJpa @NonNull @Override - public Slice findAllWithoutCount(@Nullable final AccessController.Operation operation, @Nullable Specification spec, Pageable pageable) { + public Slice findAllWithoutCount(@Nullable final AccessController.Operation operation, @Nullable Specification spec, + Pageable pageable) { return findAllWithoutCount(spec, pageable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/LocalArtifactRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/LocalArtifactRepository.java index 7bcd746e9..cea7f2266 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/LocalArtifactRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/LocalArtifactRepository.java @@ -20,7 +20,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link Artifact} repository. - * */ @Transactional(readOnly = true) public interface LocalArtifactRepository @@ -80,11 +79,8 @@ public interface LocalArtifactRepository * Searches for a {@link Artifact} based user provided filename at upload and * selected software module id. * - * @param filename - * to search - * @param softwareModuleId - * selected software module id - * + * @param filename to search + * @param softwareModuleId selected software module id * @return list of {@link Artifact}. */ Optional findFirstByFilenameAndSoftwareModuleId(String filename, Long softwareModuleId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/NoCountSliceRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/NoCountSliceRepository.java index 6d73fa522..8a0a64c3a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/NoCountSliceRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/NoCountSliceRepository.java @@ -18,16 +18,14 @@ import org.springframework.lang.Nullable; /** * Repository interface that offers findAll with disabled count query. * - * @param - * entity type + * @param entity type */ public interface NoCountSliceRepository { /** * Retrieves a slice of {@link BaseEntity}s without keeping the count updated * - * @param pageable - * page to keep track of slices + * @param pageable page to keep track of slices * @return {@link BaseEntity} */ Slice findAllWithoutCount(Pageable pageable); @@ -36,10 +34,8 @@ public interface NoCountSliceRepository { * Retrieves a slice of {@link BaseEntity}s based on spec without keeping the * count updated * - * @param spec - * to search for - * @param pageable - * page to keep track of slices + * @param spec to search for + * @param pageable page to keep track of slices * @return {@link BaseEntity} */ Slice findAllWithoutCount(@Nullable Specification spec, Pageable pageable); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutGroupRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutGroupRepository.java index 51edd6b61..e336b2042 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutGroupRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutGroupRepository.java @@ -35,8 +35,7 @@ public interface RolloutGroupRepository * Retrieves all {@link RolloutGroup} referring a specific rollout in the * order of creating them. ID ASC. * - * @param rollout - * the rollout the rolloutgroups belong to + * @param rollout the rollout the rolloutgroups belong to * @return the rollout groups belonging to a rollout ordered by ID ASC. */ List findByRolloutOrderByIdAsc(JpaRollout rollout); @@ -45,10 +44,8 @@ public interface RolloutGroupRepository * Retrieves all {@link RolloutGroup} referring a specific rollout in a * specific {@link RolloutGroupStatus}. * - * @param rollout - * the rollout the rolloutgroup belong to - * @param status - * the status of the rollout groups + * @param rollout the rollout the rolloutgroup belong to + * @param status the status of the rollout groups * @return the rollout groups belonging to a rollout in a specific status */ List findByRolloutAndStatus(Rollout rollout, RolloutGroupStatus status); @@ -60,12 +57,9 @@ public interface RolloutGroupRepository * rollout-management to find out rolloutgroups which are in specific * states. * - * @param rolloutId - * the ID of the rollout the rolloutgroup belong to - * @param rolloutGroupStatus1 - * the status of the rollout groups - * @param rolloutGroupStatus2 - * the status of the rollout groups + * @param rolloutId the ID of the rollout the rolloutgroup belong to + * @param rolloutGroupStatus1 the status of the rollout groups + * @param rolloutGroupStatus2 the status of the rollout groups * @return the count of rollout groups belonging to a rollout in specific * status */ @@ -75,18 +69,13 @@ public interface RolloutGroupRepository @Param("status2") RolloutGroupStatus rolloutGroupStatus2); /** - * * Counts all rollout-groups refering to a given {@link Rollout} by its ID * and groups which not having the given status. * - * @param rolloutId - * the ID of the rollout refering the groups - * @param status1 - * the status which the groups should not have - * @param status2 - * the status which the groups should not have - * @param status2 - * the status which the groups should not have + * @param rolloutId the ID of the rollout refering the groups + * @param status1 the status which the groups should not have + * @param status2 the status which the groups should not have + * @param status2 the status which the groups should not have * @return count of rollout-groups referning a rollout and not in the given * states */ @@ -99,10 +88,8 @@ public interface RolloutGroupRepository * Retrieves all {@link RolloutGroup} for a specific parent in a specific * status. Retrieves the child rolloutgroup for a specific status. * - * @param rolloutGroupId - * the rolloutgroupId to find the parents - * @param status - * the status of the rolloutgroups + * @param rolloutGroupId the rolloutgroupId to find the parents + * @param status the status of the rolloutgroups * @return The child {@link RolloutGroup}s in a specific status */ @Query("SELECT g FROM JpaRolloutGroup g WHERE g.parent.id=:rolloutGroupId and g.status=:status") @@ -113,10 +100,8 @@ public interface RolloutGroupRepository * Updates all {@link RolloutGroup#getStatus()} of children for given * parent. * - * @param parent - * the parent rolloutgroup - * @param status - * the status of the rolloutgroups + * @param parent the parent rolloutgroup + * @param status the status of the rolloutgroups */ @Modifying @Transactional @@ -127,10 +112,8 @@ public interface RolloutGroupRepository * Retrieves all {@link RolloutGroup} for a specific rollout and status not * having ordered by ID DESC, latest top. * - * @param rollout - * the rollout the rolloutgroup belong to - * @param notStatus - * the status which the rolloutgroup should not have + * @param rollout the rollout the rolloutgroup belong to + * @param notStatus the status which the rolloutgroup should not have * @return rolloutgroup referring to a rollout and not having a specific * status ordered by ID DESC. */ @@ -140,10 +123,8 @@ public interface RolloutGroupRepository * Retrieves all {@link RolloutGroup}s for a specific rollout and status not * having. * - * @param rollout - * the rollout the rolloutgroup belong to - * @param status - * the status which the rolloutgroup should not have + * @param rollout the rollout the rolloutgroup belong to + * @param status the status which the rolloutgroup should not have * @return rolloutgroup referring to a rollout and not having a specific * status. */ @@ -152,10 +133,8 @@ public interface RolloutGroupRepository /** * Retrieves all {@link RolloutGroup} for a specific rollout. * - * @param rolloutId - * the ID of the rollout to find the rollout groups - * @param page - * the page request to sort, limit the result + * @param rolloutId the ID of the rollout to find the rollout groups + * @param page the page request to sort, limit the result * @return a page of found {@link RolloutGroup} or {@code empty}. */ Page findByRolloutId(Long rolloutId, Pageable page); @@ -163,9 +142,7 @@ public interface RolloutGroupRepository /** * Counts all {@link RolloutGroup} for a specific rollout. * - * @param rolloutId - * the ID of the rollout to find the rollout groups - * + * @param rolloutId the ID of the rollout to find the rollout groups * @return the amount of found {@link RolloutGroup}s. */ long countByRolloutId(Long rolloutId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutRepository.java index 7a48e3077..6632ef826 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutRepository.java @@ -35,8 +35,7 @@ public interface RolloutRepository /** * Retrieves all {@link Rollout} for given status. * - * @param status - * the status of the rollouts to find + * @param status the status of the rollouts to find * @return the list of {@link Rollout} for specific status */ // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 @@ -46,8 +45,7 @@ public interface RolloutRepository /** * Retrieves all {@link Rollout} for a specific {@code name} * - * @param name - * the rollout name + * @param name the rollout name * @return {@link Rollout} for specific name */ Optional findByName(String name); @@ -58,8 +56,7 @@ public interface RolloutRepository * manually to query even if this will by done by {@link EntityManager} * anyhow. The DB should take care of optimizing this away. * - * @param tenant - * to delete data from + * @param tenant to delete data from */ @Modifying @Transactional @@ -70,10 +67,8 @@ public interface RolloutRepository * Retrieves all {@link Rollout}s for a specific {@link DistributionSet} in * a given {@link RolloutStatus}. * - * @param set - * the distribution set - * @param status - * the status of the rollout + * @param set the distribution set + * @param status the status of the rollout * @return {@link Rollout} for specific distribution set */ List findByDistributionSetAndStatusIn(DistributionSet set, Collection status); @@ -82,10 +77,8 @@ public interface RolloutRepository * Counts all {@link Rollout}s for a specific {@link DistributionSet} in a * given {@link RolloutStatus}. * - * @param distributionSetId - * the distribution set - * @param status - * the status of the rollout + * @param distributionSetId the distribution set + * @param status the status of the rollout * @return the count */ long countByDistributionSetIdAndStatusIn(long distributionSetId, Collection status); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutTargetGroupRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutTargetGroupRepository.java index 1b46ef527..82999a31f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutTargetGroupRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/RolloutTargetGroupRepository.java @@ -18,7 +18,6 @@ import org.springframework.transaction.annotation.Transactional; /** * Spring data repository for {@link RolloutTargetGroup}. - * */ @Transactional(readOnly = true) public interface RolloutTargetGroupRepository @@ -26,9 +25,8 @@ public interface RolloutTargetGroupRepository /** * Counts all entries that have the specified rolloutGroup - * - * @param rolloutGroup - * the group to filter for + * + * @param rolloutGroup the group to filter for * @return count of targets in the group */ Long countByRolloutGroup(JpaRolloutGroup rolloutGroup); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleMetadataRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleMetadataRepository.java index 622b753a4..46ecb4838 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleMetadataRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleMetadataRepository.java @@ -25,7 +25,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link SoftwareModuleMetadata} repository. - * */ @Transactional(readOnly = true) public interface SoftwareModuleMetadataRepository @@ -36,14 +35,10 @@ public interface SoftwareModuleMetadataRepository /** * Locates the meta data entries that match the given software module ID and * target visibility flag. - * - * @param page - * The pagination parameters. - * @param moduleId - * The ID of the software module. - * @param targetVisible - * The target visibility flag. - * + * + * @param page The pagination parameters. + * @param moduleId The ID of the software module. + * @param targetVisible The target visibility flag. * @return A {@link Page} with the matching meta data entries. */ Page findBySoftwareModuleIdAndTargetVisible(Pageable page, Long moduleId, @@ -54,7 +49,7 @@ public interface SoftwareModuleMetadataRepository * and target visibility flag. *

* No access control applied - * + * * @param page The pagination parameters. * @param moduleId List of software module IDs. * @param targetVisible The target visibility flag. @@ -69,7 +64,7 @@ public interface SoftwareModuleMetadataRepository * software module. *

* No access control applied - * + * * @param moduleId The ID of the software module. * @return The number of meta data entries associated with the software module. */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleRepository.java index 8ab74825f..84845a7e3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleRepository.java @@ -22,7 +22,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link SoftwareModule} repository. - * */ @Transactional(readOnly = true) public interface SoftwareModuleRepository @@ -43,9 +42,8 @@ public interface SoftwareModuleRepository * with the given ID. *

* No access control applied - * + * * @param distributionSetId the distribution set ID - * * @return the number of software modules matching the given distribution set ID. */ long countByAssignedToId(Long distributionSetId); @@ -56,8 +54,7 @@ public interface SoftwareModuleRepository * manually to query even if this will by done by {@link EntityManager} * anyhow. The DB should take care of optimizing this away. * - * @param tenant - * to delete data from + * @param tenant to delete data from */ @Modifying @Transactional diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleTypeRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleTypeRepository.java index 8d4bf232a..8e6535d99 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleTypeRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleTypeRepository.java @@ -23,25 +23,20 @@ import org.springframework.transaction.annotation.Transactional; /** * Repository for {@link SoftwareModuleType}. - * */ @Transactional(readOnly = true) public interface SoftwareModuleTypeRepository extends BaseEntityRepository { /** - * - * @param key - * to search for + * @param key to search for * @return all {@link SoftwareModuleType}s in the repository with given * {@link SoftwareModuleType#getKey()} */ Optional findByKey(String key); /** - * - * @param name - * to search for + * @param name to search for * @return all {@link SoftwareModuleType}s in the repository with given * {@link SoftwareModuleType#getName()} */ @@ -53,8 +48,7 @@ public interface SoftwareModuleTypeRepository * manually to query even if this will by done by {@link EntityManager} * anyhow. The DB should take care of optimizing this away. * - * @param tenant - * to delete data from + * @param tenant to delete data from */ @Modifying @Transactional diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetFilterQueryRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetFilterQueryRepository.java index ea23f9f3a..2de30d1ff 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetFilterQueryRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetFilterQueryRepository.java @@ -16,7 +16,6 @@ import jakarta.persistence.EntityManager; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; -import org.springframework.data.domain.Page; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -24,7 +23,6 @@ import org.springframework.transaction.annotation.Transactional; /** * Spring data repositories for {@link TargetFilterQuery}s. - * */ @Transactional(readOnly = true) public interface TargetFilterQueryRepository @@ -57,8 +55,7 @@ public interface TargetFilterQueryRepository *

* No access control applied * - * @param autoAssignDistributionSetId - * the id of the distribution set + * @param autoAssignDistributionSetId the id of the distribution set * @return the count */ long countByAutoAssignDistributionSetId(long autoAssignDistributionSetId); @@ -69,8 +66,7 @@ public interface TargetFilterQueryRepository * manually to query even if this will by done by {@link EntityManager} * anyhow. The DB should take care of optimizing this away. * - * @param tenant - * to delete data from + * @param tenant to delete data from */ @Modifying @Transactional diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetMetadataRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetMetadataRepository.java index ed49c1894..d6e0c22b8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetMetadataRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetMetadataRepository.java @@ -31,7 +31,7 @@ public interface TargetMetadataRepository * Counts the meta data entries that match the given target ID. *

* No access control applied - * + * * @param id of the target. * @return The number of matching meta data entries. */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetRepository.java index d170a5f12..3ec5e7a79 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetRepository.java @@ -25,12 +25,12 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link Target} repository. - * */ @Transactional(readOnly = true) public interface TargetRepository extends BaseEntityRepository { // TODO AC - remove it and use specification + /** * @deprecated remove it and use specification */ @@ -43,7 +43,6 @@ public interface TargetRepository extends BaseEntityRepository { @Param("set") JpaDistributionSet set, @Param("lastModifiedAt") Long modifiedAt, @Param("lastModifiedBy") String modifiedBy, @Param("targets") Collection targets); - // TODO AC - remove it and use specification /** @@ -58,7 +57,7 @@ public interface TargetRepository extends BaseEntityRepository { @Param("set") JpaDistributionSet set, @Param("lastModifiedAt") Long modifiedAt, @Param("lastModifiedBy") String modifiedBy, @Param("targets") Collection targets); - /** + /** * Counts {@link Target} instances of given type in the repository. *

* No access control applied diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetTagRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetTagRepository.java index 066a21ca4..8f85c1715 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetTagRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetTagRepository.java @@ -23,7 +23,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link TargetTag} repository. - * */ @Transactional(readOnly = true) public interface TargetTagRepository extends BaseEntityRepository { @@ -31,8 +30,7 @@ public interface TargetTagRepository extends BaseEntityRepository /** * find {@link TargetTag} by its name. * - * @param tagName - * to filter on + * @param tagName to filter on * @return the {@link TargetTag} if found, otherwise null */ Optional findByNameEquals(String tagName); @@ -43,8 +41,7 @@ public interface TargetTagRepository extends BaseEntityRepository * manually to query even if this will by done by {@link EntityManager} * anyhow. The DB should take care of optimizing this away. * - * @param tenant - * to delete data from + * @param tenant to delete data from */ @Modifying @Transactional diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetTypeRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetTypeRepository.java index 2b99809e5..edced60d5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetTypeRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TargetTypeRepository.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.jpa.repository; import java.util.List; -import java.util.Optional; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; import org.eclipse.hawkbit.repository.jpa.specifications.TargetTypeSpecification; @@ -25,7 +24,6 @@ import org.springframework.transaction.annotation.Transactional; /** * {@link PagingAndSortingRepository} and {@link org.springframework.data.repository.CrudRepository} for * {@link JpaTargetType}. - * */ @Transactional(readOnly = true) public interface TargetTypeRepository @@ -43,9 +41,7 @@ public interface TargetTypeRepository long countDsSetTypesById(@Param("id") Long id); /** - * - * @param dsTypeId - * to search for + * @param dsTypeId to search for * @return all {@link TargetType}s in the repository with given * {@link TargetType#getName()} */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantConfigurationRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantConfigurationRepository.java index ca2a4c1a4..a0cc76af7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantConfigurationRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantConfigurationRepository.java @@ -21,27 +21,23 @@ import org.springframework.transaction.annotation.Transactional; /** * The spring-data repository for the entity {@link TenantConfiguration}. - * */ @Transactional(readOnly = true) public interface TenantConfigurationRepository extends BaseEntityRepository { /** * Finds a specific {@link TenantConfiguration} by the configuration key. - * - * @param configurationKey - * the configuration key to find the configuration for + * + * @param configurationKey the configuration key to find the configuration for * @return the found tenant configuration object otherwise {@code null} */ JpaTenantConfiguration findByKey(String configurationKey); /** * Deletes a tenant configuration by tenant and key. - * - * @param tenant - * the tenant for this configuration - * @param keyName - * the name of the key to be deleted + * + * @param tenant the tenant for this configuration + * @param keyName the name of the key to be deleted */ void deleteByKey(String keyName); @@ -51,8 +47,7 @@ public interface TenantConfigurationRepository extends BaseEntityRepositorynull */ TenantMetaData findByTenantIgnoreCase(String tenant); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/RolloutScheduler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/RolloutScheduler.java index 309dcb8d5..05d38018e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/RolloutScheduler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/RolloutScheduler.java @@ -33,13 +33,10 @@ public class RolloutScheduler { /** * Constructor. - * - * @param systemManagement - * to find all tenants - * @param rolloutHandler - * to run the rollout handler - * @param systemSecurityContext - * to run as system + * + * @param systemManagement to find all tenants + * @param rolloutHandler to run the rollout handler + * @param systemSecurityContext to run as system */ public RolloutScheduler(final SystemManagement systemManagement, final RolloutHandler rolloutHandler, final SystemSecurityContext systemSecurityContext) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/EvaluatorNotConfiguredException.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/EvaluatorNotConfiguredException.java index 97c46ba38..b5a0e3848 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/EvaluatorNotConfiguredException.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/EvaluatorNotConfiguredException.java @@ -19,9 +19,8 @@ public class EvaluatorNotConfiguredException extends RuntimeException { /** * Constructor - * - * @param s - * the action/condition to evaluate + * + * @param s the action/condition to evaluate */ public EvaluatorNotConfiguredException(final String s) { super(String.format(MESSAGE_FORMAT, s)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/PauseRolloutGroupAction.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/PauseRolloutGroupAction.java index 9537b49fb..23d50aadb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/PauseRolloutGroupAction.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/PauseRolloutGroupAction.java @@ -10,8 +10,8 @@ package org.eclipse.hawkbit.repository.jpa.rollout.condition; import org.eclipse.hawkbit.repository.RolloutManagement; -import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; +import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/RolloutGroupEvaluationManager.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/RolloutGroupEvaluationManager.java index ff86da47b..4c1f55cca 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/RolloutGroupEvaluationManager.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/RolloutGroupEvaluationManager.java @@ -31,18 +31,14 @@ public class RolloutGroupEvaluationManager { /** * Constructor * - * @param errorConditionEvaluators - * evaluators for instances of {@link RolloutGroupConditionEvaluator} - * handling the {@link RolloutGroup.RolloutGroupErrorCondition} - * @param successConditionEvaluators - * evaluators for instances of {@link RolloutGroupConditionEvaluator} - * handling the {@link RolloutGroup.RolloutGroupSuccessCondition} - * @param errorActionEvaluators - * evaluators for instances of {@link RolloutGroupActionEvaluator} - * handling the {@link RolloutGroup.RolloutGroupErrorAction} - * @param successActionEvaluators - * evaluators for instances of {@link RolloutGroupActionEvaluator} - * handling the {@link RolloutGroup.RolloutGroupSuccessAction} + * @param errorConditionEvaluators evaluators for instances of {@link RolloutGroupConditionEvaluator} + * handling the {@link RolloutGroup.RolloutGroupErrorCondition} + * @param successConditionEvaluators evaluators for instances of {@link RolloutGroupConditionEvaluator} + * handling the {@link RolloutGroup.RolloutGroupSuccessCondition} + * @param errorActionEvaluators evaluators for instances of {@link RolloutGroupActionEvaluator} + * handling the {@link RolloutGroup.RolloutGroupErrorAction} + * @param successActionEvaluators evaluators for instances of {@link RolloutGroupActionEvaluator} + * handling the {@link RolloutGroup.RolloutGroupSuccessAction} */ public RolloutGroupEvaluationManager( final List> errorConditionEvaluators, @@ -62,7 +58,7 @@ public class RolloutGroupEvaluationManager { } public RolloutGroupActionEvaluator getSuccessActionEvaluator( - final RolloutGroup.RolloutGroupSuccessAction successAction) { + final RolloutGroup.RolloutGroupSuccessAction successAction) { return findFirstActionEvaluator(successActionEvaluators, successAction); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/AbstractRSQLVisitor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/AbstractRSQLVisitor.java index 9db525381..d60dd901a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/AbstractRSQLVisitor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/AbstractRSQLVisitor.java @@ -15,12 +15,11 @@ import java.util.stream.Collectors; import jakarta.validation.constraints.NotNull; +import cz.jirutka.rsql.parser.ast.ComparisonNode; import lombok.Value; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; - -import cz.jirutka.rsql.parser.ast.ComparisonNode; import org.springframework.util.ObjectUtils; @Slf4j @@ -28,25 +27,15 @@ public abstract class AbstractRSQLVisitor & RsqlQueryField> { private final Class rsqlQueryFieldType; - @Value - protected class QuertPath { - - A enumValue; - String[] jpaPath; - - private QuertPath(final A enumValue, final String[] jpaPath) { - this.enumValue = enumValue; - this.jpaPath = jpaPath; - } - } - protected AbstractRSQLVisitor(final Class rsqlQueryFieldType) { this.rsqlQueryFieldType = rsqlQueryFieldType; } protected QuertPath getQuertPath(final ComparisonNode node) { final int firstSeparatorIndex = node.getSelector().indexOf(RsqlQueryField.SUB_ATTRIBUTE_SEPARATOR); - final String enumName = (firstSeparatorIndex == -1 ? node.getSelector() : node.getSelector().substring(0, firstSeparatorIndex)).toUpperCase(); + final String enumName = (firstSeparatorIndex == -1 + ? node.getSelector() + : node.getSelector().substring(0, firstSeparatorIndex)).toUpperCase(); log.debug("Get field identifier by name {} of enum type {}", enumName, rsqlQueryFieldType); try { @@ -137,4 +126,16 @@ public abstract class AbstractRSQLVisitor & RsqlQueryField> { expectedFieldList.addAll(expectedSubFieldList); return expectedFieldList; } + + @Value + protected class QuertPath { + + A enumValue; + String[] jpaPath; + + private QuertPath(final A enumValue, final String[] jpaPath) { + this.enumValue = enumValue; + this.jpaPath = jpaPath; + } + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/DefaultRsqlVisitorFactory.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/DefaultRsqlVisitorFactory.java index de78323e5..4d03ac40c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/DefaultRsqlVisitorFactory.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/DefaultRsqlVisitorFactory.java @@ -9,11 +9,10 @@ */ package org.eclipse.hawkbit.repository.jpa.rsql; +import cz.jirutka.rsql.parser.ast.RSQLVisitor; import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.rsql.RsqlVisitorFactory; -import cz.jirutka.rsql.parser.ast.RSQLVisitor; - /** * Factory providing {@link RSQLVisitor} instances which validate the nodes * based on a given {@link RsqlQueryField}. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/FieldValidationRsqlVisitor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/FieldValidationRsqlVisitor.java index 4a09ec01e..e8acbfcf2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/FieldValidationRsqlVisitor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/FieldValidationRsqlVisitor.java @@ -9,13 +9,12 @@ */ package org.eclipse.hawkbit.repository.jpa.rsql; -import org.eclipse.hawkbit.repository.RsqlQueryField; - import cz.jirutka.rsql.parser.ast.AndNode; import cz.jirutka.rsql.parser.ast.ComparisonNode; import cz.jirutka.rsql.parser.ast.LogicalNode; import cz.jirutka.rsql.parser.ast.OrNode; import cz.jirutka.rsql.parser.ast.RSQLVisitor; +import org.eclipse.hawkbit.repository.RsqlQueryField; /** * {@link RSQLVisitor} implementation which validates the nodes (fields) based @@ -28,7 +27,7 @@ public class FieldValidationRsqlVisitor & RsqlQueryField> exte /** * Constructs the visitor and initializes it. - * + * * @param fieldNameProvider The {@link RsqlQueryField} to use for validation. */ public FieldValidationRsqlVisitor(final Class fieldNameProvider) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitor.java index 296662c8f..971e9c440 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitor.java @@ -22,6 +22,7 @@ import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; + import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Expression; @@ -43,8 +44,8 @@ import cz.jirutka.rsql.parser.ast.OrNode; import cz.jirutka.rsql.parser.ast.RSQLVisitor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.math.NumberUtils; -import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.FieldValueConverter; +import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; @@ -58,11 +59,11 @@ import org.springframework.util.ObjectUtils; * An implementation of the {@link RSQLVisitor} to visit the parsed tokens and * build JPA where clauses. * - * @deprecated Old implementation of RSQL Visitor. Deprecated in favour of next gen implementation - {@link JpaQueryRsqlVisitorG2}. - * It will be kept for some time in order to keep backward compatibility and to allow for a smooth transition. Also, in case of - * problems with the new implementation, this one can be used as a fallback. * @param the enum for providing the field name of the entity field to filter on. * @param the entity type referenced by the root + * @deprecated Old implementation of RSQL Visitor. Deprecated in favour of next gen implementation - {@link JpaQueryRsqlVisitorG2}. + * It will be kept for some time in order to keep backward compatibility and to allow for a smooth transition. Also, in case of + * problems with the new implementation, this one can be used as a fallback. */ @Deprecated(forRemoval = true) @Slf4j @@ -72,7 +73,7 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends public static final Character LIKE_WILDCARD = '*'; private static final char ESCAPE_CHAR = '\\'; private static final List NO_JOINS_OPERATOR = List.of("!=", "=out="); - private static final String ESCAPE_CHAR_WITH_ASTERISK = ESCAPE_CHAR +"*"; + private static final String ESCAPE_CHAR_WITH_ASTERISK = ESCAPE_CHAR + "*"; private final Map>> joinsInLevel = new HashMap<>(3); @@ -101,6 +102,123 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends this.ensureIgnoreCase = ensureIgnoreCase; } + @Override + public List visit(final AndNode node, final String param) { + beginLevel(false); + final List childs = acceptChildren(node); + endLevel(); + if (!childs.isEmpty()) { + return toSingleList(cb.and(childs.toArray(new Predicate[0]))); + } + return toSingleList(cb.conjunction()); + } + + @Override + public List visit(final OrNode node, final String param) { + beginLevel(true); + final List childs = acceptChildren(node); + endLevel(); + if (!childs.isEmpty()) { + return toSingleList(cb.or(childs.toArray(new Predicate[0]))); + } + return toSingleList(cb.conjunction()); + } + + @Override + // Exception squid:S2095 - see + // https://jira.sonarsource.com/browse/SONARJAVA-1478 + @SuppressWarnings({ "squid:S2095" }) + public List visit(final ComparisonNode node, final String param) { + final QuertPath queryPath = getQuertPath(node); + + final List values = node.getArguments(); + final List transformedValues = new ArrayList<>(); + final Path fieldPath = getFieldPath(queryPath.getEnumValue(), queryPath); + + for (final String value : values) { + transformedValues.add(convertValueIfNecessary(node, queryPath.getEnumValue(), value, fieldPath)); + } + + this.joinsNeeded = this.joinsNeeded || areJoinsNeeded(node); + + return mapToPredicate(node, fieldPath, node.getArguments(), transformedValues, queryPath); + } + + private static List toSingleList(final Predicate predicate) { + return Collections.singletonList(predicate); + } + + private static Optional> getFieldPath(final Root root, final String[] split, final boolean isMapKeyField, + final BiFunction, String, Path> joinFieldPathProvider) { + Path fieldPath = null; + for (int i = 0; i < split.length; i++) { + if (!(isMapKeyField && i == (split.length - 1))) { + final String fieldNameSplit = split[i]; + fieldPath = (fieldPath != null) ? fieldPath.get(fieldNameSplit) : root.get(fieldNameSplit); + fieldPath = joinFieldPathProvider.apply(fieldPath, fieldNameSplit); + } + } + return Optional.ofNullable(fieldPath); + } + + private static boolean areJoinsNeeded(final ComparisonNode node) { + return !NO_JOINS_OPERATOR.contains(node.getOperator().getSymbol()); + } + + // Exception squid:S2095 - see + // https://jira.sonarsource.com/browse/SONARJAVA-1478 + @SuppressWarnings({ "rawtypes", "unchecked", "squid:S2095" }) + private static Object transformEnumValue(final ComparisonNode node, final String value, final Class javaType) { + final Class tmpEnumType = (Class) javaType; + try { + return Enum.valueOf(tmpEnumType, value.toUpperCase()); + } catch (final IllegalArgumentException e) { + // we could not transform the given string value into the enum + // type, so ignore it and return null and do not filter + log.info("given value {} cannot be transformed into the correct enum type {}", value.toUpperCase(), + javaType); + log.debug("value cannot be transformed to an enum", e); + + throw new RSQLParameterUnsupportedFieldException("field {" + node.getSelector() + + "} must be one of the following values {" + Arrays.stream(tmpEnumType.getEnumConstants()) + .map(v -> v.name().toLowerCase()).toList() + + "}", e); + } + } + + private static boolean isSimpleField(final String[] split, final boolean isMapKeyField) { + return split.length == 1 || (split.length == 2 && isMapKeyField); + } + + private static Path getInnerFieldPath(final Root subqueryRoot, final String[] split, + final boolean isMapKeyField) { + return getFieldPath(subqueryRoot, split, isMapKeyField, + (fieldPath, fieldNameSplit) -> getInnerJoinFieldPath(subqueryRoot, fieldPath, fieldNameSplit)) + .orElseThrow(() -> new RSQLParameterUnsupportedFieldException("RSQL field path cannot be empty", + null)); + } + + private static Path getInnerJoinFieldPath(final Root subqueryRoot, final Path fieldPath, + final String fieldNameSplit) { + if (fieldPath instanceof Join) { + return subqueryRoot.join(fieldNameSplit, JoinType.INNER); + } + return fieldPath; + } + + private static boolean isPattern(final String transformedValue) { + if (transformedValue.contains(ESCAPE_CHAR_WITH_ASTERISK)) { + return transformedValue.replace(ESCAPE_CHAR_WITH_ASTERISK, "$").indexOf(LIKE_WILDCARD) != -1; + } else { + return transformedValue.indexOf(LIKE_WILDCARD) != -1; + } + } + + @SuppressWarnings("unchecked") + private static Path pathOfString(final Path path) { + return (Path) path; + } + private void beginLevel(final boolean isOr) { level++; isOrLevel = isOr; @@ -130,32 +248,6 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends } } - @Override - public List visit(final AndNode node, final String param) { - beginLevel(false); - final List childs = acceptChildren(node); - endLevel(); - if (!childs.isEmpty()) { - return toSingleList(cb.and(childs.toArray(new Predicate[0]))); - } - return toSingleList(cb.conjunction()); - } - - @Override - public List visit(final OrNode node, final String param) { - beginLevel(true); - final List childs = acceptChildren(node); - endLevel(); - if (!childs.isEmpty()) { - return toSingleList(cb.or(childs.toArray(new Predicate[0]))); - } - return toSingleList(cb.conjunction()); - } - - private static List toSingleList(final Predicate predicate) { - return Collections.singletonList(predicate); - } - /** * Resolves the Path for a field in the persistence layer and joins the * required models. This operation is part of a tree traversal through an @@ -168,9 +260,8 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends * example joins the tags model only twice, because for the OR node in * brackets only one join is used. * - * @param enumField - * field from a FieldNameProvider to resolve on the persistence - * layer + * @param enumField field from a FieldNameProvider to resolve on the persistence + * layer * @param queryPath RSQL field * @return the Path for a field */ @@ -178,10 +269,10 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends private Path getFieldPath(final A enumField, final QuertPath queryPath) { return (Path) getFieldPath(root, queryPath.getJpaPath(), enumField.isMap(), this::getJoinFieldPath).orElseThrow( - () -> new RSQLParameterUnsupportedFieldException("RSQL field path cannot be empty", null)); + () -> new RSQLParameterUnsupportedFieldException("RSQL field path cannot be empty", null)); } - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings({ "rawtypes", "unchecked" }) private Path getJoinFieldPath(final Path fieldPath, final String fieldNameSplit) { if (fieldPath instanceof PluralJoin join) { final From joinParent = join.getParent(); @@ -199,43 +290,6 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends return fieldPath; } - private static Optional> getFieldPath(final Root root, final String[] split, final boolean isMapKeyField, - final BiFunction, String, Path> joinFieldPathProvider) { - Path fieldPath = null; - for (int i = 0; i < split.length; i++) { - if (!(isMapKeyField && i == (split.length - 1))) { - final String fieldNameSplit = split[i]; - fieldPath = (fieldPath != null) ? fieldPath.get(fieldNameSplit) : root.get(fieldNameSplit); - fieldPath = joinFieldPathProvider.apply(fieldPath, fieldNameSplit); - } - } - return Optional.ofNullable(fieldPath); - } - - @Override - // Exception squid:S2095 - see - // https://jira.sonarsource.com/browse/SONARJAVA-1478 - @SuppressWarnings({ "squid:S2095" }) - public List visit(final ComparisonNode node, final String param) { - final QuertPath queryPath = getQuertPath(node); - - final List values = node.getArguments(); - final List transformedValues = new ArrayList<>(); - final Path fieldPath = getFieldPath(queryPath.getEnumValue(), queryPath); - - for (final String value : values) { - transformedValues.add(convertValueIfNecessary(node, queryPath.getEnumValue(), value, fieldPath)); - } - - this.joinsNeeded = this.joinsNeeded || areJoinsNeeded(node); - - return mapToPredicate(node, fieldPath, node.getArguments(), transformedValues, queryPath); - } - - private static boolean areJoinsNeeded(final ComparisonNode node) { - return !NO_JOINS_OPERATOR.contains(node.getOperator().getSymbol()); - } - private Object convertValueIfNecessary(final ComparisonNode node, final A fieldName, final String value, final Path fieldPath) { // in case the value of an RSQL query e.g. type==application is an @@ -283,27 +337,6 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends } } - // Exception squid:S2095 - see - // https://jira.sonarsource.com/browse/SONARJAVA-1478 - @SuppressWarnings({ "rawtypes", "unchecked", "squid:S2095" }) - private static Object transformEnumValue(final ComparisonNode node, final String value, final Class javaType) { - final Class tmpEnumType = (Class) javaType; - try { - return Enum.valueOf(tmpEnumType, value.toUpperCase()); - } catch (final IllegalArgumentException e) { - // we could not transform the given string value into the enum - // type, so ignore it and return null and do not filter - log.info("given value {} cannot be transformed into the correct enum type {}", value.toUpperCase(), - javaType); - log.debug("value cannot be transformed to an enum", e); - - throw new RSQLParameterUnsupportedFieldException("field {" + node.getSelector() - + "} must be one of the following values {" + Arrays.stream(tmpEnumType.getEnumConstants()) - .map(v -> v.name().toLowerCase()).toList() - + "}", e); - } - } - private List mapToPredicate(final ComparisonNode node, final Path fieldPath, final List values, final List transformedValues, final QuertPath queryPath) { @@ -331,25 +364,25 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends final String operator = node.getOperator().getSymbol(); switch (operator) { - case "==": - return getEqualToPredicate(transformedValue, fieldPath); - case "!=": - return getNotEqualToPredicate(transformedValue, fieldPath, queryPath); - case "=gt=": - return cb.greaterThan(pathOfString(fieldPath), value); - case "=ge=": - return cb.greaterThanOrEqualTo(pathOfString(fieldPath), value); - case "=lt=": - return cb.lessThan(pathOfString(fieldPath), value); - case "=le=": - return cb.lessThanOrEqualTo(pathOfString(fieldPath), value); - case "=in=": - return in(pathOfString(fieldPath), transformedValues); - case "=out=": - return getOutPredicate(transformedValues, queryPath, fieldPath); - default: - throw new RSQLParameterSyntaxException( - "operator symbol {" + operator + "} is either not supported or not implemented"); + case "==": + return getEqualToPredicate(transformedValue, fieldPath); + case "!=": + return getNotEqualToPredicate(transformedValue, fieldPath, queryPath); + case "=gt=": + return cb.greaterThan(pathOfString(fieldPath), value); + case "=ge=": + return cb.greaterThanOrEqualTo(pathOfString(fieldPath), value); + case "=lt=": + return cb.lessThan(pathOfString(fieldPath), value); + case "=le=": + return cb.lessThanOrEqualTo(pathOfString(fieldPath), value); + case "=in=": + return in(pathOfString(fieldPath), transformedValues); + case "=out=": + return getOutPredicate(transformedValues, queryPath, fieldPath); + default: + throw new RSQLParameterSyntaxException( + "operator symbol {" + operator + "} is either not supported or not implemented"); } } @@ -365,7 +398,8 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends clearOuterJoinsIfNotNeeded(); - return toNotExistsSubQueryPredicate(fieldNames, queryPath.getEnumValue(), expressionToCompare -> in(expressionToCompare, transformedValues)); + return toNotExistsSubQueryPredicate(fieldNames, queryPath.getEnumValue(), + expressionToCompare -> in(expressionToCompare, transformedValues)); } private Path getMapValueFieldPath(final A enumField, final Path fieldPath) { @@ -442,9 +476,11 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends clearOuterJoinsIfNotNeeded(); if (isPattern(transformedValueStr)) { // a pattern, use like - return toNotExistsSubQueryPredicate(fieldNames, queryPath.getEnumValue(), expressionToCompare -> like(expressionToCompare, toSQL(transformedValueStr))); + return toNotExistsSubQueryPredicate(fieldNames, queryPath.getEnumValue(), + expressionToCompare -> like(expressionToCompare, toSQL(transformedValueStr))); } else { - return toNotExistsSubQueryPredicate(fieldNames, queryPath.getEnumValue(), expressionToCompare -> equal(expressionToCompare, transformedValueStr)); + return toNotExistsSubQueryPredicate(fieldNames, queryPath.getEnumValue(), + expressionToCompare -> equal(expressionToCompare, transformedValueStr)); } } @@ -480,10 +516,6 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends return cb.not(cb.exists(subquery)); } - private static boolean isSimpleField(final String[] split, final boolean isMapKeyField) { - return split.length == 1 || (split.length == 2 && isMapKeyField); - } - @SuppressWarnings({ "rawtypes", "unchecked" }) private Expression getExpressionToCompare(final Path innerFieldPath, final A enumField) { if (!enumField.isMap()) { @@ -499,30 +531,6 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends return pathOfString(innerFieldPath).get(valueFieldName); } - private static Path getInnerFieldPath(final Root subqueryRoot, final String[] split, - final boolean isMapKeyField) { - return getFieldPath(subqueryRoot, split, isMapKeyField, - (fieldPath, fieldNameSplit) -> getInnerJoinFieldPath(subqueryRoot, fieldPath, fieldNameSplit)) - .orElseThrow(() -> new RSQLParameterUnsupportedFieldException("RSQL field path cannot be empty", - null)); - } - - private static Path getInnerJoinFieldPath(final Root subqueryRoot, final Path fieldPath, - final String fieldNameSplit) { - if (fieldPath instanceof Join) { - return subqueryRoot.join(fieldNameSplit, JoinType.INNER); - } - return fieldPath; - } - - private static boolean isPattern(final String transformedValue) { - if (transformedValue.contains(ESCAPE_CHAR_WITH_ASTERISK)) { - return transformedValue.replace(ESCAPE_CHAR_WITH_ASTERISK, "$").indexOf(LIKE_WILDCARD) != -1; - } else { - return transformedValue.indexOf(LIKE_WILDCARD) != -1; - } - } - private String toSQL(final String transformedValue) { final String escaped; @@ -545,11 +553,6 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends return finalizedValue; } - @SuppressWarnings("unchecked") - private static Path pathOfString(final Path path) { - return (Path) path; - } - private List acceptChildren(final LogicalNode node) { final List children = node.getChildren(); final List childs = new ArrayList<>(); @@ -567,15 +570,19 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends private Predicate equal(final Expression expressionToCompare, final String sqlValue) { return cb.equal(caseWise(cb, expressionToCompare), caseWise(sqlValue)); } + private Predicate notEqual(final Expression expressionToCompare, String transformedValueStr) { return cb.notEqual(caseWise(cb, expressionToCompare), caseWise(transformedValueStr)); } + private Predicate like(final Expression expressionToCompare, final String sqlValue) { return cb.like(caseWise(cb, expressionToCompare), caseWise(sqlValue), ESCAPE_CHAR); } + private Predicate notLike(final Expression expressionToCompare, final String sqlValue) { return cb.notLike(caseWise(cb, expressionToCompare), caseWise(sqlValue), ESCAPE_CHAR); } + private Predicate in(final Expression expressionToCompare, final List transformedValues) { final List inParams = transformedValues.stream().filter(String.class::isInstance) .map(String.class::cast).map(this::caseWise).collect(Collectors.toList()); @@ -585,6 +592,7 @@ public class JpaQueryRsqlVisitor & RsqlQueryField, T> extends private Expression caseWise(final CriteriaBuilder cb, final Expression expression) { return ensureIgnoreCase ? cb.upper(expression) : expression; } + private String caseWise(final String str) { return ensureIgnoreCase ? str.toUpperCase() : str; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitorG2.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitorG2.java index bdab25bff..61e2f004a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitorG2.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitorG2.java @@ -18,6 +18,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.function.Function; import java.util.stream.Collectors; + import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Expression; @@ -27,6 +28,9 @@ import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; +import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.SingularAttribute; +import jakarta.persistence.metamodel.Type; import cz.jirutka.rsql.parser.ast.AndNode; import cz.jirutka.rsql.parser.ast.ComparisonNode; @@ -34,13 +38,10 @@ import cz.jirutka.rsql.parser.ast.LogicalNode; import cz.jirutka.rsql.parser.ast.Node; import cz.jirutka.rsql.parser.ast.OrNode; import cz.jirutka.rsql.parser.ast.RSQLVisitor; -import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.SingularAttribute; -import jakarta.persistence.metamodel.Type; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.math.NumberUtils; -import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.FieldValueConverter; +import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; @@ -62,7 +63,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> public static final Character LIKE_WILDCARD = '*'; private static final char ESCAPE_CHAR = '\\'; - private static final String ESCAPE_CHAR_WITH_ASTERISK = ESCAPE_CHAR +"*"; + private static final String ESCAPE_CHAR_WITH_ASTERISK = ESCAPE_CHAR + "*"; private final Root root; private final CriteriaQuery query; @@ -72,9 +73,8 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> private final boolean ensureIgnoreCase; private final SimpleTypeConverter simpleTypeConverter = new SimpleTypeConverter(); - - private boolean inOr; private final Map, Path> javaTypeToPath = new HashMap<>(); + private boolean inOr; public JpaQueryRsqlVisitorG2(final Class enumType, final Root root, final CriteriaQuery query, final CriteriaBuilder cb, @@ -121,6 +121,42 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> return mapToPredicate(node, queryField, fieldPath, node.getArguments(), transformedValues); } + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static Object transformEnumValue(final ComparisonNode node, final Class javaType, final String value) { + final Class tmpEnumType = (Class) javaType; + try { + return Enum.valueOf(tmpEnumType, value.toUpperCase()); + } catch (final IllegalArgumentException e) { + // we could not transform the given string value into the enum + // type, so ignore it and return null and do not filter + log.info("given value {} cannot be transformed into the correct enum type {}", value.toUpperCase(), + javaType); + log.debug("value cannot be transformed to an enum", e); + + throw new RSQLParameterUnsupportedFieldException("field {" + node.getSelector() + + "} must be one of the following values {" + Arrays.stream(tmpEnumType.getEnumConstants()) + .map(v -> v.name().toLowerCase()).toList() + + "}", e); + } + } + + private static boolean isSimpleField(final String[] split, final boolean isMapKeyField) { + return split.length == 1 || (split.length == 2 && isMapKeyField); + } + + @SuppressWarnings("unchecked") + private static Path pathOfString(final Path path) { + return (Path) path; + } + + private static boolean isPattern(final String transformedValue) { + if (transformedValue.contains(ESCAPE_CHAR_WITH_ASTERISK)) { + return transformedValue.replace(ESCAPE_CHAR_WITH_ASTERISK, "$").indexOf(LIKE_WILDCARD) != -1; + } else { + return transformedValue.indexOf(LIKE_WILDCARD) != -1; + } + } + private List mapToPredicate(final ComparisonNode node, final QuertPath queryField, final Path fieldPath, final List values, final List transformedValues) { @@ -133,6 +169,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> return Collections.singletonList(mapPredicate != null ? cb.and(mapPredicate, valuePredicate) : valuePredicate); } + private Path getValueFieldPath(final A enumField, final Path fieldPath) { if (enumField.isMap()) { final Path mapValuePath = enumField.getSubEntityMapTuple().map(Entry::getValue).map(fieldPath::get).orElse(null); @@ -141,6 +178,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> return fieldPath; } } + @SuppressWarnings("unchecked") private Predicate mapToMapPredicate(final QuertPath queryField, final Path fieldPath) { final String[] graph = queryField.getJpaPath(); @@ -156,6 +194,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> "SimpleImmutableEntry are allowed. Neither of those could be found!")); return equal(fieldPath.get(keyFieldName), keyValue); } + private Predicate addOperatorPredicate(final ComparisonNode node, final QuertPath queryField, final Path fieldPath, final List transformedValues, final String value) { // only 'equal' and 'notEqual' can handle transformed value like enums. @@ -175,6 +214,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> "Operator symbol {" + operator + "} is either not supported or not implemented"); }; } + private Predicate getEqualToPredicate(final Path fieldPath, final Object transformedValue) { if (transformedValue == null) { return cb.isNull(fieldPath); @@ -218,9 +258,9 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> } return toNotExistsSubQueryPredicate(queryField, fieldPath, expressionToCompare -> - isPattern(transformedValueStr) ? // a pattern, use like - like(expressionToCompare, toSQL(transformedValueStr)) : - equal(expressionToCompare, transformedValueStr)); + isPattern(transformedValueStr) ? // a pattern, use like + like(expressionToCompare, toSQL(transformedValueStr)) : + equal(expressionToCompare, transformedValueStr)); } return toNullOrNotEqualPredicate(fieldPath, transformedValue); @@ -249,6 +289,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> } return fieldPath; } + // if root.get creates a join we call join directly in order to specify LEFT JOIN type, // to include rows for missing in particular table / criteria (root.get creates INNER JOIN) // (see org.eclipse.persistence.internal.jpa.querydef.FromImpl implementation for more details) @@ -292,24 +333,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> return value; } - @SuppressWarnings({ "rawtypes", "unchecked" }) - private static Object transformEnumValue(final ComparisonNode node, final Class javaType, final String value) { - final Class tmpEnumType = (Class) javaType; - try { - return Enum.valueOf(tmpEnumType, value.toUpperCase()); - } catch (final IllegalArgumentException e) { - // we could not transform the given string value into the enum - // type, so ignore it and return null and do not filter - log.info("given value {} cannot be transformed into the correct enum type {}", value.toUpperCase(), - javaType); - log.debug("value cannot be transformed to an enum", e); - throw new RSQLParameterUnsupportedFieldException("field {" + node.getSelector() - + "} must be one of the following values {" + Arrays.stream(tmpEnumType.getEnumConstants()) - .map(v -> v.name().toLowerCase()).toList() - + "}", e); - } - } private Object convertBooleanValue(final ComparisonNode node, final Class javaType, final String value) { try { return simpleTypeConverter.convertIfNecessary(value, javaType); @@ -320,6 +344,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> e); } } + @SuppressWarnings({ "rawtypes", "unchecked" }) private Object convertFieldConverterValue(final ComparisonNode node, final A fieldName, final String value) { final Object convertedValue = ((FieldValueConverter) fieldName).convertValue(fieldName, value); @@ -342,7 +367,8 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> } @SuppressWarnings({ "unchecked", "rawtypes" }) - private Predicate toNotExistsSubQueryPredicate(final QuertPath queryField, final Path fieldPath, final Function, Predicate> subQueryPredicateProvider) { + private Predicate toNotExistsSubQueryPredicate(final QuertPath queryField, final Path fieldPath, + final Function, Predicate> subQueryPredicateProvider) { // if a subquery the field's parent joins are not actually used if (!inOr) { // so, if not in or (hence not reused) we remove them. Parent shall be a Join @@ -360,6 +386,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> subQueryPredicateProvider.apply(getExpressionToCompare(queryField.getEnumValue(), getFieldPath(subqueryRoot, queryField))))))); } + @SuppressWarnings({ "rawtypes", "unchecked" }) private Expression getExpressionToCompare(final A enumField, final Path fieldPath) { if (!enumField.isMap()) { @@ -371,7 +398,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> } return enumField.getSubEntityMapTuple() .map(Entry::getValue) - .map(valueFieldName -> fieldPath.get(valueFieldName)) + .map(valueFieldName -> fieldPath. get(valueFieldName)) .orElseThrow(() -> new UnsupportedOperationException( "For the fields, defined as Map, only Map java type or tuple in the form of SimpleImmutableEntry are allowed. Neither of those could be found!")); } @@ -385,6 +412,7 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> } return replaceIfRequired(escaped); } + private String replaceIfRequired(final String escapedValue) { final String finalizedValue; if (escapedValue.contains(ESCAPE_CHAR_WITH_ASTERISK)) { @@ -412,15 +440,19 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> private Predicate equal(final Expression expressionToCompare, final String sqlValue) { return cb.equal(caseWise(cb, expressionToCompare), caseWise(sqlValue)); } + private Predicate notEqual(final Expression expressionToCompare, String transformedValueStr) { return cb.notEqual(caseWise(cb, expressionToCompare), caseWise(transformedValueStr)); } + private Predicate like(final Expression expressionToCompare, final String sqlValue) { return cb.like(caseWise(cb, expressionToCompare), caseWise(sqlValue), ESCAPE_CHAR); } + private Predicate notLike(final Expression expressionToCompare, final String sqlValue) { return cb.notLike(caseWise(cb, expressionToCompare), caseWise(sqlValue), ESCAPE_CHAR); } + private Predicate in(final Expression expressionToCompare, final List transformedValues) { final List inParams = transformedValues.stream().filter(String.class::isInstance) .map(String.class::cast).map(this::caseWise).collect(Collectors.toList()); @@ -430,24 +462,8 @@ public class JpaQueryRsqlVisitorG2 & RsqlQueryField, T> private Expression caseWise(final CriteriaBuilder cb, final Expression expression) { return ensureIgnoreCase ? cb.upper(expression) : expression; } + private String caseWise(final String str) { return ensureIgnoreCase ? str.toUpperCase() : str; } - - private static boolean isSimpleField(final String[] split, final boolean isMapKeyField) { - return split.length == 1 || (split.length == 2 && isMapKeyField); - } - - @SuppressWarnings("unchecked") - private static Path pathOfString(final Path path) { - return (Path) path; - } - - private static boolean isPattern(final String transformedValue) { - if (transformedValue.contains(ESCAPE_CHAR_WITH_ASTERISK)) { - return transformedValue.replace(ESCAPE_CHAR_WITH_ASTERISK, "$").indexOf(LIKE_WILDCARD) != -1; - } else { - return transformedValue.indexOf(LIKE_WILDCARD) != -1; - } - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/ParseExceptionWrapper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/ParseExceptionWrapper.java index 6c84e8a57..74efddcc2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/ParseExceptionWrapper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/ParseExceptionWrapper.java @@ -12,9 +12,8 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import java.lang.reflect.Field; import java.util.Arrays; -import org.springframework.util.ReflectionUtils; - import cz.jirutka.rsql.parser.ParseException; +import org.springframework.util.ReflectionUtils; /** * A {@link ParseException} wrapper which allows to access the parsing @@ -29,10 +28,9 @@ public class ParseExceptionWrapper { /** * Constructor. - * - * @param parseException - * the original parsing exception object to access its field - * using reflection + * + * @param parseException the original parsing exception object to access its field + * using reflection */ public ParseExceptionWrapper(final ParseException parseException) { this.parseException = parseException; @@ -62,7 +60,6 @@ public class ParseExceptionWrapper { + ", getCurrentToken()=" + getCurrentToken() + "]"; } - /** * A {@link TokenWrapper} which wraps the * {@code cz.jirutka.rsql.parser.Token} class of the {@link ParseException} @@ -151,6 +148,13 @@ public class ParseExceptionWrapper { return (int) getValue(endColumnTokenField); } + @Override + public String toString() { + return "TokenWrapper [tokenInstance=" + tokenInstance + ", getNext()=" + getNext() + ", getKind()=" + + getKind() + ", getImage()=" + getImage() + ", getBeginColumn()=" + getBeginColumn() + + ", getEndColumn()=" + getEndColumn() + "]"; + } + private Field getAccessibleField(final String field) throws NoSuchFieldException { final Field declaredField = tokenInstance.getClass().getDeclaredField(field); ReflectionUtils.makeAccessible(declaredField); @@ -164,16 +168,10 @@ public class ParseExceptionWrapper { throw new IllegalFieldAccessExeption(e); } } - - @Override - public String toString() { - return "TokenWrapper [tokenInstance=" + tokenInstance + ", getNext()=" + getNext() + ", getKind()=" - + getKind() + ", getImage()=" + getImage() + ", getBeginColumn()=" + getBeginColumn() - + ", getEndColumn()=" + getEndColumn() + "]"; - } } static class IllegalFieldAccessExeption extends RuntimeException { + public IllegalFieldAccessExeption(Throwable e) { super(e); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/PropertyMapper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/PropertyMapper.java index 49aa6dda3..062d0f8b9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/PropertyMapper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/PropertyMapper.java @@ -14,9 +14,6 @@ import java.util.Map; /** * Maps property of entity to its alias . - * - * - * */ public final class PropertyMapper { @@ -28,13 +25,10 @@ public final class PropertyMapper { /** * Add new mapping - property name and alias. - * - * @param type - * entity type - * @param property - * alias of property - * @param mapping - * property name + * + * @param type entity type + * @param property alias of property + * @param mapping property name */ public static void addNewMapping(final Class type, final String property, final String mapping) { allowedColumns.computeIfAbsent(type, k -> new HashMap<>()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java index 799d97e3c..8c84cb2c4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java @@ -18,6 +18,12 @@ import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; +import cz.jirutka.rsql.parser.RSQLParser; +import cz.jirutka.rsql.parser.RSQLParserException; +import cz.jirutka.rsql.parser.ast.ComparisonOperator; +import cz.jirutka.rsql.parser.ast.Node; +import cz.jirutka.rsql.parser.ast.RSQLOperators; +import cz.jirutka.rsql.parser.ast.RSQLVisitor; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -32,13 +38,6 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.jpa.vendor.Database; import org.springframework.util.CollectionUtils; -import cz.jirutka.rsql.parser.RSQLParser; -import cz.jirutka.rsql.parser.RSQLParserException; -import cz.jirutka.rsql.parser.ast.ComparisonOperator; -import cz.jirutka.rsql.parser.ast.Node; -import cz.jirutka.rsql.parser.ast.RSQLOperators; -import cz.jirutka.rsql.parser.ast.RSQLVisitor; - /** * A utility class which is able to parse RSQL strings into an spring data * {@link Specification} which then can be enhanced sql queries to filter @@ -85,7 +84,6 @@ public final class RSQLUtility { * @param fieldNameProvider the enum class type which implements the {@link RsqlQueryField} * @param virtualPropertyReplacer holds the logic how the known macros have to be resolved; may be null * @param database database in use - * * @return a specification which can be used with JPA * @throws RSQLParameterUnsupportedFieldException if a field in the RSQL string is used but not provided by the * given {@code fieldNameProvider} @@ -99,10 +97,9 @@ public final class RSQLUtility { /** * Validates the RSQL string - * + * * @param rsql RSQL string to validate * @param fieldNameProvider - * * @throws RSQLParserException if RSQL syntax is invalid * @throws RSQLParameterUnsupportedFieldException if RSQL key is not allowed */ @@ -119,7 +116,9 @@ public final class RSQLUtility { try { final Set operators = RSQLOperators.defaultOperators(); return new RSQLParser(operators).parse( - RsqlConfigHolder.getInstance().isCaseInsensitiveDB() || RsqlConfigHolder.getInstance().isIgnoreCase() ? rsql.toLowerCase() : rsql); + RsqlConfigHolder.getInstance().isCaseInsensitiveDB() || RsqlConfigHolder.getInstance().isIgnoreCase() + ? rsql.toLowerCase() + : rsql); } catch (final IllegalArgumentException e) { throw new RSQLParameterSyntaxException("RSQL filter must not be null", e); } catch (final RSQLParserException e) { @@ -157,10 +156,11 @@ public final class RSQLUtility { virtualPropertyReplacer, database, query, !RsqlConfigHolder.getInstance().isCaseInsensitiveDB() && RsqlConfigHolder.getInstance().isIgnoreCase()) : - new JpaQueryRsqlVisitorG2<>( - enumType, root, query, cb, - database, virtualPropertyReplacer, - !RsqlConfigHolder.getInstance().isCaseInsensitiveDB() && RsqlConfigHolder.getInstance().isIgnoreCase()); + new JpaQueryRsqlVisitorG2<>( + enumType, root, query, cb, + database, virtualPropertyReplacer, + !RsqlConfigHolder.getInstance().isCaseInsensitiveDB() && RsqlConfigHolder.getInstance() + .isIgnoreCase()); final List accept = rootNode.accept(jpqQueryRSQLVisitor); if (CollectionUtils.isEmpty(accept)) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlParserValidationOracle.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlParserValidationOracle.java index b1eec8406..24e20775b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlParserValidationOracle.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlParserValidationOracle.java @@ -22,6 +22,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import cz.jirutka.rsql.parser.ParseException; +import cz.jirutka.rsql.parser.RSQLParserException; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.TargetFields; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; @@ -36,17 +38,14 @@ import org.eclipse.persistence.exceptions.ConversionException; import org.springframework.orm.jpa.JpaSystemException; import org.springframework.util.CollectionUtils; -import cz.jirutka.rsql.parser.ParseException; -import cz.jirutka.rsql.parser.RSQLParserException; - /** * An implementation of {@link RsqlValidationOracle} which retrieves the * exception using the {@link ParseException} to retrieve the suggestions. - * + * * The suggestion only works when there are syntax errors existing because the * information about current and next tokens in the RSQL syntax are from the * {@link ParseException}. - * + * * There is a feature request on the GitHub project * https://github.com * /jirutka/rsql-parser/issues/22 diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/ActionSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/ActionSpecifications.java index 8b8869dc8..8b5a6581f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/ActionSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/ActionSpecifications.java @@ -9,7 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.specifications; -import jakarta.persistence.criteria.CriteriaBuilder; +import java.util.List; + import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.ListJoin; @@ -27,12 +28,9 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.model.Action; import org.springframework.data.jpa.domain.Specification; -import java.util.List; - /** * Utility class for {@link Action}s {@link Specification}s. The class provides * Spring Data JPQL Specifications. - * */ public final class ActionSpecifications { @@ -73,10 +71,10 @@ public final class ActionSpecifications { public static Specification byTargetIdsAndActiveAndStatusAndDSNotRequiredMigrationStep( final List targetIds, final boolean active, final Action.Status status) { return (root, query, cb) -> cb.and( - root.get(JpaAction_.target).in(targetIds), - cb.equal(root.get(JpaAction_.active), active), - cb.equal(root.get(JpaAction_.status), status), - cb.equal(root.get(JpaAction_.distributionSet).get(JpaDistributionSet_.requiredMigrationStep), false)); + root.get(JpaAction_.target).in(targetIds), + cb.equal(root.get(JpaAction_.active), active), + cb.equal(root.get(JpaAction_.status), status), + cb.equal(root.get(JpaAction_.distributionSet).get(JpaDistributionSet_.requiredMigrationStep), false)); } /** @@ -87,7 +85,8 @@ public final class ActionSpecifications { * @param isNull if true return with null weight, otherwise with non-null * @return the matching action s. */ - public static Specification byTargetControllerIdAndActiveAndWeightIsNullFetchDS(final String controllerId, final boolean isNull) { + public static Specification byTargetControllerIdAndActiveAndWeightIsNullFetchDS(final String controllerId, + final boolean isNull) { return (root, query, cb) -> { root.fetch(JpaAction_.distributionSet, JoinType.LEFT); return cb.and( @@ -119,13 +118,11 @@ public final class ActionSpecifications { * Specification which joins all necessary tables to retrieve the dependency * between a target and a local file assignment through the assigned action * of the target. All actions are included, not only active actions. - * - * @param controllerId - * the target to verify if the given artifact is currently - * assigned or had been assigned - * @param sha1Hash - * of the local artifact to check wherever the target had ever - * been assigned + * + * @param controllerId the target to verify if the given artifact is currently + * assigned or had been assigned + * @param sha1Hash of the local artifact to check wherever the target had ever + * been assigned * @return a specification to use with spring JPA */ public static Specification hasTargetAssignedArtifact(final String controllerId, final String sha1Hash) { @@ -144,13 +141,11 @@ public final class ActionSpecifications { * Specification which joins all necessary tables to retrieve the dependency * between a target and a local file assignment through the assigned action * of the target. All actions are included, not only active actions. - * - * @param targetId - * the target to verify if the given artifact is currently - * assigned or had been assigned - * @param sha1Hash - * of the local artifact to check wherever the target had ever - * been assigned + * + * @param targetId the target to verify if the given artifact is currently + * assigned or had been assigned + * @param sha1Hash of the local artifact to check wherever the target had ever + * been assigned * @return a specification to use with spring JPA */ public static Specification hasTargetAssignedArtifact(final Long targetId, final String sha1Hash) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetSpecification.java index 128e0da9a..befac180b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetSpecification.java @@ -58,23 +58,20 @@ public final class DistributionSetSpecification { * {@link Specification} for retrieving {@link DistributionSet}s by its * DELETED attribute. * - * @param isDeleted - * TRUE/FALSE are compared to the attribute DELETED. If NULL the - * attribute is ignored + * @param isDeleted TRUE/FALSE are compared to the attribute DELETED. If NULL the + * attribute is ignored * @return the {@link DistributionSet} {@link Specification} */ public static Specification isDeleted(final Boolean isDeleted) { return (dsRoot, query, cb) -> cb.equal(dsRoot. get(JpaDistributionSet_.deleted), isDeleted); } - /** * {@link Specification} for retrieving {@link DistributionSet}s by its * COMPLETED attribute. * - * @param isCompleted - * TRUE/FALSE are compared to the attribute COMPLETED. If NULL the - * attribute is ignored + * @param isCompleted TRUE/FALSE are compared to the attribute COMPLETED. If NULL the + * attribute is ignored * @return the {@link DistributionSet} {@link Specification} */ public static Specification isCompleted(final Boolean isCompleted) { @@ -85,9 +82,8 @@ public final class DistributionSetSpecification { * {@link Specification} for retrieving {@link DistributionSet}s by its VALID * attribute. * - * @param isValid - * TRUE/FALSE are compared to the attribute VALID. If NULL the - * attribute is ignored + * @param isValid TRUE/FALSE are compared to the attribute VALID. If NULL the + * attribute is ignored * @return the {@link DistributionSet} {@link Specification} */ public static Specification isValid(final Boolean isValid) { @@ -98,8 +94,7 @@ public final class DistributionSetSpecification { * {@link Specification} for retrieving {@link DistributionSet} with given * {@link DistributionSet#getId()}. * - * @param distid - * to search + * @param distid to search * @return the {@link DistributionSet} {@link Specification} */ public static Specification byId(final Long distid) { @@ -117,8 +112,7 @@ public final class DistributionSetSpecification { * {@link Specification} for retrieving {@link DistributionSet} with given * {@link DistributionSet#getId()}s. * - * @param distids - * to search + * @param distids to search * @return the {@link DistributionSet} {@link Specification} */ public static Specification byIds(final Collection distids) { @@ -136,10 +130,8 @@ public final class DistributionSetSpecification { * {@link Specification} for retrieving {@link DistributionSet}s by "like name * and like version". * - * @param name - * to be filtered on - * @param version - * to be filtered on + * @param name to be filtered on + * @param version to be filtered on * @return the {@link DistributionSet} {@link Specification} */ public static Specification likeNameAndVersion(final String name, final String version) { @@ -152,10 +144,8 @@ public final class DistributionSetSpecification { * {@link Specification} for retrieving {@link DistributionSet}s by "has at * least one of the given tag names". * - * @param tagNames - * to be filtered on - * @param selectDSWithNoTag - * flag to select distribution sets with no tag + * @param tagNames to be filtered on + * @param selectDSWithNoTag flag to select distribution sets with no tag * @return the {@link DistributionSet} {@link Specification} */ public static Specification hasTags(final Collection tagNames, @@ -167,6 +157,96 @@ public final class DistributionSetSpecification { }; } + /** + * returns query criteria {@link Specification} comparing case insensitive "NAME + * == AND VERSION ==". + * + * @param name to be filtered on + * @param version to be filtered on + * @return the {@link Specification} + */ + public static Specification equalsNameAndVersionIgnoreCase(final String name, + final String version) { + return (dsRoot, query, cb) -> cb.and( + cb.equal(cb.lower(dsRoot. get(JpaDistributionSet_.name)), name.toLowerCase()), + cb.equal(cb.lower(dsRoot. get(JpaDistributionSet_.version)), version.toLowerCase())); + + } + + /** + * {@link Specification} for retrieving {@link DistributionSet} with given + * {@link DistributionSet#getType()}. + * + * @param typeId id of distribution set type to search + * @return the {@link DistributionSet} {@link Specification} + */ + public static Specification byType(final Long typeId) { + return (dsRoot, query, cb) -> cb.equal(dsRoot.get(JpaDistributionSet_.type).get(JpaDistributionSetType_.id), + typeId); + } + + /** + * {@link Specification} for retrieving {@link DistributionSet} for given id + * collection of {@link DistributionSet#getType()}. + * + * @param typeIds id collection of distribution set type to search + * @return the {@link DistributionSet} {@link Specification} + */ + public static Specification hasType(final Collection typeIds) { + return (dsRoot, query, cb) -> dsRoot.get(JpaDistributionSet_.type).get(JpaDistributionSetType_.id).in(typeIds); + } + + /** + * {@link Specification} for retrieving {@link DistributionSet}s by tag. + * + * @param tagId the ID of the distribution set which must be assigned + * @return the {@link DistributionSet} {@link Specification} + */ + public static Specification hasTag(final Long tagId) { + + return (dsRoot, query, cb) -> { + final SetJoin tags = dsRoot.join(JpaDistributionSet_.tags, + JoinType.LEFT); + return cb.equal(tags.get(JpaDistributionSetTag_.id), tagId); + }; + } + + /** + * Can be added to specification chain to order result by provided target + * + * Order: 1. Distribution set installed on target, 2. Distribution set(s) + * assigned to target, 3. Based on requested sorting or id if null. + * + * NOTE: Other specs, pagables and sort objects may alter the queries orderBy + * entry too, possibly invalidating the applied order, keep in mind when using + * this + * + * @param linkedControllerId controller id to get installed/assigned DS for + * @param sort + * @return specification that applies order by target, may be overwritten + */ + public static Specification orderedByLinkedTarget(final String linkedControllerId, + final Sort sort) { + return (dsRoot, query, cb) -> { + final Root targetRoot = query.from(JpaTarget.class); + + final Expression assignedInstalledCase = cb.selectCase() + .when(cb.equal(targetRoot.get(JpaTarget_.installedDistributionSet), dsRoot), 1) + .when(cb.equal(targetRoot.get(JpaTarget_.assignedDistributionSet), dsRoot), 2).otherwise(3); + + final List orders = new ArrayList<>(); + orders.add(cb.asc(assignedInstalledCase)); + if (sort == null || sort.isEmpty()) { + orders.add(cb.asc(dsRoot.get(JpaDistributionSet_.id))); + } else { + orders.addAll(QueryUtils.toOrders(sort, dsRoot, cb)); + } + query.orderBy(orders); + + return cb.equal(targetRoot.get(JpaTarget_.controllerId), linkedControllerId); + }; + } + private static Predicate getHasTagsPredicate(final Root dsRoot, final CriteriaBuilder cb, final Boolean selectDSWithNoTag, final Collection tagNames) { final SetJoin tags = dsRoot.join(JpaDistributionSet_.tags, @@ -192,101 +272,4 @@ public final class DistributionSetSpecification { private static boolean isAtLeastOneTagActive(final Collection tagNames) { return !CollectionUtils.isEmpty(tagNames); } - - /** - * returns query criteria {@link Specification} comparing case insensitive "NAME - * == AND VERSION ==". - * - * @param name - * to be filtered on - * @param version - * to be filtered on - * @return the {@link Specification} - */ - public static Specification equalsNameAndVersionIgnoreCase(final String name, - final String version) { - return (dsRoot, query, cb) -> cb.and( - cb.equal(cb.lower(dsRoot. get(JpaDistributionSet_.name)), name.toLowerCase()), - cb.equal(cb.lower(dsRoot. get(JpaDistributionSet_.version)), version.toLowerCase())); - - } - - /** - * {@link Specification} for retrieving {@link DistributionSet} with given - * {@link DistributionSet#getType()}. - * - * @param typeId - * id of distribution set type to search - * @return the {@link DistributionSet} {@link Specification} - */ - public static Specification byType(final Long typeId) { - return (dsRoot, query, cb) -> cb.equal(dsRoot.get(JpaDistributionSet_.type).get(JpaDistributionSetType_.id), - typeId); - } - - /** - * {@link Specification} for retrieving {@link DistributionSet} for given id - * collection of {@link DistributionSet#getType()}. - * - * - * @param typeIds - * id collection of distribution set type to search - * @return the {@link DistributionSet} {@link Specification} - */ - public static Specification hasType(final Collection typeIds) { - return (dsRoot, query, cb) -> dsRoot.get(JpaDistributionSet_.type).get(JpaDistributionSetType_.id).in(typeIds); - } - - /** - * {@link Specification} for retrieving {@link DistributionSet}s by tag. - * - * @param tagId - * the ID of the distribution set which must be assigned - * @return the {@link DistributionSet} {@link Specification} - */ - public static Specification hasTag(final Long tagId) { - - return (dsRoot, query, cb) -> { - final SetJoin tags = dsRoot.join(JpaDistributionSet_.tags, - JoinType.LEFT); - return cb.equal(tags.get(JpaDistributionSetTag_.id), tagId); - }; - } - - /** - * Can be added to specification chain to order result by provided target - * - * Order: 1. Distribution set installed on target, 2. Distribution set(s) - * assigned to target, 3. Based on requested sorting or id if null. - * - * NOTE: Other specs, pagables and sort objects may alter the queries orderBy - * entry too, possibly invalidating the applied order, keep in mind when using - * this - * - * @param linkedControllerId - * controller id to get installed/assigned DS for - * @param sort - * @return specification that applies order by target, may be overwritten - */ - public static Specification orderedByLinkedTarget(final String linkedControllerId, - final Sort sort) { - return (dsRoot, query, cb) -> { - final Root targetRoot = query.from(JpaTarget.class); - - final Expression assignedInstalledCase = cb.selectCase() - .when(cb.equal(targetRoot.get(JpaTarget_.installedDistributionSet), dsRoot), 1) - .when(cb.equal(targetRoot.get(JpaTarget_.assignedDistributionSet), dsRoot), 2).otherwise(3); - - final List orders = new ArrayList<>(); - orders.add(cb.asc(assignedInstalledCase)); - if (sort == null || sort.isEmpty()) { - orders.add(cb.asc(dsRoot.get(JpaDistributionSet_.id))); - } else { - orders.addAll(QueryUtils.toOrders(sort, dsRoot, cb)); - } - query.orderBy(orders); - - return cb.equal(targetRoot.get(JpaTarget_.controllerId), linkedControllerId); - }; - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTagSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTagSpecifications.java index 0419acf8e..1592adaf6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTagSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTagSpecifications.java @@ -9,12 +9,12 @@ */ package org.eclipse.hawkbit.repository.jpa.specifications; +import jakarta.validation.constraints.NotEmpty; + import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag_; import org.springframework.data.jpa.domain.Specification; -import jakarta.validation.constraints.NotEmpty; - /** * Utility class for {@link JpaDistributionSetTag}s {@link Specification}s. The class provides * Spring Data JPQL Specifications. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTypeSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTypeSpecification.java index 64c97dd74..b0e2664e0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTypeSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTypeSpecification.java @@ -20,6 +20,7 @@ import org.springframework.data.jpa.domain.Specification; * Spring Data JPQL Specifications. */ public final class DistributionSetTypeSpecification { + private DistributionSetTypeSpecification() { // utility class } @@ -39,8 +40,7 @@ public final class DistributionSetTypeSpecification { * given {@link DistributionSetType#getName()} including fetching the * elements list. * - * @param name - * to search + * @param name to search * @return the {@link DistributionSet} {@link Specification} */ public static Specification byName(final String name) { @@ -52,8 +52,7 @@ public final class DistributionSetTypeSpecification { * given {@link DistributionSetType#getKey()} including fetching the * elements list. * - * @param key - * to search + * @param key to search * @return the {@link DistributionSet} {@link Specification} */ public static Specification byKey(final String key) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/RolloutSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/RolloutSpecification.java index 89e3d56c7..3f9bd348c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/RolloutSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/RolloutSpecification.java @@ -21,9 +21,9 @@ import org.springframework.data.jpa.repository.query.QueryUtils; /** * Specifications class for {@link Rollout}s. The class provides Spring Data * JPQL Specifications. - * */ public final class RolloutSpecification { + private RolloutSpecification() { // utility class } @@ -33,9 +33,8 @@ public final class RolloutSpecification { * attribute. Includes fetch for stuff that is required for {@link Rollout} * queries. * - * @param isDeleted - * TRUE/FALSE are compared to the attribute DELETED. If NULL the - * attribute is ignored + * @param isDeleted TRUE/FALSE are compared to the attribute DELETED. If NULL the + * attribute is ignored * @return the {@link Rollout} {@link Specification} */ public static Specification isDeletedWithDistributionSet(final Boolean isDeleted, final Sort sort) { @@ -52,13 +51,10 @@ public final class RolloutSpecification { /** * Builds a {@link Specification} to search a rollout by name. * - * @param searchText - * search string - * @param isDeleted - * true if deleted rollouts should be included in - * the search. Otherwise false + * @param searchText search string + * @param isDeleted true if deleted rollouts should be included in + * the search. Otherwise false * @return criteria specification with a query for name of a rollout - * */ public static Specification likeName(final String searchText, final boolean isDeleted) { return (rolloutRoot, query, criteriaBuilder) -> { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SoftwareModuleSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SoftwareModuleSpecification.java index c0b0bbf49..b85847c42 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SoftwareModuleSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SoftwareModuleSpecification.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa.specifications; +import jakarta.persistence.criteria.ListJoin; + import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; @@ -18,14 +20,12 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.springframework.data.jpa.domain.Specification; -import jakarta.persistence.criteria.ListJoin; - /** * Specifications class for {@link SoftwareModule}s. The class provides Spring * Data JPQL Specifications - * */ public final class SoftwareModuleSpecification { + private SoftwareModuleSpecification() { // utility class } @@ -34,8 +34,7 @@ public final class SoftwareModuleSpecification { * {@link Specification} for retrieving {@link SoftwareModule} with given * {@link DistributionSet#getId()}. * - * @param swModuleId - * to search + * @param swModuleId to search * @return the {@link SoftwareModule} {@link Specification} */ public static Specification byId(final Long swModuleId) { @@ -52,7 +51,7 @@ public final class SoftwareModuleSpecification { /** * {@link Specification} for retrieving {@link SoftwareModule}s with * DELETED attribute false - i.e. is not deleted. - * + * * @return the {@link SoftwareModule} {@link Specification} */ public static Specification isNotDeleted() { @@ -63,10 +62,8 @@ public final class SoftwareModuleSpecification { * {@link Specification} for retrieving {@link SoftwareModule}s by "like * name and like version". * - * @param name - * to be filtered on - * @param version - * to be filtered on + * @param name to be filtered on + * @param version to be filtered on * @return the {@link SoftwareModule} {@link Specification} */ public static Specification likeNameAndVersion(final String name, final String version) { @@ -78,9 +75,8 @@ public final class SoftwareModuleSpecification { /** * {@link Specification} for retrieving {@link SoftwareModule}s by "like * name or like version". - * - * @param type - * to be filtered on + * + * @param type to be filtered on * @return the {@link SoftwareModule} {@link Specification} */ public static Specification equalType(final Long type) { @@ -90,7 +86,7 @@ public final class SoftwareModuleSpecification { /** * {@link Specification} for fetching {@link SoftwareModule}s type. - * + * * @return the {@link SoftwareModule} {@link Specification} */ public static Specification fetchType() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SpecificationsBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SpecificationsBuilder.java index ee9780d34..7932cfa05 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SpecificationsBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/SpecificationsBuilder.java @@ -15,7 +15,6 @@ import org.springframework.data.jpa.domain.Specification; /** * Helper class to easily combine {@link Specification} instances. - * */ public final class SpecificationsBuilder { @@ -27,8 +26,7 @@ public final class SpecificationsBuilder { * Combine all given specification with and. The first specification is the * where clause. * - * @param specList - * all specification which will combine + * @param specList all specification which will combine * @return if the given specification list is empty */ public static Specification combineWithAnd(final List> specList) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TagSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TagSpecification.java index a95fc2338..34c504249 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TagSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TagSpecification.java @@ -31,7 +31,7 @@ public final class TagSpecification { /** * {@link Specification} for retrieving {@link DistributionSetTag}s by * assigned {@link DistributionSet}. - * + * * @param dsId of the distribution set * @return the {@link JpaDistributionSetTag} {@link Specification} */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetFilterQuerySpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetFilterQuerySpecification.java index 10962105a..6ffd2ea47 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetFilterQuerySpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetFilterQuerySpecification.java @@ -18,9 +18,9 @@ import org.springframework.data.jpa.domain.Specification; /** * Specifications class for {@link TargetFilterQuery}s. The class provides * Spring Data JPQL Specifications. - * */ public final class TargetFilterQuerySpecification { + private TargetFilterQuerySpecification() { // utility class } @@ -29,8 +29,7 @@ public final class TargetFilterQuerySpecification { * {@link Specification} for retrieving {@link JpaTargetFilterQuery}s based * on is {@link JpaTargetFilterQuery#getQuery()}. * - * @param queryValue - * the query of the filter + * @param queryValue the query of the filter * @return the {@link JpaTargetFilterQuery} {@link Specification} */ public static Specification equalsQuery(final String queryValue) { @@ -41,9 +40,8 @@ public final class TargetFilterQuerySpecification { /** * {@link Specification} for retrieving {@link JpaTargetFilterQuery}s based * on is {@link JpaTargetFilterQuery#getName()}. - * - * @param searchText - * of the filter + * + * @param searchText of the filter * @return the {@link JpaTargetFilterQuery} {@link Specification} */ public static Specification likeName(final String searchText) { @@ -57,8 +55,7 @@ public final class TargetFilterQuerySpecification { * {@link Specification} for retrieving {@link JpaTargetFilterQuery}s based * on is {@link JpaTargetFilterQuery#getName()}. * - * @param distributionSet - * of the filter + * @param distributionSet of the filter * @return the {@link JpaTargetFilterQuery} {@link Specification} */ public static Specification byAutoAssignDS(final DistributionSet distributionSet) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java index d40946c32..1a3d924dd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java @@ -100,9 +100,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by controllerId * - * @param id - * to search for - * + * @param id to search for * @return the {@link Target} {@link Specification} */ public static Specification hasId(final Long id) { @@ -112,9 +110,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by controllerId * - * @param ids - * to search for - * + * @param ids to search for * @return the {@link Target} {@link Specification} */ public static Specification hasIdIn(final Collection ids) { @@ -135,9 +131,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link JpaTarget}s including * {@link JpaTarget#getAssignedDistributionSet()}. * - * @param controllerIDs - * to search for - * + * @param controllerIDs to search for * @return the {@link Target} {@link Specification} */ public static Specification byControllerIdWithAssignedDsInJoin(final Collection controllerIDs) { @@ -153,9 +147,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s by "equal to any * given {@link TargetUpdateStatus}". * - * @param updateStatus - * to be filtered on - * + * @param updateStatus to be filtered on * @return the {@link Target} {@link Specification} */ public static Specification hasTargetUpdateStatus(final Collection updateStatus) { @@ -166,9 +158,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s by "equal to given * {@link TargetUpdateStatus}". * - * @param updateStatus - * to be filtered on - * + * @param updateStatus to be filtered on * @return the {@link Target} {@link Specification} */ public static Specification hasTargetUpdateStatus(final TargetUpdateStatus updateStatus) { @@ -179,9 +169,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s by "not equal to * given {@link TargetUpdateStatus}". * - * @param updateStatus - * to be filtered on - * + * @param updateStatus to be filtered on * @return the {@link Target} {@link Specification} */ public static Specification notEqualToTargetUpdateStatus(final TargetUpdateStatus updateStatus) { @@ -194,14 +182,12 @@ public final class TargetSpecifications { * intervals:
* poll_itvl + overdue_itvl * - * @param overdueTimestamp - * the calculated timestamp to compare with the last respond of a - * target (lastTargetQuery).
- * The overdueTimestamp has to be calculated with - * the following expression:
- * overdueTimestamp = nowTimestamp - poll_itvl - - * overdue_itvl - * + * @param overdueTimestamp the calculated timestamp to compare with the last respond of a + * target (lastTargetQuery).
+ * The overdueTimestamp has to be calculated with + * the following expression:
+ * overdueTimestamp = nowTimestamp - poll_itvl - + * overdue_itvl * @return the {@link Target} {@link Specification} */ public static Specification isOverdue(final long overdueTimestamp) { @@ -213,8 +199,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s by "like * controllerId or like name". * - * @param searchText - * to be filtered on + * @param searchText to be filtered on * @return the {@link Target} {@link Specification} */ public static Specification likeControllerIdOrName(final String searchText) { @@ -229,8 +214,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s by "like * controllerId". * - * @param distributionId - * to be filtered on + * @param distributionId to be filtered on * @return the {@link Target} {@link Specification} */ public static Specification hasInstalledOrAssignedDistributionSet(@NotNull final Long distributionId) { @@ -241,17 +225,15 @@ public final class TargetSpecifications { * Finds all targets by given {@link Target#getControllerId()}s and which * are not yet assigned to given {@link DistributionSet}. * - * @param tIDs - * to search for. - * @param distributionId - * set that is not yet assigned + * @param tIDs to search for. + * @param distributionId set that is not yet assigned * @return the {@link Target} {@link Specification} */ public static Specification hasControllerIdAndAssignedDistributionSetIdNot(final List tIDs, @NotNull final Long distributionId) { return (targetRoot, query, cb) -> cb.and(targetRoot.get(JpaTarget_.controllerId).in(tIDs), cb.or(cb.notEqual(targetRoot. get(JpaTarget_.assignedDistributionSet) - .get(JpaDistributionSet_.id), distributionId), + .get(JpaDistributionSet_.id), distributionId), cb.isNull(targetRoot. get(JpaTarget_.assignedDistributionSet)))); } @@ -259,9 +241,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s based on a * {@link TargetTag} name. * - * @param tagName - * to search for - * + * @param tagName to search for * @return the {@link Target} {@link Specification} */ public static Specification hasTagName(final String tagName) { @@ -275,10 +255,8 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s by "has no tag * names"or "has at least on of the given tag names". * - * @param tagNames - * to be filtered on - * @param selectTargetWithNoTag - * flag to get targets with no tag assigned + * @param tagNames to be filtered on + * @param selectTargetWithNoTag flag to get targets with no tag assigned * @return the {@link Target} {@link Specification} */ public static Specification hasTags(final String[] tagNames, final Boolean selectTargetWithNoTag) { @@ -289,37 +267,11 @@ public final class TargetSpecifications { }; } - private static Predicate getHasTagsPredicate(final Root targetRoot, final CriteriaBuilder cb, - final Boolean selectTargetWithNoTag, final String[] tagNames) { - final SetJoin tags = targetRoot.join(JpaTarget_.tags, JoinType.LEFT); - final Path exp = tags.get(JpaTargetTag_.name); - - final List hasTagsPredicates = new ArrayList<>(); - if (isNoTagActive(selectTargetWithNoTag)) { - hasTagsPredicates.add(exp.isNull()); - } - if (isAtLeastOneTagActive(tagNames)) { - hasTagsPredicates.add(exp.in(tagNames)); - } - - return hasTagsPredicates.stream().reduce(cb::or) - .orElseThrow(() -> new RuntimeException("Neither NO_TAG, nor TAG target tag filter was provided!")); - } - - private static boolean isNoTagActive(final Boolean selectTargetWithNoTag) { - return Boolean.TRUE.equals(selectTargetWithNoTag); - } - - private static boolean isAtLeastOneTagActive(final String[] tagNames) { - return tagNames != null && tagNames.length > 0; - } - /** * {@link Specification} for retrieving {@link Target}s by assigned * distribution set. * - * @param distributionSetId - * the ID of the distribution set which must be assigned + * @param distributionSetId the ID of the distribution set which must be assigned * @return the {@link Target} {@link Specification} */ public static Specification hasAssignedDistributionSet(final Long distributionSetId) { @@ -332,8 +284,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s that don't have the * given distribution set in their action history * - * @param distributionSetId - * the ID of the distribution set which must not be assigned + * @param distributionSetId the ID of the distribution set which must not be assigned * @return the {@link Target} {@link Specification} */ public static Specification hasNotDistributionSetInActions(final Long distributionSetId) { @@ -352,8 +303,7 @@ public final class TargetSpecifications { * checking the {@link TargetType} of a target. Targets that don't have a * {@link TargetType} are compatible with all {@link DistributionSetType} * - * @param distributionSetTypeId - * the ID of the distribution set type which must be compatible + * @param distributionSetTypeId the ID of the distribution set type which must be compatible * @return the {@link Target} {@link Specification} */ public static Specification isCompatibleWithDistributionSetType(final Long distributionSetTypeId) { @@ -366,10 +316,6 @@ public final class TargetSpecifications { }; } - private static Predicate getTargetTypeIsNullPredicate(final Root targetRoot) { - return targetRoot.get(JpaTarget_.targetType).isNull(); - } - /** * {@link Specification} for retrieving {@link Target}s that are NOT * compatible with given {@link DistributionSetType}. Compatibility is @@ -377,8 +323,7 @@ public final class TargetSpecifications { * don't have a {@link TargetType} are compatible with all * {@link DistributionSetType} * - * @param distributionSetTypeId - * the ID of the distribution set type which must be incompatible + * @param distributionSetTypeId the ID of the distribution set type which must be incompatible * @return the {@link Target} {@link Specification} */ public static Specification notCompatibleWithDistributionSetType(final Long distributionSetTypeId) { @@ -398,21 +343,11 @@ public final class TargetSpecifications { }; } - private static Path getDsTypeIdPath(final Root root) { - final Join targetTypeJoin = root.join(JpaTarget_.targetType, JoinType.LEFT); - targetTypeJoin.fetch(JpaTargetType_.distributionSetTypes); - final SetJoin dsTypeTargetTypeJoin = targetTypeJoin - .join(JpaTargetType_.distributionSetTypes, JoinType.LEFT); - - return dsTypeTargetTypeJoin.get(JpaDistributionSetType_.id); - } - /** * {@link Specification} for retrieving {@link Target}s that are in a given * {@link RolloutGroup} * - * @param group - * the {@link RolloutGroup} + * @param group the {@link RolloutGroup} * @return the {@link Target} {@link Specification} */ public static Specification isInRolloutGroup(final Long group) { @@ -427,8 +362,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s that are in an * action for a given {@link RolloutGroup} * - * @param group - * the {@link RolloutGroup} + * @param group the {@link RolloutGroup} * @return the {@link Target} {@link Specification} */ public static Specification isInActionRolloutGroup(final Long group) { @@ -442,8 +376,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s that are not in the * given {@link RolloutGroup}s * - * @param groups - * the {@link RolloutGroup}s + * @param groups the {@link RolloutGroup}s * @return the {@link Target} {@link Specification} */ public static Specification isNotInRolloutGroups(final Collection groups) { @@ -476,8 +409,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s that have no Action * of the {@link RolloutGroup}. * - * @param group - * the {@link RolloutGroup} + * @param group the {@link RolloutGroup} * @return the {@link Target} {@link Specification} */ public static Specification hasNoActionInRolloutGroup(final Long group) { @@ -498,8 +430,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s by assigned * distribution set. * - * @param distributionSetId - * the ID of the distribution set which must be assigned + * @param distributionSetId the ID of the distribution set which must be assigned * @return the {@link Target} {@link Specification} */ public static Specification hasInstalledDistributionSet(final Long distributionSetId) { @@ -510,8 +441,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by tag. * - * @param tagId - * the ID of the tag that should be to be assigned to target + * @param tagId the ID of the tag that should be to be assigned to target * @return the {@link Target} {@link Specification} */ public static Specification hasTag(final Long tagId) { @@ -525,9 +455,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by target type id * - * @param typeId - * the id of the target type - * + * @param typeId the id of the target type * @return the {@link Target} {@link Specification} */ public static Specification hasTargetType(final long typeId) { @@ -549,9 +477,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s that don't have * target type assigned * - * @param typeId - * the id of the target type - * + * @param typeId the id of the target type * @return the {@link Target} {@link Specification} */ public static Specification hasTargetTypeNot(final Long typeId) { @@ -570,10 +496,8 @@ public final class TargetSpecifications { * orderBy entry too, possibly invalidating the applied order, keep in mind * when using this * - * @param distributionSetIdForOrder - * distribution set to consider - * @param sort - * the sorting requested + * @param distributionSetIdForOrder distribution set to consider + * @param sort the sorting requested * @return specification that applies order by ds, may be overwritten */ public static Specification orderedByLinkedDistributionSet(final long distributionSetIdForOrder, @@ -603,11 +527,11 @@ public final class TargetSpecifications { public static Specification failedActionsForRollout(final String rolloutId) { return (targetRoot, query, cb) -> { Join targetActions = - targetRoot.join("actions"); + targetRoot.join("actions"); return cb.and( - cb.equal(targetActions.get("rollout").get("id"), rolloutId), - cb.equal(targetActions.get("status"), Action.Status.ERROR)); + cb.equal(targetActions.get("rollout").get("id"), rolloutId), + cb.equal(targetActions.get("status"), Action.Status.ERROR)); }; } @@ -627,7 +551,7 @@ public final class TargetSpecifications { cb.and( cb.equal(actionsJoin.get(JpaAction_.weight), weight), cb.ge(actionsJoin.get(JpaAction_.ROLLOUT).get(JpaRollout_.ID), rolloutId)))); - // another, but probably heavier variant + // another, but probably heavier variant // actionsJoin.on( // cb.or( // // in rollout @@ -643,4 +567,42 @@ public final class TargetSpecifications { return cb.isNull(actionsJoin.get(JpaAction_.id)); }; } + + private static Predicate getHasTagsPredicate(final Root targetRoot, final CriteriaBuilder cb, + final Boolean selectTargetWithNoTag, final String[] tagNames) { + final SetJoin tags = targetRoot.join(JpaTarget_.tags, JoinType.LEFT); + final Path exp = tags.get(JpaTargetTag_.name); + + final List hasTagsPredicates = new ArrayList<>(); + if (isNoTagActive(selectTargetWithNoTag)) { + hasTagsPredicates.add(exp.isNull()); + } + if (isAtLeastOneTagActive(tagNames)) { + hasTagsPredicates.add(exp.in(tagNames)); + } + + return hasTagsPredicates.stream().reduce(cb::or) + .orElseThrow(() -> new RuntimeException("Neither NO_TAG, nor TAG target tag filter was provided!")); + } + + private static boolean isNoTagActive(final Boolean selectTargetWithNoTag) { + return Boolean.TRUE.equals(selectTargetWithNoTag); + } + + private static boolean isAtLeastOneTagActive(final String[] tagNames) { + return tagNames != null && tagNames.length > 0; + } + + private static Predicate getTargetTypeIsNullPredicate(final Root targetRoot) { + return targetRoot.get(JpaTarget_.targetType).isNull(); + } + + private static Path getDsTypeIdPath(final Root root) { + final Join targetTypeJoin = root.join(JpaTarget_.targetType, JoinType.LEFT); + targetTypeJoin.fetch(JpaTargetType_.distributionSetTypes); + final SetJoin dsTypeTargetTypeJoin = targetTypeJoin + .join(JpaTargetType_.distributionSetTypes, JoinType.LEFT); + + return dsTypeTargetTypeJoin.get(JpaDistributionSetType_.id); + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetTypeSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetTypeSpecification.java index d50538350..bd7560944 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetTypeSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetTypeSpecification.java @@ -9,6 +9,10 @@ */ package org.eclipse.hawkbit.repository.jpa.specifications; +import java.util.Collection; + +import jakarta.persistence.criteria.SetJoin; + import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; @@ -19,9 +23,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.TargetType; import org.springframework.data.jpa.domain.Specification; -import jakarta.persistence.criteria.SetJoin; -import java.util.Collection; - /** * Specifications class for {@link TargetType}s. The class provides Spring Data JPQL Specifications. */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/DeploymentHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/DeploymentHelper.java index 4ed6b3aaa..49797bb42 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/DeploymentHelper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/DeploymentHelper.java @@ -16,11 +16,11 @@ import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaAction_; +import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; -import org.eclipse.hawkbit.repository.jpa.model.JpaAction; -import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -45,12 +45,9 @@ public final class DeploymentHelper { * action to canceled, resets the meta data of the target and in case there * is a new action this action is triggered. * - * @param action - * the action which is set to canceled - * @param actionRepository - * for the operation - * @param targetRepository - * for the operation + * @param action the action which is set to canceled + * @param actionRepository for the operation + * @param targetRepository for the operation */ public static void successCancellation(final JpaAction action, final ActionRepository actionRepository, final TargetRepository targetRepository) { @@ -80,13 +77,9 @@ public final class DeploymentHelper { /** * Executes the modifying action in new transaction * - * @param txManager - * transaction manager interface - * @param transactionName - * the name of the new transaction - * @param action - * the callback to execute in new tranaction - * + * @param txManager transaction manager interface + * @param transactionName the name of the new transaction + * @param action the callback to execute in new tranaction * @return the result of the action */ public static T runInNewTransaction(@NotNull final PlatformTransactionManager txManager, @@ -97,15 +90,10 @@ public final class DeploymentHelper { /** * Executes the modifying action in new transaction * - * @param txManager - * transaction manager interface - * @param transactionName - * the name of the new transaction - * @param isolationLevel - * isolation level of the new transaction - * @param action - * the callback to execute in new tranaction - * + * @param txManager transaction manager interface + * @param transactionName the name of the new transaction + * @param isolationLevel isolation level of the new transaction + * @param action the callback to execute in new tranaction * @return the result of the action */ public static T runInNewTransaction(@NotNull final PlatformTransactionManager txManager, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java index 4c520c758..f15f71206 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java @@ -31,12 +31,9 @@ public class FileSizeAndStorageQuotaCheckingInputStream extends FilterInputStrea * Creates a QuotaInputStream using the input stream in and a * limiting quota * - * @param in - * Inner InputStream that read operations will be forwarded to - * @param sizeLimit - * Quota file size limit in byte - * @param storageLeft - * Storage left until quota is reached + * @param in Inner InputStream that read operations will be forwarded to + * @param sizeLimit Quota file size limit in byte + * @param storageLeft Storage left until quota is reached */ public FileSizeAndStorageQuotaCheckingInputStream(final InputStream in, final long sizeLimit, final long storageLeft) { super(in); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/QuotaHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/QuotaHelper.java index 184c303b2..1e8594a8f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/QuotaHelper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/QuotaHelper.java @@ -30,21 +30,15 @@ public final class QuotaHelper { /** * Asserts the specified assignment quota. - * - * @param requested - * The number of entities that shall be assigned to the parent - * entity. - * @param limit - * The maximum number of entities that may be assigned to the - * parent entity. - * @param type - * The type of the entities that shall be assigned. - * @param parentType - * The type of the parent entity. - * - * @throws AssignmentQuotaExceededException - * if the assignment operation would cause the quota to be - * exceeded + * + * @param requested The number of entities that shall be assigned to the parent + * entity. + * @param limit The maximum number of entities that may be assigned to the + * parent entity. + * @param type The type of the entities that shall be assigned. + * @param parentType The type of the parent entity. + * @throws AssignmentQuotaExceededException if the assignment operation would cause the quota to be + * exceeded */ public static void assertAssignmentQuota(final long requested, final long limit, @NotNull final Class type, @NotNull final Class parentType) { @@ -53,26 +47,18 @@ public final class QuotaHelper { /** * Asserts the specified assignment quota. - * - * @param parentId - * The ID of the parent entity. - * @param requested - * The number of entities that shall be assigned to the parent - * entity. - * @param limit - * The maximum number of entities that may be assigned to the - * parent entity. - * @param type - * The type of the entities that shall be assigned. - * @param parentType - * The type of the parent entity. - * @param countFct - * Function to count the entities that are currently assigned to - * the parent entity. - * - * @throws AssignmentQuotaExceededException - * if the assignment operation would cause the quota to be - * exceeded + * + * @param parentId The ID of the parent entity. + * @param requested The number of entities that shall be assigned to the parent + * entity. + * @param limit The maximum number of entities that may be assigned to the + * parent entity. + * @param type The type of the entities that shall be assigned. + * @param parentType The type of the parent entity. + * @param countFct Function to count the entities that are currently assigned to + * the parent entity. + * @throws AssignmentQuotaExceededException if the assignment operation would cause the quota to be + * exceeded */ public static void assertAssignmentQuota(final T parentId, final long requested, final long limit, @NotNull final Class type, @NotNull final Class parentType, final ToLongFunction countFct) { @@ -81,26 +67,18 @@ public final class QuotaHelper { /** * Asserts the specified assignment quota. - * - * @param parentId - * The ID of the parent entity. - * @param requested - * The number of entities that shall be assigned to the parent - * entity. - * @param limit - * The maximum number of entities that may be assigned to the - * parent entity. - * @param type - * The type of the entities that shall be assigned. - * @param parentType - * The type of the parent entity. - * @param countFct - * Function to count the entities that are currently assigned to - * the parent entity. - * - * @throws AssignmentQuotaExceededException - * if the assignment operation would cause the quota to be - * exceeded + * + * @param parentId The ID of the parent entity. + * @param requested The number of entities that shall be assigned to the parent + * entity. + * @param limit The maximum number of entities that may be assigned to the + * parent entity. + * @param type The type of the entities that shall be assigned. + * @param parentType The type of the parent entity. + * @param countFct Function to count the entities that are currently assigned to + * the parent entity. + * @throws AssignmentQuotaExceededException if the assignment operation would cause the quota to be + * exceeded */ public static void assertAssignmentQuota(final T parentId, final long requested, final long limit, @NotNull final String type, @NotNull final String parentType, final ToLongFunction countFct) { @@ -132,11 +110,9 @@ public final class QuotaHelper { /** * Assert that the number of assignments in a request does not exceed the * limit. - * - * @param requested - * the number of assignments that are to be made - * @param limit - * the maximum number of assignments per request + * + * @param requested the number of assignments that are to be made + * @param limit the maximum number of assignments per request */ public static void assertAssignmentRequestSizeQuota(final long requested, final long limit) { if (requested > limit) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/WeightValidationHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/WeightValidationHelper.java index 4a463ff0b..83ee77311 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/WeightValidationHelper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/WeightValidationHelper.java @@ -13,7 +13,6 @@ import java.util.List; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; -import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException; import org.eclipse.hawkbit.repository.exception.NoWeightProvidedInMultiAssignmentModeException; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate; import org.eclipse.hawkbit.repository.model.DeploymentRequest; @@ -38,11 +37,9 @@ public final class WeightValidationHelper { /** * Setting the context of the tenant - * - * @param systemSecurityContext - * security context used to get the tenant and for execution - * @param tenantConfigurationManagement - * to get the value from + * + * @param systemSecurityContext security context used to get the tenant and for execution + * @param tenantConfigurationManagement to get the value from */ public static WeightValidationHelper usingContext(final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) { @@ -51,9 +48,8 @@ public final class WeightValidationHelper { /** * Validating weights associated with all the {@link DeploymentRequest}s - * - * @param deploymentRequests - * the {@linkplain List} of {@link DeploymentRequest}s + * + * @param deploymentRequests the {@linkplain List} of {@link DeploymentRequest}s */ public void validate(final List deploymentRequests) { final long assignmentsWithWeight = deploymentRequests.stream() @@ -66,9 +62,8 @@ public final class WeightValidationHelper { /** * Validating weight associated with the {@link Rollout} - * - * @param rollout - * the {@linkplain Rollout} + * + * @param rollout the {@linkplain Rollout} */ public void validate(final Rollout rollout) { validateWeight(rollout.getWeight().orElse(null)); @@ -76,9 +71,8 @@ public final class WeightValidationHelper { /** * Validating weight associated with the target filter query - * - * @param targetFilterQueryCreate - * the target filter query + * + * @param targetFilterQueryCreate the target filter query */ public void validate(final JpaTargetFilterQueryCreate targetFilterQueryCreate) { validateWeight(targetFilterQueryCreate.getAutoAssignWeight().orElse(null)); @@ -87,9 +81,8 @@ public final class WeightValidationHelper { /** * Validating weight associated with the auto assignment - * - * @param autoAssignDistributionSetUpdate - * the auto assignment distribution set update + * + * @param autoAssignDistributionSetUpdate the auto assignment distribution set update */ public void validate(final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate) { validateWeight(autoAssignDistributionSetUpdate.getWeight()); @@ -98,10 +91,9 @@ public final class WeightValidationHelper { /** * Checks if the weight is valid - * - * @param weight - * weight tied to the rollout, auto assignment, or online - * assignment. + * + * @param weight weight tied to the rollout, auto assignment, or online + * assignment. */ public void validateWeight(final Integer weight) { final boolean hasWeight = weight != null; @@ -111,11 +103,9 @@ public final class WeightValidationHelper { /** * Checks if the weight is valid with the multi-assignments being turned * off/on. - * - * @param hasWeight - * indicator of the weight if it has numerical value - * @param hasNoWeight - * indicator of the weight if it doesn't have a numerical value + * + * @param hasWeight indicator of the weight if it has numerical value + * @param hasNoWeight indicator of the weight if it doesn't have a numerical value */ public void validateWeight(final boolean hasWeight, final boolean hasNoWeight) { // remove bypassing the weight enforcement as soon as weight can be set diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_10__change_length_of_target_attributes_key___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_10__change_length_of_target_attributes_key___DB2.sql index cdcffc506..72cce7308 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_10__change_length_of_target_attributes_key___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_10__change_length_of_target_attributes_key___DB2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_target_attributes ALTER COLUMN attribute_key SET DATA TYPE VARCHAR(128); \ No newline at end of file +ALTER TABLE sp_target_attributes + ALTER COLUMN attribute_key SET DATA TYPE VARCHAR(128); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_11__add_auto_assign_action_type___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_11__add_auto_assign_action_type___DB2.sql index 9c6b67bf3..67405670e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_11__add_auto_assign_action_type___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_11__add_auto_assign_action_type___DB2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_action_type INTEGER; \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD COLUMN auto_assign_action_type INTEGER; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_12__change_length_of_controller_id_and_name___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_12__change_length_of_controller_id_and_name___DB2.sql index fc5d4f0f0..5db3dc2e5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_12__change_length_of_controller_id_and_name___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_12__change_length_of_controller_id_and_name___DB2.sql @@ -1,13 +1,24 @@ -ALTER TABLE sp_distribution_set ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_distribution_set_type ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_distributionset_tag ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_base_software_module ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_rollout ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_rolloutgroup ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_software_module_type ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_target ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_target_filter_query ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_target_tag ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_distribution_set + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_distribution_set_type + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_distributionset_tag + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_base_software_module + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_rollout + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_rolloutgroup + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_software_module_type + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_target + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_target_filter_query + ALTER COLUMN name SET DATA TYPE VARCHAR(128); +ALTER TABLE sp_target_tag + ALTER COLUMN name SET DATA TYPE VARCHAR(128); -ALTER TABLE sp_target ALTER COLUMN controller_id SET DATA TYPE VARCHAR(256); +ALTER TABLE sp_target + ALTER COLUMN controller_id SET DATA TYPE VARCHAR(256); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_13__add_action_external_id___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_13__add_action_external_id___DB2.sql index 8dbda293f..2556b7d21 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_13__add_action_external_id___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_13__add_action_external_id___DB2.sql @@ -1,4 +1,5 @@ -ALTER TABLE sp_action ADD COLUMN external_ref VARCHAR(512); +ALTER TABLE sp_action + ADD COLUMN external_ref VARCHAR(512); CREATE INDEX sp_idx_action_external_ref ON sp_action (external_ref); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_14__add_sha256_hash___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_14__add_sha256_hash___DB2.sql index ca7e53fce..bfe56f337 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_14__add_sha256_hash___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_14__add_sha256_hash___DB2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_artifact ADD COLUMN sha256_hash CHAR(64); \ No newline at end of file +ALTER TABLE sp_artifact + ADD COLUMN sha256_hash CHAR(64); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_15__add_weight___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_15__add_weight___DB2.sql index 9eaad20e1..12db78a80 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_15__add_weight___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_15__add_weight___DB2.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_action ADD weight INT; -ALTER TABLE sp_rollout ADD weight INT; -ALTER TABLE sp_target_filter_query ADD auto_assign_weight INT; +ALTER TABLE sp_action + ADD weight INT; +ALTER TABLE sp_rollout + ADD weight INT; +ALTER TABLE sp_target_filter_query + ADD auto_assign_weight INT; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_16__add_action_initiated_by___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_16__add_action_initiated_by___DB2.sql index 6d00f9f50..70f33d1d5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_16__add_action_initiated_by___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_16__add_action_initiated_by___DB2.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_action ADD COLUMN initiated_by VARCHAR(64) NOT NULL DEFAULT ''; -ALTER TABLE sp_action ALTER COLUMN initiated_by DROP DEFAULT; -ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_initiated_by VARCHAR(64); +ALTER TABLE sp_action + ADD COLUMN initiated_by VARCHAR(64) NOT NULL DEFAULT ''; +ALTER TABLE sp_action + ALTER COLUMN initiated_by DROP DEFAULT; +ALTER TABLE sp_target_filter_query + ADD COLUMN auto_assign_initiated_by VARCHAR(64); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_18__add_target_type___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_18__add_target_type___DB2.sql index fed3796ff..99d2bbcfd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_18__add_target_type___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_18__add_target_type___DB2.sql @@ -1,14 +1,14 @@ CREATE TABLE sp_target_type ( id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, + tenant VARCHAR(40) NOT NULL, colour VARCHAR(16), - created_at BIGINT NOT NULL, - created_by VARCHAR(64) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(64) NOT NULL, description VARCHAR(512), - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(64) NOT NULL, - name VARCHAR(64) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(64) NOT NULL, + name VARCHAR(64) NOT NULL, optlock_revision INTEGER, PRIMARY KEY (id) ); @@ -18,15 +18,20 @@ CREATE INDEX sp_idx_target_type_prim CREATE TABLE sp_target_type_ds_type_relation ( - target_type BIGINT NOT NULL, - distribution_set_type BIGINT NOT NULL, + target_type BIGINT NOT NULL, + distribution_set_type BIGINT NOT NULL, PRIMARY KEY (target_type, distribution_set_type) ); -ALTER TABLE sp_target_type ADD CONSTRAINT uk_target_type_name UNIQUE (name, tenant); +ALTER TABLE sp_target_type + ADD CONSTRAINT uk_target_type_name UNIQUE (name, tenant); -ALTER TABLE sp_target ADD COLUMN target_type BIGINT; -ALTER TABLE sp_target ADD CONSTRAINT fk_target_relation_target_type FOREIGN KEY (target_type) REFERENCES sp_target_type (id) ON DELETE SET NULL; +ALTER TABLE sp_target + ADD COLUMN target_type BIGINT; +ALTER TABLE sp_target + ADD CONSTRAINT fk_target_relation_target_type FOREIGN KEY (target_type) REFERENCES sp_target_type (id) ON DELETE SET NULL; -ALTER TABLE sp_target_type_ds_type_relation ADD CONSTRAINT fk_target_type_relation_target_type FOREIGN KEY (target_type) REFERENCES sp_target_type (id) ON DELETE CASCADE; -ALTER TABLE sp_target_type_ds_type_relation ADD CONSTRAINT fk_target_type_relation_ds_type FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; \ No newline at end of file +ALTER TABLE sp_target_type_ds_type_relation + ADD CONSTRAINT fk_target_type_relation_target_type FOREIGN KEY (target_type) REFERENCES sp_target_type (id) ON DELETE CASCADE; +ALTER TABLE sp_target_type_ds_type_relation + ADD CONSTRAINT fk_target_type_relation_ds_type FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_19__add_valid_flag_to_ds___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_19__add_valid_flag_to_ds___DB2.sql index 3ab0e7502..352419711 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_19__add_valid_flag_to_ds___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_19__add_valid_flag_to_ds___DB2.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN; +ALTER TABLE sp_distribution_set + ADD COLUMN valid BOOLEAN; -UPDATE sp_distribution_set SET valid = 1; \ No newline at end of file +UPDATE sp_distribution_set +SET valid = 1; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_20__add_encryption_flag_to_sm___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_20__add_encryption_flag_to_sm___DB2.sql index 9249d14a1..5dd518204 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_20__add_encryption_flag_to_sm___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_20__add_encryption_flag_to_sm___DB2.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_base_software_module ADD COLUMN encrypted BOOLEAN; +ALTER TABLE sp_base_software_module + ADD COLUMN encrypted BOOLEAN; -UPDATE sp_base_software_module SET encrypted = 0; \ No newline at end of file +UPDATE sp_base_software_module +SET encrypted = 0; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_22__change_target_type_name_length___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_22__change_target_type_name_length___DB2.sql index e7f6f7624..b52051eb9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_22__change_target_type_name_length___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_22__change_target_type_name_length___DB2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_target_type ALTER COLUMN name SET DATA TYPE VARCHAR(128); \ No newline at end of file +ALTER TABLE sp_target_type + ALTER COLUMN name SET DATA TYPE VARCHAR(128); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_23__add_action_status_code___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_23__add_action_status_code___DB2.sql index c88711e47..ff27e35bf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_23__add_action_status_code___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_23__add_action_status_code___DB2.sql @@ -1,2 +1,3 @@ -ALTER TABLE sp_action_status ADD COLUMN code INTEGER; +ALTER TABLE sp_action_status + ADD COLUMN code INTEGER; CREATE INDEX sp_idx_action_status_03 ON sp_action_status (tenant, code); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_24__add_last_action_status_code___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_24__add_last_action_status_code___DB2.sql index ee8e263bd..5bc473139 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_24__add_last_action_status_code___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_24__add_last_action_status_code___DB2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_action ADD COLUMN last_action_status_code INTEGER; \ No newline at end of file +ALTER TABLE sp_action + ADD COLUMN last_action_status_code INTEGER; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_25__add_confirmation_flag___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_25__add_confirmation_flag___DB2.sql index 5c16b5d34..8287ce1e6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_25__add_confirmation_flag___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_25__add_confirmation_flag___DB2.sql @@ -1,21 +1,25 @@ -ALTER TABLE sp_rolloutgroup ADD COLUMN confirmation_required BOOLEAN; -UPDATE sp_rolloutgroup SET confirmation_required = 0; +ALTER TABLE sp_rolloutgroup + ADD COLUMN confirmation_required BOOLEAN; +UPDATE sp_rolloutgroup +SET confirmation_required = 0; -ALTER TABLE sp_target_filter_query ADD COLUMN confirmation_required BOOLEAN; -UPDATE sp_target_filter_query SET confirmation_required = 0; +ALTER TABLE sp_target_filter_query + ADD COLUMN confirmation_required BOOLEAN; +UPDATE sp_target_filter_query +SET confirmation_required = 0; CREATE TABLE sp_target_conf_status ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - target_id bigint not null, - initiator VARCHAR(64), - remark VARCHAR(512), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) not null, + id BIGINT GENERATED always AS IDENTITY NOT NULL, + target_id bigint not null, + initiator VARCHAR(64), + remark VARCHAR(512), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) not null, primary key (id) ); ALTER TABLE sp_target_conf_status diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_26__add_access_control_context___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_26__add_access_control_context___DB2.sql index ccf16963e..fb06922c7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_26__add_access_control_context___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_26__add_access_control_context___DB2.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_target_filter_query ADD COLUMN access_control_context VARCHAR(4096); -ALTER TABLE sp_rollout ADD COLUMN access_control_context VARCHAR(4096); \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD COLUMN access_control_context VARCHAR(4096); +ALTER TABLE sp_rollout + ADD COLUMN access_control_context VARCHAR(4096); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_27__target_type_inherit_type___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_27__target_type_inherit_type___DB2.sql index 86e3350b8..2b63926eb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_27__target_type_inherit_type___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_27__target_type_inherit_type___DB2.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_target_type ADD COLUMN type_key VARCHAR (64) NOT NULL DEFAULT ('_'); -UPDATE sp_target_type SET type_key = name; -ALTER TABLE sp_target_type ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file +ALTER TABLE sp_target_type + ADD COLUMN type_key VARCHAR(64) NOT NULL DEFAULT ('_'); +UPDATE sp_target_type +SET type_key = name; +ALTER TABLE sp_target_type + ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_28__add_dynamic_rollout___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_28__add_dynamic_rollout___DB2.sql index cff85ae84..33b76ee8e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_28__add_dynamic_rollout___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_28__add_dynamic_rollout___DB2.sql @@ -1,9 +1,20 @@ -ALTER TABLE sp_rollout ADD COLUMN is_dynamic BOOLEAN; -ALTER TABLE sp_rolloutgroup ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; +ALTER TABLE sp_rollout + ADD COLUMN is_dynamic BOOLEAN; +ALTER TABLE sp_rolloutgroup + ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; -UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; -ALTER TABLE sp_rollout ALTER COLUMN weight SET NOT NULL; -ALTER TABLE sp_action ALTER COLUMN weight SET NOT NULL; -ALTER TABLE sp_target_filter_query ALTER COLUMN auto_assign_weight SET NOT NULL; +UPDATE sp_rollout +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_action +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_target_filter_query +SET auto_assign_weight = 1000 +WHERE auto_assign_weight IS NULL; +ALTER TABLE sp_rollout + ALTER COLUMN weight SET NOT NULL; +ALTER TABLE sp_action + ALTER COLUMN weight SET NOT NULL; +ALTER TABLE sp_target_filter_query + ALTER COLUMN auto_assign_weight SET NOT NULL; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_29__add_ds_sm_locked___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_29__add_ds_sm_locked___DB2.sql index c5c0de6fb..831528f40 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_29__add_ds_sm_locked___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_29__add_ds_sm_locked___DB2.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_base_software_module ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; -ALTER TABLE sp_distribution_set ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file +ALTER TABLE sp_base_software_module + ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; +ALTER TABLE sp_distribution_set + ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_5__baseline___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_5__baseline___DB2.sql index 274ead21b..2657b1a46 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_5__baseline___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_5__baseline___DB2.sql @@ -1,458 +1,500 @@ -CREATE TABLE sp_ds_type_element - ( - mandatory SMALLINT DEFAULT 0, - distribution_set_type BIGINT NOT NULL, - software_module_type BIGINT NOT NULL, - PRIMARY KEY (distribution_set_type, software_module_type) - ); +CREATE TABLE sp_ds_type_element +( + mandatory SMALLINT DEFAULT 0, + distribution_set_type BIGINT NOT NULL, + software_module_type BIGINT NOT NULL, + PRIMARY KEY (distribution_set_type, software_module_type) +); -CREATE TABLE sp_action - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - action_type INTEGER NOT NULL, - active SMALLINT DEFAULT 0, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - forced_time BIGINT, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - optlock_revision INTEGER, - status INTEGER NOT NULL, - distribution_set BIGINT NOT NULL, - rollout BIGINT, - rolloutgroup BIGINT, - target BIGINT NOT NULL, - maintenance_cron_schedule VARCHAR(40), - maintenance_duration VARCHAR(40), - maintenance_time_zone VARCHAR(40), - PRIMARY KEY (id) - ); +CREATE TABLE sp_action +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + action_type INTEGER NOT NULL, + active SMALLINT DEFAULT 0, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + forced_time BIGINT, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER, + status INTEGER NOT NULL, + distribution_set BIGINT NOT NULL, + rollout BIGINT, + rolloutgroup BIGINT, + target BIGINT NOT NULL, + maintenance_cron_schedule VARCHAR(40), + maintenance_duration VARCHAR(40), + maintenance_time_zone VARCHAR(40), + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_action_01 - ON sp_action (tenant, distribution_set); +CREATE INDEX sp_idx_action_01 + ON sp_action (tenant, distribution_set); -CREATE INDEX sp_idx_action_02 - ON sp_action (tenant, target, active); +CREATE INDEX sp_idx_action_02 + ON sp_action (tenant, target, active); -CREATE INDEX sp_idx_action_prim - ON sp_action (tenant, id); +CREATE INDEX sp_idx_action_prim + ON sp_action (tenant, id); -CREATE TABLE sp_action_status - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - target_occurred_at BIGINT NOT NULL, - optlock_revision INTEGER, - status INTEGER NOT NULL, - action BIGINT NOT NULL, - PRIMARY KEY (id) - ); +CREATE TABLE sp_action_status +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + target_occurred_at BIGINT NOT NULL, + optlock_revision INTEGER, + status INTEGER NOT NULL, + action BIGINT NOT NULL, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_action_status_02 - ON sp_action_status (tenant, action, status); +CREATE INDEX sp_idx_action_status_02 + ON sp_action_status (tenant, action, status); -CREATE INDEX sp_idx_action_status_prim - ON sp_action_status (tenant, id); +CREATE INDEX sp_idx_action_status_prim + ON sp_action_status (tenant, id); -CREATE TABLE sp_artifact - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - provided_file_name VARCHAR(256), - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - md5_hash VARCHAR(32), - optlock_revision INTEGER, - sha1_hash VARCHAR(40) NOT NULL, - file_size BIGINT, - software_module BIGINT NOT NULL, - PRIMARY KEY (id) - ); +CREATE TABLE sp_artifact +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + provided_file_name VARCHAR(256), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + md5_hash VARCHAR(32), + optlock_revision INTEGER, + sha1_hash VARCHAR(40) NOT NULL, + file_size BIGINT, + software_module BIGINT NOT NULL, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_artifact_01 - ON sp_artifact (tenant, software_module); +CREATE INDEX sp_idx_artifact_01 + ON sp_artifact (tenant, software_module); -CREATE INDEX sp_idx_artifact_02 - ON sp_artifact (tenant, sha1_hash); +CREATE INDEX sp_idx_artifact_02 + ON sp_artifact (tenant, sha1_hash); -CREATE INDEX sp_idx_artifact_prim - ON sp_artifact (tenant, id); +CREATE INDEX sp_idx_artifact_prim + ON sp_artifact (tenant, id); -CREATE TABLE sp_distribution_set - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - complete SMALLINT DEFAULT 0, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted SMALLINT DEFAULT 0, - description VARCHAR(512), - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - required_migration_step SMALLINT DEFAULT 0, - VERSION VARCHAR(64) NOT NULL, - ds_id BIGINT NOT NULL, - PRIMARY KEY (id) - ); +CREATE TABLE sp_distribution_set +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + complete SMALLINT DEFAULT 0, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + required_migration_step SMALLINT DEFAULT 0, + VERSION VARCHAR(64) NOT NULL, + ds_id BIGINT NOT NULL, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_distribution_set_01 - ON sp_distribution_set (tenant, deleted, complete); +CREATE INDEX sp_idx_distribution_set_01 + ON sp_distribution_set (tenant, deleted, complete); -CREATE INDEX sp_idx_distribution_set_prim - ON sp_distribution_set (tenant, id); +CREATE INDEX sp_idx_distribution_set_prim + ON sp_distribution_set (tenant, id); -CREATE TABLE sp_ds_metadata - ( - meta_key VARCHAR(128) NOT NULL, - meta_value VARCHAR(4000), - ds_id BIGINT NOT NULL, - PRIMARY KEY (meta_key, ds_id) - ); +CREATE TABLE sp_ds_metadata +( + meta_key VARCHAR(128) NOT NULL, + meta_value VARCHAR(4000), + ds_id BIGINT NOT NULL, + PRIMARY KEY (meta_key, ds_id) +); -CREATE TABLE sp_distributionset_tag - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16), - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - description VARCHAR(512), - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - PRIMARY KEY (id) - ); +CREATE TABLE sp_distributionset_tag +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16), + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_distribution_set_tag_prim - ON sp_distributionset_tag (tenant, id); +CREATE INDEX sp_idx_distribution_set_tag_prim + ON sp_distributionset_tag (tenant, id); -CREATE TABLE sp_distribution_set_type - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16), - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted SMALLINT DEFAULT 0, - description VARCHAR(512), - type_key VARCHAR(64) NOT NULL, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - PRIMARY KEY (id) - ); +CREATE TABLE sp_distribution_set_type +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16), + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + type_key VARCHAR(64) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_distribution_set_type_01 - ON sp_distribution_set_type (tenant, deleted); +CREATE INDEX sp_idx_distribution_set_type_01 + ON sp_distribution_set_type (tenant, deleted); -CREATE INDEX sp_idx_distribution_set_type_prim - ON sp_distribution_set_type (tenant, id); +CREATE INDEX sp_idx_distribution_set_type_prim + ON sp_distribution_set_type (tenant, id); -CREATE TABLE sp_rollout - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - action_type INTEGER NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted SMALLINT DEFAULT 0, - description VARCHAR(512), - forced_time BIGINT, - last_check BIGINT, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - rollout_groups_created INTEGER, - start_at BIGINT, - status INTEGER NOT NULL, - target_filter VARCHAR(1024) NOT NULL, - total_targets BIGINT, - distribution_set BIGINT NOT NULL, - PRIMARY KEY (id) - ); +CREATE TABLE sp_rollout +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + action_type INTEGER NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + forced_time BIGINT, + last_check BIGINT, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + rollout_groups_created INTEGER, + start_at BIGINT, + status INTEGER NOT NULL, + target_filter VARCHAR(1024) NOT NULL, + total_targets BIGINT, + distribution_set BIGINT NOT NULL, + PRIMARY KEY (id) +); -CREATE TABLE sp_rolloutgroup - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - description VARCHAR(512), - error_action INTEGER, - error_action_exp VARCHAR(512), - error_condition INTEGER, - error_condition_exp VARCHAR(512), - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - status INTEGER NOT NULL, - success_action INTEGER NOT NULL, - success_action_exp VARCHAR(512), - success_condition INTEGER NOT NULL, - success_condition_exp VARCHAR(512) NOT NULL, - target_filter VARCHAR(1024), - target_percentage FLOAT, - total_targets INTEGER, - parent_id BIGINT, - rollout BIGINT NOT NULL, - PRIMARY KEY (id) - ); +CREATE TABLE sp_rolloutgroup +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512), + error_action INTEGER, + error_action_exp VARCHAR(512), + error_condition INTEGER, + error_condition_exp VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + status INTEGER NOT NULL, + success_action INTEGER NOT NULL, + success_action_exp VARCHAR(512), + success_condition INTEGER NOT NULL, + success_condition_exp VARCHAR(512) NOT NULL, + target_filter VARCHAR(1024), + target_percentage FLOAT, + total_targets INTEGER, + parent_id BIGINT, + rollout BIGINT NOT NULL, + PRIMARY KEY (id) +); -CREATE TABLE sp_base_software_module - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted SMALLINT DEFAULT 0, - description VARCHAR(512), - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - vendor VARCHAR(256), - VERSION VARCHAR(64) NOT NULL, - module_type BIGINT NOT NULL, - PRIMARY KEY (id) - ); +CREATE TABLE sp_base_software_module +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + vendor VARCHAR(256), + VERSION VARCHAR(64) NOT NULL, + module_type BIGINT NOT NULL, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_base_sw_module_01 - ON sp_base_software_module (tenant, deleted, name, VERSION); +CREATE INDEX sp_idx_base_sw_module_01 + ON sp_base_software_module (tenant, deleted, name, VERSION); -CREATE INDEX sp_idx_base_sw_module_02 - ON sp_base_software_module (tenant, deleted, module_type); +CREATE INDEX sp_idx_base_sw_module_02 + ON sp_base_software_module (tenant, deleted, module_type); -CREATE INDEX sp_idx_base_sw_module_prim - ON sp_base_software_module (tenant, id); +CREATE INDEX sp_idx_base_sw_module_prim + ON sp_base_software_module (tenant, id); -CREATE TABLE sp_sw_metadata - ( - meta_key VARCHAR(128) NOT NULL, - target_visible SMALLINT DEFAULT 0, - meta_value VARCHAR(4000), - sw_id BIGINT NOT NULL, - PRIMARY KEY (meta_key, sw_id) - ); +CREATE TABLE sp_sw_metadata +( + meta_key VARCHAR(128) NOT NULL, + target_visible SMALLINT DEFAULT 0, + meta_value VARCHAR(4000), + sw_id BIGINT NOT NULL, + PRIMARY KEY (meta_key, sw_id) +); -CREATE TABLE sp_software_module_type - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16), - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted SMALLINT DEFAULT 0, - description VARCHAR(512), - type_key VARCHAR(64) NOT NULL, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - max_ds_assignments INTEGER NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - PRIMARY KEY (id) - ); +CREATE TABLE sp_software_module_type +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16), + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + type_key VARCHAR(64) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + max_ds_assignments INTEGER NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_software_module_type_01 - ON sp_software_module_type (tenant, deleted); +CREATE INDEX sp_idx_software_module_type_01 + ON sp_software_module_type (tenant, deleted); -CREATE INDEX sp_idx_software_module_type_prim - ON sp_software_module_type (tenant, id); +CREATE INDEX sp_idx_software_module_type_prim + ON sp_software_module_type (tenant, id); -CREATE TABLE sp_target - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - address VARCHAR(512), - controller_id VARCHAR(64) NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - description VARCHAR(512), - install_date BIGINT, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - last_target_query BIGINT, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - request_controller_attributes SMALLINT DEFAULT 0 NOT NULL, - sec_token VARCHAR(128) NOT NULL, - update_status INTEGER NOT NULL, - assigned_distribution_set BIGINT, - installed_distribution_set BIGINT, - PRIMARY KEY (id) - ); +CREATE TABLE sp_target +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + address VARCHAR(512), + controller_id VARCHAR(64) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512), + install_date BIGINT, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + last_target_query BIGINT, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + request_controller_attributes SMALLINT DEFAULT 0 NOT NULL, + sec_token VARCHAR(128) NOT NULL, + update_status INTEGER NOT NULL, + assigned_distribution_set BIGINT, + installed_distribution_set BIGINT, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_target_01 - ON sp_target (tenant, name, assigned_distribution_set); +CREATE INDEX sp_idx_target_01 + ON sp_target (tenant, name, assigned_distribution_set); -CREATE INDEX sp_idx_target_03 - ON sp_target (tenant, controller_id, assigned_distribution_set); +CREATE INDEX sp_idx_target_03 + ON sp_target (tenant, controller_id, assigned_distribution_set); -CREATE INDEX sp_idx_target_04 - ON sp_target (tenant, created_at); +CREATE INDEX sp_idx_target_04 + ON sp_target (tenant, created_at); -CREATE INDEX sp_idx_target_prim - ON sp_target (tenant, id); +CREATE INDEX sp_idx_target_prim + ON sp_target (tenant, id); -CREATE TABLE sp_target_filter_query - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - QUERY VARCHAR(1024) NOT NULL, - auto_assign_distribution_set BIGINT, - PRIMARY KEY (id) - ); +CREATE TABLE sp_target_filter_query +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + QUERY VARCHAR(1024) NOT NULL, + auto_assign_distribution_set BIGINT, + PRIMARY KEY (id) +); -CREATE TABLE sp_target_tag - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16), - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - description VARCHAR(512), - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER, - PRIMARY KEY (id) - ); +CREATE TABLE sp_target_tag +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16), + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_target_tag_prim - ON sp_target_tag (tenant, id); +CREATE INDEX sp_idx_target_tag_prim + ON sp_target_tag (tenant, id); -CREATE TABLE sp_tenant_configuration - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - conf_key VARCHAR(128) NOT NULL, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - optlock_revision INTEGER, - conf_value VARCHAR(512) NOT NULL, - PRIMARY KEY (id) - ); +CREATE TABLE sp_tenant_configuration +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + conf_key VARCHAR(128) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER, + conf_value VARCHAR(512) NOT NULL, + PRIMARY KEY (id) +); -CREATE TABLE sp_tenant - ( - id BIGINT GENERATED always AS IDENTITY NOT NULL, - created_at BIGINT NOT NULL, - created_by VARCHAR(40) NOT NULL, - last_modified_at BIGINT NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - optlock_revision INTEGER, - tenant VARCHAR(40) NOT NULL, - default_ds_type BIGINT NOT NULL, - PRIMARY KEY (id) - ); +CREATE TABLE sp_tenant +( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER, + tenant VARCHAR(40) NOT NULL, + default_ds_type BIGINT NOT NULL, + PRIMARY KEY (id) +); -CREATE INDEX sp_idx_tenant_prim - ON sp_tenant (tenant, id); +CREATE INDEX sp_idx_tenant_prim + ON sp_tenant (tenant, id); -CREATE TABLE sp_rollouttargetgroup - ( - rolloutgroup_id BIGINT NOT NULL, - target_id BIGINT NOT NULL, - PRIMARY KEY (rolloutgroup_id, target_id) - ); +CREATE TABLE sp_rollouttargetgroup +( + rolloutgroup_id BIGINT NOT NULL, + target_id BIGINT NOT NULL, + PRIMARY KEY (rolloutgroup_id, target_id) +); -CREATE TABLE sp_action_status_messages - ( - action_status_id BIGINT NOT NULL, - detail_message VARCHAR(512) NOT NULL - ); +CREATE TABLE sp_action_status_messages +( + action_status_id BIGINT NOT NULL, + detail_message VARCHAR(512) NOT NULL +); -CREATE INDEX sp_idx_action_status_msgs_01 - ON sp_action_status_messages (action_status_id); +CREATE INDEX sp_idx_action_status_msgs_01 + ON sp_action_status_messages (action_status_id); -CREATE TABLE sp_ds_module - ( - ds_id BIGINT NOT NULL, - module_id BIGINT NOT NULL, - PRIMARY KEY (ds_id, module_id) - ); +CREATE TABLE sp_ds_module +( + ds_id BIGINT NOT NULL, + module_id BIGINT NOT NULL, + PRIMARY KEY (ds_id, module_id) +); -CREATE TABLE sp_ds_dstag - ( - ds BIGINT NOT NULL, - tag BIGINT NOT NULL, - PRIMARY KEY (ds, tag) - ); +CREATE TABLE sp_ds_dstag +( + ds BIGINT NOT NULL, + tag BIGINT NOT NULL, + PRIMARY KEY (ds, tag) +); -CREATE TABLE sp_target_attributes - ( - target_id BIGINT NOT NULL, - attribute_value VARCHAR(128), - attribute_key VARCHAR(32) NOT NULL - ); +CREATE TABLE sp_target_attributes +( + target_id BIGINT NOT NULL, + attribute_value VARCHAR(128), + attribute_key VARCHAR(32) NOT NULL +); -CREATE TABLE sp_target_target_tag - ( - target BIGINT NOT NULL, - tag BIGINT NOT NULL, - PRIMARY KEY (target, tag) - ); +CREATE TABLE sp_target_target_tag +( + target BIGINT NOT NULL, + tag BIGINT NOT NULL, + PRIMARY KEY (target, tag) +); -ALTER TABLE sp_distribution_set ADD CONSTRAINT uk_distrib_set UNIQUE (name, version, tenant); -ALTER TABLE sp_distributionset_tag ADD CONSTRAINT uk_ds_tag UNIQUE (name, tenant); -ALTER TABLE sp_distribution_set_type ADD CONSTRAINT uk_dst_name UNIQUE (name, tenant); -ALTER TABLE sp_distribution_set_type ADD CONSTRAINT uk_dst_key UNIQUE (type_key, tenant); -ALTER TABLE sp_rollout ADD CONSTRAINT uk_rollout UNIQUE (name, tenant); -ALTER TABLE sp_rolloutgroup ADD CONSTRAINT uk_rolloutgroup UNIQUE (name, rollout, tenant); -ALTER TABLE sp_base_software_module ADD CONSTRAINT uk_base_sw_mod UNIQUE (module_type, name, version, tenant); -ALTER TABLE sp_software_module_type ADD CONSTRAINT uk_smt_type_key UNIQUE (type_key, tenant); -ALTER TABLE sp_software_module_type ADD CONSTRAINT uk_smt_name UNIQUE (name, tenant); -ALTER TABLE sp_target ADD CONSTRAINT uk_tenant_controller_ UNIQUE (controller_id, tenant); -ALTER TABLE sp_target_filter_query ADD CONSTRAINT uk_tenant_custom_filt UNIQUE (name, tenant); -ALTER TABLE sp_target_tag ADD CONSTRAINT uk_targ_tag UNIQUE (name, tenant); -ALTER TABLE sp_tenant_configuration ADD CONSTRAINT uk_tenant_key UNIQUE (conf_key, tenant); -ALTER TABLE sp_tenant ADD CONSTRAINT uk_tenantmd_tenant UNIQUE (tenant); +ALTER TABLE sp_distribution_set + ADD CONSTRAINT uk_distrib_set UNIQUE (name, version, tenant); +ALTER TABLE sp_distributionset_tag + ADD CONSTRAINT uk_ds_tag UNIQUE (name, tenant); +ALTER TABLE sp_distribution_set_type + ADD CONSTRAINT uk_dst_name UNIQUE (name, tenant); +ALTER TABLE sp_distribution_set_type + ADD CONSTRAINT uk_dst_key UNIQUE (type_key, tenant); +ALTER TABLE sp_rollout + ADD CONSTRAINT uk_rollout UNIQUE (name, tenant); +ALTER TABLE sp_rolloutgroup + ADD CONSTRAINT uk_rolloutgroup UNIQUE (name, rollout, tenant); +ALTER TABLE sp_base_software_module + ADD CONSTRAINT uk_base_sw_mod UNIQUE (module_type, name, version, tenant); +ALTER TABLE sp_software_module_type + ADD CONSTRAINT uk_smt_type_key UNIQUE (type_key, tenant); +ALTER TABLE sp_software_module_type + ADD CONSTRAINT uk_smt_name UNIQUE (name, tenant); +ALTER TABLE sp_target + ADD CONSTRAINT uk_tenant_controller_ UNIQUE (controller_id, tenant); +ALTER TABLE sp_target_filter_query + ADD CONSTRAINT uk_tenant_custom_filt UNIQUE (name, tenant); +ALTER TABLE sp_target_tag + ADD CONSTRAINT uk_targ_tag UNIQUE (name, tenant); +ALTER TABLE sp_tenant_configuration + ADD CONSTRAINT uk_tenant_key UNIQUE (conf_key, tenant); +ALTER TABLE sp_tenant + ADD CONSTRAINT uk_tenantmd_tenant UNIQUE (tenant); -ALTER TABLE sp_ds_type_element ADD CONSTRAINT fk_ds_type_element_element FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_type_element ADD CONSTRAINT fk_ds_type_element_smtype FOREIGN KEY (software_module_type) REFERENCES sp_software_module_type (id) ON DELETE CASCADE; -ALTER TABLE sp_action ADD CONSTRAINT fk_action_rolloutgroup FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); -ALTER TABLE sp_action ADD CONSTRAINT fk_action_rollout FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); -ALTER TABLE sp_action ADD CONSTRAINT fk_targ_act_hist_targ FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; -ALTER TABLE sp_action ADD CONSTRAINT fk_action_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; -ALTER TABLE sp_action_status ADD CONSTRAINT fk_act_stat_action FOREIGN KEY (action) REFERENCES sp_action (id) ON DELETE CASCADE; -ALTER TABLE sp_artifact ADD CONSTRAINT fk_assigned_sm FOREIGN KEY (software_module) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; -ALTER TABLE sp_distribution_set ADD CONSTRAINT fk_ds_dstype_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set_type (id); -ALTER TABLE sp_ds_metadata ADD CONSTRAINT fk_metadata_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; -ALTER TABLE sp_rollout ADD CONSTRAINT fk_rollout_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id); -ALTER TABLE sp_rolloutgroup ADD CONSTRAINT fk_rolloutgroup_rollout FOREIGN KEY (rollout) REFERENCES sp_rollout (id) ON DELETE CASCADE; -ALTER TABLE sp_base_software_module ADD CONSTRAINT fk_module_type FOREIGN KEY (module_type) REFERENCES sp_software_module_type (id); -ALTER TABLE sp_sw_metadata ADD CONSTRAINT fk_metadata_sw FOREIGN KEY (sw_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; -ALTER TABLE sp_target ADD CONSTRAINT fk_target_inst_ds FOREIGN KEY (installed_distribution_set) REFERENCES sp_distribution_set (id); -ALTER TABLE sp_target ADD CONSTRAINT fk_target_assign_ds FOREIGN KEY (assigned_distribution_set) REFERENCES sp_distribution_set (id); -ALTER TABLE sp_target_filter_query ADD CONSTRAINT fk_filter_auto_assign_ds FOREIGN KEY (auto_assign_distribution_set) REFERENCES sp_distribution_set (id) ON DELETE SET NULL; -ALTER TABLE sp_tenant ADD CONSTRAINT fk_tenant_md_default_ds_type FOREIGN KEY (default_ds_type) REFERENCES sp_distribution_set_type (id); -ALTER TABLE sp_rollouttargetgroup ADD CONSTRAINT fk_rollouttargetgroup_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; -ALTER TABLE sp_rollouttargetgroup ADD CONSTRAINT fk_rollouttargetgroup_group FOREIGN KEY (rolloutGroup_Id) REFERENCES sp_rolloutgroup (id) ON DELETE CASCADE; -ALTER TABLE sp_action_status_messages ADD CONSTRAINT fk_stat_msg_act_stat FOREIGN KEY (action_status_id) REFERENCES sp_action_status (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_module ADD CONSTRAINT fk_ds_module_module FOREIGN KEY (module_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_module ADD CONSTRAINT fk_ds_module_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_dstag ADD CONSTRAINT fk_ds_dstag_tag FOREIGN KEY (tag) REFERENCES sp_distributionset_tag (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_dstag ADD CONSTRAINT fk_ds_dstag_ds FOREIGN KEY (ds) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; -ALTER TABLE sp_target_attributes ADD CONSTRAINT fk_targ_attrib_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; -ALTER TABLE sp_target_target_tag ADD CONSTRAINT fk_targ_targtag_tag FOREIGN KEY (tag) REFERENCES sp_target_tag (id) ON DELETE CASCADE; -ALTER TABLE sp_target_target_tag ADD CONSTRAINT fk_targ_targtag_target FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element + ADD CONSTRAINT fk_ds_type_element_element FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element + ADD CONSTRAINT fk_ds_type_element_smtype FOREIGN KEY (software_module_type) REFERENCES sp_software_module_type (id) ON DELETE CASCADE; +ALTER TABLE sp_action + ADD CONSTRAINT fk_action_rolloutgroup FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); +ALTER TABLE sp_action + ADD CONSTRAINT fk_action_rollout FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); +ALTER TABLE sp_action + ADD CONSTRAINT fk_targ_act_hist_targ FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_action + ADD CONSTRAINT fk_action_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_action_status + ADD CONSTRAINT fk_act_stat_action FOREIGN KEY (action) REFERENCES sp_action (id) ON DELETE CASCADE; +ALTER TABLE sp_artifact + ADD CONSTRAINT fk_assigned_sm FOREIGN KEY (software_module) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_distribution_set + ADD CONSTRAINT fk_ds_dstype_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set_type (id); +ALTER TABLE sp_ds_metadata + ADD CONSTRAINT fk_metadata_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_rollout + ADD CONSTRAINT fk_rollout_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_rolloutgroup + ADD CONSTRAINT fk_rolloutgroup_rollout FOREIGN KEY (rollout) REFERENCES sp_rollout (id) ON DELETE CASCADE; +ALTER TABLE sp_base_software_module + ADD CONSTRAINT fk_module_type FOREIGN KEY (module_type) REFERENCES sp_software_module_type (id); +ALTER TABLE sp_sw_metadata + ADD CONSTRAINT fk_metadata_sw FOREIGN KEY (sw_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_target + ADD CONSTRAINT fk_target_inst_ds FOREIGN KEY (installed_distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target + ADD CONSTRAINT fk_target_assign_ds FOREIGN KEY (assigned_distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target_filter_query + ADD CONSTRAINT fk_filter_auto_assign_ds FOREIGN KEY (auto_assign_distribution_set) REFERENCES sp_distribution_set (id) ON DELETE SET NULL; +ALTER TABLE sp_tenant + ADD CONSTRAINT fk_tenant_md_default_ds_type FOREIGN KEY (default_ds_type) REFERENCES sp_distribution_set_type (id); +ALTER TABLE sp_rollouttargetgroup + ADD CONSTRAINT fk_rollouttargetgroup_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_rollouttargetgroup + ADD CONSTRAINT fk_rollouttargetgroup_group FOREIGN KEY (rolloutGroup_Id) REFERENCES sp_rolloutgroup (id) ON DELETE CASCADE; +ALTER TABLE sp_action_status_messages + ADD CONSTRAINT fk_stat_msg_act_stat FOREIGN KEY (action_status_id) REFERENCES sp_action_status (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_module + ADD CONSTRAINT fk_ds_module_module FOREIGN KEY (module_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_module + ADD CONSTRAINT fk_ds_module_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_dstag + ADD CONSTRAINT fk_ds_dstag_tag FOREIGN KEY (tag) REFERENCES sp_distributionset_tag (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_dstag + ADD CONSTRAINT fk_ds_dstag_ds FOREIGN KEY (ds) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_target_attributes + ADD CONSTRAINT fk_targ_attrib_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_target_target_tag + ADD CONSTRAINT fk_targ_targtag_tag FOREIGN KEY (tag) REFERENCES sp_target_tag (id) ON DELETE CASCADE; +ALTER TABLE sp_target_target_tag + ADD CONSTRAINT fk_targ_targtag_target FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_6__add_index___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_6__add_index___DB2.sql index d7d7d6cc7..9fdbca2f8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_6__add_index___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_6__add_index___DB2.sql @@ -1,2 +1,2 @@ -CREATE INDEX sp_idx_target_tag_01 ON sp_target_tag (tenant, name); +CREATE INDEX sp_idx_target_tag_01 ON sp_target_tag (tenant, name); CREATE INDEX sp_idx_distribution_set_tag_01 ON sp_distributionset_tag (tenant, name); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_7__add_rollout_approval_fields___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_7__add_rollout_approval_fields___DB2.sql index 93824dc9d..8c43cf0fb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_7__add_rollout_approval_fields___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_7__add_rollout_approval_fields___DB2.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_rollout ADD COLUMN approval_decided_by varchar(40); -ALTER TABLE sp_rollout ADD COLUMN approval_remark varchar(255); \ No newline at end of file +ALTER TABLE sp_rollout + ADD COLUMN approval_decided_by varchar(40); +ALTER TABLE sp_rollout + ADD COLUMN approval_remark varchar(255); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_8__change_length_of_created_last_modified_by___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_8__change_length_of_created_last_modified_by___DB2.sql index 46d0b8f3c..edec4a13a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_8__change_length_of_created_last_modified_by___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_8__change_length_of_created_last_modified_by___DB2.sql @@ -1,45 +1,76 @@ -ALTER TABLE sp_action ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_action ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_action + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_action + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_action_status ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_action_status ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_action_status + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_action_status + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_artifact ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_artifact ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_artifact + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_artifact + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_base_software_module ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_base_software_module ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_base_software_module + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_base_software_module + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_distributionset_tag ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_distributionset_tag ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_distributionset_tag + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_distributionset_tag + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_distribution_set ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_distribution_set ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_distribution_set + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_distribution_set + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_distribution_set_type ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_distribution_set_type ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_distribution_set_type + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_distribution_set_type + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_rollout ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_rollout ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_rollout ALTER COLUMN approval_decided_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_rollout + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_rollout + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_rollout + ALTER COLUMN approval_decided_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_rolloutgroup ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_rolloutgroup ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_rolloutgroup + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_rolloutgroup + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_software_module_type ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_software_module_type ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_software_module_type + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_software_module_type + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_target ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_target ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_target + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_target + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_target_filter_query ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_target_filter_query ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_target_filter_query + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_target_filter_query + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_target_tag ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_target_tag ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_target_tag + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_target_tag + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_tenant ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_tenant ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_tenant + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_tenant + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_tenant_configuration ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); -ALTER TABLE sp_tenant_configuration ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); \ No newline at end of file +ALTER TABLE sp_tenant_configuration + ALTER COLUMN created_by SET DATA TYPE VARCHAR(64); +ALTER TABLE sp_tenant_configuration + ALTER COLUMN last_modified_by SET DATA TYPE VARCHAR(64); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_9__add_target_metadata___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_9__add_target_metadata___DB2.sql index 027af4dd6..3d4f6f21d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_9__add_target_metadata___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_9__add_target_metadata___DB2.sql @@ -1,9 +1,10 @@ -CREATE TABLE sp_target_metadata -( - meta_key VARCHAR(128) NOT NULL, - meta_value VARCHAR(4000), - target_id BIGINT NOT NULL, - PRIMARY KEY (meta_key, target_id) -); +CREATE TABLE sp_target_metadata +( + meta_key VARCHAR(128) NOT NULL, + meta_value VARCHAR(4000), + target_id BIGINT NOT NULL, + PRIMARY KEY (meta_key, target_id) +); -ALTER TABLE sp_target_metadata ADD CONSTRAINT fk_metadata_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_target_metadata + ADD CONSTRAINT fk_metadata_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_0_1__init___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_0_1__init___H2.sql index 5f022bb3c..2aa52c6d8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_0_1__init___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_0_1__init___H2.sql @@ -1,494 +1,516 @@ +create table sp_action +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + action_type varchar(255) not null, + active boolean, + forced_time bigint, + status integer, + distribution_set bigint, + target bigint, + primary key (id) +); + +create table sp_action_status +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + target_occurred_at bigint, + status integer, + action bigint not null, + primary key (id) +); + +create table sp_action_status_messages +( + action_status_id bigint not null, + detail_message varchar(512) +); + +create table sp_artifact +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + md5_hash varchar(32), + sha1_hash varchar(40), + file_size bigint, + provided_file_name varchar(256), + gridfs_file_name varchar(40), + software_module bigint not null, + primary key (id) +); + +create table sp_base_software_module +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + version varchar(64) not null, + deleted boolean, + vendor varchar(256), + module_type bigint not null, + primary key (id) +); + +create table sp_distribution_set +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + version varchar(64) not null, + complete boolean, + deleted boolean, + required_migration_step boolean, + ds_id bigint not null, + primary key (id) +); + +create table sp_distribution_set_type +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + colour varchar(16), + deleted boolean, + type_key varchar(64) not null, + primary key (id) +); + +create table sp_distributionset_tag +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + colour varchar(16), + primary key (id) +); + +create table sp_ds_dstag +( + ds bigint not null, + TAG bigint not null, + primary key (ds, TAG) +); + +create table sp_ds_metadata +( + meta_key varchar(128) not null, + meta_value varchar(4000), + ds_id bigint not null, + primary key (ds_id, meta_key) +); + +create table sp_ds_module +( + ds_id bigint not null, + module_id bigint not null, + primary key (ds_id, module_id) +); + +create table sp_ds_type_element +( + mandatory boolean, + distribution_set_type bigint not null, + software_module_type bigint not null, + primary key (distribution_set_type, software_module_type) +); + +create table sp_external_artifact +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + md5_hash varchar(32), + sha1_hash varchar(40), + file_size bigint, + url_suffix varchar(512), + provider bigint not null, + software_module bigint not null, + primary key (id) +); + +create table sp_external_provider +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + base_url varchar(512) not null, + default_url_suffix varchar(512), + primary key (id) +); + +create table sp_software_module_type +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + colour varchar(16), + deleted boolean, + type_key varchar(64) not null, + max_ds_assignments integer not null, + primary key (id) +); + +create table sp_sw_metadata +( + meta_key varchar(128) not null, + meta_value varchar(4000), + sw_id bigint not null, + primary key (meta_key, sw_id) +); + +create table sp_target +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + controller_id varchar(64), + sec_token varchar(128) not null, + assigned_distribution_set bigint, + primary key (id) +); + +create table sp_target_attributes +( + target_id bigint not null, + attribute_value varchar(128), + attribute_key varchar(32) not null, + primary key (target_id, attribute_key) +); + +create table sp_target_info +( + target_id bigint not null, + install_date bigint, + ip_address varchar(46), + last_target_query bigint, + request_controller_attributes boolean not null, + update_status varchar(255) not null, + installed_distribution_set bigint, + primary key (target_id) +); + +create table sp_target_tag +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + colour varchar(16), + primary key (id) +); + +create table sp_target_target_tag +( + target bigint not null, + tag bigint not null, + primary key (target, tag) +); + +create table sp_tenant +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + default_ds_type bigint not null, + primary key (id) +); + +create table sp_tenant_configuration +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + conf_key varchar(128), + conf_value varchar(512), + primary key (id) +); - create table sp_action ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - action_type varchar(255) not null, - active boolean, - forced_time bigint, - status integer, - distribution_set bigint, - target bigint, - primary key (id) - ); - - create table sp_action_status ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - target_occurred_at bigint, - status integer, - action bigint not null, - primary key (id) - ); - - create table sp_action_status_messages ( - action_status_id bigint not null, - detail_message varchar(512) - ); - - create table sp_artifact ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - md5_hash varchar(32), - sha1_hash varchar(40), - file_size bigint, - provided_file_name varchar(256), - gridfs_file_name varchar(40), - software_module bigint not null, - primary key (id) - ); - - create table sp_base_software_module ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - version varchar(64) not null, - deleted boolean, - vendor varchar(256), - module_type bigint not null, - primary key (id) - ); - - create table sp_distribution_set ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - version varchar(64) not null, - complete boolean, - deleted boolean, - required_migration_step boolean, - ds_id bigint not null, - primary key (id) - ); - - create table sp_distribution_set_type ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - colour varchar(16), - deleted boolean, - type_key varchar(64) not null, - primary key (id) - ); - - create table sp_distributionset_tag ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - colour varchar(16), - primary key (id) - ); - - create table sp_ds_dstag ( - ds bigint not null, - TAG bigint not null, - primary key (ds, TAG) - ); - - create table sp_ds_metadata ( - meta_key varchar(128) not null, - meta_value varchar(4000), - ds_id bigint not null, - primary key (ds_id, meta_key) - ); - - create table sp_ds_module ( - ds_id bigint not null, - module_id bigint not null, - primary key (ds_id, module_id) - ); - - create table sp_ds_type_element ( - mandatory boolean, - distribution_set_type bigint not null, - software_module_type bigint not null, - primary key (distribution_set_type, software_module_type) - ); - - create table sp_external_artifact ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - md5_hash varchar(32), - sha1_hash varchar(40), - file_size bigint, - url_suffix varchar(512), - provider bigint not null, - software_module bigint not null, - primary key (id) - ); - - create table sp_external_provider ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - base_url varchar(512) not null, - default_url_suffix varchar(512), - primary key (id) - ); - - create table sp_software_module_type ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - colour varchar(16), - deleted boolean, - type_key varchar(64) not null, - max_ds_assignments integer not null, - primary key (id) - ); - - create table sp_sw_metadata ( - meta_key varchar(128) not null, - meta_value varchar(4000), - sw_id bigint not null, - primary key (meta_key, sw_id) - ); - - create table sp_target ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - controller_id varchar(64), - sec_token varchar(128) not null, - assigned_distribution_set bigint, - primary key (id) - ); - - create table sp_target_attributes ( - target_id bigint not null, - attribute_value varchar(128), - attribute_key varchar(32) not null, - primary key (target_id, attribute_key) - ); - - create table sp_target_info ( - target_id bigint not null, - install_date bigint, - ip_address varchar(46), - last_target_query bigint, - request_controller_attributes boolean not null, - update_status varchar(255) not null, - installed_distribution_set bigint, - primary key (target_id) - ); - - create table sp_target_tag ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - colour varchar(16), - primary key (id) - ); - - create table sp_target_target_tag ( - target bigint not null, - tag bigint not null, - primary key (target, tag) - ); - - create table sp_tenant ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - default_ds_type bigint not null, - primary key (id) - ); - - create table sp_tenant_configuration ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - conf_key varchar(128), - conf_value varchar(512), - primary key (id) - ); +create index sp_idx_action_01 on sp_action (tenant, distribution_set); - create index sp_idx_action_01 on sp_action (tenant, distribution_set); +create index sp_idx_action_02 on sp_action (tenant, target, active); - create index sp_idx_action_02 on sp_action (tenant, target, active); +create index sp_idx_action_prim on sp_action (tenant, id); - create index sp_idx_action_prim on sp_action (tenant, id); +create index sp_idx_action_status_01 on sp_action_status (tenant, action); - create index sp_idx_action_status_01 on sp_action_status (tenant, action); +create index sp_idx_action_status_02 on sp_action_status (tenant, action, status); - create index sp_idx_action_status_02 on sp_action_status (tenant, action, status); +create index sp_idx_action_status_prim on sp_action_status (tenant, id); - create index sp_idx_action_status_prim on sp_action_status (tenant, id); +create index sp_idx_action_status_msgs_01 on sp_action_status_messages (action_status_id); - create index sp_idx_action_status_msgs_01 on sp_action_status_messages (action_status_id); +create index sp_idx_artifact_01 on sp_artifact (tenant, software_module); - create index sp_idx_artifact_01 on sp_artifact (tenant, software_module); +create index sp_idx_artifact_prim on sp_artifact (tenant, id); - create index sp_idx_artifact_prim on sp_artifact (tenant, id); +alter table sp_base_software_module + add constraint uk_base_sw_mod unique (module_type, name, version, tenant); - alter table sp_base_software_module - add constraint uk_base_sw_mod unique (module_type, name, version, tenant); +create index sp_idx_base_sw_module_01 on sp_base_software_module (tenant, deleted, name, version); - create index sp_idx_base_sw_module_01 on sp_base_software_module (tenant, deleted, name, version); +create index sp_idx_base_sw_module_02 on sp_base_software_module (tenant, deleted, module_type); - create index sp_idx_base_sw_module_02 on sp_base_software_module (tenant, deleted, module_type); +create index sp_idx_base_sw_module_prim on sp_base_software_module (tenant, id); - create index sp_idx_base_sw_module_prim on sp_base_software_module (tenant, id); +alter table sp_distribution_set + add constraint uk_distrib_set unique (name, version, tenant); - alter table sp_distribution_set - add constraint uk_distrib_set unique (name, version, tenant); +create index sp_idx_distribution_set_01 on sp_distribution_set (tenant, deleted, name, complete); - create index sp_idx_distribution_set_01 on sp_distribution_set (tenant, deleted, name, complete); +create index sp_idx_distribution_set_02 on sp_distribution_set (tenant, required_migration_step); - create index sp_idx_distribution_set_02 on sp_distribution_set (tenant, required_migration_step); +create index sp_idx_distribution_set_prim on sp_distribution_set (tenant, id); - create index sp_idx_distribution_set_prim on sp_distribution_set (tenant, id); +alter table sp_distribution_set_type + add constraint uk_dst_name unique (name, tenant); - alter table sp_distribution_set_type - add constraint uk_dst_name unique (name, tenant); +alter table sp_distribution_set_type + add constraint uk_dst_key unique (type_key, tenant); - alter table sp_distribution_set_type - add constraint uk_dst_key unique (type_key, tenant); +create index sp_idx_distribution_set_type_01 on sp_distribution_set_type (tenant, deleted); - create index sp_idx_distribution_set_type_01 on sp_distribution_set_type (tenant, deleted); +create index sp_idx_distribution_set_type_prim on sp_distribution_set_type (tenant, id); - create index sp_idx_distribution_set_type_prim on sp_distribution_set_type (tenant, id); +alter table sp_distributionset_tag + add constraint uk_ds_tag unique (name, tenant); - alter table sp_distributionset_tag - add constraint uk_ds_tag unique (name, tenant); +create index sp_idx_distribution_set_tag_prim on sp_distributionset_tag (tenant, id); - create index sp_idx_distribution_set_tag_prim on sp_distributionset_tag (tenant, id); +create index sp_idx_external_artifact_prim on sp_external_artifact (id, tenant); - create index sp_idx_external_artifact_prim on sp_external_artifact (id, tenant); +create index sp_idx_external_provider_prim on sp_external_provider (tenant, id); - create index sp_idx_external_provider_prim on sp_external_provider (tenant, id); +alter table sp_software_module_type + add constraint uk_smt_type_key unique (type_key, tenant); - alter table sp_software_module_type - add constraint uk_smt_type_key unique (type_key, tenant); +alter table sp_software_module_type + add constraint uk_smt_name unique (name, tenant); - alter table sp_software_module_type - add constraint uk_smt_name unique (name, tenant); +create index sp_idx_software_module_type_01 on sp_software_module_type (tenant, deleted); - create index sp_idx_software_module_type_01 on sp_software_module_type (tenant, deleted); +create index sp_idx_software_module_type_prim on sp_software_module_type (tenant, id); - create index sp_idx_software_module_type_prim on sp_software_module_type (tenant, id); +alter table sp_target + add constraint uk_tenant_controller_id unique (controller_id, tenant); - alter table sp_target - add constraint uk_tenant_controller_id unique (controller_id, tenant); +create index sp_idx_target_01 on sp_target (tenant, name, assigned_distribution_set); - create index sp_idx_target_01 on sp_target (tenant, name, assigned_distribution_set); +create index sp_idx_target_02 on sp_target (tenant, name); - create index sp_idx_target_02 on sp_target (tenant, name); +create index sp_idx_target_03 on sp_target (tenant, controller_id, assigned_distribution_set); - create index sp_idx_target_03 on sp_target (tenant, controller_id, assigned_distribution_set); - - create index sp_idx_target_04 on sp_target (tenant, created_at); +create index sp_idx_target_04 on sp_target (tenant, created_at); - create index sp_idx_target_prim on sp_target (tenant, id); +create index sp_idx_target_prim on sp_target (tenant, id); - create index sp_idx_target_info_01 on sp_target_info (ip_address); +create index sp_idx_target_info_01 on sp_target_info (ip_address); - create index sp_idx_target_info_02 on sp_target_info (target_id, update_status); +create index sp_idx_target_info_02 on sp_target_info (target_id, update_status); - alter table sp_target_tag - add constraint uk_targ_tag unique (name, tenant); +alter table sp_target_tag + add constraint uk_targ_tag unique (name, tenant); - create index sp_idx_target_tag_prim on sp_target_tag (tenant, id); +create index sp_idx_target_tag_prim on sp_target_tag (tenant, id); - alter table sp_tenant - add constraint uk_tenantmd_tenant unique (tenant); +alter table sp_tenant + add constraint uk_tenantmd_tenant unique (tenant); - create index sp_idx_tenant_prim on sp_tenant (tenant, id); +create index sp_idx_tenant_prim on sp_tenant (tenant, id); - alter table sp_tenant_configuration - add constraint uk_tenant_key unique (conf_key, tenant); +alter table sp_tenant_configuration + add constraint uk_tenant_key unique (conf_key, tenant); - alter table sp_action - add constraint fk_action_ds - foreign key (distribution_set) - references sp_distribution_set; +alter table sp_action + add constraint fk_action_ds + foreign key (distribution_set) + references sp_distribution_set; - alter table sp_action - add constraint fk_targ_act_hist_targ - foreign key (target) - references sp_target; +alter table sp_action + add constraint fk_targ_act_hist_targ + foreign key (target) + references sp_target; - alter table sp_action_status - add constraint fk_act_stat_action - foreign key (action) - references sp_action; +alter table sp_action_status + add constraint fk_act_stat_action + foreign key (action) + references sp_action; - alter table sp_action_status_messages - add constraint fk_stat_msg_act_stat - foreign key (action_status_id) - references sp_action_status; +alter table sp_action_status_messages + add constraint fk_stat_msg_act_stat + foreign key (action_status_id) + references sp_action_status; - alter table sp_artifact - add constraint fk_assigned_sm - foreign key (software_module) - references sp_base_software_module; +alter table sp_artifact + add constraint fk_assigned_sm + foreign key (software_module) + references sp_base_software_module; - alter table sp_base_software_module - add constraint fk_module_type - foreign key (module_type) - references sp_software_module_type; +alter table sp_base_software_module + add constraint fk_module_type + foreign key (module_type) + references sp_software_module_type; - alter table sp_distribution_set - add constraint fk_ds_dstype_ds - foreign key (ds_id) - references sp_distribution_set_type; +alter table sp_distribution_set + add constraint fk_ds_dstype_ds + foreign key (ds_id) + references sp_distribution_set_type; - alter table sp_ds_dstag - add constraint fk_ds_dstag_tag - foreign key (TAG) - references sp_distributionset_tag; +alter table sp_ds_dstag + add constraint fk_ds_dstag_tag + foreign key (TAG) + references sp_distributionset_tag; - alter table sp_ds_dstag - add constraint fk_ds_dstag_ds - foreign key (ds) - references sp_distribution_set; +alter table sp_ds_dstag + add constraint fk_ds_dstag_ds + foreign key (ds) + references sp_distribution_set; - alter table sp_ds_metadata - add constraint fk_metadata_ds - foreign key (ds_id) - references sp_distribution_set; +alter table sp_ds_metadata + add constraint fk_metadata_ds + foreign key (ds_id) + references sp_distribution_set; - alter table sp_ds_module - add constraint fk_ds_module_module - foreign key (module_id) - references sp_base_software_module; +alter table sp_ds_module + add constraint fk_ds_module_module + foreign key (module_id) + references sp_base_software_module; - alter table sp_ds_module - add constraint fk_ds_module_ds - foreign key (ds_id) - references sp_distribution_set; +alter table sp_ds_module + add constraint fk_ds_module_ds + foreign key (ds_id) + references sp_distribution_set; - alter table sp_ds_type_element - add constraint fk_ds_type_element_element - foreign key (distribution_set_type) - references sp_distribution_set_type; +alter table sp_ds_type_element + add constraint fk_ds_type_element_element + foreign key (distribution_set_type) + references sp_distribution_set_type; - alter table sp_ds_type_element - add constraint fk_ds_type_element_smtype - foreign key (software_module_type) - references sp_software_module_type; - - alter table sp_external_artifact - add constraint fk_art_to_ext_provider - foreign key (provider) - references sp_external_provider; - - alter table sp_external_artifact - add constraint fk_external_assigned_sm - foreign key (software_module) - references sp_base_software_module; - - alter table sp_sw_metadata - add constraint fk_metadata_sw - foreign key (sw_id) - references sp_base_software_module; - - alter table sp_target - add constraint fk_target_assign_ds - foreign key (assigned_distribution_set) - references sp_distribution_set; - - alter table sp_target_attributes - add constraint fk_targ_attrib_target - foreign key (target_id) - references sp_target_info; - - alter table sp_target_info - add constraint fk_target_inst_ds - foreign key (installed_distribution_set) - references sp_distribution_set; - - alter table sp_target_info - add constraint fk_targ_stat_targ - foreign key (target_id) - references sp_target; - - alter table sp_target_target_tag - add constraint fk_targ_targtag_tag - foreign key (tag) - references sp_target_tag; - - alter table sp_target_target_tag - add constraint fk_targ_targtag_target - foreign key (target) - references sp_target; - - alter table sp_tenant - add constraint fk_tenant_md_default_ds_type - foreign key (default_ds_type) - references sp_distribution_set_type; +alter table sp_ds_type_element + add constraint fk_ds_type_element_smtype + foreign key (software_module_type) + references sp_software_module_type; + +alter table sp_external_artifact + add constraint fk_art_to_ext_provider + foreign key (provider) + references sp_external_provider; + +alter table sp_external_artifact + add constraint fk_external_assigned_sm + foreign key (software_module) + references sp_base_software_module; + +alter table sp_sw_metadata + add constraint fk_metadata_sw + foreign key (sw_id) + references sp_base_software_module; + +alter table sp_target + add constraint fk_target_assign_ds + foreign key (assigned_distribution_set) + references sp_distribution_set; + +alter table sp_target_attributes + add constraint fk_targ_attrib_target + foreign key (target_id) + references sp_target_info; + +alter table sp_target_info + add constraint fk_target_inst_ds + foreign key (installed_distribution_set) + references sp_distribution_set; + +alter table sp_target_info + add constraint fk_targ_stat_targ + foreign key (target_id) + references sp_target; + +alter table sp_target_target_tag + add constraint fk_targ_targtag_tag + foreign key (tag) + references sp_target_tag; + +alter table sp_target_target_tag + add constraint fk_targ_targtag_target + foreign key (target) + references sp_target; + +alter table sp_tenant + add constraint fk_tenant_md_default_ds_type + foreign key (default_ds_type) + references sp_distribution_set_type; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_0__advanced_rolloutgroup__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_0__advanced_rolloutgroup__H2.sql index 7c4954ad8..27c73472e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_0__advanced_rolloutgroup__H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_0__advanced_rolloutgroup__H2.sql @@ -1,4 +1,4 @@ ALTER TABLE sp_rolloutgroup - ADD COLUMN target_percentage FLOAT; + ADD COLUMN target_percentage FLOAT; ALTER TABLE sp_rolloutgroup - ADD COLUMN target_filter VARCHAR (1024); + ADD COLUMN target_filter VARCHAR(1024); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_2__rollout_auto_start__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_2__rollout_auto_start__H2.sql index e946026f3..14f2a7abb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_2__rollout_auto_start__H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_2__rollout_auto_start__H2.sql @@ -1,2 +1,2 @@ ALTER TABLE sp_rollout - ADD COLUMN start_at BIGINT; + ADD COLUMN start_at BIGINT; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_3__add_rollout_deleted_flag__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_3__add_rollout_deleted_flag__H2.sql index cdfafc74f..51b036496 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_3__add_rollout_deleted_flag__H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_3__add_rollout_deleted_flag__H2.sql @@ -1,6 +1,8 @@ -ALTER TABLE sp_rollout ADD COLUMN deleted BOOLEAN; +ALTER TABLE sp_rollout + ADD COLUMN deleted BOOLEAN; -UPDATE sp_rollout SET deleted = 0; +UPDATE sp_rollout +SET deleted = 0; ALTER TABLE sp_action ALTER target BIGINT NOT NULL; ALTER TABLE sp_action ALTER distribution_set BIGINT NOT NULL; @@ -11,16 +13,16 @@ ALTER TABLE sp_rollout ALTER distribution_set BIGINT NOT NULL; ALTER TABLE sp_rolloutgroup ALTER rollout BIGINT NOT NULL; ALTER TABLE sp_rolloutgroup ALTER status INTEGER NOT NULL; -ALTER TABLE sp_ds_type_element DROP CONSTRAINT fk_ds_type_element_element; -ALTER TABLE sp_ds_type_element - ADD CONSTRAINT fk_ds_type_element_element - FOREIGN KEY (distribution_set_type) - REFERENCES sp_distribution_set_type (id) - ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element DROP CONSTRAINT fk_ds_type_element_element; +ALTER TABLE sp_ds_type_element + ADD CONSTRAINT fk_ds_type_element_element + FOREIGN KEY (distribution_set_type) + REFERENCES sp_distribution_set_type (id) + ON DELETE CASCADE; -ALTER TABLE sp_ds_type_element DROP CONSTRAINT fk_ds_type_element_smtype; -ALTER TABLE sp_ds_type_element - ADD CONSTRAINT fk_ds_type_element_smtype - FOREIGN KEY (software_module_type) - REFERENCES sp_software_module_type (id) - ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element DROP CONSTRAINT fk_ds_type_element_smtype; +ALTER TABLE sp_ds_type_element + ADD CONSTRAINT fk_ds_type_element_smtype + FOREIGN KEY (software_module_type) + REFERENCES sp_software_module_type (id) + ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_0__drop_target_info__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_0__drop_target_info__H2.sql index beddebc02..343b9f5b3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_0__drop_target_info__H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_0__drop_target_info__H2.sql @@ -1,29 +1,43 @@ -ALTER TABLE sp_target ADD COLUMN install_date bigint; -ALTER TABLE sp_target ADD COLUMN address varchar(512); -ALTER TABLE sp_target ADD COLUMN last_target_query bigint; -ALTER TABLE sp_target ADD COLUMN request_controller_attributes bit not null; -ALTER TABLE sp_target ADD COLUMN update_status varchar(16) not null; -ALTER TABLE sp_target ADD COLUMN installed_distribution_set bigint; - -UPDATE sp_target t SET install_date=(SELECT i.install_date FROM sp_target_info i WHERE t.id = i.target_id); -UPDATE sp_target t SET address=(SELECT i.address FROM sp_target_info i WHERE t.id = i.target_id); -UPDATE sp_target t SET last_target_query=(SELECT i.last_target_query FROM sp_target_info i WHERE t.id = i.target_id); -UPDATE sp_target t SET request_controller_attributes=(SELECT i.request_controller_attributes FROM sp_target_info i WHERE t.id = i.target_id); -UPDATE sp_target t SET update_status=(SELECT i.update_status FROM sp_target_info i WHERE t.id = i.target_id); -UPDATE sp_target t SET installed_distribution_set=(SELECT i.installed_distribution_set FROM sp_target_info i WHERE t.id = i.target_id); +ALTER TABLE sp_target + ADD COLUMN install_date bigint; +ALTER TABLE sp_target + ADD COLUMN address varchar(512); +ALTER TABLE sp_target + ADD COLUMN last_target_query bigint; +ALTER TABLE sp_target + ADD COLUMN request_controller_attributes bit not null; +ALTER TABLE sp_target + ADD COLUMN update_status varchar(16) not null; +ALTER TABLE sp_target + ADD COLUMN installed_distribution_set bigint; + +UPDATE sp_target t +SET install_date=(SELECT i.install_date FROM sp_target_info i WHERE t.id = i.target_id); +UPDATE sp_target t +SET address=(SELECT i.address FROM sp_target_info i WHERE t.id = i.target_id); +UPDATE sp_target t +SET last_target_query=(SELECT i.last_target_query FROM sp_target_info i WHERE t.id = i.target_id); +UPDATE sp_target t +SET request_controller_attributes=(SELECT i.request_controller_attributes + FROM sp_target_info i + WHERE t.id = i.target_id); +UPDATE sp_target t +SET update_status=(SELECT i.update_status FROM sp_target_info i WHERE t.id = i.target_id); +UPDATE sp_target t +SET installed_distribution_set=(SELECT i.installed_distribution_set FROM sp_target_info i WHERE t.id = i.target_id); ALTER TABLE sp_target_attributes DROP CONSTRAINT fk_targ_attrib_target; -ALTER TABLE sp_target_attributes - ADD CONSTRAINT fk_targ_attrib_target - FOREIGN KEY (target_id) - REFERENCES sp_target (id) - ON DELETE cascade; +ALTER TABLE sp_target_attributes + ADD CONSTRAINT fk_targ_attrib_target + FOREIGN KEY (target_id) + REFERENCES sp_target (id) + ON DELETE cascade; -ALTER TABLE sp_target_info DROP CONSTRAINT fk_target_inst_ds; -ALTER TABLE sp_target - ADD CONSTRAINT fk_target_inst_ds - FOREIGN KEY (installed_distribution_set) - REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target_info DROP CONSTRAINT fk_target_inst_ds; +ALTER TABLE sp_target + ADD CONSTRAINT fk_target_inst_ds + FOREIGN KEY (installed_distribution_set) + REFERENCES sp_distribution_set (id); ALTER TABLE sp_target_info DROP CONSTRAINT fk_targ_stat_targ; DROP INDEX sp_idx_target_info_02; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_1__target_filter_query_UQ___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_1__target_filter_query_UQ___H2.sql index f494313a8..fc1f615ba 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_1__target_filter_query_UQ___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_1__target_filter_query_UQ___H2.sql @@ -1,2 +1,2 @@ - alter table sp_target_filter_query - add constraint uk_tenant_custom_filter_name unique (name, tenant); +alter table sp_target_filter_query + add constraint uk_tenant_custom_filter_name unique (name, tenant); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_3__add_module_md_targetvis__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_3__add_module_md_targetvis__H2.sql index 2d5dfc8c4..1fc2a237d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_3__add_module_md_targetvis__H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_3__add_module_md_targetvis__H2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_sw_metadata ADD COLUMN target_visible boolean; \ No newline at end of file +ALTER TABLE sp_sw_metadata + ADD COLUMN target_visible boolean; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_0__action_performance___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_0__action_performance___H2.sql index 02b4199c9..ee5c2d694 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_0__action_performance___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_0__action_performance___H2.sql @@ -1,25 +1,34 @@ -ALTER TABLE sp_action ADD COLUMN action_type_new integer not null; -UPDATE sp_action SET action_type_new = -CASE WHEN (action_type = 'SOFT') THEN 1 - WHEN (action_type = 'TIMEFORCED') THEN 2 - ELSE 0 END; +ALTER TABLE sp_action + ADD COLUMN action_type_new integer not null; +UPDATE sp_action +SET action_type_new = + CASE + WHEN (action_type = 'SOFT') THEN 1 + WHEN (action_type = 'TIMEFORCED') THEN 2 + ELSE 0 END; ALTER TABLE sp_action DROP COLUMN action_type; ALTER TABLE sp_action ALTER COLUMN action_type_new RENAME TO action_type; -ALTER TABLE sp_rollout ADD COLUMN action_type_new integer not null; -UPDATE sp_rollout SET action_type_new = -CASE WHEN (action_type = 'SOFT') THEN 1 - WHEN (action_type = 'TIMEFORCED') THEN 2 - ELSE 0 END; +ALTER TABLE sp_rollout + ADD COLUMN action_type_new integer not null; +UPDATE sp_rollout +SET action_type_new = + CASE + WHEN (action_type = 'SOFT') THEN 1 + WHEN (action_type = 'TIMEFORCED') THEN 2 + ELSE 0 END; ALTER TABLE sp_rollout DROP COLUMN action_type; ALTER TABLE sp_rollout ALTER COLUMN action_type_new RENAME to action_type; -ALTER TABLE sp_target ADD COLUMN update_status_new integer not null; -UPDATE sp_target SET update_status_new = -CASE WHEN (update_status = 'IN_SYNC') THEN 1 - WHEN (update_status = 'PENDING') THEN 2 - WHEN (update_status = 'ERROR') THEN 3 - WHEN (update_status = 'REGISTERED') THEN 4 - ELSE 0 END; +ALTER TABLE sp_target + ADD COLUMN update_status_new integer not null; +UPDATE sp_target +SET update_status_new = + CASE + WHEN (update_status = 'IN_SYNC') THEN 1 + WHEN (update_status = 'PENDING') THEN 2 + WHEN (update_status = 'ERROR') THEN 3 + WHEN (update_status = 'REGISTERED') THEN 4 + ELSE 0 END; ALTER TABLE sp_target DROP COLUMN update_status; ALTER TABLE sp_target ALTER COLUMN update_status_new RENAME TO update_status; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_11__add_auto_assign_action_type___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_11__add_auto_assign_action_type___H2.sql index 16cb03ef2..ee00de0e6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_11__add_auto_assign_action_type___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_11__add_auto_assign_action_type___H2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_action_type integer; \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD COLUMN auto_assign_action_type integer; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_13__add_action_external_id___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_13__add_action_external_id___H2.sql index 8dbda293f..2556b7d21 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_13__add_action_external_id___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_13__add_action_external_id___H2.sql @@ -1,4 +1,5 @@ -ALTER TABLE sp_action ADD COLUMN external_ref VARCHAR(512); +ALTER TABLE sp_action + ADD COLUMN external_ref VARCHAR(512); CREATE INDEX sp_idx_action_external_ref ON sp_action (external_ref); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_14__add_sha256_hash___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_14__add_sha256_hash___H2.sql index ca7e53fce..bfe56f337 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_14__add_sha256_hash___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_14__add_sha256_hash___H2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_artifact ADD COLUMN sha256_hash CHAR(64); \ No newline at end of file +ALTER TABLE sp_artifact + ADD COLUMN sha256_hash CHAR(64); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_15__add_weight___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_15__add_weight___H2.sql index 9eaad20e1..12db78a80 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_15__add_weight___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_15__add_weight___H2.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_action ADD weight INT; -ALTER TABLE sp_rollout ADD weight INT; -ALTER TABLE sp_target_filter_query ADD auto_assign_weight INT; +ALTER TABLE sp_action + ADD weight INT; +ALTER TABLE sp_rollout + ADD weight INT; +ALTER TABLE sp_target_filter_query + ADD auto_assign_weight INT; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_16__add_action_initiated_by___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_16__add_action_initiated_by___H2.sql index d0b559b61..9461e26a2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_16__add_action_initiated_by___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_16__add_action_initiated_by___H2.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_action ADD COLUMN initiated_by VARCHAR(64) NOT NULL; -ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_initiated_by VARCHAR(64); +ALTER TABLE sp_action + ADD COLUMN initiated_by VARCHAR(64) NOT NULL; +ALTER TABLE sp_target_filter_query + ADD COLUMN auto_assign_initiated_by VARCHAR(64); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_19__add_valid_flag_to_ds___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_19__add_valid_flag_to_ds___H2.sql index 3ab0e7502..352419711 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_19__add_valid_flag_to_ds___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_19__add_valid_flag_to_ds___H2.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN; +ALTER TABLE sp_distribution_set + ADD COLUMN valid BOOLEAN; -UPDATE sp_distribution_set SET valid = 1; \ No newline at end of file +UPDATE sp_distribution_set +SET valid = 1; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_20__add_encryption_flag_to_sm___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_20__add_encryption_flag_to_sm___H2.sql index 9249d14a1..5dd518204 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_20__add_encryption_flag_to_sm___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_20__add_encryption_flag_to_sm___H2.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_base_software_module ADD COLUMN encrypted BOOLEAN; +ALTER TABLE sp_base_software_module + ADD COLUMN encrypted BOOLEAN; -UPDATE sp_base_software_module SET encrypted = 0; \ No newline at end of file +UPDATE sp_base_software_module +SET encrypted = 0; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_23__add_action_status_code___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_23__add_action_status_code___H2.sql index 2e4caf07a..7bc7abb4d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_23__add_action_status_code___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_23__add_action_status_code___H2.sql @@ -1,2 +1,3 @@ -ALTER TABLE sp_action_status ADD column code integer; +ALTER TABLE sp_action_status + ADD column code integer; CREATE INDEX sp_idx_action_status_03 ON sp_action_status (tenant, code); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_24__add_last_action_status_code___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_24__add_last_action_status_code___H2.sql index f92ba4675..4369c67e8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_24__add_last_action_status_code___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_24__add_last_action_status_code___H2.sql @@ -1 +1,2 @@ -ALTER TABLE sp_action ADD column last_action_status_code integer; \ No newline at end of file +ALTER TABLE sp_action + ADD column last_action_status_code integer; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_25__add_confirmation_flag___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_25__add_confirmation_flag___H2.sql index 8249c85d4..db9683d21 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_25__add_confirmation_flag___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_25__add_confirmation_flag___H2.sql @@ -1,21 +1,25 @@ -ALTER TABLE sp_rolloutgroup ADD column confirmation_required BOOLEAN; -UPDATE sp_rolloutgroup SET confirmation_required = 0; +ALTER TABLE sp_rolloutgroup + ADD column confirmation_required BOOLEAN; +UPDATE sp_rolloutgroup +SET confirmation_required = 0; -ALTER TABLE sp_target_filter_query ADD column confirmation_required BOOLEAN; -UPDATE sp_target_filter_query SET confirmation_required = 0; +ALTER TABLE sp_target_filter_query + ADD column confirmation_required BOOLEAN; +UPDATE sp_target_filter_query +SET confirmation_required = 0; create table sp_target_conf_status ( - id bigint not null auto_increment, - target_id bigint not null, - initiator varchar(64), - remark VARCHAR(512), - created_at bigint, - created_by varchar(64), - last_modified_at bigint, - last_modified_by varchar(64), - optlock_revision bigint, - tenant varchar(40) not null, + id bigint not null auto_increment, + target_id bigint not null, + initiator varchar(64), + remark VARCHAR(512), + created_at bigint, + created_by varchar(64), + last_modified_at bigint, + last_modified_by varchar(64), + optlock_revision bigint, + tenant varchar(40) not null, primary key (id) ); ALTER TABLE sp_target_conf_status diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_26__add_access_control_context___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_26__add_access_control_context___H2.sql index ccf16963e..fb06922c7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_26__add_access_control_context___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_26__add_access_control_context___H2.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_target_filter_query ADD COLUMN access_control_context VARCHAR(4096); -ALTER TABLE sp_rollout ADD COLUMN access_control_context VARCHAR(4096); \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD COLUMN access_control_context VARCHAR(4096); +ALTER TABLE sp_rollout + ADD COLUMN access_control_context VARCHAR(4096); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_27__target_type_inherit_type___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_27__target_type_inherit_type___H2.sql index 86e3350b8..2b63926eb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_27__target_type_inherit_type___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_27__target_type_inherit_type___H2.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_target_type ADD COLUMN type_key VARCHAR (64) NOT NULL DEFAULT ('_'); -UPDATE sp_target_type SET type_key = name; -ALTER TABLE sp_target_type ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file +ALTER TABLE sp_target_type + ADD COLUMN type_key VARCHAR(64) NOT NULL DEFAULT ('_'); +UPDATE sp_target_type +SET type_key = name; +ALTER TABLE sp_target_type + ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_28__add_dynamic_rollout___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_28__add_dynamic_rollout___H2.sql index f392ccd87..117921dd1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_28__add_dynamic_rollout___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_28__add_dynamic_rollout___H2.sql @@ -1,9 +1,17 @@ -ALTER TABLE sp_rollout ADD COLUMN is_dynamic BOOLEAN; -ALTER TABLE sp_rolloutgroup ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; +ALTER TABLE sp_rollout + ADD COLUMN is_dynamic BOOLEAN; +ALTER TABLE sp_rolloutgroup + ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; -UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; +UPDATE sp_rollout +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_action +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_target_filter_query +SET auto_assign_weight = 1000 +WHERE auto_assign_weight IS NULL; ALTER TABLE sp_rollout ALTER COLUMN weight INT NOT NULL; ALTER TABLE sp_action ALTER COLUMN weight INT NOT NULL; ALTER TABLE sp_target_filter_query ALTER COLUMN auto_assign_weight INT NOT NULL; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_29__add_ds_sm_locked___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_29__add_ds_sm_locked___H2.sql index c5c0de6fb..831528f40 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_29__add_ds_sm_locked___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_29__add_ds_sm_locked___H2.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_base_software_module ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; -ALTER TABLE sp_distribution_set ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file +ALTER TABLE sp_base_software_module + ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; +ALTER TABLE sp_distribution_set + ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_4__add_maintenance_window___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_4__add_maintenance_window___H2.sql index 6c546cede..9c817454f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_4__add_maintenance_window___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_4__add_maintenance_window___H2.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_action ADD column maintenance_cron_schedule VARCHAR(40); -ALTER TABLE sp_action ADD column maintenance_duration VARCHAR(40); -ALTER TABLE sp_action ADD column maintenance_time_zone VARCHAR(40); +ALTER TABLE sp_action + ADD column maintenance_cron_schedule VARCHAR(40); +ALTER TABLE sp_action + ADD column maintenance_duration VARCHAR(40); +ALTER TABLE sp_action + ADD column maintenance_time_zone VARCHAR(40); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_6__add_index___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_6__add_index___H2.sql index d7d7d6cc7..9fdbca2f8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_6__add_index___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_6__add_index___H2.sql @@ -1,2 +1,2 @@ -CREATE INDEX sp_idx_target_tag_01 ON sp_target_tag (tenant, name); +CREATE INDEX sp_idx_target_tag_01 ON sp_target_tag (tenant, name); CREATE INDEX sp_idx_distribution_set_tag_01 ON sp_distributionset_tag (tenant, name); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_7__add_rollout_approval_fields___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_7__add_rollout_approval_fields___H2.sql index 8438d909e..3e8138835 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_7__add_rollout_approval_fields___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_7__add_rollout_approval_fields___H2.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_rollout ADD column approval_decided_by varchar(40); -ALTER TABLE sp_rollout ADD column approval_remark varchar(255); \ No newline at end of file +ALTER TABLE sp_rollout + ADD column approval_decided_by varchar(40); +ALTER TABLE sp_rollout + ADD column approval_remark varchar(255); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_9__add_target_metadata___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_9__add_target_metadata___H2.sql index de70b7519..02a23baaf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_9__add_target_metadata___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_9__add_target_metadata___H2.sql @@ -1,12 +1,13 @@ -create table sp_target_metadata ( - meta_key varchar(128) not null, - meta_value varchar(4000), - target_id bigint not null, - primary key (target_id, meta_key) +create table sp_target_metadata +( + meta_key varchar(128) not null, + meta_value varchar(4000), + target_id bigint not null, + primary key (target_id, meta_key) ); - -alter table sp_target_metadata - add constraint fk_metadata_target - foreign key (target_id) - references sp_target - on delete cascade; \ No newline at end of file + +alter table sp_target_metadata + add constraint fk_metadata_target + foreign key (target_id) + references sp_target + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_2_0__update_target_info_for_message___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_2_0__update_target_info_for_message___H2.sql index 5bf96e631..a507d8afc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_2_0__update_target_info_for_message___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_2_0__update_target_info_for_message___H2.sql @@ -4,10 +4,10 @@ ALTER TABLE sp_target_info ALTER COLUMN ip_address RENAME TO address; ALTER TABLE sp_target_info ALTER COLUMN address VARCHAR(512); UPDATE sp_target_info -SET address = CONCAT('http://',(SELECT address - FROM sp_target_info i - WHERE sp_target_info.target_id = i.target_id)) +SET address = CONCAT('http://', (SELECT address + FROM sp_target_info i + WHERE sp_target_info.target_id = i.target_id)) WHERE EXISTS(SELECT target_id - FROM sp_target_info i - WHERE sp_target_info.target_id = i.target_id) -AND address != null; \ No newline at end of file + FROM sp_target_info i + WHERE sp_target_info.target_id = i.target_id) + AND address != null; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_4_0__cascade_delete___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_4_0__cascade_delete___H2.sql index 7ed5e8d58..30d6f9229 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_4_0__cascade_delete___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_4_0__cascade_delete___H2.sql @@ -1,69 +1,69 @@ alter table sp_target_info drop constraint fk_targ_stat_targ; -alter table sp_target_info - add constraint fk_targ_stat_targ - foreign key (target_id) - references sp_target - on delete cascade; +alter table sp_target_info + add constraint fk_targ_stat_targ + foreign key (target_id) + references sp_target + on delete cascade; alter table sp_action drop constraint fk_targ_act_hist_targ; -alter table sp_action - add constraint fk_targ_act_hist_targ - foreign key (target) - references sp_target - on delete cascade; +alter table sp_action + add constraint fk_targ_act_hist_targ + foreign key (target) + references sp_target + on delete cascade; -alter table sp_action_status drop constraint fk_act_stat_action; -alter table sp_action_status - add constraint fk_act_stat_action - foreign key (action) - references sp_action - on delete cascade; +alter table sp_action_status drop constraint fk_act_stat_action; +alter table sp_action_status + add constraint fk_act_stat_action + foreign key (action) + references sp_action + on delete cascade; -alter table sp_sw_metadata drop constraint fk_metadata_sw; -alter table sp_sw_metadata - add constraint fk_metadata_sw - foreign key (sw_id) - references sp_base_software_module - on delete cascade; +alter table sp_sw_metadata drop constraint fk_metadata_sw; +alter table sp_sw_metadata + add constraint fk_metadata_sw + foreign key (sw_id) + references sp_base_software_module + on delete cascade; + +alter table sp_ds_metadata drop constraint fk_metadata_ds; +alter table sp_ds_metadata + add constraint fk_metadata_ds + foreign key (ds_id) + references sp_distribution_set + on delete cascade; + +alter table sp_action_status_messages drop constraint fk_stat_msg_act_stat; +alter table sp_action_status_messages + add constraint fk_stat_msg_act_stat + foreign key (action_status_id) + references sp_action_status + on delete cascade; -alter table sp_ds_metadata drop constraint fk_metadata_ds; -alter table sp_ds_metadata - add constraint fk_metadata_ds - foreign key (ds_id) - references sp_distribution_set - on delete cascade; - -alter table sp_action_status_messages drop constraint fk_stat_msg_act_stat; -alter table sp_action_status_messages - add constraint fk_stat_msg_act_stat - foreign key (action_status_id) - references sp_action_status - on delete cascade; - alter table sp_ds_dstag drop constraint fk_ds_dstag_tag; -alter table sp_ds_dstag - add constraint fk_ds_dstag_tag - foreign key (TAG) - references sp_distributionset_tag - on delete cascade; - +alter table sp_ds_dstag + add constraint fk_ds_dstag_tag + foreign key (TAG) + references sp_distributionset_tag + on delete cascade; + alter table sp_ds_dstag drop constraint fk_ds_dstag_ds; -alter table sp_ds_dstag - add constraint fk_ds_dstag_ds - foreign key (ds) - references sp_distribution_set - on delete cascade; +alter table sp_ds_dstag + add constraint fk_ds_dstag_ds + foreign key (ds) + references sp_distribution_set + on delete cascade; alter table sp_target_target_tag drop constraint fk_targ_targtag_tag; -alter table sp_target_target_tag - add constraint fk_targ_targtag_tag - foreign key (tag) - references sp_target_tag - on delete cascade; +alter table sp_target_target_tag + add constraint fk_targ_targtag_tag + foreign key (tag) + references sp_target_tag + on delete cascade; alter table sp_target_target_tag drop constraint fk_targ_targtag_target; -alter table sp_target_target_tag - add constraint fk_targ_targtag_target - foreign key (target) - references sp_target - on delete cascade; \ No newline at end of file +alter table sp_target_target_tag + add constraint fk_targ_targtag_target + foreign key (target) + references sp_target + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_4_1__cascade_delete___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_4_1__cascade_delete___H2.sql index 915dac153..0dc091108 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_4_1__cascade_delete___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_4_1__cascade_delete___H2.sql @@ -1,6 +1,6 @@ alter table sp_target_attributes drop constraint fk_targ_attrib_target; -alter table sp_target_attributes - add constraint fk_targ_attrib_target - foreign key (target_id) - references sp_target_info - on delete cascade; \ No newline at end of file +alter table sp_target_attributes + add constraint fk_targ_attrib_target + foreign key (target_id) + references sp_target_info + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_5_0__target_filter_query___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_5_0__target_filter_query___H2.sql index 0cbc3744a..d45c5f419 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_5_0__target_filter_query___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_5_0__target_filter_query___H2.sql @@ -1,14 +1,15 @@ - create table sp_target_filter_query ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - name varchar(64) not null, - query varchar(1024) not null, - primary key (id) +create table sp_target_filter_query +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + name varchar(64) not null, + query varchar(1024) not null, + primary key (id) ); create index sp_idx_target_filter_query_01 on sp_target_filter_query (tenant, name); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_6_0__rollout_management___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_6_0__rollout_management___H2.sql index 490400161..cd100f890 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_6_0__rollout_management___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_6_0__rollout_management___H2.sql @@ -1,103 +1,108 @@ - create table sp_rolloutgroup ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - error_condition integer, - error_condition_exp varchar(512), - error_action integer, - error_action_exp varchar(512), - success_condition integer not null, - success_condition_exp varchar(512) not null, - success_action integer not null, - success_action_exp varchar(512), - status integer, - parent_id bigint, - rollout bigint, - total_targets bigint, - primary key (id) - ); - - create table sp_rollout ( - id bigint generated by default as identity, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - last_check bigint, - group_theshold float, - status integer, - distribution_set bigint, - target_filter varchar(1024), - action_type varchar(255) not null, - forced_time bigint, - total_targets bigint, - primary key (id) - ); - - create table sp_rollouttargetgroup ( - target_Id bigint not null, - rolloutGroup_Id bigint not null, - primary key (rolloutGroup_Id, target_Id) - ); - - create index sp_idx_rollout_01 on sp_rollout (tenant, name); - - create index sp_idx_rolloutgroup_01 on sp_rolloutgroup (tenant, name); - - ALTER TABLE sp_action ADD COLUMN rollout bigint; - ALTER TABLE sp_action ADD COLUMN rolloutgroup bigint; - - alter table sp_rollout - add constraint uk_rollout unique (name, tenant); - - alter table sp_rolloutgroup - add constraint uk_rolloutgroup unique (name, rollout, tenant); - - alter table sp_action - add constraint fk_action_rollout - foreign key (rollout) - references sp_rollout; - - alter table sp_action - add constraint fk_action_rolloutgroup - foreign key (rolloutgroup) - references sp_rolloutgroup; - - alter table sp_rollout - add constraint fk_rollout_ds - foreign key (distribution_set) - references sp_distribution_set; +create table sp_rolloutgroup +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + error_condition integer, + error_condition_exp varchar(512), + error_action integer, + error_action_exp varchar(512), + success_condition integer not null, + success_condition_exp varchar(512) not null, + success_action integer not null, + success_action_exp varchar(512), + status integer, + parent_id bigint, + rollout bigint, + total_targets bigint, + primary key (id) +); - alter table sp_rolloutgroup - add constraint fk_rolloutgroup_rollout - foreign key (rollout) - references sp_rollout - on delete cascade; - - alter table sp_rolloutgroup - add constraint fk_rolloutgroup_rolloutgroup - foreign key (parent_id) - references sp_rolloutgroup - on delete cascade; - - alter table sp_rollouttargetgroup - add constraint fk_rollouttargetgroup_target - foreign key (target_id) - references sp_target - on delete cascade; +create table sp_rollout +( + id bigint generated by default as identity, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + last_check bigint, + group_theshold float, + status integer, + distribution_set bigint, + target_filter varchar(1024), + action_type varchar(255) not null, + forced_time bigint, + total_targets bigint, + primary key (id) +); - alter table sp_rollouttargetgroup - add constraint fk_rollouttargetgroup_rolloutgroup - foreign key (rolloutgroup_id) - references sp_rolloutgroup - on delete cascade; \ No newline at end of file +create table sp_rollouttargetgroup +( + target_Id bigint not null, + rolloutGroup_Id bigint not null, + primary key (rolloutGroup_Id, target_Id) +); + +create index sp_idx_rollout_01 on sp_rollout (tenant, name); + +create index sp_idx_rolloutgroup_01 on sp_rolloutgroup (tenant, name); + +ALTER TABLE sp_action + ADD COLUMN rollout bigint; +ALTER TABLE sp_action + ADD COLUMN rolloutgroup bigint; + +alter table sp_rollout + add constraint uk_rollout unique (name, tenant); + +alter table sp_rolloutgroup + add constraint uk_rolloutgroup unique (name, rollout, tenant); + +alter table sp_action + add constraint fk_action_rollout + foreign key (rollout) + references sp_rollout; + +alter table sp_action + add constraint fk_action_rolloutgroup + foreign key (rolloutgroup) + references sp_rolloutgroup; + +alter table sp_rollout + add constraint fk_rollout_ds + foreign key (distribution_set) + references sp_distribution_set; + +alter table sp_rolloutgroup + add constraint fk_rolloutgroup_rollout + foreign key (rollout) + references sp_rollout + on delete cascade; + +alter table sp_rolloutgroup + add constraint fk_rolloutgroup_rolloutgroup + foreign key (parent_id) + references sp_rolloutgroup + on delete cascade; + +alter table sp_rollouttargetgroup + add constraint fk_rollouttargetgroup_target + foreign key (target_id) + references sp_target + on delete cascade; + +alter table sp_rollouttargetgroup + add constraint fk_rollouttargetgroup_rolloutgroup + foreign key (rolloutgroup_id) + references sp_rolloutgroup + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_7_0__swmType_maxAssignment_greater_0__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_7_0__swmType_maxAssignment_greater_0__H2.sql index f79c9375c..75766d9dc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_7_0__swmType_maxAssignment_greater_0__H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_7_0__swmType_maxAssignment_greater_0__H2.sql @@ -1 +1,3 @@ -Update sp_software_module_type set max_ds_assignments = 1 where max_ds_assignments < 1; \ No newline at end of file +Update sp_software_module_type +set max_ds_assignments = 1 +where max_ds_assignments < 1; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_8_0__auto_assign_ds_filter__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_8_0__auto_assign_ds_filter__H2.sql index 2d56f27f2..f4d7f0169 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_8_0__auto_assign_ds_filter__H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_8_0__auto_assign_ds_filter__H2.sql @@ -1,8 +1,8 @@ ALTER TABLE sp_target_filter_query - ADD column auto_assign_distribution_set BIGINT; + ADD column auto_assign_distribution_set BIGINT; ALTER TABLE sp_target_filter_query - ADD CONSTRAINT fk_filter_auto_assign_ds -FOREIGN KEY (auto_assign_distribution_set) -REFERENCES sp_distribution_set -ON DELETE SET NULL; + ADD CONSTRAINT fk_filter_auto_assign_ds + FOREIGN KEY (auto_assign_distribution_set) + REFERENCES sp_distribution_set + ON DELETE SET NULL; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_8_1__cascade_delete___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_8_1__cascade_delete___H2.sql index 0c6225fae..2235078c3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_8_1__cascade_delete___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_8_1__cascade_delete___H2.sql @@ -1,27 +1,27 @@ alter table sp_ds_module drop constraint fk_ds_module_ds; -alter table sp_ds_module - add constraint fk_ds_module_ds - foreign key (ds_id) - references sp_distribution_set (id) - on delete cascade; +alter table sp_ds_module + add constraint fk_ds_module_ds + foreign key (ds_id) + references sp_distribution_set (id) + on delete cascade; alter table sp_ds_module drop constraint fk_ds_module_module; -alter table sp_ds_module - add constraint fk_ds_module_module - foreign key (module_id) - references sp_base_software_module (id) - on delete cascade; +alter table sp_ds_module + add constraint fk_ds_module_module + foreign key (module_id) + references sp_base_software_module (id) + on delete cascade; alter table sp_external_artifact drop constraint fk_external_assigned_sm; -alter table sp_external_artifact - add constraint fk_external_assigned_sm - foreign key (software_module) - references sp_base_software_module (id) - on delete cascade; +alter table sp_external_artifact + add constraint fk_external_assigned_sm + foreign key (software_module) + references sp_base_software_module (id) + on delete cascade; alter table sp_artifact drop constraint fk_assigned_sm; -alter table sp_artifact - add constraint fk_assigned_sm - foreign key (software_module) - references sp_base_software_module (id) - on delete cascade; \ No newline at end of file +alter table sp_artifact + add constraint fk_assigned_sm + foreign key (software_module) + references sp_base_software_module (id) + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_9_0__add_rollout_groups_created___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_9_0__add_rollout_groups_created___H2.sql index 64518f762..bbcd2d6af 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_9_0__add_rollout_groups_created___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_9_0__add_rollout_groups_created___H2.sql @@ -1,2 +1,3 @@ - ALTER TABLE sp_rollout ADD column rollout_groups_created BIGINT; +ALTER TABLE sp_rollout + ADD column rollout_groups_created BIGINT; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_0_1__init___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_0_1__init___MYSQL.sql index ec243a68b..ac7dc0053 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_0_1__init___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_0_1__init___MYSQL.sql @@ -1,494 +1,516 @@ +create table sp_action +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + action_type varchar(255) not null, + active bit, + forced_time bigint, + status integer, + distribution_set bigint, + target bigint, + primary key (id) +); + +create table sp_action_status +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + target_occurred_at bigint, + status integer, + action bigint not null, + primary key (id) +); + +create table sp_action_status_messages +( + action_status_id bigint not null, + detail_message varchar(512) +); + +create table sp_artifact +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + md5_hash varchar(32), + sha1_hash varchar(40), + file_size bigint, + provided_file_name varchar(256), + gridfs_file_name varchar(40), + software_module bigint not null, + primary key (id) +); + +create table sp_base_software_module +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + version varchar(64) not null, + deleted bit, + vendor varchar(256), + module_type bigint not null, + primary key (id) +); + +create table sp_distribution_set +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + version varchar(64) not null, + complete bit, + deleted bit, + required_migration_step bit, + ds_id bigint not null, + primary key (id) +); + +create table sp_distribution_set_type +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + colour varchar(16), + deleted bit, + type_key varchar(64) not null, + primary key (id) +); + +create table sp_distributionset_tag +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + colour varchar(16), + primary key (id) +); + +create table sp_ds_dstag +( + ds bigint not null, + TAG bigint not null, + primary key (ds, TAG) +); + +create table sp_ds_metadata +( + meta_key varchar(128) not null, + meta_value varchar(4000), + ds_id bigint not null, + primary key (ds_id, meta_key) +); + +create table sp_ds_module +( + ds_id bigint not null, + module_id bigint not null, + primary key (ds_id, module_id) +); + +create table sp_ds_type_element +( + mandatory bit, + distribution_set_type bigint not null, + software_module_type bigint not null, + primary key (distribution_set_type, software_module_type) +); + +create table sp_external_artifact +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + md5_hash varchar(32), + sha1_hash varchar(40), + file_size bigint, + url_suffix varchar(512), + provider bigint not null, + software_module bigint not null, + primary key (id) +); + +create table sp_external_provider +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + base_url varchar(512) not null, + default_url_suffix varchar(512), + primary key (id) +); + +create table sp_software_module_type +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + colour varchar(16), + deleted bit, + type_key varchar(64) not null, + max_ds_assignments integer not null, + primary key (id) +); + +create table sp_sw_metadata +( + meta_key varchar(128) not null, + meta_value varchar(4000), + sw_id bigint not null, + primary key (meta_key, sw_id) +); + +create table sp_target +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + controller_id varchar(64), + sec_token varchar(128) not null, + assigned_distribution_set bigint, + primary key (id) +); + +create table sp_target_attributes +( + target_id bigint not null, + attribute_value varchar(128), + attribute_key varchar(32) not null, + primary key (target_id, attribute_key) +); + +create table sp_target_info +( + target_id bigint not null, + install_date bigint, + ip_address varchar(46), + last_target_query bigint, + request_controller_attributes bit not null, + update_status varchar(255) not null, + installed_distribution_set bigint, + primary key (target_id) +); + +create table sp_target_tag +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + colour varchar(16), + primary key (id) +); + +create table sp_target_target_tag +( + target bigint not null, + tag bigint not null, + primary key (target, tag) +); + +create table sp_tenant +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + default_ds_type bigint not null, + primary key (id) +); + +create table sp_tenant_configuration +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + conf_key varchar(128), + conf_value varchar(512), + primary key (id) +); - create table sp_action ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - action_type varchar(255) not null, - active bit, - forced_time bigint, - status integer, - distribution_set bigint, - target bigint, - primary key (id) - ); - - create table sp_action_status ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - target_occurred_at bigint, - status integer, - action bigint not null, - primary key (id) - ); - - create table sp_action_status_messages ( - action_status_id bigint not null, - detail_message varchar(512) - ); - - create table sp_artifact ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - md5_hash varchar(32), - sha1_hash varchar(40), - file_size bigint, - provided_file_name varchar(256), - gridfs_file_name varchar(40), - software_module bigint not null, - primary key (id) - ); - - create table sp_base_software_module ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - version varchar(64) not null, - deleted bit, - vendor varchar(256), - module_type bigint not null, - primary key (id) - ); - - create table sp_distribution_set ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - version varchar(64) not null, - complete bit, - deleted bit, - required_migration_step bit, - ds_id bigint not null, - primary key (id) - ); - - create table sp_distribution_set_type ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - colour varchar(16), - deleted bit, - type_key varchar(64) not null, - primary key (id) - ); - - create table sp_distributionset_tag ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - colour varchar(16), - primary key (id) - ); - - create table sp_ds_dstag ( - ds bigint not null, - TAG bigint not null, - primary key (ds, TAG) - ); - - create table sp_ds_metadata ( - meta_key varchar(128) not null, - meta_value varchar(4000), - ds_id bigint not null, - primary key (ds_id, meta_key) - ); - - create table sp_ds_module ( - ds_id bigint not null, - module_id bigint not null, - primary key (ds_id, module_id) - ); - - create table sp_ds_type_element ( - mandatory bit, - distribution_set_type bigint not null, - software_module_type bigint not null, - primary key (distribution_set_type, software_module_type) - ); - - create table sp_external_artifact ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - md5_hash varchar(32), - sha1_hash varchar(40), - file_size bigint, - url_suffix varchar(512), - provider bigint not null, - software_module bigint not null, - primary key (id) - ); - - create table sp_external_provider ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - base_url varchar(512) not null, - default_url_suffix varchar(512), - primary key (id) - ); - - create table sp_software_module_type ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - colour varchar(16), - deleted bit, - type_key varchar(64) not null, - max_ds_assignments integer not null, - primary key (id) - ); - - create table sp_sw_metadata ( - meta_key varchar(128) not null, - meta_value varchar(4000), - sw_id bigint not null, - primary key (meta_key, sw_id) - ); - - create table sp_target ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - controller_id varchar(64), - sec_token varchar(128) not null, - assigned_distribution_set bigint, - primary key (id) - ); - - create table sp_target_attributes ( - target_id bigint not null, - attribute_value varchar(128), - attribute_key varchar(32) not null, - primary key (target_id, attribute_key) - ); - - create table sp_target_info ( - target_id bigint not null, - install_date bigint, - ip_address varchar(46), - last_target_query bigint, - request_controller_attributes bit not null, - update_status varchar(255) not null, - installed_distribution_set bigint, - primary key (target_id) - ); - - create table sp_target_tag ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - colour varchar(16), - primary key (id) - ); - - create table sp_target_target_tag ( - target bigint not null, - tag bigint not null, - primary key (target, tag) - ); - - create table sp_tenant ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - default_ds_type bigint not null, - primary key (id) - ); - - create table sp_tenant_configuration ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - conf_key varchar(128), - conf_value varchar(512), - primary key (id) - ); +create index sp_idx_action_01 on sp_action (tenant, distribution_set); - create index sp_idx_action_01 on sp_action (tenant, distribution_set); +create index sp_idx_action_02 on sp_action (tenant, target, active); - create index sp_idx_action_02 on sp_action (tenant, target, active); +create index sp_idx_action_prim on sp_action (tenant, id); - create index sp_idx_action_prim on sp_action (tenant, id); +create index sp_idx_action_status_01 on sp_action_status (tenant, action); - create index sp_idx_action_status_01 on sp_action_status (tenant, action); +create index sp_idx_action_status_02 on sp_action_status (tenant, action, status); - create index sp_idx_action_status_02 on sp_action_status (tenant, action, status); +create index sp_idx_action_status_prim on sp_action_status (tenant, id); - create index sp_idx_action_status_prim on sp_action_status (tenant, id); +create index sp_idx_action_status_msgs_01 on sp_action_status_messages (action_status_id); - create index sp_idx_action_status_msgs_01 on sp_action_status_messages (action_status_id); +create index sp_idx_artifact_01 on sp_artifact (tenant, software_module); - create index sp_idx_artifact_01 on sp_artifact (tenant, software_module); +create index sp_idx_artifact_prim on sp_artifact (tenant, id); - create index sp_idx_artifact_prim on sp_artifact (tenant, id); +alter table sp_base_software_module + add constraint uk_base_sw_mod unique (module_type, name, version, tenant); - alter table sp_base_software_module - add constraint uk_base_sw_mod unique (module_type, name, version, tenant); +create index sp_idx_base_sw_module_01 on sp_base_software_module (tenant, deleted, name, version); - create index sp_idx_base_sw_module_01 on sp_base_software_module (tenant, deleted, name, version); +create index sp_idx_base_sw_module_02 on sp_base_software_module (tenant, deleted, module_type); - create index sp_idx_base_sw_module_02 on sp_base_software_module (tenant, deleted, module_type); +create index sp_idx_base_sw_module_prim on sp_base_software_module (tenant, id); - create index sp_idx_base_sw_module_prim on sp_base_software_module (tenant, id); +alter table sp_distribution_set + add constraint uk_distrib_set unique (name, version, tenant); - alter table sp_distribution_set - add constraint uk_distrib_set unique (name, version, tenant); +create index sp_idx_distribution_set_01 on sp_distribution_set (tenant, deleted, name, complete); - create index sp_idx_distribution_set_01 on sp_distribution_set (tenant, deleted, name, complete); +create index sp_idx_distribution_set_02 on sp_distribution_set (tenant, required_migration_step); - create index sp_idx_distribution_set_02 on sp_distribution_set (tenant, required_migration_step); +create index sp_idx_distribution_set_prim on sp_distribution_set (tenant, id); - create index sp_idx_distribution_set_prim on sp_distribution_set (tenant, id); +alter table sp_distribution_set_type + add constraint uk_dst_name unique (name, tenant); - alter table sp_distribution_set_type - add constraint uk_dst_name unique (name, tenant); +alter table sp_distribution_set_type + add constraint uk_dst_key unique (type_key, tenant); - alter table sp_distribution_set_type - add constraint uk_dst_key unique (type_key, tenant); +create index sp_idx_distribution_set_type_01 on sp_distribution_set_type (tenant, deleted); - create index sp_idx_distribution_set_type_01 on sp_distribution_set_type (tenant, deleted); +create index sp_idx_distribution_set_type_prim on sp_distribution_set_type (tenant, id); - create index sp_idx_distribution_set_type_prim on sp_distribution_set_type (tenant, id); +alter table sp_distributionset_tag + add constraint uk_ds_tag unique (name, tenant); - alter table sp_distributionset_tag - add constraint uk_ds_tag unique (name, tenant); +create index sp_idx_distribution_set_tag_prim on sp_distributionset_tag (tenant, id); - create index sp_idx_distribution_set_tag_prim on sp_distributionset_tag (tenant, id); +create index sp_idx_external_artifact_prim on sp_external_artifact (id, tenant); - create index sp_idx_external_artifact_prim on sp_external_artifact (id, tenant); +create index sp_idx_external_provider_prim on sp_external_provider (tenant, id); - create index sp_idx_external_provider_prim on sp_external_provider (tenant, id); +alter table sp_software_module_type + add constraint uk_smt_type_key unique (type_key, tenant); - alter table sp_software_module_type - add constraint uk_smt_type_key unique (type_key, tenant); +alter table sp_software_module_type + add constraint uk_smt_name unique (name, tenant); - alter table sp_software_module_type - add constraint uk_smt_name unique (name, tenant); +create index sp_idx_software_module_type_01 on sp_software_module_type (tenant, deleted); - create index sp_idx_software_module_type_01 on sp_software_module_type (tenant, deleted); +create index sp_idx_software_module_type_prim on sp_software_module_type (tenant, id); - create index sp_idx_software_module_type_prim on sp_software_module_type (tenant, id); +alter table sp_target + add constraint uk_tenant_controller_id unique (controller_id, tenant); - alter table sp_target - add constraint uk_tenant_controller_id unique (controller_id, tenant); +create index sp_idx_target_01 on sp_target (tenant, name, assigned_distribution_set); - create index sp_idx_target_01 on sp_target (tenant, name, assigned_distribution_set); +create index sp_idx_target_02 on sp_target (tenant, name); - create index sp_idx_target_02 on sp_target (tenant, name); +create index sp_idx_target_03 on sp_target (tenant, controller_id, assigned_distribution_set); - create index sp_idx_target_03 on sp_target (tenant, controller_id, assigned_distribution_set); - - create index sp_idx_target_04 on sp_target (tenant, created_at); +create index sp_idx_target_04 on sp_target (tenant, created_at); - create index sp_idx_target_prim on sp_target (tenant, id); +create index sp_idx_target_prim on sp_target (tenant, id); - create index sp_idx_target_info_01 on sp_target_info (ip_address); +create index sp_idx_target_info_01 on sp_target_info (ip_address); - create index sp_idx_target_info_02 on sp_target_info (target_id, update_status); +create index sp_idx_target_info_02 on sp_target_info (target_id, update_status); - alter table sp_target_tag - add constraint uk_targ_tag unique (name, tenant); +alter table sp_target_tag + add constraint uk_targ_tag unique (name, tenant); - create index sp_idx_target_tag_prim on sp_target_tag (tenant, id); +create index sp_idx_target_tag_prim on sp_target_tag (tenant, id); - alter table sp_tenant - add constraint uk_tenantmd_tenant unique (tenant); +alter table sp_tenant + add constraint uk_tenantmd_tenant unique (tenant); - create index sp_idx_tenant_prim on sp_tenant (tenant, id); +create index sp_idx_tenant_prim on sp_tenant (tenant, id); - alter table sp_tenant_configuration - add constraint uk_tenant_key unique (conf_key, tenant); +alter table sp_tenant_configuration + add constraint uk_tenant_key unique (conf_key, tenant); - alter table sp_action - add constraint fk_action_ds - foreign key (distribution_set) - references sp_distribution_set (id); +alter table sp_action + add constraint fk_action_ds + foreign key (distribution_set) + references sp_distribution_set (id); - alter table sp_action - add constraint fk_targ_act_hist_targ - foreign key (target) - references sp_target (id); +alter table sp_action + add constraint fk_targ_act_hist_targ + foreign key (target) + references sp_target (id); - alter table sp_action_status - add constraint fk_act_stat_action - foreign key (action) - references sp_action (id); +alter table sp_action_status + add constraint fk_act_stat_action + foreign key (action) + references sp_action (id); - alter table sp_action_status_messages - add constraint fk_stat_msg_act_stat - foreign key (action_status_id) - references sp_action_status (id); +alter table sp_action_status_messages + add constraint fk_stat_msg_act_stat + foreign key (action_status_id) + references sp_action_status (id); - alter table sp_artifact - add constraint fk_assigned_sm - foreign key (software_module) - references sp_base_software_module (id); +alter table sp_artifact + add constraint fk_assigned_sm + foreign key (software_module) + references sp_base_software_module (id); - alter table sp_base_software_module - add constraint fk_module_type - foreign key (module_type) - references sp_software_module_type (id); +alter table sp_base_software_module + add constraint fk_module_type + foreign key (module_type) + references sp_software_module_type (id); - alter table sp_distribution_set - add constraint fk_ds_dstype_ds - foreign key (ds_id) - references sp_distribution_set_type (id); +alter table sp_distribution_set + add constraint fk_ds_dstype_ds + foreign key (ds_id) + references sp_distribution_set_type (id); - alter table sp_ds_dstag - add constraint fk_ds_dstag_tag - foreign key (TAG) - references sp_distributionset_tag (id); +alter table sp_ds_dstag + add constraint fk_ds_dstag_tag + foreign key (TAG) + references sp_distributionset_tag (id); - alter table sp_ds_dstag - add constraint fk_ds_dstag_ds - foreign key (ds) - references sp_distribution_set (id); +alter table sp_ds_dstag + add constraint fk_ds_dstag_ds + foreign key (ds) + references sp_distribution_set (id); - alter table sp_ds_metadata - add constraint fk_metadata_ds - foreign key (ds_id) - references sp_distribution_set (id); +alter table sp_ds_metadata + add constraint fk_metadata_ds + foreign key (ds_id) + references sp_distribution_set (id); - alter table sp_ds_module - add constraint fk_ds_module_module - foreign key (module_id) - references sp_base_software_module (id); +alter table sp_ds_module + add constraint fk_ds_module_module + foreign key (module_id) + references sp_base_software_module (id); - alter table sp_ds_module - add constraint fk_ds_module_ds - foreign key (ds_id) - references sp_distribution_set (id); +alter table sp_ds_module + add constraint fk_ds_module_ds + foreign key (ds_id) + references sp_distribution_set (id); - alter table sp_ds_type_element - add constraint fk_ds_type_element_element - foreign key (distribution_set_type) - references sp_distribution_set_type (id); +alter table sp_ds_type_element + add constraint fk_ds_type_element_element + foreign key (distribution_set_type) + references sp_distribution_set_type (id); - alter table sp_ds_type_element - add constraint fk_ds_type_element_smtype - foreign key (software_module_type) - references sp_software_module_type (id); - - alter table sp_external_artifact - add constraint fk_art_to_ext_provider - foreign key (provider) - references sp_external_provider (id); - - alter table sp_external_artifact - add constraint fk_external_assigned_sm - foreign key (software_module) - references sp_base_software_module (id); - - alter table sp_sw_metadata - add constraint fk_metadata_sw - foreign key (sw_id) - references sp_base_software_module (id); - - alter table sp_target - add constraint fk_target_assign_ds - foreign key (assigned_distribution_set) - references sp_distribution_set (id); - - alter table sp_target_attributes - add constraint fk_targ_attrib_target - foreign key (target_id) - references sp_target_info (target_id); - - alter table sp_target_info - add constraint fk_target_inst_ds - foreign key (installed_distribution_set) - references sp_distribution_set (id); - - alter table sp_target_info - add constraint fk_targ_stat_targ - foreign key (target_id) - references sp_target (id); - - alter table sp_target_target_tag - add constraint fk_targ_targtag_tag - foreign key (tag) - references sp_target_tag (id); - - alter table sp_target_target_tag - add constraint fk_targ_targtag_target - foreign key (target) - references sp_target (id); - - alter table sp_tenant - add constraint fk_tenant_md_default_ds_type - foreign key (default_ds_type) - references sp_distribution_set_type (id); +alter table sp_ds_type_element + add constraint fk_ds_type_element_smtype + foreign key (software_module_type) + references sp_software_module_type (id); + +alter table sp_external_artifact + add constraint fk_art_to_ext_provider + foreign key (provider) + references sp_external_provider (id); + +alter table sp_external_artifact + add constraint fk_external_assigned_sm + foreign key (software_module) + references sp_base_software_module (id); + +alter table sp_sw_metadata + add constraint fk_metadata_sw + foreign key (sw_id) + references sp_base_software_module (id); + +alter table sp_target + add constraint fk_target_assign_ds + foreign key (assigned_distribution_set) + references sp_distribution_set (id); + +alter table sp_target_attributes + add constraint fk_targ_attrib_target + foreign key (target_id) + references sp_target_info (target_id); + +alter table sp_target_info + add constraint fk_target_inst_ds + foreign key (installed_distribution_set) + references sp_distribution_set (id); + +alter table sp_target_info + add constraint fk_targ_stat_targ + foreign key (target_id) + references sp_target (id); + +alter table sp_target_target_tag + add constraint fk_targ_targtag_tag + foreign key (tag) + references sp_target_tag (id); + +alter table sp_target_target_tag + add constraint fk_targ_targtag_target + foreign key (target) + references sp_target (id); + +alter table sp_tenant + add constraint fk_tenant_md_default_ds_type + foreign key (default_ds_type) + references sp_distribution_set_type (id); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_0__advanced_rolloutgroup__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_0__advanced_rolloutgroup__MYSQL.sql index 7c4954ad8..27c73472e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_0__advanced_rolloutgroup__MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_0__advanced_rolloutgroup__MYSQL.sql @@ -1,4 +1,4 @@ ALTER TABLE sp_rolloutgroup - ADD COLUMN target_percentage FLOAT; + ADD COLUMN target_percentage FLOAT; ALTER TABLE sp_rolloutgroup - ADD COLUMN target_filter VARCHAR (1024); + ADD COLUMN target_filter VARCHAR(1024); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_1__consolidate_artifact_sha1__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_1__consolidate_artifact_sha1__MYSQL.sql index 05b34fd5f..9c2ed1c23 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_1__consolidate_artifact_sha1__MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_1__consolidate_artifact_sha1__MYSQL.sql @@ -1,3 +1,3 @@ ALTER TABLE sp_artifact DROP COLUMN sha1_hash; -ALTER TABLE sp_artifact CHANGE gridfs_file_name sha1_hash varchar(40) not null; +ALTER TABLE sp_artifact CHANGE gridfs_file_name sha1_hash varchar (40) not null; CREATE INDEX sp_idx_artifact_02 ON sp_artifact (tenant, sha1_hash); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_2__rollout_auto_start__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_2__rollout_auto_start__MYSQL.sql index e946026f3..14f2a7abb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_2__rollout_auto_start__MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_2__rollout_auto_start__MYSQL.sql @@ -1,2 +1,2 @@ ALTER TABLE sp_rollout - ADD COLUMN start_at BIGINT; + ADD COLUMN start_at BIGINT; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_3__add_rollout_deleted_flag__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_3__add_rollout_deleted_flag__MYSQL.sql index ed184162e..bbe81787e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_3__add_rollout_deleted_flag__MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_3__add_rollout_deleted_flag__MYSQL.sql @@ -1,6 +1,8 @@ -ALTER TABLE sp_rollout ADD COLUMN deleted BOOLEAN; +ALTER TABLE sp_rollout + ADD COLUMN deleted BOOLEAN; -UPDATE sp_rollout SET deleted = 0; +UPDATE sp_rollout +SET deleted = 0; ALTER TABLE sp_action MODIFY target BIGINT NOT NULL; ALTER TABLE sp_action MODIFY distribution_set BIGINT NOT NULL; @@ -12,15 +14,15 @@ ALTER TABLE sp_rolloutgroup MODIFY rollout BIGINT NOT NULL; ALTER TABLE sp_rolloutgroup MODIFY status INTEGER NOT NULL; ALTER TABLE sp_ds_type_element DROP FOREIGN KEY fk_ds_type_element_element; -ALTER TABLE sp_ds_type_element - ADD CONSTRAINT fk_ds_type_element_element - FOREIGN KEY (distribution_set_type) - REFERENCES sp_distribution_set_type (id) - ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element + ADD CONSTRAINT fk_ds_type_element_element + FOREIGN KEY (distribution_set_type) + REFERENCES sp_distribution_set_type (id) + ON DELETE CASCADE; ALTER TABLE sp_ds_type_element DROP FOREIGN KEY fk_ds_type_element_smtype; -ALTER TABLE sp_ds_type_element - ADD CONSTRAINT fk_ds_type_element_smtype - FOREIGN KEY (software_module_type) - REFERENCES sp_software_module_type (id) - ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element + ADD CONSTRAINT fk_ds_type_element_smtype + FOREIGN KEY (software_module_type) + REFERENCES sp_software_module_type (id) + ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_0__drop_target_info__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_0__drop_target_info__MYSQL.sql index f170e0f22..f225f65cc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_0__drop_target_info__MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_0__drop_target_info__MYSQL.sql @@ -1,30 +1,34 @@ -ALTER TABLE sp_target ADD COLUMN install_date bigint; -ALTER TABLE sp_target ADD COLUMN address varchar(512); -ALTER TABLE sp_target ADD COLUMN last_target_query bigint; -ALTER TABLE sp_target ADD COLUMN request_controller_attributes bit not null; -ALTER TABLE sp_target ADD COLUMN update_status varchar(16) not null; -ALTER TABLE sp_target ADD COLUMN installed_distribution_set bigint; +ALTER TABLE sp_target + ADD COLUMN install_date bigint; +ALTER TABLE sp_target + ADD COLUMN address varchar(512); +ALTER TABLE sp_target + ADD COLUMN last_target_query bigint; +ALTER TABLE sp_target + ADD COLUMN request_controller_attributes bit not null; +ALTER TABLE sp_target + ADD COLUMN update_status varchar(16) not null; +ALTER TABLE sp_target + ADD COLUMN installed_distribution_set bigint; UPDATE sp_target AS t INNER JOIN sp_target_info AS i - ON t.id = i.target_id -SET t.install_date = i.install_date, t.address = i.address,t.last_target_query = i.last_target_query, - t.request_controller_attributes = i.request_controller_attributes,t.update_status = i.update_status, - t.installed_distribution_set = i.installed_distribution_set; +ON t.id = i.target_id + SET t.install_date = i.install_date, t.address = i.address, t.last_target_query = i.last_target_query, t.request_controller_attributes = i.request_controller_attributes, t.update_status = i.update_status, t.installed_distribution_set = i.installed_distribution_set; ALTER TABLE sp_target_info DROP INDEX sp_idx_target_info_02; ALTER TABLE sp_target_attributes DROP FOREIGN KEY fk_targ_attrib_target; -ALTER TABLE sp_target_attributes - ADD CONSTRAINT fk_targ_attrib_target - FOREIGN KEY (target_id) - REFERENCES sp_target (id) - ON DELETE cascade; +ALTER TABLE sp_target_attributes + ADD CONSTRAINT fk_targ_attrib_target + FOREIGN KEY (target_id) + REFERENCES sp_target (id) + ON DELETE cascade; -ALTER TABLE sp_target_info DROP FOREIGN KEY fk_target_inst_ds; -ALTER TABLE sp_target - ADD CONSTRAINT fk_target_inst_ds - FOREIGN KEY (installed_distribution_set) - REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target_info DROP FOREIGN KEY fk_target_inst_ds; +ALTER TABLE sp_target + ADD CONSTRAINT fk_target_inst_ds + FOREIGN KEY (installed_distribution_set) + REFERENCES sp_distribution_set (id); ALTER TABLE sp_target_info DROP FOREIGN KEY fk_targ_stat_targ; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_1__target_filter_query_UQ___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_1__target_filter_query_UQ___MYSQL.sql index f494313a8..fc1f615ba 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_1__target_filter_query_UQ___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_1__target_filter_query_UQ___MYSQL.sql @@ -1,2 +1,2 @@ - alter table sp_target_filter_query - add constraint uk_tenant_custom_filter_name unique (name, tenant); +alter table sp_target_filter_query + add constraint uk_tenant_custom_filter_name unique (name, tenant); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_3__add_module_md_targetvis__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_3__add_module_md_targetvis__MYSQL.sql index 4165f7ed1..fba01b8e3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_3__add_module_md_targetvis__MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_3__add_module_md_targetvis__MYSQL.sql @@ -1 +1,2 @@ -ALTER TABLE sp_sw_metadata ADD COLUMN target_visible bit; \ No newline at end of file +ALTER TABLE sp_sw_metadata + ADD COLUMN target_visible bit; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_0__action_performance___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_0__action_performance___MYSQL.sql index 1dff4e13a..05ba3cf12 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_0__action_performance___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_0__action_performance___MYSQL.sql @@ -1,25 +1,34 @@ -ALTER TABLE sp_action ADD COLUMN action_type_new integer not null; -UPDATE sp_action SET action_type_new = -CASE WHEN (action_type = 'SOFT') THEN 1 - WHEN (action_type = 'TIMEFORCED') THEN 2 - ELSE 0 END; +ALTER TABLE sp_action + ADD COLUMN action_type_new integer not null; +UPDATE sp_action +SET action_type_new = + CASE + WHEN (action_type = 'SOFT') THEN 1 + WHEN (action_type = 'TIMEFORCED') THEN 2 + ELSE 0 END; ALTER TABLE sp_action DROP COLUMN action_type; ALTER TABLE sp_action CHANGE COLUMN action_type_new action_type integer; -ALTER TABLE sp_rollout ADD COLUMN action_type_new integer not null; -UPDATE sp_rollout SET action_type_new = -CASE WHEN (action_type = 'SOFT') THEN 1 - WHEN (action_type = 'TIMEFORCED') THEN 2 - ELSE 0 END; +ALTER TABLE sp_rollout + ADD COLUMN action_type_new integer not null; +UPDATE sp_rollout +SET action_type_new = + CASE + WHEN (action_type = 'SOFT') THEN 1 + WHEN (action_type = 'TIMEFORCED') THEN 2 + ELSE 0 END; ALTER TABLE sp_rollout DROP COLUMN action_type; ALTER TABLE sp_rollout CHANGE COLUMN action_type_new action_type integer; -ALTER TABLE sp_target ADD COLUMN update_status_new integer not null; -UPDATE sp_target SET update_status_new = -CASE WHEN (update_status = 'IN_SYNC') THEN 1 - WHEN (update_status = 'PENDING') THEN 2 - WHEN (update_status = 'ERROR') THEN 3 - WHEN (update_status = 'REGISTERED') THEN 4 - ELSE 0 END; +ALTER TABLE sp_target + ADD COLUMN update_status_new integer not null; +UPDATE sp_target +SET update_status_new = + CASE + WHEN (update_status = 'IN_SYNC') THEN 1 + WHEN (update_status = 'PENDING') THEN 2 + WHEN (update_status = 'ERROR') THEN 3 + WHEN (update_status = 'REGISTERED') THEN 4 + ELSE 0 END; ALTER TABLE sp_target DROP COLUMN update_status; ALTER TABLE sp_target CHANGE COLUMN update_status_new update_status integer; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_10__change_length_of_target_attributes_key___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_10__change_length_of_target_attributes_key___MYSQL.sql index aeec222c2..37fd46b20 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_10__change_length_of_target_attributes_key___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_10__change_length_of_target_attributes_key___MYSQL.sql @@ -1 +1 @@ -ALTER TABLE sp_target_attributes MODIFY attribute_key VARCHAR(128); \ No newline at end of file +ALTER TABLE sp_target_attributes MODIFY attribute_key VARCHAR (128); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_11__add_auto_assign_action_type___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_11__add_auto_assign_action_type___MYSQL.sql index 16cb03ef2..ee00de0e6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_11__add_auto_assign_action_type___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_11__add_auto_assign_action_type___MYSQL.sql @@ -1 +1,2 @@ -ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_action_type integer; \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD COLUMN auto_assign_action_type integer; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_12__change_length_of_controller_id_and_name___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_12__change_length_of_controller_id_and_name___MYSQL.sql index 32b39dd59..44077c4b2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_12__change_length_of_controller_id_and_name___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_12__change_length_of_controller_id_and_name___MYSQL.sql @@ -1,13 +1,13 @@ -ALTER TABLE sp_distribution_set MODIFY name VARCHAR(128); -ALTER TABLE sp_distribution_set_type MODIFY name VARCHAR(128); -ALTER TABLE sp_distributionset_tag MODIFY name VARCHAR(128); -ALTER TABLE sp_base_software_module MODIFY name VARCHAR(128); -ALTER TABLE sp_rollout MODIFY name VARCHAR(128); -ALTER TABLE sp_rolloutgroup MODIFY name VARCHAR(128); -ALTER TABLE sp_software_module_type MODIFY name VARCHAR(128); -ALTER TABLE sp_target MODIFY name VARCHAR(128); -ALTER TABLE sp_target_filter_query MODIFY name VARCHAR(128); -ALTER TABLE sp_target_tag MODIFY name VARCHAR(128); +ALTER TABLE sp_distribution_set MODIFY name VARCHAR (128); +ALTER TABLE sp_distribution_set_type MODIFY name VARCHAR (128); +ALTER TABLE sp_distributionset_tag MODIFY name VARCHAR (128); +ALTER TABLE sp_base_software_module MODIFY name VARCHAR (128); +ALTER TABLE sp_rollout MODIFY name VARCHAR (128); +ALTER TABLE sp_rolloutgroup MODIFY name VARCHAR (128); +ALTER TABLE sp_software_module_type MODIFY name VARCHAR (128); +ALTER TABLE sp_target MODIFY name VARCHAR (128); +ALTER TABLE sp_target_filter_query MODIFY name VARCHAR (128); +ALTER TABLE sp_target_tag MODIFY name VARCHAR (128); -ALTER TABLE sp_target MODIFY controller_id VARCHAR(256); +ALTER TABLE sp_target MODIFY controller_id VARCHAR (256); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_13__add_action_external_id___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_13__add_action_external_id___MYSQL.sql index 8dbda293f..2556b7d21 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_13__add_action_external_id___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_13__add_action_external_id___MYSQL.sql @@ -1,4 +1,5 @@ -ALTER TABLE sp_action ADD COLUMN external_ref VARCHAR(512); +ALTER TABLE sp_action + ADD COLUMN external_ref VARCHAR(512); CREATE INDEX sp_idx_action_external_ref ON sp_action (external_ref); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_14__add_sha256_hash___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_14__add_sha256_hash___MYSQL.sql index ca7e53fce..bfe56f337 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_14__add_sha256_hash___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_14__add_sha256_hash___MYSQL.sql @@ -1 +1,2 @@ -ALTER TABLE sp_artifact ADD COLUMN sha256_hash CHAR(64); \ No newline at end of file +ALTER TABLE sp_artifact + ADD COLUMN sha256_hash CHAR(64); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_15__add_weight___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_15__add_weight___MYSQL.sql index 9eaad20e1..12db78a80 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_15__add_weight___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_15__add_weight___MYSQL.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_action ADD weight INT; -ALTER TABLE sp_rollout ADD weight INT; -ALTER TABLE sp_target_filter_query ADD auto_assign_weight INT; +ALTER TABLE sp_action + ADD weight INT; +ALTER TABLE sp_rollout + ADD weight INT; +ALTER TABLE sp_target_filter_query + ADD auto_assign_weight INT; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_16__add_action_initiated_by___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_16__add_action_initiated_by___MYSQL.sql index d0b559b61..9461e26a2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_16__add_action_initiated_by___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_16__add_action_initiated_by___MYSQL.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_action ADD COLUMN initiated_by VARCHAR(64) NOT NULL; -ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_initiated_by VARCHAR(64); +ALTER TABLE sp_action + ADD COLUMN initiated_by VARCHAR(64) NOT NULL; +ALTER TABLE sp_target_filter_query + ADD COLUMN auto_assign_initiated_by VARCHAR(64); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_19__add_valid_flag_to_ds___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_19__add_valid_flag_to_ds___MYSQL.sql index 3ab0e7502..352419711 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_19__add_valid_flag_to_ds___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_19__add_valid_flag_to_ds___MYSQL.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN; +ALTER TABLE sp_distribution_set + ADD COLUMN valid BOOLEAN; -UPDATE sp_distribution_set SET valid = 1; \ No newline at end of file +UPDATE sp_distribution_set +SET valid = 1; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_1__missing_non_null___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_1__missing_non_null___MYSQL.sql index deb2ab79d..c540a3eec 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_1__missing_non_null___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_1__missing_non_null___MYSQL.sql @@ -1,4 +1,4 @@ -ALTER TABLE sp_action_status_messages CHANGE COLUMN detail_message detail_message varchar(512) not null; +ALTER TABLE sp_action_status_messages CHANGE COLUMN detail_message detail_message varchar (512) not null; ALTER TABLE sp_action CHANGE COLUMN distribution_set distribution_set bigint not null; ALTER TABLE sp_action CHANGE COLUMN target target bigint not null; ALTER TABLE sp_action CHANGE COLUMN status status integer not null; @@ -8,5 +8,5 @@ ALTER TABLE sp_rollout CHANGE COLUMN distribution_set distribution_set bigint no ALTER TABLE sp_rollout CHANGE COLUMN status status integer not null; ALTER TABLE sp_rolloutgroup CHANGE COLUMN rollout rollout bigint not null; ALTER TABLE sp_rolloutgroup CHANGE COLUMN status status integer not null; -ALTER TABLE sp_artifact CHANGE COLUMN sha1_hash sha1_hash varchar(40) not null; -ALTER TABLE sp_target CHANGE COLUMN controller_id controller_id varchar(64) not null; \ No newline at end of file +ALTER TABLE sp_artifact CHANGE COLUMN sha1_hash sha1_hash varchar (40) not null; +ALTER TABLE sp_target CHANGE COLUMN controller_id controller_id varchar (64) not null; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_20__add_encryption_flag_to_sm___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_20__add_encryption_flag_to_sm___MYSQL.sql index 9249d14a1..5dd518204 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_20__add_encryption_flag_to_sm___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_20__add_encryption_flag_to_sm___MYSQL.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_base_software_module ADD COLUMN encrypted BOOLEAN; +ALTER TABLE sp_base_software_module + ADD COLUMN encrypted BOOLEAN; -UPDATE sp_base_software_module SET encrypted = 0; \ No newline at end of file +UPDATE sp_base_software_module +SET encrypted = 0; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_22__change_target_type_name_length___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_22__change_target_type_name_length___MYSQL.sql index 39c4c5965..152eedc79 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_22__change_target_type_name_length___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_22__change_target_type_name_length___MYSQL.sql @@ -1 +1 @@ -ALTER TABLE sp_target_type MODIFY name VARCHAR(128); \ No newline at end of file +ALTER TABLE sp_target_type MODIFY name VARCHAR (128); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_23__add_action_status_code___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_23__add_action_status_code___MYSQL.sql index b5640ddec..c8573eab7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_23__add_action_status_code___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_23__add_action_status_code___MYSQL.sql @@ -1,2 +1,3 @@ -ALTER TABLE sp_action_status ADD COLUMN code integer; +ALTER TABLE sp_action_status + ADD COLUMN code integer; CREATE INDEX sp_idx_action_status_03 ON sp_action_status (tenant, code); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_24__add_last_action_status_code___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_24__add_last_action_status_code___MYSQL.sql index 03539efb3..253c8a5d4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_24__add_last_action_status_code___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_24__add_last_action_status_code___MYSQL.sql @@ -1 +1,2 @@ -ALTER TABLE sp_action ADD COLUMN last_action_status_code integer; \ No newline at end of file +ALTER TABLE sp_action + ADD COLUMN last_action_status_code integer; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_25__add_confirmation_flag___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_25__add_confirmation_flag___MYSQL.sql index e8a7594c7..c8a38cf00 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_25__add_confirmation_flag___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_25__add_confirmation_flag___MYSQL.sql @@ -1,21 +1,25 @@ -ALTER TABLE sp_rolloutgroup ADD column confirmation_required BOOLEAN; -UPDATE sp_rolloutgroup SET confirmation_required = 0; +ALTER TABLE sp_rolloutgroup + ADD column confirmation_required BOOLEAN; +UPDATE sp_rolloutgroup +SET confirmation_required = 0; -ALTER TABLE sp_target_filter_query ADD column confirmation_required BOOLEAN; -UPDATE sp_target_filter_query SET confirmation_required = 0; +ALTER TABLE sp_target_filter_query + ADD column confirmation_required BOOLEAN; +UPDATE sp_target_filter_query +SET confirmation_required = 0; create table sp_target_conf_status ( - id bigint not null auto_increment, - target_id bigint not null, - initiator varchar(64), - remark varchar(512), - created_at bigint, - created_by varchar(64), - last_modified_at bigint, - last_modified_by varchar(64), - optlock_revision bigint, - tenant varchar(40) not null, + id bigint not null auto_increment, + target_id bigint not null, + initiator varchar(64), + remark varchar(512), + created_at bigint, + created_by varchar(64), + last_modified_at bigint, + last_modified_by varchar(64), + optlock_revision bigint, + tenant varchar(40) not null, primary key (id) ); ALTER TABLE sp_target_conf_status diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_26__add_access_control_context___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_26__add_access_control_context___MYSQL.sql index ccf16963e..fb06922c7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_26__add_access_control_context___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_26__add_access_control_context___MYSQL.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_target_filter_query ADD COLUMN access_control_context VARCHAR(4096); -ALTER TABLE sp_rollout ADD COLUMN access_control_context VARCHAR(4096); \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD COLUMN access_control_context VARCHAR(4096); +ALTER TABLE sp_rollout + ADD COLUMN access_control_context VARCHAR(4096); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_27__target_type_inherit_type___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_27__target_type_inherit_type___MYSQL.sql index 86e3350b8..2b63926eb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_27__target_type_inherit_type___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_27__target_type_inherit_type___MYSQL.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_target_type ADD COLUMN type_key VARCHAR (64) NOT NULL DEFAULT ('_'); -UPDATE sp_target_type SET type_key = name; -ALTER TABLE sp_target_type ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file +ALTER TABLE sp_target_type + ADD COLUMN type_key VARCHAR(64) NOT NULL DEFAULT ('_'); +UPDATE sp_target_type +SET type_key = name; +ALTER TABLE sp_target_type + ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_28__add_dynamic_rollout___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_28__add_dynamic_rollout___MYSQL.sql index 030727a57..6b6e3c2e2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_28__add_dynamic_rollout___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_28__add_dynamic_rollout___MYSQL.sql @@ -1,9 +1,17 @@ -ALTER TABLE sp_rollout ADD COLUMN is_dynamic BOOLEAN; -ALTER TABLE sp_rolloutgroup ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; +ALTER TABLE sp_rollout + ADD COLUMN is_dynamic BOOLEAN; +ALTER TABLE sp_rolloutgroup + ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; -UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; +UPDATE sp_rollout +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_action +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_target_filter_query +SET auto_assign_weight = 1000 +WHERE auto_assign_weight IS NULL; ALTER TABLE sp_rollout MODIFY COLUMN weight INT NOT NULL; ALTER TABLE sp_action MODIFY COLUMN weight INT NOT NULL; ALTER TABLE sp_target_filter_query MODIFY COLUMN auto_assign_weight INT NOT NULL; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_29__add_ds_sm_locked___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_29__add_ds_sm_locked___MYSQL.sql index c5c0de6fb..831528f40 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_29__add_ds_sm_locked___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_29__add_ds_sm_locked___MYSQL.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_base_software_module ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; -ALTER TABLE sp_distribution_set ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file +ALTER TABLE sp_base_software_module + ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; +ALTER TABLE sp_distribution_set + ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_4__add_maintenance_window___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_4__add_maintenance_window___MYSQL.sql index 6c546cede..9c817454f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_4__add_maintenance_window___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_4__add_maintenance_window___MYSQL.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_action ADD column maintenance_cron_schedule VARCHAR(40); -ALTER TABLE sp_action ADD column maintenance_duration VARCHAR(40); -ALTER TABLE sp_action ADD column maintenance_time_zone VARCHAR(40); +ALTER TABLE sp_action + ADD column maintenance_cron_schedule VARCHAR(40); +ALTER TABLE sp_action + ADD column maintenance_duration VARCHAR(40); +ALTER TABLE sp_action + ADD column maintenance_time_zone VARCHAR(40); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_6__add_index___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_6__add_index___MYSQL.sql index d7d7d6cc7..9fdbca2f8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_6__add_index___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_6__add_index___MYSQL.sql @@ -1,2 +1,2 @@ -CREATE INDEX sp_idx_target_tag_01 ON sp_target_tag (tenant, name); +CREATE INDEX sp_idx_target_tag_01 ON sp_target_tag (tenant, name); CREATE INDEX sp_idx_distribution_set_tag_01 ON sp_distributionset_tag (tenant, name); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_7__add_rollout_approval_fields___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_7__add_rollout_approval_fields___MYSQL.sql index 8438d909e..3e8138835 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_7__add_rollout_approval_fields___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_7__add_rollout_approval_fields___MYSQL.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_rollout ADD column approval_decided_by varchar(40); -ALTER TABLE sp_rollout ADD column approval_remark varchar(255); \ No newline at end of file +ALTER TABLE sp_rollout + ADD column approval_decided_by varchar(40); +ALTER TABLE sp_rollout + ADD column approval_remark varchar(255); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_8__change_length_of_created_last_modified_by___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_8__change_length_of_created_last_modified_by___MYSQL.sql index 283fdf2c9..5093f8854 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_8__change_length_of_created_last_modified_by___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_8__change_length_of_created_last_modified_by___MYSQL.sql @@ -1,29 +1,29 @@ -ALTER TABLE sp_action MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_action MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_action_status MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_action_status MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_artifact MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_artifact MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_base_software_module MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_base_software_module MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_distributionset_tag MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_distributionset_tag MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_distribution_set MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_distribution_set MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_distribution_set_type MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_distribution_set_type MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_rollout MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64), MODIFY approval_decided_by VARCHAR(64); +ALTER TABLE sp_rollout MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64), MODIFY approval_decided_by VARCHAR (64); -ALTER TABLE sp_rolloutgroup MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_rolloutgroup MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_software_module_type MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_software_module_type MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_target MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_target MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_target_filter_query MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_target_filter_query MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_target_tag MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_target_tag MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_tenant MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); +ALTER TABLE sp_tenant MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); -ALTER TABLE sp_tenant_configuration MODIFY created_by VARCHAR(64), MODIFY last_modified_by VARCHAR(64); \ No newline at end of file +ALTER TABLE sp_tenant_configuration MODIFY created_by VARCHAR (64), MODIFY last_modified_by VARCHAR (64); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_9__add_target_metadata___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_9__add_target_metadata___MYSQL.sql index 3b1be5e4b..8e17215ce 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_9__add_target_metadata___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_9__add_target_metadata___MYSQL.sql @@ -1,12 +1,13 @@ -create table sp_target_metadata ( - meta_key varchar(128) not null, - meta_value varchar(4000), - target_id bigint not null, - primary key (target_id, meta_key) +create table sp_target_metadata +( + meta_key varchar(128) not null, + meta_value varchar(4000), + target_id bigint not null, + primary key (target_id, meta_key) ); - -alter table sp_target_metadata - add constraint fk_metadata_target - foreign key (target_id) - references sp_target (id) - on delete cascade; \ No newline at end of file + +alter table sp_target_metadata + add constraint fk_metadata_target + foreign key (target_id) + references sp_target (id) + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_2_0__update_target_info_for_message___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_2_0__update_target_info_for_message___MYSQL.sql index 84f37aed8..ac2792156 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_2_0__update_target_info_for_message___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_2_0__update_target_info_for_message___MYSQL.sql @@ -1,8 +1,8 @@ DROP INDEX sp_idx_target_info_01 ON sp_target_info; ALTER TABLE sp_target_info -CHANGE ip_address address VARCHAR(512); + CHANGE ip_address address VARCHAR (512); UPDATE sp_target_info t1, sp_target_info t2 -SET t1.address = CONCAT('http://',t2.address) +SET t1.address = CONCAT('http://', t2.address) WHERE t1.target_id = t2.target_id AND t2.address is not null \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_4_0__cascade_delete___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_4_0__cascade_delete___MYSQL.sql index a96f76dcb..f7bf3ad8b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_4_0__cascade_delete___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_4_0__cascade_delete___MYSQL.sql @@ -1,73 +1,73 @@ alter table sp_target_info drop FOREIGN KEY fk_targ_stat_targ; -alter table sp_target_info - add constraint fk_targ_stat_targ - foreign key (target_id) - references sp_target (id) - on delete cascade; +alter table sp_target_info + add constraint fk_targ_stat_targ + foreign key (target_id) + references sp_target (id) + on delete cascade; alter table sp_action drop FOREIGN KEY fk_targ_act_hist_targ; alter table sp_action drop index fk_targ_act_hist_targ; -alter table sp_action - add constraint fk_targ_act_hist_targ - foreign key (target) - references sp_target (id) - on delete cascade; +alter table sp_action + add constraint fk_targ_act_hist_targ + foreign key (target) + references sp_target (id) + on delete cascade; alter table sp_action_status drop FOREIGN KEY fk_act_stat_action; -alter table sp_action_status drop index fk_act_stat_action; -alter table sp_action_status - add constraint fk_act_stat_action - foreign key (action) - references sp_action (id) - on delete cascade; +alter table sp_action_status drop index fk_act_stat_action; +alter table sp_action_status + add constraint fk_act_stat_action + foreign key (action) + references sp_action (id) + on delete cascade; alter table sp_sw_metadata drop FOREIGN KEY fk_metadata_sw; alter table sp_sw_metadata drop index fk_metadata_sw; -alter table sp_sw_metadata - add constraint fk_metadata_sw - foreign key (sw_id) - references sp_base_software_module (id) - on delete cascade; +alter table sp_sw_metadata + add constraint fk_metadata_sw + foreign key (sw_id) + references sp_base_software_module (id) + on delete cascade; -alter table sp_ds_metadata drop FOREIGN KEY fk_metadata_ds; -alter table sp_ds_metadata - add constraint fk_metadata_ds - foreign key (ds_id) - references sp_distribution_set (id) - on delete cascade; +alter table sp_ds_metadata drop FOREIGN KEY fk_metadata_ds; +alter table sp_ds_metadata + add constraint fk_metadata_ds + foreign key (ds_id) + references sp_distribution_set (id) + on delete cascade; -alter table sp_action_status_messages drop FOREIGN KEY fk_stat_msg_act_stat; -alter table sp_action_status_messages - add constraint fk_stat_msg_act_stat - foreign key (action_status_id) - references sp_action_status (id) - on delete cascade; +alter table sp_action_status_messages drop FOREIGN KEY fk_stat_msg_act_stat; +alter table sp_action_status_messages + add constraint fk_stat_msg_act_stat + foreign key (action_status_id) + references sp_action_status (id) + on delete cascade; alter table sp_ds_dstag drop FOREIGN KEY fk_ds_dstag_tag; alter table sp_ds_dstag drop index fk_ds_dstag_tag; -alter table sp_ds_dstag - add constraint fk_ds_dstag_tag - foreign key (TAG) - references sp_distributionset_tag (id) - on delete cascade; +alter table sp_ds_dstag + add constraint fk_ds_dstag_tag + foreign key (TAG) + references sp_distributionset_tag (id) + on delete cascade; alter table sp_ds_dstag drop FOREIGN KEY fk_ds_dstag_ds; -alter table sp_ds_dstag - add constraint fk_ds_dstag_ds - foreign key (ds) - references sp_distribution_set (id) - on delete cascade; +alter table sp_ds_dstag + add constraint fk_ds_dstag_ds + foreign key (ds) + references sp_distribution_set (id) + on delete cascade; alter table sp_target_target_tag drop FOREIGN KEY fk_targ_targtag_tag; -alter table sp_target_target_tag - add constraint fk_targ_targtag_tag - foreign key (tag) - references sp_target_tag (id) - on delete cascade; +alter table sp_target_target_tag + add constraint fk_targ_targtag_tag + foreign key (tag) + references sp_target_tag (id) + on delete cascade; alter table sp_target_target_tag drop FOREIGN KEY fk_targ_targtag_target; -alter table sp_target_target_tag - add constraint fk_targ_targtag_target - foreign key (target) - references sp_target (id) - on delete cascade; \ No newline at end of file +alter table sp_target_target_tag + add constraint fk_targ_targtag_target + foreign key (target) + references sp_target (id) + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_4_1__cascade_delete___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_4_1__cascade_delete___MYSQL.sql index e1ba9ec74..d507739ec 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_4_1__cascade_delete___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_4_1__cascade_delete___MYSQL.sql @@ -1,6 +1,6 @@ alter table sp_target_attributes drop FOREIGN KEY fk_targ_attrib_target; -alter table sp_target_attributes - add constraint fk_targ_attrib_target - foreign key (target_id) - references sp_target_info (target_id) - on delete cascade; \ No newline at end of file +alter table sp_target_attributes + add constraint fk_targ_attrib_target + foreign key (target_id) + references sp_target_info (target_id) + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_5_0__target_filter_query___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_5_0__target_filter_query___MYSQL.sql index 590329345..ef41368f6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_5_0__target_filter_query___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_5_0__target_filter_query___MYSQL.sql @@ -1,15 +1,16 @@ - create table sp_target_filter_query ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - name varchar(64) not null, - query varchar(1024) not null, - primary key (id) - ); - - - create index sp_idx_target_filter_query_01 on sp_target_filter_query (tenant, name); +create table sp_target_filter_query +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + name varchar(64) not null, + query varchar(1024) not null, + primary key (id) +); + + +create index sp_idx_target_filter_query_01 on sp_target_filter_query (tenant, name); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_6_0__rollout_management___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_6_0__rollout_management___MYSQL.sql index 4cd4c7ea4..5c5122939 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_6_0__rollout_management___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_6_0__rollout_management___MYSQL.sql @@ -1,103 +1,108 @@ - create table sp_rolloutgroup ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - error_condition integer, - error_condition_exp varchar(512), - error_action integer, - error_action_exp varchar(512), - success_condition integer not null, - success_condition_exp varchar(512) not null, - success_action integer not null, - success_action_exp varchar(512), - status integer, - parent_id bigint, - rollout bigint, - total_targets bigint, - primary key (id) - ); - - create table sp_rollout ( - id bigint not null auto_increment, - created_at bigint, - created_by varchar(40), - last_modified_at bigint, - last_modified_by varchar(40), - optlock_revision bigint, - tenant varchar(40) not null, - description varchar(512), - name varchar(64) not null, - last_check bigint, - group_theshold float, - status integer, - distribution_set bigint, - target_filter varchar(1024), - action_type varchar(255) not null, - forced_time bigint, - total_targets bigint, - primary key (id) - ); - - create table sp_rollouttargetgroup ( - target_Id bigint not null, - rolloutGroup_Id bigint not null, - primary key (rolloutGroup_Id, target_Id) - ); - - create index sp_idx_rollout_01 on sp_rollout (tenant, name); - - create index sp_idx_rolloutgroup_01 on sp_rolloutgroup (tenant, name); - - ALTER TABLE sp_action ADD COLUMN rollout bigint; - ALTER TABLE sp_action ADD COLUMN rolloutgroup bigint; - - alter table sp_rollout - add constraint uk_rollout unique (name, tenant); - - alter table sp_rolloutgroup - add constraint uk_rolloutgroup unique (name, rollout, tenant); - - alter table sp_action - add constraint fk_action_rollout - foreign key (rollout) - references sp_rollout (id); - - alter table sp_action - add constraint fk_action_rolloutgroup - foreign key (rolloutgroup) - references sp_rolloutgroup (id); - - alter table sp_rollout - add constraint fk_rollout_ds - foreign key (distribution_set) - references sp_distribution_set (id); +create table sp_rolloutgroup +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + error_condition integer, + error_condition_exp varchar(512), + error_action integer, + error_action_exp varchar(512), + success_condition integer not null, + success_condition_exp varchar(512) not null, + success_action integer not null, + success_action_exp varchar(512), + status integer, + parent_id bigint, + rollout bigint, + total_targets bigint, + primary key (id) +); - alter table sp_rolloutgroup - add constraint fk_rolloutgroup_rollout - foreign key (rollout) - references sp_rollout (id) - on delete cascade; - - alter table sp_rolloutgroup - add constraint fk_rolloutgroup_rolloutgroup - foreign key (parent_id) - references sp_rolloutgroup (id) - on delete cascade; - - alter table sp_rollouttargetgroup - add constraint fk_rollouttargetgroup_target - foreign key (target_id) - references sp_target (id) - on delete cascade; +create table sp_rollout +( + id bigint not null auto_increment, + created_at bigint, + created_by varchar(40), + last_modified_at bigint, + last_modified_by varchar(40), + optlock_revision bigint, + tenant varchar(40) not null, + description varchar(512), + name varchar(64) not null, + last_check bigint, + group_theshold float, + status integer, + distribution_set bigint, + target_filter varchar(1024), + action_type varchar(255) not null, + forced_time bigint, + total_targets bigint, + primary key (id) +); - alter table sp_rollouttargetgroup - add constraint fk_rollouttargetgroup_rolloutgroup - foreign key (rolloutgroup_id) - references sp_rolloutgroup (id) - on delete cascade; \ No newline at end of file +create table sp_rollouttargetgroup +( + target_Id bigint not null, + rolloutGroup_Id bigint not null, + primary key (rolloutGroup_Id, target_Id) +); + +create index sp_idx_rollout_01 on sp_rollout (tenant, name); + +create index sp_idx_rolloutgroup_01 on sp_rolloutgroup (tenant, name); + +ALTER TABLE sp_action + ADD COLUMN rollout bigint; +ALTER TABLE sp_action + ADD COLUMN rolloutgroup bigint; + +alter table sp_rollout + add constraint uk_rollout unique (name, tenant); + +alter table sp_rolloutgroup + add constraint uk_rolloutgroup unique (name, rollout, tenant); + +alter table sp_action + add constraint fk_action_rollout + foreign key (rollout) + references sp_rollout (id); + +alter table sp_action + add constraint fk_action_rolloutgroup + foreign key (rolloutgroup) + references sp_rolloutgroup (id); + +alter table sp_rollout + add constraint fk_rollout_ds + foreign key (distribution_set) + references sp_distribution_set (id); + +alter table sp_rolloutgroup + add constraint fk_rolloutgroup_rollout + foreign key (rollout) + references sp_rollout (id) + on delete cascade; + +alter table sp_rolloutgroup + add constraint fk_rolloutgroup_rolloutgroup + foreign key (parent_id) + references sp_rolloutgroup (id) + on delete cascade; + +alter table sp_rollouttargetgroup + add constraint fk_rollouttargetgroup_target + foreign key (target_id) + references sp_target (id) + on delete cascade; + +alter table sp_rollouttargetgroup + add constraint fk_rollouttargetgroup_rolloutgroup + foreign key (rolloutgroup_id) + references sp_rolloutgroup (id) + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_7_0__swmType_maxAssignment_greater_0__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_7_0__swmType_maxAssignment_greater_0__MYSQL.sql index f79c9375c..75766d9dc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_7_0__swmType_maxAssignment_greater_0__MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_7_0__swmType_maxAssignment_greater_0__MYSQL.sql @@ -1 +1,3 @@ -Update sp_software_module_type set max_ds_assignments = 1 where max_ds_assignments < 1; \ No newline at end of file +Update sp_software_module_type +set max_ds_assignments = 1 +where max_ds_assignments < 1; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_7_1__reduce_length_enums___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_7_1__reduce_length_enums___MYSQL.sql index ae9eef28e..4a342472e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_7_1__reduce_length_enums___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_7_1__reduce_length_enums___MYSQL.sql @@ -1,5 +1,5 @@ -ALTER TABLE sp_target_info MODIFY update_status VARCHAR(16) not null; -ALTER TABLE sp_action MODIFY action_type VARCHAR(16) not null; -ALTER TABLE sp_rollout MODIFY action_type VARCHAR(16) not null; -ALTER TABLE sp_tenant_configuration MODIFY conf_key VARCHAR(128) not null; -ALTER TABLE sp_tenant_configuration MODIFY conf_value VARCHAR(512) not null; \ No newline at end of file +ALTER TABLE sp_target_info MODIFY update_status VARCHAR (16) not null; +ALTER TABLE sp_action MODIFY action_type VARCHAR (16) not null; +ALTER TABLE sp_rollout MODIFY action_type VARCHAR (16) not null; +ALTER TABLE sp_tenant_configuration MODIFY conf_key VARCHAR (128) not null; +ALTER TABLE sp_tenant_configuration MODIFY conf_value VARCHAR (512) not null; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_8_0__auto_assign_ds_filter__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_8_0__auto_assign_ds_filter__MYSQL.sql index e56a6d242..d6ea40ccc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_8_0__auto_assign_ds_filter__MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_8_0__auto_assign_ds_filter__MYSQL.sql @@ -1,8 +1,8 @@ ALTER TABLE sp_target_filter_query - ADD COLUMN auto_assign_distribution_set BIGINT; + ADD COLUMN auto_assign_distribution_set BIGINT; ALTER TABLE sp_target_filter_query - ADD CONSTRAINT fk_filter_auto_assign_ds -FOREIGN KEY (auto_assign_distribution_set) -REFERENCES sp_distribution_set (id) -ON DELETE SET NULL; + ADD CONSTRAINT fk_filter_auto_assign_ds + FOREIGN KEY (auto_assign_distribution_set) + REFERENCES sp_distribution_set (id) + ON DELETE SET NULL; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_8_1__cascade_delete___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_8_1__cascade_delete___MYSQL.sql index 9cc12b375..5c11fb7ab 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_8_1__cascade_delete___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_8_1__cascade_delete___MYSQL.sql @@ -1,27 +1,27 @@ alter table sp_ds_module drop FOREIGN KEY fk_ds_module_ds; -alter table sp_ds_module - add constraint fk_ds_module_ds - foreign key (ds_id) - references sp_distribution_set (id) - on delete cascade; +alter table sp_ds_module + add constraint fk_ds_module_ds + foreign key (ds_id) + references sp_distribution_set (id) + on delete cascade; alter table sp_ds_module drop FOREIGN KEY fk_ds_module_module; -alter table sp_ds_module - add constraint fk_ds_module_module - foreign key (module_id) - references sp_base_software_module (id) - on delete cascade; +alter table sp_ds_module + add constraint fk_ds_module_module + foreign key (module_id) + references sp_base_software_module (id) + on delete cascade; alter table sp_external_artifact drop FOREIGN KEY fk_external_assigned_sm; -alter table sp_external_artifact - add constraint fk_external_assigned_sm - foreign key (software_module) - references sp_base_software_module (id) - on delete cascade; +alter table sp_external_artifact + add constraint fk_external_assigned_sm + foreign key (software_module) + references sp_base_software_module (id) + on delete cascade; alter table sp_artifact drop FOREIGN KEY fk_assigned_sm; -alter table sp_artifact - add constraint fk_assigned_sm - foreign key (software_module) - references sp_base_software_module (id) - on delete cascade; \ No newline at end of file +alter table sp_artifact + add constraint fk_assigned_sm + foreign key (software_module) + references sp_base_software_module (id) + on delete cascade; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_9_0__add_rollout_groups_created___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_9_0__add_rollout_groups_created___MYSQL.sql index 64518f762..bbcd2d6af 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_9_0__add_rollout_groups_created___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_9_0__add_rollout_groups_created___MYSQL.sql @@ -1,2 +1,3 @@ - ALTER TABLE sp_rollout ADD column rollout_groups_created BIGINT; +ALTER TABLE sp_rollout + ADD column rollout_groups_created BIGINT; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_15__baseline___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_15__baseline___POSTGRESQL.sql index ba8b988d6..ab260ed75 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_15__baseline___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_15__baseline___POSTGRESQL.sql @@ -77,796 +77,821 @@ NO CYCLE; -- ------------ Write CREATE-TABLE-stage scripts ----------- -CREATE TABLE sp_action( - id BIGINT NOT NULL DEFAULT nextval('sp_action_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - active BOOLEAN, - forced_time BIGINT, - status INTEGER NOT NULL, - distribution_set BIGINT NOT NULL, - target BIGINT NOT NULL, - rollout BIGINT, - rolloutgroup BIGINT, - action_type INTEGER NOT NULL, +CREATE TABLE sp_action +( + id BIGINT NOT NULL DEFAULT nextval('sp_action_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + active BOOLEAN, + forced_time BIGINT, + status INTEGER NOT NULL, + distribution_set BIGINT NOT NULL, + target BIGINT NOT NULL, + rollout BIGINT, + rolloutgroup BIGINT, + action_type INTEGER NOT NULL, maintenance_cron_schedule VARCHAR(40), - maintenance_duration VARCHAR(40), - maintenance_time_zone VARCHAR(40), - external_ref VARCHAR(512), - weight INTEGER + maintenance_duration VARCHAR(40), + maintenance_time_zone VARCHAR(40), + external_ref VARCHAR(512), + weight INTEGER ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_action_status( - id BIGINT NOT NULL DEFAULT nextval('sp_action_status_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - target_occurred_at BIGINT NOT NULL, - status INTEGER NOT NULL, - action BIGINT NOT NULL +CREATE TABLE sp_action_status +( + id BIGINT NOT NULL DEFAULT nextval('sp_action_status_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + target_occurred_at BIGINT NOT NULL, + status INTEGER NOT NULL, + action BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_action_status_messages( - action_status_id BIGINT NOT NULL, - detail_message VARCHAR(512) NOT NULL +CREATE TABLE sp_action_status_messages +( + action_status_id BIGINT NOT NULL, + detail_message VARCHAR(512) NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_artifact( - id BIGINT NOT NULL DEFAULT nextval('sp_artifact_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - md5_hash VARCHAR(32), - file_size BIGINT, +CREATE TABLE sp_artifact +( + id BIGINT NOT NULL DEFAULT nextval('sp_artifact_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + md5_hash VARCHAR(32), + file_size BIGINT, provided_file_name VARCHAR(256), - sha1_hash VARCHAR(40) NOT NULL, - software_module BIGINT NOT NULL, - sha256_hash CHAR(64) + sha1_hash VARCHAR(40) NOT NULL, + software_module BIGINT NOT NULL, + sha256_hash CHAR(64) ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_base_software_module( - id BIGINT NOT NULL DEFAULT nextval('sp_base_software_module_seq'), - created_at BIGINT, - created_by VARCHAR(64), +CREATE TABLE sp_base_software_module +( + id BIGINT NOT NULL DEFAULT nextval('sp_base_software_module_seq'), + created_at BIGINT, + created_by VARCHAR(64), last_modified_at BIGINT, last_modified_by VARCHAR(64), optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - version VARCHAR(64) NOT NULL, - deleted BOOLEAN, - vendor VARCHAR(256), - module_type BIGINT NOT NULL + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + version VARCHAR(64) NOT NULL, + deleted BOOLEAN, + vendor VARCHAR(256), + module_type BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_distribution_set( - id BIGINT NOT NULL DEFAULT nextval('sp_distribution_set_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - version VARCHAR(64) NOT NULL, - complete BOOLEAN, - deleted BOOLEAN, +CREATE TABLE sp_distribution_set +( + id BIGINT NOT NULL DEFAULT nextval('sp_distribution_set_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + version VARCHAR(64) NOT NULL, + complete BOOLEAN, + deleted BOOLEAN, required_migration_step BOOLEAN, - ds_id BIGINT NOT NULL + ds_id BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_distribution_set_type( - id BIGINT NOT NULL DEFAULT nextval('sp_distribution_set_type_seq'), - created_at BIGINT, - created_by VARCHAR(64), +CREATE TABLE sp_distribution_set_type +( + id BIGINT NOT NULL DEFAULT nextval('sp_distribution_set_type_seq'), + created_at BIGINT, + created_by VARCHAR(64), last_modified_at BIGINT, last_modified_by VARCHAR(64), optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - colour VARCHAR(16), - deleted BOOLEAN, - type_key VARCHAR(64) NOT NULL + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + colour VARCHAR(16), + deleted BOOLEAN, + type_key VARCHAR(64) NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_distributionset_tag( - id BIGINT NOT NULL DEFAULT nextval('sp_distributionset_tag_seq'), - created_at BIGINT, - created_by VARCHAR(64), +CREATE TABLE sp_distributionset_tag +( + id BIGINT NOT NULL DEFAULT nextval('sp_distributionset_tag_seq'), + created_at BIGINT, + created_by VARCHAR(64), last_modified_at BIGINT, last_modified_by VARCHAR(64), optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - colour VARCHAR(16) + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + colour VARCHAR(16) ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_ds_dstag( - ds BIGINT NOT NULL, +CREATE TABLE sp_ds_dstag +( + ds BIGINT NOT NULL, tag BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_ds_metadata( - meta_key VARCHAR(128) NOT NULL, +CREATE TABLE sp_ds_metadata +( + meta_key VARCHAR(128) NOT NULL, meta_value VARCHAR(4000), - ds_id BIGINT NOT NULL + ds_id BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_ds_module( - ds_id BIGINT NOT NULL, +CREATE TABLE sp_ds_module +( + ds_id BIGINT NOT NULL, module_id BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_ds_type_element( - mandatory BOOLEAN, +CREATE TABLE sp_ds_type_element +( + mandatory BOOLEAN, distribution_set_type BIGINT NOT NULL, - software_module_type BIGINT NOT NULL + software_module_type BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_rollout( - id BIGINT NOT NULL DEFAULT nextval('sp_rollout_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - last_check BIGINT, - group_theshold REAL, - status INTEGER NOT NULL, - distribution_set BIGINT NOT NULL, - target_filter VARCHAR(1024), - forced_time BIGINT, - total_targets BIGINT, +CREATE TABLE sp_rollout +( + id BIGINT NOT NULL DEFAULT nextval('sp_rollout_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + last_check BIGINT, + group_theshold REAL, + status INTEGER NOT NULL, + distribution_set BIGINT NOT NULL, + target_filter VARCHAR(1024), + forced_time BIGINT, + total_targets BIGINT, rollout_groups_created BIGINT, - start_at BIGINT, - deleted BOOLEAN, - action_type INTEGER NOT NULL, - approval_decided_by VARCHAR(64), - approval_remark VARCHAR(255), - weight INTEGER + start_at BIGINT, + deleted BOOLEAN, + action_type INTEGER NOT NULL, + approval_decided_by VARCHAR(64), + approval_remark VARCHAR(255), + weight INTEGER ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_rolloutgroup( - id BIGINT NOT NULL DEFAULT nextval('sp_rolloutgroup_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - error_condition INTEGER, - error_condition_exp VARCHAR(512), - error_action INTEGER, - error_action_exp VARCHAR(512), - success_condition INTEGER NOT NULL, +CREATE TABLE sp_rolloutgroup +( + id BIGINT NOT NULL DEFAULT nextval('sp_rolloutgroup_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + error_condition INTEGER, + error_condition_exp VARCHAR(512), + error_action INTEGER, + error_action_exp VARCHAR(512), + success_condition INTEGER NOT NULL, success_condition_exp VARCHAR(512) NOT NULL, - success_action INTEGER NOT NULL, - success_action_exp VARCHAR(512), - status INTEGER NOT NULL, - parent_id BIGINT, - rollout BIGINT NOT NULL, - total_targets BIGINT, - target_percentage REAL, - target_filter VARCHAR(1024) + success_action INTEGER NOT NULL, + success_action_exp VARCHAR(512), + status INTEGER NOT NULL, + parent_id BIGINT, + rollout BIGINT NOT NULL, + total_targets BIGINT, + target_percentage REAL, + target_filter VARCHAR(1024) ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_rollouttargetgroup( - target_id BIGINT NOT NULL, +CREATE TABLE sp_rollouttargetgroup +( + target_id BIGINT NOT NULL, rolloutgroup_id BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_software_module_type( - id BIGINT NOT NULL DEFAULT nextval('sp_software_module_type_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - colour VARCHAR(16), - deleted BOOLEAN, - type_key VARCHAR(64) NOT NULL, - max_ds_assignments INTEGER NOT NULL +CREATE TABLE sp_software_module_type +( + id BIGINT NOT NULL DEFAULT nextval('sp_software_module_type_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + colour VARCHAR(16), + deleted BOOLEAN, + type_key VARCHAR(64) NOT NULL, + max_ds_assignments INTEGER NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_sw_metadata( - meta_key VARCHAR(128) NOT NULL, - meta_value VARCHAR(4000), - sw_id BIGINT NOT NULL, +CREATE TABLE sp_sw_metadata +( + meta_key VARCHAR(128) NOT NULL, + meta_value VARCHAR(4000), + sw_id BIGINT NOT NULL, target_visible BOOLEAN ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_target( - id BIGINT NOT NULL DEFAULT nextval('sp_target_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - controller_id VARCHAR(256), - sec_token VARCHAR(128) NOT NULL, - assigned_distribution_set BIGINT, - install_date BIGINT, - address VARCHAR(512), - last_target_query BIGINT, - request_controller_attributes BOOLEAN NOT NULL, - installed_distribution_set BIGINT, - update_status INTEGER NOT NULL +CREATE TABLE sp_target +( + id BIGINT NOT NULL DEFAULT nextval('sp_target_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + controller_id VARCHAR(256), + sec_token VARCHAR(128) NOT NULL, + assigned_distribution_set BIGINT, + install_date BIGINT, + address VARCHAR(512), + last_target_query BIGINT, + request_controller_attributes BOOLEAN NOT NULL, + installed_distribution_set BIGINT, + update_status INTEGER NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_target_attributes( - target_id BIGINT NOT NULL, +CREATE TABLE sp_target_attributes +( + target_id BIGINT NOT NULL, attribute_value VARCHAR(128), - attribute_key VARCHAR(128) NOT NULL + attribute_key VARCHAR(128) NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_target_filter_query( - id BIGINT NOT NULL DEFAULT nextval('sp_target_filter_query_seq'), - created_at BIGINT, - created_by VARCHAR(64), - last_modified_at BIGINT, - last_modified_by VARCHAR(64), - optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - name VARCHAR(128), - query VARCHAR(1024) NOT NULL, +CREATE TABLE sp_target_filter_query +( + id BIGINT NOT NULL DEFAULT nextval('sp_target_filter_query_seq'), + created_at BIGINT, + created_by VARCHAR(64), + last_modified_at BIGINT, + last_modified_by VARCHAR(64), + optlock_revision BIGINT, + tenant VARCHAR(40) NOT NULL, + name VARCHAR(128), + query VARCHAR(1024) NOT NULL, auto_assign_distribution_set BIGINT, - auto_assign_action_type INTEGER, - auto_assign_weight INTEGER + auto_assign_action_type INTEGER, + auto_assign_weight INTEGER ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_target_metadata( - meta_key VARCHAR(128) NOT NULL, +CREATE TABLE sp_target_metadata +( + meta_key VARCHAR(128) NOT NULL, meta_value VARCHAR(4000), - target_id BIGINT NOT NULL + target_id BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_target_tag( - id BIGINT NOT NULL DEFAULT nextval('sp_target_tag_seq'), - created_at BIGINT, - created_by VARCHAR(64), +CREATE TABLE sp_target_tag +( + id BIGINT NOT NULL DEFAULT nextval('sp_target_tag_seq'), + created_at BIGINT, + created_by VARCHAR(64), last_modified_at BIGINT, last_modified_by VARCHAR(64), optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - description VARCHAR(512), - name VARCHAR(128), - colour VARCHAR(16) + tenant VARCHAR(40) NOT NULL, + description VARCHAR(512), + name VARCHAR(128), + colour VARCHAR(16) ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_target_target_tag( +CREATE TABLE sp_target_target_tag +( target BIGINT NOT NULL, - tag BIGINT NOT NULL + tag BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_tenant( - id BIGINT NOT NULL DEFAULT nextval('sp_tenant_seq'), - created_at BIGINT, - created_by VARCHAR(64), +CREATE TABLE sp_tenant +( + id BIGINT NOT NULL DEFAULT nextval('sp_tenant_seq'), + created_at BIGINT, + created_by VARCHAR(64), last_modified_at BIGINT, last_modified_by VARCHAR(64), optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - default_ds_type BIGINT NOT NULL + tenant VARCHAR(40) NOT NULL, + default_ds_type BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_tenant_configuration( - id BIGINT NOT NULL DEFAULT nextval('sp_tenant_configuration_seq'), - created_at BIGINT, - created_by VARCHAR(64), +CREATE TABLE sp_tenant_configuration +( + id BIGINT NOT NULL DEFAULT nextval('sp_tenant_configuration_seq'), + created_at BIGINT, + created_by VARCHAR(64), last_modified_at BIGINT, last_modified_by VARCHAR(64), optlock_revision BIGINT, - tenant VARCHAR(40) NOT NULL, - conf_key VARCHAR(128) NOT NULL, - conf_value VARCHAR(512) NOT NULL + tenant VARCHAR(40) NOT NULL, + conf_key VARCHAR(128) NOT NULL, + conf_value VARCHAR(512) NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -- ------------ Write CREATE-INDEX-stage scripts ----------- CREATE INDEX sp_idx_action_01_sp_action -ON sp_action -USING BTREE (tenant, distribution_set); + ON sp_action + USING BTREE (tenant, distribution_set); CREATE INDEX sp_idx_action_02_sp_action -ON sp_action -USING BTREE (tenant, target, active); + ON sp_action + USING BTREE (tenant, target, active); CREATE INDEX sp_idx_action_external_ref_sp_action -ON sp_action -USING BTREE (external_ref); + ON sp_action + USING BTREE (external_ref); CREATE INDEX sp_idx_action_prim_sp_action -ON sp_action -USING BTREE (tenant, id); + ON sp_action + USING BTREE (tenant, id); CREATE INDEX sp_idx_action_status_02_sp_action_status -ON sp_action_status -USING BTREE (tenant, action, status); + ON sp_action_status + USING BTREE (tenant, action, status); CREATE INDEX sp_idx_action_status_prim_sp_action_status -ON sp_action_status -USING BTREE (tenant, id); + ON sp_action_status + USING BTREE (tenant, id); CREATE INDEX sp_idx_action_status_msgs_01_sp_action_status_messages -ON sp_action_status_messages -USING BTREE (action_status_id); + ON sp_action_status_messages + USING BTREE (action_status_id); CREATE INDEX sp_idx_artifact_01_sp_artifact -ON sp_artifact -USING BTREE (tenant, software_module); + ON sp_artifact + USING BTREE (tenant, software_module); CREATE INDEX sp_idx_artifact_02_sp_artifact -ON sp_artifact -USING BTREE (tenant, sha1_hash); + ON sp_artifact + USING BTREE (tenant, sha1_hash); CREATE INDEX sp_idx_artifact_prim_sp_artifact -ON sp_artifact -USING BTREE (tenant, id); + ON sp_artifact + USING BTREE (tenant, id); CREATE INDEX sp_idx_base_sw_module_01_sp_base_software_module -ON sp_base_software_module -USING BTREE (tenant, deleted, name, version); + ON sp_base_software_module + USING BTREE (tenant, deleted, name, version); CREATE INDEX sp_idx_base_sw_module_02_sp_base_software_module -ON sp_base_software_module -USING BTREE (tenant, deleted, module_type); + ON sp_base_software_module + USING BTREE (tenant, deleted, module_type); CREATE INDEX sp_idx_base_sw_module_prim_sp_base_software_module -ON sp_base_software_module -USING BTREE (tenant, id); + ON sp_base_software_module + USING BTREE (tenant, id); CREATE INDEX sp_idx_distribution_set_01_sp_distribution_set -ON sp_distribution_set -USING BTREE (tenant, deleted, complete); + ON sp_distribution_set + USING BTREE (tenant, deleted, complete); CREATE INDEX sp_idx_distribution_set_prim_sp_distribution_set -ON sp_distribution_set -USING BTREE (tenant, id); + ON sp_distribution_set + USING BTREE (tenant, id); CREATE INDEX sp_idx_distribution_set_type_01_sp_distribution_set_type -ON sp_distribution_set_type -USING BTREE (tenant, deleted); + ON sp_distribution_set_type + USING BTREE (tenant, deleted); CREATE INDEX sp_idx_distribution_set_type_prim_sp_distribution_set_type -ON sp_distribution_set_type -USING BTREE (tenant, id); + ON sp_distribution_set_type + USING BTREE (tenant, id); CREATE INDEX sp_idx_distribution_set_tag_01_sp_distributionset_tag -ON sp_distributionset_tag -USING BTREE (tenant, name); + ON sp_distributionset_tag + USING BTREE (tenant, name); CREATE INDEX sp_idx_distribution_set_tag_prim_sp_distributionset_tag -ON sp_distributionset_tag -USING BTREE (tenant, id); + ON sp_distributionset_tag + USING BTREE (tenant, id); CREATE INDEX fk_rolloutgroup_rolloutgroup_sp_rolloutgroup -ON sp_rolloutgroup -USING BTREE (parent_id); + ON sp_rolloutgroup + USING BTREE (parent_id); CREATE INDEX sp_idx_software_module_type_01_sp_software_module_type -ON sp_software_module_type -USING BTREE (tenant, deleted); + ON sp_software_module_type + USING BTREE (tenant, deleted); CREATE INDEX sp_idx_software_module_type_prim_sp_software_module_type -ON sp_software_module_type -USING BTREE (tenant, id); + ON sp_software_module_type + USING BTREE (tenant, id); CREATE INDEX sp_idx_target_01_sp_target -ON sp_target -USING BTREE (tenant, name, assigned_distribution_set); + ON sp_target + USING BTREE (tenant, name, assigned_distribution_set); CREATE INDEX sp_idx_target_03_sp_target -ON sp_target -USING BTREE (tenant, controller_id, assigned_distribution_set); + ON sp_target + USING BTREE (tenant, controller_id, assigned_distribution_set); CREATE INDEX sp_idx_target_04_sp_target -ON sp_target -USING BTREE (tenant, created_at); + ON sp_target + USING BTREE (tenant, created_at); CREATE INDEX sp_idx_target_prim_sp_target -ON sp_target -USING BTREE (tenant, id); + ON sp_target + USING BTREE (tenant, id); CREATE INDEX sp_idx_target_tag_01_sp_target_tag -ON sp_target_tag -USING BTREE (tenant, name); + ON sp_target_tag + USING BTREE (tenant, name); CREATE INDEX sp_idx_target_tag_prim_sp_target_tag -ON sp_target_tag -USING BTREE (tenant, id); + ON sp_target_tag + USING BTREE (tenant, id); CREATE INDEX sp_idx_tenant_prim_sp_tenant -ON sp_tenant -USING BTREE (tenant, id); + ON sp_tenant + USING BTREE (tenant, id); -- ------------ Write CREATE-CONSTRAINT-stage scripts ----------- ALTER TABLE sp_action -ADD CONSTRAINT pk_sp_action PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_action PRIMARY KEY (id); ALTER TABLE sp_action_status -ADD CONSTRAINT pk_sp_action_status PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_action_status PRIMARY KEY (id); ALTER TABLE sp_artifact -ADD CONSTRAINT pk_sp_artifact PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_artifact PRIMARY KEY (id); ALTER TABLE sp_base_software_module -ADD CONSTRAINT pk_sp_base_software_module PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_base_software_module PRIMARY KEY (id); ALTER TABLE sp_base_software_module -ADD CONSTRAINT uk_base_sw_mod_sp_base_software_module UNIQUE (module_type, name, version, tenant); + ADD CONSTRAINT uk_base_sw_mod_sp_base_software_module UNIQUE (module_type, name, version, tenant); ALTER TABLE sp_distribution_set -ADD CONSTRAINT pk_sp_distribution_set PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_distribution_set PRIMARY KEY (id); ALTER TABLE sp_distribution_set -ADD CONSTRAINT uk_distrib_set_sp_distribution_set UNIQUE (name, version, tenant); + ADD CONSTRAINT uk_distrib_set_sp_distribution_set UNIQUE (name, version, tenant); ALTER TABLE sp_distribution_set_type -ADD CONSTRAINT pk_sp_distribution_set_type PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_distribution_set_type PRIMARY KEY (id); ALTER TABLE sp_distribution_set_type -ADD CONSTRAINT uk_dst_key_sp_distribution_set_type UNIQUE (type_key, tenant); + ADD CONSTRAINT uk_dst_key_sp_distribution_set_type UNIQUE (type_key, tenant); ALTER TABLE sp_distribution_set_type -ADD CONSTRAINT uk_dst_name_sp_distribution_set_type UNIQUE (name, tenant); + ADD CONSTRAINT uk_dst_name_sp_distribution_set_type UNIQUE (name, tenant); ALTER TABLE sp_distributionset_tag -ADD CONSTRAINT pk_sp_distributionset_tag PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_distributionset_tag PRIMARY KEY (id); ALTER TABLE sp_distributionset_tag -ADD CONSTRAINT uk_ds_tag_sp_distributionset_tag UNIQUE (name, tenant); + ADD CONSTRAINT uk_ds_tag_sp_distributionset_tag UNIQUE (name, tenant); ALTER TABLE sp_ds_dstag -ADD CONSTRAINT pk_sp_ds_dstag PRIMARY KEY (ds, tag); + ADD CONSTRAINT pk_sp_ds_dstag PRIMARY KEY (ds, tag); ALTER TABLE sp_ds_metadata -ADD CONSTRAINT pk_sp_ds_metadata PRIMARY KEY (ds_id, meta_key); + ADD CONSTRAINT pk_sp_ds_metadata PRIMARY KEY (ds_id, meta_key); ALTER TABLE sp_ds_module -ADD CONSTRAINT pk_sp_ds_module PRIMARY KEY (ds_id, module_id); + ADD CONSTRAINT pk_sp_ds_module PRIMARY KEY (ds_id, module_id); ALTER TABLE sp_ds_type_element -ADD CONSTRAINT pk_sp_ds_type_element PRIMARY KEY (distribution_set_type, software_module_type); + ADD CONSTRAINT pk_sp_ds_type_element PRIMARY KEY (distribution_set_type, software_module_type); ALTER TABLE sp_rollout -ADD CONSTRAINT pk_sp_rollout PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_rollout PRIMARY KEY (id); ALTER TABLE sp_rollout -ADD CONSTRAINT uk_rollout_sp_rollout UNIQUE (name, tenant); + ADD CONSTRAINT uk_rollout_sp_rollout UNIQUE (name, tenant); ALTER TABLE sp_rolloutgroup -ADD CONSTRAINT pk_sp_rolloutgroup PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_rolloutgroup PRIMARY KEY (id); ALTER TABLE sp_rolloutgroup -ADD CONSTRAINT uk_rolloutgroup_sp_rolloutgroup UNIQUE (name, rollout, tenant); + ADD CONSTRAINT uk_rolloutgroup_sp_rolloutgroup UNIQUE (name, rollout, tenant); ALTER TABLE sp_rollouttargetgroup -ADD CONSTRAINT pk_sp_rollouttargetgroup PRIMARY KEY (rolloutgroup_id, target_id); + ADD CONSTRAINT pk_sp_rollouttargetgroup PRIMARY KEY (rolloutgroup_id, target_id); ALTER TABLE sp_software_module_type -ADD CONSTRAINT pk_sp_software_module_type PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_software_module_type PRIMARY KEY (id); ALTER TABLE sp_software_module_type -ADD CONSTRAINT uk_smt_name_sp_software_module_type UNIQUE (name, tenant); + ADD CONSTRAINT uk_smt_name_sp_software_module_type UNIQUE (name, tenant); ALTER TABLE sp_software_module_type -ADD CONSTRAINT uk_smt_type_key_sp_software_module_type UNIQUE (type_key, tenant); + ADD CONSTRAINT uk_smt_type_key_sp_software_module_type UNIQUE (type_key, tenant); ALTER TABLE sp_sw_metadata -ADD CONSTRAINT pk_sp_sw_metadata PRIMARY KEY (meta_key, sw_id); + ADD CONSTRAINT pk_sp_sw_metadata PRIMARY KEY (meta_key, sw_id); ALTER TABLE sp_target -ADD CONSTRAINT pk_sp_target PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_target PRIMARY KEY (id); ALTER TABLE sp_target -ADD CONSTRAINT uk_tenant_controller_id_sp_target UNIQUE (controller_id, tenant); + ADD CONSTRAINT uk_tenant_controller_id_sp_target UNIQUE (controller_id, tenant); ALTER TABLE sp_target_attributes -ADD CONSTRAINT pk_sp_target_attributes PRIMARY KEY (target_id, attribute_key); + ADD CONSTRAINT pk_sp_target_attributes PRIMARY KEY (target_id, attribute_key); ALTER TABLE sp_target_filter_query -ADD CONSTRAINT pk_sp_target_filter_query PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_target_filter_query PRIMARY KEY (id); ALTER TABLE sp_target_filter_query -ADD CONSTRAINT uk_tenant_custom_filter_name_sp_target_filter_query UNIQUE (name, tenant); + ADD CONSTRAINT uk_tenant_custom_filter_name_sp_target_filter_query UNIQUE (name, tenant); ALTER TABLE sp_target_metadata -ADD CONSTRAINT pk_sp_target_metadata PRIMARY KEY (target_id, meta_key); + ADD CONSTRAINT pk_sp_target_metadata PRIMARY KEY (target_id, meta_key); ALTER TABLE sp_target_tag -ADD CONSTRAINT pk_sp_target_tag PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_target_tag PRIMARY KEY (id); ALTER TABLE sp_target_tag -ADD CONSTRAINT uk_targ_tag_sp_target_tag UNIQUE (name, tenant); + ADD CONSTRAINT uk_targ_tag_sp_target_tag UNIQUE (name, tenant); ALTER TABLE sp_target_target_tag -ADD CONSTRAINT pk_sp_target_target_tag PRIMARY KEY (target, tag); + ADD CONSTRAINT pk_sp_target_target_tag PRIMARY KEY (target, tag); ALTER TABLE sp_tenant -ADD CONSTRAINT pk_sp_tenant PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_tenant PRIMARY KEY (id); ALTER TABLE sp_tenant -ADD CONSTRAINT uk_tenantmd_tenant_sp_tenant UNIQUE (tenant); + ADD CONSTRAINT uk_tenantmd_tenant_sp_tenant UNIQUE (tenant); ALTER TABLE sp_tenant_configuration -ADD CONSTRAINT pk_sp_tenant_configuration PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_tenant_configuration PRIMARY KEY (id); ALTER TABLE sp_tenant_configuration -ADD CONSTRAINT uk_tenant_key_sp_tenant_configuration UNIQUE (conf_key, tenant); + ADD CONSTRAINT uk_tenant_key_sp_tenant_configuration UNIQUE (conf_key, tenant); -- ------------ Write CREATE-FOREIGN-KEY-CONSTRAINT-stage scripts ----------- ALTER TABLE sp_action -ADD CONSTRAINT fk_action_ds FOREIGN KEY (distribution_set) -REFERENCES sp_distribution_set (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_action_ds FOREIGN KEY (distribution_set) + REFERENCES sp_distribution_set (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; ALTER TABLE sp_action -ADD CONSTRAINT fk_action_rollout FOREIGN KEY (rollout) -REFERENCES sp_rollout (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_action_rollout FOREIGN KEY (rollout) + REFERENCES sp_rollout (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; ALTER TABLE sp_action -ADD CONSTRAINT fk_action_rolloutgroup FOREIGN KEY (rolloutgroup) -REFERENCES sp_rolloutgroup (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_action_rolloutgroup FOREIGN KEY (rolloutgroup) + REFERENCES sp_rolloutgroup (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; ALTER TABLE sp_action -ADD CONSTRAINT fk_targ_act_hist_targ FOREIGN KEY (target) -REFERENCES sp_target (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_targ_act_hist_targ FOREIGN KEY (target) + REFERENCES sp_target (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_action_status -ADD CONSTRAINT fk_act_stat_action FOREIGN KEY (action) -REFERENCES sp_action (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_act_stat_action FOREIGN KEY (action) + REFERENCES sp_action (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_action_status_messages -ADD CONSTRAINT fk_stat_msg_act_stat FOREIGN KEY (action_status_id) -REFERENCES sp_action_status (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_stat_msg_act_stat FOREIGN KEY (action_status_id) + REFERENCES sp_action_status (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_artifact -ADD CONSTRAINT fk_assigned_sm FOREIGN KEY (software_module) -REFERENCES sp_base_software_module (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_assigned_sm FOREIGN KEY (software_module) + REFERENCES sp_base_software_module (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_base_software_module -ADD CONSTRAINT fk_module_type FOREIGN KEY (module_type) -REFERENCES sp_software_module_type (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_module_type FOREIGN KEY (module_type) + REFERENCES sp_software_module_type (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; ALTER TABLE sp_distribution_set -ADD CONSTRAINT fk_ds_dstype_ds FOREIGN KEY (ds_id) -REFERENCES sp_distribution_set_type (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_ds_dstype_ds FOREIGN KEY (ds_id) + REFERENCES sp_distribution_set_type (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; ALTER TABLE sp_ds_dstag -ADD CONSTRAINT fk_ds_dstag_ds FOREIGN KEY (ds) -REFERENCES sp_distribution_set (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_ds_dstag_ds FOREIGN KEY (ds) + REFERENCES sp_distribution_set (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_ds_dstag -ADD CONSTRAINT fk_ds_dstag_tag FOREIGN KEY (tag) -REFERENCES sp_distributionset_tag (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_ds_dstag_tag FOREIGN KEY (tag) + REFERENCES sp_distributionset_tag (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_ds_metadata -ADD CONSTRAINT fk_metadata_ds FOREIGN KEY (ds_id) -REFERENCES sp_distribution_set (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_metadata_ds FOREIGN KEY (ds_id) + REFERENCES sp_distribution_set (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_ds_module -ADD CONSTRAINT fk_ds_module_ds FOREIGN KEY (ds_id) -REFERENCES sp_distribution_set (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_ds_module_ds FOREIGN KEY (ds_id) + REFERENCES sp_distribution_set (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_ds_module -ADD CONSTRAINT fk_ds_module_module FOREIGN KEY (module_id) -REFERENCES sp_base_software_module (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_ds_module_module FOREIGN KEY (module_id) + REFERENCES sp_base_software_module (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_ds_type_element -ADD CONSTRAINT fk_ds_type_element_element FOREIGN KEY (distribution_set_type) -REFERENCES sp_distribution_set_type (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_ds_type_element_element FOREIGN KEY (distribution_set_type) + REFERENCES sp_distribution_set_type (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_ds_type_element -ADD CONSTRAINT fk_ds_type_element_smtype FOREIGN KEY (software_module_type) -REFERENCES sp_software_module_type (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_ds_type_element_smtype FOREIGN KEY (software_module_type) + REFERENCES sp_software_module_type (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_rollout -ADD CONSTRAINT fk_rollout_ds FOREIGN KEY (distribution_set) -REFERENCES sp_distribution_set (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_rollout_ds FOREIGN KEY (distribution_set) + REFERENCES sp_distribution_set (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; ALTER TABLE sp_rolloutgroup -ADD CONSTRAINT fk_rolloutgroup_rollout FOREIGN KEY (rollout) -REFERENCES sp_rollout (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_rolloutgroup_rollout FOREIGN KEY (rollout) + REFERENCES sp_rollout (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_rollouttargetgroup -ADD CONSTRAINT fk_rollouttargetgroup_rolloutgroup FOREIGN KEY (rolloutgroup_id) -REFERENCES sp_rolloutgroup (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_rollouttargetgroup_rolloutgroup FOREIGN KEY (rolloutgroup_id) + REFERENCES sp_rolloutgroup (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_rollouttargetgroup -ADD CONSTRAINT fk_rollouttargetgroup_target FOREIGN KEY (target_id) -REFERENCES sp_target (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_rollouttargetgroup_target FOREIGN KEY (target_id) + REFERENCES sp_target (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_sw_metadata -ADD CONSTRAINT fk_metadata_sw FOREIGN KEY (sw_id) -REFERENCES sp_base_software_module (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_metadata_sw FOREIGN KEY (sw_id) + REFERENCES sp_base_software_module (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_target -ADD CONSTRAINT fk_target_assign_ds FOREIGN KEY (assigned_distribution_set) -REFERENCES sp_distribution_set (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_target_assign_ds FOREIGN KEY (assigned_distribution_set) + REFERENCES sp_distribution_set (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; ALTER TABLE sp_target -ADD CONSTRAINT fk_target_inst_ds FOREIGN KEY (installed_distribution_set) -REFERENCES sp_distribution_set (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_target_inst_ds FOREIGN KEY (installed_distribution_set) + REFERENCES sp_distribution_set (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; ALTER TABLE sp_target_attributes -ADD CONSTRAINT fk_targ_attrib_target FOREIGN KEY (target_id) -REFERENCES sp_target (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_targ_attrib_target FOREIGN KEY (target_id) + REFERENCES sp_target (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_target_filter_query -ADD CONSTRAINT fk_filter_auto_assign_ds FOREIGN KEY (auto_assign_distribution_set) -REFERENCES sp_distribution_set (id) -ON UPDATE RESTRICT -ON DELETE SET NULL; + ADD CONSTRAINT fk_filter_auto_assign_ds FOREIGN KEY (auto_assign_distribution_set) + REFERENCES sp_distribution_set (id) + ON UPDATE RESTRICT + ON DELETE SET NULL; ALTER TABLE sp_target_metadata -ADD CONSTRAINT fk_metadata_target FOREIGN KEY (target_id) -REFERENCES sp_target (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_metadata_target FOREIGN KEY (target_id) + REFERENCES sp_target (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_target_target_tag -ADD CONSTRAINT fk_targ_targtag_tag FOREIGN KEY (tag) -REFERENCES sp_target_tag (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_targ_targtag_tag FOREIGN KEY (tag) + REFERENCES sp_target_tag (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_target_target_tag -ADD CONSTRAINT fk_targ_targtag_target FOREIGN KEY (target) -REFERENCES sp_target (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_targ_targtag_target FOREIGN KEY (target) + REFERENCES sp_target (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_tenant -ADD CONSTRAINT fk_tenant_md_default_ds_type FOREIGN KEY (default_ds_type) -REFERENCES sp_distribution_set_type (id) -ON UPDATE RESTRICT -ON DELETE RESTRICT; + ADD CONSTRAINT fk_tenant_md_default_ds_type FOREIGN KEY (default_ds_type) + REFERENCES sp_distribution_set_type (id) + ON UPDATE RESTRICT + ON DELETE RESTRICT; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_16__add_action_initiated_by___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_16__add_action_initiated_by___POSTGRESQL.sql index 14a68bfd3..034090ae8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_16__add_action_initiated_by___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_16__add_action_initiated_by___POSTGRESQL.sql @@ -1,7 +1,7 @@ ALTER TABLE sp_action -ADD COLUMN initiated_by VARCHAR (64) NOT NULL DEFAULT ''; + ADD COLUMN initiated_by VARCHAR(64) NOT NULL DEFAULT ''; ALTER TABLE sp_action -ALTER COLUMN initiated_by DROP DEFAULT; + ALTER COLUMN initiated_by DROP DEFAULT; ALTER TABLE sp_target_filter_query -ADD COLUMN auto_assign_initiated_by VARCHAR (64); \ No newline at end of file + ADD COLUMN auto_assign_initiated_by VARCHAR(64); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_17__add_index_target_modified___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_17__add_index_target_modified___POSTGRESQL.sql index e509359e4..10ea8e46a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_17__add_index_target_modified___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_17__add_index_target_modified___POSTGRESQL.sql @@ -1,3 +1,3 @@ CREATE INDEX sp_idx_target_05 -ON sp_target -USING BTREE (tenant, last_modified_at); \ No newline at end of file + ON sp_target + USING BTREE (tenant, last_modified_at); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_18__add_target_type___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_18__add_target_type___POSTGRESQL.sql index 8acd8038d..857ba4637 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_18__add_target_type___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_18__add_target_type___POSTGRESQL.sql @@ -7,8 +7,9 @@ NO CYCLE; -- ------------ Write CREATE-TABLE-stage scripts ----------- -CREATE TABLE sp_target_type( - id BIGINT NOT NULL DEFAULT nextval('sp_target_type_seq'), +CREATE TABLE sp_target_type +( + id BIGINT NOT NULL DEFAULT nextval('sp_target_type_seq'), created_at BIGINT, created_by VARCHAR(64), last_modified_at BIGINT, @@ -19,47 +20,48 @@ CREATE TABLE sp_target_type( name VARCHAR(64), colour VARCHAR(16) ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -CREATE TABLE sp_target_type_ds_type_relation( +CREATE TABLE sp_target_type_ds_type_relation +( target_type BIGINT NOT NULL, distribution_set_type BIGINT NOT NULL ) - WITH ( - OIDS=FALSE + WITH ( + OIDS = FALSE ); -- ------------ Alter Table and Write INDEX scripts ----------- ALTER TABLE sp_target_type -ADD CONSTRAINT pk_sp_target_type PRIMARY KEY (id); + ADD CONSTRAINT pk_sp_target_type PRIMARY KEY (id); ALTER TABLE sp_target_type -ADD CONSTRAINT uk_target_type_name UNIQUE (name, tenant); + ADD CONSTRAINT uk_target_type_name UNIQUE (name, tenant); CREATE INDEX sp_idx_target_type_prim -ON sp_target_type -USING BTREE (tenant, id); + ON sp_target_type + USING BTREE (tenant, id); ALTER TABLE sp_target -ADD COLUMN target_type BIGINT; + ADD COLUMN target_type BIGINT; ALTER TABLE sp_target -ADD CONSTRAINT fk_target_relation_target_type FOREIGN KEY (target_type) -REFERENCES sp_target_type (id) -ON UPDATE RESTRICT -ON DELETE SET NULL; + ADD CONSTRAINT fk_target_relation_target_type FOREIGN KEY (target_type) + REFERENCES sp_target_type (id) + ON UPDATE RESTRICT + ON DELETE SET NULL; ALTER TABLE sp_target_type_ds_type_relation -ADD CONSTRAINT fk_target_type_relation_target_type FOREIGN KEY (target_type) -REFERENCES sp_target_type (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; + ADD CONSTRAINT fk_target_type_relation_target_type FOREIGN KEY (target_type) + REFERENCES sp_target_type (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; ALTER TABLE sp_target_type_ds_type_relation -ADD CONSTRAINT fk_target_type_relation_ds_type FOREIGN KEY (distribution_set_type) -REFERENCES sp_distribution_set_type (id) -ON UPDATE RESTRICT -ON DELETE CASCADE; \ No newline at end of file + ADD CONSTRAINT fk_target_type_relation_ds_type FOREIGN KEY (distribution_set_type) + REFERENCES sp_distribution_set_type (id) + ON UPDATE RESTRICT + ON DELETE CASCADE; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_19__add_valid_flag_to_ds___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_19__add_valid_flag_to_ds___POSTGRESQL.sql index 6d2f70e74..9f1194af5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_19__add_valid_flag_to_ds___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_19__add_valid_flag_to_ds___POSTGRESQL.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN; +ALTER TABLE sp_distribution_set + ADD COLUMN valid BOOLEAN; -UPDATE sp_distribution_set SET valid = TRUE; \ No newline at end of file +UPDATE sp_distribution_set +SET valid = TRUE; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_20__add_encryption_flag_to_sm___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_20__add_encryption_flag_to_sm___POSTGRESQL.sql index 00ae94f2d..3366980a1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_20__add_encryption_flag_to_sm___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_20__add_encryption_flag_to_sm___POSTGRESQL.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_base_software_module ADD COLUMN encrypted BOOLEAN; +ALTER TABLE sp_base_software_module + ADD COLUMN encrypted BOOLEAN; -UPDATE sp_base_software_module SET encrypted = FALSE; \ No newline at end of file +UPDATE sp_base_software_module +SET encrypted = FALSE; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_21__add_rollouts_status_index___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_21__add_rollouts_status_index___POSTGRESQL.sql index 0d4783710..f6c0a1a55 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_21__add_rollouts_status_index___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_21__add_rollouts_status_index___POSTGRESQL.sql @@ -1,3 +1,3 @@ CREATE INDEX sp_idx_rollout_status_tenant -ON sp_rollout -USING BTREE (tenant, status); \ No newline at end of file + ON sp_rollout + USING BTREE (tenant, status); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_23__add_action_status_code___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_23__add_action_status_code___POSTGRESQL.sql index 623bc3141..9ec28c334 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_23__add_action_status_code___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_23__add_action_status_code___POSTGRESQL.sql @@ -1,4 +1,5 @@ -ALTER TABLE sp_action_status ADD COLUMN code INTEGER; +ALTER TABLE sp_action_status + ADD COLUMN code INTEGER; CREATE INDEX sp_idx_action_status_03 ON sp_action_status USING BTREE (tenant, code); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_24__add_last_action_status_code___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_24__add_last_action_status_code___POSTGRESQL.sql index d5a4cc232..76ec231cf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_24__add_last_action_status_code___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_24__add_last_action_status_code___POSTGRESQL.sql @@ -1 +1,2 @@ -ALTER TABLE sp_action ADD last_action_status_code INTEGER; \ No newline at end of file +ALTER TABLE sp_action + ADD last_action_status_code INTEGER; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_25__add_confirmation_flag___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_25__add_confirmation_flag___POSTGRESQL.sql index 265771afe..a0aea8e78 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_25__add_confirmation_flag___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_25__add_confirmation_flag___POSTGRESQL.sql @@ -3,8 +3,10 @@ ALTER TABLE sp_rolloutgroup ALTER TABLE sp_target_filter_query ADD COLUMN confirmation_required BOOLEAN; -UPDATE sp_rolloutgroup SET confirmation_required = FALSE; -UPDATE sp_target_filter_query SET confirmation_required = FALSE; +UPDATE sp_rolloutgroup +SET confirmation_required = FALSE; +UPDATE sp_target_filter_query +SET confirmation_required = FALSE; CREATE TABLE sp_target_conf_status ( diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_26__add_access_control_context___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_26__add_access_control_context___POSTGRESQL.sql index ccf16963e..fb06922c7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_26__add_access_control_context___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_26__add_access_control_context___POSTGRESQL.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_target_filter_query ADD COLUMN access_control_context VARCHAR(4096); -ALTER TABLE sp_rollout ADD COLUMN access_control_context VARCHAR(4096); \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD COLUMN access_control_context VARCHAR(4096); +ALTER TABLE sp_rollout + ADD COLUMN access_control_context VARCHAR(4096); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_27__target_type_inherit_type___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_27__target_type_inherit_type___POSTGRESQL.sql index 86e3350b8..2b63926eb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_27__target_type_inherit_type___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_27__target_type_inherit_type___POSTGRESQL.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_target_type ADD COLUMN type_key VARCHAR (64) NOT NULL DEFAULT ('_'); -UPDATE sp_target_type SET type_key = name; -ALTER TABLE sp_target_type ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file +ALTER TABLE sp_target_type + ADD COLUMN type_key VARCHAR(64) NOT NULL DEFAULT ('_'); +UPDATE sp_target_type +SET type_key = name; +ALTER TABLE sp_target_type + ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_28__add_dynamic_rollout___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_28__add_dynamic_rollout___POSTGRESQL.sql index de6a6f14f..001527803 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_28__add_dynamic_rollout___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_28__add_dynamic_rollout___POSTGRESQL.sql @@ -1,9 +1,20 @@ -ALTER TABLE sp_rollout ADD COLUMN is_dynamic BOOLEAN; -ALTER TABLE sp_rolloutgroup ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; +ALTER TABLE sp_rollout + ADD COLUMN is_dynamic BOOLEAN; +ALTER TABLE sp_rolloutgroup + ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; -UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; -ALTER TABLE sp_rollout ALTER COLUMN weight SET NOT NULL; -ALTER TABLE sp_action ALTER COLUMN weight SET NOT NULL; -ALTER TABLE sp_target_filter_query ALTER COLUMN auto_assign_weight SET NOT NULL; \ No newline at end of file +UPDATE sp_rollout +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_action +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_target_filter_query +SET auto_assign_weight = 1000 +WHERE auto_assign_weight IS NULL; +ALTER TABLE sp_rollout + ALTER COLUMN weight SET NOT NULL; +ALTER TABLE sp_action + ALTER COLUMN weight SET NOT NULL; +ALTER TABLE sp_target_filter_query + ALTER COLUMN auto_assign_weight SET NOT NULL; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_29__add_ds_sm_locked___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_29__add_ds_sm_locked___POSTGRESQL.sql index c5c0de6fb..831528f40 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_29__add_ds_sm_locked___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_29__add_ds_sm_locked___POSTGRESQL.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_base_software_module ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; -ALTER TABLE sp_distribution_set ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file +ALTER TABLE sp_base_software_module + ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; +ALTER TABLE sp_distribution_set + ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_11__add_auto_assign_action_type___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_11__add_auto_assign_action_type___SQL_SERVER.sql index 0e8c37bda..8e5680514 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_11__add_auto_assign_action_type___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_11__add_auto_assign_action_type___SQL_SERVER.sql @@ -1 +1,2 @@ -ALTER TABLE sp_target_filter_query ADD auto_assign_action_type INTEGER; \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD auto_assign_action_type INTEGER; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_13__add_action_external_id___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_13__add_action_external_id___SQL_SERVER.sql index b5ca92aec..aef991e40 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_13__add_action_external_id___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_13__add_action_external_id___SQL_SERVER.sql @@ -1,4 +1,5 @@ -ALTER TABLE sp_action ADD external_ref VARCHAR(512); +ALTER TABLE sp_action + ADD external_ref VARCHAR(512); CREATE INDEX sp_idx_action_external_ref ON sp_action (external_ref); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_14__add_sha256_hash___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_14__add_sha256_hash___SQL_SERVER.sql index c72b8b124..364792ae6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_14__add_sha256_hash___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_14__add_sha256_hash___SQL_SERVER.sql @@ -1 +1,2 @@ -ALTER TABLE sp_artifact ADD sha256_hash CHAR(64); \ No newline at end of file +ALTER TABLE sp_artifact + ADD sha256_hash CHAR(64); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_15__add_weight___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_15__add_weight___SQL_SERVER.sql index 9eaad20e1..12db78a80 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_15__add_weight___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_15__add_weight___SQL_SERVER.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_action ADD weight INT; -ALTER TABLE sp_rollout ADD weight INT; -ALTER TABLE sp_target_filter_query ADD auto_assign_weight INT; +ALTER TABLE sp_action + ADD weight INT; +ALTER TABLE sp_rollout + ADD weight INT; +ALTER TABLE sp_target_filter_query + ADD auto_assign_weight INT; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_16__add_action_initiated_by___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_16__add_action_initiated_by___SQL_SERVER.sql index dc6eae613..e9d92bdbd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_16__add_action_initiated_by___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_16__add_action_initiated_by___SQL_SERVER.sql @@ -1,3 +1,5 @@ -ALTER TABLE sp_action ADD initiated_by VARCHAR(64) NOT NULL CONSTRAINT DF_SpAction_InitiatedBy DEFAULT ''; +ALTER TABLE sp_action + ADD initiated_by VARCHAR(64) NOT NULL CONSTRAINT DF_SpAction_InitiatedBy DEFAULT ''; ALTER TABLE sp_action DROP CONSTRAINT DF_SpAction_InitiatedBy; -ALTER TABLE sp_target_filter_query ADD auto_assign_initiated_by VARCHAR(64); +ALTER TABLE sp_target_filter_query + ADD auto_assign_initiated_by VARCHAR(64); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_18__add_target_type___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_18__add_target_type___SQL_SERVER.sql index 924e0681c..308f198c8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_18__add_target_type___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_18__add_target_type___SQL_SERVER.sql @@ -1,27 +1,32 @@ CREATE TABLE sp_target_type ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16) NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(64) NOT NULL, - description VARCHAR(512) NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(64) NOT NULL, + description VARCHAR(512) NULL, last_modified_at NUMERIC(19) NOT NULL, last_modified_by VARCHAR(64) NOT NULL, - name VARCHAR(64) NOT NULL, + name VARCHAR(64) NOT NULL, optlock_revision INTEGER NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_target_type_prim ON sp_target_type (tenant, id); CREATE TABLE sp_target_type_ds_type_relation ( - target_type NUMERIC(19) NOT NULL, + target_type NUMERIC(19) NOT NULL, distribution_set_type NUMERIC(19) NOT NULL, PRIMARY KEY (target_type, distribution_set_type) ); -ALTER TABLE sp_target_type ADD CONSTRAINT uk_target_type_name UNIQUE (name, tenant); -ALTER TABLE sp_target ADD target_type NUMERIC(19) NULL; -ALTER TABLE sp_target ADD CONSTRAINT fk_target_relation_target_type FOREIGN KEY (target_type) REFERENCES sp_target_type (id) ON DELETE SET NULL; -ALTER TABLE sp_target_type_ds_type_relation ADD CONSTRAINT fk_target_type_relation_target_type FOREIGN KEY (target_type) REFERENCES sp_target_type (id) ON DELETE CASCADE; -ALTER TABLE sp_target_type_ds_type_relation ADD CONSTRAINT fk_target_type_relation_ds_type FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; +ALTER TABLE sp_target_type + ADD CONSTRAINT uk_target_type_name UNIQUE (name, tenant); +ALTER TABLE sp_target + ADD target_type NUMERIC(19) NULL; +ALTER TABLE sp_target + ADD CONSTRAINT fk_target_relation_target_type FOREIGN KEY (target_type) REFERENCES sp_target_type (id) ON DELETE SET NULL; +ALTER TABLE sp_target_type_ds_type_relation + ADD CONSTRAINT fk_target_type_relation_target_type FOREIGN KEY (target_type) REFERENCES sp_target_type (id) ON DELETE CASCADE; +ALTER TABLE sp_target_type_ds_type_relation + ADD CONSTRAINT fk_target_type_relation_ds_type FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_19__add_valid_flag_to_ds___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_19__add_valid_flag_to_ds___SQL_SERVER.sql index 1ec1d0407..33c7369ba 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_19__add_valid_flag_to_ds___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_19__add_valid_flag_to_ds___SQL_SERVER.sql @@ -1 +1,2 @@ -ALTER TABLE sp_distribution_set ADD valid BIT DEFAULT 1; \ No newline at end of file +ALTER TABLE sp_distribution_set + ADD valid BIT DEFAULT 1; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_20__add_encryption_flag_to_sm___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_20__add_encryption_flag_to_sm___SQL_SERVER.sql index 092fdbdcc..ad1eec100 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_20__add_encryption_flag_to_sm___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_20__add_encryption_flag_to_sm___SQL_SERVER.sql @@ -1 +1,2 @@ -ALTER TABLE sp_base_software_module ADD encrypted BIT DEFAULT 0; \ No newline at end of file +ALTER TABLE sp_base_software_module + ADD encrypted BIT DEFAULT 0; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_23__add_action_status_code___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_23__add_action_status_code___SQL_SERVER.sql index 38a6aeaab..9b107a092 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_23__add_action_status_code___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_23__add_action_status_code___SQL_SERVER.sql @@ -1,2 +1,3 @@ -ALTER TABLE sp_action_status ADD code INT; +ALTER TABLE sp_action_status + ADD code INT; CREATE INDEX sp_idx_action_status_03 ON sp_action_status (tenant, code); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_24__add_last_action_status_code___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_24__add_last_action_status_code___SQL_SERVER.sql index db38eeb10..3fc8e3ea5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_24__add_last_action_status_code___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_24__add_last_action_status_code___SQL_SERVER.sql @@ -1 +1,2 @@ -ALTER TABLE sp_action ADD last_action_status_code INT; \ No newline at end of file +ALTER TABLE sp_action + ADD last_action_status_code INT; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_25__add_confirmation_flag___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_25__add_confirmation_flag___SQL_SERVER.sql index 0cd9e2fef..230a3248c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_25__add_confirmation_flag___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_25__add_confirmation_flag___SQL_SERVER.sql @@ -1,18 +1,20 @@ -ALTER TABLE sp_rolloutgroup ADD confirmation_required BIT DEFAULT 0; -ALTER TABLE sp_target_filter_query ADD confirmation_required BIT DEFAULT 0; +ALTER TABLE sp_rolloutgroup + ADD confirmation_required BIT DEFAULT 0; +ALTER TABLE sp_target_filter_query + ADD confirmation_required BIT DEFAULT 0; CREATE TABLE sp_target_conf_status ( - id NUMERIC(19) IDENTITY NOT NULL, - target_id NUMERIC(19) NOT NULL, - initiator VARCHAR(64), - remark VARCHAR(512), - tenant VARCHAR(40) NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(64) NOT NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(64) NOT NULL, - optlock_revision INTEGER NULL, + id NUMERIC(19) IDENTITY NOT NULL, + target_id NUMERIC(19) NOT NULL, + initiator VARCHAR(64), + remark VARCHAR(512), + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(64) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, PRIMARY KEY (id) ); ALTER TABLE sp_target_conf_status diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_26__add_access_control_context___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_26__add_access_control_context___SQL_SERVER.sql index 24f81bc7e..637b01170 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_26__add_access_control_context___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_26__add_access_control_context___SQL_SERVER.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_target_filter_query ADD access_control_context VARCHAR(4096); -ALTER TABLE sp_rollout ADD access_control_context VARCHAR(4096); \ No newline at end of file +ALTER TABLE sp_target_filter_query + ADD access_control_context VARCHAR(4096); +ALTER TABLE sp_rollout + ADD access_control_context VARCHAR(4096); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_27__target_type_inherit_type___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_27__target_type_inherit_type___SQL_SERVER.sql index f64339420..441854a15 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_27__target_type_inherit_type___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_27__target_type_inherit_type___SQL_SERVER.sql @@ -1,3 +1,6 @@ -ALTER TABLE sp_target_type ADD type_key VARCHAR (64) NOT NULL DEFAULT ('_'); -UPDATE sp_target_type SET type_key = name; -ALTER TABLE sp_target_type ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file +ALTER TABLE sp_target_type + ADD type_key VARCHAR(64) NOT NULL DEFAULT ('_'); +UPDATE sp_target_type +SET type_key = name; +ALTER TABLE sp_target_type + ADD CONSTRAINT uk_target_type_key UNIQUE (type_key, tenant); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_28__add_dynamic_rollout___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_28__add_dynamic_rollout___SQL_SERVER.sql index a22a7f997..fde4df351 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_28__add_dynamic_rollout___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_28__add_dynamic_rollout___SQL_SERVER.sql @@ -1,9 +1,17 @@ -ALTER TABLE sp_rollout ADD is_dynamic BIT; -ALTER TABLE sp_rolloutgroup ADD is_dynamic BIT NOT NULL DEFAULT 0; +ALTER TABLE sp_rollout + ADD is_dynamic BIT; +ALTER TABLE sp_rolloutgroup + ADD is_dynamic BIT NOT NULL DEFAULT 0; -UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; -UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; +UPDATE sp_rollout +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_action +SET weight = 1000 +WHERE weight IS NULL; +UPDATE sp_target_filter_query +SET auto_assign_weight = 1000 +WHERE auto_assign_weight IS NULL; ALTER TABLE sp_rollout ALTER COLUMN weight INT NOT NULL; ALTER TABLE sp_action ALTER COLUMN weight INT NOT NULL; ALTER TABLE sp_target_filter_query ALTER COLUMN auto_assign_weight INT NOT NULL; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_29__add_ds_sm_locked___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_29__add_ds_sm_locked___SQL_SERVER.sql index 946d0b8e0..2c391200a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_29__add_ds_sm_locked___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_29__add_ds_sm_locked___SQL_SERVER.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_base_software_module ADD locked BIT NOT NULL DEFAULT 1; -ALTER TABLE sp_distribution_set ADD locked BIT NOT NULL DEFAULT 1; \ No newline at end of file +ALTER TABLE sp_base_software_module + ADD locked BIT NOT NULL DEFAULT 1; +ALTER TABLE sp_distribution_set + ADD locked BIT NOT NULL DEFAULT 1; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_5__baseline___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_5__baseline___SQL_SERVER.sql index 42a3895b4..15c665719 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_5__baseline___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_5__baseline___SQL_SERVER.sql @@ -1,30 +1,30 @@ CREATE TABLE sp_ds_type_element ( - mandatory BIT default 0 NULL, + mandatory BIT default 0 NULL, distribution_set_type NUMERIC(19) NOT NULL, - software_module_type NUMERIC(19) NOT NULL, + software_module_type NUMERIC(19) NOT NULL, PRIMARY KEY (distribution_set_type, software_module_type) ); CREATE TABLE sp_action ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - action_type INTEGER NOT NULL, - active BIT default 0 NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - forced_time NUMERIC(19) NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - optlock_revision INTEGER NULL, - status INTEGER NOT NULL, - distribution_set NUMERIC(19) NOT NULL, - rollout NUMERIC(19) NULL, - rolloutgroup NUMERIC(19) NULL, - target NUMERIC(19) NOT NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + action_type INTEGER NOT NULL, + active BIT default 0 NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + forced_time NUMERIC(19) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER NULL, + status INTEGER NOT NULL, + distribution_set NUMERIC(19) NOT NULL, + rollout NUMERIC(19) NULL, + rolloutgroup NUMERIC(19) NULL, + target NUMERIC(19) NOT NULL, maintenance_cron_schedule VARCHAR(40), - maintenance_duration VARCHAR(40), - maintenance_time_zone VARCHAR(40), + maintenance_duration VARCHAR(40), + maintenance_time_zone VARCHAR(40), PRIMARY KEY (id) ); CREATE INDEX sp_idx_action_01 ON sp_action (tenant, distribution_set); @@ -32,34 +32,34 @@ CREATE INDEX sp_idx_action_02 ON sp_action (tenant, target, active); CREATE INDEX sp_idx_action_prim ON sp_action (tenant, id); CREATE TABLE sp_action_status ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, target_occurred_at NUMERIC(19) NOT NULL, - optlock_revision INTEGER NULL, - status INTEGER NOT NULL, - action NUMERIC(19) NOT NULL, + optlock_revision INTEGER NULL, + status INTEGER NOT NULL, + action NUMERIC(19) NOT NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_action_status_02 ON sp_action_status (tenant, action, status); CREATE INDEX sp_idx_action_status_prim ON sp_action_status (tenant, id); CREATE TABLE sp_artifact ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, provided_file_name VARCHAR(256) NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - md5_hash VARCHAR(32) NULL, - optlock_revision INTEGER NULL, - sha1_hash VARCHAR(40) NOT NULL, - file_size NUMERIC(19) NULL, - software_module NUMERIC(19) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + md5_hash VARCHAR(32) NULL, + optlock_revision INTEGER NULL, + sha1_hash VARCHAR(40) NOT NULL, + file_size NUMERIC(19) NULL, + software_module NUMERIC(19) NOT NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_artifact_01 ON sp_artifact (tenant, software_module); @@ -67,59 +67,59 @@ CREATE INDEX sp_idx_artifact_02 ON sp_artifact (tenant, sha1_hash); CREATE INDEX sp_idx_artifact_prim ON sp_artifact (tenant, id); CREATE TABLE sp_distribution_set ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - complete BIT default 0 NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted BIT default 0 NULL, - description VARCHAR(512) NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + complete BIT default 0 NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, required_migration_step BIT default 0 NULL, - version VARCHAR(64) NOT NULL, - ds_id NUMERIC(19) NOT NULL, + version VARCHAR(64) NOT NULL, + ds_id NUMERIC(19) NOT NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_distribution_set_01 ON sp_distribution_set (tenant, deleted, complete); CREATE INDEX sp_idx_distribution_set_prim ON sp_distribution_set (tenant, id); CREATE TABLE sp_ds_metadata ( - meta_key VARCHAR(128) NOT NULL, + meta_key VARCHAR(128) NOT NULL, meta_value VARCHAR(4000) NULL, - ds_id NUMERIC(19) NOT NULL, + ds_id NUMERIC(19) NOT NULL, PRIMARY KEY (meta_key, ds_id) ); CREATE TABLE sp_distributionset_tag ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16) NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - description VARCHAR(512) NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512) NULL, last_modified_at NUMERIC(19) NOT NULL, last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, + name VARCHAR(64) NOT NULL, optlock_revision INTEGER NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_distribution_set_tag_prim ON sp_distributionset_tag (tenant, id); CREATE TABLE sp_distribution_set_type ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16) NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted BIT default 0 NULL, - description VARCHAR(512) NULL, - type_key VARCHAR(64) NOT NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + type_key VARCHAR(64) NOT NULL, last_modified_at NUMERIC(19) NOT NULL, last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, + name VARCHAR(64) NOT NULL, optlock_revision INTEGER NULL, PRIMARY KEY (id) ); @@ -127,69 +127,69 @@ CREATE INDEX sp_idx_distribution_set_type_01 ON sp_distribution_set_type (tenant CREATE INDEX sp_idx_distribution_set_type_prim ON sp_distribution_set_type (tenant, id); CREATE TABLE sp_rollout ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - action_type INTEGER NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted BIT default 0 NULL, - description VARCHAR(512) NULL, - forced_time NUMERIC(19) NULL, - last_check NUMERIC(19) NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + action_type INTEGER NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + forced_time NUMERIC(19) NULL, + last_check NUMERIC(19) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, rollout_groups_created INTEGER NULL, - start_at NUMERIC(19) NULL, - status INTEGER NOT NULL, - target_filter VARCHAR(1024) NOT NULL, - total_targets NUMERIC(19) NULL, - distribution_set NUMERIC(19) NOT NULL, + start_at NUMERIC(19) NULL, + status INTEGER NOT NULL, + target_filter VARCHAR(1024) NOT NULL, + total_targets NUMERIC(19) NULL, + distribution_set NUMERIC(19) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE sp_rolloutgroup ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - description VARCHAR(512) NULL, - error_action INTEGER NULL, - error_action_exp VARCHAR(512) NULL, - error_condition INTEGER NULL, - error_condition_exp VARCHAR(512) NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER NULL, - status INTEGER NOT NULL, - success_action INTEGER NOT NULL, - success_action_exp VARCHAR(512) NULL, - success_condition INTEGER NOT NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512) NULL, + error_action INTEGER NULL, + error_action_exp VARCHAR(512) NULL, + error_condition INTEGER NULL, + error_condition_exp VARCHAR(512) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + status INTEGER NOT NULL, + success_action INTEGER NOT NULL, + success_action_exp VARCHAR(512) NULL, + success_condition INTEGER NOT NULL, success_condition_exp VARCHAR(512) NOT NULL, - target_filter VARCHAR(1024) NULL, - target_percentage FLOAT(16) NULL, - total_targets INTEGER NULL, - parent_id NUMERIC(19) NULL, - rollout NUMERIC(19) NOT NULL, + target_filter VARCHAR(1024) NULL, + target_percentage FLOAT(16) NULL, + total_targets INTEGER NULL, + parent_id NUMERIC(19) NULL, + rollout NUMERIC(19) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE sp_base_software_module ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted BIT default 0 NULL, - description VARCHAR(512) NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, last_modified_at NUMERIC(19) NOT NULL, last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, + name VARCHAR(64) NOT NULL, optlock_revision INTEGER NULL, - vendor VARCHAR(256) NULL, - version VARCHAR(64) NOT NULL, - module_type NUMERIC(19) NOT NULL, + vendor VARCHAR(256) NULL, + version VARCHAR(64) NOT NULL, + module_type NUMERIC(19) NOT NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_base_sw_module_01 ON sp_base_software_module (tenant, deleted, name, version); @@ -197,51 +197,51 @@ CREATE INDEX sp_idx_base_sw_module_02 ON sp_base_software_module (tenant, delete CREATE INDEX sp_idx_base_sw_module_prim ON sp_base_software_module (tenant, id); CREATE TABLE sp_sw_metadata ( - meta_key VARCHAR(128) NOT NULL, + meta_key VARCHAR(128) NOT NULL, target_visible BIT default 0 NULL, - meta_value VARCHAR(4000) NULL, - sw_id NUMERIC(19) NOT NULL, + meta_value VARCHAR(4000) NULL, + sw_id NUMERIC(19) NOT NULL, PRIMARY KEY (meta_key, sw_id) ); CREATE TABLE sp_software_module_type ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16) NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - deleted BIT default 0 NULL, - description VARCHAR(512) NULL, - type_key VARCHAR(64) NOT NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - max_ds_assignments INTEGER NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + type_key VARCHAR(64) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + max_ds_assignments INTEGER NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_software_module_type_01 ON sp_software_module_type (tenant, deleted); CREATE INDEX sp_idx_software_module_type_prim ON sp_software_module_type (tenant, id); CREATE TABLE sp_target ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - address VARCHAR(512) NULL, - controller_id VARCHAR(64) NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - description VARCHAR(512) NULL, - install_date NUMERIC(19) NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - last_target_query NUMERIC(19) NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + address VARCHAR(512) NULL, + controller_id VARCHAR(64) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512) NULL, + install_date NUMERIC(19) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + last_target_query NUMERIC(19) NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, request_controller_attributes BIT default 0 NOT NULL, - sec_token VARCHAR(128) NOT NULL, - update_status INTEGER NOT NULL, - assigned_distribution_set NUMERIC(19) NULL, - installed_distribution_set NUMERIC(19) NULL, + sec_token VARCHAR(128) NOT NULL, + update_status INTEGER NOT NULL, + assigned_distribution_set NUMERIC(19) NULL, + installed_distribution_set NUMERIC(19) NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_target_01 ON sp_target (tenant, name, assigned_distribution_set); @@ -250,134 +250,176 @@ CREATE INDEX sp_idx_target_04 ON sp_target (tenant, created_at); CREATE INDEX sp_idx_target_prim ON sp_target (tenant, id); CREATE TABLE sp_target_filter_query ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, - optlock_revision INTEGER NULL, - query VARCHAR(1024) NOT NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + query VARCHAR(1024) NOT NULL, auto_assign_distribution_set NUMERIC(19) NULL, PRIMARY KEY (id) ); CREATE TABLE sp_target_tag ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - colour VARCHAR(16) NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - description VARCHAR(512) NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512) NULL, last_modified_at NUMERIC(19) NOT NULL, last_modified_by VARCHAR(40) NOT NULL, - name VARCHAR(64) NOT NULL, + name VARCHAR(64) NOT NULL, optlock_revision INTEGER NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_target_tag_prim ON sp_target_tag (tenant, id); CREATE TABLE sp_tenant_configuration ( - id NUMERIC(19) IDENTITY NOT NULL, - tenant VARCHAR(40) NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, - conf_key VARCHAR(128) NOT NULL, - last_modified_at NUMERIC(19) NOT NULL, - last_modified_by VARCHAR(40) NOT NULL, + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + conf_key VARCHAR(128) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, optlock_revision INTEGER NULL, - conf_value VARCHAR(512) NOT NULL, + conf_value VARCHAR(512) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE sp_tenant ( - id NUMERIC(19) IDENTITY NOT NULL, - created_at NUMERIC(19) NOT NULL, - created_by VARCHAR(40) NOT NULL, + id NUMERIC(19) IDENTITY NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, last_modified_at NUMERIC(19) NOT NULL, last_modified_by VARCHAR(40) NOT NULL, optlock_revision INTEGER NULL, - tenant VARCHAR(40) NOT NULL, - default_ds_type NUMERIC(19) NOT NULL, + tenant VARCHAR(40) NOT NULL, + default_ds_type NUMERIC(19) NOT NULL, PRIMARY KEY (id) ); CREATE INDEX sp_idx_tenant_prim ON sp_tenant (tenant, id); CREATE TABLE sp_rollouttargetgroup ( rolloutGroup_Id NUMERIC(19) NOT NULL, - target_id NUMERIC(19) NOT NULL, + target_id NUMERIC(19) NOT NULL, PRIMARY KEY (rolloutGroup_Id, target_id) ); CREATE TABLE sp_action_status_messages ( - action_status_id NUMERIC(19) NOT NULL, - detail_message VARCHAR(512) NOT NULL + action_status_id NUMERIC(19) NOT NULL, + detail_message VARCHAR(512) NOT NULL ); CREATE INDEX sp_idx_action_status_msgs_01 ON sp_action_status_messages (action_status_id); CREATE TABLE sp_ds_module ( - ds_id NUMERIC(19) NOT NULL, + ds_id NUMERIC(19) NOT NULL, module_id NUMERIC(19) NOT NULL, PRIMARY KEY (ds_id, module_id) ); CREATE TABLE sp_ds_dstag ( - ds NUMERIC(19) NOT NULL, + ds NUMERIC(19) NOT NULL, TAG NUMERIC(19) NOT NULL, PRIMARY KEY (ds, TAG) ); CREATE TABLE sp_target_attributes ( - target_id NUMERIC(19) NOT NULL, + target_id NUMERIC(19) NOT NULL, attribute_value VARCHAR(128) NULL, - attribute_key VARCHAR(32) NOT NULL + attribute_key VARCHAR(32) NOT NULL ); CREATE TABLE sp_target_target_tag ( target NUMERIC(19) NOT NULL, - tag NUMERIC(19) NOT NULL, + tag NUMERIC(19) NOT NULL, PRIMARY KEY (target, tag) ); -ALTER TABLE sp_distribution_set ADD CONSTRAINT uk_distrib_set UNIQUE (name, version, tenant); -ALTER TABLE sp_distributionset_tag ADD CONSTRAINT uk_ds_tag UNIQUE (name, tenant); -ALTER TABLE sp_distribution_set_type ADD CONSTRAINT uk_dst_name UNIQUE (name, tenant); -ALTER TABLE sp_distribution_set_type ADD CONSTRAINT uk_dst_key UNIQUE (type_key, tenant); -ALTER TABLE sp_rollout ADD CONSTRAINT uk_rollout UNIQUE (name, tenant); -ALTER TABLE sp_rolloutgroup ADD CONSTRAINT uk_rolloutgroup UNIQUE (name, rollout, tenant); -ALTER TABLE sp_base_software_module ADD CONSTRAINT uk_base_sw_mod UNIQUE (module_type, name, version, tenant); -ALTER TABLE sp_software_module_type ADD CONSTRAINT uk_smt_type_key UNIQUE (type_key, tenant); -ALTER TABLE sp_software_module_type ADD CONSTRAINT uk_smt_name UNIQUE (name, tenant); -ALTER TABLE sp_target ADD CONSTRAINT uk_tenant_controller_ UNIQUE (controller_id, tenant); -ALTER TABLE sp_target_filter_query ADD CONSTRAINT uk_tenant_custom_filt UNIQUE (name, tenant); -ALTER TABLE sp_target_tag ADD CONSTRAINT uk_targ_tag UNIQUE (name, tenant); -ALTER TABLE sp_tenant_configuration ADD CONSTRAINT uk_tenant_key UNIQUE (conf_key, tenant); -ALTER TABLE sp_tenant ADD CONSTRAINT uk_tenantmd_tenant UNIQUE (tenant); -ALTER TABLE sp_ds_type_element ADD CONSTRAINT fk_ds_type_element_element FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_type_element ADD CONSTRAINT fk_ds_type_element_smtype FOREIGN KEY (software_module_type) REFERENCES sp_software_module_type (id) ON DELETE CASCADE; -ALTER TABLE sp_action ADD CONSTRAINT fk_action_rolloutgroup FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); -ALTER TABLE sp_action ADD CONSTRAINT fk_action_rollout FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); -ALTER TABLE sp_action ADD CONSTRAINT fk_targ_act_hist_targ FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; -ALTER TABLE sp_action ADD CONSTRAINT fk_action_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; -ALTER TABLE sp_action_status ADD CONSTRAINT fk_act_stat_action FOREIGN KEY (action) REFERENCES sp_action (id) ON DELETE CASCADE; -ALTER TABLE sp_artifact ADD CONSTRAINT fk_assigned_sm FOREIGN KEY (software_module) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; -ALTER TABLE sp_distribution_set ADD CONSTRAINT fk_ds_dstype_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set_type (id); -ALTER TABLE sp_ds_metadata ADD CONSTRAINT fk_metadata_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; -ALTER TABLE sp_rollout ADD CONSTRAINT fk_rollout_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id); -ALTER TABLE sp_rolloutgroup ADD CONSTRAINT fk_rolloutgroup_rollout FOREIGN KEY (rollout) REFERENCES sp_rollout (id) ON DELETE CASCADE; -ALTER TABLE sp_base_software_module ADD CONSTRAINT fk_module_type FOREIGN KEY (module_type) REFERENCES sp_software_module_type (id); -ALTER TABLE sp_sw_metadata ADD CONSTRAINT fk_metadata_sw FOREIGN KEY (sw_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; -ALTER TABLE sp_target ADD CONSTRAINT fk_target_inst_ds FOREIGN KEY (installed_distribution_set) REFERENCES sp_distribution_set (id); -ALTER TABLE sp_target ADD CONSTRAINT fk_target_assign_ds FOREIGN KEY (assigned_distribution_set) REFERENCES sp_distribution_set (id); -ALTER TABLE sp_target_filter_query ADD CONSTRAINT fk_filter_auto_assign_ds FOREIGN KEY (auto_assign_distribution_set) REFERENCES sp_distribution_set (id) ON DELETE SET NULL; -ALTER TABLE sp_tenant ADD CONSTRAINT fk_tenant_md_default_ds_type FOREIGN KEY (default_ds_type) REFERENCES sp_distribution_set_type (id); -ALTER TABLE sp_rollouttargetgroup ADD CONSTRAINT fk_rollouttargetgroup_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; -ALTER TABLE sp_rollouttargetgroup ADD CONSTRAINT fk_rollouttargetgroup_group FOREIGN KEY (rolloutGroup_Id) REFERENCES sp_rolloutgroup (id) ON DELETE CASCADE; -ALTER TABLE sp_action_status_messages ADD CONSTRAINT fk_stat_msg_act_stat FOREIGN KEY (action_status_id) REFERENCES sp_action_status (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_module ADD CONSTRAINT fk_ds_module_module FOREIGN KEY (module_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_module ADD CONSTRAINT fk_ds_module_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_dstag ADD CONSTRAINT fk_ds_dstag_tag FOREIGN KEY (tag) REFERENCES sp_distributionset_tag (id) ON DELETE CASCADE; -ALTER TABLE sp_ds_dstag ADD CONSTRAINT fk_ds_dstag_ds FOREIGN KEY (ds) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; -ALTER TABLE sp_target_attributes ADD CONSTRAINT fk_targ_attrib_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; -ALTER TABLE sp_target_target_tag ADD CONSTRAINT fk_targ_targtag_tag FOREIGN KEY (tag) REFERENCES sp_target_tag (id) ON DELETE CASCADE; -ALTER TABLE sp_target_target_tag ADD CONSTRAINT fk_targ_targtag_target FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_distribution_set + ADD CONSTRAINT uk_distrib_set UNIQUE (name, version, tenant); +ALTER TABLE sp_distributionset_tag + ADD CONSTRAINT uk_ds_tag UNIQUE (name, tenant); +ALTER TABLE sp_distribution_set_type + ADD CONSTRAINT uk_dst_name UNIQUE (name, tenant); +ALTER TABLE sp_distribution_set_type + ADD CONSTRAINT uk_dst_key UNIQUE (type_key, tenant); +ALTER TABLE sp_rollout + ADD CONSTRAINT uk_rollout UNIQUE (name, tenant); +ALTER TABLE sp_rolloutgroup + ADD CONSTRAINT uk_rolloutgroup UNIQUE (name, rollout, tenant); +ALTER TABLE sp_base_software_module + ADD CONSTRAINT uk_base_sw_mod UNIQUE (module_type, name, version, tenant); +ALTER TABLE sp_software_module_type + ADD CONSTRAINT uk_smt_type_key UNIQUE (type_key, tenant); +ALTER TABLE sp_software_module_type + ADD CONSTRAINT uk_smt_name UNIQUE (name, tenant); +ALTER TABLE sp_target + ADD CONSTRAINT uk_tenant_controller_ UNIQUE (controller_id, tenant); +ALTER TABLE sp_target_filter_query + ADD CONSTRAINT uk_tenant_custom_filt UNIQUE (name, tenant); +ALTER TABLE sp_target_tag + ADD CONSTRAINT uk_targ_tag UNIQUE (name, tenant); +ALTER TABLE sp_tenant_configuration + ADD CONSTRAINT uk_tenant_key UNIQUE (conf_key, tenant); +ALTER TABLE sp_tenant + ADD CONSTRAINT uk_tenantmd_tenant UNIQUE (tenant); +ALTER TABLE sp_ds_type_element + ADD CONSTRAINT fk_ds_type_element_element FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element + ADD CONSTRAINT fk_ds_type_element_smtype FOREIGN KEY (software_module_type) REFERENCES sp_software_module_type (id) ON DELETE CASCADE; +ALTER TABLE sp_action + ADD CONSTRAINT fk_action_rolloutgroup FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); +ALTER TABLE sp_action + ADD CONSTRAINT fk_action_rollout FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); +ALTER TABLE sp_action + ADD CONSTRAINT fk_targ_act_hist_targ FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_action + ADD CONSTRAINT fk_action_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_action_status + ADD CONSTRAINT fk_act_stat_action FOREIGN KEY (action) REFERENCES sp_action (id) ON DELETE CASCADE; +ALTER TABLE sp_artifact + ADD CONSTRAINT fk_assigned_sm FOREIGN KEY (software_module) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_distribution_set + ADD CONSTRAINT fk_ds_dstype_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set_type (id); +ALTER TABLE sp_ds_metadata + ADD CONSTRAINT fk_metadata_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_rollout + ADD CONSTRAINT fk_rollout_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_rolloutgroup + ADD CONSTRAINT fk_rolloutgroup_rollout FOREIGN KEY (rollout) REFERENCES sp_rollout (id) ON DELETE CASCADE; +ALTER TABLE sp_base_software_module + ADD CONSTRAINT fk_module_type FOREIGN KEY (module_type) REFERENCES sp_software_module_type (id); +ALTER TABLE sp_sw_metadata + ADD CONSTRAINT fk_metadata_sw FOREIGN KEY (sw_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_target + ADD CONSTRAINT fk_target_inst_ds FOREIGN KEY (installed_distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target + ADD CONSTRAINT fk_target_assign_ds FOREIGN KEY (assigned_distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target_filter_query + ADD CONSTRAINT fk_filter_auto_assign_ds FOREIGN KEY (auto_assign_distribution_set) REFERENCES sp_distribution_set (id) ON DELETE SET NULL; +ALTER TABLE sp_tenant + ADD CONSTRAINT fk_tenant_md_default_ds_type FOREIGN KEY (default_ds_type) REFERENCES sp_distribution_set_type (id); +ALTER TABLE sp_rollouttargetgroup + ADD CONSTRAINT fk_rollouttargetgroup_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_rollouttargetgroup + ADD CONSTRAINT fk_rollouttargetgroup_group FOREIGN KEY (rolloutGroup_Id) REFERENCES sp_rolloutgroup (id) ON DELETE CASCADE; +ALTER TABLE sp_action_status_messages + ADD CONSTRAINT fk_stat_msg_act_stat FOREIGN KEY (action_status_id) REFERENCES sp_action_status (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_module + ADD CONSTRAINT fk_ds_module_module FOREIGN KEY (module_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_module + ADD CONSTRAINT fk_ds_module_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_dstag + ADD CONSTRAINT fk_ds_dstag_tag FOREIGN KEY (tag) REFERENCES sp_distributionset_tag (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_dstag + ADD CONSTRAINT fk_ds_dstag_ds FOREIGN KEY (ds) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_target_attributes + ADD CONSTRAINT fk_targ_attrib_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_target_target_tag + ADD CONSTRAINT fk_targ_targtag_tag FOREIGN KEY (tag) REFERENCES sp_target_tag (id) ON DELETE CASCADE; +ALTER TABLE sp_target_target_tag + ADD CONSTRAINT fk_targ_targtag_target FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_6__add_index___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_6__add_index___SQL_SERVER.sql index d7d7d6cc7..9fdbca2f8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_6__add_index___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_6__add_index___SQL_SERVER.sql @@ -1,2 +1,2 @@ -CREATE INDEX sp_idx_target_tag_01 ON sp_target_tag (tenant, name); +CREATE INDEX sp_idx_target_tag_01 ON sp_target_tag (tenant, name); CREATE INDEX sp_idx_distribution_set_tag_01 ON sp_distributionset_tag (tenant, name); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_7__add_rollout_approval_fields___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_7__add_rollout_approval_fields___SQL_SERVER.sql index 18d86a1ee..23eaea3fd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_7__add_rollout_approval_fields___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_7__add_rollout_approval_fields___SQL_SERVER.sql @@ -1,2 +1,4 @@ -ALTER TABLE sp_rollout ADD approval_decided_by varchar(40); -ALTER TABLE sp_rollout ADD approval_remark varchar(255); \ No newline at end of file +ALTER TABLE sp_rollout + ADD approval_decided_by varchar(40); +ALTER TABLE sp_rollout + ADD approval_remark varchar(255); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_9__add_target_metadata___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_9__add_target_metadata___SQL_SERVER.sql index baa8cf292..2d3795c8c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_9__add_target_metadata___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_9__add_target_metadata___SQL_SERVER.sql @@ -1,9 +1,10 @@ CREATE TABLE sp_target_metadata ( - meta_key VARCHAR(128) NOT NULL, - meta_value VARCHAR(4000) NULL, - target_id NUMERIC(19) NOT NULL, - PRIMARY KEY (meta_key, target_id) + meta_key VARCHAR(128) NOT NULL, + meta_value VARCHAR(4000) NULL, + target_id NUMERIC(19) NOT NULL, + PRIMARY KEY (meta_key, target_id) ); -ALTER TABLE sp_target_metadata ADD CONSTRAINT fk_metadata_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_target_metadata + ADD CONSTRAINT fk_metadata_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/hawkbit-jpa-defaults.properties b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/hawkbit-jpa-defaults.properties index 7e158e4e0..c479402cf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/hawkbit-jpa-defaults.properties +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/hawkbit-jpa-defaults.properties @@ -7,9 +7,7 @@ # # SPDX-License-Identifier: EPL-2.0 # - spring.main.allow-bean-definition-overriding=true - ### JPA / Datasource - START spring.jpa.database=H2 spring.jpa.show-sql=false diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/AbstractRemoteEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/AbstractRemoteEventTest.java index 3bc9fe340..10cf19aba 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/AbstractRemoteEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/AbstractRemoteEventTest.java @@ -14,6 +14,8 @@ import static org.junit.jupiter.api.Assertions.fail; import java.util.LinkedHashMap; import java.util.Map; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.hawkbit.event.BusProtoStuffMessageConverter; import org.eclipse.hawkbit.repository.event.TenantAwareEvent; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -32,9 +34,6 @@ import org.springframework.util.ClassUtils; import org.springframework.util.MimeType; import org.springframework.util.MimeTypeUtils; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * Test the remote entity events. */ @@ -56,6 +55,23 @@ public abstract class AbstractRemoteEventTest extends AbstractJpaIntegrationTest } + protected Message createMessageWithImmutableHeader(final TenantAwareEvent event) { + final Map headers = new LinkedHashMap<>(); + return busProtoStuffMessageConverter.toMessage(event, new MessageHeaders(headers)); + } + + @SuppressWarnings("unchecked") + protected T createJacksonEvent(final T event) { + final Message message = createJsonMessage(event); + return (T) jacksonMessageConverter.fromMessage(message, event.getClass()); + } + + @SuppressWarnings("unchecked") + protected T createProtoStuffEvent(final T event) { + final Message message = createProtoStuffMessage(event); + return (T) busProtoStuffMessageConverter.fromMessage(message, event.getClass()); + } + private Message createProtoStuffMessage(final TenantAwareEvent event) { final Map headers = new LinkedHashMap<>(); headers.put(MessageHeaders.CONTENT_TYPE, BusProtoStuffMessageConverter.APPLICATION_BINARY_PROTOSTUFF); @@ -74,21 +90,4 @@ public abstract class AbstractRemoteEventTest extends AbstractJpaIntegrationTest } return null; } - - protected Message createMessageWithImmutableHeader(final TenantAwareEvent event) { - final Map headers = new LinkedHashMap<>(); - return busProtoStuffMessageConverter.toMessage(event, new MessageHeaders(headers)); - } - - @SuppressWarnings("unchecked") - protected T createJacksonEvent(final T event) { - final Message message = createJsonMessage(event); - return (T) jacksonMessageConverter.fromMessage(message, event.getClass()); - } - - @SuppressWarnings("unchecked") - protected T createProtoStuffEvent(final T event) { - final Message message = createProtoStuffMessage(event); - return (T) busProtoStuffMessageConverter.fromMessage(message, event.getClass()); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteIdEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteIdEventTest.java index 6ff00c873..6af751056 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteIdEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteIdEventTest.java @@ -18,10 +18,8 @@ import java.util.Arrays; import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; - import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteTenantAwareEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteTenantAwareEventTest.java index db9e7f7ae..2e14f551f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteTenantAwareEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteTenantAwareEventTest.java @@ -15,6 +15,9 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionType; @@ -23,10 +26,6 @@ import org.eclipse.hawkbit.repository.model.ActionProperties; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.junit.jupiter.api.Test; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RemoteTenantAwareEvent Tests") public class RemoteTenantAwareEventTest extends AbstractRemoteEventTest { @@ -53,16 +52,6 @@ public class RemoteTenantAwareEventTest extends AbstractRemoteEventTest { assertThat(remoteAssignEventJackson.getControllerIds()).containsExactlyElementsOf(controllerIds); } - private Action createAction(final String controllerId) { - long id = 1; - final JpaAction generateAction = new JpaAction(); - generateAction.setId(id++); - generateAction.setActionType(ActionType.FORCED); - generateAction.setTarget(testdataFactory.createTarget(controllerId)); - generateAction.setStatus(Status.RUNNING); - return generateAction; - } - @Test @Description("Verifies that a MultiActionCancelEvent can be properly serialized and deserialized") public void testMultiActionCancelEvent() { @@ -148,6 +137,16 @@ public class RemoteTenantAwareEventTest extends AbstractRemoteEventTest { assertCancelTargetAssignmentEvent(action, remoteEventJackson); } + private Action createAction(final String controllerId) { + long id = 1; + final JpaAction generateAction = new JpaAction(); + generateAction.setId(id++); + generateAction.setActionType(ActionType.FORCED); + generateAction.setTarget(testdataFactory.createTarget(controllerId)); + generateAction.setStatus(Status.RUNNING); + return generateAction; + } + private void assertTargetAssignDistributionSetEvent(final Action action, final TargetAssignDistributionSetEvent underTest) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractRemoteEntityEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractRemoteEntityEventTest.java index 5a4ed4c9a..d84fece72 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractRemoteEntityEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractRemoteEntityEventTest.java @@ -15,10 +15,9 @@ import static org.junit.jupiter.api.Assertions.fail; import java.lang.reflect.Constructor; import java.util.Arrays; -import org.eclipse.hawkbit.repository.event.remote.AbstractRemoteEventTest; - import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.eclipse.hawkbit.repository.event.remote.AbstractRemoteEventTest; /** * Test the remote entity events. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/ActionEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/ActionEventTest.java index 1522cdea9..9792841d5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/ActionEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/ActionEventTest.java @@ -11,7 +11,9 @@ package org.eclipse.hawkbit.repository.event.remote.entity; import static org.assertj.core.api.Assertions.assertThat; -import net.bytebuddy.agent.builder.AgentBuilder; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionType; @@ -20,10 +22,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; import org.junit.jupiter.api.Test; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Test the remote entity events. */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetCreatedEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetCreatedEventTest.java index 73b0567cd..9e1ec0593 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetCreatedEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetCreatedEventTest.java @@ -9,11 +9,10 @@ */ package org.eclipse.hawkbit.repository.event.remote.entity; -import org.eclipse.hawkbit.repository.model.DistributionSet; - import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.eclipse.hawkbit.repository.model.DistributionSet; import org.junit.jupiter.api.Test; /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetTagEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetTagEventTest.java index 1db1ee759..868e2e6d5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetTagEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetTagEventTest.java @@ -9,12 +9,11 @@ */ package org.eclipse.hawkbit.repository.event.remote.entity; -import org.eclipse.hawkbit.repository.model.DistributionSetTag; -import org.junit.jupiter.api.Test; - import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.eclipse.hawkbit.repository.model.DistributionSetTag; +import org.junit.jupiter.api.Test; /** * Test the remote entity events. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetUpdatedEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetUpdatedEventTest.java index b79e682bc..1a7082546 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetUpdatedEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetUpdatedEventTest.java @@ -9,12 +9,11 @@ */ package org.eclipse.hawkbit.repository.event.remote.entity; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.junit.jupiter.api.Test; - import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.junit.jupiter.api.Test; /** * Test the remote entity events. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutEventTest.java index 2d9dde83b..07bd65d73 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutEventTest.java @@ -11,6 +11,9 @@ package org.eclipse.hawkbit.repository.event.remote.entity; import java.util.Collections; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition; @@ -18,10 +21,6 @@ import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.junit.jupiter.api.Test; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Test the remote entity events. */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java index db93d3bb6..861a5d019 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java @@ -14,6 +14,9 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.Collections; import java.util.UUID; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; @@ -22,10 +25,6 @@ import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.junit.jupiter.api.Test; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Test the remote entity events. */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/SoftwareModuleEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/SoftwareModuleEventTest.java index f1f00dad1..885dd31ac 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/SoftwareModuleEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/SoftwareModuleEventTest.java @@ -9,12 +9,11 @@ */ package org.eclipse.hawkbit.repository.event.remote.entity; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.junit.jupiter.api.Test; - import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.junit.jupiter.api.Test; /** * Test the remote entity events. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/TargetEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/TargetEventTest.java index 79d6434d2..96b012d9e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/TargetEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/TargetEventTest.java @@ -9,14 +9,11 @@ */ package org.eclipse.hawkbit.repository.event.remote.entity; -import static org.assertj.core.api.Assertions.assertThat; - -import org.eclipse.hawkbit.repository.model.Target; -import org.junit.jupiter.api.Test; - import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.eclipse.hawkbit.repository.model.Target; +import org.junit.jupiter.api.Test; /** * Test the remote entity events. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/TargetTagEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/TargetTagEventTest.java index 496e39bcb..875639d8e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/TargetTagEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/TargetTagEventTest.java @@ -9,12 +9,11 @@ */ package org.eclipse.hawkbit.repository.event.remote.entity; -import org.eclipse.hawkbit.repository.model.TargetTag; -import org.junit.jupiter.api.Test; - import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.eclipse.hawkbit.repository.model.TargetTag; +import org.junit.jupiter.api.Test; /** * Test the remote entity events. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java index d70a62860..9a3341486 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.jpa; +import static org.assertj.core.api.Assertions.assertThat; + import java.lang.reflect.Array; import java.util.Collection; import java.util.List; @@ -46,13 +48,11 @@ import org.eclipse.hawkbit.repository.jpa.repository.TenantMetaDataRepository; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetTag; -import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; -import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult; import org.eclipse.hawkbit.repository.test.TestConfiguration; @@ -69,8 +69,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.transaction.annotation.Transactional; -import static org.assertj.core.api.Assertions.assertThat; - @ContextConfiguration(classes = { RepositoryApplicationConfiguration.class, TestConfiguration.class }) @Import(TestChannelBinderConfiguration.class) @@ -141,6 +139,34 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest @Autowired private JpaProperties jpaProperties; + protected static void verifyThrownExceptionBy(final ThrowingCallable tc, final String objectType) { + Assertions.assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(tc) + .withMessageContaining(NOT_EXIST_ID).withMessageContaining(objectType); + } + + protected static List toList(final Iterable it) { + return StreamSupport.stream(it.spliterator(), false).map(e -> (T) e).toList(); + } + + protected static T[] toArray(final Iterable it, final Class type) { + final List list = toList(it); + final T[] array = (T[]) Array.newInstance(type, list.size()); + for (int i = 0; i < array.length; i++) { + array[i] = list.get(i); + } + return array; + } + + // just increase the opt lock revision if the instance in order to match it against locked db instance - not really locking + protected static void implicitLock(final DistributionSet set) { + ((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1); + } + + // just increase the opt lock revision if the instance in order to match it against locked db instance - not really locking + protected static void implicitLock(final SoftwareModule module) { + ((JpaSoftwareModule) module).setOptLockRevision(module.getOptLockRevision() + 1); + } + protected Database getDatabase() { return jpaProperties.getDatabase(); } @@ -150,15 +176,11 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest return toList(actionRepository.findByRolloutIdAndStatus(PAGE, rollout.getId(), actionStatus)); } - protected static void verifyThrownExceptionBy(final ThrowingCallable tc, final String objectType) { - Assertions.assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(tc) - .withMessageContaining(NOT_EXIST_ID).withMessageContaining(objectType); - } - protected List assignTag(final Collection targets, final TargetTag tag) { return targetManagement.assignTag( targets.stream().map(Target::getControllerId).collect(Collectors.toList()), tag.getId()); } + protected List unassignTag(final Collection targets, final TargetTag tag) { return targetManagement.unassignTag( targets.stream().map(Target::getControllerId).collect(Collectors.toList()), tag.getId()); @@ -169,6 +191,7 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest return distributionSetManagement.assignTag( sets.stream().map(DistributionSet::getId).collect(Collectors.toList()), tag.getId()); } + protected List unassignTag(final Collection sets, final DistributionSetTag tag) { return distributionSetManagement.unassignTag( @@ -180,7 +203,8 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest targets.stream().map(Target::getControllerId).collect(Collectors.toList()), type.getId()); } - protected void assertRollout(final Rollout rollout, final boolean dynamic, final Rollout.RolloutStatus status, final int groupCreated, final long totalTargets) { + protected void assertRollout(final Rollout rollout, final boolean dynamic, final Rollout.RolloutStatus status, final int groupCreated, + final long totalTargets) { final Rollout refreshed = refresh(rollout); assertThat(refreshed.isDynamic()).as("Is dynamic").isEqualTo(dynamic); assertThat(refreshed.getStatus()).as("Status").isEqualTo(status); @@ -188,7 +212,8 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest assertThat(refreshed.getTotalTargets()).as("Total targets").isEqualTo(totalTargets); } - protected void assertGroup(final RolloutGroup group, final boolean dynamic, final RolloutGroup.RolloutGroupStatus status, final long totalTargets) { + protected void assertGroup(final RolloutGroup group, final boolean dynamic, final RolloutGroup.RolloutGroupStatus status, + final long totalTargets) { final RolloutGroup refreshed = refresh(group); assertThat(refreshed.isDynamic()).as("Is dynamic").isEqualTo(dynamic); assertThat(refreshed.getStatus()).as("Status").isEqualTo(status); @@ -215,34 +240,11 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest return targetManagement.getTagsByControllerId(controllerId); } - private JpaRollout refresh(final Rollout rollout) { - return rolloutRepository.findById(rollout.getId()).get(); - } - protected JpaRolloutGroup refresh(final RolloutGroup group) { return rolloutGroupRepository.findById(group.getId()).get(); } - protected static List toList(final Iterable it) { - return StreamSupport.stream(it.spliterator(), false).map(e -> (T)e).toList(); - } - - protected static T[] toArray(final Iterable it, final Class type) { - final List list = toList(it); - final T[] array = (T[])Array.newInstance(type, list.size()); - for (int i = 0; i < array.length; i++) { - array[i] = list.get(i); - } - return array; - } - - // just increase the opt lock revision if the instance in order to match it against locked db instance - not really locking - protected static void implicitLock(final DistributionSet set) { - ((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1); - } - - // just increase the opt lock revision if the instance in order to match it against locked db instance - not really locking - protected static void implicitLock(final SoftwareModule module) { - ((JpaSoftwareModule) module).setOptLockRevision(module.getOptLockRevision() + 1); + private JpaRollout refresh(final Rollout rollout) { + return rolloutRepository.findById(rollout.getId()).get(); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java index c19693d5c..dd1338107 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ConcurrentDistributionSetInvalidationTest.java @@ -19,6 +19,9 @@ import java.time.Duration; import java.util.Collections; import java.util.concurrent.TimeUnit; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.awaitility.Awaitility; import org.eclipse.hawkbit.repository.exception.StopRolloutException; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; @@ -40,21 +43,59 @@ import org.springframework.context.annotation.Primary; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Test class testing the invalidation of a {@link DistributionSet} while the * handle rollouts is ongoing. - * */ @Feature("Component Tests - Repository") @Story("Concurrent Distribution Set invalidation") @ContextConfiguration(classes = ConcurrentDistributionSetInvalidationTest.Config.class) @TestPropertySource(properties = { "hawkbit.server.repository.dsInvalidationLockTimeout=1" }) public class ConcurrentDistributionSetInvalidationTest extends AbstractJpaIntegrationTest { - + + @Test + @Description("Verify that a large rollout causes a timeout when trying to invalidate a distribution set") + public void verifyInvalidateDistributionSetWithLargeRolloutThrowsException() throws Exception { + final DistributionSet distributionSet = testdataFactory.createDistributionSet(); + final Rollout rollout = createRollout(distributionSet); + final String tenant = tenantAware.getCurrentTenant(); + + // run in new Thread so that the invalidation can be executed in + // parallel + new Thread(() -> systemSecurityContext.runAsSystemAsTenant(() -> { + rolloutHandler.handleAll(); + return 0; + }, tenant)).start(); + + // wait until at least one RolloutGroup is created, as this means that + // the thread has started and has acquired the lock + Awaitility.await().atMost(Duration.ofSeconds(5)) + .pollInterval(Duration.ofMillis(100)) + .until(() -> tenantAware.runAsTenant(tenant, () -> systemSecurityContext + .runAsSystem(() -> rolloutGroupManagement.findByRollout(PAGE, rollout.getId()).getSize() > 0))); + + assertThatExceptionOfType(StopRolloutException.class) + .as("Invalidation of distributionSet should throw an exception") + .isThrownBy(() -> distributionSetInvalidationManagement.invalidateDistributionSet( + new DistributionSetInvalidation(Collections.singletonList(distributionSet.getId()), + CancelationType.SOFT, true))); + } + + private Rollout createRollout(final DistributionSet distributionSet) { + testdataFactory.createTargets( + quotaManagement.getMaxTargetsPerRolloutGroup() * quotaManagement.getMaxRolloutGroupsPerRollout(), + "verifyInvalidateDistributionSetWithLargeRolloutThrowsException"); + final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults() + .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "50") + .errorCondition(RolloutGroupErrorCondition.THRESHOLD, "80") + .errorAction(RolloutGroupErrorAction.PAUSE, null).build(); + + return rolloutManagement.create(entityFactory.rollout().create() + .name("verifyInvalidateDistributionSetWithLargeRolloutThrowsException").description("desc") + .targetFilterQuery("name==*").distributionSetId(distributionSet).actionType(ActionType.FORCED), + quotaManagement.getMaxRolloutGroupsPerRollout(), false, conditions); + } + @Configuration static class Config { @@ -80,47 +121,4 @@ public class ConcurrentDistributionSetInvalidationTest extends AbstractJpaIntegr } } - @Test - @Description("Verify that a large rollout causes a timeout when trying to invalidate a distribution set") - public void verifyInvalidateDistributionSetWithLargeRolloutThrowsException() throws Exception { - final DistributionSet distributionSet = testdataFactory.createDistributionSet(); - final Rollout rollout = createRollout(distributionSet); - final String tenant = tenantAware.getCurrentTenant(); - - // run in new Thread so that the invalidation can be executed in - // parallel - new Thread(() -> systemSecurityContext.runAsSystemAsTenant(() -> { - rolloutHandler.handleAll(); - return 0; - }, tenant)).start(); - - // wait until at least one RolloutGroup is created, as this means that - // the thread has started and has acquired the lock - Awaitility.await().atMost(Duration.ofSeconds(5)) - .pollInterval(Duration.ofMillis(100)) - .until(() -> tenantAware.runAsTenant(tenant, () -> systemSecurityContext - .runAsSystem(() -> rolloutGroupManagement.findByRollout(PAGE, rollout.getId()).getSize() > 0))); - - assertThatExceptionOfType(StopRolloutException.class) - .as("Invalidation of distributionSet should throw an exception") - .isThrownBy(() -> distributionSetInvalidationManagement.invalidateDistributionSet( - new DistributionSetInvalidation(Collections.singletonList(distributionSet.getId()), - CancelationType.SOFT, true))); - } - - private Rollout createRollout(final DistributionSet distributionSet) { - testdataFactory.createTargets( - quotaManagement.getMaxTargetsPerRolloutGroup() * quotaManagement.getMaxRolloutGroupsPerRollout(), - "verifyInvalidateDistributionSetWithLargeRolloutThrowsException"); - final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults() - .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "50") - .errorCondition(RolloutGroupErrorCondition.THRESHOLD, "80") - .errorAction(RolloutGroupErrorAction.PAUSE, null).build(); - - return rolloutManagement.create(entityFactory.rollout().create() - .name("verifyInvalidateDistributionSetWithLargeRolloutThrowsException").description("desc") - .targetFilterQuery("name==*").distributionSetId(distributionSet).actionType(ActionType.FORCED), - quotaManagement.getMaxRolloutGroupsPerRollout(), false, conditions); - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/HawkBitEclipseLinkJpaDialectTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/HawkBitEclipseLinkJpaDialectTest.java index cb8ef4e1a..119a4a5f1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/HawkBitEclipseLinkJpaDialectTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/HawkBitEclipseLinkJpaDialectTest.java @@ -18,21 +18,20 @@ import java.sql.SQLException; import jakarta.persistence.OptimisticLockException; import jakarta.persistence.PersistenceException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.junit.jupiter.api.Test; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.UncategorizedDataAccessException; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Mapping tests for {@link HawkBitEclipseLinkJpaDialect}. - * */ @Feature("Unit Tests - Repository") @Story("Exception handling") public class HawkBitEclipseLinkJpaDialectTest { + private final HawkBitEclipseLinkJpaDialect hawkBitEclipseLinkJpaDialectUnderTest = new HawkBitEclipseLinkJpaDialect(); @Test @@ -40,7 +39,7 @@ public class HawkBitEclipseLinkJpaDialectTest { public void jpaOptimisticLockExceptionIsConcurrencyFailureException() { assertThat( hawkBitEclipseLinkJpaDialectUnderTest.translateExceptionIfPossible(mock(OptimisticLockException.class))) - .isInstanceOf(ConcurrencyFailureException.class); + .isInstanceOf(ConcurrencyFailureException.class); } @Test diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RandomGeneratedInputStream.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RandomGeneratedInputStream.java index b62ca5b5d..bbf697dd7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RandomGeneratedInputStream.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RandomGeneratedInputStream.java @@ -15,8 +15,6 @@ import java.security.SecureRandom; import java.util.Random; /** - * - * * */ public class RandomGeneratedInputStream extends InputStream { @@ -30,8 +28,7 @@ public class RandomGeneratedInputStream extends InputStream { private long index; /** - * @param size - * target size of the stream [byte] + * @param size target size of the stream [byte] */ public RandomGeneratedInputStream(final long size) { this.size = size; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/context/ContextAwareTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/context/ContextAwareTest.java index 92b6a5f6a..738c99670 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/context/ContextAwareTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/context/ContextAwareTest.java @@ -15,6 +15,9 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -26,10 +29,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; - -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/AbstractAccessControllerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/AbstractAccessControllerTest.java index c5bb514b6..2d694c5ff 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/AbstractAccessControllerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/AbstractAccessControllerTest.java @@ -38,14 +38,10 @@ public abstract class AbstractAccessControllerTest extends AbstractJpaIntegratio @Autowired protected TestAccessControlManger testAccessControlManger; - @BeforeEach - void beforeEach() { - testAccessControlManger.deleteAllRules(); - } - - @AfterEach - void afterEach() { - testAccessControlManger.deleteAllRules(); + protected static List merge(final List lists0, final List list1) { + final List merge = new ArrayList<>(lists0); + merge.addAll(list1); + return merge; } protected void permitAllOperations(final AccessController.Operation operation) { @@ -57,6 +53,16 @@ public abstract class AbstractAccessControllerTest extends AbstractJpaIntegratio JpaDistributionSet.class, operation, Specification.where(null), type -> true); } + @BeforeEach + void beforeEach() { + testAccessControlManger.deleteAllRules(); + } + + @AfterEach + void afterEach() { + testAccessControlManger.deleteAllRules(); + } + public static class AccessControlTestConfig { private final ContextAware contextAware = new SecurityContextTenantAware((tenant, username) -> List.of()); @@ -77,7 +83,8 @@ public abstract class AbstractAccessControllerTest extends AbstractJpaIntegratio @Override public Optional> getAccessRules(final Operation operation) { - if (contextAware.getCurrentTenant() != null && SecurityContextTenantAware.SYSTEM_USER.equals(contextAware.getCurrentUsername())) { + if (contextAware.getCurrentTenant() != null && SecurityContextTenantAware.SYSTEM_USER.equals( + contextAware.getCurrentUsername())) { // as tenant, no restrictions return Optional.empty(); } @@ -104,7 +111,8 @@ public abstract class AbstractAccessControllerTest extends AbstractJpaIntegratio @Override public Optional> getAccessRules(final Operation operation) { - if (contextAware.getCurrentTenant() != null && SecurityContextTenantAware.SYSTEM_USER.equals(contextAware.getCurrentUsername())) { + if (contextAware.getCurrentTenant() != null && SecurityContextTenantAware.SYSTEM_USER.equals( + contextAware.getCurrentUsername())) { // as tenant, no restrictions return Optional.empty(); } @@ -131,7 +139,8 @@ public abstract class AbstractAccessControllerTest extends AbstractJpaIntegratio @Override public Optional> getAccessRules(final Operation operation) { - if (contextAware.getCurrentTenant() != null && SecurityContextTenantAware.SYSTEM_USER.equals(contextAware.getCurrentUsername())) { + if (contextAware.getCurrentTenant() != null && SecurityContextTenantAware.SYSTEM_USER.equals( + contextAware.getCurrentUsername())) { // as tenant, no restrictions return Optional.empty(); } @@ -151,10 +160,4 @@ public abstract class AbstractAccessControllerTest extends AbstractJpaIntegratio }; } } - - protected static List merge(final List lists0, final List list1) { - final List merge = new ArrayList<>(lists0); - merge.addAll(list1); - return merge; - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/DistributionSetAccessControllerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/DistributionSetAccessControllerTest.java index 1aed67652..07b4fe931 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/DistributionSetAccessControllerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/DistributionSetAccessControllerTest.java @@ -139,8 +139,8 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest { // verify distributionSetManagement#assignSoftwareModules assertThat(distributionSetManagement.assignSoftwareModules(permitted.getId(), Collections.singletonList(swModule.getId()))).satisfies(ds -> { - assertThat(ds.getModules().stream().map(Identifiable::getId).toList()).contains(swModule.getId()); - }); + assertThat(ds.getModules().stream().map(Identifiable::getId).toList()).contains(swModule.getId()); + }); assertThatThrownBy(() -> { distributionSetManagement.assignSoftwareModules(readOnly.getId(), Collections.singletonList(swModule.getId())); @@ -226,8 +226,8 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest { // assignment is denied for readOnlyTarget (read, but no update permissions) assertThatThrownBy(() -> - distributionSetManagement.unassignTag(Collections.singletonList(readOnly.getId()), dsTag.getId())) - .as("Missing update permissions for target to toggle tag assignment.") + distributionSetManagement.unassignTag(Collections.singletonList(readOnly.getId()), dsTag.getId())) + .as("Missing update permissions for target to toggle tag assignment.") .isInstanceOf(InsufficientPermissionException.class); // assignment is denied for readOnlyTarget (read, but no update permissions) @@ -296,7 +296,6 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest { }).isInstanceOf(EntityNotFoundException.class); } - private void defineAccess(final AccessController.Operation operation, final DistributionSet... distributionSets) { defineAccess(operation, List.of(distributionSets)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TargetAccessControllerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TargetAccessControllerTest.java index 06d4ea4b0..f803b9d2f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TargetAccessControllerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TargetAccessControllerTest.java @@ -16,6 +16,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; @@ -38,10 +41,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Access Control") @Story("Test Target Access Controller") class TargetAccessControllerTest extends AbstractAccessControllerTest { @@ -328,11 +327,11 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest { assertThat(content).hasSize(updateTargets.size()); final List rolloutTargets = content.stream().flatMap( - group -> rolloutGroupManagement.findTargetsOfRolloutGroup(Pageable.unpaged(), group.getId()).get()) + group -> rolloutGroupManagement.findTargetsOfRolloutGroup(Pageable.unpaged(), group.getId()).get()) .toList(); assertThat(rolloutTargets).hasSize(updateTargets.size()).allMatch( - target -> updateTargets.stream().anyMatch(readTarget -> readTarget.getId().equals(target.getId()))) + target -> updateTargets.stream().anyMatch(readTarget -> readTarget.getId().equals(target.getId()))) .noneMatch(target -> readTargets.stream() .anyMatch(readTarget -> readTarget.getId().equals(target.getId()))) .noneMatch(target -> hiddenTargets.stream() @@ -358,7 +357,8 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest { "hidden5"); defineAccess(AccessController.Operation.UPDATE, updateTargets); - defineAccess(AccessController.Operation.READ, merge(updateTargets, readTargets));; + defineAccess(AccessController.Operation.READ, merge(updateTargets, readTargets)); + ; final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement .create(entityFactory.targetFilterQuery().create().name("testName").query("id==*")); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TargetTypeAccessControllerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TargetTypeAccessControllerTest.java index e9393c665..11e6ad6b0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TargetTypeAccessControllerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TargetTypeAccessControllerTest.java @@ -59,7 +59,7 @@ class TargetTypeAccessControllerTest extends AbstractAccessControllerTest { // verify targetTypeManagement#findByName assertThat(targetTypeManagement.findByName(Pageable.unpaged(), permittedTargetType.getName()).getContent()) .hasSize(1).satisfies(results -> - assertThat(results.get(0).getId()).isEqualTo(permittedTargetType.getId())); + assertThat(results.get(0).getId()).isEqualTo(permittedTargetType.getId())); assertThat(targetTypeManagement.findByName(Pageable.unpaged(), hiddenTargetType.getName())).isEmpty(); // verify targetTypeManagement#count @@ -144,7 +144,7 @@ class TargetTypeAccessControllerTest extends AbstractAccessControllerTest { // verify targetTypeManagement#update for readOnlyTargetType is not possible assertThatThrownBy(() -> targetTypeManagement.update(entityFactory.targetType().update(readOnlyTargetType.getId()) - .name(readOnlyTargetType.getName() + "/new").description("newDesc"))) + .name(readOnlyTargetType.getName() + "/new").description("newDesc"))) .isInstanceOf(InsufficientPermissionException.class); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TestAccessControlManger.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TestAccessControlManger.java index d0156b20a..bb53f1242 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TestAccessControlManger.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/controller/TestAccessControlManger.java @@ -20,8 +20,6 @@ import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.springframework.data.jpa.domain.Specification; -import jakarta.persistence.criteria.CriteriaQuery; - public class TestAccessControlManger { private final Map, AccessRule> accessRules = new HashMap<>(); @@ -36,22 +34,20 @@ public class TestAccessControlManger { accessRules.put(new AccessRuleId(ruleClass, operation), new AccessRule(specification, check)); } - public Specification getAccessRule(final Class ruleClass, final AccessController.Operation operation) { - @SuppressWarnings("unchecked") - final AccessRule accessRule = (AccessRule) accessRules.getOrDefault(new AccessRuleId(ruleClass, operation), null); + public Specification getAccessRule(final Class ruleClass, + final AccessController.Operation operation) { + @SuppressWarnings("unchecked") final AccessRule accessRule = (AccessRule) accessRules.getOrDefault( + new AccessRuleId(ruleClass, operation), null); if (accessRule == null) { return nop(); } else { return accessRule.specification(); } } - private static Specification nop() { - return (targetRoot, query, cb) -> cb.equal(targetRoot.get(AbstractJpaBaseEntity_.id), -1); - } public void assertOperation(final Class ruleClass, final AccessController.Operation operation, final List entities) { - @SuppressWarnings("unchecked") - final AccessRule accessRule = (AccessRule) accessRules.getOrDefault(new AccessRuleId(ruleClass, operation), null); + @SuppressWarnings("unchecked") final AccessRule accessRule = (AccessRule) accessRules.getOrDefault( + new AccessRuleId(ruleClass, operation), null); if (accessRule == null) { throw new InsufficientPermissionException("No access define - reject all"); } else { @@ -65,6 +61,11 @@ public class TestAccessControlManger { } } + private static Specification nop() { + return (targetRoot, query, cb) -> cb.equal(targetRoot.get(AbstractJpaBaseEntity_.id), -1); + } + private record AccessRuleId(Class ruleClass, AccessController.Operation operation) {} - private record AccessRule (Specification specification, Predicate checker) {} + + private record AccessRule(Specification specification, Predicate checker) {} } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java index 3d6c44408..83c05ff54 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java @@ -20,6 +20,10 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -42,14 +46,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; - /** * Test class for {@link AutoAssignChecker}. - * */ @Feature("Component Tests - Repository") @Story("Auto assign checker") @@ -236,14 +234,6 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { verifyThatTargetsNotHaveDistributionSetAssignment(toAssignDs, targets.subList(1, 25)); } - private static Stream confirmationOptions() { - return Stream.of( // - Arguments.of(true, true, Status.WAIT_FOR_CONFIRMATION), // - Arguments.of(true, false, Status.RUNNING), // - Arguments.of(false, true, Status.RUNNING), // - Arguments.of(false, false, Status.RUNNING)); - } - @Test @Description("Test auto assignment of an incomplete DS to filtered targets, that causes failures") void checkAutoAssignWithFailures() { @@ -261,7 +251,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { // fail assertThatExceptionOfType(IncompleteDistributionSetException.class).isThrownBy(() -> { final Long filterId = targetFilterQueryManagement.create( - entityFactory.targetFilterQuery().create().name("filterA").query("id==" + targetDsFIdPref + "*")) + entityFactory.targetFilterQuery().create().name("filterA").query("id==" + targetDsFIdPref + "*")) .getId(); targetFilterQueryManagement .updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(setF.getId())); @@ -295,71 +285,6 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { } - /** - * @param set - * the expected distribution set - * @param targets - * the targets that should have it - */ - @Step - private void verifyThatTargetsHaveDistributionSetAssignment(final DistributionSet set, final List targets, - final int count) { - final List targetIds = targets.stream().map(Target::getId).collect(Collectors.toList()); - - final Slice targetsAll = targetManagement.findAll(PAGE); - assertThat(targetsAll).as("Count of targets").hasSize(count); - - for (final Target target : targetsAll) { - if (targetIds.contains(target.getId())) { - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()) - .as("assigned DS").isEqualTo(set); - } - } - } - - @Step - private void verifyThatTargetsHaveDistributionSetAssignedAndActionStatus(final DistributionSet set, - final List targets, final Action.Status status) { - final List targetIds = targets.stream().map(Target::getControllerId).collect(Collectors.toList()); - final List targetsWithAssignedDS = targetManagement.findByAssignedDistributionSet(PAGE, set.getId()) - .getContent(); - assertThat(targetsWithAssignedDS).isNotEmpty(); - assertThat(targetsWithAssignedDS).allMatch(target -> targetIds.contains(target.getControllerId())); - - final List actionsByDs = findActionsByDistributionSet(PAGE, set.getId()) - .getContent(); - - assertThat(actionsByDs).hasSize(targets.size()); - assertThat(actionsByDs).allMatch(action -> action.getStatus() == status); - } - - @Step - private void verifyThatTargetsNotHaveDistributionSetAssignment(final DistributionSet set, - final List targets) { - final List targetIds = targets.stream().map(Target::getId).collect(Collectors.toList()); - - final Slice targetsAll = targetManagement.findAll(PAGE); - - for (final Target target : targetsAll) { - if (targetIds.contains(target.getId())) { - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).isEmpty(); - } - } - - } - - @Step - private void verifyThatCreatedActionsAreInitiatedByCurrentUser(final TargetFilterQuery targetFilterQuery, - final DistributionSet distributionSet, final List targets) { - final Set targetIds = targets.stream().map(Target::getControllerId).collect(Collectors.toSet()); - - findActionsByDistributionSet(Pageable.unpaged(), distributionSet.getId()).stream() - .filter(a -> targetIds.contains(a.getTarget().getControllerId())) - .forEach(a -> assertThat(a.getInitiatedBy()) - .as("Action should be initiated by the user who initiated the auto assignment") - .isEqualTo(targetFilterQuery.getAutoAssignInitiatedBy())); - } - @Test @Description("Test auto assignment of a distribution set with FORCED, SOFT and DOWNLOAD_ONLY action types") void checkAutoAssignWithDifferentActionTypes() { @@ -389,29 +314,6 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { verifyThatTargetsHaveAssignmentActionType(ActionType.DOWNLOAD_ONLY, targetsC); } - @Step - private List createTargetsAndAutoAssignDistSet(final String prefix, final int targetCount, - final DistributionSet distributionSet, final ActionType actionType) { - - final List targets = testdataFactory.createTargets(targetCount, "target" + prefix, - prefix.concat(" description")); - targetFilterQueryManagement.create( - entityFactory.targetFilterQuery().create().name("filter" + prefix).query("id==target" + prefix + "*") - .autoAssignDistributionSet(distributionSet).autoAssignActionType(actionType)); - - return targets; - } - - @Step - private void verifyThatTargetsHaveAssignmentActionType(final ActionType actionType, final List targets) { - final List actions = targets.stream().map(Target::getControllerId).flatMap( - controllerId -> deploymentManagement.findActionsByTarget(controllerId, PAGE).getContent().stream()) - .collect(Collectors.toList()); - - assertThat(actions).hasSize(targets.size()); - assertThat(actions).allMatch(action -> action.getActionType().equals(actionType)); - } - @Test @Description("An auto assignment target filter with weight creates actions with weights") void actionsWithWeightAreCreated() throws Exception { @@ -497,6 +399,100 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { assertThat(actionTargets).containsExactlyInAnyOrderElementsOf(compatibleTargets); } + private static Stream confirmationOptions() { + return Stream.of( // + Arguments.of(true, true, Status.WAIT_FOR_CONFIRMATION), // + Arguments.of(true, false, Status.RUNNING), // + Arguments.of(false, true, Status.RUNNING), // + Arguments.of(false, false, Status.RUNNING)); + } + + /** + * @param set the expected distribution set + * @param targets the targets that should have it + */ + @Step + private void verifyThatTargetsHaveDistributionSetAssignment(final DistributionSet set, final List targets, + final int count) { + final List targetIds = targets.stream().map(Target::getId).collect(Collectors.toList()); + + final Slice targetsAll = targetManagement.findAll(PAGE); + assertThat(targetsAll).as("Count of targets").hasSize(count); + + for (final Target target : targetsAll) { + if (targetIds.contains(target.getId())) { + assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()) + .as("assigned DS").isEqualTo(set); + } + } + } + + @Step + private void verifyThatTargetsHaveDistributionSetAssignedAndActionStatus(final DistributionSet set, + final List targets, final Action.Status status) { + final List targetIds = targets.stream().map(Target::getControllerId).collect(Collectors.toList()); + final List targetsWithAssignedDS = targetManagement.findByAssignedDistributionSet(PAGE, set.getId()) + .getContent(); + assertThat(targetsWithAssignedDS).isNotEmpty(); + assertThat(targetsWithAssignedDS).allMatch(target -> targetIds.contains(target.getControllerId())); + + final List actionsByDs = findActionsByDistributionSet(PAGE, set.getId()) + .getContent(); + + assertThat(actionsByDs).hasSize(targets.size()); + assertThat(actionsByDs).allMatch(action -> action.getStatus() == status); + } + + @Step + private void verifyThatTargetsNotHaveDistributionSetAssignment(final DistributionSet set, + final List targets) { + final List targetIds = targets.stream().map(Target::getId).collect(Collectors.toList()); + + final Slice targetsAll = targetManagement.findAll(PAGE); + + for (final Target target : targetsAll) { + if (targetIds.contains(target.getId())) { + assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).isEmpty(); + } + } + + } + + @Step + private void verifyThatCreatedActionsAreInitiatedByCurrentUser(final TargetFilterQuery targetFilterQuery, + final DistributionSet distributionSet, final List targets) { + final Set targetIds = targets.stream().map(Target::getControllerId).collect(Collectors.toSet()); + + findActionsByDistributionSet(Pageable.unpaged(), distributionSet.getId()).stream() + .filter(a -> targetIds.contains(a.getTarget().getControllerId())) + .forEach(a -> assertThat(a.getInitiatedBy()) + .as("Action should be initiated by the user who initiated the auto assignment") + .isEqualTo(targetFilterQuery.getAutoAssignInitiatedBy())); + } + + @Step + private List createTargetsAndAutoAssignDistSet(final String prefix, final int targetCount, + final DistributionSet distributionSet, final ActionType actionType) { + + final List targets = testdataFactory.createTargets(targetCount, "target" + prefix, + prefix.concat(" description")); + targetFilterQueryManagement.create( + entityFactory.targetFilterQuery().create().name("filter" + prefix).query("id==target" + prefix + "*") + .autoAssignDistributionSet(distributionSet).autoAssignActionType(actionType)); + + return targets; + } + + @Step + private void verifyThatTargetsHaveAssignmentActionType(final ActionType actionType, final List targets) { + final List actions = targets.stream().map(Target::getControllerId).flatMap( + controllerId -> deploymentManagement.findActionsByTarget(controllerId, PAGE).getContent().stream()) + .collect(Collectors.toList()); + + assertThat(actions).hasSize(targets.size()); + assertThat(actions).allMatch(action -> action.getActionType().equals(actionType)); + } + private Slice findActionsByDistributionSet(final Pageable pageable, final long distributionSetId) { return actionRepository .findAll(ActionSpecifications.byDistributionSetId(distributionSetId), pageable) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java index 9f755b18d..9caf7e961 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java @@ -11,13 +11,19 @@ package org.eclipse.hawkbit.repository.jpa.autoassign; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.ContextAware; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; @@ -36,14 +42,11 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.domain.SliceImpl; import org.springframework.transaction.PlatformTransactionManager; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Unit Tests - Repository") @Story("Auto assign checker") @ExtendWith(MockitoExtension.class) class AutoAssignCheckerTest { + @Mock private TargetFilterQueryManagement targetFilterQueryManagement; @Mock @@ -86,13 +89,6 @@ class AutoAssignCheckerTest { Mockito.verifyNoMoreInteractions(deploymentManagement); } - private ArgumentMatcher> deployReqMatcher(final String target, final long ds) { - return requests -> { - final DeploymentRequest request = requests.get(0); - return requests.size() == 1 && request.getDistributionSetId() == ds && request.getControllerId() == target; - }; - } - private static TargetFilterQuery mockFilterQuery(final long dsId) { final DistributionSet ds = mock(DistributionSet.class); when(ds.getId()).thenReturn(dsId); @@ -104,12 +100,6 @@ class AutoAssignCheckerTest { return filter; } - private void mockRunningAsNonSystem() { - when(contextAware.getCurrentTenant()).thenReturn(getRandomString()); - when(contextAware.runAsTenantAsUser(any(String.class), any(String.class), any(TenantAware.TenantRunner.class))) - .thenAnswer(i -> ((TenantAware.TenantRunner)i.getArgument(2)).run()); - } - private static long getRandomLong() { return ThreadLocalRandom.current().nextLong(); } @@ -118,4 +108,17 @@ class AutoAssignCheckerTest { return UUID.randomUUID().toString(); } + private ArgumentMatcher> deployReqMatcher(final String target, final long ds) { + return requests -> { + final DeploymentRequest request = requests.get(0); + return requests.size() == 1 && request.getDistributionSetId() == ds && request.getControllerId() == target; + }; + } + + private void mockRunningAsNonSystem() { + when(contextAware.getCurrentTenant()).thenReturn(getRandomString()); + when(contextAware.runAsTenantAsUser(any(String.class), any(String.class), any(TenantAware.TenantRunner.class))) + .thenAnswer(i -> ((TenantAware.TenantRunner) i.getArgument(2)).run()); + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java index 621d77aa2..561a21af4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java @@ -17,6 +17,9 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationPrope import java.util.Arrays; import java.util.stream.Collectors; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -25,13 +28,8 @@ import org.eclipse.hawkbit.repository.model.Target; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Test class for {@link AutoActionCleanup}. - * */ @Feature("Component Tests - Repository") @Story("Action cleanup handler") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoCleanupSchedulerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoCleanupSchedulerTest.java index 8575e7de4..78d012aca 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoCleanupSchedulerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoCleanupSchedulerTest.java @@ -14,19 +14,17 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.support.locks.LockRegistry; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Test class for {@link AutoCleanupScheduler}. - * */ @Feature("Component Tests - Repository") @Story("Auto cleanup scheduler") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/event/RepositoryEntityEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/event/RepositoryEntityEventTest.java index 8aa9e204a..c0d84637d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/event/RepositoryEntityEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/event/RepositoryEntityEventTest.java @@ -15,6 +15,9 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.assertj.core.api.Assertions; import org.eclipse.hawkbit.repository.event.TenantAwareEvent; import org.eclipse.hawkbit.repository.event.remote.DistributionSetDeletedEvent; @@ -44,10 +47,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.context.event.EventListener; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("Entity Events") @SpringBootTest(classes = { RepositoryTestConfiguration.class }, webEnvironment = SpringBootTest.WebEnvironment.NONE) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ActionTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ActionTest.java index 0abe1231f..dc7ba044c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ActionTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ActionTest.java @@ -11,16 +11,15 @@ package org.eclipse.hawkbit.repository.jpa.management; import static org.assertj.core.api.Assertions.assertThat; -import org.awaitility.Awaitility; -import org.eclipse.hawkbit.repository.jpa.model.JpaAction; -import org.eclipse.hawkbit.repository.model.Action.ActionType; -import org.junit.jupiter.api.Test; +import java.time.Duration; import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; - -import java.time.Duration; +import org.awaitility.Awaitility; +import org.eclipse.hawkbit.repository.jpa.model.JpaAction; +import org.eclipse.hawkbit.repository.model.Action.ActionType; +import org.junit.jupiter.api.Test; @Feature("Unit Tests - Repository") @Story("Deployment Management") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ArtifactManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ArtifactManagementTest.java index 324484a0c..cffe9392d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ArtifactManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ArtifactManagementTest.java @@ -27,6 +27,9 @@ import java.util.concurrent.Callable; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; @@ -56,10 +59,6 @@ import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Test class for {@link ArtifactManagement}. */ @@ -280,7 +279,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { final int artifactSize = 5 * 1024; try (final InputStream inputStream1 = new RandomGeneratedInputStream(artifactSize); - final InputStream inputStream2 = new RandomGeneratedInputStream(artifactSize)) { + final InputStream inputStream2 = new RandomGeneratedInputStream(artifactSize)) { final Artifact artifact1 = createArtifactForSoftwareModule("file1", sm.getId(), artifactSize, inputStream1); final Artifact artifact2 = createArtifactForSoftwareModule("file2", sm2.getId(), artifactSize, @@ -294,10 +293,10 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) - .isNotNull(); + .isNotNull(); assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact2.getSha1Hash())) - .isNotNull(); + .isNotNull(); artifactManagement.delete(artifact1.getId()); @@ -305,15 +304,15 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) - .isNull(); + .isNull(); assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact2.getSha1Hash())) - .isNotNull(); + .isNotNull(); artifactManagement.delete(artifact2.getId()); assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact2.getSha1Hash())) - .isNull(); + .isNull(); assertThat(artifactRepository.findAll()).hasSize(0); } @@ -345,19 +344,19 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) - .isNotNull(); + .isNotNull(); artifactManagement.delete(artifact1.getId()); assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) - .isNotNull(); + .isNotNull(); assertThat(artifactRepository.findAll()).hasSize(1); assertThat(artifactRepository.existsById(artifact1.getId())).isFalse(); artifactManagement.delete(artifact2.getId()); assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) - .isNull(); + .isNull(); assertThat(artifactRepository.findAll()).hasSize(0); } } @@ -422,7 +421,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat(runAsTenant(tenant1, () -> artifactRepository .countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(artifactTenant2.getSha1Hash(), tenant2))) - .isLessThanOrEqualTo(1); + .isLessThanOrEqualTo(1); runAsTenant(tenant2, () -> { artifactRepository.deleteById(artifactTenant2.getId()); return null; @@ -579,6 +578,10 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { } } + private static byte[] randomBytes(final int len) { + return RandomStringUtils.randomAlphanumeric(len).getBytes(); + } + private DbArtifactHash calcHashes(final byte[] input) throws NoSuchAlgorithmException { final String sha1Hash = toBase16Hash("SHA1", input); final String md5Hash = toBase16Hash("MD5", input); @@ -606,10 +609,6 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { return artifactManagement.create(new ArtifactUpload(inputStream, moduleId, filename, false, artifactSize)); } - private static byte[] randomBytes(final int len) { - return RandomStringUtils.randomAlphanumeric(len).getBytes(); - } - private T runAsTenant(final String tenant, final Callable callable) throws Exception { return SecurityContextSwitch.runAs(SecurityContextSwitch.withUserAndTenantAllSpPermissions("user", tenant), callable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ConfirmationManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ConfirmationManagementTest.java index fb8e764a8..988b3939d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ConfirmationManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ConfirmationManagementTest.java @@ -19,6 +19,9 @@ import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.exception.AutoConfirmationAlreadyActiveException; import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -29,10 +32,6 @@ import org.eclipse.hawkbit.repository.model.DeploymentRequestBuilder; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; import org.junit.jupiter.api.Test; - -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -40,7 +39,6 @@ import org.junit.jupiter.params.provider.MethodSource; /** * Test class testing the functionality of triggering a deployment of * {@link DistributionSet}s to {@link Target}s with AutoConfirmation active. - * */ @Feature("Component Tests - Repository") @Story("Confirmation Management") @@ -140,9 +138,9 @@ class ConfirmationManagementTest extends AbstractJpaIntegrationTest { assertThat(newAction.getStatus()).isEqualTo(Status.RUNNING); assertThatThrownBy(() -> confirmationManagement.confirmAction(actions.get(0).getId(), null, null)) - .isInstanceOf(InvalidConfirmationFeedbackException.class) - .matches(e -> ((InvalidConfirmationFeedbackException) e) - .getReason() == InvalidConfirmationFeedbackException.Reason.NOT_AWAITING_CONFIRMATION); + .isInstanceOf(InvalidConfirmationFeedbackException.class) + .matches(e -> ((InvalidConfirmationFeedbackException) e) + .getReason() == InvalidConfirmationFeedbackException.Reason.NOT_AWAITING_CONFIRMATION); } @Test @@ -152,9 +150,9 @@ class ConfirmationManagementTest extends AbstractJpaIntegrationTest { final Action action = prepareFinishedUpdate(); assertThatThrownBy(() -> confirmationManagement.confirmAction(action.getId(), null, null)) - .isInstanceOf(InvalidConfirmationFeedbackException.class) - .matches(e -> ((InvalidConfirmationFeedbackException) e) - .getReason() == InvalidConfirmationFeedbackException.Reason.ACTION_CLOSED); + .isInstanceOf(InvalidConfirmationFeedbackException.class) + .matches(e -> ((InvalidConfirmationFeedbackException) e) + .getReason() == InvalidConfirmationFeedbackException.Reason.ACTION_CLOSED); } @Test @@ -197,7 +195,7 @@ class ConfirmationManagementTest extends AbstractJpaIntegrationTest { final List actions = assignDistributionSets( Arrays.asList(toDeploymentRequest(controllerId, dsId), toDeploymentRequest(controllerId, dsId2))) - .stream().flatMap(s -> s.getAssignedEntity().stream()).collect(Collectors.toList()); + .stream().flatMap(s -> s.getAssignedEntity().stream()).collect(Collectors.toList()); assertThat(actions).hasSize(2); assertThat(confirmationManagement.findActiveActionsWaitingConfirmation(controllerId)).hasSize(2) @@ -276,11 +274,6 @@ class ConfirmationManagementTest extends AbstractJpaIntegrationTest { verifyAutoConfirmationIsDisabled(controllerId); } - private static Stream getAutoConfirmationArguments() { - return Stream.of(Arguments.of("TestUser", "TestRemark"), Arguments.of("TestUser", null), - Arguments.of(null, "TestRemark"), Arguments.of(null, null)); - } - @Test @Description("Verify activating already active auto confirmation will throw exception.") void verifyActivateAlreadyActiveAutoConfirmationThrowException() { @@ -305,13 +298,18 @@ class ConfirmationManagementTest extends AbstractJpaIntegrationTest { verifyAutoConfirmationIsDisabled(controllerId); } - private void verifyAutoConfirmationIsDisabled(final String controllerId) { - assertThat(targetManagement.getByControllerID(controllerId)) - .hasValueSatisfying(target -> assertThat(target.getAutoConfirmationStatus()).isNull()); + private static Stream getAutoConfirmationArguments() { + return Stream.of(Arguments.of("TestUser", "TestRemark"), Arguments.of("TestUser", null), + Arguments.of(null, "TestRemark"), Arguments.of(null, null)); } private static DeploymentRequest toDeploymentRequest(final String controllerId, final Long distributionSetId) { return new DeploymentRequestBuilder(controllerId, distributionSetId).setConfirmationRequired(true).build(); } + private void verifyAutoConfirmationIsDisabled(final String controllerId) { + assertThat(targetManagement.getByControllerID(controllerId)) + .hasValueSatisfying(target -> assertThat(target.getAutoConfirmationStatus()).isNull()); + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java index 8fab8f76b..db969d82f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java @@ -9,11 +9,37 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; +import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY; +import static org.eclipse.hawkbit.repository.test.util.TestdataFactory.DEFAULT_CONTROLLER_ID; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import jakarta.validation.ConstraintViolationException; + import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Step; import io.qameta.allure.Story; -import jakarta.validation.ConstraintViolationException; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.assertj.core.api.Assertions; @@ -66,31 +92,6 @@ import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.ConcurrencyFailureException; -import java.io.ByteArrayInputStream; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.Assertions.assertThatNoException; -import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE; -import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS; -import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; -import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY; -import static org.eclipse.hawkbit.repository.test.util.TestdataFactory.DEFAULT_CONTROLLER_ID; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @Feature("Component Tests - Repository") @Story("Controller Management") class ControllerManagementTest extends AbstractJpaIntegrationTest { @@ -98,6 +99,209 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { @Autowired private RepositoryProperties repositoryProperties; + @Test + @Description("Ensures that target attribute update fails if quota hits.") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), + @Expect(type = TargetUpdatedEvent.class, count = 2) }) + public void updateTargetAttributesFailsIfTooManyEntries() throws Exception { + final String controllerId = "test123"; + final int allowedAttributes = quotaManagement.getMaxAttributeEntriesPerTarget(); + testdataFactory.createTarget(controllerId); + + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> SecurityContextSwitch + .runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { + writeAttributes(controllerId, allowedAttributes + 1, "key", "value"); + return null; + })).withMessageContaining("" + allowedAttributes); + + // verify that no attributes have been written + assertThat(targetManagement.getControllerAttributes(controllerId)).isEmpty(); + + // Write allowed number of attributes twice with same key should result + // in update but work + SecurityContextSwitch.runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { + writeAttributes(controllerId, allowedAttributes, "key", "value1"); + writeAttributes(controllerId, allowedAttributes, "key", "value2"); + return null; + }); + assertThat(targetManagement.getControllerAttributes(controllerId)).hasSize(10); + + // Now rite one more + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> SecurityContextSwitch + .runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { + writeAttributes(controllerId, 1, "additional", "value1"); + return null; + })).withMessageContaining("" + allowedAttributes); + assertThat(targetManagement.getControllerAttributes(controllerId)).hasSize(10); + + } + + @Test + @Description("Checks if invalid values of attribute-key and attribute-value are handled correctly") + public void updateTargetAttributesFailsForInvalidAttributes() { + final String controllerId = "targetId123"; + testdataFactory.createTarget(controllerId); + + assertThatExceptionOfType(InvalidTargetAttributeException.class) + .as("Attribute with key too long should not be created") + .isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId, + Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_TOO_LONG, TargetTestData.ATTRIBUTE_VALUE_VALID), null)); + + assertThatExceptionOfType(InvalidTargetAttributeException.class) + .as("Attribute with key too long and value too long should not be created") + .isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId, + Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_TOO_LONG, TargetTestData.ATTRIBUTE_VALUE_TOO_LONG), null)); + + assertThatExceptionOfType(InvalidTargetAttributeException.class) + .as("Attribute with value too long should not be created") + .isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId, + Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_VALID, TargetTestData.ATTRIBUTE_VALUE_TOO_LONG), null)); + + assertThatExceptionOfType(InvalidTargetAttributeException.class) + .as("Attribute with key NULL should not be created").isThrownBy(() -> controllerManagement + .updateControllerAttributes(controllerId, + Collections.singletonMap(null, TargetTestData.ATTRIBUTE_VALUE_VALID), null)); + } + + @Test + @Description("Controller providing status entries fails if providing more than permitted by quota.") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), + @Expect(type = DistributionSetCreatedEvent.class, count = 1), + @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock + @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), + @Expect(type = TargetAssignDistributionSetEvent.class, count = 1) }) + public void controllerProvidesIntermediateFeedbackFailsIfQuotaHit() { + final int allowStatusEntries = 10; + final Long actionId = createTargetAndAssignDs(); + + // Fails as one entry is already in there from the assignment + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> SecurityContextSwitch + .runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { + writeStatus(actionId, allowStatusEntries); + return null; + })).withMessageContaining("" + allowStatusEntries); + + } + + @Test + @Description("Test to verify the storage and retrieval of action history.") + public void findMessagesByActionStatusId() { + final DistributionSet testDs = testdataFactory.createDistributionSet("1"); + final List testTarget = testdataFactory.createTargets(1); + + final Long actionId = getFirstAssignedActionId(assignDistributionSet(testDs, testTarget)); + + controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) + .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()) + .messages(List.of("proceeding message 1"))); + + final long createTime = System.currentTimeMillis(); + waitNextMillis(); + controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) + .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()) + .messages(List.of("proceeding message 2"))); + + final List messages = controllerManagement.getActionHistoryMessages(actionId, 2); + + assertThat(deploymentManagement.findActionStatusByAction(PAGE, actionId).getTotalElements()) + .as("Two action-states in total").isEqualTo(3L); + assertThat(messages.get(0)).as("Message of action-status").isEqualTo("proceeding message 2"); + assertThat(messages.get(1)).as("Message of action-status").isEqualTo("proceeding message 1"); + } + + @Test + @Description("Verifies that the quota specifying the maximum number of status entries per action is enforced.") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 2), + @Expect(type = DistributionSetCreatedEvent.class, count = 2), + @Expect(type = SoftwareModuleCreatedEvent.class, count = 6), + @Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), // implicit lock + @Expect(type = ActionCreatedEvent.class, count = 2), @Expect(type = TargetUpdatedEvent.class, count = 2), + @Expect(type = TargetAssignDistributionSetEvent.class, count = 2) }) + public void addActionStatusUpdatesUntilQuotaIsExceeded() { + + // any distribution set assignment causes 1 status entity to be created + final int maxStatusEntries = quotaManagement.getMaxStatusEntriesPerAction() - 1; + + // test for informational status + final Long actionId1 = getFirstAssignedActionId(assignDistributionSet( + testdataFactory.createDistributionSet("ds1"), testdataFactory.createTargets(1, "t1"))); + assertThat(actionId1).isNotNull(); + for (int i = 0; i < maxStatusEntries; ++i) { + controllerManagement.addInformationalActionStatus(entityFactory.actionStatus().create(actionId1) + .status(Status.WARNING).message("Msg " + i).occurredAt(System.currentTimeMillis())); + } + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> controllerManagement + .addInformationalActionStatus(entityFactory.actionStatus().create(actionId1).status(Status.WARNING))); + + // test for update status (and mixed case) + final Long actionId2 = getFirstAssignedActionId(assignDistributionSet( + testdataFactory.createDistributionSet("ds2"), testdataFactory.createTargets(1, "t2"))); + assertThat(actionId2).isNotEqualTo(actionId1); + for (int i = 0; i < maxStatusEntries; ++i) { + controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId2) + .status(Status.WARNING).message("Msg " + i).occurredAt(System.currentTimeMillis())); + } + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> controllerManagement + .addInformationalActionStatus(entityFactory.actionStatus().create(actionId2).status(Status.WARNING))); + + } + + @Test + @Description("Verifies that the quota specifying the maximum number of messages per action status is enforced.") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), + @Expect(type = DistributionSetCreatedEvent.class, count = 1), + @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock + @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), + @Expect(type = TargetAssignDistributionSetEvent.class, count = 1) }) + public void createActionStatusWithTooManyMessages() { + + final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus(); + + final Long actionId = getFirstAssignedActionId( + assignDistributionSet(testdataFactory.createDistributionSet("ds1"), testdataFactory.createTargets(1))); + assertThat(actionId).isNotNull(); + + final List messages = new ArrayList<>(); + IntStream.range(0, maxMessages).forEach(i -> messages.add(i, "msg")); + + assertThat(controllerManagement.addInformationalActionStatus( + entityFactory.actionStatus().create(actionId).messages(messages).status(Status.WARNING))).isNotNull(); + + messages.add("msg"); + assertThatExceptionOfType(AssignmentQuotaExceededException.class) + .isThrownBy(() -> controllerManagement.addInformationalActionStatus( + entityFactory.actionStatus().create(actionId).messages(messages).status(Status.WARNING))); + + } + + @Test + @Description("Verifies that a DOWNLOAD_ONLY action is not marked complete when the controller reports DOWNLOAD") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), + @Expect(type = DistributionSetCreatedEvent.class, count = 1), + @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock + @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), + @Expect(type = TargetAssignDistributionSetEvent.class, count = 1) }) + public void controllerReportsDownloadForDownloadOnlyAction() { + testdataFactory.createTarget(); + final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID); + assertThat(actionId).isNotNull(); + controllerManagement + .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOAD)); + assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, + Action.Status.DOWNLOAD, true); + + assertThat(actionStatusRepository.count()).isEqualTo(2); + assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(2); + assertThat(activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID)).isEqualTo(true); + } + @Test @Description("Verifies that management get access react as specified on calls for non existing entities by means " + "of Optional not present.") @@ -138,7 +342,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { entityFactory.actionStatus().create(NOT_EXIST_IDL).status(Action.Status.FINISHED)), "Action"); verifyThrownExceptionBy(() -> controllerManagement - .getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), NOT_EXIST_IDL), + .getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), NOT_EXIST_IDL), "SoftwareModule"); verifyThrownExceptionBy( @@ -378,117 +582,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(8); } - @Step - private Long createTargetAndAssignDs() { - final Long dsId = testdataFactory.createDistributionSet().getId(); - testdataFactory.createTarget(); - assignDistributionSet(dsId, DEFAULT_CONTROLLER_ID); - assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.PENDING); - - return deploymentManagement.findActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID).getContent().get(0).getId(); - } - - @Step - private Long createAndAssignDsAsDownloadOnly(final String dsName, final String defaultControllerId) { - final Long dsId = testdataFactory.createDistributionSet(dsName).getId(); - assignDistributionSet(dsId, defaultControllerId, DOWNLOAD_ONLY); - assertThat(targetManagement.getByControllerID(defaultControllerId).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.PENDING); - - final Long id = deploymentManagement.findActiveActionsByTarget(PAGE, defaultControllerId).getContent().get(0) - .getId(); - assertThat(id).isNotNull(); - return id; - } - - @Step - private Long assignDs(final Long dsId, final String defaultControllerId, final Action.ActionType actionType) { - assignDistributionSet(dsId, defaultControllerId, actionType); - assertThat(targetManagement.getByControllerID(defaultControllerId).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.PENDING); - - final Long id = deploymentManagement.findActiveActionsByTarget(PAGE, defaultControllerId).getContent().get(0) - .getId(); - assertThat(id).isNotNull(); - return id; - } - - @Step - private void simulateIntermediateStatusOnCancellation(final Long actionId) { - controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING)); - assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, - Action.Status.RUNNING, true); - - controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOAD)); - assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, - Action.Status.DOWNLOAD, true); - - controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOADED)); - assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, - Action.Status.DOWNLOADED, true); - - controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RETRIEVED)); - assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, - Action.Status.RETRIEVED, true); - - controllerManagement - .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.WARNING)); - assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, - Action.Status.WARNING, true); - } - - @Step - private void simulateIntermediateStatusOnUpdate(final Long actionId) { - addUpdateActionStatusAndAssert(actionId, Action.Status.RUNNING); - - addUpdateActionStatusAndAssert(actionId, Action.Status.DOWNLOAD); - - addUpdateActionStatusAndAssert(actionId, Action.Status.DOWNLOADED); - - addUpdateActionStatusAndAssert(actionId, Action.Status.RETRIEVED); - - addUpdateActionStatusAndAssert(actionId, Action.Status.WARNING); - } - - private void addUpdateActionStatusAndAssert(final Long actionId, final Action.Status actionStatus) { - addUpdateActionStatusAndAssert(actionId, actionStatus, null); - } - - private void addUpdateActionStatusAndAssert(final Long actionId, final Action.Status actionStatus, - final Integer code) { - final ActionStatusCreate status = entityFactory.actionStatus().create(actionId).status(actionStatus); - if (code != null) { - status.code(code.intValue()); - } - controllerManagement - .addUpdateActionStatus(status); - assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, - actionStatus, true); - } - - private void assertActionStatus(final Long actionId, final String controllerId, - final TargetUpdateStatus expectedTargetUpdateStatus, final Action.Status expectedActionActionStatus, - final Action.Status expectedActionStatus, final boolean actionActive) { - final TargetUpdateStatus targetStatus = targetManagement.getByControllerID(controllerId).get() - .getUpdateStatus(); - assertThat(targetStatus).isEqualTo(expectedTargetUpdateStatus); - final Action action = deploymentManagement.findAction(actionId).get(); - assertThat(action.getStatus()).isEqualTo(expectedActionActionStatus); - assertThat(action.isActive()).isEqualTo(actionActive); - final List actionStatusList = controllerManagement.findActionStatusByAction(PAGE, actionId) - .getContent(); - assertThat(actionStatusList.get(actionStatusList.size() - 1).getStatus()).isEqualTo(expectedActionStatus); - if (actionActive) { - assertThat(controllerManagement.findActiveActionWithHighestWeight(controllerId).get().getId()) - .isEqualTo(actionId); - } - } - @Test @Description("Verifies that assignment verification works based on SHA1 hash. By design it is not important which artifact " + "is actually used for the check as long as they have an identical binary, i.e. same SHA1 hash. ") @@ -516,14 +609,14 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat( controllerManagement.hasTargetArtifactAssigned(savedTarget.getControllerId(), artifact.getSha1Hash())) - .isFalse(); + .isFalse(); savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId())); assertThat( controllerManagement.hasTargetArtifactAssigned(savedTarget.getControllerId(), artifact.getSha1Hash())) - .isTrue(); + .isTrue(); assertThat( controllerManagement.hasTargetArtifactAssigned(savedTarget.getControllerId(), artifact2.getSha1Hash())) - .isTrue(); + .isTrue(); } @Test @@ -577,11 +670,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(targetRepository.count()).as("Only 1 target should be registred").isEqualTo(1L); } - private void createTargetType(String targetTypeName) { - systemSecurityContext.runAsSystem(() -> - targetTypeManagement.create(entityFactory.targetType().create().name(targetTypeName))); - } - @Test @Description("Register a controller which does not exist with existing target type and update its target type to non existing one") @WithUser(principal = "controller", authorities = { CONTROLLER_ROLE }) @@ -591,9 +679,9 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { void findOrRegisterTargetIfItDoesNotExistWithExistingTypeAndUpdateToNonExistingType() { createTargetType("knownTargetTypeName"); final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST, - null,"knownTargetTypeName"); + null, "knownTargetTypeName"); final Target sameTarget = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST, - null,"unknownTargetTypeName"); + null, "unknownTargetTypeName"); assertThat(target.getId()).as("Target should be the same").isEqualTo(sameTarget.getId()); assertThat(sameTarget.getTargetType().getName()).as("Target type should be unchanged") .isEqualTo("knownTargetTypeName"); @@ -995,39 +1083,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(targetVerify.getLastModifiedAt()).isEqualTo(target.getLastModifiedAt()); } - @Step - private void addAttributeAndVerify(final String controllerId) { - final Map testData = new HashMap<>(1); - testData.put("test1", "testdata1"); - controllerManagement.updateControllerAttributes(controllerId, testData, null); - - assertThat(targetManagement.getControllerAttributes(controllerId)).as("Controller Attributes are wrong") - .isEqualTo(testData); - } - - @Step - private void addSecondAttributeAndVerify(final String controllerId) { - final Map testData = new HashMap<>(2); - testData.put("test2", "testdata20"); - controllerManagement.updateControllerAttributes(controllerId, testData, null); - - testData.put("test1", "testdata1"); - assertThat(targetManagement.getControllerAttributes(controllerId)).as("Controller Attributes are wrong") - .isEqualTo(testData); - } - - @Step - private void updateAttributeAndVerify(final String controllerId) { - final Map testData = new HashMap<>(2); - testData.put("test1", "testdata12"); - - controllerManagement.updateControllerAttributes(controllerId, testData, null); - - testData.put("test2", "testdata20"); - assertThat(targetManagement.getControllerAttributes(controllerId)).as("Controller Attributes are wrong") - .isEqualTo(testData); - } - @Test @Description("Ensures that target attributes can be updated using different update modes.") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @@ -1051,300 +1106,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { } - @Step - private void updateTargetAttributesWithUpdateModeRemove(final String controllerId) { - - final int previousSize = targetManagement.getControllerAttributes(controllerId).size(); - - // update the attributes using update mode REMOVE - final Map removeAttributes = new HashMap<>(); - removeAttributes.put("k1", "foo"); - removeAttributes.put("k3", "bar"); - controllerManagement.updateControllerAttributes(controllerId, removeAttributes, UpdateMode.REMOVE); - - // verify attribute removal - final Map updatedAttributes = targetManagement.getControllerAttributes(controllerId); - assertThat(updatedAttributes.size()).isEqualTo(previousSize - 2); - assertThat(updatedAttributes).doesNotContainKeys("k1", "k3"); - - } - - @Step - private void updateTargetAttributesWithUpdateModeMerge(final String controllerId) { - // get the current attributes - final HashMap attributes = new HashMap<>( - targetManagement.getControllerAttributes(controllerId)); - - // update the attributes using update mode MERGE - final Map mergeAttributes = new HashMap<>(); - mergeAttributes.put("k1", "v1_modified_again"); - mergeAttributes.put("k4", "v4"); - controllerManagement.updateControllerAttributes(controllerId, mergeAttributes, UpdateMode.MERGE); - - // verify attribute merge - final Map updatedAttributes = targetManagement.getControllerAttributes(controllerId); - assertThat(updatedAttributes.size()).isEqualTo(4); - assertThat(updatedAttributes).containsAllEntriesOf(mergeAttributes); - assertThat(updatedAttributes.get("k1")).isEqualTo("v1_modified_again"); - attributes.keySet().forEach(assertThat(updatedAttributes)::containsKey); - } - - @Step - private void updateTargetAttributesWithUpdateModeReplace(final String controllerId) { - - // get the current attributes - final HashMap attributes = new HashMap<>( - targetManagement.getControllerAttributes(controllerId)); - - // update the attributes using update mode REPLACE - final Map replacementAttributes = new HashMap<>(); - replacementAttributes.put("k1", "v1_modified"); - replacementAttributes.put("k2", "v2"); - replacementAttributes.put("k3", "v3"); - controllerManagement.updateControllerAttributes(controllerId, replacementAttributes, UpdateMode.REPLACE); - - // verify attribute replacement - final Map updatedAttributes = targetManagement.getControllerAttributes(controllerId); - assertThat(updatedAttributes.size()).isEqualTo(replacementAttributes.size()); - assertThat(updatedAttributes).containsAllEntriesOf(replacementAttributes); - assertThat(updatedAttributes.get("k1")).isEqualTo("v1_modified"); - attributes.entrySet().forEach(assertThat(updatedAttributes)::doesNotContain); - } - - @Step - private void updateTargetAttributesWithoutUpdateMode(final String controllerId) { - - // set the initial attributes - final Map attributes = new HashMap<>(); - attributes.put("k0", "v0"); - attributes.put("k1", "v1"); - controllerManagement.updateControllerAttributes(controllerId, attributes, null); - - // verify initial attributes - final Map updatedAttributes = targetManagement.getControllerAttributes(controllerId); - assertThat(updatedAttributes.size()).isEqualTo(attributes.size()); - assertThat(updatedAttributes).containsAllEntriesOf(attributes); - } - - @Test - @Description("Ensures that target attribute update fails if quota hits.") - @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), - @Expect(type = TargetUpdatedEvent.class, count = 2) }) - public void updateTargetAttributesFailsIfTooManyEntries() throws Exception { - final String controllerId = "test123"; - final int allowedAttributes = quotaManagement.getMaxAttributeEntriesPerTarget(); - testdataFactory.createTarget(controllerId); - - assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> SecurityContextSwitch - .runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { - writeAttributes(controllerId, allowedAttributes + 1, "key", "value"); - return null; - })).withMessageContaining("" + allowedAttributes); - - // verify that no attributes have been written - assertThat(targetManagement.getControllerAttributes(controllerId)).isEmpty(); - - // Write allowed number of attributes twice with same key should result - // in update but work - SecurityContextSwitch.runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { - writeAttributes(controllerId, allowedAttributes, "key", "value1"); - writeAttributes(controllerId, allowedAttributes, "key", "value2"); - return null; - }); - assertThat(targetManagement.getControllerAttributes(controllerId)).hasSize(10); - - // Now rite one more - assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> SecurityContextSwitch - .runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { - writeAttributes(controllerId, 1, "additional", "value1"); - return null; - })).withMessageContaining("" + allowedAttributes); - assertThat(targetManagement.getControllerAttributes(controllerId)).hasSize(10); - - } - - private void writeAttributes(final String controllerId, final int allowedAttributes, final String keyPrefix, - final String valuePrefix) { - final Map testData = new HashMap<>(allowedAttributes); - for (int i = 0; i < allowedAttributes; i++) { - testData.put(keyPrefix + i, valuePrefix); - } - controllerManagement.updateControllerAttributes(controllerId, testData, null); - } - - @Test - @Description("Checks if invalid values of attribute-key and attribute-value are handled correctly") - public void updateTargetAttributesFailsForInvalidAttributes() { - final String controllerId = "targetId123"; - testdataFactory.createTarget(controllerId); - - assertThatExceptionOfType(InvalidTargetAttributeException.class) - .as("Attribute with key too long should not be created") - .isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId, - Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_TOO_LONG, TargetTestData.ATTRIBUTE_VALUE_VALID), null)); - - assertThatExceptionOfType(InvalidTargetAttributeException.class) - .as("Attribute with key too long and value too long should not be created") - .isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId, - Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_TOO_LONG, TargetTestData.ATTRIBUTE_VALUE_TOO_LONG), null)); - - assertThatExceptionOfType(InvalidTargetAttributeException.class) - .as("Attribute with value too long should not be created") - .isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId, - Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_VALID, TargetTestData.ATTRIBUTE_VALUE_TOO_LONG), null)); - - assertThatExceptionOfType(InvalidTargetAttributeException.class) - .as("Attribute with key NULL should not be created").isThrownBy(() -> controllerManagement - .updateControllerAttributes(controllerId, - Collections.singletonMap(null, TargetTestData.ATTRIBUTE_VALUE_VALID), null)); - } - - @Test - @Description("Controller providing status entries fails if providing more than permitted by quota.") - @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), - @Expect(type = DistributionSetCreatedEvent.class, count = 1), - @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), - @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock - @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock - @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), - @Expect(type = TargetAssignDistributionSetEvent.class, count = 1) }) - public void controllerProvidesIntermediateFeedbackFailsIfQuotaHit() { - final int allowStatusEntries = 10; - final Long actionId = createTargetAndAssignDs(); - - // Fails as one entry is already in there from the assignment - assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> SecurityContextSwitch - .runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { - writeStatus(actionId, allowStatusEntries); - return null; - })).withMessageContaining("" + allowStatusEntries); - - } - - private void writeStatus(final Long actionId, final int allowedStatusEntries) { - for (int i = 0; i < allowedStatusEntries; i++) { - controllerManagement.addInformationalActionStatus( - entityFactory.actionStatus().create(actionId).status(Status.RUNNING).message("test" + i)); - } - } - - @Test - @Description("Test to verify the storage and retrieval of action history.") - public void findMessagesByActionStatusId() { - final DistributionSet testDs = testdataFactory.createDistributionSet("1"); - final List testTarget = testdataFactory.createTargets(1); - - final Long actionId = getFirstAssignedActionId(assignDistributionSet(testDs, testTarget)); - - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) - .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()) - .messages(List.of("proceeding message 1"))); - - final long createTime = System.currentTimeMillis(); - waitNextMillis(); - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) - .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()) - .messages(List.of("proceeding message 2"))); - - final List messages = controllerManagement.getActionHistoryMessages(actionId, 2); - - assertThat(deploymentManagement.findActionStatusByAction(PAGE, actionId).getTotalElements()) - .as("Two action-states in total").isEqualTo(3L); - assertThat(messages.get(0)).as("Message of action-status").isEqualTo("proceeding message 2"); - assertThat(messages.get(1)).as("Message of action-status").isEqualTo("proceeding message 1"); - } - - @Test - @Description("Verifies that the quota specifying the maximum number of status entries per action is enforced.") - @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 2), - @Expect(type = DistributionSetCreatedEvent.class, count = 2), - @Expect(type = SoftwareModuleCreatedEvent.class, count = 6), - @Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock - @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), // implicit lock - @Expect(type = ActionCreatedEvent.class, count = 2), @Expect(type = TargetUpdatedEvent.class, count = 2), - @Expect(type = TargetAssignDistributionSetEvent.class, count = 2) }) - public void addActionStatusUpdatesUntilQuotaIsExceeded() { - - // any distribution set assignment causes 1 status entity to be created - final int maxStatusEntries = quotaManagement.getMaxStatusEntriesPerAction() - 1; - - // test for informational status - final Long actionId1 = getFirstAssignedActionId(assignDistributionSet( - testdataFactory.createDistributionSet("ds1"), testdataFactory.createTargets(1, "t1"))); - assertThat(actionId1).isNotNull(); - for (int i = 0; i < maxStatusEntries; ++i) { - controllerManagement.addInformationalActionStatus(entityFactory.actionStatus().create(actionId1) - .status(Status.WARNING).message("Msg " + i).occurredAt(System.currentTimeMillis())); - } - assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> controllerManagement - .addInformationalActionStatus(entityFactory.actionStatus().create(actionId1).status(Status.WARNING))); - - // test for update status (and mixed case) - final Long actionId2 = getFirstAssignedActionId(assignDistributionSet( - testdataFactory.createDistributionSet("ds2"), testdataFactory.createTargets(1, "t2"))); - assertThat(actionId2).isNotEqualTo(actionId1); - for (int i = 0; i < maxStatusEntries; ++i) { - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId2) - .status(Status.WARNING).message("Msg " + i).occurredAt(System.currentTimeMillis())); - } - assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> controllerManagement - .addInformationalActionStatus(entityFactory.actionStatus().create(actionId2).status(Status.WARNING))); - - } - - @Test - @Description("Verifies that the quota specifying the maximum number of messages per action status is enforced.") - @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), - @Expect(type = DistributionSetCreatedEvent.class, count = 1), - @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), - @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock - @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock - @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), - @Expect(type = TargetAssignDistributionSetEvent.class, count = 1) }) - public void createActionStatusWithTooManyMessages() { - - final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus(); - - final Long actionId = getFirstAssignedActionId( - assignDistributionSet(testdataFactory.createDistributionSet("ds1"), testdataFactory.createTargets(1))); - assertThat(actionId).isNotNull(); - - final List messages = new ArrayList<>(); - IntStream.range(0, maxMessages).forEach(i -> messages.add(i, "msg")); - - assertThat(controllerManagement.addInformationalActionStatus( - entityFactory.actionStatus().create(actionId).messages(messages).status(Status.WARNING))).isNotNull(); - - messages.add("msg"); - assertThatExceptionOfType(AssignmentQuotaExceededException.class) - .isThrownBy(() -> controllerManagement.addInformationalActionStatus( - entityFactory.actionStatus().create(actionId).messages(messages).status(Status.WARNING))); - - } - - @Test - @Description("Verifies that a DOWNLOAD_ONLY action is not marked complete when the controller reports DOWNLOAD") - @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), - @Expect(type = DistributionSetCreatedEvent.class, count = 1), - @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), - @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock - @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock - @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), - @Expect(type = TargetAssignDistributionSetEvent.class, count = 1) }) - public void controllerReportsDownloadForDownloadOnlyAction() { - testdataFactory.createTarget(); - final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID); - assertThat(actionId).isNotNull(); - controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOAD)); - assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, - Action.Status.DOWNLOAD, true); - - assertThat(actionStatusRepository.count()).isEqualTo(2); - assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(2); - assertThat(activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID)).isEqualTo(true); - } - @Test @Description("Verifies that a DOWNLOAD_ONLY action is marked complete once the controller reports DOWNLOADED") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @@ -1468,17 +1229,16 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { () -> IntStream.range(0, maxMessages).forEach(i -> controllerManagement.addUpdateActionStatus( entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)))); - //assert that Final result is accepted even if quota is reached assertThatNoException().isThrownBy(() -> { - Action updatedAction = controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED)); + Action updatedAction = controllerManagement.addUpdateActionStatus( + entityFactory.actionStatus().create(actionId).status(Status.FINISHED)); // check if action really finished assertThat(updatedAction.isActive()).isFalse(); // check if final status is updated accordingly assertThat(updatedAction.getStatus()).isEqualTo(Status.FINISHED); }); - //assert that additional final result is not accepted assertThatNoException().isThrownBy(() -> { Action updatedAction = controllerManagement @@ -1513,7 +1273,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { () -> IntStream.range(0, maxMessages).forEach(i -> controllerManagement.addUpdateActionStatus( entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)))); - //assert that Final result is accepted even if quota is reached assertThatNoException().isThrownBy(() -> { Action updatedAction = controllerManagement @@ -1524,7 +1283,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(updatedAction.getStatus()).isEqualTo(Status.FINISHED); }); - //assert that additional final result is not accepted assertThatNoException().isThrownBy(() -> { Action updatedAction = controllerManagement @@ -1558,9 +1316,9 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { } final List foundAction = actionRepository.findAll((root, query, cb) -> cb.and( - root.get(JpaAction_.externalRef).in(allExternalRef), - cb.equal(root.get(JpaAction_.active), true) - )).stream().map(Action.class::cast).toList(); + root.get(JpaAction_.externalRef).in(allExternalRef), + cb.equal(root.get(JpaAction_.active), true) + )).stream().map(Action.class::cast).toList(); assertThat(foundAction).isNotNull(); for (int i = 0; i < numberOfActions; i++) { assertThat(foundAction.get(i).getId()).isEqualTo(allActionId.get(i)); @@ -1589,6 +1347,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(foundAction).isPresent(); assertThat(foundAction.get().getId()).isEqualTo(actionId); } + @Test @Description("Verify that assigning version form target works") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @@ -1597,8 +1356,8 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { @Expect(type = DistributionSetUpdatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = ActionCreatedEvent.class, count = 1), - @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3)} - ) + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3) } + ) void assignVersionToTarget() { final DistributionSet knownDistributionSet = testdataFactory.createDistributionSet(); @@ -1608,10 +1367,10 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { // WHEN boolean updated1 = controllerManagement.updateOfflineAssignedVersion(DEFAULT_CONTROLLER_ID, - knownDistributionSet.getName(),knownDistributionSet.getVersion()); + knownDistributionSet.getName(), knownDistributionSet.getVersion()); // if target is already assigned to a distribution then it shouldn't reassign the distribution boolean updated2 = controllerManagement.updateOfflineAssignedVersion(DEFAULT_CONTROLLER_ID, - knownDistributionSet.getName(),knownDistributionSet.getVersion()); + knownDistributionSet.getName(), knownDistributionSet.getVersion()); // THEN assertAssignedDistributionSetId(DEFAULT_CONTROLLER_ID, knownDistributionSet.getId()); @@ -1671,16 +1430,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(actionStatusRepository.count()).isEqualTo(12L); } - @Step - private void finishDownloadOnlyUpdateAndSendUpdateActionStatus(final Long actionId, final Status status) { - // finishing action - controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)); - - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(status)); - assertThat(activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID)).isEqualTo(false); - } - @Test @Description("Verifies that a controller can report a FINISHED event for a DOWNLOAD_ONLY action after having" + " installed an intermediate update.") @@ -1720,12 +1469,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertNoActiveActionsExistsForControllerId(DEFAULT_CONTROLLER_ID); } - @Step - private void addUpdateActionStatus(final Long actionId, final String controllerId, final Status actionStatus) { - controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(actionStatus)); - assertActionStatus(actionId, controllerId, TargetUpdateStatus.IN_SYNC, actionStatus, actionStatus, false); - } - @Test @Description("Actions are exposed according to thier weight in multi assignment mode.") void actionsAreExposedAccordingToTheirWeight() { @@ -1759,24 +1502,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId)).isEmpty(); } - private void assertAssignedDistributionSetId(final String controllerId, final Long dsId) { - final Optional target = controllerManagement.getByControllerId(controllerId); - assertThat(target).isPresent(); - final DistributionSet assignedDistributionSet = ((JpaTarget) target.get()).getAssignedDistributionSet(); - assertThat(assignedDistributionSet.getId()).isEqualTo(dsId); - } - - private void assertInstalledDistributionSetId(final String controllerId, final Long dsId) { - final Optional target = controllerManagement.getByControllerId(controllerId); - assertThat(target).isPresent(); - final DistributionSet installedDistributionSet = ((JpaTarget) target.get()).getInstalledDistributionSet(); - if (dsId == null) { - assertThat(installedDistributionSet).isNull(); - } else { - assertThat(installedDistributionSet.getId()).isEqualTo(dsId); - } - } - @Test @Description("Delete a target on requested target deletion from client side") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @@ -1834,6 +1559,280 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { } + @Step + private Long createTargetAndAssignDs() { + final Long dsId = testdataFactory.createDistributionSet().getId(); + testdataFactory.createTarget(); + assignDistributionSet(dsId, DEFAULT_CONTROLLER_ID); + assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.PENDING); + + return deploymentManagement.findActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID).getContent().get(0).getId(); + } + + @Step + private Long createAndAssignDsAsDownloadOnly(final String dsName, final String defaultControllerId) { + final Long dsId = testdataFactory.createDistributionSet(dsName).getId(); + assignDistributionSet(dsId, defaultControllerId, DOWNLOAD_ONLY); + assertThat(targetManagement.getByControllerID(defaultControllerId).get().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.PENDING); + + final Long id = deploymentManagement.findActiveActionsByTarget(PAGE, defaultControllerId).getContent().get(0) + .getId(); + assertThat(id).isNotNull(); + return id; + } + + @Step + private Long assignDs(final Long dsId, final String defaultControllerId, final Action.ActionType actionType) { + assignDistributionSet(dsId, defaultControllerId, actionType); + assertThat(targetManagement.getByControllerID(defaultControllerId).get().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.PENDING); + + final Long id = deploymentManagement.findActiveActionsByTarget(PAGE, defaultControllerId).getContent().get(0) + .getId(); + assertThat(id).isNotNull(); + return id; + } + + @Step + private void simulateIntermediateStatusOnCancellation(final Long actionId) { + controllerManagement + .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING)); + assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, + Action.Status.RUNNING, true); + + controllerManagement + .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOAD)); + assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, + Action.Status.DOWNLOAD, true); + + controllerManagement + .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOADED)); + assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, + Action.Status.DOWNLOADED, true); + + controllerManagement + .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RETRIEVED)); + assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, + Action.Status.RETRIEVED, true); + + controllerManagement + .addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.WARNING)); + assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.CANCELING, + Action.Status.WARNING, true); + } + + @Step + private void simulateIntermediateStatusOnUpdate(final Long actionId) { + addUpdateActionStatusAndAssert(actionId, Action.Status.RUNNING); + + addUpdateActionStatusAndAssert(actionId, Action.Status.DOWNLOAD); + + addUpdateActionStatusAndAssert(actionId, Action.Status.DOWNLOADED); + + addUpdateActionStatusAndAssert(actionId, Action.Status.RETRIEVED); + + addUpdateActionStatusAndAssert(actionId, Action.Status.WARNING); + } + + private void addUpdateActionStatusAndAssert(final Long actionId, final Action.Status actionStatus) { + addUpdateActionStatusAndAssert(actionId, actionStatus, null); + } + + private void addUpdateActionStatusAndAssert(final Long actionId, final Action.Status actionStatus, + final Integer code) { + final ActionStatusCreate status = entityFactory.actionStatus().create(actionId).status(actionStatus); + if (code != null) { + status.code(code.intValue()); + } + controllerManagement + .addUpdateActionStatus(status); + assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING, Action.Status.RUNNING, + actionStatus, true); + } + + private void assertActionStatus(final Long actionId, final String controllerId, + final TargetUpdateStatus expectedTargetUpdateStatus, final Action.Status expectedActionActionStatus, + final Action.Status expectedActionStatus, final boolean actionActive) { + final TargetUpdateStatus targetStatus = targetManagement.getByControllerID(controllerId).get() + .getUpdateStatus(); + assertThat(targetStatus).isEqualTo(expectedTargetUpdateStatus); + final Action action = deploymentManagement.findAction(actionId).get(); + assertThat(action.getStatus()).isEqualTo(expectedActionActionStatus); + assertThat(action.isActive()).isEqualTo(actionActive); + final List actionStatusList = controllerManagement.findActionStatusByAction(PAGE, actionId) + .getContent(); + assertThat(actionStatusList.get(actionStatusList.size() - 1).getStatus()).isEqualTo(expectedActionStatus); + if (actionActive) { + assertThat(controllerManagement.findActiveActionWithHighestWeight(controllerId).get().getId()) + .isEqualTo(actionId); + } + } + + private void createTargetType(String targetTypeName) { + systemSecurityContext.runAsSystem(() -> + targetTypeManagement.create(entityFactory.targetType().create().name(targetTypeName))); + } + + @Step + private void addAttributeAndVerify(final String controllerId) { + final Map testData = new HashMap<>(1); + testData.put("test1", "testdata1"); + controllerManagement.updateControllerAttributes(controllerId, testData, null); + + assertThat(targetManagement.getControllerAttributes(controllerId)).as("Controller Attributes are wrong") + .isEqualTo(testData); + } + + @Step + private void addSecondAttributeAndVerify(final String controllerId) { + final Map testData = new HashMap<>(2); + testData.put("test2", "testdata20"); + controllerManagement.updateControllerAttributes(controllerId, testData, null); + + testData.put("test1", "testdata1"); + assertThat(targetManagement.getControllerAttributes(controllerId)).as("Controller Attributes are wrong") + .isEqualTo(testData); + } + + @Step + private void updateAttributeAndVerify(final String controllerId) { + final Map testData = new HashMap<>(2); + testData.put("test1", "testdata12"); + + controllerManagement.updateControllerAttributes(controllerId, testData, null); + + testData.put("test2", "testdata20"); + assertThat(targetManagement.getControllerAttributes(controllerId)).as("Controller Attributes are wrong") + .isEqualTo(testData); + } + + @Step + private void updateTargetAttributesWithUpdateModeRemove(final String controllerId) { + + final int previousSize = targetManagement.getControllerAttributes(controllerId).size(); + + // update the attributes using update mode REMOVE + final Map removeAttributes = new HashMap<>(); + removeAttributes.put("k1", "foo"); + removeAttributes.put("k3", "bar"); + controllerManagement.updateControllerAttributes(controllerId, removeAttributes, UpdateMode.REMOVE); + + // verify attribute removal + final Map updatedAttributes = targetManagement.getControllerAttributes(controllerId); + assertThat(updatedAttributes.size()).isEqualTo(previousSize - 2); + assertThat(updatedAttributes).doesNotContainKeys("k1", "k3"); + + } + + @Step + private void updateTargetAttributesWithUpdateModeMerge(final String controllerId) { + // get the current attributes + final HashMap attributes = new HashMap<>( + targetManagement.getControllerAttributes(controllerId)); + + // update the attributes using update mode MERGE + final Map mergeAttributes = new HashMap<>(); + mergeAttributes.put("k1", "v1_modified_again"); + mergeAttributes.put("k4", "v4"); + controllerManagement.updateControllerAttributes(controllerId, mergeAttributes, UpdateMode.MERGE); + + // verify attribute merge + final Map updatedAttributes = targetManagement.getControllerAttributes(controllerId); + assertThat(updatedAttributes.size()).isEqualTo(4); + assertThat(updatedAttributes).containsAllEntriesOf(mergeAttributes); + assertThat(updatedAttributes.get("k1")).isEqualTo("v1_modified_again"); + attributes.keySet().forEach(assertThat(updatedAttributes)::containsKey); + } + + @Step + private void updateTargetAttributesWithUpdateModeReplace(final String controllerId) { + + // get the current attributes + final HashMap attributes = new HashMap<>( + targetManagement.getControllerAttributes(controllerId)); + + // update the attributes using update mode REPLACE + final Map replacementAttributes = new HashMap<>(); + replacementAttributes.put("k1", "v1_modified"); + replacementAttributes.put("k2", "v2"); + replacementAttributes.put("k3", "v3"); + controllerManagement.updateControllerAttributes(controllerId, replacementAttributes, UpdateMode.REPLACE); + + // verify attribute replacement + final Map updatedAttributes = targetManagement.getControllerAttributes(controllerId); + assertThat(updatedAttributes.size()).isEqualTo(replacementAttributes.size()); + assertThat(updatedAttributes).containsAllEntriesOf(replacementAttributes); + assertThat(updatedAttributes.get("k1")).isEqualTo("v1_modified"); + attributes.entrySet().forEach(assertThat(updatedAttributes)::doesNotContain); + } + + @Step + private void updateTargetAttributesWithoutUpdateMode(final String controllerId) { + + // set the initial attributes + final Map attributes = new HashMap<>(); + attributes.put("k0", "v0"); + attributes.put("k1", "v1"); + controllerManagement.updateControllerAttributes(controllerId, attributes, null); + + // verify initial attributes + final Map updatedAttributes = targetManagement.getControllerAttributes(controllerId); + assertThat(updatedAttributes.size()).isEqualTo(attributes.size()); + assertThat(updatedAttributes).containsAllEntriesOf(attributes); + } + + private void writeAttributes(final String controllerId, final int allowedAttributes, final String keyPrefix, + final String valuePrefix) { + final Map testData = new HashMap<>(allowedAttributes); + for (int i = 0; i < allowedAttributes; i++) { + testData.put(keyPrefix + i, valuePrefix); + } + controllerManagement.updateControllerAttributes(controllerId, testData, null); + } + + private void writeStatus(final Long actionId, final int allowedStatusEntries) { + for (int i = 0; i < allowedStatusEntries; i++) { + controllerManagement.addInformationalActionStatus( + entityFactory.actionStatus().create(actionId).status(Status.RUNNING).message("test" + i)); + } + } + + @Step + private void finishDownloadOnlyUpdateAndSendUpdateActionStatus(final Long actionId, final Status status) { + // finishing action + controllerManagement + .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)); + + controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(status)); + assertThat(activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID)).isEqualTo(false); + } + + @Step + private void addUpdateActionStatus(final Long actionId, final String controllerId, final Status actionStatus) { + controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(actionStatus)); + assertActionStatus(actionId, controllerId, TargetUpdateStatus.IN_SYNC, actionStatus, actionStatus, false); + } + + private void assertAssignedDistributionSetId(final String controllerId, final Long dsId) { + final Optional target = controllerManagement.getByControllerId(controllerId); + assertThat(target).isPresent(); + final DistributionSet assignedDistributionSet = ((JpaTarget) target.get()).getAssignedDistributionSet(); + assertThat(assignedDistributionSet.getId()).isEqualTo(dsId); + } + + private void assertInstalledDistributionSetId(final String controllerId, final Long dsId) { + final Optional target = controllerManagement.getByControllerId(controllerId); + assertThat(target).isPresent(); + final DistributionSet installedDistributionSet = ((JpaTarget) target.get()).getInstalledDistributionSet(); + if (dsId == null) { + assertThat(installedDistributionSet).isNull(); + } else { + assertThat(installedDistributionSet.getId()).isEqualTo(dsId); + } + } + private void assertLastActionStatusCodeInAction(final Long actionId, final Integer expectedLastActionStatusCode) { final Optional action = actionRepository.findWithDetailsById(actionId); assertThat(action).isPresent(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java index 366d436fa..9b69f22c3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java @@ -30,15 +30,18 @@ import java.util.stream.Stream; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.assertj.core.api.Assertions; import org.eclipse.hawkbit.repository.ActionStatusFields; import org.eclipse.hawkbit.repository.DeploymentManagement; +import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent; import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent; -import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; @@ -92,10 +95,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort.Direction; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Test class testing the functionality of triggering a deployment of {@link DistributionSet}s to {@link Target}s. */ @@ -106,6 +105,44 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { private static final boolean STATE_ACTIVE = true; private static final boolean STATE_INACTIVE = false; + @Test + @Description("Tests that an exception is thrown when a target is assigned to an incomplete distribution set") + public void verifyAssignTargetsToIncompleteDistribution() { + final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet(); + final Target target = testdataFactory.createTarget(); + + assertThatExceptionOfType(IncompleteDistributionSetException.class) + .as("Incomplete distributionSet should throw an exception") + .isThrownBy(() -> assignDistributionSet(distributionSet, target)); + + } + + @Test + @Description("Tests that an exception is thrown when a target is assigned to an invalidated distribution set") + public void verifyAssignTargetsToInvalidDistribution() { + final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet(); + final Target target = testdataFactory.createTarget(); + + assertThatExceptionOfType(InvalidDistributionSetException.class) + .as("Invalid distributionSet should throw an exception") + .isThrownBy(() -> assignDistributionSet(distributionSet, target)); + + } + + protected List createAssignmentRequests(final Collection distributionSets, + final Collection targets, final int weight) { + return createAssignmentRequests(distributionSets, targets, weight, false); + } + + protected List createAssignmentRequests(final Collection distributionSets, + final Collection targets, final int weight, final boolean confirmationRequired) { + final List deploymentRequests = new ArrayList<>(); + distributionSets.forEach(ds -> targets.forEach(target -> deploymentRequests + .add(DeploymentManagement.deploymentRequest(target.getControllerId(), ds.getId()).setWeight(weight) + .setConfirmationRequired(confirmationRequired).build()))); + return deploymentRequests; + } + @Test @Description("Verifies that management get access react as specified on calls for non existing entities by means " + "of Optional not present.") @@ -279,7 +316,8 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { @Expect(type = DistributionSetCreatedEvent.class, count = 2), @Expect(type = SoftwareModuleCreatedEvent.class, count = 6), @Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock - @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6) }) // implicit lock }) + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6) }) + // implicit lock }) void multiAssigmentHistoryOverMultiplePagesResultsInTwoActiveAction() { final DistributionSet cancelDs = testdataFactory.createDistributionSet("Canceled DS", "1.0", @@ -450,24 +488,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { .isThrownBy(() -> deploymentManagement.forceQuitAction(assigningAction.getId())); } - private JpaAction assignSet(final Target target, final DistributionSet ds) { - assignDistributionSet(ds.getId(), target.getControllerId()); - implicitLock(ds); - assertThat(targetManagement.getByControllerID(target.getControllerId()).get().getUpdateStatus()) - .as("wrong update status").isEqualTo(TargetUpdateStatus.PENDING); - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).as("wrong assigned ds") - .contains(ds); - final JpaAction action = actionRepository - .findAll( - (root, query, cb) -> - cb.and( - cb.equal(root.get(JpaAction_.target).get(JpaTarget_.id), target.getId()), - cb.equal(root.get(JpaAction_.distributionSet).get(JpaDistributionSet_.id), ds.getId())), - PAGE).getContent().get(0); - assertThat(action).as("action should not be null").isNotNull(); - return action; - } - @Test @Description("Simple offline deployment of a distribution set to a list of targets. Verifies that offline assigment " + "is correctly executed for targets that do not have a running update already. Those are ignored.") @@ -617,20 +637,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertDsExclusivelyAssignedToTargets(targets, ds1.getId(), STATE_ACTIVE, RUNNING); } - private void assertDsExclusivelyAssignedToTargets(final List targets, final long dsId, final boolean active, - final Status status) { - final List assignment = findActionsByDistributionSet(PAGE, dsId).getContent(); - final String currentUsername = tenantAware.getCurrentUsername(); - - assertThat(assignment).hasSize(10).allMatch(action -> action.isActive() == active) - .as("Is assigned to DS " + dsId).allMatch(action -> action.getDistributionSet().getId().equals(dsId)) - .as("State is " + status).allMatch(action -> action.getStatus() == status) - .as("Initiated by " + currentUsername).allMatch(a -> a.getInitiatedBy().equals(currentUsername)); - final long[] targetIds = targets.stream().mapToLong(Target::getId).toArray(); - assertThat(targetIds).as("All targets represented in assignment").containsExactlyInAnyOrder( - assignment.stream().mapToLong(action -> action.getTarget().getId()).toArray()); - } - @Test @Description("Assign multiple DSs to a single Target in one request in multiassignment mode.") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @@ -699,20 +705,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { }); } - protected List createAssignmentRequests(final Collection distributionSets, - final Collection targets, final int weight) { - return createAssignmentRequests(distributionSets, targets, weight, false); - } - - protected List createAssignmentRequests(final Collection distributionSets, - final Collection targets, final int weight, final boolean confirmationRequired) { - final List deploymentRequests = new ArrayList<>(); - distributionSets.forEach(ds -> targets.forEach(target -> deploymentRequests - .add(DeploymentManagement.deploymentRequest(target.getControllerId(), ds.getId()).setWeight(weight) - .setConfirmationRequired(confirmationRequired).build()))); - return deploymentRequests; - } - @Test @Description("A Request resulting in multiple assignments to a single target is only allowed when multiassignment is enabled.") void multipleAssignmentsToTargetOnlyAllowedInMultiAssignMode() { @@ -741,7 +733,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { final DistributionSet createdDs = testdataFactory.createDistributionSet(); final List knownTargetIds = new ArrayList<>(); - knownTargetIds.add( "1"); + knownTargetIds.add("1"); knownTargetIds.add("2"); testdataFactory.createTargets(knownTargetIds.toArray(new String[0])); @@ -898,16 +890,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { }); } - private List assignDistributionSetToTargets(final DistributionSet distributionSet, - final Iterable targetIds, final boolean confirmationRequired) { - final List deploymentRequests = new ArrayList<>(); - for (final String controllerId : targetIds) { - deploymentRequests.add(new DeploymentRequest(controllerId, distributionSet.getId(), ActionType.FORCED, 0, - null, null, null, null, confirmationRequired)); - } - return deploymentManagement.assignDistributionSets(deploymentRequests); - } - @Test @Description("Duplicate Assignments are removed from a request when multiassignment is disabled, otherwise not") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @@ -936,10 +918,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { .isEqualTo(1); } - private int getResultingActionCount(final List results) { - return results.stream().map(DistributionSetAssignmentResult::getTotal).reduce(0, Integer::sum); - } - @Test @Description("An assignment request is not accepted if it would lead to a target exceeding the max actions per target quota.") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @@ -1033,7 +1011,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { * test a simple deployment by calling the * {@link TargetRepository#assignDistributionSet(DistributionSet, Iterable)} and * checking the active action and the action history of the targets. - * */ @Test @Description("Simple deployment or distribution set to target assignment test.") @@ -1319,7 +1296,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertThat(allFoundDS.size()).as("no ds should be founded").isZero(); assertThat(distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(Arrays - .asList(DistributionSetSpecification.isDeleted(true), DistributionSetSpecification.isCompleted(true))), + .asList(DistributionSetSpecification.isDeleted(true), DistributionSetSpecification.isCompleted(true))), PAGE).getContent()).as("wrong size of founded ds").hasSize(noOfDistributionSets); for (final DistributionSet ds : deploymentResult.getDistributionSets()) { @@ -1335,7 +1312,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { allFoundDS = distributionSetManagement.findByCompleted(pageRequest, true).getContent(); assertThat(allFoundDS.size()).as("no ds should be founded").isZero(); assertThat(distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(Arrays - .asList(DistributionSetSpecification.isDeleted(true), DistributionSetSpecification.isCompleted(true))), + .asList(DistributionSetSpecification.isDeleted(true), DistributionSetSpecification.isCompleted(true))), PAGE).getContent()).as("wrong size of founded ds").hasSize(noOfDistributionSets); } @@ -1549,30 +1526,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertThat(distributionSetRepository.findAll()).hasSize(1); } - @Test - @Description("Tests that an exception is thrown when a target is assigned to an incomplete distribution set") - public void verifyAssignTargetsToIncompleteDistribution() { - final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet(); - final Target target = testdataFactory.createTarget(); - - assertThatExceptionOfType(IncompleteDistributionSetException.class) - .as("Incomplete distributionSet should throw an exception") - .isThrownBy(() -> assignDistributionSet(distributionSet, target)); - - } - - @Test - @Description("Tests that an exception is thrown when a target is assigned to an invalidated distribution set") - public void verifyAssignTargetsToInvalidDistribution() { - final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet(); - final Target target = testdataFactory.createTarget(); - - assertThatExceptionOfType(InvalidDistributionSetException.class) - .as("Invalid distributionSet should throw an exception") - .isThrownBy(() -> assignDistributionSet(distributionSet, target)); - - } - @Test @Description("Verify that the DistributionSet assignments work for multiple targets of the same target type within the same request.") void verifyDSAssignmentForMultipleTargetsWithSameTargetType() { @@ -1661,6 +1614,52 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { .isThrownBy(() -> deploymentManagement.assignDistributionSets(deploymentRequests)); } + private JpaAction assignSet(final Target target, final DistributionSet ds) { + assignDistributionSet(ds.getId(), target.getControllerId()); + implicitLock(ds); + assertThat(targetManagement.getByControllerID(target.getControllerId()).get().getUpdateStatus()) + .as("wrong update status").isEqualTo(TargetUpdateStatus.PENDING); + assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).as("wrong assigned ds") + .contains(ds); + final JpaAction action = actionRepository + .findAll( + (root, query, cb) -> + cb.and( + cb.equal(root.get(JpaAction_.target).get(JpaTarget_.id), target.getId()), + cb.equal(root.get(JpaAction_.distributionSet).get(JpaDistributionSet_.id), ds.getId())), + PAGE).getContent().get(0); + assertThat(action).as("action should not be null").isNotNull(); + return action; + } + + private void assertDsExclusivelyAssignedToTargets(final List targets, final long dsId, final boolean active, + final Status status) { + final List assignment = findActionsByDistributionSet(PAGE, dsId).getContent(); + final String currentUsername = tenantAware.getCurrentUsername(); + + assertThat(assignment).hasSize(10).allMatch(action -> action.isActive() == active) + .as("Is assigned to DS " + dsId).allMatch(action -> action.getDistributionSet().getId().equals(dsId)) + .as("State is " + status).allMatch(action -> action.getStatus() == status) + .as("Initiated by " + currentUsername).allMatch(a -> a.getInitiatedBy().equals(currentUsername)); + final long[] targetIds = targets.stream().mapToLong(Target::getId).toArray(); + assertThat(targetIds).as("All targets represented in assignment").containsExactlyInAnyOrder( + assignment.stream().mapToLong(action -> action.getTarget().getId()).toArray()); + } + + private List assignDistributionSetToTargets(final DistributionSet distributionSet, + final Iterable targetIds, final boolean confirmationRequired) { + final List deploymentRequests = new ArrayList<>(); + for (final String controllerId : targetIds) { + deploymentRequests.add(new DeploymentRequest(controllerId, distributionSet.getId(), ActionType.FORCED, 0, + null, null, null, null, confirmationRequired)); + } + return deploymentManagement.assignDistributionSets(deploymentRequests); + } + + private int getResultingActionCount(final List results) { + return results.stream().map(DistributionSetAssignmentResult::getTotal).reduce(0, Integer::sum); + } + /** * Helper methods that creates 2 lists of targets and a list of distribution * sets. @@ -1668,18 +1667,12 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { * All created distribution sets are assigned to all targets of the target * list deployedTargets. * - * @param undeployedTargetPrefix - * prefix to be used as target controller prefix - * @param noOfUndeployedTargets - * number of targets which remain undeployed - * @param deployedTargetPrefix - * prefix to be used as target controller prefix - * @param noOfDeployedTargets - * number of targets to which the created distribution sets assigned - * @param noOfDistributionSets - * number of distribution sets - * @param distributionSetPrefix - * prefix for the created distribution sets + * @param undeployedTargetPrefix prefix to be used as target controller prefix + * @param noOfUndeployedTargets number of targets which remain undeployed + * @param deployedTargetPrefix prefix to be used as target controller prefix + * @param noOfDeployedTargets number of targets to which the created distribution sets assigned + * @param noOfDistributionSets number of distribution sets + * @param distributionSetPrefix prefix for the created distribution sets * @return the {@link DeploymentResult} containing all created targets, the * distribution sets, the corresponding IDs for later evaluation in * tests @@ -1720,6 +1713,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } private static class DeploymentResult { + final List deployedTargetIDs = new ArrayList<>(); final List undeployedTargetIDs = new ArrayList<>(); final List distributionSetIDs = new ArrayList<>(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java index ed8380c3c..b5f94575e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java @@ -15,9 +15,11 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import java.util.Collections; import java.util.List; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; -import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; @@ -34,16 +36,11 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; - -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; import org.springframework.data.repository.query.Param; /** * Test class testing the functionality of invalidating a * {@link DistributionSet} - * */ @Feature("Component Tests - Repository") @Story("Distribution set invalidation management") @@ -104,7 +101,7 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe // if status is pending, the assignment has not been canceled assertThat( targetRepository.findById(invalidationTestData.getTargets().get(0).getId()).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.PENDING); + .isEqualTo(TargetUpdateStatus.PENDING); assertThat(findActionsByTarget(target).size()).isEqualTo(1); assertThat(findActionsByTarget(target).get(0).getStatus()).isEqualTo(Status.RUNNING); } @@ -140,17 +137,6 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe } } - private void assertNoScheduledActionsExist(final Rollout rollout) { - assertThat( - actionRepository.findByRolloutIdAndStatus(PAGE, rollout.getId(), Status.SCHEDULED).getTotalElements()) - .isZero(); - } - - private void assertRolloutGroupsAreFinished(final Rollout rollout) { - assertThat(rolloutGroupRepository.findByRolloutId(rollout.getId(), PAGE)) - .allMatch(rolloutGroup -> rolloutGroup.getStatus().equals(RolloutGroupStatus.FINISHED)); - } - @Test @Description("Verify invalidation of distribution sets that removes distribution sets from auto assignments, stops rollouts and cancels assignments") void verifyInvalidateDistributionSetStopAll() { @@ -196,8 +182,8 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe void verifyInvalidateInvalidatedDistributionSetDontThrowsException() { final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet(); distributionSetInvalidationManagement.invalidateDistributionSet( - new DistributionSetInvalidation(Collections.singletonList(distributionSet.getId()), - CancelationType.SOFT, true)); + new DistributionSetInvalidation(Collections.singletonList(distributionSet.getId()), + CancelationType.SOFT, true)); } @Test @@ -234,7 +220,7 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe false)); assertThat( distributionSetRepository.findById(invalidationTestData.getDistributionSet().getId()).get().isValid()) - .isFalse(); + .isFalse(); } @Test @@ -249,7 +235,18 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe true)); assertThat( distributionSetRepository.findById(invalidationTestData.getDistributionSet().getId()).get().isValid()) - .isFalse(); + .isFalse(); + } + + private void assertNoScheduledActionsExist(final Rollout rollout) { + assertThat( + actionRepository.findByRolloutIdAndStatus(PAGE, rollout.getId(), Status.SCHEDULED).getTotalElements()) + .isZero(); + } + + private void assertRolloutGroupsAreFinished(final Rollout rollout) { + assertThat(rolloutGroupRepository.findByRolloutId(rollout.getId(), PAGE)) + .allMatch(rolloutGroup -> rolloutGroup.getStatus().equals(RolloutGroupStatus.FINISHED)); } private InvalidationTestData createInvalidationTestData(final String testName) { @@ -264,7 +261,20 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe return new InvalidationTestData(distributionSet, targets, targetFilterQuery, rollout); } + private void assertDistributionSetInvalidationCount( + final DistributionSetInvalidationCount distributionSetInvalidationCount, + final long expectedAutoAssignmentCount, final long expectedActionCount, final long expectedRolloutCount) { + assertThat(distributionSetInvalidationCount.getAutoAssignmentCount()).isEqualTo(expectedAutoAssignmentCount); + assertThat(distributionSetInvalidationCount.getActionCount()).isEqualTo(expectedActionCount); + assertThat(distributionSetInvalidationCount.getRolloutsCount()).isEqualTo(expectedRolloutCount); + } + + private List findActionsByTarget(@Param("target") Target target) { // order by id ? + return actionRepository.findAll(ActionSpecifications.byTargetControllerId(target.getControllerId())); + } + private static class InvalidationTestData { + private final DistributionSet distributionSet; private final List targets; private final TargetFilterQuery targetFilterQuery; @@ -295,16 +305,4 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe return rollout; } } - - private void assertDistributionSetInvalidationCount( - final DistributionSetInvalidationCount distributionSetInvalidationCount, - final long expectedAutoAssignmentCount, final long expectedActionCount, final long expectedRolloutCount) { - assertThat(distributionSetInvalidationCount.getAutoAssignmentCount()).isEqualTo(expectedAutoAssignmentCount); - assertThat(distributionSetInvalidationCount.getActionCount()).isEqualTo(expectedActionCount); - assertThat(distributionSetInvalidationCount.getRolloutsCount()).isEqualTo(expectedRolloutCount); - } - - private List findActionsByTarget(@Param("target") Target target) { // order by id ? - return actionRepository.findAll(ActionSpecifications.byTargetControllerId(target.getControllerId())); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java index 944b9b6dd..b485464af 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java @@ -28,6 +28,10 @@ import java.util.stream.Stream; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.apache.commons.lang3.RandomStringUtils; import org.assertj.core.api.Condition; import org.eclipse.hawkbit.repository.DistributionSetManagement; @@ -74,20 +78,16 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; - /** * {@link DistributionSetManagement} tests. - * */ @Feature("Component Tests - Repository") @Story("DistributionSet Management") class DistributionSetManagementTest extends AbstractJpaIntegrationTest { public static final String TAG1_NAME = "Tag1"; + @Autowired + RepositoryProperties repositoryProperties; @Test @Description("Verifies that management get access react as specified on calls for non existing entities by means " @@ -213,84 +213,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { createAndUpdateDistributionSetWithInvalidVersion(set); } - @Step - private void createAndUpdateDistributionSetWithInvalidDescription(final DistributionSet set) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too long description should not be created") - .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") - .version("a").description(RandomStringUtils.randomAlphanumeric(513)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with invalid description should not be created") - .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") - .version("a").description(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too long description should not be updated") - .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) - .description(RandomStringUtils.randomAlphanumeric(513)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with invalid characters should not be updated").isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML))); - } - - @Step - private void createAndUpdateDistributionSetWithInvalidName(final DistributionSet set) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too long name should not be created") - .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().version("a") - .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too short name should not be created").isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().version("a").name(""))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with invalid characters in name should not be created") - .isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too long name should not be updated") - .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) - .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with invalid characters should not be updated").isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too short name should not be updated").isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).name(""))); - - } - - @Step - private void createAndUpdateDistributionSetWithInvalidVersion(final DistributionSet set) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too long version should not be created") - .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") - .version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too short version should not be created").isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().name("a").version(""))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too long version should not be updated") - .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) - .version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("entity with too short version should not be updated").isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).version(""))); - - } - @Test @Description("Ensures that it is not possible to create a DS that already exists (unique constraint is on name,version for DS).") void createDuplicateDistributionSetsFailsWithException() { @@ -333,6 +255,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { final List sets = distributionSetManagement.create(creates); assertThat(sets).as("Type should be equal to default type of tenant").are(new Condition() { + @Override public boolean matches(final DistributionSet value) { return value.getType().equals(systemManagement.getTenantMetadata().getDefaultDsType()); @@ -484,7 +407,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { // update data assertThatThrownBy( () -> distributionSetManagement.assignSoftwareModules(set.getId(), Set.of(module.getId()))) - .isInstanceOf(UnsupportedSoftwareModuleForThisDistributionSetException.class); + .isInstanceOf(UnsupportedSoftwareModuleForThisDistributionSetException.class); } @Test @@ -772,223 +695,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { validateDeletedAndCompletedAndTypeAndSearchTextAndTag(dsGroup2, dsTagA, dsGroup2Prefix); } - @Step - private void validateFindAll(final List expectedDistributionsets) { - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder(), expectedDistributionsets); - } - - @Step - private void validateDeleted(final DistributionSet deletedDistributionSet, final int notDeletedSize) { - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.TRUE), - singletonList(deletedDistributionSet)); - - assertThatFilterHasSizeAndDoesNotContainDistributionSet( - DistributionSetFilter.builder().isDeleted(Boolean.FALSE), notDeletedSize, deletedDistributionSet); - } - - @Step - private void validateCompleted(final DistributionSet dsIncomplete, final int completedSize) { - - assertThatFilterHasSizeAndDoesNotContainDistributionSet( - DistributionSetFilter.builder().isComplete(Boolean.TRUE), completedSize, dsIncomplete); - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().isComplete(Boolean.FALSE), singletonList(dsIncomplete)); - } - - @Step - private void validateType(final DistributionSetType newType, final DistributionSet dsNewType, - final int standardDsTypeSize) { - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().typeId(newType.getId()), - singletonList(dsNewType)); - assertThatFilterHasSizeAndDoesNotContainDistributionSet( - DistributionSetFilter.builder().typeId(standardDsType.getId()), standardDsTypeSize, dsNewType); - } - - @Step - private void validateSearchText(final List allDistributionSets, final String dsNamePrefix) { - - final List withTestNamePrefix = allDistributionSets.stream() - .filter(ds -> ds.getName().startsWith(dsNamePrefix)).collect(Collectors.toList()); - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(dsNamePrefix), - withTestNamePrefix); - - final List withTestNameExact = withTestNamePrefix.stream() - .filter(ds -> ds.getName().equals(dsNamePrefix)).collect(Collectors.toList()); - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().searchText(dsNamePrefix + ":"), withTestNameExact); - - final List withTestNameExactAndVersionPrefix = withTestNameExact.stream() - .filter(ds -> ds.getVersion().startsWith("1")).collect(Collectors.toList()); - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().searchText(dsNamePrefix + ":1"), - withTestNameExactAndVersionPrefix); - - final List dsWithExactNameAndVersion = withTestNameExactAndVersionPrefix.stream() - .filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList()); - assertThat(dsWithExactNameAndVersion).hasSize(1); - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().searchText(dsNamePrefix + ":1.0.0"), dsWithExactNameAndVersion); - - final List withVersionPrefix = allDistributionSets.stream() - .filter(ds -> ds.getVersion().startsWith("1.0.")).collect(Collectors.toList()); - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":1.0."), - withVersionPrefix); - - final List withVersionExact = withVersionPrefix.stream() - .filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList()); - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":1.0.0"), - withVersionExact); - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":"), - allDistributionSets); - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(" : "), - allDistributionSets); - } - - @Step - private void validateTags(final DistributionSetTag dsTagA, final DistributionSetTag dsTagB, - final DistributionSetTag dsTagC, final List dsWithTagA, - final List dsWithTagB) { - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().tagNames(singletonList(dsTagA.getName())), dsWithTagA); - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().tagNames(singletonList(dsTagB.getName())), dsWithTagB); - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().tagNames(Arrays.asList(dsTagA.getName(), dsTagB.getName())), - dsWithTagA); - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().tagNames(Arrays.asList(dsTagC.getName(), dsTagB.getName())), - dsWithTagB); - - assertThatFilterDoesNotContainAnyDistributionSet( - DistributionSetFilter.builder().tagNames(singletonList(dsTagC.getName()))); - } - - @Step - private void validateDeletedAndCompleted(final List completedStandardType, - final DistributionSet dsNewType, final DistributionSet dsDeleted) { - - final List completedNotDeleted = new ArrayList<>(completedStandardType); - completedNotDeleted.add(dsNewType); - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().isComplete(Boolean.TRUE).isDeleted(Boolean.FALSE), - completedNotDeleted); - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().isComplete(Boolean.TRUE).isDeleted(Boolean.TRUE), - singletonList(dsDeleted)); - - assertThatFilterDoesNotContainAnyDistributionSet( - DistributionSetFilter.builder().isComplete(Boolean.FALSE).isDeleted(Boolean.TRUE)); - } - - @Step - private void validateDeletedAndCompletedAndType(final List deletedAndCompletedAndStandardType, - final DistributionSet dsDeleted, final DistributionSetType newType, final DistributionSet dsNewType) { - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.FALSE) - .isComplete(Boolean.TRUE).typeId(standardDsType.getId()), deletedAndCompletedAndStandardType); - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isComplete(Boolean.TRUE) - .typeId(standardDsType.getId()).isDeleted(Boolean.TRUE), singletonList(dsDeleted)); - assertThatFilterDoesNotContainAnyDistributionSet(DistributionSetFilter.builder().isDeleted(Boolean.TRUE) - .isComplete(Boolean.FALSE).typeId(standardDsType.getId())); - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().isComplete(Boolean.TRUE).typeId(newType.getId()), - singletonList(dsNewType)); - } - - @Step - private void validateDeletedAndCompletedAndTypeAndSearchText( - final List completedAndStandardTypeAndSearchText, final DistributionSetType newType, - final String text) { - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.FALSE) - .isComplete(Boolean.TRUE).typeId(standardDsType.getId()).searchText(text), - completedAndStandardTypeAndSearchText); - - assertThatFilterDoesNotContainAnyDistributionSet(DistributionSetFilter.builder().isComplete(Boolean.TRUE) - .isDeleted(Boolean.TRUE).typeId(standardDsType.getId()).searchText(text + ":")); - - assertThatFilterDoesNotContainAnyDistributionSet( - DistributionSetFilter.builder().typeId(standardDsType.getId()).searchText(text) - .isComplete(Boolean.FALSE).isDeleted(Boolean.FALSE)); - - assertThatFilterDoesNotContainAnyDistributionSet(DistributionSetFilter.builder().typeId(newType.getId()) - .searchText(text).isComplete(Boolean.TRUE).isDeleted(Boolean.FALSE)); - } - - @Step - private void validateDeletedAndCompletedAndTypeAndSearchText( - final List completedAndNotDeletedStandardTypeAndFilterString, - final DistributionSet dsDeleted, final DistributionSet dsInComplete, final DistributionSet dsNewType, - final DistributionSetType newType, final String filterString) { - - final List completedAndStandardTypeAndFilterString = new ArrayList<>( - completedAndNotDeletedStandardTypeAndFilterString); - completedAndStandardTypeAndFilterString.add(dsDeleted); - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isComplete(Boolean.TRUE) - .typeId(standardDsType.getId()).searchText(filterString), - completedAndStandardTypeAndFilterString); - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().isComplete(Boolean.TRUE).isDeleted(Boolean.FALSE) - .typeId(standardDsType.getId()).searchText(filterString), - completedAndNotDeletedStandardTypeAndFilterString); - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isComplete(Boolean.TRUE) - .isDeleted(Boolean.TRUE).typeId(standardDsType.getId()).searchText(filterString), - singletonList(dsDeleted)); - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().typeId(standardDsType.getId()).searchText(filterString) - .isComplete(Boolean.FALSE).isDeleted(Boolean.FALSE), - singletonList(dsInComplete)); - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().typeId(newType.getId()) - .searchText(filterString).isComplete(Boolean.TRUE).isDeleted(Boolean.FALSE), - singletonList(dsNewType)); - } - - @Step - private void validateDeletedAndCompletedAndTypeAndSearchTextAndTag( - final List completedAndStandartTypeAndSearchTextAndTagA, final DistributionSetTag dsTagA, - final String text) { - - assertThatFilterContainsOnlyGivenDistributionSets( - DistributionSetFilter.builder().isComplete(Boolean.TRUE).typeId(standardDsType.getId()) - .searchText(text).tagNames(singletonList(dsTagA.getName())), - completedAndStandartTypeAndSearchTextAndTagA); - - assertThatFilterDoesNotContainAnyDistributionSet(DistributionSetFilter.builder() - .typeId(standardDsType.getId()).searchText(text).tagNames(singletonList(dsTagA.getName())) - .isComplete(Boolean.FALSE).isDeleted(Boolean.FALSE)); - } - - private void assertThatFilterContainsOnlyGivenDistributionSets(final DistributionSetFilterBuilder filterBuilder, - final List distributionSets) { - final int expectedDsSize = distributionSets.size(); - assertThat(distributionSetManagement.findByDistributionSetFilter(PAGE, filterBuilder.build()).getContent()) - .hasSize(expectedDsSize).containsOnly(distributionSets.toArray(new DistributionSet[expectedDsSize])); - } - - private void assertThatFilterDoesNotContainAnyDistributionSet(final DistributionSetFilterBuilder filterBuilder) { - assertThat(distributionSetManagement.findByDistributionSetFilter(PAGE, filterBuilder.build()).getContent()) - .isEmpty(); - } - - private void assertThatFilterHasSizeAndDoesNotContainDistributionSet( - final DistributionSetFilterBuilder filterBuilder, final int size, final DistributionSet ds) { - assertThat(distributionSetManagement.findByDistributionSetFilter(PAGE, filterBuilder.build()).getContent()) - .hasSize(size).doesNotContain(ds); - } - @Test @Description("Simple DS load without the related data that should be loaded lazy.") void findDistributionSetsWithoutLazy() { @@ -1097,25 +803,24 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { .isEqualTo(softwareModuleCount); } - @Autowired RepositoryProperties repositoryProperties; @Test @Description("Test implicit locks for a DS and skip tags.") void isImplicitLockApplicableForDistributionSet() { final JpaDistributionSetManagement distributionSetManagement = - (JpaDistributionSetManagement)this.distributionSetManagement; + (JpaDistributionSetManagement) this.distributionSetManagement; final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-non-skip"); // assert that implicit lock is applicable for non skip tags assertThat(distributionSetManagement.isImplicitLockApplicable(distributionSet)).isTrue(); assertThat(repositoryProperties.getSkipImplicitLockForTags().size()).isNotEqualTo(0); final List skipTags = distributionSetTagManagement.create( - repositoryProperties.getSkipImplicitLockForTags().stream() - .map(String::toLowerCase) - // remove same in case-insensitive terms tags - // in of case-insensitive db's it will end up as same names and constraint violation (?) - .distinct() - .map(skipTag -> entityFactory.tag().create().name(skipTag)) - .toList()); + repositoryProperties.getSkipImplicitLockForTags().stream() + .map(String::toLowerCase) + // remove same in case-insensitive terms tags + // in of case-insensitive db's it will end up as same names and constraint violation (?) + .distinct() + .map(skipTag -> entityFactory.tag().create().name(skipTag)) + .toList()); // assert that implicit lock locks for every skip tag skipTags.forEach(skipTag -> { DistributionSet distributionSetWithSkipTag = @@ -1324,10 +1029,14 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { assertThat(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds3.getId())).isEmpty(); Optional rollout = rolloutManagement.get(rollout1.getId()); - rollout.ifPresent(value -> assertThat(Rollout.RolloutStatus.valueOf(String.valueOf(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds1.getId()).get(0).getName()))).isEqualTo(value.getStatus())); + rollout.ifPresent(value -> assertThat(Rollout.RolloutStatus.valueOf( + String.valueOf(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds1.getId()).get(0).getName()))).isEqualTo( + value.getStatus())); rollout = rolloutManagement.get(rollout2.getId()); - rollout.ifPresent(value -> assertThat(Rollout.RolloutStatus.valueOf(String.valueOf(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds2.getId()).get(0).getName()))).isEqualTo(value.getStatus())); + rollout.ifPresent(value -> assertThat(Rollout.RolloutStatus.valueOf( + String.valueOf(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds2.getId()).get(0).getName()))).isEqualTo( + value.getStatus())); } @Test @@ -1366,6 +1075,301 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { assertThat(distributionSetManagement.countAutoAssignmentsForDistributionSet(ds2.getId())).isNull(); } + @Step + private void createAndUpdateDistributionSetWithInvalidDescription(final DistributionSet set) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too long description should not be created") + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") + .version("a").description(RandomStringUtils.randomAlphanumeric(513)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with invalid description should not be created") + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") + .version("a").description(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too long description should not be updated") + .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) + .description(RandomStringUtils.randomAlphanumeric(513)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with invalid characters should not be updated").isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML))); + } + + @Step + private void createAndUpdateDistributionSetWithInvalidName(final DistributionSet set) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too long name should not be created") + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().version("a") + .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too short name should not be created").isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().version("a").name(""))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with invalid characters in name should not be created") + .isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too long name should not be updated") + .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) + .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with invalid characters should not be updated").isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too short name should not be updated").isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).name(""))); + + } + + @Step + private void createAndUpdateDistributionSetWithInvalidVersion(final DistributionSet set) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too long version should not be created") + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") + .version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too short version should not be created").isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().name("a").version(""))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too long version should not be updated") + .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) + .version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("entity with too short version should not be updated").isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).version(""))); + + } + + @Step + private void validateFindAll(final List expectedDistributionsets) { + + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder(), expectedDistributionsets); + } + + @Step + private void validateDeleted(final DistributionSet deletedDistributionSet, final int notDeletedSize) { + + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.TRUE), + singletonList(deletedDistributionSet)); + + assertThatFilterHasSizeAndDoesNotContainDistributionSet( + DistributionSetFilter.builder().isDeleted(Boolean.FALSE), notDeletedSize, deletedDistributionSet); + } + + @Step + private void validateCompleted(final DistributionSet dsIncomplete, final int completedSize) { + + assertThatFilterHasSizeAndDoesNotContainDistributionSet( + DistributionSetFilter.builder().isComplete(Boolean.TRUE), completedSize, dsIncomplete); + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().isComplete(Boolean.FALSE), singletonList(dsIncomplete)); + } + + @Step + private void validateType(final DistributionSetType newType, final DistributionSet dsNewType, + final int standardDsTypeSize) { + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().typeId(newType.getId()), + singletonList(dsNewType)); + assertThatFilterHasSizeAndDoesNotContainDistributionSet( + DistributionSetFilter.builder().typeId(standardDsType.getId()), standardDsTypeSize, dsNewType); + } + + @Step + private void validateSearchText(final List allDistributionSets, final String dsNamePrefix) { + + final List withTestNamePrefix = allDistributionSets.stream() + .filter(ds -> ds.getName().startsWith(dsNamePrefix)).collect(Collectors.toList()); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(dsNamePrefix), + withTestNamePrefix); + + final List withTestNameExact = withTestNamePrefix.stream() + .filter(ds -> ds.getName().equals(dsNamePrefix)).collect(Collectors.toList()); + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().searchText(dsNamePrefix + ":"), withTestNameExact); + + final List withTestNameExactAndVersionPrefix = withTestNameExact.stream() + .filter(ds -> ds.getVersion().startsWith("1")).collect(Collectors.toList()); + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().searchText(dsNamePrefix + ":1"), + withTestNameExactAndVersionPrefix); + + final List dsWithExactNameAndVersion = withTestNameExactAndVersionPrefix.stream() + .filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList()); + assertThat(dsWithExactNameAndVersion).hasSize(1); + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().searchText(dsNamePrefix + ":1.0.0"), dsWithExactNameAndVersion); + + final List withVersionPrefix = allDistributionSets.stream() + .filter(ds -> ds.getVersion().startsWith("1.0.")).collect(Collectors.toList()); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":1.0."), + withVersionPrefix); + + final List withVersionExact = withVersionPrefix.stream() + .filter(ds -> ds.getVersion().equals("1.0.0")).collect(Collectors.toList()); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":1.0.0"), + withVersionExact); + + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":"), + allDistributionSets); + + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(" : "), + allDistributionSets); + } + + @Step + private void validateTags(final DistributionSetTag dsTagA, final DistributionSetTag dsTagB, + final DistributionSetTag dsTagC, final List dsWithTagA, + final List dsWithTagB) { + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().tagNames(singletonList(dsTagA.getName())), dsWithTagA); + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().tagNames(singletonList(dsTagB.getName())), dsWithTagB); + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().tagNames(Arrays.asList(dsTagA.getName(), dsTagB.getName())), + dsWithTagA); + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().tagNames(Arrays.asList(dsTagC.getName(), dsTagB.getName())), + dsWithTagB); + + assertThatFilterDoesNotContainAnyDistributionSet( + DistributionSetFilter.builder().tagNames(singletonList(dsTagC.getName()))); + } + + @Step + private void validateDeletedAndCompleted(final List completedStandardType, + final DistributionSet dsNewType, final DistributionSet dsDeleted) { + + final List completedNotDeleted = new ArrayList<>(completedStandardType); + completedNotDeleted.add(dsNewType); + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().isComplete(Boolean.TRUE).isDeleted(Boolean.FALSE), + completedNotDeleted); + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().isComplete(Boolean.TRUE).isDeleted(Boolean.TRUE), + singletonList(dsDeleted)); + + assertThatFilterDoesNotContainAnyDistributionSet( + DistributionSetFilter.builder().isComplete(Boolean.FALSE).isDeleted(Boolean.TRUE)); + } + + @Step + private void validateDeletedAndCompletedAndType(final List deletedAndCompletedAndStandardType, + final DistributionSet dsDeleted, final DistributionSetType newType, final DistributionSet dsNewType) { + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.FALSE) + .isComplete(Boolean.TRUE).typeId(standardDsType.getId()), deletedAndCompletedAndStandardType); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isComplete(Boolean.TRUE) + .typeId(standardDsType.getId()).isDeleted(Boolean.TRUE), singletonList(dsDeleted)); + assertThatFilterDoesNotContainAnyDistributionSet(DistributionSetFilter.builder().isDeleted(Boolean.TRUE) + .isComplete(Boolean.FALSE).typeId(standardDsType.getId())); + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().isComplete(Boolean.TRUE).typeId(newType.getId()), + singletonList(dsNewType)); + } + + @Step + private void validateDeletedAndCompletedAndTypeAndSearchText( + final List completedAndStandardTypeAndSearchText, final DistributionSetType newType, + final String text) { + + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.FALSE) + .isComplete(Boolean.TRUE).typeId(standardDsType.getId()).searchText(text), + completedAndStandardTypeAndSearchText); + + assertThatFilterDoesNotContainAnyDistributionSet(DistributionSetFilter.builder().isComplete(Boolean.TRUE) + .isDeleted(Boolean.TRUE).typeId(standardDsType.getId()).searchText(text + ":")); + + assertThatFilterDoesNotContainAnyDistributionSet( + DistributionSetFilter.builder().typeId(standardDsType.getId()).searchText(text) + .isComplete(Boolean.FALSE).isDeleted(Boolean.FALSE)); + + assertThatFilterDoesNotContainAnyDistributionSet(DistributionSetFilter.builder().typeId(newType.getId()) + .searchText(text).isComplete(Boolean.TRUE).isDeleted(Boolean.FALSE)); + } + + @Step + private void validateDeletedAndCompletedAndTypeAndSearchText( + final List completedAndNotDeletedStandardTypeAndFilterString, + final DistributionSet dsDeleted, final DistributionSet dsInComplete, final DistributionSet dsNewType, + final DistributionSetType newType, final String filterString) { + + final List completedAndStandardTypeAndFilterString = new ArrayList<>( + completedAndNotDeletedStandardTypeAndFilterString); + completedAndStandardTypeAndFilterString.add(dsDeleted); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isComplete(Boolean.TRUE) + .typeId(standardDsType.getId()).searchText(filterString), + completedAndStandardTypeAndFilterString); + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().isComplete(Boolean.TRUE).isDeleted(Boolean.FALSE) + .typeId(standardDsType.getId()).searchText(filterString), + completedAndNotDeletedStandardTypeAndFilterString); + + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isComplete(Boolean.TRUE) + .isDeleted(Boolean.TRUE).typeId(standardDsType.getId()).searchText(filterString), + singletonList(dsDeleted)); + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().typeId(standardDsType.getId()).searchText(filterString) + .isComplete(Boolean.FALSE).isDeleted(Boolean.FALSE), + singletonList(dsInComplete)); + + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().typeId(newType.getId()) + .searchText(filterString).isComplete(Boolean.TRUE).isDeleted(Boolean.FALSE), + singletonList(dsNewType)); + } + + @Step + private void validateDeletedAndCompletedAndTypeAndSearchTextAndTag( + final List completedAndStandartTypeAndSearchTextAndTagA, final DistributionSetTag dsTagA, + final String text) { + + assertThatFilterContainsOnlyGivenDistributionSets( + DistributionSetFilter.builder().isComplete(Boolean.TRUE).typeId(standardDsType.getId()) + .searchText(text).tagNames(singletonList(dsTagA.getName())), + completedAndStandartTypeAndSearchTextAndTagA); + + assertThatFilterDoesNotContainAnyDistributionSet(DistributionSetFilter.builder() + .typeId(standardDsType.getId()).searchText(text).tagNames(singletonList(dsTagA.getName())) + .isComplete(Boolean.FALSE).isDeleted(Boolean.FALSE)); + } + + private void assertThatFilterContainsOnlyGivenDistributionSets(final DistributionSetFilterBuilder filterBuilder, + final List distributionSets) { + final int expectedDsSize = distributionSets.size(); + assertThat(distributionSetManagement.findByDistributionSetFilter(PAGE, filterBuilder.build()).getContent()) + .hasSize(expectedDsSize).containsOnly(distributionSets.toArray(new DistributionSet[expectedDsSize])); + } + + private void assertThatFilterDoesNotContainAnyDistributionSet(final DistributionSetFilterBuilder filterBuilder) { + assertThat(distributionSetManagement.findByDistributionSetFilter(PAGE, filterBuilder.build()).getContent()) + .isEmpty(); + } + + private void assertThatFilterHasSizeAndDoesNotContainDistributionSet( + final DistributionSetFilterBuilder filterBuilder, final int size, final DistributionSet ds) { + assertThat(distributionSetManagement.findByDistributionSetFilter(PAGE, filterBuilder.build()).getContent()) + .hasSize(size).doesNotContain(ds); + } + // can be removed with java-11 private T getOrThrow(final Optional opt) { return opt.orElseThrow(NoSuchElementException::new); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementTest.java index 9b223fd76..f376f5ba1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementTest.java @@ -22,6 +22,10 @@ import java.util.Random; import java.util.stream.Collectors; import java.util.stream.Stream; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.builder.TagCreate; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagUpdatedEvent; @@ -33,17 +37,10 @@ import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetFilter; import org.eclipse.hawkbit.repository.model.DistributionSetTag; -import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.Tag; -import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; import org.junit.jupiter.api.Test; - -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; import org.springframework.data.domain.Pageable; /** @@ -53,6 +50,8 @@ import org.springframework.data.domain.Pageable; @Story("DistributionSet Tag Management") public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { + private static final Random RND = new Random(); + @Test @Description("Verifies that management get access reacts as specfied on calls for non existing entities by means " + "of Optional not present.") @@ -137,17 +136,6 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest Stream.of(dsCs, dsACs, dsBCs, dsABCs)); } - @Step - private void verifyExpectedFilteredDistributionSets(final DistributionSetFilter.DistributionSetFilterBuilder distributionSetFilterBuilder, - final Stream> expectedFilteredDistributionSets) { - final Collection retrievedFilteredDsIds = distributionSetManagement - .findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()).stream() - .map(DistributionSet::getId).collect(Collectors.toList()); - final Collection expectedFilteredDsIds = expectedFilteredDistributionSets.flatMap(Collection::stream) - .map(DistributionSet::getId).collect(Collectors.toList()); - assertThat(retrievedFilteredDsIds).hasSameElementsAs(expectedFilteredDsIds); - } - @Test @Description("Verifies assign/unassign.") public void assignAndUnassignDistributionSetTags() { @@ -162,7 +150,9 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest assertThat(result).size().isEqualTo(20); assertThat(result).containsAll(distributionSetManagement .get(groupA.stream().map(DistributionSet::getId).collect(Collectors.toList()))); - assertThat(distributionSetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent().stream().map(DistributionSet::getId).sorted().toList()) + assertThat( + distributionSetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent().stream().map(DistributionSet::getId).sorted() + .toList()) .isEqualTo(groupA.stream().map(DistributionSet::getId).sorted().toList()); final Collection groupAB = concat(groupA, groupB); @@ -171,7 +161,9 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest assertThat(result).size().isEqualTo(40); assertThat(result).containsAll(distributionSetManagement .get(groupAB.stream().map(DistributionSet::getId).collect(Collectors.toList()))); - assertThat(distributionSetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent().stream().map(DistributionSet::getId).sorted().toList()) + assertThat( + distributionSetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent().stream().map(DistributionSet::getId).sorted() + .toList()) .isEqualTo(groupAB.stream().map(DistributionSet::getId).sorted().toList()); // toggle A+B -> both unassigned @@ -182,7 +174,6 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest assertThat(distributionSetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent()).isEmpty(); } - private static final Random RND = new Random(); @Test @Description("Verifies that tagging of set containing missing DS throws meaningful and correct exception.") public void failOnMissingDs() { @@ -312,6 +303,17 @@ public class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest assertThat(distributionSetTagRepository.findAll()).as("Wrong size of tags created").hasSize(tags.size()); } + @Step + private void verifyExpectedFilteredDistributionSets(final DistributionSetFilter.DistributionSetFilterBuilder distributionSetFilterBuilder, + final Stream> expectedFilteredDistributionSets) { + final Collection retrievedFilteredDsIds = distributionSetManagement + .findByDistributionSetFilter(PAGE, distributionSetFilterBuilder.build()).stream() + .map(DistributionSet::getId).collect(Collectors.toList()); + final Collection expectedFilteredDsIds = expectedFilteredDistributionSets.flatMap(Collection::stream) + .map(DistributionSet::getId).collect(Collectors.toList()); + assertThat(retrievedFilteredDsIds).hasSameElementsAs(expectedFilteredDsIds); + } + private List createDsSetsWithTags() { final Collection sets = testdataFactory.createDistributionSets(20); final Iterable tags = testdataFactory.createDistributionSetTags(20); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementTest.java index af7d50b8a..868bcb0dd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementTest.java @@ -21,8 +21,11 @@ import java.util.Set; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.apache.commons.lang3.RandomStringUtils; -import org.assertj.core.util.Lists; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; @@ -42,18 +45,13 @@ import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; import org.junit.jupiter.api.Test; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; - /** * {@link DistributionSetManagement} tests. - * */ @Feature("Component Tests - Repository") @Story("DistributionSet Management") public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { + @Test @Description("Verifies that management get access react as specfied on calls for non existing entities by means " + "of Optional not present.") @@ -77,13 +75,13 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes softwareModuleTypes), "DistributionSetType"); final List notExistingSwModuleTypeIds = Collections.singletonList(NOT_EXIST_IDL); verifyThrownExceptionBy(() -> distributionSetTypeManagement.assignMandatorySoftwareModuleTypes( - testdataFactory.findOrCreateDistributionSetType("xxx", "xxx").getId(), notExistingSwModuleTypeIds), + testdataFactory.findOrCreateDistributionSetType("xxx", "xxx").getId(), notExistingSwModuleTypeIds), "SoftwareModuleType"); verifyThrownExceptionBy(() -> distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(NOT_EXIST_IDL, softwareModuleTypes), "DistributionSetType"); verifyThrownExceptionBy(() -> distributionSetTypeManagement.assignOptionalSoftwareModuleTypes( - testdataFactory.findOrCreateDistributionSetType("xxx", "xxx").getId(), notExistingSwModuleTypeIds), + testdataFactory.findOrCreateDistributionSetType("xxx", "xxx").getId(), notExistingSwModuleTypeIds), "SoftwareModuleType"); verifyThrownExceptionBy(() -> distributionSetTypeManagement.delete(NOT_EXIST_IDL), "DistributionSetType"); @@ -106,96 +104,6 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes createAndUpdateDistributionSetWithInvalidVersion(set); } - @Step - private void createAndUpdateDistributionSetWithInvalidDescription(final DistributionSet set) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with too long description should not be created") - .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") - .version("a").description(RandomStringUtils.randomAlphanumeric(513)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set invalid description text should not be created") - .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") - .version("a").description(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with too long description should not be updated") - .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) - .description(RandomStringUtils.randomAlphanumeric(513)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with invalid description should not be updated").isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML))); - - } - - @Step - private void createAndUpdateDistributionSetWithInvalidName(final DistributionSet set) { - - assertThatExceptionOfType(ConstraintViolationException.class).as("set with too long name should not be created") - .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().version("a") - .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class).as("set with invalid name should not be created") - .isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with too short name should not be created").isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().version("a").name(""))); - - assertThatExceptionOfType(ConstraintViolationException.class).as("set with null name should not be created") - .isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().version("a").name(null))); - - assertThatExceptionOfType(ConstraintViolationException.class).as("set with too long name should not be updated") - .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) - .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class).as("set with invalid name should not be updated") - .isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with too short name should not be updated").isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).name(""))); - } - - @Step - private void createAndUpdateDistributionSetWithInvalidVersion(final DistributionSet set) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with too long version should not be created") - .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") - .version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with invalid version should not be created").isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().name("a").version(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with too short version should not be created").isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().name("a").version(""))); - - assertThatExceptionOfType(ConstraintViolationException.class).as("set with null version should not be created") - .isThrownBy(() -> distributionSetManagement - .create(entityFactory.distributionSet().create().name("a").version(null))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with too long version should not be updated") - .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) - .version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with invalid version should not be updated").isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).version(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("set with too short version should not be updated").isThrownBy(() -> distributionSetManagement - .update(entityFactory.distributionSet().update(set.getId()).version(""))); - } - @Test @Description("Tests the successful module update of unused distribution set type which is in fact allowed.") public void updateUnassignedDistributionSetTypeModules() { @@ -290,16 +198,7 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes assertThatThrownBy(() -> distributionSetTypeManagement .assignMandatorySoftwareModuleTypes(nonUpdatableType.getId(), Set.of(osType.getId()))) - .isInstanceOf(EntityReadOnlyException.class); - } - - private DistributionSetType createDistributionSetTypeUsedByDs() { - final DistributionSetType nonUpdatableType = distributionSetTypeManagement.create(entityFactory - .distributionSetType().create().key("updatableType").name("to be deleted").colour("test123")); - assertThat(distributionSetTypeManagement.getByKey("updatableType").get().getMandatoryModuleTypes()).isEmpty(); - distributionSetManagement.create(entityFactory.distributionSet().create().name("newtypesoft").version("1") - .type(nonUpdatableType.getKey())); - return nonUpdatableType; + .isInstanceOf(EntityReadOnlyException.class); } @Test @@ -365,4 +264,103 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes assertThat(jpaDistributionSetType.checkComplete(distributionSet)).isFalse(); } + + @Step + private void createAndUpdateDistributionSetWithInvalidDescription(final DistributionSet set) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with too long description should not be created") + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") + .version("a").description(RandomStringUtils.randomAlphanumeric(513)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set invalid description text should not be created") + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") + .version("a").description(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with too long description should not be updated") + .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) + .description(RandomStringUtils.randomAlphanumeric(513)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with invalid description should not be updated").isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML))); + + } + + @Step + private void createAndUpdateDistributionSetWithInvalidName(final DistributionSet set) { + + assertThatExceptionOfType(ConstraintViolationException.class).as("set with too long name should not be created") + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().version("a") + .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class).as("set with invalid name should not be created") + .isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with too short name should not be created").isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().version("a").name(""))); + + assertThatExceptionOfType(ConstraintViolationException.class).as("set with null name should not be created") + .isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().version("a").name(null))); + + assertThatExceptionOfType(ConstraintViolationException.class).as("set with too long name should not be updated") + .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) + .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class).as("set with invalid name should not be updated") + .isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with too short name should not be updated").isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).name(""))); + } + + @Step + private void createAndUpdateDistributionSetWithInvalidVersion(final DistributionSet set) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with too long version should not be created") + .isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a") + .version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with invalid version should not be created").isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().name("a").version(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with too short version should not be created").isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().name("a").version(""))); + + assertThatExceptionOfType(ConstraintViolationException.class).as("set with null version should not be created") + .isThrownBy(() -> distributionSetManagement + .create(entityFactory.distributionSet().create().name("a").version(null))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with too long version should not be updated") + .isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) + .version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with invalid version should not be updated").isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).version(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("set with too short version should not be updated").isThrownBy(() -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).version(""))); + } + + private DistributionSetType createDistributionSetTypeUsedByDs() { + final DistributionSetType nonUpdatableType = distributionSetTypeManagement.create(entityFactory + .distributionSetType().create().key("updatableType").name("to be deleted").colour("test123")); + assertThat(distributionSetTypeManagement.getByKey("updatableType").get().getMandatoryModuleTypes()).isEmpty(); + distributionSetManagement.create(entityFactory.distributionSet().create().name("newtypesoft").version("1") + .type(nonUpdatableType.getKey())); + return nonUpdatableType; + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/LazyControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/LazyControllerManagementTest.java index f03ddf0a0..582ddfcab 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/LazyControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/LazyControllerManagementTest.java @@ -13,6 +13,9 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.concurrent.TimeUnit; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; @@ -24,10 +27,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.TestPropertySource; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("Controller Management") @TestPropertySource(locations = "classpath:/jpa-test.properties", properties = { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutGroupManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutGroupManagementTest.java index f6f933d30..0c0dbed13 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutGroupManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutGroupManagementTest.java @@ -13,6 +13,9 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.List; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent; @@ -38,10 +41,6 @@ import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.util.CollectionUtils; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("Rollout Management") class RolloutGroupManagementTest extends AbstractJpaIntegrationTest { @@ -159,42 +158,11 @@ class RolloutGroupManagementTest extends AbstractJpaIntegrationTest { .hasSize((int) rolloutGroupManagement.countTargetsOfRolloutsGroup(rolloutGroup.getId())); targetsWithActionStatus = rolloutGroupManagement.findAllTargetsOfRolloutGroupWithActionStatus( - PageRequest.of(0, 500, Sort.by(Direction.DESC, "lastActionStatusCode")), rolloutGroup.getId()) + PageRequest.of(0, 500, Sort.by(Direction.DESC, "lastActionStatusCode")), rolloutGroup.getId()) .getContent(); assertSortedListOfActionStatus(targetsWithActionStatus, target24, 24, target0, 0); } - private void assertSortedListOfActionStatus(final List targetsWithActionStatus, - final Target first, final Integer firstStatusCode, final Target last, final Integer lastStatusCode) { - assertTargetAndActionStatusCode(CollectionUtils.firstElement(targetsWithActionStatus), first, firstStatusCode); - assertTargetAndActionStatusCode(CollectionUtils.lastElement(targetsWithActionStatus), last, lastStatusCode); - } - - private void assertTargetAndActionStatusCode(final TargetWithActionStatus targetWithActionStatus, - final Target target, final Integer actionStatusCode) { - assertThat(targetWithActionStatus.getTarget().getControllerId()).isEqualTo(target.getControllerId()); - assertThat(targetWithActionStatus.getLastActionStatusCode()).isEqualTo(actionStatusCode); - } - - private void assertTargetNotNullAndActionStatusNullAndActionStatusCode( - final List targetsWithActionStatus, final Integer actionStatusCode) { - targetsWithActionStatus.forEach(targetWithActionStatus -> { - assertThat(targetWithActionStatus.getTarget().getControllerId()).isNotNull(); - assertThat(targetWithActionStatus.getStatus()).isNull(); - assertThat(targetWithActionStatus.getLastActionStatusCode()).isEqualTo(actionStatusCode); - }); - } - - private void assertTargetNotNullAndActionStatusAndActionStatusCode( - final List targetsWithActionStatus, final Status actionStatus, - final Integer actionStatusCode) { - targetsWithActionStatus.forEach(targetWithActionStatus -> { - assertThat(targetWithActionStatus.getTarget().getControllerId()).isNotNull(); - assertThat(targetWithActionStatus.getStatus()).isEqualTo(actionStatus); - assertThat(targetWithActionStatus.getLastActionStatusCode()).isEqualTo(actionStatusCode); - }); - } - @Test @Description("Verifies that Rollouts in different states are handled correctly.") void findAllTargetsOfRolloutGroupWithActionStatus() { @@ -249,6 +217,37 @@ class RolloutGroupManagementTest extends AbstractJpaIntegrationTest { Status.RUNNING, 100); } + private void assertSortedListOfActionStatus(final List targetsWithActionStatus, + final Target first, final Integer firstStatusCode, final Target last, final Integer lastStatusCode) { + assertTargetAndActionStatusCode(CollectionUtils.firstElement(targetsWithActionStatus), first, firstStatusCode); + assertTargetAndActionStatusCode(CollectionUtils.lastElement(targetsWithActionStatus), last, lastStatusCode); + } + + private void assertTargetAndActionStatusCode(final TargetWithActionStatus targetWithActionStatus, + final Target target, final Integer actionStatusCode) { + assertThat(targetWithActionStatus.getTarget().getControllerId()).isEqualTo(target.getControllerId()); + assertThat(targetWithActionStatus.getLastActionStatusCode()).isEqualTo(actionStatusCode); + } + + private void assertTargetNotNullAndActionStatusNullAndActionStatusCode( + final List targetsWithActionStatus, final Integer actionStatusCode) { + targetsWithActionStatus.forEach(targetWithActionStatus -> { + assertThat(targetWithActionStatus.getTarget().getControllerId()).isNotNull(); + assertThat(targetWithActionStatus.getStatus()).isNull(); + assertThat(targetWithActionStatus.getLastActionStatusCode()).isEqualTo(actionStatusCode); + }); + } + + private void assertTargetNotNullAndActionStatusAndActionStatusCode( + final List targetsWithActionStatus, final Status actionStatus, + final Integer actionStatusCode) { + targetsWithActionStatus.forEach(targetWithActionStatus -> { + assertThat(targetWithActionStatus.getTarget().getControllerId()).isNotNull(); + assertThat(targetWithActionStatus.getStatus()).isEqualTo(actionStatus); + assertThat(targetWithActionStatus.getLastActionStatusCode()).isEqualTo(actionStatusCode); + }); + } + private void assertThatListIsSortedByTargetName(final List targets, final Direction sortDirection) { String previousName = null; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java index 55e7d63da..477800961 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java @@ -9,6 +9,11 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; @@ -24,17 +29,10 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.PropertySource; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.test.context.TestPropertySource; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.assertj.core.api.Assertions.assertThat; - /** * Junit tests for RolloutManagement. */ @@ -300,7 +298,6 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest { assertGroup(dynamic2, true, RolloutGroupStatus.RUNNING, 4); // assign the target created when paused } - @Test @Description("Verifies a simple pure (no static groups) dynamic rollout flow with a dynamic group template") void dynamicRolloutPureFlow() { @@ -362,7 +359,7 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest { assertAndGetRunning(rollout, 1); // remains on in the first dynamic rolloutHandler.handleAll(); - assertRollout(rollout, true, RolloutStatus.RUNNING, 2, 8); + assertRollout(rollout, true, RolloutStatus.RUNNING, 2, 8); assertGroup(dynamic1, true, RolloutGroupStatus.RUNNING, 6); // first dynamic threshold is reached, second is started assertGroup(dynamic2, true, RolloutGroupStatus.RUNNING, 2); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java index 6d87cfc1d..c6e540f3f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java @@ -29,6 +29,10 @@ import java.util.stream.Stream; import jakarta.validation.ConstraintViolationException; import jakarta.validation.ValidationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.apache.commons.lang3.RandomStringUtils; import org.assertj.core.api.Assertions; import org.assertj.core.api.Condition; @@ -96,11 +100,6 @@ import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; - /** * Junit tests for RolloutManagement. */ @@ -108,6 +107,68 @@ import io.qameta.allure.Story; @Story("Rollout Management") class RolloutManagementTest extends AbstractJpaIntegrationTest { + /** + * Tests static assignment aspects of the dynamic group assignment filters. + */ + @Test + @Description("Dynamic group doesn't override newer static group assignments") + public void dynamicGroupDoesntOverrideItsOrNewerStaticGroups() { + final int amountGroups = 1; // static only + final String targetPrefix = "controller-dynamic-rollout-"; + final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds"); + + testdataFactory.createTargets(targetPrefix, 0, amountGroups * 2); + final Rollout dynamicRollout = testdataFactory.createRolloutByVariables("dynamic", "static rollout", amountGroups, + "controllerid==" + targetPrefix + "*", distributionSet, "0", "30", ActionType.FORCED, 1000, false, true); + rolloutManagement.start(dynamicRollout.getId()); + rolloutHandler.handleAll(); + assertRollout(dynamicRollout, true, RolloutStatus.RUNNING, amountGroups + 1, amountGroups * 2); + final List dynamicGroups = rolloutGroupManagement.findByRollout( + new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id")), + dynamicRollout.getId()).getContent(); + for (int i = 0; i < dynamicGroups.size(); i++) { + final RolloutGroup group = dynamicGroups.get(i); + if (i + 1 == dynamicGroups.size()) { + assertGroup(group, true, RolloutGroupStatus.SCHEDULED, 0); + } else { + assertGroup(group, false, RolloutGroupStatus.RUNNING, 2); + } + } + assertAndGetRunning(dynamicRollout, 2).forEach(this::finishAction); + rolloutHandler.handleAll(); + for (int i = 0; i < dynamicGroups.size(); i++) { + final RolloutGroup group = dynamicGroups.get(i); + if (i + 1 == dynamicGroups.size()) { + assertGroup(group, true, RolloutGroupStatus.RUNNING, 0); + } else { + assertGroup(group, false, RolloutGroupStatus.FINISHED, 2); + } + } + assertAndGetRunning(dynamicRollout, 0); + rolloutHandler.handleAll(); + // NB: asserts that dynamic group doesn't get from its static groups (already finished action targets) + assertGroup(dynamicGroups.get(dynamicGroups.size() - 1), true, RolloutGroupStatus.RUNNING, 0); + assertAndGetRunning(dynamicRollout, 0); + rolloutManagement.pauseRollout(dynamicRollout.getId()); + rolloutHandler.handleAll(); + + testdataFactory.createTargets(targetPrefix, amountGroups * 2, amountGroups); + final Rollout staticRollout = testdataFactory.createRolloutByVariables("static", "static rollout", amountGroups, + "controllerid==" + targetPrefix + "*", distributionSet, "0", "30", ActionType.FORCED, 0, false, false); + rolloutManagement.start(staticRollout.getId()); + rolloutHandler.handleAll(); + assertRollout(staticRollout, false, RolloutStatus.RUNNING, amountGroups, amountGroups * 3); + final List staticGroups = rolloutGroupManagement.findByRollout( + new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id")), + staticRollout.getId()).getContent(); + staticGroups.forEach(group -> assertGroup(group, false, RolloutGroupStatus.RUNNING, 3)); + + rolloutManagement.resumeRollout(dynamicRollout.getId()); + rolloutHandler.handleAll(); // resume, do not get last devices (they are assigned to a newer group, nevertheless newer is with bigger weight + assertGroup(dynamicGroups.get(dynamicGroups.size() - 1), true, RolloutGroupStatus.RUNNING, 0); + assertAndGetRunning(dynamicRollout, 0); + } + @BeforeEach void reset() { this.approvalStrategy.setApprovalNeeded(false); @@ -176,13 +237,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(actionsByKnownTarget.get(0).getStatus()).isEqualTo(expectedStatus); } - private static Stream simpleRolloutsPossibilities() { - return Stream.of(Arguments.of(true, true, Status.WAIT_FOR_CONFIRMATION), // - Arguments.of(true, false, Status.RUNNING), // - Arguments.of(false, true, Status.RUNNING), // - Arguments.of(false, false, Status.RUNNING));// - } - @Test @Description("Verifies that a running action is auto canceled by a rollout which assigns another distribution-set.") void rolloutAssignsNewDistributionSetAndAutoCloseActiveActions() { @@ -382,64 +436,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { verifyRolloutAndAllGroupsAreFinished(createdRollout); } - @Step("Finish three actions of the rollout group and delete two targets") - private void finishActionAndDeleteTargetsOfFirstRunningGroup(final Rollout createdRollout) { - // finish group one by finishing targets and deleting targets - final Slice runningActionsSlice = actionRepository.findByRolloutIdAndStatus(PAGE, - createdRollout.getId(), Status.RUNNING); - final List runningActions = runningActionsSlice.getContent(); - finishAction(runningActions.get(0)); - finishAction(runningActions.get(1)); - finishAction(runningActions.get(2)); - targetManagement.delete( - Arrays.asList(runningActions.get(3).getTarget().getId(), runningActions.get(4).getTarget().getId())); - } - - @Step("Check the status of the rollout groups, second group should be in running status") - private void checkSecondGroupStatusIsRunning(final Rollout createdRollout) { - rolloutHandler.handleAll(); - final List runningRolloutGroups = rolloutGroupManagement - .findByRollout(new OffsetBasedPageRequest(0, 10, Sort.by(Direction.ASC, "id")), createdRollout.getId()) - .getContent(); - assertThat(runningRolloutGroups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED); - assertThat(runningRolloutGroups.get(1).getStatus()).isEqualTo(RolloutGroupStatus.RUNNING); - assertThat(runningRolloutGroups.get(2).getStatus()).isEqualTo(RolloutGroupStatus.SCHEDULED); - } - - @Step("Finish one action of the rollout group and delete four targets") - private void finishActionAndDeleteTargetsOfSecondRunningGroup(final Rollout createdRollout) { - final Slice runningActionsSlice = actionRepository.findByRolloutIdAndStatus(PAGE, - createdRollout.getId(), Status.RUNNING); - final List runningActions = runningActionsSlice.getContent(); - finishAction(runningActions.get(0)); - targetManagement.delete( - Arrays.asList(runningActions.get(1).getTarget().getId(), runningActions.get(2).getTarget().getId(), - runningActions.get(3).getTarget().getId(), runningActions.get(4).getTarget().getId())); - - } - - @Step("Delete all targets of the rollout group") - private void deleteAllTargetsFromThirdGroup(final Rollout createdRollout) { - final Slice runningActionsSlice = actionRepository.findByRolloutIdAndStatus(PAGE, - createdRollout.getId(), Status.SCHEDULED); - final List runningActions = runningActionsSlice.getContent(); - targetManagement.delete(Arrays.asList(runningActions.get(0).getTarget().getId(), - runningActions.get(1).getTarget().getId(), runningActions.get(2).getTarget().getId(), - runningActions.get(3).getTarget().getId(), runningActions.get(4).getTarget().getId())); - } - - @Step("Check the status of the rollout groups and the rollout") - private void verifyRolloutAndAllGroupsAreFinished(final Rollout createdRollout) { - rolloutHandler.handleAll(); - final List runningRolloutGroups = rolloutGroupManagement - .findByRollout(PAGE, createdRollout.getId()).getContent(); - assertThat(runningRolloutGroups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED); - assertThat(runningRolloutGroups.get(1).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED); - assertThat(runningRolloutGroups.get(2).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED); - assertThat(reloadRollout(createdRollout).getStatus()).isEqualTo(RolloutStatus.FINISHED); - - } - @Test @Description("Verifying that the error handling action of a group is executed to pause the current rollout") void checkErrorHitOfGroupCallsErrorActionToPauseTheRollout() { @@ -1491,14 +1487,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(myRollout.getDescription()).isEqualTo("newDesc"); } - private Rollout reloadRollout(final Rollout r) { - return getRollout(r.getId()); - } - - private Rollout getRollout(final Long myRolloutId) { - return rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new); - } - @Test @Description("Verify the creation of a rollout with a groups definition.") void createRolloutWithGroupDefinition() throws Exception { @@ -1635,41 +1623,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { } - private void assertRolloutGroup(final long rolloutGroupId, final RolloutGroupStatus status, - final boolean isConfirmationRequired, final long totalTargets, final Status actionStatusToCheck) { - assertThat(rolloutGroupManagement.get(rolloutGroupId)).hasValueSatisfying(rolloutGroup -> { - assertThat(rolloutGroup.getStatus()).isEqualTo(status); - assertThat(rolloutGroup.isConfirmationRequired()).isEqualTo(isConfirmationRequired); - assertThat(rolloutGroup.getTotalTargets()).isEqualTo(totalTargets); - if (actionStatusToCheck != null) { - assertAllActionOfRolloutGroupHavingStatus(rolloutGroup.getId(), actionStatusToCheck); - } - }); - } - - private void assertAllActionOfRolloutGroupHavingStatus(final long rolloutGroupId, final Status status) { - final List targets = rolloutGroupManagement.findTargetsOfRolloutGroup(PAGE, rolloutGroupId) - .getContent(); - targets.forEach(target -> { - final List activeActions = deploymentManagement - .findActionsByTarget(target.getControllerId(), PAGE).getContent(); - assertThat(activeActions).hasSize(1); - assertThat(activeActions.get(0).getStatus()).isEqualTo(status); - }); - } - - private void forceQuitAllActionsOfRolloutGroup(final long rolloutGroupId) { - final List targets = rolloutGroupManagement.findTargetsOfRolloutGroup(PAGE, rolloutGroupId) - .getContent(); - targets.forEach(target -> { - deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().stream().map(Identifiable::getId) - .forEach(actionId -> { - deploymentManagement.cancelAction(actionId); - deploymentManagement.forceQuitAction(actionId); - }); - }); - } - @Test @Description("Verify rollout creation fails if group definition does not address all targets") void createRolloutWithGroupsNotMatchingTargets() { @@ -1961,8 +1914,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { @Description("Creating a rollout with a weight causes an error when multi assignment in disabled.") void weightAllowedWhenMultiAssignmentModeNotEnabled() { testdataFactory.createSimpleTestRolloutWithTargetsAndDistributionSet(10, 10, 2, "50", - "80", - ActionType.FORCED, 66); + "80", + ActionType.FORCED, 66); } @Test @@ -1996,7 +1949,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { enableMultiAssignments(); final Long rolloutId = testdataFactory .createSimpleTestRolloutWithTargetsAndDistributionSet(amountOfTargets, 2, amountOfTargets, - "80", "50", null, weight).getId(); + "80", "50", null, weight).getId(); rolloutManagement.start(rolloutId); rolloutHandler.handleAll(); final List actions = deploymentManagement.findActionsAll(PAGE).getContent(); @@ -2086,102 +2039,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { .doesNotContainAnyElementsOf(incompatibleTargets); } - private RolloutGroupCreate generateRolloutGroup(final int index, final Integer percentage, - final String targetFilter) { - return generateRolloutGroup(index, percentage, targetFilter, false); - } - - private RolloutGroupCreate generateRolloutGroup(final int index, final Integer percentage, - final String targetFilter, final boolean confirmationRequired) { - return entityFactory.rolloutGroup().create().name("Group" + index).description("Group" + index + "desc") - .targetPercentage(Float.valueOf(percentage)).targetFilterQuery(targetFilter) - .confirmationRequired(confirmationRequired); - } - - private RolloutCreate generateTargetsAndRollout(final String rolloutName, final int amountTargetsForRollout) { - final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName); - - testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName); - - return entityFactory.rollout().create().name(rolloutName) - .description("This is a test description for the rollout") - .targetFilterQuery("controllerId==" + rolloutName + "-*").distributionSetId(distributionSet); - } - - private void validateRolloutGroupActionStatus(final RolloutGroup rolloutGroup, - final Map expectedTargetCountStatus) { - final RolloutGroup rolloutGroupWithDetail = rolloutGroupManagement.getWithDetailedStatus(rolloutGroup.getId()) - .get(); - validateStatus(rolloutGroupWithDetail.getTotalTargetCountStatus(), expectedTargetCountStatus); - } - - private void validateRolloutActionStatus(final Long rolloutId, - final Map expectedTargetCountStatus) { - final Rollout rolloutWithDetail = rolloutManagement.getWithDetailedStatus(rolloutId).get(); - validateStatus(rolloutWithDetail.getTotalTargetCountStatus(), expectedTargetCountStatus); - } - - private void validateStatus(final TotalTargetCountStatus totalTargetCountStatus, - final Map expectedTotalCountStates) { - for (final Map.Entry entry : expectedTotalCountStates.entrySet()) { - final Long countReady = totalTargetCountStatus.getTotalTargetCountByStatus(entry.getKey()); - assertThat(countReady).as("targets in status " + entry.getKey()).isEqualTo(entry.getValue()); - } - } - - private Rollout createTestRolloutWithTargetsAndDistributionSet(final int amountTargetsForRollout, - final int groupSize, final String successCondition, final String errorCondition, final String rolloutName, - final String targetPrefixName) { - return createTestRolloutWithTargetsAndDistributionSet(amountTargetsForRollout, groupSize, successCondition, - errorCondition, rolloutName, targetPrefixName, null); - } - - private Rollout createTestRolloutWithTargetsAndDistributionSet(final int amountTargetsForRollout, - final int groupSize, final String successCondition, final String errorCondition, final String rolloutName, - final String targetPrefixName, final Integer weight) { - final DistributionSet dsForRolloutTwo = testdataFactory.createDistributionSet("dsFor" + rolloutName); - testdataFactory.createTargets(amountTargetsForRollout, targetPrefixName + "-", targetPrefixName); - return testdataFactory.createRolloutByVariables(rolloutName, rolloutName + "description", groupSize, - "controllerId==" + targetPrefixName + "-*", dsForRolloutTwo, successCondition, errorCondition, - Action.ActionType.FORCED, weight, false); - } - - private int changeStatusForAllRunningActions(final Rollout rollout, final Status status) { - final List runningActions = findActionsByRolloutAndStatus(rollout, Status.RUNNING); - for (final Action action : runningActions) { - controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(status)); - } - return runningActions.size(); - } - - private int changeStatusForRunningActions(final Rollout rollout, final Status status, - final int amountOfTargetsToGetChanged) { - final List runningActions = findActionsByRolloutAndStatus(rollout, Status.RUNNING); - assertThat(runningActions.size()).isGreaterThanOrEqualTo(amountOfTargetsToGetChanged); - for (int i = 0; i < amountOfTargetsToGetChanged; i++) { - controllerManagement.addUpdateActionStatus( - entityFactory.actionStatus().create(runningActions.get(i).getId()).status(status)); - } - return runningActions.size(); - } - - private static Map createInitStatusMap() { - final Map map = new HashMap<>(); - for (final TotalTargetCountStatus.Status status : TotalTargetCountStatus.Status.values()) { - map.put(status, 0L); - } - return map; - } - - private void awaitRunningState(final Long myRolloutId) { - Awaitility.await().atMost(Duration.ofSeconds(10)).pollInterval(Duration.ofMillis(500)).with() - .until(() -> SecurityContextSwitch - .runAsPrivileged( - () -> rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new)) - .getStatus().equals(RolloutStatus.RUNNING)); - } - @Test @Description("Verifying that next group is started on manual trigger next group.") void checkRunningRolloutsManualTriggerNextGroup() { @@ -2272,65 +2129,207 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { .withMessageContaining(errorMessage); } - /** - * Tests static assignment aspects of the dynamic group assignment filters. - */ - @Test - @Description("Dynamic group doesn't override newer static group assignments") - public void dynamicGroupDoesntOverrideItsOrNewerStaticGroups() { - final int amountGroups = 1; // static only - final String targetPrefix = "controller-dynamic-rollout-"; - final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds"); + private static Stream simpleRolloutsPossibilities() { + return Stream.of(Arguments.of(true, true, Status.WAIT_FOR_CONFIRMATION), // + Arguments.of(true, false, Status.RUNNING), // + Arguments.of(false, true, Status.RUNNING), // + Arguments.of(false, false, Status.RUNNING));// + } - testdataFactory.createTargets(targetPrefix, 0, amountGroups * 2); - final Rollout dynamicRollout = testdataFactory.createRolloutByVariables("dynamic", "static rollout", amountGroups, - "controllerid==" + targetPrefix + "*", distributionSet, "0", "30", ActionType.FORCED, 1000, false, true); - rolloutManagement.start(dynamicRollout.getId()); - rolloutHandler.handleAll(); - assertRollout(dynamicRollout, true, RolloutStatus.RUNNING, amountGroups + 1, amountGroups * 2); - final List dynamicGroups = rolloutGroupManagement.findByRollout( - new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id")), - dynamicRollout.getId()).getContent(); - for (int i = 0; i < dynamicGroups.size(); i++) { - final RolloutGroup group = dynamicGroups.get(i); - if (i + 1 == dynamicGroups.size()) { - assertGroup(group, true, RolloutGroupStatus.SCHEDULED, 0); - } else { - assertGroup(group, false, RolloutGroupStatus.RUNNING, 2); - } + private static Map createInitStatusMap() { + final Map map = new HashMap<>(); + for (final TotalTargetCountStatus.Status status : TotalTargetCountStatus.Status.values()) { + map.put(status, 0L); } - assertAndGetRunning(dynamicRollout, 2).forEach(this::finishAction); + return map; + } + + @Step("Finish three actions of the rollout group and delete two targets") + private void finishActionAndDeleteTargetsOfFirstRunningGroup(final Rollout createdRollout) { + // finish group one by finishing targets and deleting targets + final Slice runningActionsSlice = actionRepository.findByRolloutIdAndStatus(PAGE, + createdRollout.getId(), Status.RUNNING); + final List runningActions = runningActionsSlice.getContent(); + finishAction(runningActions.get(0)); + finishAction(runningActions.get(1)); + finishAction(runningActions.get(2)); + targetManagement.delete( + Arrays.asList(runningActions.get(3).getTarget().getId(), runningActions.get(4).getTarget().getId())); + } + + @Step("Check the status of the rollout groups, second group should be in running status") + private void checkSecondGroupStatusIsRunning(final Rollout createdRollout) { rolloutHandler.handleAll(); - for (int i = 0; i < dynamicGroups.size(); i++) { - final RolloutGroup group = dynamicGroups.get(i); - if (i + 1 == dynamicGroups.size()) { - assertGroup(group, true, RolloutGroupStatus.RUNNING, 0); - } else { - assertGroup(group, false, RolloutGroupStatus.FINISHED, 2); + final List runningRolloutGroups = rolloutGroupManagement + .findByRollout(new OffsetBasedPageRequest(0, 10, Sort.by(Direction.ASC, "id")), createdRollout.getId()) + .getContent(); + assertThat(runningRolloutGroups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED); + assertThat(runningRolloutGroups.get(1).getStatus()).isEqualTo(RolloutGroupStatus.RUNNING); + assertThat(runningRolloutGroups.get(2).getStatus()).isEqualTo(RolloutGroupStatus.SCHEDULED); + } + + @Step("Finish one action of the rollout group and delete four targets") + private void finishActionAndDeleteTargetsOfSecondRunningGroup(final Rollout createdRollout) { + final Slice runningActionsSlice = actionRepository.findByRolloutIdAndStatus(PAGE, + createdRollout.getId(), Status.RUNNING); + final List runningActions = runningActionsSlice.getContent(); + finishAction(runningActions.get(0)); + targetManagement.delete( + Arrays.asList(runningActions.get(1).getTarget().getId(), runningActions.get(2).getTarget().getId(), + runningActions.get(3).getTarget().getId(), runningActions.get(4).getTarget().getId())); + + } + + @Step("Delete all targets of the rollout group") + private void deleteAllTargetsFromThirdGroup(final Rollout createdRollout) { + final Slice runningActionsSlice = actionRepository.findByRolloutIdAndStatus(PAGE, + createdRollout.getId(), Status.SCHEDULED); + final List runningActions = runningActionsSlice.getContent(); + targetManagement.delete(Arrays.asList(runningActions.get(0).getTarget().getId(), + runningActions.get(1).getTarget().getId(), runningActions.get(2).getTarget().getId(), + runningActions.get(3).getTarget().getId(), runningActions.get(4).getTarget().getId())); + } + + @Step("Check the status of the rollout groups and the rollout") + private void verifyRolloutAndAllGroupsAreFinished(final Rollout createdRollout) { + rolloutHandler.handleAll(); + final List runningRolloutGroups = rolloutGroupManagement + .findByRollout(PAGE, createdRollout.getId()).getContent(); + assertThat(runningRolloutGroups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED); + assertThat(runningRolloutGroups.get(1).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED); + assertThat(runningRolloutGroups.get(2).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED); + assertThat(reloadRollout(createdRollout).getStatus()).isEqualTo(RolloutStatus.FINISHED); + + } + + private Rollout reloadRollout(final Rollout r) { + return getRollout(r.getId()); + } + + private Rollout getRollout(final Long myRolloutId) { + return rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new); + } + + private void assertRolloutGroup(final long rolloutGroupId, final RolloutGroupStatus status, + final boolean isConfirmationRequired, final long totalTargets, final Status actionStatusToCheck) { + assertThat(rolloutGroupManagement.get(rolloutGroupId)).hasValueSatisfying(rolloutGroup -> { + assertThat(rolloutGroup.getStatus()).isEqualTo(status); + assertThat(rolloutGroup.isConfirmationRequired()).isEqualTo(isConfirmationRequired); + assertThat(rolloutGroup.getTotalTargets()).isEqualTo(totalTargets); + if (actionStatusToCheck != null) { + assertAllActionOfRolloutGroupHavingStatus(rolloutGroup.getId(), actionStatusToCheck); } + }); + } + + private void assertAllActionOfRolloutGroupHavingStatus(final long rolloutGroupId, final Status status) { + final List targets = rolloutGroupManagement.findTargetsOfRolloutGroup(PAGE, rolloutGroupId) + .getContent(); + targets.forEach(target -> { + final List activeActions = deploymentManagement + .findActionsByTarget(target.getControllerId(), PAGE).getContent(); + assertThat(activeActions).hasSize(1); + assertThat(activeActions.get(0).getStatus()).isEqualTo(status); + }); + } + + private void forceQuitAllActionsOfRolloutGroup(final long rolloutGroupId) { + final List targets = rolloutGroupManagement.findTargetsOfRolloutGroup(PAGE, rolloutGroupId) + .getContent(); + targets.forEach(target -> { + deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().stream().map(Identifiable::getId) + .forEach(actionId -> { + deploymentManagement.cancelAction(actionId); + deploymentManagement.forceQuitAction(actionId); + }); + }); + } + + private RolloutGroupCreate generateRolloutGroup(final int index, final Integer percentage, + final String targetFilter) { + return generateRolloutGroup(index, percentage, targetFilter, false); + } + + private RolloutGroupCreate generateRolloutGroup(final int index, final Integer percentage, + final String targetFilter, final boolean confirmationRequired) { + return entityFactory.rolloutGroup().create().name("Group" + index).description("Group" + index + "desc") + .targetPercentage(Float.valueOf(percentage)).targetFilterQuery(targetFilter) + .confirmationRequired(confirmationRequired); + } + + private RolloutCreate generateTargetsAndRollout(final String rolloutName, final int amountTargetsForRollout) { + final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName); + + testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName); + + return entityFactory.rollout().create().name(rolloutName) + .description("This is a test description for the rollout") + .targetFilterQuery("controllerId==" + rolloutName + "-*").distributionSetId(distributionSet); + } + + private void validateRolloutGroupActionStatus(final RolloutGroup rolloutGroup, + final Map expectedTargetCountStatus) { + final RolloutGroup rolloutGroupWithDetail = rolloutGroupManagement.getWithDetailedStatus(rolloutGroup.getId()) + .get(); + validateStatus(rolloutGroupWithDetail.getTotalTargetCountStatus(), expectedTargetCountStatus); + } + + private void validateRolloutActionStatus(final Long rolloutId, + final Map expectedTargetCountStatus) { + final Rollout rolloutWithDetail = rolloutManagement.getWithDetailedStatus(rolloutId).get(); + validateStatus(rolloutWithDetail.getTotalTargetCountStatus(), expectedTargetCountStatus); + } + + private void validateStatus(final TotalTargetCountStatus totalTargetCountStatus, + final Map expectedTotalCountStates) { + for (final Map.Entry entry : expectedTotalCountStates.entrySet()) { + final Long countReady = totalTargetCountStatus.getTotalTargetCountByStatus(entry.getKey()); + assertThat(countReady).as("targets in status " + entry.getKey()).isEqualTo(entry.getValue()); } - assertAndGetRunning(dynamicRollout, 0); - rolloutHandler.handleAll(); - // NB: asserts that dynamic group doesn't get from its static groups (already finished action targets) - assertGroup(dynamicGroups.get(dynamicGroups.size() - 1), true, RolloutGroupStatus.RUNNING, 0); - assertAndGetRunning(dynamicRollout, 0); - rolloutManagement.pauseRollout(dynamicRollout.getId()); - rolloutHandler.handleAll(); + } - testdataFactory.createTargets(targetPrefix, amountGroups * 2, amountGroups); - final Rollout staticRollout = testdataFactory.createRolloutByVariables("static", "static rollout", amountGroups, - "controllerid==" + targetPrefix + "*", distributionSet, "0", "30", ActionType.FORCED, 0, false, false); - rolloutManagement.start(staticRollout.getId()); - rolloutHandler.handleAll(); - assertRollout(staticRollout, false, RolloutStatus.RUNNING, amountGroups, amountGroups * 3); - final List staticGroups = rolloutGroupManagement.findByRollout( - new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id")), - staticRollout.getId()).getContent(); - staticGroups.forEach(group -> assertGroup(group, false, RolloutGroupStatus.RUNNING, 3)); + private Rollout createTestRolloutWithTargetsAndDistributionSet(final int amountTargetsForRollout, + final int groupSize, final String successCondition, final String errorCondition, final String rolloutName, + final String targetPrefixName) { + return createTestRolloutWithTargetsAndDistributionSet(amountTargetsForRollout, groupSize, successCondition, + errorCondition, rolloutName, targetPrefixName, null); + } - rolloutManagement.resumeRollout(dynamicRollout.getId()); - rolloutHandler.handleAll(); // resume, do not get last devices (they are assigned to a newer group, nevertheless newer is with bigger weight - assertGroup(dynamicGroups.get(dynamicGroups.size() - 1), true, RolloutGroupStatus.RUNNING, 0); - assertAndGetRunning(dynamicRollout, 0); + private Rollout createTestRolloutWithTargetsAndDistributionSet(final int amountTargetsForRollout, + final int groupSize, final String successCondition, final String errorCondition, final String rolloutName, + final String targetPrefixName, final Integer weight) { + final DistributionSet dsForRolloutTwo = testdataFactory.createDistributionSet("dsFor" + rolloutName); + testdataFactory.createTargets(amountTargetsForRollout, targetPrefixName + "-", targetPrefixName); + return testdataFactory.createRolloutByVariables(rolloutName, rolloutName + "description", groupSize, + "controllerId==" + targetPrefixName + "-*", dsForRolloutTwo, successCondition, errorCondition, + Action.ActionType.FORCED, weight, false); + } + + private int changeStatusForAllRunningActions(final Rollout rollout, final Status status) { + final List runningActions = findActionsByRolloutAndStatus(rollout, Status.RUNNING); + for (final Action action : runningActions) { + controllerManagement + .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(status)); + } + return runningActions.size(); + } + + private int changeStatusForRunningActions(final Rollout rollout, final Status status, + final int amountOfTargetsToGetChanged) { + final List runningActions = findActionsByRolloutAndStatus(rollout, Status.RUNNING); + assertThat(runningActions.size()).isGreaterThanOrEqualTo(amountOfTargetsToGetChanged); + for (int i = 0; i < amountOfTargetsToGetChanged; i++) { + controllerManagement.addUpdateActionStatus( + entityFactory.actionStatus().create(runningActions.get(i).getId()).status(status)); + } + return runningActions.size(); + } + + private void awaitRunningState(final Long myRolloutId) { + Awaitility.await().atMost(Duration.ofSeconds(10)).pollInterval(Duration.ofMillis(500)).with() + .until(() -> SecurityContextSwitch + .runAsPrivileged( + () -> rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new)) + .getStatus().equals(RolloutStatus.RUNNING)); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java index 2e0658cbe..6b0ab0240 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java @@ -14,7 +14,6 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -23,6 +22,9 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.apache.commons.lang3.RandomUtils; import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; @@ -40,9 +42,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; -import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; @@ -54,12 +54,6 @@ import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Direction; - -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; @Feature("Component Tests - Repository") @Story("Software Module Management") @@ -220,25 +214,6 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { .isEqualTo(ah); } - private Action assignSet(final JpaTarget target, final JpaDistributionSet ds) { - assignDistributionSet(ds.getId(), target.getControllerId()); - implicitLock(ds); - assertThat(targetManagement.getByControllerID(target.getControllerId()).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.PENDING); - final Optional assignedDistributionSet = deploymentManagement - .getAssignedDistributionSet(target.getControllerId()); - assertThat(assignedDistributionSet).contains(ds); - final Action action = actionRepository - .findAll( - (root, query, cb) -> - cb.and( - cb.equal(root.get(JpaAction_.target).get(JpaTarget_.id), target.getId()), - cb.equal(root.get(JpaAction_.distributionSet).get(JpaDistributionSet_.id), ds.getId())), - PAGE).getContent().get(0);; - assertThat(action).isNotNull(); - return action; - } - @Test @Description("Searches for software modules based on a list of IDs.") public void findSoftwareModulesById() { @@ -482,52 +457,6 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(artifactRepository.findById(artifactY.getId())).isNotNull(); } - private SoftwareModule createSoftwareModuleWithArtifacts(final SoftwareModuleType type, final String name, - final String version, final int numberArtifacts) { - - final long countSoftwareModule = softwareModuleRepository.count(); - - // create SoftwareModule - SoftwareModule softwareModule = softwareModuleManagement.create(entityFactory.softwareModule().create() - .type(type).name(name).version(version).description("description of artifact " + name)); - - final int artifactSize = 5 * 1024; - for (int i = 0; i < numberArtifacts; i++) { - artifactManagement.create(new ArtifactUpload(new RandomGeneratedInputStream(artifactSize), - softwareModule.getId(), "file" + (i + 1), false, artifactSize)); - } - - // Verify correct Creation of SoftwareModule and corresponding artifacts - softwareModule = softwareModuleManagement.get(softwareModule.getId()).get(); - assertThat(softwareModuleRepository.findAll()).hasSize((int) countSoftwareModule + 1); - - final List artifacts = softwareModule.getArtifacts(); - - assertThat(artifacts).hasSize(numberArtifacts); - if (numberArtifacts != 0) { - assertArtifactNotNull(artifacts.toArray(new Artifact[artifacts.size()])); - } - - artifacts.forEach(artifact -> assertThat(artifactRepository.findById(artifact.getId())).isNotNull()); - return softwareModule; - } - - private void assertArtifactNotNull(final Artifact... results) { - assertThat(artifactRepository.findAll()).hasSize(results.length); - for (final Artifact result : results) { - assertThat(result.getId()).isNotNull(); - assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash())) - .isNotNull(); - } - } - - private void assertArtifactNull(final Artifact... results) { - for (final Artifact result : results) { - assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash())) - .isNull(); - } - } - @Test @Description("Verfies that all undeleted software modules are found in the repository.") public void countSoftwareModuleTypesAll() { @@ -719,103 +648,16 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(PageRequest.of(0, 10), swModule.getId()) .getContent()).as("Contains the created metadata element").allSatisfy(metadata -> { - assertThat(metadata.getSoftwareModule().getId()).isEqualTo(swModule.getId()); - assertThat(metadata.getKey()).isEqualTo(knownKey1); - assertThat(metadata.getValue()).isEqualTo(knownValue1); - }); + assertThat(metadata.getSoftwareModule().getId()).isEqualTo(swModule.getId()); + assertThat(metadata.getKey()).isEqualTo(knownKey1); + assertThat(metadata.getValue()).isEqualTo(knownValue1); + }); softwareModuleManagement.deleteMetaData(swModule.getId(), knownKey1); assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(PageRequest.of(0, 10), swModule.getId()) .getContent()).as("Metadata elements are").isEmpty(); } - @Test - @Description("Locks a SM.") - void lockSoftwareModule() { - final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1"); - assertThat( - softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(true)) - .isFalse(); - softwareModuleManagement.lock(softwareModule.getId()); - assertThat( - softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(false)) - .isTrue(); - } - - @Test - @Description("Unlocks a SM.") - void unlockSoftwareModule() { - final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1"); - softwareModuleManagement.lock(softwareModule.getId()); - assertThat( - softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(false)) - .isTrue(); - softwareModuleManagement.unlock(softwareModule.getId()); - assertThat( - softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(true)) - .isFalse(); - } - - @Test - @Description("Artifacts of a locked SM can't be modified. Expected behaviour is to throw an exception and to do not modify them.") - void lockSoftwareModuleApplied() { - final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1"); - artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(new byte[] {1}), softwareModule.getId(), - "artifact1", false, 1)); - final int artifactCount = softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size(); - assertThat(artifactCount).isNotEqualTo(0); - softwareModuleManagement.lock(softwareModule.getId()); - assertThat( - softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(false)) - .isTrue(); - - - // try add - assertThatExceptionOfType(LockedException.class) - .as("Attempt to modify a locked SM artifacts should throw an exception") - .isThrownBy(() -> artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(new byte[] {2}), softwareModule.getId(), - "artifact2", false, 1))); - assertThat(softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size()) - .as("Artifacts shall not be added to a locked SM.") - .isEqualTo(artifactCount); - - // try remove - final long artifactId = softwareModuleManagement.get(softwareModule.getId()).get() - .getArtifacts().stream().findFirst().get().getId(); - assertThatExceptionOfType(LockedException.class) - .as("Attempt to modify a locked SM artifacts should throw an exception") - .isThrownBy(() -> artifactManagement.delete(artifactId)); - assertThat(softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size()) - .as("Artifact shall not be removed from a locked SM.") - .isEqualTo(artifactCount); - assertThat(artifactManagement.get(artifactId)) - .as("Artifact shall not be removed if belongs to a locked SM.") - .isPresent(); - } - - @Test - @Description("Artifacts of a locked SM can't be modified. Expected behaviour is to throw an exception and to do not modify them.") - void lockedContainingDistributionSetApplied() { - final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1"); - final List modules = distributionSet.getModules().stream().toList(); - assertThat(modules.size()).isGreaterThan(1); - - // try delete while DS is not locked - softwareModuleManagement.delete(modules.get(0).getId()); - - distributionSetManagement.lock(distributionSet.getId()); - assertThat( - distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)) - .isTrue(); - - // try delete SM of a locked DS - assertThatExceptionOfType(LockedException.class) - .as("Attempt to delete a software module of a locked DS should throw an exception") - .isThrownBy(() -> softwareModuleManagement.delete(modules.get(1).getId())); - } - @Test @Description("Verifies that non existing metadata find results in exception.") public void findSoftwareModuleMetadataFailsIfEntryDoesNotExist() { @@ -874,4 +716,156 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(metadataSw2.getNumberOfElements()).isZero(); assertThat(metadataSw2.getTotalElements()).isZero(); } + + @Test + @Description("Locks a SM.") + void lockSoftwareModule() { + final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1"); + assertThat( + softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(true)) + .isFalse(); + softwareModuleManagement.lock(softwareModule.getId()); + assertThat( + softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(false)) + .isTrue(); + } + + @Test + @Description("Unlocks a SM.") + void unlockSoftwareModule() { + final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1"); + softwareModuleManagement.lock(softwareModule.getId()); + assertThat( + softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(false)) + .isTrue(); + softwareModuleManagement.unlock(softwareModule.getId()); + assertThat( + softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(true)) + .isFalse(); + } + + @Test + @Description("Artifacts of a locked SM can't be modified. Expected behaviour is to throw an exception and to do not modify them.") + void lockSoftwareModuleApplied() { + final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1"); + artifactManagement.create( + new ArtifactUpload(new ByteArrayInputStream(new byte[] { 1 }), softwareModule.getId(), + "artifact1", false, 1)); + final int artifactCount = softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size(); + assertThat(artifactCount).isNotEqualTo(0); + softwareModuleManagement.lock(softwareModule.getId()); + assertThat( + softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(false)) + .isTrue(); + + // try add + assertThatExceptionOfType(LockedException.class) + .as("Attempt to modify a locked SM artifacts should throw an exception") + .isThrownBy(() -> artifactManagement.create( + new ArtifactUpload(new ByteArrayInputStream(new byte[] { 2 }), softwareModule.getId(), + "artifact2", false, 1))); + assertThat(softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size()) + .as("Artifacts shall not be added to a locked SM.") + .isEqualTo(artifactCount); + + // try remove + final long artifactId = softwareModuleManagement.get(softwareModule.getId()).get() + .getArtifacts().stream().findFirst().get().getId(); + assertThatExceptionOfType(LockedException.class) + .as("Attempt to modify a locked SM artifacts should throw an exception") + .isThrownBy(() -> artifactManagement.delete(artifactId)); + assertThat(softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size()) + .as("Artifact shall not be removed from a locked SM.") + .isEqualTo(artifactCount); + assertThat(artifactManagement.get(artifactId)) + .as("Artifact shall not be removed if belongs to a locked SM.") + .isPresent(); + } + + @Test + @Description("Artifacts of a locked SM can't be modified. Expected behaviour is to throw an exception and to do not modify them.") + void lockedContainingDistributionSetApplied() { + final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1"); + final List modules = distributionSet.getModules().stream().toList(); + assertThat(modules.size()).isGreaterThan(1); + + // try delete while DS is not locked + softwareModuleManagement.delete(modules.get(0).getId()); + + distributionSetManagement.lock(distributionSet.getId()); + assertThat( + distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)) + .isTrue(); + + // try delete SM of a locked DS + assertThatExceptionOfType(LockedException.class) + .as("Attempt to delete a software module of a locked DS should throw an exception") + .isThrownBy(() -> softwareModuleManagement.delete(modules.get(1).getId())); + } + + private Action assignSet(final JpaTarget target, final JpaDistributionSet ds) { + assignDistributionSet(ds.getId(), target.getControllerId()); + implicitLock(ds); + assertThat(targetManagement.getByControllerID(target.getControllerId()).get().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.PENDING); + final Optional assignedDistributionSet = deploymentManagement + .getAssignedDistributionSet(target.getControllerId()); + assertThat(assignedDistributionSet).contains(ds); + final Action action = actionRepository + .findAll( + (root, query, cb) -> + cb.and( + cb.equal(root.get(JpaAction_.target).get(JpaTarget_.id), target.getId()), + cb.equal(root.get(JpaAction_.distributionSet).get(JpaDistributionSet_.id), ds.getId())), + PAGE).getContent().get(0); + ; + assertThat(action).isNotNull(); + return action; + } + + private SoftwareModule createSoftwareModuleWithArtifacts(final SoftwareModuleType type, final String name, + final String version, final int numberArtifacts) { + + final long countSoftwareModule = softwareModuleRepository.count(); + + // create SoftwareModule + SoftwareModule softwareModule = softwareModuleManagement.create(entityFactory.softwareModule().create() + .type(type).name(name).version(version).description("description of artifact " + name)); + + final int artifactSize = 5 * 1024; + for (int i = 0; i < numberArtifacts; i++) { + artifactManagement.create(new ArtifactUpload(new RandomGeneratedInputStream(artifactSize), + softwareModule.getId(), "file" + (i + 1), false, artifactSize)); + } + + // Verify correct Creation of SoftwareModule and corresponding artifacts + softwareModule = softwareModuleManagement.get(softwareModule.getId()).get(); + assertThat(softwareModuleRepository.findAll()).hasSize((int) countSoftwareModule + 1); + + final List artifacts = softwareModule.getArtifacts(); + + assertThat(artifacts).hasSize(numberArtifacts); + if (numberArtifacts != 0) { + assertArtifactNotNull(artifacts.toArray(new Artifact[artifacts.size()])); + } + + artifacts.forEach(artifact -> assertThat(artifactRepository.findById(artifact.getId())).isNotNull()); + return softwareModule; + } + + private void assertArtifactNotNull(final Artifact... results) { + assertThat(artifactRepository.findAll()).hasSize(results.length); + for (final Artifact result : results) { + assertThat(result.getId()).isNotNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash())) + .isNotNull(); + } + } + + private void assertArtifactNull(final Artifact... results) { + for (final Artifact result : results) { + assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash())) + .isNull(); + } + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java index eb5a8abe3..78759980c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java @@ -17,6 +17,9 @@ import java.util.List; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; @@ -27,10 +30,6 @@ import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; import org.junit.jupiter.api.Test; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("Software Module Management") public class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java index 5501c345e..85721f819 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java @@ -15,6 +15,9 @@ import java.io.ByteArrayInputStream; import java.util.List; import java.util.Random; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.ArtifactUpload; @@ -27,10 +30,6 @@ import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("System Management") @ExtendWith(DisposableSqlTestDatabaseExtension.class) @@ -135,25 +134,25 @@ public class SystemManagementTest extends AbstractJpaIntegrationTest { final String tenantname = "tenant" + i; SecurityContextSwitch.runAs(SecurityContextSwitch.withUserAndTenant("bumlux", tenantname, true, true, false, SpringEvalExpressions.SYSTEM_ROLE), () -> { - systemManagement.getTenantMetadata(); - if (artifactSize > 0) { - createTestArtifact(random); - createDeletedTestArtifact(random); - } - if (targets > 0) { - final List createdTargets = createTestTargets(targets); - if (updates > 0) { - for (int x = 0; x < updates; x++) { - final DistributionSet ds = testdataFactory - .createDistributionSet("to be deployed" + x, true); + systemManagement.getTenantMetadata(); + if (artifactSize > 0) { + createTestArtifact(random); + createDeletedTestArtifact(random); + } + if (targets > 0) { + final List createdTargets = createTestTargets(targets); + if (updates > 0) { + for (int x = 0; x < updates; x++) { + final DistributionSet ds = testdataFactory + .createDistributionSet("to be deployed" + x, true); - assignDistributionSet(ds, createdTargets); - } - } + assignDistributionSet(ds, createdTargets); } + } + } - return null; - }); + return null; + }); } return random; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetFilterQueryManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetFilterQueryManagementTest.java index 5baab7500..89b99f6b8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetFilterQueryManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetFilterQueryManagementTest.java @@ -22,6 +22,10 @@ import java.util.List; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.assertj.core.api.Assertions; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; @@ -49,14 +53,8 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; - /** * Test class for {@link TargetFilterQueryManagement}. - * */ @Feature("Component Tests - Repository") @Story("Target Filter Query Management") @@ -93,7 +91,7 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest "TargetFilterQuery"); verifyThrownExceptionBy(() -> targetFilterQueryManagement.updateAutoAssignDS( - entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)), + entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)), "DistributionSet"); verifyThrownExceptionBy( @@ -102,7 +100,7 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest "TargetFilterQuery"); verifyThrownExceptionBy(() -> targetFilterQueryManagement.updateAutoAssignDS( - entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)), + entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)), "DistributionSet"); } @@ -214,65 +212,6 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest verifyAutoAssignmentWithSoftDeletedDs(targetFilterQuery); } - @Step - private void verifyAutoAssignmentWithDefaultActionType(final String filterName, - final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) { - targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() - .updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId())); - implicitLock(distributionSet); - verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.FORCED); - } - - @Step - private void verifyAutoAssignmentWithSoftActionType(final String filterName, - final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) { - targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() - .updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()).actionType(ActionType.SOFT)); - verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.SOFT); - } - - @Step - private void verifyAutoAssignmentWithDownloadOnlyActionType(final String filterName, - final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) { - targetFilterQueryManagement - .updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()) - .ds(distributionSet.getId()).actionType(ActionType.DOWNLOAD_ONLY)); - verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.DOWNLOAD_ONLY); - } - - @Step - private void verifyAutoAssignmentWithInvalidActionType(final TargetFilterQuery targetFilterQuery, - final DistributionSet distributionSet) { - // assigning a distribution set with TIMEFORCED action is supposed to - // fail as only FORCED and SOFT action types are allowed - assertThatExceptionOfType(InvalidAutoAssignActionTypeException.class) - .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS( - entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()) - .ds(distributionSet.getId()).actionType(ActionType.TIMEFORCED))); - } - - @Step - private void verifyAutoAssignmentWithIncompleteDs(final TargetFilterQuery targetFilterQuery) { - final DistributionSet incompleteDistributionSet = distributionSetManagement - .create(entityFactory.distributionSet().create().name("incomplete").version("1") - .type(testdataFactory.findOrCreateDefaultTestDsType())); - - assertThatExceptionOfType(IncompleteDistributionSetException.class) - .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() - .updateAutoAssign(targetFilterQuery.getId()).ds(incompleteDistributionSet.getId()))); - } - - @Step - private void verifyAutoAssignmentWithSoftDeletedDs(final TargetFilterQuery targetFilterQuery) { - final DistributionSet softDeletedDs = testdataFactory.createDistributionSet("softDeleted"); - assignDistributionSet(softDeletedDs, testdataFactory.createTarget("forSoftDeletedDs")); - distributionSetManagement.delete(softDeletedDs.getId()); - - assertThatExceptionOfType(DeletedException.class) - .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() - .updateAutoAssign(targetFilterQuery.getId()).ds(softDeletedDs.getId()))); - } - @Test @Description("Assigns a distribution set to an existing filter query and verifies that the quota 'max targets per auto assignment' is enforced.") public void assignDistributionSetToTargetFilterQueryThatExceedsQuota() { @@ -407,39 +346,6 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest verifyFindForAllWithAutoAssignDs(tfq, tfq2); } - @Step - private void verifyFindByDistributionSetAndRsql(final DistributionSet distributionSet, final String rsql, - final TargetFilterQuery... expectedFilterQueries) { - final Page tfqList = targetFilterQueryManagement - .findByAutoAssignDSAndRsql(PageRequest.of(0, 500), distributionSet.getId(), rsql); - - assertThat(tfqList.getTotalElements()).isEqualTo(expectedFilterQueries.length); - verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries); - } - - private void verifyExpectedFilterQueriesInList(final Slice tfqList, - final TargetFilterQuery... expectedFilterQueries) { - assertThat(tfqList.map(TargetFilterQuery::getId)).containsExactly( - Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new)); - } - - @Step - private void verifyFindForAllWithAutoAssignDs(final TargetFilterQuery... expectedFilterQueries) { - final Slice tfqList = targetFilterQueryManagement - .findWithAutoAssignDS(PageRequest.of(0, 500)); - - assertThat(tfqList.getNumberOfElements()).isEqualTo(expectedFilterQueries.length); - verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries); - } - - private void verifyExpectedFilterQueriesInList(final Page tfqList, - final TargetFilterQuery... expectedFilterQueries) { - assertThat(expectedFilterQueries).as("Target filter query count").hasSize((int) tfqList.getTotalElements()); - - assertThat(tfqList.map(TargetFilterQuery::getId)).containsExactly( - Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new)); - } - @Test @Description("Creating or updating a target filter query with autoassignment and no-value weight when multi assignment in enabled.") public void weightNotRequiredInMultiAssignmentMode() { @@ -462,9 +368,9 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest .create(entityFactory.targetFilterQuery().create().name("a").query("name==*")).getId(); targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create() - .name("b").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(342)); + .name("b").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(342)); targetFilterQueryManagement.updateAutoAssignDS( - entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId()).weight(343)); + entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId()).weight(343)); } @Test @@ -563,6 +469,98 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest .ds(incompleteDistributionSet.getId()))); } + @Step + private void verifyAutoAssignmentWithDefaultActionType(final String filterName, + final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) { + targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() + .updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId())); + implicitLock(distributionSet); + verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.FORCED); + } + + @Step + private void verifyAutoAssignmentWithSoftActionType(final String filterName, + final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) { + targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() + .updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()).actionType(ActionType.SOFT)); + verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.SOFT); + } + + @Step + private void verifyAutoAssignmentWithDownloadOnlyActionType(final String filterName, + final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) { + targetFilterQueryManagement + .updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()) + .ds(distributionSet.getId()).actionType(ActionType.DOWNLOAD_ONLY)); + verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.DOWNLOAD_ONLY); + } + + @Step + private void verifyAutoAssignmentWithInvalidActionType(final TargetFilterQuery targetFilterQuery, + final DistributionSet distributionSet) { + // assigning a distribution set with TIMEFORCED action is supposed to + // fail as only FORCED and SOFT action types are allowed + assertThatExceptionOfType(InvalidAutoAssignActionTypeException.class) + .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS( + entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()) + .ds(distributionSet.getId()).actionType(ActionType.TIMEFORCED))); + } + + @Step + private void verifyAutoAssignmentWithIncompleteDs(final TargetFilterQuery targetFilterQuery) { + final DistributionSet incompleteDistributionSet = distributionSetManagement + .create(entityFactory.distributionSet().create().name("incomplete").version("1") + .type(testdataFactory.findOrCreateDefaultTestDsType())); + + assertThatExceptionOfType(IncompleteDistributionSetException.class) + .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() + .updateAutoAssign(targetFilterQuery.getId()).ds(incompleteDistributionSet.getId()))); + } + + @Step + private void verifyAutoAssignmentWithSoftDeletedDs(final TargetFilterQuery targetFilterQuery) { + final DistributionSet softDeletedDs = testdataFactory.createDistributionSet("softDeleted"); + assignDistributionSet(softDeletedDs, testdataFactory.createTarget("forSoftDeletedDs")); + distributionSetManagement.delete(softDeletedDs.getId()); + + assertThatExceptionOfType(DeletedException.class) + .isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery() + .updateAutoAssign(targetFilterQuery.getId()).ds(softDeletedDs.getId()))); + } + + @Step + private void verifyFindByDistributionSetAndRsql(final DistributionSet distributionSet, final String rsql, + final TargetFilterQuery... expectedFilterQueries) { + final Page tfqList = targetFilterQueryManagement + .findByAutoAssignDSAndRsql(PageRequest.of(0, 500), distributionSet.getId(), rsql); + + assertThat(tfqList.getTotalElements()).isEqualTo(expectedFilterQueries.length); + verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries); + } + + private void verifyExpectedFilterQueriesInList(final Slice tfqList, + final TargetFilterQuery... expectedFilterQueries) { + assertThat(tfqList.map(TargetFilterQuery::getId)).containsExactly( + Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new)); + } + + @Step + private void verifyFindForAllWithAutoAssignDs(final TargetFilterQuery... expectedFilterQueries) { + final Slice tfqList = targetFilterQueryManagement + .findWithAutoAssignDS(PageRequest.of(0, 500)); + + assertThat(tfqList.getNumberOfElements()).isEqualTo(expectedFilterQueries.length); + verifyExpectedFilterQueriesInList(tfqList, expectedFilterQueries); + } + + private void verifyExpectedFilterQueriesInList(final Page tfqList, + final TargetFilterQuery... expectedFilterQueries) { + assertThat(expectedFilterQueries).as("Target filter query count").hasSize((int) tfqList.getTotalElements()); + + assertThat(tfqList.map(TargetFilterQuery::getId)).containsExactly( + Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new)); + } + private void verifyAutoAssignDsAndActionType(final String filterName, final DistributionSet distributionSet, final ActionType actionType) { final TargetFilterQuery tfq = targetFilterQueryManagement.getByName(filterName).get(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java index 0caa18e22..029ed823f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java @@ -19,6 +19,10 @@ import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; @@ -39,15 +43,32 @@ import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("Target Management Searches") class TargetManagementSearchTest extends AbstractJpaIntegrationTest { + @Test + @Description("Verifies that targets with given target type are returned from repository.") + public void findTargetByTargetType() { + final TargetType testType = testdataFactory.createTargetType("testType", + Collections.singletonList(standardDsType)); + final List unassigned = testdataFactory.createTargets(9, "unassigned"); + final List assigned = testdataFactory.createTargetsWithType(11, "assigned", testType); + + assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, false, testType.getId()))) + .as("Contains the targets with set type").containsAll(assigned) + .as("and that means the following expected amount").hasSize(11); + assertThat(targetManagement.countByFilters(new FilterParams(null, null, false, testType.getId()))) + .as("Count the targets with set type").isEqualTo(11); + + assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, true, null))) + .as("Contains the targets without a type").containsAll(unassigned) + .as("and that means the following expected amount").hasSize(9); + assertThat(targetManagement.countByFilters(new FilterParams(null, null, true, null))) + .as("Counts the targets without a type").isEqualTo(9); + + } + @Test @Description("Tests different parameter combinations for target search operations. " + "That includes both the test itself, as a count operation with the same filters " @@ -178,382 +199,6 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { verifyThat198TargetsAreInStatusUnknownAndOverdue(unknown, expected); } - @Step - private void verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(final DistributionSet installedSet, - final List pending, final Target expected) { - final FilterParams filterParams = new FilterParams(pending, null, null, installedSet.getId(), Boolean.FALSE); - final String query = "updatestatus==pending and installedds.name==" + installedSet.getName(); - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(1).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsExactly(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat200targetsWithGivenTagAreInStatusPendingorUnknown(final TargetTag targTagW, - final List both, final List expected) { - final FilterParams filterParams = new FilterParams(both, null, null, null, Boolean.FALSE, targTagW.getName()); - final String query = "(updatestatus==pending or updatestatus==unknown) and tag==" + targTagW.getName(); - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(200).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat2TargetsWithGivenTagAreInPending(final TargetTag targTagW, - final List pending, final List expected) { - final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE, - targTagW.getName()); - final String query = "updatestatus==pending and tag==" + targTagW.getName(); - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(2).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat2TargetsWithGivenTagAndDSIsInPending(final TargetTag targTagW, final DistributionSet setA, - final List pending, final List expected) { - final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE, - targTagW.getName()); - final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" - + setA.getName() + ") and tag==" + targTagW.getName(); - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(2).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat1TargetWithGivenNameOrDescAndTagAndDSIsInPending(final TargetTag targTagW, - final DistributionSet setA, final List pending, final Target expected) { - final FilterParams filterParams = new FilterParams(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE, - targTagW.getName()); - final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" - + setA.getName() + ") and (name==*targ-B* or description==*targ-B*) and tag==" + targTagW.getName(); - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(1).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsExactly(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(final DistributionSet setA, - final List pending, final Target expected) { - final FilterParams filterParams = new FilterParams(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE); - final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" - + setA.getName() + ") and (name==*targ-A* or description==*targ-A*)"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(1).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsExactly(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat3TargetsWithGivenDSAreInPending(final DistributionSet setA, - final List pending, final List expected) { - final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE); - final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" - + setA.getName() + ")"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(3).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat4TargetsAreInStatusPending(final List pending, - final List expected) { - final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE); - final String query = "updatestatus==pending"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(4).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat99TargetsWithGivenNameOrDescAndTagAreInStatusUnknown(final TargetTag targTagW, - final List unknown, final List expected) { - final FilterParams filterParams = new FilterParams(unknown, null, "%targ-B%", null, Boolean.FALSE, - targTagW.getName()); - final String query = "updatestatus==unknown and (name==*targ-B* or description==*targ-B*) and tag==" - + targTagW.getName(); - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(99).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat99TargetsWithNameOrDescriptionAreInGivenStatus(final List unknown, - final List expected) { - final FilterParams filterParams = new FilterParams(unknown, null, "%targ-A%", null, Boolean.FALSE); - final String query = "updatestatus==unknown and (name==*targ-A* or description==*targ-A*)"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(99).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(final DistributionSet setA, - final List unknown) { - final FilterParams filterParams = new FilterParams(unknown, null, null, setA.getId(), Boolean.FALSE); - final String query = "updatestatus==unknown and (assignedds.name==" + setA.getName() + " or installedds.name==" - + setA.getName() + ")"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(0).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and filter query returns the same result") - .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size()); - } - - @Step - private void verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(final TargetTag targTagY, - final TargetTag targTagW, final List unknown, final List expected) { - final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE, targTagY.getName(), - targTagW.getName()); - final String query = "updatestatus==unknown and (tag==" + targTagY.getName() + " or tag==" + targTagW.getName() - + ")"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(198).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat496TargetsAreInStatusUnknown(final List unknown, - final List expected) { - final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE); - final String query = "updatestatus==unknown"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(496).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat198TargetsAreInStatusUnknownAndOverdue(final List unknown, - final List expected) { - final FilterParams filterParams = new FilterParams(unknown, Boolean.TRUE, null, null, Boolean.FALSE); - // be careful: simple filters are concatenated using AND-gating - final String query = "lastcontrollerrequestat=le=${overdue_ts};updatestatus==UNKNOWN"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(198).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat1TargetWithDescOrNameHasDS(final DistributionSet setA, final Target expected) { - final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE); - final String query = "(name==*targ-A* or description==*targ-A*) and (assignedds.name==" + setA.getName() - + " or installedds.name==" + setA.getName() + ")"; - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(1).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsExactly(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat3TargetsHaveDSAssigned(final DistributionSet setA, final List expected) { - final FilterParams filterParams = new FilterParams(null, null, null, setA.getId(), Boolean.FALSE); - final String query = "assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName(); - - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(3).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat0TargetsWithNameOrdescAndDSHaveTag(final TargetTag targTagX, final DistributionSet setA) { - final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, - targTagX.getName()); - final String query = "(name==*targ-C* or description==*targ-C*) and tag==" + targTagX.getName() - + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(0).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and filter query returns the same result") - .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size()); - } - - @Step - private void verifyThat0TargetsWithTagAndDescOrNameHasDS(final TargetTag targTagW, final DistributionSet setA) { - final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, - targTagW.getName()); - final String query = "(name==*targ-A* or description==*targ-A*) and tag==" + targTagW.getName() - + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(0).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and filter query returns the same result") - .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size()); - } - - @Step - private void verifyThat1TargetHasTagHasDescOrNameAndDs(final TargetTag targTagW, final DistributionSet setA, - final Target expected) { - final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, - targTagW.getName()); - final String query = "(name==*targ-c* or description==*targ-C*) and tag==" + targTagW.getName() - + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(1).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsExactly(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThat1TargetHasNameAndId(final String name, final String controllerId) { - final FilterParams filterParamsByName = new FilterParams(null, null, name, null, Boolean.FALSE); - assertThat(targetManagement.findByFilters(PAGE, filterParamsByName).getContent()).as("has number of elements") - .hasSize(1).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParamsByName)); - - final FilterParams filterParamsByControllerId = new FilterParams(null, null, controllerId, null, Boolean.FALSE); - assertThat(targetManagement.findByFilters(PAGE, filterParamsByControllerId).getContent()) - .as("has number of elements").hasSize(1).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParamsByControllerId)); - } - - @Step - private void verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(final TargetTag targTagY, - final TargetTag targTagW, final List expected) { - final FilterParams filterParams = new FilterParams(null, null, "%targ-B%", null, Boolean.FALSE, - targTagY.getName(), targTagW.getName()); - final String query = "(name==*targ-B* or description==*targ-B*) and (tag==" + targTagY.getName() + " or tag==" - + targTagW.getName() + ")"; - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(100).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @SafeVarargs - private List concat(final List... targets) { - final List result = new ArrayList<>(); - Arrays.asList(targets).forEach(result::addAll); - return result; - } - - @Step - private void verifyThat200TargetsHaveTagD(final TargetTag targTagD, final List expected) { - final FilterParams filterParams = new FilterParams(null, null, null, null, Boolean.FALSE, targTagD.getName()); - final String query = "tag==" + targTagD.getName(); - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("Expected number of results is") - .hasSize(200).as("and is expected number of results is equal to ") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected) - .as("and filter query returns the same result") - .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); - } - - @Step - private void verifyThatRepositoryContains500Targets() { - final FilterParams filterParams = new FilterParams(null, null, null, null, null); - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()) - .as("Overall we expect that many targets in the repository").hasSize(500) - .as("which is also reflected by repository count").hasSize((int)targetManagement.count()) - .as("which is also reflected by call without specification") - .containsAll(targetManagement.findAll(PAGE).getContent()); - } - - @Step - private void verifyThat1TargetHasTypeAndDSAssigned(final TargetType type, final DistributionSet set, - final Target expected) { - final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.FALSE, type.getId()); - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(1).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsExactly(expected); - } - - @Step - private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set, - final List expected) { - final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null); - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(expected.size()).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected); - } - - @Step - private void verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(final TargetType targetType, - final List expected) { - final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId()); - final List filteredTargets = targetManagement.findByFilters(PAGE, filterParams).getContent(); - assertThat(filteredTargets).as("has number of elements").hasSize(100) - .as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)); - // Comparing the controller ids, as one of the targets was modified, so - // a 1:1 - // comparison of the objects is not possible - assertThat(filteredTargets.stream().map(Target::getControllerId).collect(Collectors.toList())) - .containsAll(expected.stream().map(Target::getControllerId).collect(Collectors.toList())); - } - - @Step - private void verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(final List expected) { - final FilterParams filterParams = new FilterParams("%targ-%", null, Boolean.TRUE, null); - assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") - .hasSize(400).as("that number is also returned by count query") - .hasSize((int)targetManagement.countByFilters(filterParams)) - .as("and contains the following elements").containsAll(expected); - } - @Test @Description("Tests the correct order of targets based on selected distribution set. The system expects to have an order based on installed, assigned DS.") void targetSearchWithVariousFilterCombinationsAndOrderByDistributionSet() { @@ -624,11 +269,6 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThatTargetNameEquals(targetsOrderedByDistAndName, 8, notAssigned, 0); } - private void assertThatTargetNameEquals(final List targets1, final int index1, final List targets2, - final int index2) { - assertThat(targets1.get(index1).getName()).isEqualTo(targets2.get(index2).getName()); - } - @Test @Description("Tests the correct order of targets with applied overdue filter based on selected distribution set. The system expects to have an order based on installed, assigned DS.") void targetSearchWithOverdueFilterAndOrderByDistributionSet() { @@ -794,32 +434,391 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .doesNotContainAnyElementsOf(targetsWithIncompatibleType); } + @Step + private void verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(final DistributionSet installedSet, + final List pending, final Target expected) { + final FilterParams filterParams = new FilterParams(pending, null, null, installedSet.getId(), Boolean.FALSE); + final String query = "updatestatus==pending and installedds.name==" + installedSet.getName(); + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(1).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsExactly(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat200targetsWithGivenTagAreInStatusPendingorUnknown(final TargetTag targTagW, + final List both, final List expected) { + final FilterParams filterParams = new FilterParams(both, null, null, null, Boolean.FALSE, targTagW.getName()); + final String query = "(updatestatus==pending or updatestatus==unknown) and tag==" + targTagW.getName(); + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(200).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat2TargetsWithGivenTagAreInPending(final TargetTag targTagW, + final List pending, final List expected) { + final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE, + targTagW.getName()); + final String query = "updatestatus==pending and tag==" + targTagW.getName(); + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(2).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat2TargetsWithGivenTagAndDSIsInPending(final TargetTag targTagW, final DistributionSet setA, + final List pending, final List expected) { + final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE, + targTagW.getName()); + final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" + + setA.getName() + ") and tag==" + targTagW.getName(); + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(2).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat1TargetWithGivenNameOrDescAndTagAndDSIsInPending(final TargetTag targTagW, + final DistributionSet setA, final List pending, final Target expected) { + final FilterParams filterParams = new FilterParams(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE, + targTagW.getName()); + final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" + + setA.getName() + ") and (name==*targ-B* or description==*targ-B*) and tag==" + targTagW.getName(); + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(1).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsExactly(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(final DistributionSet setA, + final List pending, final Target expected) { + final FilterParams filterParams = new FilterParams(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE); + final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" + + setA.getName() + ") and (name==*targ-A* or description==*targ-A*)"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(1).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsExactly(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat3TargetsWithGivenDSAreInPending(final DistributionSet setA, + final List pending, final List expected) { + final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE); + final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" + + setA.getName() + ")"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(3).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat4TargetsAreInStatusPending(final List pending, + final List expected) { + final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE); + final String query = "updatestatus==pending"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(4).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat99TargetsWithGivenNameOrDescAndTagAreInStatusUnknown(final TargetTag targTagW, + final List unknown, final List expected) { + final FilterParams filterParams = new FilterParams(unknown, null, "%targ-B%", null, Boolean.FALSE, + targTagW.getName()); + final String query = "updatestatus==unknown and (name==*targ-B* or description==*targ-B*) and tag==" + + targTagW.getName(); + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(99).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat99TargetsWithNameOrDescriptionAreInGivenStatus(final List unknown, + final List expected) { + final FilterParams filterParams = new FilterParams(unknown, null, "%targ-A%", null, Boolean.FALSE); + final String query = "updatestatus==unknown and (name==*targ-A* or description==*targ-A*)"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(99).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(final DistributionSet setA, + final List unknown) { + final FilterParams filterParams = new FilterParams(unknown, null, null, setA.getId(), Boolean.FALSE); + final String query = "updatestatus==unknown and (assignedds.name==" + setA.getName() + " or installedds.name==" + + setA.getName() + ")"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(0).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and filter query returns the same result") + .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size()); + } + + @Step + private void verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(final TargetTag targTagY, + final TargetTag targTagW, final List unknown, final List expected) { + final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE, targTagY.getName(), + targTagW.getName()); + final String query = "updatestatus==unknown and (tag==" + targTagY.getName() + " or tag==" + targTagW.getName() + + ")"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(198).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat496TargetsAreInStatusUnknown(final List unknown, + final List expected) { + final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE); + final String query = "updatestatus==unknown"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(496).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat198TargetsAreInStatusUnknownAndOverdue(final List unknown, + final List expected) { + final FilterParams filterParams = new FilterParams(unknown, Boolean.TRUE, null, null, Boolean.FALSE); + // be careful: simple filters are concatenated using AND-gating + final String query = "lastcontrollerrequestat=le=${overdue_ts};updatestatus==UNKNOWN"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(198).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat1TargetWithDescOrNameHasDS(final DistributionSet setA, final Target expected) { + final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE); + final String query = "(name==*targ-A* or description==*targ-A*) and (assignedds.name==" + setA.getName() + + " or installedds.name==" + setA.getName() + ")"; + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(1).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsExactly(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat3TargetsHaveDSAssigned(final DistributionSet setA, final List expected) { + final FilterParams filterParams = new FilterParams(null, null, null, setA.getId(), Boolean.FALSE); + final String query = "assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName(); + + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(3).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat0TargetsWithNameOrdescAndDSHaveTag(final TargetTag targTagX, final DistributionSet setA) { + final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, + targTagX.getName()); + final String query = "(name==*targ-C* or description==*targ-C*) and tag==" + targTagX.getName() + + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(0).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and filter query returns the same result") + .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size()); + } + + @Step + private void verifyThat0TargetsWithTagAndDescOrNameHasDS(final TargetTag targTagW, final DistributionSet setA) { + final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, + targTagW.getName()); + final String query = "(name==*targ-A* or description==*targ-A*) and tag==" + targTagW.getName() + + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(0).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and filter query returns the same result") + .hasSize(targetManagement.findByRsql(PAGE, query).getContent().size()); + } + + @Step + private void verifyThat1TargetHasTagHasDescOrNameAndDs(final TargetTag targTagW, final DistributionSet setA, + final Target expected) { + final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, + targTagW.getName()); + final String query = "(name==*targ-c* or description==*targ-C*) and tag==" + targTagW.getName() + + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(1).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsExactly(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThat1TargetHasNameAndId(final String name, final String controllerId) { + final FilterParams filterParamsByName = new FilterParams(null, null, name, null, Boolean.FALSE); + assertThat(targetManagement.findByFilters(PAGE, filterParamsByName).getContent()).as("has number of elements") + .hasSize(1).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParamsByName)); + + final FilterParams filterParamsByControllerId = new FilterParams(null, null, controllerId, null, Boolean.FALSE); + assertThat(targetManagement.findByFilters(PAGE, filterParamsByControllerId).getContent()) + .as("has number of elements").hasSize(1).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParamsByControllerId)); + } + + @Step + private void verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(final TargetTag targTagY, + final TargetTag targTagW, final List expected) { + final FilterParams filterParams = new FilterParams(null, null, "%targ-B%", null, Boolean.FALSE, + targTagY.getName(), targTagW.getName()); + final String query = "(name==*targ-B* or description==*targ-B*) and (tag==" + targTagY.getName() + " or tag==" + + targTagW.getName() + ")"; + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(100).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @SafeVarargs + private List concat(final List... targets) { + final List result = new ArrayList<>(); + Arrays.asList(targets).forEach(result::addAll); + return result; + } + + @Step + private void verifyThat200TargetsHaveTagD(final TargetTag targTagD, final List expected) { + final FilterParams filterParams = new FilterParams(null, null, null, null, Boolean.FALSE, targTagD.getName()); + final String query = "tag==" + targTagD.getName(); + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("Expected number of results is") + .hasSize(200).as("and is expected number of results is equal to ") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findByRsql(PAGE, query).getContent()); + } + + @Step + private void verifyThatRepositoryContains500Targets() { + final FilterParams filterParams = new FilterParams(null, null, null, null, null); + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()) + .as("Overall we expect that many targets in the repository").hasSize(500) + .as("which is also reflected by repository count").hasSize((int) targetManagement.count()) + .as("which is also reflected by call without specification") + .containsAll(targetManagement.findAll(PAGE).getContent()); + } + + @Step + private void verifyThat1TargetHasTypeAndDSAssigned(final TargetType type, final DistributionSet set, + final Target expected) { + final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.FALSE, type.getId()); + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(1).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsExactly(expected); + } + + @Step + private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set, + final List expected) { + final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null); + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(expected.size()).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected); + } + + @Step + private void verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(final TargetType targetType, + final List expected) { + final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId()); + final List filteredTargets = targetManagement.findByFilters(PAGE, filterParams).getContent(); + assertThat(filteredTargets).as("has number of elements").hasSize(100) + .as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)); + // Comparing the controller ids, as one of the targets was modified, so + // a 1:1 + // comparison of the objects is not possible + assertThat(filteredTargets.stream().map(Target::getControllerId).collect(Collectors.toList())) + .containsAll(expected.stream().map(Target::getControllerId).collect(Collectors.toList())); + } + + @Step + private void verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(final List expected) { + final FilterParams filterParams = new FilterParams("%targ-%", null, Boolean.TRUE, null); + assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements") + .hasSize(400).as("that number is also returned by count query") + .hasSize((int) targetManagement.countByFilters(filterParams)) + .as("and contains the following elements").containsAll(expected); + } + + private void assertThatTargetNameEquals(final List targets1, final int index1, final List targets2, + final int index2) { + assertThat(targets1.get(index1).getName()).isEqualTo(targets2.get(index2).getName()); + } + private DistributionSet createDistSetWithType(final DistributionSetType type) { final DistributionSetCreate dsCreate = entityFactory.distributionSet().create().name("test-ds").version("1.0") .type(type); return distributionSetManagement.create(dsCreate); } - @Test - @Description("Verifies that targets with given target type are returned from repository.") - public void findTargetByTargetType() { - final TargetType testType = testdataFactory.createTargetType("testType", - Collections.singletonList(standardDsType)); - final List unassigned = testdataFactory.createTargets(9, "unassigned"); - final List assigned = testdataFactory.createTargetsWithType(11, "assigned", testType); - - assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, false, testType.getId()))) - .as("Contains the targets with set type").containsAll(assigned) - .as("and that means the following expected amount").hasSize(11); - assertThat(targetManagement.countByFilters(new FilterParams(null, null, false, testType.getId()))) - .as("Count the targets with set type").isEqualTo(11); - - assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, true, null))) - .as("Contains the targets without a type").containsAll(unassigned) - .as("and that means the following expected amount").hasSize(9); - assertThat(targetManagement.countByFilters(new FilterParams(null, null, true, null))) - .as("Counts the targets without a type").isEqualTo(9); - - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java index 492651a7e..fefce5375 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java @@ -27,6 +27,10 @@ import java.util.stream.Collectors; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.apache.commons.lang3.RandomStringUtils; import org.awaitility.Awaitility; import org.eclipse.hawkbit.im.authentication.SpPermission; @@ -82,11 +86,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("Target Management") class TargetManagementTest extends AbstractJpaIntegrationTest { @@ -252,136 +251,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { createAndUpdateTargetWithInvalidAddress(target); } - @Step - private void createAndUpdateTargetWithInvalidDescription(final Target target) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long description should not be created") - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") - .description(RandomStringUtils.randomAlphanumeric(513)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid description should not be created").isThrownBy(() -> targetManagement - .create(entityFactory.target().create().controllerId("a").description(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long description should not be updated") - .isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId()) - .description(RandomStringUtils.randomAlphanumeric(513)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid description should not be updated").isThrownBy(() -> targetManagement.update( - entityFactory.target().update(target.getControllerId()).description(INVALID_TEXT_HTML))); - } - - @Step - private void createAndUpdateTargetWithInvalidName(final Target target) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long name should not be created") - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") - .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid name should not be created").isThrownBy(() -> targetManagement - .create(entityFactory.target().create().controllerId("a").name(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long name should not be updated") - .isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId()) - .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid name should not be updated").isThrownBy(() -> targetManagement - .update(entityFactory.target().update(target.getControllerId()).name(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too short name should not be updated").isThrownBy(() -> targetManagement - .update(entityFactory.target().update(target.getControllerId()).name(""))); - - } - - @Step - private void createAndUpdateTargetWithInvalidSecurityToken(final Target target) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long token should not be created") - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") - .securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid token should not be created").isThrownBy(() -> targetManagement - .create(entityFactory.target().create().controllerId("a").securityToken(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long token should not be updated") - .isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId()) - .securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid token should not be updated").isThrownBy(() -> targetManagement.update( - entityFactory.target().update(target.getControllerId()).securityToken(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too short token should not be updated").isThrownBy(() -> targetManagement - .update(entityFactory.target().update(target.getControllerId()).securityToken(""))); - } - - @Step - private void createAndUpdateTargetWithInvalidAddress(final Target target) { - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long address should not be created") - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") - .address(RandomStringUtils.randomAlphanumeric(513)))); - - assertThatExceptionOfType(InvalidTargetAddressException.class).as("target with invalid should not be created") - .isThrownBy(() -> targetManagement - .create(entityFactory.target().create().controllerId("a").address(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long address should not be updated") - .isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId()) - .address(RandomStringUtils.randomAlphanumeric(513)))); - - assertThatExceptionOfType(InvalidTargetAddressException.class) - .as("target with invalid address should not be updated").isThrownBy(() -> targetManagement - .update(entityFactory.target().update(target.getControllerId()).address(INVALID_TEXT_HTML))); - } - - @Step - private void createTargetWithInvalidControllerId() { - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with empty controller id should not be created") - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(""))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with null controller id should not be created") - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(null))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with too long controller id should not be created") - .isThrownBy(() -> targetManagement.create(entityFactory.target().create() - .controllerId(RandomStringUtils.randomAlphanumeric(Target.CONTROLLER_ID_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("target with invalid controller id should not be created").isThrownBy( - () -> targetManagement.create(entityFactory.target().create().controllerId(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" "))); - - assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a b"))); - - assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" "))); - - assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) - .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("aaa bbb"))); - - } - @Test @Description("Ensures that targets can assigned and unassigned to a target tag. Not exists target will be ignored for the assignment.") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 4), @@ -450,18 +319,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { assertThat(targetManagement.count()).as("target count is wrong").isZero(); } - private Target createTargetWithAttributes(final String controllerId) { - final Map testData = new HashMap<>(); - testData.put("test1", "testdata1"); - - targetManagement.create(entityFactory.target().create().controllerId(controllerId)); - final Target target = controllerManagement.updateControllerAttributes(controllerId, testData, null); - - assertThat(targetManagement.getControllerAttributes(controllerId)).as("Controller Attributes are wrong") - .isEqualTo(testData); - return target; - } - @Test @Description("Finds a target by given ID and checks if all data is in the response (including the data defined as lazy).") @ExpectEvents({ @Expect(type = DistributionSetCreatedEvent.class, count = 2), @@ -554,50 +411,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { } } - /** - * verifies, that all {@link TargetTag} of parameter. NOTE: it's accepted - * that the target have additional tags assigned to them which are not - * contained within parameter tags. - * - * @param strict - * if true, the given targets MUST contain EXACTLY ALL given - * tags, AND NO OTHERS. If false, the given targets MUST contain - * ALL given tags, BUT MAY CONTAIN FURTHER ONE - * @param targets - * targets to be verified - * @param tags - * are contained within tags of all targets. - */ - private void checkTargetHasTags(final boolean strict, final Iterable targets, final TargetTag... tags) { - _target: for (final Target tl : targets) { - for (final Tag tt : getTargetTags(tl.getControllerId())) { - for (final Tag tag : tags) { - if (tag.getName().equals(tt.getName())) { - continue _target; - } - } - if (strict) { - fail("Target does not contain all tags"); - } - } - fail("Target does not contain any tags or the expected tag was not found"); - } - } - - private void checkTargetHasNotTags(final Iterable targets, final TargetTag... tags) { - for (final Target tl : targets) { - targetManagement.getByControllerID(tl.getControllerId()).get(); - - for (final Tag tag : tags) { - for (final Tag tt : getTargetTags(tl.getControllerId())) { - if (tag.getName().equals(tt.getName())) { - fail("Target should have no tags"); - } - } - } - } - } - @Test @WithUser(allSpPermissions = true) @Description("Creates and updates a target and verifies the changes in the repository.") @@ -662,7 +475,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .collect(Collectors.toList()); // verify that all entries are found - _founds: for (final Target foundTarget : allFound) { + _founds: + for (final Target foundTarget : allFound) { for (final Target changedTarget : firstList) { if (changedTarget.getControllerId().equals(foundTarget.getControllerId())) { assertThat(changedTarget.getDescription()) @@ -970,13 +784,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { assertThat(createdMetadata.getValue()).isEqualTo(knownValue); } - private JpaTargetMetadata insertTargetMetadata(final String knownKey, final String knownValue, - final Target target) { - final JpaTargetMetadata metadata = new JpaTargetMetadata(knownKey, knownValue, target); - return (JpaTargetMetadata) targetManagement - .createMetaData(target.getControllerId(), Collections.singletonList(metadata)).get(0); - } - @Test @Description("Verifies the enforcement of the metadata quota per target.") void createTargetMetadataUntilQuotaIsExceeded() { @@ -1163,16 +970,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { checkTargetsHaveType(typeATargets, typeB); } - private void checkTargetsHaveType(final List targets, final TargetType type) { - final List foundTargets = targetRepository - .findAllById(targets.stream().map(Identifiable::getId).collect(Collectors.toList())); - for (final Target target : foundTargets) { - if (!type.getName().equals(type.getName())) { - fail(String.format("Target %s is not of type %s.", target, type)); - } - } - } - @Test @Description("Queries and loads the metadata related to a given target.") void findAllTargetMetadataByControllerId() { @@ -1193,26 +990,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { assertThat(metadataOfTarget2.getTotalElements()).isEqualTo(8); } - private Target createTargetWithMetadata(final String controllerId, final int count) { - final Target target = testdataFactory.createTarget(controllerId); - - for (int index = 1; index <= count; index++) { - insertTargetMetadata("key" + index, controllerId + "-value" + index, target); - } - - return target; - } - - private Target createTargetWithTargetTypeAndMetadata(final String controllerId, final long targetTypeId, final int count) { - final Target target = testdataFactory.createTarget(controllerId, controllerId, targetTypeId); - - for (int index = 1; index <= count; index++) { - insertTargetMetadata("key" + index, controllerId + "-value" + index, target); - } - - return target; - } - @Test @WithUser(allSpPermissions = true) @Description("Checks that target type is not assigned to target if invalid.") @@ -1411,7 +1188,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { createAction(targets.get(8), rolloutNewer, 20, Status.DOWNLOADED, distributionSet); final Slice matching = targetManagement.findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable( - PAGE, rollout.getId(), 10, Long.MAX_VALUE,"controllerid==dyn_action_filter_*", distributionSet.getType()); + PAGE, rollout.getId(), 10, Long.MAX_VALUE, "controllerid==dyn_action_filter_*", distributionSet.getType()); assertThat(matching.getNumberOfElements()).isEqualTo(5); assertThat(matching.stream() @@ -1421,7 +1198,239 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { .sorted() .toList()).isEqualTo(List.of(0, 1, 2, 5, 6)); } - private void createAction(final Target target, final Rollout rollout, final Integer weight, final Action.Status status, final DistributionSet distributionSet) { + + @Test + @Description("Target matches filter for not existing DS.") + void matchesFilterDsNotExists() { + final String target = testdataFactory.createTarget().getControllerId(); + + assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy( + () -> targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target, 123, "name==*")); + } + + @Step + private void createAndUpdateTargetWithInvalidDescription(final Target target) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long description should not be created") + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") + .description(RandomStringUtils.randomAlphanumeric(513)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with invalid description should not be created").isThrownBy(() -> targetManagement + .create(entityFactory.target().create().controllerId("a").description(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long description should not be updated") + .isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId()) + .description(RandomStringUtils.randomAlphanumeric(513)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with invalid description should not be updated").isThrownBy(() -> targetManagement.update( + entityFactory.target().update(target.getControllerId()).description(INVALID_TEXT_HTML))); + } + + @Step + private void createAndUpdateTargetWithInvalidName(final Target target) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long name should not be created") + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") + .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with invalid name should not be created").isThrownBy(() -> targetManagement + .create(entityFactory.target().create().controllerId("a").name(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long name should not be updated") + .isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId()) + .name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with invalid name should not be updated").isThrownBy(() -> targetManagement + .update(entityFactory.target().update(target.getControllerId()).name(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too short name should not be updated").isThrownBy(() -> targetManagement + .update(entityFactory.target().update(target.getControllerId()).name(""))); + + } + + @Step + private void createAndUpdateTargetWithInvalidSecurityToken(final Target target) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long token should not be created") + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") + .securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with invalid token should not be created").isThrownBy(() -> targetManagement + .create(entityFactory.target().create().controllerId("a").securityToken(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long token should not be updated") + .isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId()) + .securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with invalid token should not be updated").isThrownBy(() -> targetManagement.update( + entityFactory.target().update(target.getControllerId()).securityToken(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too short token should not be updated").isThrownBy(() -> targetManagement + .update(entityFactory.target().update(target.getControllerId()).securityToken(""))); + } + + @Step + private void createAndUpdateTargetWithInvalidAddress(final Target target) { + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long address should not be created") + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a") + .address(RandomStringUtils.randomAlphanumeric(513)))); + + assertThatExceptionOfType(InvalidTargetAddressException.class).as("target with invalid should not be created") + .isThrownBy(() -> targetManagement + .create(entityFactory.target().create().controllerId("a").address(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long address should not be updated") + .isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId()) + .address(RandomStringUtils.randomAlphanumeric(513)))); + + assertThatExceptionOfType(InvalidTargetAddressException.class) + .as("target with invalid address should not be updated").isThrownBy(() -> targetManagement + .update(entityFactory.target().update(target.getControllerId()).address(INVALID_TEXT_HTML))); + } + + @Step + private void createTargetWithInvalidControllerId() { + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with empty controller id should not be created") + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(""))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with null controller id should not be created") + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(null))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with too long controller id should not be created") + .isThrownBy(() -> targetManagement.create(entityFactory.target().create() + .controllerId(RandomStringUtils.randomAlphanumeric(Target.CONTROLLER_ID_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("target with invalid controller id should not be created").isThrownBy( + () -> targetManagement.create(entityFactory.target().create().controllerId(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" "))); + + assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a b"))); + + assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" "))); + + assertThatExceptionOfType(ConstraintViolationException.class).as(WHITESPACE_ERROR) + .isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("aaa bbb"))); + + } + + private Target createTargetWithAttributes(final String controllerId) { + final Map testData = new HashMap<>(); + testData.put("test1", "testdata1"); + + targetManagement.create(entityFactory.target().create().controllerId(controllerId)); + final Target target = controllerManagement.updateControllerAttributes(controllerId, testData, null); + + assertThat(targetManagement.getControllerAttributes(controllerId)).as("Controller Attributes are wrong") + .isEqualTo(testData); + return target; + } + + /** + * verifies, that all {@link TargetTag} of parameter. NOTE: it's accepted + * that the target have additional tags assigned to them which are not + * contained within parameter tags. + * + * @param strict if true, the given targets MUST contain EXACTLY ALL given + * tags, AND NO OTHERS. If false, the given targets MUST contain + * ALL given tags, BUT MAY CONTAIN FURTHER ONE + * @param targets targets to be verified + * @param tags are contained within tags of all targets. + */ + private void checkTargetHasTags(final boolean strict, final Iterable targets, final TargetTag... tags) { + _target: + for (final Target tl : targets) { + for (final Tag tt : getTargetTags(tl.getControllerId())) { + for (final Tag tag : tags) { + if (tag.getName().equals(tt.getName())) { + continue _target; + } + } + if (strict) { + fail("Target does not contain all tags"); + } + } + fail("Target does not contain any tags or the expected tag was not found"); + } + } + + private void checkTargetHasNotTags(final Iterable targets, final TargetTag... tags) { + for (final Target tl : targets) { + targetManagement.getByControllerID(tl.getControllerId()).get(); + + for (final Tag tag : tags) { + for (final Tag tt : getTargetTags(tl.getControllerId())) { + if (tag.getName().equals(tt.getName())) { + fail("Target should have no tags"); + } + } + } + } + } + + private JpaTargetMetadata insertTargetMetadata(final String knownKey, final String knownValue, + final Target target) { + final JpaTargetMetadata metadata = new JpaTargetMetadata(knownKey, knownValue, target); + return (JpaTargetMetadata) targetManagement + .createMetaData(target.getControllerId(), Collections.singletonList(metadata)).get(0); + } + + private void checkTargetsHaveType(final List targets, final TargetType type) { + final List foundTargets = targetRepository + .findAllById(targets.stream().map(Identifiable::getId).collect(Collectors.toList())); + for (final Target target : foundTargets) { + if (!type.getName().equals(type.getName())) { + fail(String.format("Target %s is not of type %s.", target, type)); + } + } + } + + private Target createTargetWithMetadata(final String controllerId, final int count) { + final Target target = testdataFactory.createTarget(controllerId); + + for (int index = 1; index <= count; index++) { + insertTargetMetadata("key" + index, controllerId + "-value" + index, target); + } + + return target; + } + + private Target createTargetWithTargetTypeAndMetadata(final String controllerId, final long targetTypeId, final int count) { + final Target target = testdataFactory.createTarget(controllerId, controllerId, targetTypeId); + + for (int index = 1; index <= count; index++) { + insertTargetMetadata("key" + index, controllerId + "-value" + index, target); + } + + return target; + } + + private void createAction(final Target target, final Rollout rollout, final Integer weight, final Action.Status status, + final DistributionSet distributionSet) { final JpaAction action = new JpaAction(); action.setActionType(Action.ActionType.FORCED); action.setTarget(target); @@ -1437,15 +1446,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest { actionRepository.save(action); } - @Test - @Description("Target matches filter for not existing DS.") - void matchesFilterDsNotExists() { - final String target = testdataFactory.createTarget().getControllerId(); - - assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy( - () -> targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target, 123, "name==*")); - } - private void validateFoundTargetsByRsql(final String rsqlFilter, final String... controllerIds) { final Slice foundTargetsByMetadataAndControllerId = targetManagement.findByRsql(PAGE, rsqlFilter); final long foundTargetsByMetadataAndControllerIdCount = targetManagement.countByRsql(rsqlFilter); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java index b2bf0e701..a533085bf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java @@ -23,6 +23,10 @@ import java.util.stream.Collectors; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.apache.commons.lang3.RandomStringUtils; import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagUpdatedEvent; @@ -32,21 +36,13 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; -import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult; import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; import org.junit.jupiter.api.Test; - -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; import org.springframework.data.domain.Pageable; /** @@ -56,129 +52,8 @@ import org.springframework.data.domain.Pageable; @Story("Target Tag Management") class TargetTagManagementTest extends AbstractJpaIntegrationTest { - @Test - @Description("Verifies that management get access reacts as specfied on calls for non existing entities by means " + - "of Optional not present.") - @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) }) - void nonExistingEntityAccessReturnsNotPresent() { - assertThat(targetTagManagement.getByName(NOT_EXIST_ID)).isNotPresent(); - assertThat(targetTagManagement.get(NOT_EXIST_IDL)).isNotPresent(); - } - - @Test - @Description("Verifies that management queries react as specfied on calls for non existing entities " + - " by means of throwing EntityNotFoundException.") - @ExpectEvents({ @Expect(type = DistributionSetTagUpdatedEvent.class), @Expect(type = TargetTagUpdatedEvent.class) }) - void entityQueriesReferringToNotExistingEntitiesThrowsException() { - verifyThrownExceptionBy(() -> targetTagManagement.delete(NOT_EXIST_ID), "TargetTag"); - verifyThrownExceptionBy(() -> targetTagManagement.update(entityFactory.tag().update(NOT_EXIST_IDL)), "TargetTag"); - verifyThrownExceptionBy(() -> getTargetTags(NOT_EXIST_ID), "Target"); - } - - @Test - @Description("Verify that a tag with with invalid properties cannot be created or updated") - void createAndUpdateTagWithInvalidFields() { - final TargetTag tag = targetTagManagement.create(entityFactory.tag().create().name("tag1").description("tagdesc1")); - createAndUpdateTagWithInvalidDescription(tag); - createAndUpdateTagWithInvalidColour(tag); - createAndUpdateTagWithInvalidName(tag); - } - - @Step - private void createAndUpdateTagWithInvalidDescription(final Tag tag) { - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with too long description should not be created") - .isThrownBy(() -> targetTagManagement.create( - entityFactory.tag().create().name("a").description(RandomStringUtils.randomAlphanumeric(513)))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with invalid description should not be created").isThrownBy(() -> targetTagManagement - .create(entityFactory.tag().create().name("a").description(INVALID_TEXT_HTML))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with too long description should not be updated") - .isThrownBy(() -> targetTagManagement.update( - entityFactory.tag().update(tag.getId()) - .description(RandomStringUtils.randomAlphanumeric(513)))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with invalid description should not be updated") - .isThrownBy(() -> targetTagManagement - .update(entityFactory.tag().update(tag.getId()).description(INVALID_TEXT_HTML))); - } - - @Step - private void createAndUpdateTagWithInvalidColour(final Tag tag) { - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with too long colour should not be created") - .isThrownBy(() -> targetTagManagement.create( - entityFactory.tag().create().name("a").colour(RandomStringUtils.randomAlphanumeric(17)))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with invalid colour should not be created").isThrownBy(() -> targetTagManagement - .create(entityFactory.tag().create().name("a").colour(INVALID_TEXT_HTML))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with too long colour should not be updated") - .isThrownBy(() -> targetTagManagement.update( - entityFactory.tag().update(tag.getId()).colour(RandomStringUtils.randomAlphanumeric(17)))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with invalid colour should not be updated").isThrownBy(() -> targetTagManagement - .update(entityFactory.tag().update(tag.getId()).colour(INVALID_TEXT_HTML))); - } - - @Step - private void createAndUpdateTagWithInvalidName(final Tag tag) { - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with too long name should not be created") - .isThrownBy(() -> targetTagManagement - .create(entityFactory.tag().create().name(RandomStringUtils.randomAlphanumeric( - NamedEntity.NAME_MAX_SIZE + 1)))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with invalidname should not be created") - .isThrownBy(() -> targetTagManagement.create(entityFactory.tag().create().name(INVALID_TEXT_HTML))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with too long name should not be updated") - .isThrownBy(() -> targetTagManagement - .update(entityFactory.tag().update(tag.getId()).name(RandomStringUtils.randomAlphanumeric( - NamedEntity.NAME_MAX_SIZE + 1)))); - assertThatExceptionOfType(ConstraintViolationException.class).as("tag with invalid name should not be updated") - .isThrownBy(() -> targetTagManagement - .update(entityFactory.tag().update(tag.getId()).name(INVALID_TEXT_HTML))); - assertThatExceptionOfType(ConstraintViolationException.class) - .as("tag with too short name should not be updated") - .isThrownBy(() -> targetTagManagement.update(entityFactory.tag().update(tag.getId()).name(""))); - } - - @Test - @Description("Verifies assign/unassign.") - void assignAndUnassignTargetTags() { - final List groupA = testdataFactory.createTargets(20); - final List groupB = testdataFactory.createTargets(20, "groupb", "groupb"); - - final TargetTag tag = targetTagManagement.create(entityFactory.tag().create().name("tag1").description("tagdesc1")); - - // toggle A only -> A is now assigned - List result = assignTag(groupA, tag); - assertThat(result).size().isEqualTo(20); - assertThat(result).containsAll( - targetManagement.getByControllerID(groupA.stream().map(Target::getControllerId).collect(Collectors.toList()))); - assertThat(targetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent().stream().map(Target::getControllerId).sorted().toList()) - .isEqualTo(groupA.stream().map(Target::getControllerId).sorted().toList()); - - // toggle A+B -> A is still assigned and B is assigned as well - final Collection groupAB = concat(groupA, groupB); - result = assignTag(groupAB, tag); - assertThat(result).size().isEqualTo(40); - assertThat(result).containsAll( - targetManagement.getByControllerID(groupAB.stream().map(Target::getControllerId).collect(Collectors.toList()))); - assertThat(targetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent().stream().map(Target::getControllerId).sorted().toList()) - .isEqualTo(groupAB.stream().map(Target::getControllerId).sorted().toList()); - - // toggle A+B -> both unassigned - result = unassignTag(groupAB, tag); - assertThat(result).size().isEqualTo(40); - assertThat(result).containsAll( - targetManagement.getByControllerID(groupAB.stream().map(Target::getControllerId).collect(Collectors.toList()))); - assertThat(targetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent()).isEmpty(); - } - private static final Random RND = new Random(); + @Test @Description("Verifies that tagging of set containing missing DS throws meaningful and correct exception.") public void failOnMissingDs() { @@ -212,11 +87,67 @@ class TargetTagManagementTest extends AbstractJpaIntegrationTest { }); } - @SafeVarargs - private Collection concat(final Collection... targets) { - final List result = new ArrayList<>(); - Arrays.asList(targets).forEach(result::addAll); - return result; + @Test + @Description("Verifies that management get access reacts as specfied on calls for non existing entities by means " + + "of Optional not present.") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) }) + void nonExistingEntityAccessReturnsNotPresent() { + assertThat(targetTagManagement.getByName(NOT_EXIST_ID)).isNotPresent(); + assertThat(targetTagManagement.get(NOT_EXIST_IDL)).isNotPresent(); + } + + @Test + @Description("Verifies that management queries react as specfied on calls for non existing entities " + + " by means of throwing EntityNotFoundException.") + @ExpectEvents({ @Expect(type = DistributionSetTagUpdatedEvent.class), @Expect(type = TargetTagUpdatedEvent.class) }) + void entityQueriesReferringToNotExistingEntitiesThrowsException() { + verifyThrownExceptionBy(() -> targetTagManagement.delete(NOT_EXIST_ID), "TargetTag"); + verifyThrownExceptionBy(() -> targetTagManagement.update(entityFactory.tag().update(NOT_EXIST_IDL)), "TargetTag"); + verifyThrownExceptionBy(() -> getTargetTags(NOT_EXIST_ID), "Target"); + } + + @Test + @Description("Verify that a tag with with invalid properties cannot be created or updated") + void createAndUpdateTagWithInvalidFields() { + final TargetTag tag = targetTagManagement.create(entityFactory.tag().create().name("tag1").description("tagdesc1")); + createAndUpdateTagWithInvalidDescription(tag); + createAndUpdateTagWithInvalidColour(tag); + createAndUpdateTagWithInvalidName(tag); + } + + @Test + @Description("Verifies assign/unassign.") + void assignAndUnassignTargetTags() { + final List groupA = testdataFactory.createTargets(20); + final List groupB = testdataFactory.createTargets(20, "groupb", "groupb"); + + final TargetTag tag = targetTagManagement.create(entityFactory.tag().create().name("tag1").description("tagdesc1")); + + // toggle A only -> A is now assigned + List result = assignTag(groupA, tag); + assertThat(result).size().isEqualTo(20); + assertThat(result).containsAll( + targetManagement.getByControllerID(groupA.stream().map(Target::getControllerId).collect(Collectors.toList()))); + assertThat(targetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent().stream().map(Target::getControllerId).sorted() + .toList()) + .isEqualTo(groupA.stream().map(Target::getControllerId).sorted().toList()); + + // toggle A+B -> A is still assigned and B is assigned as well + final Collection groupAB = concat(groupA, groupB); + result = assignTag(groupAB, tag); + assertThat(result).size().isEqualTo(40); + assertThat(result).containsAll( + targetManagement.getByControllerID(groupAB.stream().map(Target::getControllerId).collect(Collectors.toList()))); + assertThat(targetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent().stream().map(Target::getControllerId).sorted() + .toList()) + .isEqualTo(groupAB.stream().map(Target::getControllerId).sorted().toList()); + + // toggle A+B -> both unassigned + result = unassignTag(groupAB, tag); + assertThat(result).size().isEqualTo(40); + assertThat(result).containsAll( + targetManagement.getByControllerID(groupAB.stream().map(Target::getControllerId).collect(Collectors.toList()))); + assertThat(targetManagement.findByTag(Pageable.unpaged(), tag.getId()).getContent()).isEmpty(); } @Test @@ -302,6 +233,74 @@ class TargetTagManagementTest extends AbstractJpaIntegrationTest { .isThrownBy(() -> targetTagManagement.update(entityFactory.tag().update(tag.getId()).name("A"))); } + @Step + private void createAndUpdateTagWithInvalidDescription(final Tag tag) { + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with too long description should not be created") + .isThrownBy(() -> targetTagManagement.create( + entityFactory.tag().create().name("a").description(RandomStringUtils.randomAlphanumeric(513)))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with invalid description should not be created").isThrownBy(() -> targetTagManagement + .create(entityFactory.tag().create().name("a").description(INVALID_TEXT_HTML))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with too long description should not be updated") + .isThrownBy(() -> targetTagManagement.update( + entityFactory.tag().update(tag.getId()) + .description(RandomStringUtils.randomAlphanumeric(513)))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with invalid description should not be updated") + .isThrownBy(() -> targetTagManagement + .update(entityFactory.tag().update(tag.getId()).description(INVALID_TEXT_HTML))); + } + + @Step + private void createAndUpdateTagWithInvalidColour(final Tag tag) { + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with too long colour should not be created") + .isThrownBy(() -> targetTagManagement.create( + entityFactory.tag().create().name("a").colour(RandomStringUtils.randomAlphanumeric(17)))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with invalid colour should not be created").isThrownBy(() -> targetTagManagement + .create(entityFactory.tag().create().name("a").colour(INVALID_TEXT_HTML))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with too long colour should not be updated") + .isThrownBy(() -> targetTagManagement.update( + entityFactory.tag().update(tag.getId()).colour(RandomStringUtils.randomAlphanumeric(17)))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with invalid colour should not be updated").isThrownBy(() -> targetTagManagement + .update(entityFactory.tag().update(tag.getId()).colour(INVALID_TEXT_HTML))); + } + + @Step + private void createAndUpdateTagWithInvalidName(final Tag tag) { + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with too long name should not be created") + .isThrownBy(() -> targetTagManagement + .create(entityFactory.tag().create().name(RandomStringUtils.randomAlphanumeric( + NamedEntity.NAME_MAX_SIZE + 1)))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with invalidname should not be created") + .isThrownBy(() -> targetTagManagement.create(entityFactory.tag().create().name(INVALID_TEXT_HTML))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with too long name should not be updated") + .isThrownBy(() -> targetTagManagement + .update(entityFactory.tag().update(tag.getId()).name(RandomStringUtils.randomAlphanumeric( + NamedEntity.NAME_MAX_SIZE + 1)))); + assertThatExceptionOfType(ConstraintViolationException.class).as("tag with invalid name should not be updated") + .isThrownBy(() -> targetTagManagement + .update(entityFactory.tag().update(tag.getId()).name(INVALID_TEXT_HTML))); + assertThatExceptionOfType(ConstraintViolationException.class) + .as("tag with too short name should not be updated") + .isThrownBy(() -> targetTagManagement.update(entityFactory.tag().update(tag.getId()).name(""))); + } + + @SafeVarargs + private Collection concat(final Collection... targets) { + final List result = new ArrayList<>(); + Arrays.asList(targets).forEach(result::addAll); + return result; + } + private List createTargetsWithTags() { final List targets = testdataFactory.createTargets(20); final Iterable tags = testdataFactory.createTargetTags(20, ""); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTypeManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTypeManagementTest.java index facdf89e1..e2f3bd7a2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTypeManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTypeManagementTest.java @@ -18,6 +18,10 @@ import java.util.Optional; import jakarta.validation.ConstraintViolationException; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Step; +import io.qameta.allure.Story; import org.apache.commons.lang3.RandomStringUtils; import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeUpdatedEvent; @@ -32,11 +36,6 @@ import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; import org.junit.jupiter.api.Test; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Step; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("Target Type Management") class TargetTypeManagementTest extends AbstractJpaIntegrationTest { @@ -98,70 +97,6 @@ class TargetTypeManagementTest extends AbstractJpaIntegrationTest { .update(entityFactory.targetType().update(targetType.getId()).description(INVALID_TEXT_HTML))); } - @Step - private void createAndUpdateTargetTypeWithInvalidColour(final TargetType targetType) { - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with too long colour should not be created") - .isThrownBy(() -> targetTypeManagement.create( - entityFactory.targetType().create().name("a") - .colour(RandomStringUtils.randomAlphanumeric(TargetType.COLOUR_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with invalid colour should not be created").isThrownBy(() -> targetTypeManagement - .create(entityFactory.targetType().create().name("a").colour(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with too long colour should not be updated") - .isThrownBy(() -> targetTypeManagement.update( - entityFactory.targetType().update(targetType.getId()) - .colour(RandomStringUtils.randomAlphanumeric(TargetType.COLOUR_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with invalid colour should not be updated").isThrownBy(() -> targetTypeManagement - .update(entityFactory.targetType().update(targetType.getId()).colour(INVALID_TEXT_HTML))); - } - - @Step - private void createTargetTypeWithInvalidKey() { - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with too long key should not be created") - .isThrownBy(() -> targetTypeManagement - .create(entityFactory.targetType().create().name(RandomStringUtils.randomAlphanumeric( - Type.KEY_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with invalid key should not be created").isThrownBy( - () -> targetTypeManagement.create(entityFactory.targetType().create().name(INVALID_TEXT_HTML))); - } - - @Step - private void createAndUpdateTargetTypeWithInvalidName(final TargetType targetType) { - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with too long name should not be created") - .isThrownBy(() -> targetTypeManagement - .create(entityFactory.targetType().create().name(RandomStringUtils.randomAlphanumeric( - NamedEntity.NAME_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with invalid name should not be created").isThrownBy( - () -> targetTypeManagement.create(entityFactory.targetType().create().name(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with too long name should not be updated") - .isThrownBy(() -> targetTypeManagement - .update(entityFactory.targetType().update(targetType.getId()).name(RandomStringUtils.randomAlphanumeric( - NamedEntity.NAME_MAX_SIZE + 1)))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with invalid name should not be updated").isThrownBy(() -> targetTypeManagement - .update(entityFactory.targetType().update(targetType.getId()).name(INVALID_TEXT_HTML))); - - assertThatExceptionOfType(ConstraintViolationException.class) - .as("targetType with too short name should not be updated").isThrownBy(() -> targetTypeManagement - .update(entityFactory.targetType().update(targetType.getId()).name(""))); - - } - @Test @Description("Tests the successful assignment of compatible distribution set types to a target type") void assignCompatibleDistributionSetTypesToTargetType() { @@ -189,7 +124,7 @@ class TargetTypeManagementTest extends AbstractJpaIntegrationTest { Optional targetTypeWithDsTypes = targetTypeRepository.findById(targetType.getId()); assertThat(targetTypeWithDsTypes).isPresent(); assertThat(targetTypeWithDsTypes.get().getCompatibleDistributionSetTypes()).extracting("key").contains("testDst1"); - targetTypeManagement.unassignDistributionSetType(targetType.getId(),distributionSetType.getId()); + targetTypeManagement.unassignDistributionSetType(targetType.getId(), distributionSetType.getId()); Optional targetTypeWithDsTypes1 = targetTypeRepository.findById(targetType.getId()); assertThat(targetTypeWithDsTypes1).isPresent(); assertThat(targetTypeWithDsTypes1.get().getCompatibleDistributionSetTypes()).isEmpty(); @@ -260,7 +195,8 @@ class TargetTypeManagementTest extends AbstractJpaIntegrationTest { @Description("Ensures that a target type cannot be created if one exists already with that name (expects EntityAlreadyExistsException).") void failedDuplicateTargetTypeNameException() { targetTypeManagement.create(entityFactory.targetType().create().name("targettype123")); - assertThrows(EntityAlreadyExistsException.class, () -> targetTypeManagement.create(entityFactory.targetType().create().name("targettype123"))); + assertThrows(EntityAlreadyExistsException.class, + () -> targetTypeManagement.create(entityFactory.targetType().create().name("targettype123"))); } @Test @@ -268,7 +204,72 @@ class TargetTypeManagementTest extends AbstractJpaIntegrationTest { void failedDuplicateTargetTypeNameExceptionAfterUpdate() { targetTypeManagement.create(entityFactory.targetType().create().name("targettype1234")); TargetType targetType = targetTypeManagement.create(entityFactory.targetType().create().name("targettype12345")); - assertThrows(EntityAlreadyExistsException.class, () -> targetTypeManagement.update(entityFactory.targetType().update(targetType.getId()).name("targettype1234"))); + assertThrows(EntityAlreadyExistsException.class, + () -> targetTypeManagement.update(entityFactory.targetType().update(targetType.getId()).name("targettype1234"))); + } + + @Step + private void createAndUpdateTargetTypeWithInvalidColour(final TargetType targetType) { + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with too long colour should not be created") + .isThrownBy(() -> targetTypeManagement.create( + entityFactory.targetType().create().name("a") + .colour(RandomStringUtils.randomAlphanumeric(TargetType.COLOUR_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with invalid colour should not be created").isThrownBy(() -> targetTypeManagement + .create(entityFactory.targetType().create().name("a").colour(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with too long colour should not be updated") + .isThrownBy(() -> targetTypeManagement.update( + entityFactory.targetType().update(targetType.getId()) + .colour(RandomStringUtils.randomAlphanumeric(TargetType.COLOUR_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with invalid colour should not be updated").isThrownBy(() -> targetTypeManagement + .update(entityFactory.targetType().update(targetType.getId()).colour(INVALID_TEXT_HTML))); + } + + @Step + private void createTargetTypeWithInvalidKey() { + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with too long key should not be created") + .isThrownBy(() -> targetTypeManagement + .create(entityFactory.targetType().create().name(RandomStringUtils.randomAlphanumeric( + Type.KEY_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with invalid key should not be created").isThrownBy( + () -> targetTypeManagement.create(entityFactory.targetType().create().name(INVALID_TEXT_HTML))); + } + + @Step + private void createAndUpdateTargetTypeWithInvalidName(final TargetType targetType) { + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with too long name should not be created") + .isThrownBy(() -> targetTypeManagement + .create(entityFactory.targetType().create().name(RandomStringUtils.randomAlphanumeric( + NamedEntity.NAME_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with invalid name should not be created").isThrownBy( + () -> targetTypeManagement.create(entityFactory.targetType().create().name(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with too long name should not be updated") + .isThrownBy(() -> targetTypeManagement + .update(entityFactory.targetType().update(targetType.getId()).name(RandomStringUtils.randomAlphanumeric( + NamedEntity.NAME_MAX_SIZE + 1)))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with invalid name should not be updated").isThrownBy(() -> targetTypeManagement + .update(entityFactory.targetType().update(targetType.getId()).name(INVALID_TEXT_HTML))); + + assertThatExceptionOfType(ConstraintViolationException.class) + .as("targetType with too short name should not be updated").isThrownBy(() -> targetTypeManagement + .update(entityFactory.targetType().update(targetType.getId()).name(""))); + } private Optional findByName(final String name) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementTest.java index 53ca069a8..774b17ce8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementTest.java @@ -17,6 +17,9 @@ import java.time.Duration; import java.util.HashMap; import java.util.Map; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.exception.InvalidTenantConfigurationKeyException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; @@ -28,10 +31,6 @@ import org.junit.jupiter.api.Test; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("Tenant Configuration Management") public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest implements EnvironmentAware { @@ -101,9 +100,11 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes // add value first tenantConfigurationManagement.addOrUpdateConfiguration(configuration); - assertThat(tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY, String.class).getValue()) + assertThat(tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY, + String.class).getValue()) .isEqualTo("token_123"); - assertThat(tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class).getValue()) + assertThat( + tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class).getValue()) .isTrue(); } @@ -149,9 +150,12 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes tenantConfigurationManagement.addOrUpdateConfiguration(configuration); fail("should not have worked as type is wrong"); } catch (final TenantConfigurationValidatorException e) { - assertThat(tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY, String.class).getValue()) + assertThat( + tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY, + String.class).getValue()) .isNotEqualTo("token_123"); - assertThat(tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class).getValue()) + assertThat(tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class) + .getValue()) .isNotEqualTo(true); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java index 79402309d..b1d28e61f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java @@ -11,15 +11,14 @@ package org.eclipse.hawkbit.repository.jpa.model; import static org.assertj.core.api.Assertions.assertThat; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.EntityInterceptor; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.Target; - -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -131,6 +130,7 @@ public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { } private static class PrePersistEntityListener extends AbstractEntityListener { + @Override public void prePersist(final Object entity) { setEntity(entity); @@ -138,6 +138,7 @@ public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { } private static class PostPersistEntityListener extends AbstractEntityListener { + @Override public void postPersist(final Object entity) { setEntity(entity); @@ -146,6 +147,7 @@ public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { } private static class PostLoadEntityListener extends AbstractEntityListener { + @Override public void postLoad(final Object entity) { setEntity(entity); @@ -154,6 +156,7 @@ public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { } private static class PreUpdateEntityListener extends AbstractEntityListener { + @Override public void preUpdate(final Object entity) { setEntity(entity); @@ -161,6 +164,7 @@ public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { } private static class PostUpdateEntityListener extends AbstractEntityListener { + @Override public void postUpdate(final Object entity) { setEntity(entity); @@ -168,6 +172,7 @@ public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { } private static class PreRemoveEntityListener extends AbstractEntityListener { + @Override public void preRemove(final Object entity) { setEntity(entity); @@ -175,6 +180,7 @@ public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { } private static class PostRemoveEntityListener extends AbstractEntityListener { + @Override public void postRemove(final Object entity) { setEntity(entity); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/ModelEqualsHashcodeTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/ModelEqualsHashcodeTest.java index 791e84885..c0807e5b5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/ModelEqualsHashcodeTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/ModelEqualsHashcodeTest.java @@ -11,13 +11,12 @@ package org.eclipse.hawkbit.repository.jpa.model; import static org.assertj.core.api.Assertions.assertThat; -import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.junit.jupiter.api.Test; - import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; +import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.junit.jupiter.api.Test; @Feature("Unit Tests - Repository") @Story("Repository Model") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLActionFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLActionFieldsTest.java index 28ba4e501..7ea5b6583 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLActionFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLActionFieldsTest.java @@ -12,6 +12,9 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.ActionFields; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -28,10 +31,6 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; import org.springframework.orm.jpa.vendor.Database; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter actions") public class RSQLActionFieldsTest extends AbstractJpaIntegrationTest { @@ -51,25 +50,6 @@ public class RSQLActionFieldsTest extends AbstractJpaIntegrationTest { } } - private @NotNull JpaAction newJpaAction(final DistributionSet dsA, final boolean active, final String extRef) { - final JpaAction newAction = new JpaAction(); - newAction.setActionType(ActionType.SOFT); - newAction.setDistributionSet(dsA); - newAction.setActive(active); - newAction.setStatus(Status.RUNNING); - newAction.setTarget(target); - newAction.setWeight(45); - newAction.setInitiatedBy(tenantAware.getCurrentUsername()); - if (extRef != null) { - newAction.setExternalRef(extRef); - } - actionRepository.save(newAction); - - target.addAction(action); - - return newAction; - } - @Test @Description("Test filter action by id") public void testFilterByParameterId() { @@ -104,6 +84,7 @@ public class RSQLActionFieldsTest extends AbstractJpaIntegrationTest { } } + @Test @Description("Test action by status") public void testFilterByParameterExtRef() { @@ -112,6 +93,25 @@ public class RSQLActionFieldsTest extends AbstractJpaIntegrationTest { assertRSQLQuery(ActionFields.EXTERNALREF.name() + "==extRef*", 10); } + private @NotNull JpaAction newJpaAction(final DistributionSet dsA, final boolean active, final String extRef) { + final JpaAction newAction = new JpaAction(); + newAction.setActionType(ActionType.SOFT); + newAction.setDistributionSet(dsA); + newAction.setActive(active); + newAction.setStatus(Status.RUNNING); + newAction.setTarget(target); + newAction.setWeight(45); + newAction.setInitiatedBy(tenantAware.getCurrentUsername()); + if (extRef != null) { + newAction.setExternalRef(extRef); + } + actionRepository.save(newAction); + + target.addAction(action); + + return newAction; + } + private void assertRSQLQuery(final String rsqlParam, final long expectedEntities) { final Slice findEntity = deploymentManagement.findActionsByTarget(rsqlParam, target.getControllerId(), PageRequest.of(0, 100)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLDistributionSetFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLDistributionSetFieldTest.java index f1a3d4b12..0daa761c1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLDistributionSetFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLDistributionSetFieldTest.java @@ -16,6 +16,9 @@ import static org.junit.jupiter.api.Assertions.fail; import java.util.Arrays; import java.util.Collections; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.DistributionSetFields; import org.eclipse.hawkbit.repository.SoftwareModuleFields; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; @@ -31,10 +34,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.orm.jpa.vendor.Database; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter distribution set") public class RSQLDistributionSetFieldTest extends AbstractJpaIntegrationTest { @@ -47,7 +46,7 @@ public class RSQLDistributionSetFieldTest extends AbstractJpaIntegrationTest { sm = testdataFactory.createSoftwareModuleApp("SM"); - ds = testdataFactory.createDistributionSet(Collections.singletonList(sm),"DS"); + ds = testdataFactory.createDistributionSet(Collections.singletonList(sm), "DS"); ds = distributionSetManagement.update(entityFactory.distributionSet().update(ds.getId()).description("DS")); createDistributionSetMetadata(ds.getId(), entityFactory.generateDsMetadata("metaKey", "metaValue")); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLDistributionSetMetadataFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLDistributionSetMetadataFieldsTest.java index 140f87db2..cdb899a4b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLDistributionSetMetadataFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLDistributionSetMetadataFieldsTest.java @@ -15,6 +15,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.DistributionSetMetadataFields; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -25,10 +28,6 @@ import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter distribution set metadata") public class RSQLDistributionSetMetadataFieldsTest extends AbstractJpaIntegrationTest { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLParserValidationOracleTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLParserValidationOracleTest.java index b2c2a4f43..33bbb52b8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLParserValidationOracleTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLParserValidationOracleTest.java @@ -15,31 +15,28 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.TargetFields; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.rsql.RsqlValidationOracle; import org.eclipse.hawkbit.repository.rsql.SuggestToken; -import org.eclipse.hawkbit.repository.rsql.ValidationOracleContext; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter suggestion") public class RSQLParserValidationOracleTest extends AbstractJpaIntegrationTest { - @Autowired - private RsqlValidationOracle rsqlValidationOracle; - private static final String[] OP_SUGGESTIONS = new String[] { "==", "!=", "=ge=", "=le=", "=gt=", "=lt=", "=in=", "=out=" }; private static final String[] FIELD_SUGGESTIONS = Arrays.stream(TargetFields.values()) .map(field -> field.name().toLowerCase()).toArray(String[]::new); private static final String[] AND_OR_SUGGESTIONS = new String[] { "and", "or" }; private static final String[] NAME_VERSION_SUGGESTIONS = new String[] { "name", "version" }; + @Autowired + private RsqlValidationOracle rsqlValidationOracle; @Test @Description("Verifies that suggestions contains all possible field names") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLRolloutGroupFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLRolloutGroupFieldTest.java index 256d5aae3..d92ff5b16 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLRolloutGroupFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLRolloutGroupFieldTest.java @@ -11,6 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.RolloutGroupFields; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -24,10 +27,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.orm.jpa.vendor.Database; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter rollout group") public class RSQLRolloutGroupFieldTest extends AbstractJpaIntegrationTest { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java index 8c9ce246f..399d0e0c9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java @@ -11,6 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.SoftwareModuleFields; import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -18,16 +21,11 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.orm.jpa.vendor.Database; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter software module") public class RSQLSoftwareModuleFieldTest extends AbstractJpaIntegrationTest { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java index a6be9f505..f00d53aca 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java @@ -14,6 +14,9 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields; import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -25,10 +28,6 @@ import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter software module metadata") public class RSQLSoftwareModuleMetadataFieldsTest extends AbstractJpaIntegrationTest { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleTypeFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleTypeFieldsTest.java index c8c111ca2..5c27267f2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleTypeFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleTypeFieldsTest.java @@ -11,6 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.Constants; import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -20,10 +23,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.orm.jpa.vendor.Database; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter software module test type") public class RSQLSoftwareModuleTypeFieldsTest extends AbstractJpaIntegrationTest { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTagFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTagFieldsTest.java index f760d94be..8efd56c24 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTagFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTagFieldsTest.java @@ -11,6 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.TagFields; import org.eclipse.hawkbit.repository.builder.TagCreate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -21,10 +24,6 @@ import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter target and distribution set tags") public class RSQLTagFieldsTest extends AbstractJpaIntegrationTest { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFieldTest.java index 914066498..1f062d5b3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFieldTest.java @@ -17,6 +17,9 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.assertj.core.util.Maps; import org.eclipse.hawkbit.repository.TargetFields; import org.eclipse.hawkbit.repository.TargetTypeFields; @@ -31,22 +34,17 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Slice; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter target") class RSQLTargetFieldTest extends AbstractJpaIntegrationTest { + private static final String OR = ","; + private static final String AND = ";"; private Target target; private Target target2; private TargetType targetType1; private TargetType targetType2; - private static final String OR = ","; - private static final String AND = ";"; - @BeforeEach void setupBeforeTest() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFilterQueryFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFilterQueryFieldsTest.java index f400ca3f0..0e6e10fd8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFilterQueryFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetFilterQueryFieldsTest.java @@ -12,6 +12,9 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.TargetFilterQueryFields; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.Action.ActionType; @@ -23,10 +26,6 @@ import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.orm.jpa.vendor.Database; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter target filter query") public class RSQLTargetFilterQueryFieldsTest extends AbstractJpaIntegrationTest { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetMetadataFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetMetadataFieldsTest.java index 141ae5fd9..4b18899d9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetMetadataFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLTargetMetadataFieldsTest.java @@ -15,6 +15,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.TargetMetadataFields; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.MetaData; @@ -25,13 +28,10 @@ import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Component Tests - Repository") @Story("RSQL filter target metadata") public class RSQLTargetMetadataFieldsTest extends AbstractJpaIntegrationTest { + private String controllerId; @BeforeEach diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLToSQL.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLToSQL.java index 29855b9ca..294eda33f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLToSQL.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLToSQL.java @@ -13,12 +13,14 @@ import cz.jirutka.rsql.parser.RSQLParser; import cz.jirutka.rsql.parser.ast.Node; import cz.jirutka.rsql.parser.ast.RSQLOperators; import cz.jirutka.rsql.parser.ast.RSQLVisitor; + import jakarta.persistence.EntityManager; import jakarta.persistence.TypedQuery; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; + import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; @@ -39,11 +41,13 @@ public class RSQLToSQL { this.entityManager = entityManager; } - public & RsqlQueryField> String toSQL(final Class domainClass, final Class fieldsClass, final String rsql, final boolean legacyRsqlVisitor) { + public & RsqlQueryField> String toSQL(final Class domainClass, final Class fieldsClass, final String rsql, + final boolean legacyRsqlVisitor) { return createDbQuery(domainClass, fieldsClass, rsql, legacyRsqlVisitor).getSQLString(); } - public & RsqlQueryField> DatabaseQuery createDbQuery(final Class domainClass, final Class fieldsClass, final String rsql, final boolean legacyRsqlVisitor) { + public & RsqlQueryField> DatabaseQuery createDbQuery(final Class domainClass, final Class fieldsClass, + final String rsql, final boolean legacyRsqlVisitor) { final CriteriaQuery query = createQuery(domainClass, fieldsClass, rsql, legacyRsqlVisitor); final TypedQuery typedQuery = entityManager.createQuery(query); // executes the query - otherwise the SQL string is not generated @@ -52,13 +56,14 @@ public class RSQLToSQL { return typedQuery.unwrap(JpaQuery.class).getDatabaseQuery(); } - private & RsqlQueryField> CriteriaQuery createQuery(final Class domainClass, final Class fieldsClass, final String rsql, final boolean legacyRsqlVisitor) { + private & RsqlQueryField> CriteriaQuery createQuery(final Class domainClass, final Class fieldsClass, + final String rsql, final boolean legacyRsqlVisitor) { final CriteriaQuery query = entityManager.getCriteriaBuilder().createQuery(domainClass); final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); return query.where( RsqlConfigHolder.getInstance().isLegacyRsqlVisitor() == legacyRsqlVisitor ? // use directly - RSQLUtility.buildRsqlSpecification(rsql, fieldsClass, null, DATABASE) + RSQLUtility. buildRsqlSpecification(rsql, fieldsClass, null, DATABASE) .toPredicate(query.from(domainClass), cb.createQuery(domainClass), cb) : toPredicate(rsql, fieldsClass, null, query.from(domainClass), cb.createQuery(domainClass), cb, legacyRsqlVisitor) @@ -80,10 +85,10 @@ public class RSQLToSQL { virtualPropertyReplacer, DATABASE, query, !RsqlConfigHolder.getInstance().isCaseInsensitiveDB() && RsqlConfigHolder.getInstance().isIgnoreCase()) : - new JpaQueryRsqlVisitorG2<>( - fieldsClass, root, query, cb, - DATABASE, virtualPropertyReplacer, - !RsqlConfigHolder.getInstance().isCaseInsensitiveDB() && RsqlConfigHolder.getInstance().isIgnoreCase()); + new JpaQueryRsqlVisitorG2<>( + fieldsClass, root, query, cb, + DATABASE, virtualPropertyReplacer, + !RsqlConfigHolder.getInstance().isCaseInsensitiveDB() && RsqlConfigHolder.getInstance().isIgnoreCase()); final List accept = rootNode.accept(jpqQueryRSQLVisitor); if (CollectionUtils.isEmpty(accept)) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLToSQLTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLToSQLTest.java index 9764cf6a3..098ae0c9f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLToSQLTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLToSQLTest.java @@ -9,8 +9,11 @@ */ package org.eclipse.hawkbit.repository.jpa.rsql; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; + import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; + import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.TargetFields; import org.eclipse.hawkbit.repository.jpa.RepositoryApplicationConfiguration; @@ -24,10 +27,8 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; - @ActiveProfiles("test") -@SpringBootTest(webEnvironment=NONE, properties = { +@SpringBootTest(webEnvironment = NONE, properties = { "hawkbit.rsql.caseInsensitiveDB=true", "spring.main.allow-bean-definition-overriding=true", "spring.main.banner-mode=off", @@ -39,11 +40,6 @@ public class RSQLToSQLTest { private RSQLToSQL rsqlToSQL; - @PersistenceContext - private void setEntityManager(final EntityManager entityManager) { - rsqlToSQL = new RSQLToSQL(entityManager); - } - @Test public void print() { print(JpaTarget.class, TargetFields.class, "tag==tag1 and tag==tag2"); @@ -58,6 +54,15 @@ public class RSQLToSQLTest { printFrom(JpaTarget.class, TargetFields.class, "tag==TAG1 and tag!=TAG2"); } + private static String from(final String sql) { + return sql.substring(sql.indexOf("FROM")); + } + + @PersistenceContext + private void setEntityManager(final EntityManager entityManager) { + rsqlToSQL = new RSQLToSQL(entityManager); + } + private & RsqlQueryField> void print(final Class domainClass, final Class fieldsClass, final String rsql) { System.out.println(rsql); System.out.println("\tlegacy:\n" + @@ -73,7 +78,4 @@ public class RSQLToSQLTest { System.out.println("\tG2:\n" + "\t\t" + from(rsqlToSQL.toSQL(domainClass, fieldsClass, rsql, false))); } - private static String from(final String sql) { - return sql.substring(sql.indexOf("FROM")); - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java index 8fc34bea9..929b99bb8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java @@ -33,10 +33,13 @@ import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.Attribute; - import jakarta.persistence.metamodel.EntityType; import jakarta.persistence.metamodel.SingularAttribute; import jakarta.persistence.metamodel.Type; + +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.DistributionSetFields; import org.eclipse.hawkbit.repository.RsqlQueryField; import org.eclipse.hawkbit.repository.SoftwareModuleFields; @@ -48,8 +51,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder; -import org.eclipse.hawkbit.repository.rsql.RsqlVisitorFactory; import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder; +import org.eclipse.hawkbit.repository.rsql.RsqlVisitorFactory; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver; import org.eclipse.hawkbit.security.SystemSecurityContext; @@ -66,10 +69,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.orm.jpa.vendor.Database; import org.springframework.test.context.junit.jupiter.SpringExtension; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @ExtendWith(SpringExtension.class) @Feature("Component Tests - Repository") @Story("RSQL search utility") @@ -77,58 +76,31 @@ import io.qameta.allure.Story; // method name as short text public class RSQLUtilityTest { - @Spy - private final VirtualPropertyResolver macroResolver = new VirtualPropertyResolver(); - - @MockBean - private TenantConfigurationManagement confMgmt; - - @MockBean - private SystemSecurityContext securityContext; - - @MockBean - private RsqlVisitorFactory rsqlVisitorFactory; - - @Mock - private Root baseSoftwareModuleRootMock; - - @Mock - private CriteriaQuery criteriaQueryMock; - @Mock - private CriteriaBuilder criteriaBuilderMock; - - @Mock - private Subquery subqueryMock; - @Mock - private Root subqueryRootMock; - - private final Database testDb = Database.H2; - - @Mock - private Attribute attribute; - - @Configuration - static class Config { - @Bean - TenantConfigurationManagementHolder tenantConfigurationManagementHolder() { - return TenantConfigurationManagementHolder.getInstance(); - } - - @Bean - SystemSecurityContextHolder systemSecurityContextHolder() { - return SystemSecurityContextHolder.getInstance(); - } - - @Bean - RsqlConfigHolder rsqlVisitorFactoryHolder() { - return RsqlConfigHolder.getInstance(); - } - } - private static final TenantConfigurationValue TEST_POLLING_TIME_INTERVAL = TenantConfigurationValue . builder().value("00:05:00").build(); private static final TenantConfigurationValue TEST_POLLING_OVERDUE_TIME_INTERVAL = TenantConfigurationValue . builder().value("00:07:37").build(); + @Spy + private final VirtualPropertyResolver macroResolver = new VirtualPropertyResolver(); + private final Database testDb = Database.H2; + @MockBean + private TenantConfigurationManagement confMgmt; + @MockBean + private SystemSecurityContext securityContext; + @MockBean + private RsqlVisitorFactory rsqlVisitorFactory; + @Mock + private Root baseSoftwareModuleRootMock; + @Mock + private CriteriaQuery criteriaQueryMock; + @Mock + private CriteriaBuilder criteriaBuilderMock; + @Mock + private Subquery subqueryMock; + @Mock + private Root subqueryRootMock; + @Mock + private Attribute attribute; @BeforeEach public void beforeEach() { @@ -555,6 +527,34 @@ public class RSQLUtilityTest { return (Path) path; } + private void validateRsqlForTestFields(final String rsql) { + when(rsqlVisitorFactory.validationRsqlVisitor(eq(TestFieldEnum.class))).thenReturn( + new FieldValidationRsqlVisitor<>(TestFieldEnum.class)); + RSQLUtility.validateRsqlFor(rsql, TestFieldEnum.class); + } + + private void reset0(final Object... mocks) { + reset(mocks); + if (Arrays.asList(mocks).contains(baseSoftwareModuleRootMock)) { + setupRoot(baseSoftwareModuleRootMock); + } + if (Arrays.asList(mocks).contains(subqueryRootMock)) { + setupRoot(subqueryRootMock); + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private void setupRoot(final Root root) { + final Type type = Mockito.mock(Type.class); + when(type.getPersistenceType()).thenReturn(Type.PersistenceType.BASIC); + final SingularAttribute singularAttribute = Mockito.mock(SingularAttribute.class); + when(singularAttribute.getType()).thenReturn(type); + final EntityType entityType = Mockito.mock(EntityType.class); + when(entityType.getAttribute(any())).thenReturn(singularAttribute); + when(entityType.getPersistenceType()).thenReturn(Type.PersistenceType.BASIC); + when(root.getModel()).thenReturn(entityType); + } + private enum TestFieldEnum implements RsqlQueryField { TESTFIELD("testfield"), TESTFIELD_WITH_SUB_ENTITIES("testfieldWithSubEntities", "subentity11", "subentity22"); @@ -581,34 +581,26 @@ public class RSQLUtilityTest { } } - private void validateRsqlForTestFields(final String rsql) { - when(rsqlVisitorFactory.validationRsqlVisitor(eq(TestFieldEnum.class))).thenReturn(new FieldValidationRsqlVisitor<>(TestFieldEnum.class)); - RSQLUtility.validateRsqlFor(rsql, TestFieldEnum.class); - } - - private void reset0(final Object... mocks) { - reset(mocks); - if (Arrays.asList(mocks).contains(baseSoftwareModuleRootMock)) { - setupRoot(baseSoftwareModuleRootMock); - } - if (Arrays.asList(mocks).contains(subqueryRootMock)) { - setupRoot(subqueryRootMock); - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private void setupRoot(final Root root) { - final Type type = Mockito.mock(Type.class); - when(type.getPersistenceType()).thenReturn(Type.PersistenceType.BASIC); - final SingularAttribute singularAttribute = Mockito.mock(SingularAttribute.class); - when(singularAttribute.getType()).thenReturn(type); - final EntityType entityType = Mockito.mock(EntityType.class); - when(entityType.getAttribute(any())).thenReturn(singularAttribute); - when(entityType.getPersistenceType()).thenReturn(Type.PersistenceType.BASIC); - when(root.getModel()).thenReturn(entityType); - } - private enum TestValueEnum { BUMLUX; } + + @Configuration + static class Config { + + @Bean + TenantConfigurationManagementHolder tenantConfigurationManagementHolder() { + return TenantConfigurationManagementHolder.getInstance(); + } + + @Bean + SystemSecurityContextHolder systemSecurityContextHolder() { + return SystemSecurityContextHolder.getInstance(); + } + + @Bean + RsqlConfigHolder rsqlVisitorFactoryHolder() { + return RsqlConfigHolder.getInstance(); + } + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolverTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolverTest.java index c121b5add..bb8078540 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolverTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolverTest.java @@ -14,6 +14,9 @@ import static org.mockito.Mockito.when; import java.util.concurrent.Callable; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.apache.commons.lang3.text.StrSubstitutor; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; @@ -34,43 +37,22 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit.jupiter.SpringExtension; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @ExtendWith(SpringExtension.class) @Feature("Unit Tests - Repository") @Story("Placeholder resolution for virtual properties") public class VirtualPropertyResolverTest { - @Spy - private final VirtualPropertyResolver resolverUnderTest = new VirtualPropertyResolver(); - - @MockBean - private TenantConfigurationManagement confMgmt; - - @MockBean - private SystemSecurityContext securityContext; - - private StrSubstitutor substitutor; - private static final TenantConfigurationValue TEST_POLLING_TIME_INTERVAL = TenantConfigurationValue . builder().value("00:05:00").build(); private static final TenantConfigurationValue TEST_POLLING_OVERDUE_TIME_INTERVAL = TenantConfigurationValue . builder().value("00:07:37").build(); - - @Configuration - static class Config { - @Bean - TenantConfigurationManagementHolder tenantConfigurationManagementHolder() { - return TenantConfigurationManagementHolder.getInstance(); - } - - @Bean - SystemSecurityContextHolder systemSecurityContextHolder() { - return SystemSecurityContextHolder.getInstance(); - } - } + @Spy + private final VirtualPropertyResolver resolverUnderTest = new VirtualPropertyResolver(); + @MockBean + private TenantConfigurationManagement confMgmt; + @MockBean + private SystemSecurityContext securityContext; + private StrSubstitutor substitutor; @BeforeEach public void before() { @@ -83,18 +65,6 @@ public class VirtualPropertyResolverTest { StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE); } - @ParameterizedTest - @ValueSource(strings = { "${NOW_TS}", "${OVERDUE_TS}", "${overdue_ts}" }) - @Description("Tests resolution of NOW_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.") - void resolveNowTimestampPlaceholder(final String placeholder) { - when(securityContext.runAsSystem(Mockito.any())).thenAnswer(a -> ((Callable) a.getArgument(0)).call()); - final String testString = "lhs=lt=" + placeholder; - - final String resolvedPlaceholders = substitutor.replace(testString); - assertThat(resolvedPlaceholders).as("'%s' placeholder was not replaced", placeholder) - .doesNotContain(placeholder); - } - @Test @Description("Tests VirtualPropertyResolver with a placeholder unknown to VirtualPropertyResolver.") public void handleUnknownPlaceholder() { @@ -115,4 +85,30 @@ public class VirtualPropertyResolverTest { final String resolvedPlaceholders = substitutor.replace(testString); assertThat(resolvedPlaceholders).as("Escaped OVERDUE_TS should not be resolved!").contains(placeholder); } + + @ParameterizedTest + @ValueSource(strings = { "${NOW_TS}", "${OVERDUE_TS}", "${overdue_ts}" }) + @Description("Tests resolution of NOW_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.") + void resolveNowTimestampPlaceholder(final String placeholder) { + when(securityContext.runAsSystem(Mockito.any())).thenAnswer(a -> ((Callable) a.getArgument(0)).call()); + final String testString = "lhs=lt=" + placeholder; + + final String resolvedPlaceholders = substitutor.replace(testString); + assertThat(resolvedPlaceholders).as("'%s' placeholder was not replaced", placeholder) + .doesNotContain(placeholder); + } + + @Configuration + static class Config { + + @Bean + TenantConfigurationManagementHolder tenantConfigurationManagementHolder() { + return TenantConfigurationManagementHolder.getInstance(); + } + + @Bean + SystemSecurityContextHolder systemSecurityContextHolder() { + return SystemSecurityContextHolder.getInstance(); + } + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/specifications/SpecificationsBuilderTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/specifications/SpecificationsBuilderTest.java index 34e6b2554..681240352 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/specifications/SpecificationsBuilderTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/specifications/SpecificationsBuilderTest.java @@ -27,12 +27,11 @@ import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; -import org.junit.jupiter.api.Test; -import org.springframework.data.jpa.domain.Specification; - import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; +import org.junit.jupiter.api.Test; +import org.springframework.data.jpa.domain.Specification; @Feature("Unit Tests - Repository") @Story("Specifications builder") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java index d48575f7e..d31453932 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java @@ -16,6 +16,9 @@ import java.util.Arrays; import java.util.Collection; import java.util.concurrent.Callable; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -27,15 +30,10 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Slice; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - /** * Multi-Tenancy tests which testing the CRUD operations of entities that all * CRUD-Operations are tenant aware and cannot access or delete entities not * belonging to the current tenant. - * */ @Feature("Component Tests - Repository") @Story("Multi Tenancy") @@ -110,7 +108,7 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest { // autogenerated assertThat(distributionSetTypeManagement.findAll(PAGE)).isEmpty(); SecurityContextSwitch.runAsPrivileged(() -> - assertThat(systemManagement.createTenantMetadata("mytenant").getTenant().toUpperCase()).isEqualTo("mytenant".toUpperCase())); + assertThat(systemManagement.createTenantMetadata("mytenant").getTenant().toUpperCase()).isEqualTo("mytenant".toUpperCase())); assertThat(distributionSetTypeManagement.findAll(PAGE)).isNotEmpty(); @@ -119,7 +117,7 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest { // mytenant assertThat(SecurityContextSwitch.runAs(SecurityContextSwitch.withUserAndTenantAllSpPermissions("user", "bumlux"), () -> systemManagement.getTenantMetadata().getTenant().toUpperCase())) - .isEqualTo("bumlux".toUpperCase()); + .isEqualTo("bumlux".toUpperCase()); } @Test diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/jpa-test.properties b/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/jpa-test.properties index 8c0d0f609..42a14eec3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/jpa-test.properties +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/jpa-test.properties @@ -7,7 +7,6 @@ # # SPDX-License-Identifier: EPL-2.0 # - # Debug utility functions - START logging.level.org.eclipse.persistence=ERROR #incomment to see the debug of persistence, e.g. to see the generated SQLs @@ -16,6 +15,5 @@ spring.jpa.properties.eclipselink.logging.level=FINE spring.jpa.properties.eclipselink.logging.level.sql=FINE spring.jpa.properties.eclipselink.logging.parameters=true # Debug utility functions - END - # enable / disable case sensitiveness of the DB when playing around #hawkbit.rsql.caseInsensitiveDB=true