diff --git a/eoxserver/backends/management/commands/storage.py b/eoxserver/backends/management/commands/storage.py index 126a8fded..5e3e2e80c 100644 --- a/eoxserver/backends/management/commands/storage.py +++ b/eoxserver/backends/management/commands/storage.py @@ -79,6 +79,14 @@ def add_arguments(self, parser): accessor will be used.""" ) + create_parser.add_argument( + '--replace', action='store_true', + default=False, + help=( + 'Replace storage definition if already exists.' + ) + ) + for parser in [list_parser, env_parser]: parser.add_argument( 'paths', nargs='*', default=None, @@ -109,7 +117,7 @@ def handle(self, subcommand, name, *args, **kwargs): self.handle_env(name, *args, **kwargs) def handle_create(self, name, url, type_name, parent_name, - storage_auth_name, streaming, **kwargs): + storage_auth_name, streaming, replace, **kwargs): """ Handle the creation of a new storage. """ url = url[0] @@ -144,11 +152,22 @@ def handle_create(self, name, url, type_name, parent_name, ) else: storage_auth = None - - backends.Storage.objects.create( - name=name, url=url, storage_type=type_name, parent=parent, - storage_auth=storage_auth, streaming=streaming, - ) + if replace: + backends.Storage.objects.update_or_create( + name=name, + defaults={ + 'url':url, + 'storage_type':type_name, + 'parent':parent, + 'storage_auth':storage_auth, + 'streaming':streaming, + }, + ) + else: + backends.Storage.objects.create( + storage_type=type_name, parent=parent, + storage_auth=storage_auth, streaming=streaming, + ) self.print_msg( 'Successfully created storage %s (%s)' % ( diff --git a/eoxserver/backends/management/commands/storageauth.py b/eoxserver/backends/management/commands/storageauth.py index 9f94be195..5a386141b 100644 --- a/eoxserver/backends/management/commands/storageauth.py +++ b/eoxserver/backends/management/commands/storageauth.py @@ -74,6 +74,14 @@ def add_arguments(self, parser): help='Check access to the storage auth.', ) + create_parser.add_argument( + '--replace', action='store_true', + default=False, + help=( + 'Replace storage auth definition if already exists.' + ) + ) + @transaction.atomic def handle(self, subcommand, name, *args, **kwargs): """ Dispatch sub-commands: create, delete, insert, exclude, purge. @@ -84,7 +92,7 @@ def handle(self, subcommand, name, *args, **kwargs): elif subcommand == "delete": self.handle_delete(name, *args, **kwargs) - def handle_create(self, name, url, type_name, parameters, check, **kwargs): + def handle_create(self, name, url, type_name, parameters, check, replace, **kwargs): """ Handle the creation of a new storage. """ url = url[0] @@ -102,15 +110,24 @@ def parse_parameter(key, value=None, *extra): parse_parameter(*param) for param in parameters ) - - storage_auth = backends.StorageAuth( - name=name, - url=url, - storage_auth_type=type_name, - auth_parameters=json.dumps(parameters), - ) - storage_auth.full_clean() - storage_auth.save() + if replace: + backends.StorageAuth.objects.update_or_create( + name=name, + defaults={ + 'url':url, + 'storage_auth_type':type_name, + 'auth_parameters':json.dumps(parameters), + }, + ) + else: + storage_auth = backends.StorageAuth( + name=name, + url=url, + storage_auth_type=type_name, + auth_parameters=json.dumps(parameters), + ) + storage_auth.full_clean() + storage_auth.save() if check: _ = get_handler_for_model(storage_auth) diff --git a/eoxserver/resources/coverages/management/commands/browsetype.py b/eoxserver/resources/coverages/management/commands/browsetype.py index 6301436a2..a38920a46 100644 --- a/eoxserver/resources/coverages/management/commands/browsetype.py +++ b/eoxserver/resources/coverages/management/commands/browsetype.py @@ -109,6 +109,13 @@ def add_arguments(self, parser): action="store_true", default=False, ) + create_parser.add_argument( + '--replace', action='store_true', + default=False, + help=( + '''Change browse type if browse type already exists.''' + ) + ) list_parser.add_argument( @@ -141,6 +148,7 @@ def handle_create(self, product_type_name, browse_type_name, red_or_grey_nodata=None, green_nodata=None, blue_nodata=None, alpha_nodata=None, show_out_of_bounds_data=False, + replace=False, *args, **kwargs): """ Handle the creation of a new browse type. """ @@ -158,28 +166,52 @@ def handle_create(self, product_type_name, browse_type_name, green_min, green_max = green_range blue_min, blue_max = blue_range alpha_min, alpha_max = alpha_range - - models.BrowseType.objects.create( - product_type=product_type, - name=browse_type_name, - red_or_grey_expression=red_or_grey_expression, - green_expression=green_expression, - blue_expression=blue_expression, - alpha_expression=alpha_expression, - red_or_grey_range_min=red_min, - red_or_grey_range_max=red_max, - green_range_min=green_min, - green_range_max=green_max, - blue_range_min=blue_min, - blue_range_max=blue_max, - alpha_range_min=alpha_min, - alpha_range_max=alpha_max, - red_or_grey_nodata_value=red_or_grey_nodata, - green_nodata_value=green_nodata, - blue_nodata_value=blue_nodata, - alpha_nodata_value=alpha_nodata, - show_out_of_bounds_data=show_out_of_bounds_data, - ) + if replace: + models.BrowseType.objects.update_or_create( + product_type=product_type, + name=browse_type_name, + defaults={ + 'red_or_grey_expression':red_or_grey_expression, + 'green_expression':green_expression, + 'blue_expression':blue_expression, + 'alpha_expression':alpha_expression, + 'red_or_grey_range_min':red_min, + 'red_or_grey_range_max':red_max, + 'green_range_min':green_min, + 'green_range_max':green_max, + 'blue_range_min':blue_min, + 'blue_range_max':blue_max, + 'alpha_range_min':alpha_min, + 'alpha_range_max':alpha_max, + 'red_or_grey_nodata_value':red_or_grey_nodata, + 'green_nodata_value':green_nodata, + 'blue_nodata_value':blue_nodata, + 'alpha_nodata_value':alpha_nodata, + 'show_out_of_bounds_data':show_out_of_bounds_data, + }, + ) + else: + models.BrowseType.objects.create( + product_type=product_type, + name=browse_type_name, + red_or_grey_expression=red_or_grey_expression, + green_expression=green_expression, + blue_expression=blue_expression, + alpha_expression=alpha_expression, + red_or_grey_range_min=red_min, + red_or_grey_range_max=red_max, + green_range_min=green_min, + green_range_max=green_max, + blue_range_min=blue_min, + blue_range_max=blue_max, + alpha_range_min=alpha_min, + alpha_range_max=alpha_max, + red_or_grey_nodata_value=red_or_grey_nodata, + green_nodata_value=green_nodata, + blue_nodata_value=blue_nodata, + alpha_nodata_value=alpha_nodata, + show_out_of_bounds_data=show_out_of_bounds_data, + ) if not browse_type_name: print( diff --git a/eoxserver/resources/coverages/management/commands/collection.py b/eoxserver/resources/coverages/management/commands/collection.py index e5a4cfb0f..f4cfab4e3 100644 --- a/eoxserver/resources/coverages/management/commands/collection.py +++ b/eoxserver/resources/coverages/management/commands/collection.py @@ -73,6 +73,14 @@ def add_arguments(self, parser): '"platform".' ) ) + create_parser.add_argument( + '--replace', action='store_true', + default=False, + help=( + '''Change collection type references according to parameters + if collection type already exists.''' + ) + ) delete_parser.add_argument( '--all', '-a', action="store_true", default=False, dest='all_collections', @@ -155,7 +163,7 @@ def handle(self, subcommand, identifier, *args, **kwargs): elif subcommand == "summary": self.handle_summary(identifier[0], *args, **kwargs) - def handle_create(self, identifier, type_name, grid_name, **kwargs): + def handle_create(self, identifier, type_name, grid_name, replace, **kwargs): """ Handle the creation of a new collection. """ if grid_name: @@ -176,11 +184,18 @@ def handle_create(self, identifier, type_name, grid_name, **kwargs): raise CommandError( "Collection type %r does not exist." % type_name ) - - models.Collection.objects.create( - identifier=identifier, - collection_type=collection_type, grid=grid - ) + if replace: + models.Collection.objects.update_or_create( + identifier=identifier, + defaults={ + 'collection_type':collection_type, + 'grid':grid, + } + ) + else: + models.Collection.objects.create( + identifier=identifier, collection_type=collection_type, grid=grid + ) print('Successfully created collection %r' % identifier) diff --git a/eoxserver/resources/coverages/management/commands/collectiontype.py b/eoxserver/resources/coverages/management/commands/collectiontype.py index ad1941d36..fb93a5c17 100644 --- a/eoxserver/resources/coverages/management/commands/collectiontype.py +++ b/eoxserver/resources/coverages/management/commands/collectiontype.py @@ -66,6 +66,15 @@ def add_arguments(self, parser): ) ) + create_parser.add_argument( + '--replace', action='store_true', + default=False, + help=( + '''Change collection type references according to parameters + if collection type already exists.''' + ) + ) + delete_parser.add_argument( '--force', '-f', action='store_true', default=False, help='Also remove all collections associated with that type.' @@ -88,37 +97,39 @@ def handle(self, subcommand, *args, **kwargs): self.handle_list(*args, **kwargs) def handle_create(self, name, allowed_coverage_type_names, - allowed_product_type_names, **kwargs): + allowed_product_type_names, replace, **kwargs): """ Handle the creation of a new collection type. """ - - collection_type = models.CollectionType.objects.create(name=name) + if replace: + collection_type = models.CollectionType.objects.get_or_create(name=name)[0] + else: + collection_type = models.CollectionType.objects.create(name=name) for allowed_coverage_type_name in allowed_coverage_type_names: - try: - collection_type.allowed_coverage_types.add( - models.CoverageType.objects.get( - name=allowed_coverage_type_name - ) - ) - except models.CoverageType.DoesNotExist: - raise CommandError( - 'Coverage type %r does not exist.' % - allowed_coverage_type_name - ) + if replace: + if not collection_type.allowed_coverage_types.filter(name=allowed_coverage_type_name).exists(): + self.add_allowed_coverage_type_name(collection_type, allowed_coverage_type_name) + else: + self.add_allowed_coverage_type_name(collection_type, allowed_coverage_type_name) + if replace: + # remove allowed coverage types not part of definition of collection type + referenced_coverage_types = collection_type.allowed_coverage_types.all() + for ct in referenced_coverage_types: + if ct.name not in allowed_coverage_type_names: + collection_type.allowed_coverage_types.remove(ct) for allowed_product_type_name in allowed_product_type_names: - try: - collection_type.allowed_product_types.add( - models.ProductType.objects.get( - name=allowed_product_type_name - ) - ) - except models.ProductType.DoesNotExist: - raise CommandError( - 'Product type %r does not exist.' % - allowed_product_type_name - ) + if replace: + if not collection_type.allowed_product_types.filter(name=allowed_product_type_name).exists(): + self.add_allowed_product_type_name(collection_type, allowed_product_type_name) + else: + self.add_allowed_product_type_name(collection_type, allowed_product_type_name) + if replace: + # remove allowed product types not part of definition of collection type + referenced_product_types = collection_type.allowed_product_types.all() + for pt in referenced_product_types: + if pt.name not in allowed_product_type_names: + collection_type.allowed_product_types.remove(pt) print('Successfully created collection type %r' % name) @@ -139,3 +150,30 @@ def handle_list(self, detail, *args, **kwargs): # if detail: # for coverage_type in collection_type.allowed_coverage_types.all(): # print("\t%s" % coverage_type.name) + + def add_allowed_coverage_type_name(self, collection_type, allowed_coverage_type_name): + try: + collection_type.allowed_coverage_types.add( + models.CoverageType.objects.get( + name=allowed_coverage_type_name + ) + ) + except models.CoverageType.DoesNotExist: + raise CommandError( + 'Coverage type %r does not exist.' % + allowed_coverage_type_name + ) + + + def add_allowed_product_type_name(self, collection_type, allowed_product_type_name): + try: + collection_type.allowed_product_types.add( + models.ProductType.objects.get( + name=allowed_product_type_name + ) + ) + except models.CoverageType.DoesNotExist: + raise CommandError( + 'Product type %r does not exist.' % + allowed_product_type_name + ) diff --git a/eoxserver/resources/coverages/management/commands/coveragetype.py b/eoxserver/resources/coverages/management/commands/coveragetype.py index 54f2d52ae..4dfc500a7 100644 --- a/eoxserver/resources/coverages/management/commands/coveragetype.py +++ b/eoxserver/resources/coverages/management/commands/coveragetype.py @@ -78,6 +78,15 @@ def add_arguments(self, parser): help='Read the definition from stdin instead from a file.' ) + for parser in [create_parser, import_parser]: + parser.add_argument( + '--replace', action='store_true', + default=False, + help=( + 'Replace field types if coverage type already exists.' + ) + ) + delete_parser.add_argument( '--force', '-f', action='store_true', default=False, help='Also remove all collections associated with that type.' @@ -103,42 +112,42 @@ def handle(self, subcommand, *args, **kwargs): elif subcommand == "list": self.handle_list(*args, **kwargs) - def handle_create(self, name, field_types, **kwargs): + def handle_create(self, name, field_types, replace, **kwargs): """ Handle the creation of a new coverage type. """ coverage_type = self._create_coverage_type(name) - - self._create_field_types(coverage_type, {}, [ - dict( - identifier=field_type_definition[0], - description=field_type_definition[1], - definition=field_type_definition[2], - unit_of_measure=field_type_definition[3], - wavelength=field_type_definition[4] - ) - for field_type_definition in field_types - ]) + if replace or not models.FieldType.objects.filter(coverage_type=coverage_type).exists(): + self._create_field_types(coverage_type, {}, [ + dict( + identifier=field_type_definition[0], + description=field_type_definition[1], + definition=field_type_definition[2], + unit_of_measure=field_type_definition[3], + wavelength=field_type_definition[4] + ) + for field_type_definition in field_types + ], replace) print('Successfully created coverage type %r' % name) def handle_import(self, locations, *args, **kwargs): - def _import(definitions): + def _import(definitions, replace): if isinstance(definitions, dict): definitions = [definitions] for definition in definitions: - self._import_definition(definition) + self._import_definition(definition, replace) - if kwargs['stdin']: + if kwargs.get('stdin'): try: - _import(json.load(sys.stdin)) + _import(json.load(sys.stdin), kwargs.get('replace')) except ValueError: raise CommandError('Could not parse JSON from stdin') else: for location in locations: with open(location) as f: try: - _import(json.load(f)) + _import(json.load(f), kwargs.get('replace')) except ValueError: raise CommandError( 'Could not parse JSON from %r' % location @@ -183,32 +192,37 @@ def handle_list(self, detail, *args, **kwargs): for coverage_type in coverage_type.field_types.all(): print("\t%s" % coverage_type.identifier) - def _import_definition(self, definition): + def _import_definition(self, definition, replace): name = str(definition['name']) coverage_type = self._create_coverage_type(name) field_type_definitions = ( definition.get('field_type') or definition.get('bands') ) - self._create_field_types( - coverage_type, definition, field_type_definitions - ) - self.print_msg('Successfully imported coverage type %r' % name) + if replace or not models.FieldType.objects.filter(coverage_type=coverage_type).exists(): + self._create_field_types( + coverage_type, definition, field_type_definitions, replace + ) + self.print_msg('Successfully imported coverage type %r' % name) def _create_coverage_type(self, name): - try: - return models.CoverageType.objects.create(name=name) - except IntegrityError: - raise CommandError("Coverage type %r already exists." % name) + return models.CoverageType.objects.get_or_create(name=name)[0] def _create_field_types(self, coverage_type, coverage_type_definition, - field_type_definitions): + field_type_definitions, replace): for i, field_type_definition in enumerate(field_type_definitions): + if i == 0: + # only in first iteration consider replace + if replace: + # delete FieldTypes attached to CoverageType if any exist + field_types = models.FieldType.objects.filter( + coverage_type=coverage_type, + ) + field_types.delete() uom = ( field_type_definition.get('unit_of_measure') or field_type_definition.get('uom') ) - - field_type = models.FieldType( + field_type = models.FieldType.objects.create( coverage_type=coverage_type, index=i, identifier=field_type_definition.get('identifier'), diff --git a/eoxserver/resources/coverages/management/commands/producttype.py b/eoxserver/resources/coverages/management/commands/producttype.py index 9ce13614b..f1492b54c 100644 --- a/eoxserver/resources/coverages/management/commands/producttype.py +++ b/eoxserver/resources/coverages/management/commands/producttype.py @@ -73,6 +73,15 @@ def add_arguments(self, parser): ) ) + create_parser.add_argument( + '--replace', action='store_true', + default=False, + help=( + '''Change product type references according to parameters + if product type already exists.''' + ) + ) + delete_parser.add_argument( '--force', '-f', action='store_true', default=False, help='Also remove all products associated with that type.' @@ -83,6 +92,7 @@ def add_arguments(self, parser): help="Disable the printing of details of the product type." ) + @transaction.atomic def handle(self, subcommand, *args, **kwargs): """ Dispatch sub-commands: create, delete, list. @@ -95,13 +105,15 @@ def handle(self, subcommand, *args, **kwargs): self.handle_list(*args, **kwargs) def handle_create(self, name, coverage_type_names, mask_type_names, - validity_mask_type_names, browse_type_names, + validity_mask_type_names, browse_type_names, replace, *args, **kwargs): """ Handle the creation of a new product type. """ - - product_type = models.ProductType.objects.create(name=name) - + product_type = None + if replace: + product_type = models.ProductType.objects.get_or_create(name=name)[0] + else: + product_type = models.ProductType.objects.create(name=name) for coverage_type_name in coverage_type_names: try: coverage_type = models.CoverageType.objects.get( @@ -112,22 +124,46 @@ def handle_create(self, name, coverage_type_names, mask_type_names, raise CommandError( 'Coverage type %r does not exist' % coverage_type_name ) + if replace: + # remove allowed coverage types not part of definition of product type + referenced_coverage_types = product_type.allowed_coverage_types.all() + for ct in referenced_coverage_types: + if ct.name not in coverage_type_names: + product_type.allowed_coverage_types.remove(ct) for mask_type_name in mask_type_names: - models.MaskType.objects.create( - name=mask_type_name, product_type=product_type - ) + if replace: + mt = models.MaskType.objects.get_or_create( + name=mask_type_name, product_type=product_type + )[0] + mt.validity = False + else: + models.MaskType.objects.create( + name=mask_type_name, product_type=product_type, + validity=False + ) for mask_type_name in validity_mask_type_names: - models.MaskType.objects.create( - name=mask_type_name, product_type=product_type, - validity=True - ) + if replace: + mt = models.MaskType.objects.get_or_create( + name=mask_type_name, product_type=product_type + )[0] + mt.validity = True + else: + models.MaskType.objects.create( + name=mask_type_name, product_type=product_type, + validity=True + ) for browse_type_name in browse_type_names: - models.BrowseType.objects.create( - name=browse_type_name, product_type=product_type - ) + if replace: + models.BrowseType.objects.get_or_create( + name=browse_type_name, product_type=product_type + ) + else: + models.BrowseType.objects.create( + name=browse_type_name, product_type=product_type + ) print('Successfully created product type %r' % name)